diff options
author | Maxime Bizon <mbizon@freebox.fr> | 2011-11-04 19:09:32 +0100 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2011-12-07 22:03:03 +0000 |
commit | 37c42a741f6c2c76dc5e61650e5d66dd20540aaf (patch) | |
tree | 7e36523bbbc016e4606966ef45ba006999b93cc2 /arch/mips/bcm63xx | |
parent | f61cced99347783c1f3a7464e88b855a5ca6c227 (diff) |
MIPS: BCM63XX: Prepare irq code to handle different external irq hardware implementation.
External irq only works for 6348, change code to prepare support of
other CPUs.
Signed-off-by: Maxime Bizon <mbizon@freebox.fr>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/2895/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/bcm63xx')
-rw-r--r-- | arch/mips/bcm63xx/irq.c | 104 |
1 files changed, 67 insertions, 37 deletions
diff --git a/arch/mips/bcm63xx/irq.c b/arch/mips/bcm63xx/irq.c index a81cd828c76..cdf352b040a 100644 --- a/arch/mips/bcm63xx/irq.c +++ b/arch/mips/bcm63xx/irq.c @@ -25,18 +25,32 @@ static void __dispatch_internal(void) __maybe_unused; #ifdef CONFIG_BCM63XX_CPU_6338 #define irq_stat_reg PERF_IRQSTAT_6338_REG #define irq_mask_reg PERF_IRQMASK_6338_REG +#define is_ext_irq_cascaded 0 +#define ext_irq_start 0 +#define ext_irq_end 0 #endif #ifdef CONFIG_BCM63XX_CPU_6345 #define irq_stat_reg PERF_IRQSTAT_6345_REG #define irq_mask_reg PERF_IRQMASK_6345_REG +#define is_ext_irq_cascaded 0 +#define ext_irq_start 0 +#define ext_irq_end 0 #endif #ifdef CONFIG_BCM63XX_CPU_6348 #define irq_stat_reg PERF_IRQSTAT_6348_REG #define irq_mask_reg PERF_IRQMASK_6348_REG +#define dispatch_internal __dispatch_internal +#define is_ext_irq_cascaded 0 +#define ext_irq_start 0 +#define ext_irq_end 0 #endif #ifdef CONFIG_BCM63XX_CPU_6358 #define irq_stat_reg PERF_IRQSTAT_6358_REG #define irq_mask_reg PERF_IRQMASK_6358_REG +#define dispatch_internal __dispatch_internal +#define is_ext_irq_cascaded 1 +#define ext_irq_start (BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE) +#define ext_irq_end (BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE) #endif #define dispatch_internal __dispatch_internal @@ -51,6 +65,8 @@ static inline void bcm63xx_init_irq(void) static u32 irq_stat_addr, irq_mask_addr; static void (*dispatch_internal)(void); +static int is_ext_irq_cascaded; +static unsigned int ext_irq_start, ext_irq_end; static void bcm63xx_init_irq(void) { @@ -73,6 +89,9 @@ static void bcm63xx_init_irq(void) case BCM6358_CPU_ID: irq_stat_addr += PERF_IRQSTAT_6358_REG; irq_mask_addr += PERF_IRQMASK_6358_REG; + is_ext_irq_cascaded = 1; + ext_irq_start = BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE; + ext_irq_end = BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE; break; default: BUG(); @@ -84,7 +103,11 @@ static void bcm63xx_init_irq(void) static inline void handle_internal(int intbit) { - do_IRQ(intbit + IRQ_INTERNAL_BASE); + if (is_ext_irq_cascaded && + intbit >= ext_irq_start && intbit <= ext_irq_end) + do_IRQ(intbit - ext_irq_start + IRQ_EXTERNAL_BASE); + else + do_IRQ(intbit + IRQ_INTERNAL_BASE); } /* @@ -128,14 +151,16 @@ asmlinkage void plat_irq_dispatch(void) do_IRQ(7); if (cause & CAUSEF_IP2) dispatch_internal(); - if (cause & CAUSEF_IP3) - do_IRQ(IRQ_EXT_0); - if (cause & CAUSEF_IP4) - do_IRQ(IRQ_EXT_1); - if (cause & CAUSEF_IP5) - do_IRQ(IRQ_EXT_2); - if (cause & CAUSEF_IP6) - do_IRQ(IRQ_EXT_3); + if (!is_ext_irq_cascaded) { + if (cause & CAUSEF_IP3) + do_IRQ(IRQ_EXT_0); + if (cause & CAUSEF_IP4) + do_IRQ(IRQ_EXT_1); + if (cause & CAUSEF_IP5) + do_IRQ(IRQ_EXT_2); + if (cause & CAUSEF_IP6) + do_IRQ(IRQ_EXT_3); + } } while (1); } @@ -143,9 +168,8 @@ asmlinkage void plat_irq_dispatch(void) * internal IRQs operations: only mask/unmask on PERF irq mask * register. */ -static inline void bcm63xx_internal_irq_mask(struct irq_data *d) +static void internal_irq_mask(unsigned int irq) { - unsigned int irq = d->irq - IRQ_INTERNAL_BASE; u32 mask; mask = bcm_readl(irq_mask_addr); @@ -153,9 +177,8 @@ static inline void bcm63xx_internal_irq_mask(struct irq_data *d) bcm_writel(mask, irq_mask_addr); } -static void bcm63xx_internal_irq_unmask(struct irq_data *d) +static void internal_irq_unmask(unsigned int irq) { - unsigned int irq = d->irq - IRQ_INTERNAL_BASE; u32 mask; mask = bcm_readl(irq_mask_addr); @@ -163,33 +186,47 @@ static void bcm63xx_internal_irq_unmask(struct irq_data *d) bcm_writel(mask, irq_mask_addr); } +static void bcm63xx_internal_irq_mask(struct irq_data *d) +{ + internal_irq_mask(d->irq - IRQ_INTERNAL_BASE); +} + +static void bcm63xx_internal_irq_unmask(struct irq_data *d) +{ + internal_irq_unmask(d->irq - IRQ_INTERNAL_BASE); +} + /* * external IRQs operations: mask/unmask and clear on PERF external * irq control register. */ static void bcm63xx_external_irq_mask(struct irq_data *d) { - unsigned int irq = d->irq - IRQ_EXT_BASE; + unsigned int irq = d->irq - IRQ_EXTERNAL_BASE; u32 reg; reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG); reg &= ~EXTIRQ_CFG_MASK(irq); bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG); + if (is_ext_irq_cascaded) + internal_irq_mask(irq + ext_irq_start); } static void bcm63xx_external_irq_unmask(struct irq_data *d) { - unsigned int irq = d->irq - IRQ_EXT_BASE; + unsigned int irq = d->irq - IRQ_EXTERNAL_BASE; u32 reg; reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG); reg |= EXTIRQ_CFG_MASK(irq); bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG); + if (is_ext_irq_cascaded) + internal_irq_unmask(irq + ext_irq_start); } static void bcm63xx_external_irq_clear(struct irq_data *d) { - unsigned int irq = d->irq - IRQ_EXT_BASE; + unsigned int irq = d->irq - IRQ_EXTERNAL_BASE; u32 reg; reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG); @@ -197,25 +234,10 @@ static void bcm63xx_external_irq_clear(struct irq_data *d) bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG); } -static unsigned int bcm63xx_external_irq_startup(struct irq_data *d) -{ - set_c0_status(0x100 << (d->irq - IRQ_MIPS_BASE)); - irq_enable_hazard(); - bcm63xx_external_irq_unmask(d); - return 0; -} - -static void bcm63xx_external_irq_shutdown(struct irq_data *d) -{ - bcm63xx_external_irq_mask(d); - clear_c0_status(0x100 << (d->irq - IRQ_MIPS_BASE)); - irq_disable_hazard(); -} - static int bcm63xx_external_irq_set_type(struct irq_data *d, unsigned int flow_type) { - unsigned int irq = d->irq - IRQ_EXT_BASE; + unsigned int irq = d->irq - IRQ_EXTERNAL_BASE; u32 reg; flow_type &= IRQ_TYPE_SENSE_MASK; @@ -275,9 +297,6 @@ static struct irq_chip bcm63xx_internal_irq_chip = { static struct irq_chip bcm63xx_external_irq_chip = { .name = "bcm63xx_epic", - .irq_startup = bcm63xx_external_irq_startup, - .irq_shutdown = bcm63xx_external_irq_shutdown, - .irq_ack = bcm63xx_external_irq_clear, .irq_mask = bcm63xx_external_irq_mask, @@ -292,6 +311,12 @@ static struct irqaction cpu_ip2_cascade_action = { .flags = IRQF_NO_THREAD, }; +static struct irqaction cpu_ext_cascade_action = { + .handler = no_action, + .name = "cascade_extirq", + .flags = IRQF_NO_THREAD, +}; + void __init arch_init_irq(void) { int i; @@ -302,9 +327,14 @@ void __init arch_init_irq(void) irq_set_chip_and_handler(i, &bcm63xx_internal_irq_chip, handle_level_irq); - for (i = IRQ_EXT_BASE; i < IRQ_EXT_BASE + 4; ++i) + for (i = IRQ_EXTERNAL_BASE; i < IRQ_EXTERNAL_BASE + 4; ++i) irq_set_chip_and_handler(i, &bcm63xx_external_irq_chip, handle_edge_irq); - setup_irq(IRQ_MIPS_BASE + 2, &cpu_ip2_cascade_action); + if (!is_ext_irq_cascaded) { + for (i = 3; i < 7; ++i) + setup_irq(MIPS_CPU_IRQ_BASE + i, &cpu_ext_cascade_action); + } + + setup_irq(MIPS_CPU_IRQ_BASE + 2, &cpu_ip2_cascade_action); } |