Commit 42a859daaf6af4d234fcf964a421666d5cca3f6a
Committed by
Nicolas Ferre
1 parent
f25b00be60
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
ARM: at91: aic can use fast eoi handler type
The Advanced Interrupt Controller allows us to use the fast EOI handler type. It lets us remove the Atmel specific workaround into arch/arm/kernel/irq.c used to indicate to the AIC the end of the interrupt treatment. Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
Showing 4 changed files with 17 additions and 24 deletions Side-by-side Diff
arch/arm/kernel/irq.c
... | ... | @@ -40,13 +40,6 @@ |
40 | 40 | #include <asm/mach/irq.h> |
41 | 41 | #include <asm/mach/time.h> |
42 | 42 | |
43 | -/* | |
44 | - * No architecture-specific irq_finish function defined in arm/arch/irqs.h. | |
45 | - */ | |
46 | -#ifndef irq_finish | |
47 | -#define irq_finish(irq) do { } while (0) | |
48 | -#endif | |
49 | - | |
50 | 43 | unsigned long irq_err_count; |
51 | 44 | |
52 | 45 | int arch_show_interrupts(struct seq_file *p, int prec) |
... | ... | @@ -84,9 +77,6 @@ |
84 | 77 | } else { |
85 | 78 | generic_handle_irq(irq); |
86 | 79 | } |
87 | - | |
88 | - /* AT91 specific workaround */ | |
89 | - irq_finish(irq); | |
90 | 80 | |
91 | 81 | irq_exit(); |
92 | 82 | set_irq_regs(old_regs); |
arch/arm/mach-at91/gpio.c
... | ... | @@ -26,6 +26,8 @@ |
26 | 26 | #include <linux/of_irq.h> |
27 | 27 | #include <linux/of_gpio.h> |
28 | 28 | |
29 | +#include <asm/mach/irq.h> | |
30 | + | |
29 | 31 | #include <mach/hardware.h> |
30 | 32 | #include <mach/at91_pio.h> |
31 | 33 | |
32 | 34 | |
33 | 35 | |
... | ... | @@ -585,15 +587,14 @@ |
585 | 587 | |
586 | 588 | static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) |
587 | 589 | { |
590 | + struct irq_chip *chip = irq_desc_get_chip(desc); | |
588 | 591 | struct irq_data *idata = irq_desc_get_irq_data(desc); |
589 | - struct irq_chip *chip = irq_data_get_irq_chip(idata); | |
590 | 592 | struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(idata); |
591 | 593 | void __iomem *pio = at91_gpio->regbase; |
592 | 594 | unsigned long isr; |
593 | 595 | int n; |
594 | 596 | |
595 | - /* temporarily mask (level sensitive) parent IRQ */ | |
596 | - chip->irq_ack(idata); | |
597 | + chained_irq_enter(chip, desc); | |
597 | 598 | for (;;) { |
598 | 599 | /* Reading ISR acks pending (edge triggered) GPIO interrupts. |
599 | 600 | * When there none are pending, we're finished unless we need |
... | ... | @@ -614,7 +615,7 @@ |
614 | 615 | n = find_next_bit(&isr, BITS_PER_LONG, n + 1); |
615 | 616 | } |
616 | 617 | } |
617 | - chip->irq_unmask(idata); | |
618 | + chained_irq_exit(chip, desc); | |
618 | 619 | /* now it may re-trigger */ |
619 | 620 | } |
620 | 621 |
arch/arm/mach-at91/include/mach/irqs.h
... | ... | @@ -28,13 +28,6 @@ |
28 | 28 | |
29 | 29 | |
30 | 30 | /* |
31 | - * Acknowledge interrupt with AIC after interrupt has been handled. | |
32 | - * (by kernel/irq.c) | |
33 | - */ | |
34 | -#define irq_finish(irq) do { at91_aic_write(AT91_AIC_EOICR, 0); } while (0) | |
35 | - | |
36 | - | |
37 | -/* | |
38 | 31 | * IRQ interrupt symbols are the AT91xxx_ID_* symbols |
39 | 32 | * for IRQs handled directly through the AIC, or else the AT91_PIN_* |
40 | 33 | * symbols in gpio.h for ones handled indirectly as GPIOs. |
arch/arm/mach-at91/irq.c
... | ... | @@ -55,6 +55,15 @@ |
55 | 55 | at91_aic_write(AT91_AIC_IECR, 1 << d->hwirq); |
56 | 56 | } |
57 | 57 | |
58 | +static void at91_aic_eoi(struct irq_data *d) | |
59 | +{ | |
60 | + /* | |
61 | + * Mark end-of-interrupt on AIC, the controller doesn't care about | |
62 | + * the value written. Moreover it's a write-only register. | |
63 | + */ | |
64 | + at91_aic_write(AT91_AIC_EOICR, 0); | |
65 | +} | |
66 | + | |
58 | 67 | unsigned int at91_extern_irq; |
59 | 68 | |
60 | 69 | #define is_extern_irq(hwirq) ((1 << (hwirq)) & at91_extern_irq) |
61 | 70 | |
... | ... | @@ -128,11 +137,11 @@ |
128 | 137 | |
129 | 138 | static struct irq_chip at91_aic_chip = { |
130 | 139 | .name = "AIC", |
131 | - .irq_ack = at91_aic_mask_irq, | |
132 | 140 | .irq_mask = at91_aic_mask_irq, |
133 | 141 | .irq_unmask = at91_aic_unmask_irq, |
134 | 142 | .irq_set_type = at91_aic_set_type, |
135 | 143 | .irq_set_wake = at91_aic_set_wake, |
144 | + .irq_eoi = at91_aic_eoi, | |
136 | 145 | }; |
137 | 146 | |
138 | 147 | static void __init at91_aic_hw_init(unsigned int spu_vector) |
... | ... | @@ -171,7 +180,7 @@ |
171 | 180 | /* Active Low interrupt, without priority */ |
172 | 181 | at91_aic_write(AT91_AIC_SMR(hw), AT91_AIC_SRCTYPE_LOW); |
173 | 182 | |
174 | - irq_set_chip_and_handler(virq, &at91_aic_chip, handle_level_irq); | |
183 | + irq_set_chip_and_handler(virq, &at91_aic_chip, handle_fasteoi_irq); | |
175 | 184 | set_irq_flags(virq, IRQF_VALID | IRQF_PROBE); |
176 | 185 | |
177 | 186 | return 0; |
... | ... | @@ -238,7 +247,7 @@ |
238 | 247 | /* Active Low interrupt, with the specified priority */ |
239 | 248 | at91_aic_write(AT91_AIC_SMR(i), AT91_AIC_SRCTYPE_LOW | priority[i]); |
240 | 249 | |
241 | - irq_set_chip_and_handler(i, &at91_aic_chip, handle_level_irq); | |
250 | + irq_set_chip_and_handler(i, &at91_aic_chip, handle_fasteoi_irq); | |
242 | 251 | set_irq_flags(i, IRQF_VALID | IRQF_PROBE); |
243 | 252 | } |
244 | 253 |