This lets me get rid of plat_irq_dispatch, so I can later build a
kernel with both the Au1000- and Au1300-style interrupt controllers
selected at runtime. And another stupid global function is gone as well.
Boots and runs on all my Alchemy boards.
Signed-off-by: Manuel Lauss <manuel.lauss@googlemail.com>
---
arch/mips/alchemy/common/irq.c | 55 ++++++++++++++--------------------------
arch/mips/kernel/genex.S | 12 ++++++++
2 files changed, 31 insertions(+), 36 deletions(-)
diff --git a/arch/mips/alchemy/common/irq.c b/arch/mips/alchemy/common/irq.c
index 8b60ba0..8cf7cc7 100644
--- a/arch/mips/alchemy/common/irq.c
+++ b/arch/mips/alchemy/common/irq.c
@@ -470,41 +470,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 */
@@ -521,6 +486,21 @@ static inline void ic_init(void __iomem *base)
wmb();
}
+#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;
@@ -561,7 +541,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)
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index 8882e57..306feaa 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -202,7 +202,19 @@ NESTED(handle_int, PT_SIZE, sp)
LONG_L s0, TI_REGS($28)
LONG_S sp, TI_REGS($28)
PTR_LA ra, ret_from_irq
+#ifdef CONFIG_MIPS_ALCHEMY
+ mfc0 t0, CP0_STATUS
+ mfc0 v1, CP0_CAUSE
+ and t0, v1, t0
+ sra t0, t0, 8
+ andi t0, t0, 0xff
+ li a0, 31
+ clz t0, t0
+ subu a0, a0, t0
+ j do_IRQ
+#else
j plat_irq_dispatch
+#endif
END(handle_int)
__INIT
--
1.7.6
|