diff options
author | Alexander Shiyan <shc_work@mail.ru> | 2012-11-17 17:57:14 +0400 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2012-11-21 09:57:42 -0800 |
commit | 99f04c8f69753e4032059eeb0c21197948e459f7 (patch) | |
tree | 876d54413124fb63dcab9d95446a8686953d2414 /arch/arm/mach-clps711x/common.c | |
parent | 0d8be81c0e15ad8ebdd35bbbeb35b03f85a4b558 (diff) | |
download | op-kernel-dev-99f04c8f69753e4032059eeb0c21197948e459f7.zip op-kernel-dev-99f04c8f69753e4032059eeb0c21197948e459f7.tar.gz |
ARM: clps711x: Implement usage "MULTI_IRQ_HANDLER" kernel option for a platform
Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'arch/arm/mach-clps711x/common.c')
-rw-r--r-- | arch/arm/mach-clps711x/common.c | 45 |
1 files changed, 41 insertions, 4 deletions
diff --git a/arch/arm/mach-clps711x/common.c b/arch/arm/mach-clps711x/common.c index 286d6e6..0842024 100644 --- a/arch/arm/mach-clps711x/common.c +++ b/arch/arm/mach-clps711x/common.c @@ -29,6 +29,7 @@ #include <linux/clockchips.h> #include <linux/clk-provider.h> +#include <asm/exception.h> #include <asm/mach/map.h> #include <asm/mach/time.h> #include <asm/system_misc.h> @@ -134,13 +135,11 @@ static struct irq_chip int2_chip = { .irq_unmask = int2_unmask, }; -struct clps711x_irqdesc { +static struct { int nr; struct irq_chip *chip; irq_flow_handler_t handle; -}; - -static struct clps711x_irqdesc clps711x_irqdescs[] __initdata = { +} clps711x_irqdescs[] __initdata = { { IRQ_CSINT, &int1_chip, handle_fasteoi_irq, }, { IRQ_EINT1, &int1_chip, handle_level_irq, }, { IRQ_EINT2, &int1_chip, handle_level_irq, }, @@ -191,6 +190,44 @@ void __init clps711x_init_irq(void) } } +inline u32 fls16(u32 x) +{ + u32 r = 15; + + if (!(x & 0xff00)) { + x <<= 8; + r -= 8; + } + if (!(x & 0xf000)) { + x <<= 4; + r -= 4; + } + if (!(x & 0xc000)) { + x <<= 2; + r -= 2; + } + if (!(x & 0x8000)) + r--; + + return r; +} + +asmlinkage void __exception_irq_entry clps711x_handle_irq(struct pt_regs *regs) +{ + u32 irqstat; + void __iomem *base = CLPS711X_VIRT_BASE; + + irqstat = readl_relaxed(base + INTSR1) & readl_relaxed(base + INTMR1); + if (irqstat) { + handle_IRQ(fls16(irqstat), regs); + return; + } + + irqstat = readl_relaxed(base + INTSR2) & readl_relaxed(base + INTMR2); + if (likely(irqstat)) + handle_IRQ(fls16(irqstat) + 16, regs); +} + static void clps711x_clockevent_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { |