External irq only works for 6348, change code to prepare support of other CPUs. Signed-off-by: Maxime Bizon <mbizon@xxxxxxxxxx> --- arch/mips/bcm63xx/irq.c | 77 ++++++++++++++++++++++++++++++++++++---------- 1 files changed, 60 insertions(+), 17 deletions(-) diff --git a/arch/mips/bcm63xx/irq.c b/arch/mips/bcm63xx/irq.c index d002831..2e4f317 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_EXT_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,6 +186,16 @@ 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. @@ -175,6 +208,8 @@ static void bcm63xx_external_irq_mask(struct irq_data *d) 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) @@ -185,6 +220,8 @@ static void bcm63xx_external_irq_unmask(struct irq_data *d) 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) @@ -195,12 +232,16 @@ static void bcm63xx_external_irq_clear(struct irq_data *d) reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG); reg |= EXTIRQ_CFG_CLEAR(irq); bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG); + if (is_ext_irq_cascaded) + internal_irq_mask(irq + ext_irq_start); } static unsigned int bcm63xx_external_irq_startup(struct irq_data *d) { - set_c0_status(0x100 << (d->irq - IRQ_MIPS_BASE)); - irq_enable_hazard(); + if (!is_ext_irq_cascaded) { + set_c0_status(0x100 << (d->irq - IRQ_MIPS_BASE)); + irq_enable_hazard(); + } bcm63xx_external_irq_unmask(d); return 0; } @@ -208,8 +249,10 @@ static unsigned int bcm63xx_external_irq_startup(struct irq_data *d) 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(); + if (!is_ext_irq_cascaded) { + clear_c0_status(0x100 << (d->irq - IRQ_MIPS_BASE)); + irq_disable_hazard(); + } } static int bcm63xx_external_irq_set_type(struct irq_data *d, -- 1.7.1.1