diff options
-rw-r--r-- | arch/arm/common/vic.c | 38 | ||||
-rw-r--r-- | arch/arm/include/asm/hardware/vic.h | 3 |
2 files changed, 41 insertions, 0 deletions
diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c index a227a7d53700..0a69547e0312 100644 --- a/arch/arm/common/vic.c +++ b/arch/arm/common/vic.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/device.h> | 31 | #include <linux/device.h> |
32 | #include <linux/amba/bus.h> | 32 | #include <linux/amba/bus.h> |
33 | 33 | ||
34 | #include <asm/exception.h> | ||
34 | #include <asm/mach/irq.h> | 35 | #include <asm/mach/irq.h> |
35 | #include <asm/hardware/vic.h> | 36 | #include <asm/hardware/vic.h> |
36 | 37 | ||
@@ -428,3 +429,40 @@ int __init vic_of_init(struct device_node *node, struct device_node *parent) | |||
428 | return -EIO; | 429 | return -EIO; |
429 | } | 430 | } |
430 | #endif /* CONFIG OF */ | 431 | #endif /* CONFIG OF */ |
432 | |||
433 | #ifdef CONFIG_MULTI_IRQ_HANDLER | ||
434 | /* | ||
435 | * Handle each interrupt in a single VIC. Returns non-zero if we've | ||
436 | * handled at least one interrupt. This does a single read of the | ||
437 | * status register and handles all interrupts in order from LSB first. | ||
438 | */ | ||
439 | static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs) | ||
440 | { | ||
441 | u32 stat, irq; | ||
442 | int handled = 0; | ||
443 | |||
444 | stat = readl_relaxed(vic->base + VIC_IRQ_STATUS); | ||
445 | while (stat) { | ||
446 | irq = ffs(stat) - 1; | ||
447 | handle_IRQ(irq_domain_to_irq(&vic->domain, irq), regs); | ||
448 | stat &= ~(1 << irq); | ||
449 | handled = 1; | ||
450 | } | ||
451 | |||
452 | return handled; | ||
453 | } | ||
454 | |||
455 | /* | ||
456 | * Keep iterating over all registered VIC's until there are no pending | ||
457 | * interrupts. | ||
458 | */ | ||
459 | asmlinkage void __exception_irq_entry vic_handle_irq(struct pt_regs *regs) | ||
460 | { | ||
461 | int i, handled; | ||
462 | |||
463 | do { | ||
464 | for (i = 0, handled = 0; i < vic_id; ++i) | ||
465 | handled |= handle_one_vic(&vic_devices[i], regs); | ||
466 | } while (handled); | ||
467 | } | ||
468 | #endif /* CONFIG_MULTI_IRQ_HANDLER */ | ||
diff --git a/arch/arm/include/asm/hardware/vic.h b/arch/arm/include/asm/hardware/vic.h index b348a545de23..f42ebd619590 100644 --- a/arch/arm/include/asm/hardware/vic.h +++ b/arch/arm/include/asm/hardware/vic.h | |||
@@ -45,8 +45,11 @@ | |||
45 | #include <linux/types.h> | 45 | #include <linux/types.h> |
46 | 46 | ||
47 | struct device_node; | 47 | struct device_node; |
48 | struct pt_regs; | ||
49 | |||
48 | void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources); | 50 | void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources); |
49 | int vic_of_init(struct device_node *node, struct device_node *parent); | 51 | int vic_of_init(struct device_node *node, struct device_node *parent); |
52 | void vic_handle_irq(struct pt_regs *regs); | ||
50 | 53 | ||
51 | #endif /* __ASSEMBLY__ */ | 54 | #endif /* __ASSEMBLY__ */ |
52 | #endif | 55 | #endif |