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>
This commit is contained in:
parent
f25b00be60
commit
42a859daaf
|
@ -40,13 +40,6 @@
|
||||||
#include <asm/mach/irq.h>
|
#include <asm/mach/irq.h>
|
||||||
#include <asm/mach/time.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;
|
unsigned long irq_err_count;
|
||||||
|
|
||||||
int arch_show_interrupts(struct seq_file *p, int prec)
|
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);
|
generic_handle_irq(irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* AT91 specific workaround */
|
|
||||||
irq_finish(irq);
|
|
||||||
|
|
||||||
irq_exit();
|
irq_exit();
|
||||||
set_irq_regs(old_regs);
|
set_irq_regs(old_regs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
#include <linux/of_irq.h>
|
#include <linux/of_irq.h>
|
||||||
#include <linux/of_gpio.h>
|
#include <linux/of_gpio.h>
|
||||||
|
|
||||||
|
#include <asm/mach/irq.h>
|
||||||
|
|
||||||
#include <mach/hardware.h>
|
#include <mach/hardware.h>
|
||||||
#include <mach/at91_pio.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)
|
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_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);
|
struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(idata);
|
||||||
void __iomem *pio = at91_gpio->regbase;
|
void __iomem *pio = at91_gpio->regbase;
|
||||||
unsigned long isr;
|
unsigned long isr;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
/* temporarily mask (level sensitive) parent IRQ */
|
chained_irq_enter(chip, desc);
|
||||||
chip->irq_ack(idata);
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/* Reading ISR acks pending (edge triggered) GPIO interrupts.
|
/* Reading ISR acks pending (edge triggered) GPIO interrupts.
|
||||||
* When there none are pending, we're finished unless we need
|
* 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);
|
n = find_next_bit(&isr, BITS_PER_LONG, n + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
chip->irq_unmask(idata);
|
chained_irq_exit(chip, desc);
|
||||||
/* now it may re-trigger */
|
/* now it may re-trigger */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,13 +27,6 @@
|
||||||
#define NR_AIC_IRQS 32
|
#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
|
* IRQ interrupt symbols are the AT91xxx_ID_* symbols
|
||||||
* for IRQs handled directly through the AIC, or else the AT91_PIN_*
|
* for IRQs handled directly through the AIC, or else the AT91_PIN_*
|
||||||
|
|
|
@ -55,6 +55,15 @@ static void at91_aic_unmask_irq(struct irq_data *d)
|
||||||
at91_aic_write(AT91_AIC_IECR, 1 << d->hwirq);
|
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;
|
unsigned int at91_extern_irq;
|
||||||
|
|
||||||
#define is_extern_irq(hwirq) ((1 << (hwirq)) & 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 = {
|
static struct irq_chip at91_aic_chip = {
|
||||||
.name = "AIC",
|
.name = "AIC",
|
||||||
.irq_ack = at91_aic_mask_irq,
|
|
||||||
.irq_mask = at91_aic_mask_irq,
|
.irq_mask = at91_aic_mask_irq,
|
||||||
.irq_unmask = at91_aic_unmask_irq,
|
.irq_unmask = at91_aic_unmask_irq,
|
||||||
.irq_set_type = at91_aic_set_type,
|
.irq_set_type = at91_aic_set_type,
|
||||||
.irq_set_wake = at91_aic_set_wake,
|
.irq_set_wake = at91_aic_set_wake,
|
||||||
|
.irq_eoi = at91_aic_eoi,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void __init at91_aic_hw_init(unsigned int spu_vector)
|
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 */
|
/* Active Low interrupt, without priority */
|
||||||
at91_aic_write(AT91_AIC_SMR(hw), AT91_AIC_SRCTYPE_LOW);
|
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);
|
set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -238,7 +247,7 @@ void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS])
|
||||||
/* Active Low interrupt, with the specified priority */
|
/* Active Low interrupt, with the specified priority */
|
||||||
at91_aic_write(AT91_AIC_SMR(i), AT91_AIC_SRCTYPE_LOW | priority[i]);
|
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);
|
set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue