aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLudovic Desroches <ludovic.desroches@atmel.com>2012-05-25 08:11:51 -0400
committerNicolas Ferre <nicolas.ferre@atmel.com>2012-07-02 08:26:57 -0400
commit42a859daaf6af4d234fcf964a421666d5cca3f6a (patch)
treea025e57314554a8547b1afd782c7982631298adb
parentf25b00be60ab3865308a89437af66b277b04f53e (diff)
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>
-rw-r--r--arch/arm/kernel/irq.c10
-rw-r--r--arch/arm/mach-at91/gpio.c9
-rw-r--r--arch/arm/mach-at91/include/mach/irqs.h7
-rw-r--r--arch/arm/mach-at91/irq.c15
4 files changed, 17 insertions, 24 deletions
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 8349d4e97e2b..16cedb42c0c3 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -40,13 +40,6 @@
40#include <asm/mach/irq.h> 40#include <asm/mach/irq.h>
41#include <asm/mach/time.h> 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
50unsigned long irq_err_count; 43unsigned long irq_err_count;
51 44
52int arch_show_interrupts(struct seq_file *p, int prec) 45int arch_show_interrupts(struct seq_file *p, int prec)
@@ -85,9 +78,6 @@ void handle_IRQ(unsigned int irq, struct pt_regs *regs)
85 generic_handle_irq(irq); 78 generic_handle_irq(irq);
86 } 79 }
87 80
88 /* AT91 specific workaround */
89 irq_finish(irq);
90
91 irq_exit(); 81 irq_exit();
92 set_irq_regs(old_regs); 82 set_irq_regs(old_regs);
93} 83}
diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c
index 325837a264c9..be42cf0e74bd 100644
--- a/arch/arm/mach-at91/gpio.c
+++ b/arch/arm/mach-at91/gpio.c
@@ -26,6 +26,8 @@
26#include <linux/of_irq.h> 26#include <linux/of_irq.h>
27#include <linux/of_gpio.h> 27#include <linux/of_gpio.h>
28 28
29#include <asm/mach/irq.h>
30
29#include <mach/hardware.h> 31#include <mach/hardware.h>
30#include <mach/at91_pio.h> 32#include <mach/at91_pio.h>
31 33
@@ -585,15 +587,14 @@ static struct irq_chip gpio_irqchip = {
585 587
586static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) 588static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
587{ 589{
590 struct irq_chip *chip = irq_desc_get_chip(desc);
588 struct irq_data *idata = irq_desc_get_irq_data(desc); 591 struct irq_data *idata = irq_desc_get_irq_data(desc);
589 struct irq_chip *chip = irq_data_get_irq_chip(idata);
590 struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(idata); 592 struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(idata);
591 void __iomem *pio = at91_gpio->regbase; 593 void __iomem *pio = at91_gpio->regbase;
592 unsigned long isr; 594 unsigned long isr;
593 int n; 595 int n;
594 596
595 /* temporarily mask (level sensitive) parent IRQ */ 597 chained_irq_enter(chip, desc);
596 chip->irq_ack(idata);
597 for (;;) { 598 for (;;) {
598 /* Reading ISR acks pending (edge triggered) GPIO interrupts. 599 /* Reading ISR acks pending (edge triggered) GPIO interrupts.
599 * When there none are pending, we're finished unless we need 600 * When there none are pending, we're finished unless we need
@@ -614,7 +615,7 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
614 n = find_next_bit(&isr, BITS_PER_LONG, n + 1); 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 /* now it may re-trigger */ 619 /* now it may re-trigger */
619} 620}
620 621
diff --git a/arch/arm/mach-at91/include/mach/irqs.h b/arch/arm/mach-at91/include/mach/irqs.h
index ac8b7dfc85ef..2d510ee6ac03 100644
--- a/arch/arm/mach-at91/include/mach/irqs.h
+++ b/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 * IRQ interrupt symbols are the AT91xxx_ID_* symbols 31 * IRQ interrupt symbols are the AT91xxx_ID_* symbols
39 * for IRQs handled directly through the AIC, or else the AT91_PIN_* 32 * for IRQs handled directly through the AIC, or else the AT91_PIN_*
40 * symbols in gpio.h for ones handled indirectly as GPIOs. 33 * symbols in gpio.h for ones handled indirectly as GPIOs.
diff --git a/arch/arm/mach-at91/irq.c b/arch/arm/mach-at91/irq.c
index cfcfcbe36269..2d5d4c88a527 100644
--- a/arch/arm/mach-at91/irq.c
+++ b/arch/arm/mach-at91/irq.c
@@ -55,6 +55,15 @@ static void at91_aic_unmask_irq(struct irq_data *d)
55 at91_aic_write(AT91_AIC_IECR, 1 << d->hwirq); 55 at91_aic_write(AT91_AIC_IECR, 1 << d->hwirq);
56} 56}
57 57
58static 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
58unsigned int at91_extern_irq; 67unsigned int at91_extern_irq;
59 68
60#define is_extern_irq(hwirq) ((1 << (hwirq)) & at91_extern_irq) 69#define is_extern_irq(hwirq) ((1 << (hwirq)) & at91_extern_irq)
@@ -128,11 +137,11 @@ void at91_irq_resume(void)
128 137
129static struct irq_chip at91_aic_chip = { 138static struct irq_chip at91_aic_chip = {
130 .name = "AIC", 139 .name = "AIC",
131 .irq_ack = at91_aic_mask_irq,
132 .irq_mask = at91_aic_mask_irq, 140 .irq_mask = at91_aic_mask_irq,
133 .irq_unmask = at91_aic_unmask_irq, 141 .irq_unmask = at91_aic_unmask_irq,
134 .irq_set_type = at91_aic_set_type, 142 .irq_set_type = at91_aic_set_type,
135 .irq_set_wake = at91_aic_set_wake, 143 .irq_set_wake = at91_aic_set_wake,
144 .irq_eoi = at91_aic_eoi,
136}; 145};
137 146
138static void __init at91_aic_hw_init(unsigned int spu_vector) 147static void __init at91_aic_hw_init(unsigned int spu_vector)
@@ -171,7 +180,7 @@ static int at91_aic_irq_map(struct irq_domain *h, unsigned int virq,
171 /* Active Low interrupt, without priority */ 180 /* Active Low interrupt, without priority */
172 at91_aic_write(AT91_AIC_SMR(hw), AT91_AIC_SRCTYPE_LOW); 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 set_irq_flags(virq, IRQF_VALID | IRQF_PROBE); 184 set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
176 185
177 return 0; 186 return 0;
@@ -238,7 +247,7 @@ void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS])
238 /* Active Low interrupt, with the specified priority */ 247 /* Active Low interrupt, with the specified priority */
239 at91_aic_write(AT91_AIC_SMR(i), AT91_AIC_SRCTYPE_LOW | priority[i]); 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 set_irq_flags(i, IRQF_VALID | IRQF_PROBE); 251 set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
243 } 252 }
244 253