aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/ath79/irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/ath79/irq.c')
-rw-r--r--arch/mips/ath79/irq.c147
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
26static unsigned int ath79_ip2_flush_reg; 27static void (*ath79_ip2_handler)(void);
27static unsigned int ath79_ip3_flush_reg; 28static void (*ath79_ip3_handler)(void);
28 29
29static void ath79_misc_irq_handler(unsigned int irq, struct irq_desc *desc) 30static 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
147static 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
168static 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
146asmlinkage void plat_irq_dispatch(void) 180asmlinkage 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 */
215static 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
221static 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
227static 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
233static 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
239static void ar934x_ip2_handler(void)
240{
241 do_IRQ(ATH79_CPU_IRQ_IP2);
242}
243
244static 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
250static 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
256static 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
262static 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
268static 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
178void __init arch_init_irq(void) 274void __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}