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 /arch/mips/ath79 | |
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>
Diffstat (limited to 'arch/mips/ath79')
-rw-r--r-- | arch/mips/ath79/irq.c | 110 |
1 files changed, 103 insertions, 7 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 | } |