Skip to content

Commit

Permalink
ARM: at91: aic can use fast eoi handler type
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Ludovic Desroches authored and Nicolas Ferre committed Jul 2, 2012
1 parent f25b00b commit 42a859d
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 24 deletions.
10 changes: 0 additions & 10 deletions arch/arm/kernel/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,6 @@
#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)
Expand Down Expand Up @@ -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);
}
Expand Down
9 changes: 5 additions & 4 deletions arch/arm/mach-at91/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down Expand Up @@ -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
Expand All @@ -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 */
}

Expand Down
7 changes: 0 additions & 7 deletions arch/arm/mach-at91/include/mach/irqs.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,6 @@
#define NR_AIC_IRQS 32


/*
* 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_*
Expand Down
15 changes: 12 additions & 3 deletions arch/arm/mach-at91/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}

Expand Down

0 comments on commit 42a859d

Please sign in to comment.