diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-01-19 15:32:15 +0000 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-02-19 11:11:33 +0000 |
commit | c41b16f8c9d9dc74ed5669d4a3e3d42374c9e609 (patch) | |
tree | 0e7ee2bef09e6c752cda71087795bd40f0f35177 /arch/arm/plat-versatile | |
parent | dc37c31bbfaf87118d6c827be0a38a512a40b741 (diff) |
ARM: integrator/versatile: consolidate FPGA IRQ handling code
Consolidate the FPGA IRQ handling code. Integrator/AP and Versatile
have one FPGA-based IRQ handler each. Integrator/CP has three.
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/plat-versatile')
-rw-r--r-- | arch/arm/plat-versatile/Kconfig | 3 | ||||
-rw-r--r-- | arch/arm/plat-versatile/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/plat-versatile/fpga-irq.c | 72 | ||||
-rw-r--r-- | arch/arm/plat-versatile/include/plat/fpga-irq.h | 12 |
4 files changed, 88 insertions, 0 deletions
diff --git a/arch/arm/plat-versatile/Kconfig b/arch/arm/plat-versatile/Kconfig index c5e2cd014c6..0b275008d3e 100644 --- a/arch/arm/plat-versatile/Kconfig +++ b/arch/arm/plat-versatile/Kconfig @@ -3,6 +3,9 @@ if PLAT_VERSATILE config PLAT_VERSATILE_CLCD bool +config PLAT_VERSATILE_FPGA_IRQ + bool + config PLAT_VERSATILE_LEDS def_bool y if LEDS_CLASS depends on ARCH_REALVIEW || ARCH_VERSATILE diff --git a/arch/arm/plat-versatile/Makefile b/arch/arm/plat-versatile/Makefile index de6f42f003b..41f57f4b903 100644 --- a/arch/arm/plat-versatile/Makefile +++ b/arch/arm/plat-versatile/Makefile @@ -1,5 +1,6 @@ obj-y := clock.o obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o +obj-$(CONFIG_PLAT_VERSATILE_FPGA_IRQ) += fpga-irq.o obj-$(CONFIG_PLAT_VERSATILE_LEDS) += leds.o obj-$(CONFIG_PLAT_VERSATILE_SCHED_CLOCK) += sched-clock.o diff --git a/arch/arm/plat-versatile/fpga-irq.c b/arch/arm/plat-versatile/fpga-irq.c new file mode 100644 index 00000000000..31d945d37e4 --- /dev/null +++ b/arch/arm/plat-versatile/fpga-irq.c @@ -0,0 +1,72 @@ +/* + * Support for Versatile FPGA-based IRQ controllers + */ +#include <linux/irq.h> +#include <linux/io.h> + +#include <asm/mach/irq.h> +#include <plat/fpga-irq.h> + +#define IRQ_STATUS 0x00 +#define IRQ_RAW_STATUS 0x04 +#define IRQ_ENABLE_SET 0x08 +#define IRQ_ENABLE_CLEAR 0x0c + +static void fpga_irq_mask(struct irq_data *d) +{ + struct fpga_irq_data *f = irq_data_get_irq_chip_data(d); + u32 mask = 1 << (d->irq - f->irq_start); + + writel(mask, f->base + IRQ_ENABLE_CLEAR); +} + +static void fpga_irq_unmask(struct irq_data *d) +{ + struct fpga_irq_data *f = irq_data_get_irq_chip_data(d); + u32 mask = 1 << (d->irq - f->irq_start); + + writel(mask, f->base + IRQ_ENABLE_SET); +} + +static void fpga_irq_handle(unsigned int irq, struct irq_desc *desc) +{ + struct fpga_irq_data *f = get_irq_desc_data(desc); + u32 status = readl(f->base + IRQ_STATUS); + + if (status == 0) { + do_bad_IRQ(irq, desc); + return; + } + + do { + irq = ffs(status) - 1; + status &= ~(1 << irq); + + generic_handle_irq(irq + f->irq_start); + } while (status); +} + +void __init fpga_irq_init(int parent_irq, u32 valid, struct fpga_irq_data *f) +{ + unsigned int i; + + f->chip.irq_ack = fpga_irq_mask; + f->chip.irq_mask = fpga_irq_mask; + f->chip.irq_unmask = fpga_irq_unmask; + + if (parent_irq != -1) { + set_irq_data(parent_irq, f); + set_irq_chained_handler(parent_irq, fpga_irq_handle); + } + + for (i = 0; i < 32; i++) { + if (valid & (1 << i)) { + unsigned int irq = f->irq_start + i; + + set_irq_chip_data(irq, f); + set_irq_chip(irq, &f->chip); + set_irq_handler(irq, handle_level_irq); + set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + } + } +} diff --git a/arch/arm/plat-versatile/include/plat/fpga-irq.h b/arch/arm/plat-versatile/include/plat/fpga-irq.h new file mode 100644 index 00000000000..627fafd1e59 --- /dev/null +++ b/arch/arm/plat-versatile/include/plat/fpga-irq.h @@ -0,0 +1,12 @@ +#ifndef PLAT_FPGA_IRQ_H +#define PLAT_FPGA_IRQ_H + +struct fpga_irq_data { + void __iomem *base; + unsigned int irq_start; + struct irq_chip chip; +}; + +void fpga_irq_init(int, u32, struct fpga_irq_data *); + +#endif |