diff options
author | Gabor Juhos <juhosg@openwrt.org> | 2013-02-15 13:53:47 -0500 |
---|---|---|
committer | John Crispin <blogic@openwrt.org> | 2013-02-19 03:36:25 -0500 |
commit | 53330332f176eaa9567481c69bbad8b2176b4eb5 (patch) | |
tree | d5278cdce05a2a3bbfacb0e774c45f67ca3429ff | |
parent | 41583c05c15cd3adb848f9ee8316bf8084c961cb (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.c | 110 | ||||
-rw-r--r-- | arch/mips/include/asm/mach-ath79/ar71xx_regs.h | 32 | ||||
-rw-r--r-- | arch/mips/include/asm/mach-ath79/irq.h | 6 |
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 | ||
156 | static 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 | |||
180 | enable: | ||
181 | enable_irq(irq); | ||
182 | } | ||
183 | |||
184 | static 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 | |||
215 | enable: | ||
216 | enable_irq(irq); | ||
217 | } | ||
218 | |||
219 | static 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 | |||
153 | asmlinkage void plat_irq_dispatch(void) | 238 | asmlinkage 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 | |||
274 | static void ath79_default_ip2_handler(void) | ||
275 | { | ||
276 | do_IRQ(ATH79_CPU_IRQ(2)); | ||
277 | } | ||
278 | |||
279 | static void ath79_default_ip3_handler(void) | ||
280 | { | ||
281 | do_IRQ(ATH79_CPU_IRQ(3)); | ||
282 | } | ||
283 | |||
188 | static void ar71xx_ip2_handler(void) | 284 | static 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 | ||
212 | static void ar934x_ip2_handler(void) | ||
213 | { | ||
214 | do_IRQ(ATH79_CPU_IRQ(2)); | ||
215 | } | ||
216 | |||
217 | static void ar71xx_ip3_handler(void) | 308 | static 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 */ |