aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/common/vic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/common/vic.c')
-rw-r--r--arch/arm/common/vic.c70
1 files changed, 36 insertions, 34 deletions
diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c
index 5feb004aaea6..49af6187885f 100644
--- a/arch/arm/common/vic.c
+++ b/arch/arm/common/vic.c
@@ -83,6 +83,8 @@ static struct vic_device vic_devices[CONFIG_ARM_VIC_NR];
83 83
84static int vic_id; 84static int vic_id;
85 85
86static void vic_handle_irq(struct pt_regs *regs);
87
86/** 88/**
87 * vic_init2 - common initialisation code 89 * vic_init2 - common initialisation code
88 * @base: Base of the VIC. 90 * @base: Base of the VIC.
@@ -199,6 +201,40 @@ static int vic_irqdomain_map(struct irq_domain *d, unsigned int irq,
199 return 0; 201 return 0;
200} 202}
201 203
204/*
205 * Handle each interrupt in a single VIC. Returns non-zero if we've
206 * handled at least one interrupt. This reads the status register
207 * before handling each interrupt, which is necessary given that
208 * handle_IRQ may briefly re-enable interrupts for soft IRQ handling.
209 */
210static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs)
211{
212 u32 stat, irq;
213 int handled = 0;
214
215 while ((stat = readl_relaxed(vic->base + VIC_IRQ_STATUS))) {
216 irq = ffs(stat) - 1;
217 handle_IRQ(irq_find_mapping(vic->domain, irq), regs);
218 handled = 1;
219 }
220
221 return handled;
222}
223
224/*
225 * Keep iterating over all registered VIC's until there are no pending
226 * interrupts.
227 */
228static asmlinkage void __exception_irq_entry vic_handle_irq(struct pt_regs *regs)
229{
230 int i, handled;
231
232 do {
233 for (i = 0, handled = 0; i < vic_id; ++i)
234 handled |= handle_one_vic(&vic_devices[i], regs);
235 } while (handled);
236}
237
202static struct irq_domain_ops vic_irqdomain_ops = { 238static struct irq_domain_ops vic_irqdomain_ops = {
203 .map = vic_irqdomain_map, 239 .map = vic_irqdomain_map,
204 .xlate = irq_domain_xlate_onetwocell, 240 .xlate = irq_domain_xlate_onetwocell,
@@ -446,37 +482,3 @@ int __init vic_of_init(struct device_node *node, struct device_node *parent)
446 return 0; 482 return 0;
447} 483}
448#endif /* CONFIG OF */ 484#endif /* CONFIG OF */
449
450/*
451 * Handle each interrupt in a single VIC. Returns non-zero if we've
452 * handled at least one interrupt. This reads the status register
453 * before handling each interrupt, which is necessary given that
454 * handle_IRQ may briefly re-enable interrupts for soft IRQ handling.
455 */
456static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs)
457{
458 u32 stat, irq;
459 int handled = 0;
460
461 while ((stat = readl_relaxed(vic->base + VIC_IRQ_STATUS))) {
462 irq = ffs(stat) - 1;
463 handle_IRQ(irq_find_mapping(vic->domain, irq), regs);
464 handled = 1;
465 }
466
467 return handled;
468}
469
470/*
471 * Keep iterating over all registered VIC's until there are no pending
472 * interrupts.
473 */
474asmlinkage void __exception_irq_entry vic_handle_irq(struct pt_regs *regs)
475{
476 int i, handled;
477
478 do {
479 for (i = 0, handled = 0; i < vic_id; ++i)
480 handled |= handle_one_vic(&vic_devices[i], regs);
481 } while (handled);
482}