ARM: at91: aic can use fast eoi handler type
authorLudovic Desroches <ludovic.desroches@atmel.com>
Fri, 25 May 2012 12:11:51 +0000 (14:11 +0200)
committerNicolas Ferre <nicolas.ferre@atmel.com>
Mon, 2 Jul 2012 12:26:57 +0000 (14:26 +0200)
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>
arch/arm/kernel/irq.c
arch/arm/mach-at91/gpio.c
arch/arm/mach-at91/include/mach/irqs.h
arch/arm/mach-at91/irq.c

index 8349d4e..16cedb4 100644 (file)
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 
-/*
- * No architecture-specific irq_finish function defined in arm/arch/irqs.h.
- */
-#ifndef irq_finish
-#define irq_finish(irq) do { } while (0)
-#endif
-
 unsigned long irq_err_count;
 
 int arch_show_interrupts(struct seq_file *p, int prec)
@@ -85,9 +78,6 @@ void handle_IRQ(unsigned int irq, struct pt_regs *regs)
                generic_handle_irq(irq);
        }
 
-       /* AT91 specific workaround */
-       irq_finish(irq);
-
        irq_exit();
        set_irq_regs(old_regs);
 }
index 325837a..be42cf0 100644 (file)
@@ -26,6 +26,8 @@
 #include <linux/of_irq.h>
 #include <linux/of_gpio.h>
 
+#include <asm/mach/irq.h>
+
 #include <mach/hardware.h>
 #include <mach/at91_pio.h>
 
@@ -585,15 +587,14 @@ static struct irq_chip gpio_irqchip = {
 
 static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
 {
+       struct irq_chip *chip = irq_desc_get_chip(desc);
        struct irq_data *idata = irq_desc_get_irq_data(desc);
-       struct irq_chip *chip = irq_data_get_irq_chip(idata);
        struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(idata);
        void __iomem    *pio = at91_gpio->regbase;
        unsigned long   isr;
        int             n;
 
-       /* temporarily mask (level sensitive) parent IRQ */
-       chip->irq_ack(idata);
+       chained_irq_enter(chip, desc);
        for (;;) {
                /* Reading ISR acks pending (edge triggered) GPIO interrupts.
                 * 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)
                        n = find_next_bit(&isr, BITS_PER_LONG, n + 1);
                }
        }
-       chip->irq_unmask(idata);
+       chained_irq_exit(chip, desc);
        /* now it may re-trigger */
 }
 
index ac8b7df..2d510ee 100644 (file)
 
 
 /*
- * Acknowledge interrupt with AIC after interrupt has been handled.
- *   (by kernel/irq.c)
- */
-#define irq_finish(irq) do { at91_aic_write(AT91_AIC_EOICR, 0); } while (0)
-
-
-/*
  * IRQ interrupt symbols are the AT91xxx_ID_* symbols
  * for IRQs handled directly through the AIC, or else the AT91_PIN_*
  * symbols in gpio.h for ones handled indirectly as GPIOs.
index cfcfcbe..2d5d4c8 100644 (file)
@@ -55,6 +55,15 @@ static void at91_aic_unmask_irq(struct irq_data *d)
        at91_aic_write(AT91_AIC_IECR, 1 << d->hwirq);
 }
 
+static void at91_aic_eoi(struct irq_data *d)
+{
+       /*
+        * Mark end-of-interrupt on AIC, the controller doesn't care about
+        * the value written. Moreover it's a write-only register.
+        */
+       at91_aic_write(AT91_AIC_EOICR, 0);
+}
+
 unsigned int at91_extern_irq;
 
 #define is_extern_irq(hwirq) ((1 << (hwirq)) & at91_extern_irq)
@@ -128,11 +137,11 @@ void at91_irq_resume(void)
 
 static struct irq_chip at91_aic_chip = {
        .name           = "AIC",
-       .irq_ack        = at91_aic_mask_irq,
        .irq_mask       = at91_aic_mask_irq,
        .irq_unmask     = at91_aic_unmask_irq,
        .irq_set_type   = at91_aic_set_type,
        .irq_set_wake   = at91_aic_set_wake,
+       .irq_eoi        = at91_aic_eoi,
 };
 
 static 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,
        /* Active Low interrupt, without priority */
        at91_aic_write(AT91_AIC_SMR(hw), AT91_AIC_SRCTYPE_LOW);
 
-       irq_set_chip_and_handler(virq, &at91_aic_chip, handle_level_irq);
+       irq_set_chip_and_handler(virq, &at91_aic_chip, handle_fasteoi_irq);
        set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
 
        return 0;
@@ -238,7 +247,7 @@ void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS])
                /* Active Low interrupt, with the specified priority */
                at91_aic_write(AT91_AIC_SMR(i), AT91_AIC_SRCTYPE_LOW | priority[i]);
 
-               irq_set_chip_and_handler(i, &at91_aic_chip, handle_level_irq);
+               irq_set_chip_and_handler(i, &at91_aic_chip, handle_fasteoi_irq);
                set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
        }