aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGabor Juhos <juhosg@openwrt.org>2013-02-15 13:53:47 -0500
committerJohn Crispin <blogic@openwrt.org>2013-02-19 03:36:25 -0500
commit53330332f176eaa9567481c69bbad8b2176b4eb5 (patch)
treed5278cdce05a2a3bbfacb0e774c45f67ca3429ff
parent41583c05c15cd3adb848f9ee8316bf8084c961cb (diff)
MIPS: ath79: add IRQ handling code for the QCA955X SoCs
The IRQ routing in the QCA955x SoCs is slightly different from the routing implemented in the already supported SoCs. Cc: Rodriguez, Luis <rodrigue@qca.qualcomm.com> Cc: Giori, Kathy <kgiori@qca.qualcomm.com> Cc: QCA Linux Team <qca-linux-team@qca.qualcomm.com> Signed-off-by: Gabor Juhos <juhosg@openwrt.org> Patchwork: http://patchwork.linux-mips.org/patch/4955/ Signed-off-by: John Crispin <blogic@openwrt.org>
-rw-r--r--arch/mips/ath79/irq.c110
-rw-r--r--arch/mips/include/asm/mach-ath79/ar71xx_regs.h32
-rw-r--r--arch/mips/include/asm/mach-ath79/irq.h6
3 files changed, 140 insertions, 8 deletions
diff --git a/arch/mips/ath79/irq.c b/arch/mips/ath79/irq.c
index df88d49bcb05..9c0e1761773f 100644
--- a/arch/mips/ath79/irq.c
+++ b/arch/mips/ath79/irq.c
@@ -103,7 +103,10 @@ static void __init ath79_misc_irq_init(void)
103 103
104 if (soc_is_ar71xx() || soc_is_ar913x()) 104 if (soc_is_ar71xx() || soc_is_ar913x())
105 ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask; 105 ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask;
106 else if (soc_is_ar724x() || soc_is_ar933x() || soc_is_ar934x()) 106 else if (soc_is_ar724x() ||
107 soc_is_ar933x() ||
108 soc_is_ar934x() ||
109 soc_is_qca955x())
107 ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack; 110 ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack;
108 else 111 else
109 BUG(); 112 BUG();
@@ -150,6 +153,88 @@ static void ar934x_ip2_irq_init(void)
150 irq_set_chained_handler(ATH79_CPU_IRQ(2), ar934x_ip2_irq_dispatch); 153 irq_set_chained_handler(ATH79_CPU_IRQ(2), ar934x_ip2_irq_dispatch);
151} 154}
152 155
156static void qca955x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc)
157{
158 u32 status;
159
160 disable_irq_nosync(irq);
161
162 status = ath79_reset_rr(QCA955X_RESET_REG_EXT_INT_STATUS);
163 status &= QCA955X_EXT_INT_PCIE_RC1_ALL | QCA955X_EXT_INT_WMAC_ALL;
164
165 if (status == 0) {
166 spurious_interrupt();
167 goto enable;
168 }
169
170 if (status & QCA955X_EXT_INT_PCIE_RC1_ALL) {
171 /* TODO: flush DDR? */
172 generic_handle_irq(ATH79_IP2_IRQ(0));
173 }
174
175 if (status & QCA955X_EXT_INT_WMAC_ALL) {
176 /* TODO: flush DDR? */
177 generic_handle_irq(ATH79_IP2_IRQ(1));
178 }
179
180enable:
181 enable_irq(irq);
182}
183
184static void qca955x_ip3_irq_dispatch(unsigned int irq, struct irq_desc *desc)
185{
186 u32 status;
187
188 disable_irq_nosync(irq);
189
190 status = ath79_reset_rr(QCA955X_RESET_REG_EXT_INT_STATUS);
191 status &= QCA955X_EXT_INT_PCIE_RC2_ALL |
192 QCA955X_EXT_INT_USB1 |
193 QCA955X_EXT_INT_USB2;
194
195 if (status == 0) {
196 spurious_interrupt();
197 goto enable;
198 }
199
200 if (status & QCA955X_EXT_INT_USB1) {
201 /* TODO: flush DDR? */
202 generic_handle_irq(ATH79_IP3_IRQ(0));
203 }
204
205 if (status & QCA955X_EXT_INT_USB2) {
206 /* TODO: flush DDR? */
207 generic_handle_irq(ATH79_IP3_IRQ(1));
208 }
209
210 if (status & QCA955X_EXT_INT_PCIE_RC2_ALL) {
211 /* TODO: flush DDR? */
212 generic_handle_irq(ATH79_IP3_IRQ(2));
213 }
214
215enable:
216 enable_irq(irq);
217}
218
219static void qca955x_irq_init(void)
220{
221 int i;
222
223 for (i = ATH79_IP2_IRQ_BASE;
224 i < ATH79_IP2_IRQ_BASE + ATH79_IP2_IRQ_COUNT; i++)
225 irq_set_chip_and_handler(i, &dummy_irq_chip,
226 handle_level_irq);
227
228 irq_set_chained_handler(ATH79_CPU_IRQ(2), qca955x_ip2_irq_dispatch);
229
230 for (i = ATH79_IP3_IRQ_BASE;
231 i < ATH79_IP3_IRQ_BASE + ATH79_IP3_IRQ_COUNT; i++)
232 irq_set_chip_and_handler(i, &dummy_irq_chip,
233 handle_level_irq);
234
235 irq_set_chained_handler(ATH79_CPU_IRQ(3), qca955x_ip3_irq_dispatch);
236}
237
153asmlinkage void plat_irq_dispatch(void) 238asmlinkage void plat_irq_dispatch(void)
154{ 239{
155 unsigned long pending; 240 unsigned long pending;
@@ -185,6 +270,17 @@ asmlinkage void plat_irq_dispatch(void)
185 * Issue a flush in the handlers to ensure that the driver sees 270 * Issue a flush in the handlers to ensure that the driver sees
186 * the update. 271 * the update.
187 */ 272 */
273
274static void ath79_default_ip2_handler(void)
275{
276 do_IRQ(ATH79_CPU_IRQ(2));
277}
278
279static void ath79_default_ip3_handler(void)
280{
281 do_IRQ(ATH79_CPU_IRQ(3));
282}
283
188static void ar71xx_ip2_handler(void) 284static void ar71xx_ip2_handler(void)
189{ 285{
190 ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_PCI); 286 ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_PCI);
@@ -209,11 +305,6 @@ static void ar933x_ip2_handler(void)
209 do_IRQ(ATH79_CPU_IRQ(2)); 305 do_IRQ(ATH79_CPU_IRQ(2));
210} 306}
211 307
212static void ar934x_ip2_handler(void)
213{
214 do_IRQ(ATH79_CPU_IRQ(2));
215}
216
217static void ar71xx_ip3_handler(void) 308static void ar71xx_ip3_handler(void)
218{ 309{
219 ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_USB); 310 ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_USB);
@@ -259,8 +350,11 @@ void __init arch_init_irq(void)
259 ath79_ip2_handler = ar933x_ip2_handler; 350 ath79_ip2_handler = ar933x_ip2_handler;
260 ath79_ip3_handler = ar933x_ip3_handler; 351 ath79_ip3_handler = ar933x_ip3_handler;
261 } else if (soc_is_ar934x()) { 352 } else if (soc_is_ar934x()) {
262 ath79_ip2_handler = ar934x_ip2_handler; 353 ath79_ip2_handler = ath79_default_ip2_handler;
263 ath79_ip3_handler = ar934x_ip3_handler; 354 ath79_ip3_handler = ar934x_ip3_handler;
355 } else if (soc_is_qca955x()) {
356 ath79_ip2_handler = ath79_default_ip2_handler;
357 ath79_ip3_handler = ath79_default_ip3_handler;
264 } else { 358 } else {
265 BUG(); 359 BUG();
266 } 360 }
@@ -271,4 +365,6 @@ void __init arch_init_irq(void)
271 365
272 if (soc_is_ar934x()) 366 if (soc_is_ar934x())
273 ar934x_ip2_irq_init(); 367 ar934x_ip2_irq_init();
368 else if (soc_is_qca955x())
369 qca955x_irq_init();
274} 370}
diff --git a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
index 7b00e12afc1c..8782d8b097a3 100644
--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
+++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
@@ -300,6 +300,7 @@
300#define AR934X_RESET_REG_PCIE_WMAC_INT_STATUS 0xac 300#define AR934X_RESET_REG_PCIE_WMAC_INT_STATUS 0xac
301 301
302#define QCA955X_RESET_REG_BOOTSTRAP 0xb0 302#define QCA955X_RESET_REG_BOOTSTRAP 0xb0
303#define QCA955X_RESET_REG_EXT_INT_STATUS 0xac
303 304
304#define MISC_INT_ETHSW BIT(12) 305#define MISC_INT_ETHSW BIT(12)
305#define MISC_INT_TIMER4 BIT(10) 306#define MISC_INT_TIMER4 BIT(10)
@@ -398,6 +399,37 @@
398 AR934X_PCIE_WMAC_INT_PCIE_RC1 | AR934X_PCIE_WMAC_INT_PCIE_RC2 | \ 399 AR934X_PCIE_WMAC_INT_PCIE_RC1 | AR934X_PCIE_WMAC_INT_PCIE_RC2 | \
399 AR934X_PCIE_WMAC_INT_PCIE_RC3) 400 AR934X_PCIE_WMAC_INT_PCIE_RC3)
400 401
402#define QCA955X_EXT_INT_WMAC_MISC BIT(0)
403#define QCA955X_EXT_INT_WMAC_TX BIT(1)
404#define QCA955X_EXT_INT_WMAC_RXLP BIT(2)
405#define QCA955X_EXT_INT_WMAC_RXHP BIT(3)
406#define QCA955X_EXT_INT_PCIE_RC1 BIT(4)
407#define QCA955X_EXT_INT_PCIE_RC1_INT0 BIT(5)
408#define QCA955X_EXT_INT_PCIE_RC1_INT1 BIT(6)
409#define QCA955X_EXT_INT_PCIE_RC1_INT2 BIT(7)
410#define QCA955X_EXT_INT_PCIE_RC1_INT3 BIT(8)
411#define QCA955X_EXT_INT_PCIE_RC2 BIT(12)
412#define QCA955X_EXT_INT_PCIE_RC2_INT0 BIT(13)
413#define QCA955X_EXT_INT_PCIE_RC2_INT1 BIT(14)
414#define QCA955X_EXT_INT_PCIE_RC2_INT2 BIT(15)
415#define QCA955X_EXT_INT_PCIE_RC2_INT3 BIT(16)
416#define QCA955X_EXT_INT_USB1 BIT(24)
417#define QCA955X_EXT_INT_USB2 BIT(28)
418
419#define QCA955X_EXT_INT_WMAC_ALL \
420 (QCA955X_EXT_INT_WMAC_MISC | QCA955X_EXT_INT_WMAC_TX | \
421 QCA955X_EXT_INT_WMAC_RXLP | QCA955X_EXT_INT_WMAC_RXHP)
422
423#define QCA955X_EXT_INT_PCIE_RC1_ALL \
424 (QCA955X_EXT_INT_PCIE_RC1 | QCA955X_EXT_INT_PCIE_RC1_INT0 | \
425 QCA955X_EXT_INT_PCIE_RC1_INT1 | QCA955X_EXT_INT_PCIE_RC1_INT2 | \
426 QCA955X_EXT_INT_PCIE_RC1_INT3)
427
428#define QCA955X_EXT_INT_PCIE_RC2_ALL \
429 (QCA955X_EXT_INT_PCIE_RC2 | QCA955X_EXT_INT_PCIE_RC2_INT0 | \
430 QCA955X_EXT_INT_PCIE_RC2_INT1 | QCA955X_EXT_INT_PCIE_RC2_INT2 | \
431 QCA955X_EXT_INT_PCIE_RC2_INT3)
432
401#define REV_ID_MAJOR_MASK 0xfff0 433#define REV_ID_MAJOR_MASK 0xfff0
402#define REV_ID_MAJOR_AR71XX 0x00a0 434#define REV_ID_MAJOR_AR71XX 0x00a0
403#define REV_ID_MAJOR_AR913X 0x00b0 435#define REV_ID_MAJOR_AR913X 0x00b0
diff --git a/arch/mips/include/asm/mach-ath79/irq.h b/arch/mips/include/asm/mach-ath79/irq.h
index 23e2bba42482..5c9ca76a7ebf 100644
--- a/arch/mips/include/asm/mach-ath79/irq.h
+++ b/arch/mips/include/asm/mach-ath79/irq.h
@@ -10,7 +10,7 @@
10#define __ASM_MACH_ATH79_IRQ_H 10#define __ASM_MACH_ATH79_IRQ_H
11 11
12#define MIPS_CPU_IRQ_BASE 0 12#define MIPS_CPU_IRQ_BASE 0
13#define NR_IRQS 48 13#define NR_IRQS 51
14 14
15#define ATH79_CPU_IRQ(_x) (MIPS_CPU_IRQ_BASE + (_x)) 15#define ATH79_CPU_IRQ(_x) (MIPS_CPU_IRQ_BASE + (_x))
16 16
@@ -26,6 +26,10 @@
26#define ATH79_IP2_IRQ_COUNT 2 26#define ATH79_IP2_IRQ_COUNT 2
27#define ATH79_IP2_IRQ(_x) (ATH79_IP2_IRQ_BASE + (_x)) 27#define ATH79_IP2_IRQ(_x) (ATH79_IP2_IRQ_BASE + (_x))
28 28
29#define ATH79_IP3_IRQ_BASE (ATH79_IP2_IRQ_BASE + ATH79_IP2_IRQ_COUNT)
30#define ATH79_IP3_IRQ_COUNT 3
31#define ATH79_IP3_IRQ(_x) (ATH79_IP3_IRQ_BASE + (_x))
32
29#include_next <irq.h> 33#include_next <irq.h>
30 34
31#endif /* __ASM_MACH_ATH79_IRQ_H */ 35#endif /* __ASM_MACH_ATH79_IRQ_H */