IC and GPIC are now chain handlers of the traditional MIPS IRQ controller. Signed-off-by: Manuel Lauss <manuel.lauss@xxxxxxxxxxxxxx> --- Even the C0 timer works with this. arch/mips/alchemy/common/gpioint.c | 26 +++++++------- arch/mips/alchemy/common/irq.c | 62 +++++++++++++++--------------------- 2 files changed, 39 insertions(+), 49 deletions(-) diff --git a/arch/mips/alchemy/common/gpioint.c b/arch/mips/alchemy/common/gpioint.c index 5d7729a..daaaab0 100644 --- a/arch/mips/alchemy/common/gpioint.c +++ b/arch/mips/alchemy/common/gpioint.c @@ -349,6 +349,12 @@ static struct syscore_ops alchemy_gpic_pmops = { .resume = alchemy_gpic_resume, }; +static void alchemy_gpic_dispatch(unsigned int irq, struct irq_desc *d) +{ + int i = __raw_readl(AU1300_GPIC_ADDR + AU1300_GPIC_PRIENC); + generic_handle_irq(ALCHEMY_GPIC_INT_BASE + i); +} + static void __init alchemy_gpic_init_irq(const struct gpic_devint_data *dints) { int i; @@ -383,7 +389,10 @@ static void __init alchemy_gpic_init_irq(const struct gpic_devint_data *dints) dints++; } - set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3); + irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 2, alchemy_gpic_dispatch); + irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 3, alchemy_gpic_dispatch); + irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 4, alchemy_gpic_dispatch); + irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 5, alchemy_gpic_dispatch); } /**********************************************************************/ @@ -397,17 +406,8 @@ void __init arch_init_irq(void) } } -#define CAUSEF_GPIC (CAUSEF_IP2 | CAUSEF_IP3 | CAUSEF_IP4 | CAUSEF_IP5) - -void plat_irq_dispatch(void) +asmlinkage void plat_irq_dispatch(void) { - unsigned long i, c = read_c0_cause() & read_c0_status(); - - if (c & CAUSEF_IP7) /* c0 timer */ - do_IRQ(MIPS_CPU_IRQ_BASE + 7); - else if (likely(c & CAUSEF_GPIC)) { - i = __raw_readl(AU1300_GPIC_ADDR + AU1300_GPIC_PRIENC); - do_IRQ(i + ALCHEMY_GPIC_INT_BASE); - } else - spurious_interrupt(); + unsigned long r = (read_c0_status() & read_c0_cause()) >> 8; + do_IRQ(MIPS_CPU_IRQ_BASE + __ffs(r & 0xff)); } diff --git a/arch/mips/alchemy/common/irq.c b/arch/mips/alchemy/common/irq.c index f206e24..ee80a32 100644 --- a/arch/mips/alchemy/common/irq.c +++ b/arch/mips/alchemy/common/irq.c @@ -459,41 +459,6 @@ static int au1x_ic_settype(struct irq_data *d, unsigned int flow_type) return ret; } -asmlinkage void plat_irq_dispatch(void) -{ - unsigned int pending = read_c0_status() & read_c0_cause(); - unsigned long s, off; - - if (pending & CAUSEF_IP7) { - off = MIPS_CPU_IRQ_BASE + 7; - goto handle; - } else if (pending & CAUSEF_IP2) { - s = KSEG1ADDR(AU1000_IC0_PHYS_ADDR) + IC_REQ0INT; - off = AU1000_INTC0_INT_BASE; - } else if (pending & CAUSEF_IP3) { - s = KSEG1ADDR(AU1000_IC0_PHYS_ADDR) + IC_REQ1INT; - off = AU1000_INTC0_INT_BASE; - } else if (pending & CAUSEF_IP4) { - s = KSEG1ADDR(AU1000_IC1_PHYS_ADDR) + IC_REQ0INT; - off = AU1000_INTC1_INT_BASE; - } else if (pending & CAUSEF_IP5) { - s = KSEG1ADDR(AU1000_IC1_PHYS_ADDR) + IC_REQ1INT; - off = AU1000_INTC1_INT_BASE; - } else - goto spurious; - - s = __raw_readl((void __iomem *)s); - if (unlikely(!s)) { -spurious: - spurious_interrupt(); - return; - } - off += __ffs(s); -handle: - do_IRQ(off); -} - - static inline void ic_init(void __iomem *base) { /* initialize interrupt controller to a safe state */ @@ -562,6 +527,22 @@ static struct syscore_ops alchemy_ic_syscore_ops = { .resume = alchemy_ic_resume, }; +/* create chained handlers for the 4 IC requests to the MIPS IRQ ctrl */ +#define DISP(name, base, addr) \ +static void au1000_##name##_dispatch(unsigned int irq, struct irq_desc *d) \ +{ \ + unsigned long r = __raw_readl((void __iomem *)KSEG1ADDR(addr)); \ + if (likely(r)) \ + generic_handle_irq(base + __ffs(r)); \ + else \ + spurious_interrupt(); \ +} + +DISP(ic0r0, AU1000_INTC0_INT_BASE, AU1000_IC0_PHYS_ADDR + IC_REQ0INT) +DISP(ic0r1, AU1000_INTC0_INT_BASE, AU1000_IC0_PHYS_ADDR + IC_REQ1INT) +DISP(ic1r0, AU1000_INTC1_INT_BASE, AU1000_IC1_PHYS_ADDR + IC_REQ0INT) +DISP(ic1r1, AU1000_INTC1_INT_BASE, AU1000_IC1_PHYS_ADDR + IC_REQ1INT) + static void __init au1000_init_irq(struct au1xxx_irqmap *map) { unsigned int bit, irq_nr; @@ -603,7 +584,10 @@ static void __init au1000_init_irq(struct au1xxx_irqmap *map) ++map; } - set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3); + irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 2, au1000_ic0r0_dispatch); + irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 3, au1000_ic0r1_dispatch); + irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 4, au1000_ic1r0_dispatch); + irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 5, au1000_ic1r1_dispatch); } void __init arch_init_irq(void) @@ -626,3 +610,9 @@ void __init arch_init_irq(void) break; } } + +asmlinkage void plat_irq_dispatch(void) +{ + unsigned long r = (read_c0_status() & read_c0_cause()) >> 8; + do_IRQ(MIPS_CPU_IRQ_BASE + __ffs(r & 0xff)); +} -- 1.7.7.2