diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/blackfin/mach-common/Makefile | 4 | ||||
-rw-r--r-- | arch/blackfin/mach-common/ints-priority-dc.c | 484 | ||||
-rw-r--r-- | arch/blackfin/mach-common/ints-priority.c (renamed from arch/blackfin/mach-common/ints-priority-sc.c) | 129 |
3 files changed, 97 insertions, 520 deletions
diff --git a/arch/blackfin/mach-common/Makefile b/arch/blackfin/mach-common/Makefile index 8636d4284bd..15e33ca1ce8 100644 --- a/arch/blackfin/mach-common/Makefile +++ b/arch/blackfin/mach-common/Makefile @@ -4,8 +4,6 @@ obj-y := \ cache.o cacheinit.o entry.o \ - interrupt.o lock.o irqpanic.o arch_checks.o + interrupt.o lock.o irqpanic.o arch_checks.o ints-priority.o -obj-$(CONFIG_BFIN_SINGLE_CORE) += ints-priority-sc.o -obj-$(CONFIG_BFIN_DUAL_CORE) += ints-priority-dc.o obj-$(CONFIG_PM) += pm.o dpmc.o diff --git a/arch/blackfin/mach-common/ints-priority-dc.c b/arch/blackfin/mach-common/ints-priority-dc.c deleted file mode 100644 index 8d18d6b163b..00000000000 --- a/arch/blackfin/mach-common/ints-priority-dc.c +++ /dev/null @@ -1,484 +0,0 @@ -/* - * File: arch/blackfin/mach-common/ints-priority-dc.c - * Based on: - * Author: - * - * Created: ? - * Description: Set up the interrupt priorities - * - * Modified: - * 1996 Roman Zippel - * 1999 D. Jeff Dionne <jeff@uclinux.org> - * 2000-2001 Lineo, Inc. D. Jefff Dionne <jeff@lineo.ca> - * 2002 Arcturus Networks Inc. MaTed <mated@sympatico.ca> - * 2003 Metrowerks/Motorola - * 2003 Bas Vermeulen <bas@buyways.nl> - * Copyright 2004-2006 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <linux/module.h> -#include <linux/kernel_stat.h> -#include <linux/seq_file.h> -#include <linux/irq.h> -#ifdef CONFIG_KGDB -#include <linux/kgdb.h> -#endif -#include <asm/traps.h> -#include <asm/blackfin.h> -#include <asm/gpio.h> -#include <asm/irq_handler.h> - -/* - * NOTES: - * - we have separated the physical Hardware interrupt from the - * levels that the LINUX kernel sees (see the description in irq.h) - * - - */ - -/* Initialize this to an actual value to force it into the .data - * section so that we know it is properly initialized at entry into - * the kernel but before bss is initialized to zero (which is where - * it would live otherwise). The 0x1f magic represents the IRQs we - * cannot actually mask out in hardware. - */ -unsigned long irq_flags = 0x1f; - -/* The number of spurious interrupts */ -atomic_t num_spurious; - -struct ivgx { - /* irq number for request_irq, available in mach-bf561/irq.h */ - int irqno; - /* corresponding bit in the SICA_ISR0 register */ - int isrflag0; - /* corresponding bit in the SICA_ISR1 register */ - int isrflag1; -} ivg_table[NR_PERI_INTS]; - -struct ivg_slice { - /* position of first irq in ivg_table for given ivg */ - struct ivgx *ifirst; - struct ivgx *istop; -} ivg7_13[IVG13 - IVG7 + 1]; - -static void search_IAR(void); - -/* - * Search SIC_IAR and fill tables with the irqvalues - * and their positions in the SIC_ISR register. - */ -static void __init search_IAR(void) -{ - unsigned ivg, irq_pos = 0; - for (ivg = 0; ivg <= IVG13 - IVG7; ivg++) { - int irqn; - - ivg7_13[ivg].istop = ivg7_13[ivg].ifirst = &ivg_table[irq_pos]; - - for (irqn = 0; irqn < NR_PERI_INTS; irqn++) { - int iar_shift = (irqn & 7) * 4; - if (ivg == - (0xf & - bfin_read32((unsigned long *)SICA_IAR0 + - (irqn >> 3)) >> iar_shift)) { - ivg_table[irq_pos].irqno = IVG7 + irqn; - ivg_table[irq_pos].isrflag0 = - (irqn < 32 ? (1 << irqn) : 0); - ivg_table[irq_pos].isrflag1 = - (irqn < 32 ? 0 : (1 << (irqn - 32))); - ivg7_13[ivg].istop++; - irq_pos++; - } - } - } -} - -/* - * This is for BF561 internal IRQs - */ - -static void ack_noop(unsigned int irq) -{ - /* Dummy function. */ -} - -static void bf561_core_mask_irq(unsigned int irq) -{ - irq_flags &= ~(1 << irq); - if (!irqs_disabled()) - local_irq_enable(); -} - -static void bf561_core_unmask_irq(unsigned int irq) -{ - irq_flags |= 1 << irq; - /* - * If interrupts are enabled, IMASK must contain the same value - * as irq_flags. Make sure that invariant holds. If interrupts - * are currently disabled we need not do anything; one of the - * callers will take care of setting IMASK to the proper value - * when reenabling interrupts. - * local_irq_enable just does "STI irq_flags", so it's exactly - * what we need. - */ - if (!irqs_disabled()) - local_irq_enable(); - return; -} - -static void bf561_internal_mask_irq(unsigned int irq) -{ - unsigned long irq_mask; - if ((irq - (IRQ_CORETMR + 1)) < 32) { - irq_mask = (1 << (irq - (IRQ_CORETMR + 1))); - bfin_write_SICA_IMASK0(bfin_read_SICA_IMASK0() & ~irq_mask); - } else { - irq_mask = (1 << (irq - (IRQ_CORETMR + 1) - 32)); - bfin_write_SICA_IMASK1(bfin_read_SICA_IMASK1() & ~irq_mask); - } -} - -static void bf561_internal_unmask_irq(unsigned int irq) -{ - unsigned long irq_mask; - - if ((irq - (IRQ_CORETMR + 1)) < 32) { - irq_mask = (1 << (irq - (IRQ_CORETMR + 1))); - bfin_write_SICA_IMASK0(bfin_read_SICA_IMASK0() | irq_mask); - } else { - irq_mask = (1 << (irq - (IRQ_CORETMR + 1) - 32)); - bfin_write_SICA_IMASK1(bfin_read_SICA_IMASK1() | irq_mask); - } - SSYNC(); -} - -static struct irq_chip bf561_core_irqchip = { - .ack = ack_noop, - .mask = bf561_core_mask_irq, - .unmask = bf561_core_unmask_irq, -}; - -static struct irq_chip bf561_internal_irqchip = { - .ack = ack_noop, - .mask = bf561_internal_mask_irq, - .unmask = bf561_internal_unmask_irq, -}; - -static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)]; -static unsigned short gpio_edge_triggered[gpio_bank(MAX_BLACKFIN_GPIOS)]; - -static void bf561_gpio_ack_irq(unsigned int irq) -{ - u16 gpionr = irq - IRQ_PF0; - - if (gpio_edge_triggered[gpio_bank(gpionr)] & gpio_bit(gpionr)) { - set_gpio_data(gpionr, 0); - SSYNC(); - } -} - -static void bf561_gpio_mask_ack_irq(unsigned int irq) -{ - u16 gpionr = irq - IRQ_PF0; - - if (gpio_edge_triggered[gpio_bank(gpionr)] & gpio_bit(gpionr)) { - set_gpio_data(gpionr, 0); - SSYNC(); - } - - set_gpio_maska(gpionr, 0); - SSYNC(); -} - -static void bf561_gpio_mask_irq(unsigned int irq) -{ - set_gpio_maska(irq - IRQ_PF0, 0); - SSYNC(); -} - -static void bf561_gpio_unmask_irq(unsigned int irq) -{ - set_gpio_maska(irq - IRQ_PF0, 1); - SSYNC(); -} - -static unsigned int bf561_gpio_irq_startup(unsigned int irq) -{ - unsigned int ret; - char buf[8]; - u16 gpionr = irq - IRQ_PF0; - - if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) { - snprintf(buf, sizeof buf, "IRQ %d", irq); - ret = gpio_request(gpionr, buf); - if (ret) - return ret; - - } - - gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr); - bf561_gpio_unmask_irq(irq); - - return ret; - -} - -static void bf561_gpio_irq_shutdown(unsigned int irq) -{ - bf561_gpio_mask_irq(irq); - gpio_free(irq - IRQ_PF0); - gpio_enabled[gpio_bank(irq - IRQ_PF0)] &= ~gpio_bit(irq - IRQ_PF0); -} - -static int bf561_gpio_irq_type(unsigned int irq, unsigned int type) -{ - - unsigned int ret; - char buf[8]; - u16 gpionr = irq - IRQ_PF0; - - - if (type == IRQ_TYPE_PROBE) { - /* only probe unenabled GPIO interrupt lines */ - if (gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr)) - return 0; - type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; - - } - - if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING | - IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { - - if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) { - snprintf(buf, sizeof buf, "IRQ %d", irq); - ret = gpio_request(gpionr, buf); - if (ret) - return ret; - - } - - gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr); - } else { - gpio_enabled[gpio_bank(gpionr)] &= ~gpio_bit(gpionr); - return 0; - } - - - set_gpio_dir(gpionr, 0); - set_gpio_inen(gpionr, 1); - - - if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { - gpio_edge_triggered[gpio_bank(gpionr)] |= gpio_bit(gpionr); - set_gpio_edge(gpionr, 1); - } else { - set_gpio_edge(gpionr, 0); - gpio_edge_triggered[gpio_bank(gpionr)] &= ~gpio_bit(gpionr); - } - - if ((type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) - == (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) - set_gpio_both(gpionr, 1); - else - set_gpio_both(gpionr, 0); - - if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW))) - set_gpio_polar(gpionr, 1); /* low or falling edge denoted by one */ - else - set_gpio_polar(gpionr, 0); /* high or rising edge denoted by zero */ - - SSYNC(); - - if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) - set_irq_handler(irq, handle_edge_irq); - else - set_irq_handler(irq, handle_level_irq); - - return 0; -} - -static struct irq_chip bf561_gpio_irqchip = { - .ack = bf561_gpio_ack_irq, - .mask = bf561_gpio_mask_irq, - .mask_ack = bf561_gpio_mask_ack_irq, - .unmask = bf561_gpio_unmask_irq, - .set_type = bf561_gpio_irq_type, - .startup = bf561_gpio_irq_startup, - .shutdown = bf561_gpio_irq_shutdown -}; - -static void bf561_demux_gpio_irq(unsigned int inta_irq, - struct irq_desc *intb_desc) -{ - int irq, flag_d, mask; - u16 gpio; - - switch (inta_irq) { - case IRQ_PROG0_INTA: - irq = IRQ_PF0; - break; - case IRQ_PROG1_INTA: - irq = IRQ_PF16; - break; - case IRQ_PROG2_INTA: - irq = IRQ_PF32; - break; - default: - dump_stack(); - return; - } - - gpio = irq - IRQ_PF0; - - flag_d = get_gpiop_data(gpio); - mask = flag_d & (gpio_enabled[gpio_bank(gpio)] & - get_gpiop_maska(gpio)); - - do { - if (mask & 1) { - struct irq_desc *desc = irq_desc + irq; - desc->handle_irq(irq, desc); - } - irq++; - mask >>= 1; - } while (mask); - - -} - -void __init init_exception_vectors(void) -{ - SSYNC(); - - /* cannot program in software: - * evt0 - emulation (jtag) - * evt1 - reset - */ - bfin_write_EVT2(evt_nmi); - bfin_write_EVT3(trap); - bfin_write_EVT5(evt_ivhw); - bfin_write_EVT6(evt_timer); - bfin_write_EVT7(evt_evt7); - bfin_write_EVT8(evt_evt8); - bfin_write_EVT9(evt_evt9); - bfin_write_EVT10(evt_evt10); - bfin_write_EVT11(evt_evt11); - bfin_write_EVT12(evt_evt12); - bfin_write_EVT13(evt_evt13); - bfin_write_EVT14(evt14_softirq); - bfin_write_EVT15(evt_system_call); - CSYNC(); -} - -/* - * This function should be called during kernel startup to initialize - * the BFin IRQ handling routines. - */ -int __init init_arch_irq(void) -{ - int irq; - unsigned long ilat = 0; - /* Disable all the peripheral intrs - page 4-29 HW Ref manual */ - bfin_write_SICA_IMASK0(SIC_UNMASK_ALL); - bfin_write_SICA_IMASK1(SIC_UNMASK_ALL); - SSYNC(); - - bfin_write_SICA_IWR0(IWR_ENABLE_ALL); - bfin_write_SICA_IWR1(IWR_ENABLE_ALL); - - local_irq_disable(); - - init_exception_buff(); - - for (irq = 0; irq <= SYS_IRQS; irq++) { - if (irq <= IRQ_CORETMR) - set_irq_chip(irq, &bf561_core_irqchip); - else - set_irq_chip(irq, &bf561_internal_irqchip); - - if ((irq != IRQ_PROG0_INTA) && - (irq != IRQ_PROG1_INTA) && - (irq != IRQ_PROG2_INTA)) - set_irq_handler(irq, handle_simple_irq); - else - set_irq_chained_handler(irq, bf561_demux_gpio_irq); - } - - for (irq = IRQ_PF0; irq <= IRQ_PF47; irq++) { - set_irq_chip(irq, &bf561_gpio_irqchip); - /* if configured as edge, then will be changed to do_edge_IRQ */ - set_irq_handler(irq, handle_level_irq); - } - - bfin_write_IMASK(0); - CSYNC(); - ilat = bfin_read_ILAT(); - CSYNC(); - bfin_write_ILAT(ilat); - CSYNC(); - - printk(KERN_INFO "Configuring Blackfin Priority Driven Interrupts\n"); - /* IMASK=xxx is equivalent to STI xx or irq_flags=xx, - * local_irq_enable() - */ - program_IAR(); - /* Therefore it's better to setup IARs before interrupts enabled */ - search_IAR(); - - /* Enable interrupts IVG7-15 */ - irq_flags = irq_flags | IMASK_IVG15 | - IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 | - IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW; - - return 0; -} - -#ifdef CONFIG_DO_IRQ_L1 -__attribute__((l1_text)) -#endif -void do_irq(int vec, struct pt_regs *fp) -{ - if (vec == EVT_IVTMR_P) { - vec = IRQ_CORETMR; - } else { - struct ivgx *ivg = ivg7_13[vec - IVG7].ifirst; - struct ivgx *ivg_stop = ivg7_13[vec - IVG7].istop; - unsigned long sic_status0, sic_status1; - - SSYNC(); - sic_status0 = bfin_read_SICA_IMASK0() & bfin_read_SICA_ISR0(); - sic_status1 = bfin_read_SICA_IMASK1() & bfin_read_SICA_ISR1(); - - for (;; ivg++) { - if (ivg >= ivg_stop) { - atomic_inc(&num_spurious); - return; - } else if ((sic_status0 & ivg->isrflag0) || - (sic_status1 & ivg->isrflag1)) - break; - } - vec = ivg->irqno; - } - asm_do_IRQ(vec, fp); - -#ifdef CONFIG_KGDB - kgdb_process_breakpoint(); -#endif -} diff --git a/arch/blackfin/mach-common/ints-priority-sc.c b/arch/blackfin/mach-common/ints-priority.c index dec42acb5de..166dbba0c39 100644 --- a/arch/blackfin/mach-common/ints-priority-sc.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -98,8 +98,7 @@ static void __init search_IAR(void) for (irqn = 0; irqn < NR_PERI_INTS; irqn++) { int iar_shift = (irqn & 7) * 4; - if (ivg == - (0xf & + if (ivg == (0xf & #ifndef CONFIG_BF52x bfin_read32((unsigned long *)SIC_IAR0 + (irqn >> 3)) >> iar_shift)) { @@ -206,8 +205,7 @@ static void bfin_generic_error_mask_irq(unsigned int irq) if (!error_int_mask) { local_irq_disable(); bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() & - ~(1 << - (IRQ_GENERIC_ERROR - + ~(1 << (IRQ_GENERIC_ERROR - (IRQ_CORETMR + 1)))); SSYNC(); local_irq_enable(); @@ -232,7 +230,7 @@ static struct irq_chip bfin_generic_error_irqchip = { }; static void bfin_demux_error_irq(unsigned int int_err_irq, - struct irq_desc *intb_desc) + struct irq_desc *inta_desc) { int irq = 0; @@ -446,27 +444,81 @@ static struct irq_chip bfin_gpio_irqchip = { .shutdown = bfin_gpio_irq_shutdown }; -static void bfin_demux_gpio_irq(unsigned int intb_irq, - struct irq_desc *intb_desc) +static void bfin_demux_gpio_irq(unsigned int inta_irq, + struct irq_desc *desc) { - u16 i; - struct irq_desc *desc; - - for (i = 0; i < MAX_BLACKFIN_GPIOS; i += 16) { - int irq = IRQ_PF0 + i; - int flag_d = get_gpiop_data(i); - int mask = - flag_d & (gpio_enabled[gpio_bank(i)] & get_gpiop_maska(i)); - - while (mask) { - if (mask & 1) { - desc = irq_desc + irq; - desc->handle_irq(irq, desc); + unsigned int i, gpio, mask, irq, search = 0; + + switch (inta_irq) { +#if defined(CONFIG_BF53x) + case IRQ_PROG_INTA: + irq = IRQ_PF0; + search = 1; + break; +# if defined(BF537_FAMILY) && !(defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)) + case IRQ_MAC_RX: + irq = IRQ_PH0; + break; +# endif +#elif defined(CONFIG_BF52x) + case IRQ_PORTF_INTA: + irq = IRQ_PF0; + break; + case IRQ_PORTG_INTA: + irq = IRQ_PG0; + break; + case IRQ_PORTH_INTA: + irq = IRQ_PH0; + break; +#elif defined(CONFIG_BF561) + case IRQ_PROG0_INTA: + irq = IRQ_PF0; + break; + case IRQ_PROG1_INTA: + irq = IRQ_PF16; + break; + case IRQ_PROG2_INTA: + irq = IRQ_PF32; + break; +#endif + default: + BUG(); + return; + } + + if (search) { + for (i = 0; i < MAX_BLACKFIN_GPIOS; i += 16) { + irq += i; + + mask = get_gpiop_data(i) & + (gpio_enabled[gpio_bank(i)] & + get_gpiop_maska(i)); + + while (mask) { + if (mask & 1) { + desc = irq_desc + irq; + desc->handle_irq(irq, desc); + } + irq++; + mask >>= 1; } - irq++; - mask >>= 1; } + } else { + gpio = irq_to_gpio(irq); + mask = get_gpiop_data(gpio) & + (gpio_enabled[gpio_bank(gpio)] & + get_gpiop_maska(gpio)); + + do { + if (mask & 1) { + desc = irq_desc + irq; + desc->handle_irq(irq, desc); + } + irq++; + mask >>= 1; + } while (mask); } + } #else /* CONFIG_BF54x */ @@ -721,14 +773,13 @@ static struct irq_chip bfin_gpio_irqchip = { .shutdown = bfin_gpio_irq_shutdown }; -static void bfin_demux_gpio_irq(unsigned int intb_irq, - struct irq_desc *intb_desc) +static void bfin_demux_gpio_irq(unsigned int inta_irq, + struct irq_desc *desc) { u8 bank, pint_val; u32 request, irq; - struct irq_desc *desc; - switch (intb_irq) { + switch (inta_irq) { case IRQ_PINT0: bank = 0; break; @@ -795,7 +846,7 @@ int __init init_arch_irq(void) int irq; unsigned long ilat = 0; /* Disable all the peripheral intrs - page 4-29 HW Ref manual */ -#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) +#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) bfin_write_SIC_IMASK0(SIC_UNMASK_ALL); bfin_write_SIC_IMASK1(SIC_UNMASK_ALL); bfin_write_SIC_IWR0(IWR_ENABLE_ALL); @@ -812,6 +863,8 @@ int __init init_arch_irq(void) local_irq_disable(); + init_exception_buff(); + #ifdef CONFIG_BF54x # ifdef CONFIG_PINTx_REASSIGN pint[0]->assign = CONFIG_PINT0_ASSIGN; @@ -874,6 +927,19 @@ int __init init_arch_irq(void) set_irq_chained_handler(irq, bfin_demux_gpio_irq); break; +#elif defined(CONFIG_BF561) + case IRQ_PROG0_INTA: + set_irq_chained_handler(irq, + bfin_demux_gpio_irq); + break; + case IRQ_PROG1_INTA: + set_irq_chained_handler(irq, + bfin_demux_gpio_irq); + break; + case IRQ_PROG2_INTA: + set_irq_chained_handler(irq, + bfin_demux_gpio_irq); + break; #endif default: set_irq_handler(irq, handle_simple_irq); @@ -893,11 +959,8 @@ int __init init_arch_irq(void) } #endif -#ifndef CONFIG_BF54x - for (irq = IRQ_PF0; irq < NR_IRQS; irq++) { -#else - for (irq = IRQ_PA0; irq < NR_IRQS; irq++) { -#endif + for (irq = GPIO_IRQ_BASE; irq < NR_IRQS; irq++) { + set_irq_chip(irq, &bfin_gpio_irqchip); /* if configured as edge, then will be changed to do_edge_IRQ */ set_irq_handler(irq, handle_level_irq); @@ -936,7 +999,7 @@ void do_irq(int vec, struct pt_regs *fp) } else { struct ivgx *ivg = ivg7_13[vec - IVG7].ifirst; struct ivgx *ivg_stop = ivg7_13[vec - IVG7].istop; -#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) +#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) unsigned long sic_status[3]; SSYNC(); |