diff options
-rw-r--r-- | arch/mips/ath79/irq.c | 81 | ||||
-rw-r--r-- | arch/mips/include/asm/mach-ath79/ath79.h | 1 | ||||
-rw-r--r-- | drivers/irqchip/Makefile | 1 | ||||
-rw-r--r-- | drivers/irqchip/irq-ath79-cpu.c | 97 |
4 files changed, 105 insertions, 75 deletions
diff --git a/arch/mips/ath79/irq.c b/arch/mips/ath79/irq.c index 05b45140bc1f..2dfff1f19004 100644 --- a/arch/mips/ath79/irq.c +++ b/arch/mips/ath79/irq.c | |||
@@ -128,79 +128,10 @@ static void qca955x_irq_init(void) | |||
128 | irq_set_chained_handler(ATH79_CPU_IRQ(3), qca955x_ip3_irq_dispatch); | 128 | irq_set_chained_handler(ATH79_CPU_IRQ(3), qca955x_ip3_irq_dispatch); |
129 | } | 129 | } |
130 | 130 | ||
131 | /* | ||
132 | * The IP2/IP3 lines are tied to a PCI/WMAC/USB device. Drivers for | ||
133 | * these devices typically allocate coherent DMA memory, however the | ||
134 | * DMA controller may still have some unsynchronized data in the FIFO. | ||
135 | * Issue a flush in the handlers to ensure that the driver sees | ||
136 | * the update. | ||
137 | * | ||
138 | * This array map the interrupt lines to the DDR write buffer channels. | ||
139 | */ | ||
140 | |||
141 | static unsigned irq_wb_chan[8] = { | ||
142 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
143 | }; | ||
144 | |||
145 | asmlinkage void plat_irq_dispatch(void) | ||
146 | { | ||
147 | unsigned long pending; | ||
148 | int irq; | ||
149 | |||
150 | pending = read_c0_status() & read_c0_cause() & ST0_IM; | ||
151 | |||
152 | if (!pending) { | ||
153 | spurious_interrupt(); | ||
154 | return; | ||
155 | } | ||
156 | |||
157 | pending >>= CAUSEB_IP; | ||
158 | while (pending) { | ||
159 | irq = fls(pending) - 1; | ||
160 | if (irq < ARRAY_SIZE(irq_wb_chan) && irq_wb_chan[irq] != -1) | ||
161 | ath79_ddr_wb_flush(irq_wb_chan[irq]); | ||
162 | do_IRQ(MIPS_CPU_IRQ_BASE + irq); | ||
163 | pending &= ~BIT(irq); | ||
164 | } | ||
165 | } | ||
166 | |||
167 | static int __init ar79_cpu_intc_of_init( | ||
168 | struct device_node *node, struct device_node *parent) | ||
169 | { | ||
170 | int err, i, count; | ||
171 | |||
172 | /* Fill the irq_wb_chan table */ | ||
173 | count = of_count_phandle_with_args( | ||
174 | node, "qca,ddr-wb-channels", "#qca,ddr-wb-channel-cells"); | ||
175 | |||
176 | for (i = 0; i < count; i++) { | ||
177 | struct of_phandle_args args; | ||
178 | u32 irq = i; | ||
179 | |||
180 | of_property_read_u32_index( | ||
181 | node, "qca,ddr-wb-channel-interrupts", i, &irq); | ||
182 | if (irq >= ARRAY_SIZE(irq_wb_chan)) | ||
183 | continue; | ||
184 | |||
185 | err = of_parse_phandle_with_args( | ||
186 | node, "qca,ddr-wb-channels", | ||
187 | "#qca,ddr-wb-channel-cells", | ||
188 | i, &args); | ||
189 | if (err) | ||
190 | return err; | ||
191 | |||
192 | irq_wb_chan[irq] = args.args[0]; | ||
193 | pr_info("IRQ: Set flush channel of IRQ%d to %d\n", | ||
194 | irq, args.args[0]); | ||
195 | } | ||
196 | |||
197 | return mips_cpu_irq_of_init(node, parent); | ||
198 | } | ||
199 | IRQCHIP_DECLARE(ar79_cpu_intc, "qca,ar7100-cpu-intc", | ||
200 | ar79_cpu_intc_of_init); | ||
201 | |||
202 | void __init arch_init_irq(void) | 131 | void __init arch_init_irq(void) |
203 | { | 132 | { |
133 | unsigned irq_wb_chan2 = -1; | ||
134 | unsigned irq_wb_chan3 = -1; | ||
204 | bool misc_is_ar71xx; | 135 | bool misc_is_ar71xx; |
205 | 136 | ||
206 | if (mips_machtype == ATH79_MACH_GENERIC_OF) { | 137 | if (mips_machtype == ATH79_MACH_GENERIC_OF) { |
@@ -210,13 +141,13 @@ void __init arch_init_irq(void) | |||
210 | 141 | ||
211 | if (soc_is_ar71xx() || soc_is_ar724x() || | 142 | if (soc_is_ar71xx() || soc_is_ar724x() || |
212 | soc_is_ar913x() || soc_is_ar933x()) { | 143 | soc_is_ar913x() || soc_is_ar933x()) { |
213 | irq_wb_chan[2] = 3; | 144 | irq_wb_chan2 = 3; |
214 | irq_wb_chan[3] = 2; | 145 | irq_wb_chan3 = 2; |
215 | } else if (soc_is_ar934x()) { | 146 | } else if (soc_is_ar934x()) { |
216 | irq_wb_chan[3] = 2; | 147 | irq_wb_chan3 = 2; |
217 | } | 148 | } |
218 | 149 | ||
219 | mips_cpu_irq_init(); | 150 | ath79_cpu_irq_init(irq_wb_chan2, irq_wb_chan3); |
220 | 151 | ||
221 | if (soc_is_ar71xx() || soc_is_ar913x()) | 152 | if (soc_is_ar71xx() || soc_is_ar913x()) |
222 | misc_is_ar71xx = true; | 153 | misc_is_ar71xx = true; |
diff --git a/arch/mips/include/asm/mach-ath79/ath79.h b/arch/mips/include/asm/mach-ath79/ath79.h index 22a2f56ad5e9..441faa92c3cd 100644 --- a/arch/mips/include/asm/mach-ath79/ath79.h +++ b/arch/mips/include/asm/mach-ath79/ath79.h | |||
@@ -144,6 +144,7 @@ static inline u32 ath79_reset_rr(unsigned reg) | |||
144 | void ath79_device_reset_set(u32 mask); | 144 | void ath79_device_reset_set(u32 mask); |
145 | void ath79_device_reset_clear(u32 mask); | 145 | void ath79_device_reset_clear(u32 mask); |
146 | 146 | ||
147 | void ath79_cpu_irq_init(unsigned irq_wb_chan2, unsigned irq_wb_chan3); | ||
147 | void ath79_misc_irq_init(void __iomem *regs, int irq, | 148 | void ath79_misc_irq_init(void __iomem *regs, int irq, |
148 | int irq_base, bool is_ar71xx); | 149 | int irq_base, bool is_ar71xx); |
149 | 150 | ||
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index b873d4a081b4..aeb9200f0e16 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile | |||
@@ -1,5 +1,6 @@ | |||
1 | obj-$(CONFIG_IRQCHIP) += irqchip.o | 1 | obj-$(CONFIG_IRQCHIP) += irqchip.o |
2 | 2 | ||
3 | obj-$(CONFIG_ATH79) += irq-ath79-cpu.o | ||
3 | obj-$(CONFIG_ATH79) += irq-ath79-misc.o | 4 | obj-$(CONFIG_ATH79) += irq-ath79-misc.o |
4 | obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o | 5 | obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o |
5 | obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2836.o | 6 | obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2836.o |
diff --git a/drivers/irqchip/irq-ath79-cpu.c b/drivers/irqchip/irq-ath79-cpu.c new file mode 100644 index 000000000000..befe93c5a51a --- /dev/null +++ b/drivers/irqchip/irq-ath79-cpu.c | |||
@@ -0,0 +1,97 @@ | |||
1 | /* | ||
2 | * Atheros AR71xx/AR724x/AR913x specific interrupt handling | ||
3 | * | ||
4 | * Copyright (C) 2015 Alban Bedel <albeu@free.fr> | ||
5 | * Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com> | ||
6 | * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> | ||
7 | * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> | ||
8 | * | ||
9 | * Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License version 2 as published | ||
13 | * by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/irqchip.h> | ||
18 | #include <linux/of.h> | ||
19 | |||
20 | #include <asm/irq_cpu.h> | ||
21 | #include <asm/mach-ath79/ath79.h> | ||
22 | |||
23 | /* | ||
24 | * The IP2/IP3 lines are tied to a PCI/WMAC/USB device. Drivers for | ||
25 | * these devices typically allocate coherent DMA memory, however the | ||
26 | * DMA controller may still have some unsynchronized data in the FIFO. | ||
27 | * Issue a flush in the handlers to ensure that the driver sees | ||
28 | * the update. | ||
29 | * | ||
30 | * This array map the interrupt lines to the DDR write buffer channels. | ||
31 | */ | ||
32 | |||
33 | static unsigned irq_wb_chan[8] = { | ||
34 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
35 | }; | ||
36 | |||
37 | asmlinkage void plat_irq_dispatch(void) | ||
38 | { | ||
39 | unsigned long pending; | ||
40 | int irq; | ||
41 | |||
42 | pending = read_c0_status() & read_c0_cause() & ST0_IM; | ||
43 | |||
44 | if (!pending) { | ||
45 | spurious_interrupt(); | ||
46 | return; | ||
47 | } | ||
48 | |||
49 | pending >>= CAUSEB_IP; | ||
50 | while (pending) { | ||
51 | irq = fls(pending) - 1; | ||
52 | if (irq < ARRAY_SIZE(irq_wb_chan) && irq_wb_chan[irq] != -1) | ||
53 | ath79_ddr_wb_flush(irq_wb_chan[irq]); | ||
54 | do_IRQ(MIPS_CPU_IRQ_BASE + irq); | ||
55 | pending &= ~BIT(irq); | ||
56 | } | ||
57 | } | ||
58 | |||
59 | static int __init ar79_cpu_intc_of_init( | ||
60 | struct device_node *node, struct device_node *parent) | ||
61 | { | ||
62 | int err, i, count; | ||
63 | |||
64 | /* Fill the irq_wb_chan table */ | ||
65 | count = of_count_phandle_with_args( | ||
66 | node, "qca,ddr-wb-channels", "#qca,ddr-wb-channel-cells"); | ||
67 | |||
68 | for (i = 0; i < count; i++) { | ||
69 | struct of_phandle_args args; | ||
70 | u32 irq = i; | ||
71 | |||
72 | of_property_read_u32_index( | ||
73 | node, "qca,ddr-wb-channel-interrupts", i, &irq); | ||
74 | if (irq >= ARRAY_SIZE(irq_wb_chan)) | ||
75 | continue; | ||
76 | |||
77 | err = of_parse_phandle_with_args( | ||
78 | node, "qca,ddr-wb-channels", | ||
79 | "#qca,ddr-wb-channel-cells", | ||
80 | i, &args); | ||
81 | if (err) | ||
82 | return err; | ||
83 | |||
84 | irq_wb_chan[irq] = args.args[0]; | ||
85 | } | ||
86 | |||
87 | return mips_cpu_irq_of_init(node, parent); | ||
88 | } | ||
89 | IRQCHIP_DECLARE(ar79_cpu_intc, "qca,ar7100-cpu-intc", | ||
90 | ar79_cpu_intc_of_init); | ||
91 | |||
92 | void __init ath79_cpu_irq_init(unsigned irq_wb_chan2, unsigned irq_wb_chan3) | ||
93 | { | ||
94 | irq_wb_chan[2] = irq_wb_chan2; | ||
95 | irq_wb_chan[3] = irq_wb_chan3; | ||
96 | mips_cpu_irq_init(); | ||
97 | } | ||