diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-01-19 10:32:15 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-02-19 06:11:33 -0500 |
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 c5e2cd014c61..0b275008d3e0 100644 --- a/arch/arm/plat-versatile/Kconfig +++ b/arch/arm/plat-versatile/Kconfig | |||
@@ -3,6 +3,9 @@ if PLAT_VERSATILE | |||
3 | config PLAT_VERSATILE_CLCD | 3 | config PLAT_VERSATILE_CLCD |
4 | bool | 4 | bool |
5 | 5 | ||
6 | config PLAT_VERSATILE_FPGA_IRQ | ||
7 | bool | ||
8 | |||
6 | config PLAT_VERSATILE_LEDS | 9 | config PLAT_VERSATILE_LEDS |
7 | def_bool y if LEDS_CLASS | 10 | def_bool y if LEDS_CLASS |
8 | depends on ARCH_REALVIEW || ARCH_VERSATILE | 11 | depends on ARCH_REALVIEW || ARCH_VERSATILE |
diff --git a/arch/arm/plat-versatile/Makefile b/arch/arm/plat-versatile/Makefile index de6f42f003b3..41f57f4b9038 100644 --- a/arch/arm/plat-versatile/Makefile +++ b/arch/arm/plat-versatile/Makefile | |||
@@ -1,5 +1,6 @@ | |||
1 | obj-y := clock.o | 1 | obj-y := clock.o |
2 | obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o | 2 | obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o |
3 | obj-$(CONFIG_PLAT_VERSATILE_FPGA_IRQ) += fpga-irq.o | ||
3 | obj-$(CONFIG_PLAT_VERSATILE_LEDS) += leds.o | 4 | obj-$(CONFIG_PLAT_VERSATILE_LEDS) += leds.o |
4 | obj-$(CONFIG_PLAT_VERSATILE_SCHED_CLOCK) += sched-clock.o | 5 | obj-$(CONFIG_PLAT_VERSATILE_SCHED_CLOCK) += sched-clock.o |
5 | 6 | ||
diff --git a/arch/arm/plat-versatile/fpga-irq.c b/arch/arm/plat-versatile/fpga-irq.c new file mode 100644 index 000000000000..31d945d37e4f --- /dev/null +++ b/arch/arm/plat-versatile/fpga-irq.c | |||
@@ -0,0 +1,72 @@ | |||
1 | /* | ||
2 | * Support for Versatile FPGA-based IRQ controllers | ||
3 | */ | ||
4 | #include <linux/irq.h> | ||
5 | #include <linux/io.h> | ||
6 | |||
7 | #include <asm/mach/irq.h> | ||
8 | #include <plat/fpga-irq.h> | ||
9 | |||
10 | #define IRQ_STATUS 0x00 | ||
11 | #define IRQ_RAW_STATUS 0x04 | ||
12 | #define IRQ_ENABLE_SET 0x08 | ||
13 | #define IRQ_ENABLE_CLEAR 0x0c | ||
14 | |||
15 | static void fpga_irq_mask(struct irq_data *d) | ||
16 | { | ||
17 | struct fpga_irq_data *f = irq_data_get_irq_chip_data(d); | ||
18 | u32 mask = 1 << (d->irq - f->irq_start); | ||
19 | |||
20 | writel(mask, f->base + IRQ_ENABLE_CLEAR); | ||
21 | } | ||
22 | |||
23 | static void fpga_irq_unmask(struct irq_data *d) | ||
24 | { | ||
25 | struct fpga_irq_data *f = irq_data_get_irq_chip_data(d); | ||
26 | u32 mask = 1 << (d->irq - f->irq_start); | ||
27 | |||
28 | writel(mask, f->base + IRQ_ENABLE_SET); | ||
29 | } | ||
30 | |||
31 | static void fpga_irq_handle(unsigned int irq, struct irq_desc *desc) | ||
32 | { | ||
33 | struct fpga_irq_data *f = get_irq_desc_data(desc); | ||
34 | u32 status = readl(f->base + IRQ_STATUS); | ||
35 | |||
36 | if (status == 0) { | ||
37 | do_bad_IRQ(irq, desc); | ||
38 | return; | ||
39 | } | ||
40 | |||
41 | do { | ||
42 | irq = ffs(status) - 1; | ||
43 | status &= ~(1 << irq); | ||
44 | |||
45 | generic_handle_irq(irq + f->irq_start); | ||
46 | } while (status); | ||
47 | } | ||
48 | |||
49 | void __init fpga_irq_init(int parent_irq, u32 valid, struct fpga_irq_data *f) | ||
50 | { | ||
51 | unsigned int i; | ||
52 | |||
53 | f->chip.irq_ack = fpga_irq_mask; | ||
54 | f->chip.irq_mask = fpga_irq_mask; | ||
55 | f->chip.irq_unmask = fpga_irq_unmask; | ||
56 | |||
57 | if (parent_irq != -1) { | ||
58 | set_irq_data(parent_irq, f); | ||
59 | set_irq_chained_handler(parent_irq, fpga_irq_handle); | ||
60 | } | ||
61 | |||
62 | for (i = 0; i < 32; i++) { | ||
63 | if (valid & (1 << i)) { | ||
64 | unsigned int irq = f->irq_start + i; | ||
65 | |||
66 | set_irq_chip_data(irq, f); | ||
67 | set_irq_chip(irq, &f->chip); | ||
68 | set_irq_handler(irq, handle_level_irq); | ||
69 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | ||
70 | } | ||
71 | } | ||
72 | } | ||
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 000000000000..627fafd1e595 --- /dev/null +++ b/arch/arm/plat-versatile/include/plat/fpga-irq.h | |||
@@ -0,0 +1,12 @@ | |||
1 | #ifndef PLAT_FPGA_IRQ_H | ||
2 | #define PLAT_FPGA_IRQ_H | ||
3 | |||
4 | struct fpga_irq_data { | ||
5 | void __iomem *base; | ||
6 | unsigned int irq_start; | ||
7 | struct irq_chip chip; | ||
8 | }; | ||
9 | |||
10 | void fpga_irq_init(int, u32, struct fpga_irq_data *); | ||
11 | |||
12 | #endif | ||