diff options
Diffstat (limited to 'arch/mips/ath79/irq.c')
-rw-r--r-- | arch/mips/ath79/irq.c | 147 |
1 files changed, 125 insertions, 22 deletions
diff --git a/arch/mips/ath79/irq.c b/arch/mips/ath79/irq.c index 1b073de44680..90d09fc15398 100644 --- a/arch/mips/ath79/irq.c +++ b/arch/mips/ath79/irq.c | |||
@@ -1,10 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | * Atheros AR71xx/AR724x/AR913x specific interrupt handling | 2 | * Atheros AR71xx/AR724x/AR913x specific interrupt handling |
3 | * | 3 | * |
4 | * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> | 4 | * Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com> |
5 | * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> | ||
5 | * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> | 6 | * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> |
6 | * | 7 | * |
7 | * Parts of this file are based on Atheros' 2.6.15 BSP | 8 | * Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP |
8 | * | 9 | * |
9 | * This program is free software; you can redistribute it and/or modify it | 10 | * This program is free software; you can redistribute it and/or modify it |
10 | * under the terms of the GNU General Public License version 2 as published | 11 | * under the terms of the GNU General Public License version 2 as published |
@@ -23,8 +24,8 @@ | |||
23 | #include <asm/mach-ath79/ar71xx_regs.h> | 24 | #include <asm/mach-ath79/ar71xx_regs.h> |
24 | #include "common.h" | 25 | #include "common.h" |
25 | 26 | ||
26 | static unsigned int ath79_ip2_flush_reg; | 27 | static void (*ath79_ip2_handler)(void); |
27 | static unsigned int ath79_ip3_flush_reg; | 28 | static void (*ath79_ip3_handler)(void); |
28 | 29 | ||
29 | static void ath79_misc_irq_handler(unsigned int irq, struct irq_desc *desc) | 30 | static void ath79_misc_irq_handler(unsigned int irq, struct irq_desc *desc) |
30 | { | 31 | { |
@@ -129,7 +130,7 @@ static void __init ath79_misc_irq_init(void) | |||
129 | 130 | ||
130 | if (soc_is_ar71xx() || soc_is_ar913x()) | 131 | if (soc_is_ar71xx() || soc_is_ar913x()) |
131 | ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask; | 132 | ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask; |
132 | else if (soc_is_ar724x() || soc_is_ar933x()) | 133 | else if (soc_is_ar724x() || soc_is_ar933x() || soc_is_ar934x()) |
133 | ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack; | 134 | ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack; |
134 | else | 135 | else |
135 | BUG(); | 136 | BUG(); |
@@ -143,6 +144,39 @@ static void __init ath79_misc_irq_init(void) | |||
143 | irq_set_chained_handler(ATH79_CPU_IRQ_MISC, ath79_misc_irq_handler); | 144 | irq_set_chained_handler(ATH79_CPU_IRQ_MISC, ath79_misc_irq_handler); |
144 | } | 145 | } |
145 | 146 | ||
147 | static void ar934x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc) | ||
148 | { | ||
149 | u32 status; | ||
150 | |||
151 | disable_irq_nosync(irq); | ||
152 | |||
153 | status = ath79_reset_rr(AR934X_RESET_REG_PCIE_WMAC_INT_STATUS); | ||
154 | |||
155 | if (status & AR934X_PCIE_WMAC_INT_PCIE_ALL) { | ||
156 | ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_PCIE); | ||
157 | generic_handle_irq(ATH79_IP2_IRQ(0)); | ||
158 | } else if (status & AR934X_PCIE_WMAC_INT_WMAC_ALL) { | ||
159 | ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_WMAC); | ||
160 | generic_handle_irq(ATH79_IP2_IRQ(1)); | ||
161 | } else { | ||
162 | spurious_interrupt(); | ||
163 | } | ||
164 | |||
165 | enable_irq(irq); | ||
166 | } | ||
167 | |||
168 | static void ar934x_ip2_irq_init(void) | ||
169 | { | ||
170 | int i; | ||
171 | |||
172 | for (i = ATH79_IP2_IRQ_BASE; | ||
173 | i < ATH79_IP2_IRQ_BASE + ATH79_IP2_IRQ_COUNT; i++) | ||
174 | irq_set_chip_and_handler(i, &dummy_irq_chip, | ||
175 | handle_level_irq); | ||
176 | |||
177 | irq_set_chained_handler(ATH79_CPU_IRQ_IP2, ar934x_ip2_irq_dispatch); | ||
178 | } | ||
179 | |||
146 | asmlinkage void plat_irq_dispatch(void) | 180 | asmlinkage void plat_irq_dispatch(void) |
147 | { | 181 | { |
148 | unsigned long pending; | 182 | unsigned long pending; |
@@ -152,10 +186,8 @@ asmlinkage void plat_irq_dispatch(void) | |||
152 | if (pending & STATUSF_IP7) | 186 | if (pending & STATUSF_IP7) |
153 | do_IRQ(ATH79_CPU_IRQ_TIMER); | 187 | do_IRQ(ATH79_CPU_IRQ_TIMER); |
154 | 188 | ||
155 | else if (pending & STATUSF_IP2) { | 189 | else if (pending & STATUSF_IP2) |
156 | ath79_ddr_wb_flush(ath79_ip2_flush_reg); | 190 | ath79_ip2_handler(); |
157 | do_IRQ(ATH79_CPU_IRQ_IP2); | ||
158 | } | ||
159 | 191 | ||
160 | else if (pending & STATUSF_IP4) | 192 | else if (pending & STATUSF_IP4) |
161 | do_IRQ(ATH79_CPU_IRQ_GE0); | 193 | do_IRQ(ATH79_CPU_IRQ_GE0); |
@@ -163,10 +195,8 @@ asmlinkage void plat_irq_dispatch(void) | |||
163 | else if (pending & STATUSF_IP5) | 195 | else if (pending & STATUSF_IP5) |
164 | do_IRQ(ATH79_CPU_IRQ_GE1); | 196 | do_IRQ(ATH79_CPU_IRQ_GE1); |
165 | 197 | ||
166 | else if (pending & STATUSF_IP3) { | 198 | else if (pending & STATUSF_IP3) |
167 | ath79_ddr_wb_flush(ath79_ip3_flush_reg); | 199 | ath79_ip3_handler(); |
168 | do_IRQ(ATH79_CPU_IRQ_USB); | ||
169 | } | ||
170 | 200 | ||
171 | else if (pending & STATUSF_IP6) | 201 | else if (pending & STATUSF_IP6) |
172 | do_IRQ(ATH79_CPU_IRQ_MISC); | 202 | do_IRQ(ATH79_CPU_IRQ_MISC); |
@@ -175,24 +205,97 @@ asmlinkage void plat_irq_dispatch(void) | |||
175 | spurious_interrupt(); | 205 | spurious_interrupt(); |
176 | } | 206 | } |
177 | 207 | ||
208 | /* | ||
209 | * The IP2/IP3 lines are tied to a PCI/WMAC/USB device. Drivers for | ||
210 | * these devices typically allocate coherent DMA memory, however the | ||
211 | * DMA controller may still have some unsynchronized data in the FIFO. | ||
212 | * Issue a flush in the handlers to ensure that the driver sees | ||
213 | * the update. | ||
214 | */ | ||
215 | static void ar71xx_ip2_handler(void) | ||
216 | { | ||
217 | ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_PCI); | ||
218 | do_IRQ(ATH79_CPU_IRQ_IP2); | ||
219 | } | ||
220 | |||
221 | static void ar724x_ip2_handler(void) | ||
222 | { | ||
223 | ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_PCIE); | ||
224 | do_IRQ(ATH79_CPU_IRQ_IP2); | ||
225 | } | ||
226 | |||
227 | static void ar913x_ip2_handler(void) | ||
228 | { | ||
229 | ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_WMAC); | ||
230 | do_IRQ(ATH79_CPU_IRQ_IP2); | ||
231 | } | ||
232 | |||
233 | static void ar933x_ip2_handler(void) | ||
234 | { | ||
235 | ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_WMAC); | ||
236 | do_IRQ(ATH79_CPU_IRQ_IP2); | ||
237 | } | ||
238 | |||
239 | static void ar934x_ip2_handler(void) | ||
240 | { | ||
241 | do_IRQ(ATH79_CPU_IRQ_IP2); | ||
242 | } | ||
243 | |||
244 | static void ar71xx_ip3_handler(void) | ||
245 | { | ||
246 | ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_USB); | ||
247 | do_IRQ(ATH79_CPU_IRQ_USB); | ||
248 | } | ||
249 | |||
250 | static void ar724x_ip3_handler(void) | ||
251 | { | ||
252 | ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_USB); | ||
253 | do_IRQ(ATH79_CPU_IRQ_USB); | ||
254 | } | ||
255 | |||
256 | static void ar913x_ip3_handler(void) | ||
257 | { | ||
258 | ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_USB); | ||
259 | do_IRQ(ATH79_CPU_IRQ_USB); | ||
260 | } | ||
261 | |||
262 | static void ar933x_ip3_handler(void) | ||
263 | { | ||
264 | ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_USB); | ||
265 | do_IRQ(ATH79_CPU_IRQ_USB); | ||
266 | } | ||
267 | |||
268 | static void ar934x_ip3_handler(void) | ||
269 | { | ||
270 | ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_USB); | ||
271 | do_IRQ(ATH79_CPU_IRQ_USB); | ||
272 | } | ||
273 | |||
178 | void __init arch_init_irq(void) | 274 | void __init arch_init_irq(void) |
179 | { | 275 | { |
180 | if (soc_is_ar71xx()) { | 276 | if (soc_is_ar71xx()) { |
181 | ath79_ip2_flush_reg = AR71XX_DDR_REG_FLUSH_PCI; | 277 | ath79_ip2_handler = ar71xx_ip2_handler; |
182 | ath79_ip3_flush_reg = AR71XX_DDR_REG_FLUSH_USB; | 278 | ath79_ip3_handler = ar71xx_ip3_handler; |
183 | } else if (soc_is_ar724x()) { | 279 | } else if (soc_is_ar724x()) { |
184 | ath79_ip2_flush_reg = AR724X_DDR_REG_FLUSH_PCIE; | 280 | ath79_ip2_handler = ar724x_ip2_handler; |
185 | ath79_ip3_flush_reg = AR724X_DDR_REG_FLUSH_USB; | 281 | ath79_ip3_handler = ar724x_ip3_handler; |
186 | } else if (soc_is_ar913x()) { | 282 | } else if (soc_is_ar913x()) { |
187 | ath79_ip2_flush_reg = AR913X_DDR_REG_FLUSH_WMAC; | 283 | ath79_ip2_handler = ar913x_ip2_handler; |
188 | ath79_ip3_flush_reg = AR913X_DDR_REG_FLUSH_USB; | 284 | ath79_ip3_handler = ar913x_ip3_handler; |
189 | } else if (soc_is_ar933x()) { | 285 | } else if (soc_is_ar933x()) { |
190 | ath79_ip2_flush_reg = AR933X_DDR_REG_FLUSH_WMAC; | 286 | ath79_ip2_handler = ar933x_ip2_handler; |
191 | ath79_ip3_flush_reg = AR933X_DDR_REG_FLUSH_USB; | 287 | ath79_ip3_handler = ar933x_ip3_handler; |
192 | } else | 288 | } else if (soc_is_ar934x()) { |
289 | ath79_ip2_handler = ar934x_ip2_handler; | ||
290 | ath79_ip3_handler = ar934x_ip3_handler; | ||
291 | } else { | ||
193 | BUG(); | 292 | BUG(); |
293 | } | ||
194 | 294 | ||
195 | cp0_perfcount_irq = ATH79_MISC_IRQ_PERFC; | 295 | cp0_perfcount_irq = ATH79_MISC_IRQ_PERFC; |
196 | mips_cpu_irq_init(); | 296 | mips_cpu_irq_init(); |
197 | ath79_misc_irq_init(); | 297 | ath79_misc_irq_init(); |
298 | |||
299 | if (soc_is_ar934x()) | ||
300 | ar934x_ip2_irq_init(); | ||
198 | } | 301 | } |