aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/ath79
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 /arch/mips/ath79
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>
Diffstat (limited to 'arch/mips/ath79')
-rw-r--r--arch/mips/ath79/irq.c110
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
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}