Merge tag 'iwlwifi-next-for-kalle-2014-12-30' of https://git.kernel.org/pub/scm/linux...
[cascardo/linux.git] / arch / mips / ath79 / irq.c
1 /*
2  *  Atheros AR71xx/AR724x/AR913x specific interrupt handling
3  *
4  *  Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com>
5  *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
6  *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
7  *
8  *  Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP
9  *
10  *  This program is free software; you can redistribute it and/or modify it
11  *  under the terms of the GNU General Public License version 2 as published
12  *  by the Free Software Foundation.
13  */
14
15 #include <linux/kernel.h>
16 #include <linux/init.h>
17 #include <linux/interrupt.h>
18 #include <linux/irq.h>
19
20 #include <asm/irq_cpu.h>
21 #include <asm/mipsregs.h>
22
23 #include <asm/mach-ath79/ath79.h>
24 #include <asm/mach-ath79/ar71xx_regs.h>
25 #include "common.h"
26
27 static void (*ath79_ip2_handler)(void);
28 static void (*ath79_ip3_handler)(void);
29
30 static void ath79_misc_irq_handler(unsigned int irq, struct irq_desc *desc)
31 {
32         void __iomem *base = ath79_reset_base;
33         u32 pending;
34
35         pending = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS) &
36                   __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
37
38         if (!pending) {
39                 spurious_interrupt();
40                 return;
41         }
42
43         while (pending) {
44                 int bit = __ffs(pending);
45
46                 generic_handle_irq(ATH79_MISC_IRQ(bit));
47                 pending &= ~BIT(bit);
48         }
49 }
50
51 static void ar71xx_misc_irq_unmask(struct irq_data *d)
52 {
53         unsigned int irq = d->irq - ATH79_MISC_IRQ_BASE;
54         void __iomem *base = ath79_reset_base;
55         u32 t;
56
57         t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
58         __raw_writel(t | (1 << irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE);
59
60         /* flush write */
61         __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
62 }
63
64 static void ar71xx_misc_irq_mask(struct irq_data *d)
65 {
66         unsigned int irq = d->irq - ATH79_MISC_IRQ_BASE;
67         void __iomem *base = ath79_reset_base;
68         u32 t;
69
70         t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
71         __raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE);
72
73         /* flush write */
74         __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
75 }
76
77 static void ar724x_misc_irq_ack(struct irq_data *d)
78 {
79         unsigned int irq = d->irq - ATH79_MISC_IRQ_BASE;
80         void __iomem *base = ath79_reset_base;
81         u32 t;
82
83         t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS);
84         __raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_MISC_INT_STATUS);
85
86         /* flush write */
87         __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS);
88 }
89
90 static struct irq_chip ath79_misc_irq_chip = {
91         .name           = "MISC",
92         .irq_unmask     = ar71xx_misc_irq_unmask,
93         .irq_mask       = ar71xx_misc_irq_mask,
94 };
95
96 static void __init ath79_misc_irq_init(void)
97 {
98         void __iomem *base = ath79_reset_base;
99         int i;
100
101         __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_ENABLE);
102         __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS);
103
104         if (soc_is_ar71xx() || soc_is_ar913x())
105                 ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask;
106         else if (soc_is_ar724x() ||
107                  soc_is_ar933x() ||
108                  soc_is_ar934x() ||
109                  soc_is_qca955x())
110                 ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack;
111         else
112                 BUG();
113
114         for (i = ATH79_MISC_IRQ_BASE;
115              i < ATH79_MISC_IRQ_BASE + ATH79_MISC_IRQ_COUNT; i++) {
116                 irq_set_chip_and_handler(i, &ath79_misc_irq_chip,
117                                          handle_level_irq);
118         }
119
120         irq_set_chained_handler(ATH79_CPU_IRQ(6), ath79_misc_irq_handler);
121 }
122
123 static void ar934x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc)
124 {
125         u32 status;
126
127         disable_irq_nosync(irq);
128
129         status = ath79_reset_rr(AR934X_RESET_REG_PCIE_WMAC_INT_STATUS);
130
131         if (status & AR934X_PCIE_WMAC_INT_PCIE_ALL) {
132                 ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_PCIE);
133                 generic_handle_irq(ATH79_IP2_IRQ(0));
134         } else if (status & AR934X_PCIE_WMAC_INT_WMAC_ALL) {
135                 ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_WMAC);
136                 generic_handle_irq(ATH79_IP2_IRQ(1));
137         } else {
138                 spurious_interrupt();
139         }
140
141         enable_irq(irq);
142 }
143
144 static void ar934x_ip2_irq_init(void)
145 {
146         int i;
147
148         for (i = ATH79_IP2_IRQ_BASE;
149              i < ATH79_IP2_IRQ_BASE + ATH79_IP2_IRQ_COUNT; i++)
150                 irq_set_chip_and_handler(i, &dummy_irq_chip,
151                                          handle_level_irq);
152
153         irq_set_chained_handler(ATH79_CPU_IRQ(2), ar934x_ip2_irq_dispatch);
154 }
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
238 asmlinkage void plat_irq_dispatch(void)
239 {
240         unsigned long pending;
241
242         pending = read_c0_status() & read_c0_cause() & ST0_IM;
243
244         if (pending & STATUSF_IP7)
245                 do_IRQ(ATH79_CPU_IRQ(7));
246
247         else if (pending & STATUSF_IP2)
248                 ath79_ip2_handler();
249
250         else if (pending & STATUSF_IP4)
251                 do_IRQ(ATH79_CPU_IRQ(4));
252
253         else if (pending & STATUSF_IP5)
254                 do_IRQ(ATH79_CPU_IRQ(5));
255
256         else if (pending & STATUSF_IP3)
257                 ath79_ip3_handler();
258
259         else if (pending & STATUSF_IP6)
260                 do_IRQ(ATH79_CPU_IRQ(6));
261
262         else
263                 spurious_interrupt();
264 }
265
266 /*
267  * The IP2/IP3 lines are tied to a PCI/WMAC/USB device. Drivers for
268  * these devices typically allocate coherent DMA memory, however the
269  * DMA controller may still have some unsynchronized data in the FIFO.
270  * Issue a flush in the handlers to ensure that the driver sees
271  * the update.
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
284 static void ar71xx_ip2_handler(void)
285 {
286         ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_PCI);
287         do_IRQ(ATH79_CPU_IRQ(2));
288 }
289
290 static void ar724x_ip2_handler(void)
291 {
292         ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_PCIE);
293         do_IRQ(ATH79_CPU_IRQ(2));
294 }
295
296 static void ar913x_ip2_handler(void)
297 {
298         ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_WMAC);
299         do_IRQ(ATH79_CPU_IRQ(2));
300 }
301
302 static void ar933x_ip2_handler(void)
303 {
304         ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_WMAC);
305         do_IRQ(ATH79_CPU_IRQ(2));
306 }
307
308 static void ar71xx_ip3_handler(void)
309 {
310         ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_USB);
311         do_IRQ(ATH79_CPU_IRQ(3));
312 }
313
314 static void ar724x_ip3_handler(void)
315 {
316         ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_USB);
317         do_IRQ(ATH79_CPU_IRQ(3));
318 }
319
320 static void ar913x_ip3_handler(void)
321 {
322         ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_USB);
323         do_IRQ(ATH79_CPU_IRQ(3));
324 }
325
326 static void ar933x_ip3_handler(void)
327 {
328         ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_USB);
329         do_IRQ(ATH79_CPU_IRQ(3));
330 }
331
332 static void ar934x_ip3_handler(void)
333 {
334         ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_USB);
335         do_IRQ(ATH79_CPU_IRQ(3));
336 }
337
338 void __init arch_init_irq(void)
339 {
340         if (soc_is_ar71xx()) {
341                 ath79_ip2_handler = ar71xx_ip2_handler;
342                 ath79_ip3_handler = ar71xx_ip3_handler;
343         } else if (soc_is_ar724x()) {
344                 ath79_ip2_handler = ar724x_ip2_handler;
345                 ath79_ip3_handler = ar724x_ip3_handler;
346         } else if (soc_is_ar913x()) {
347                 ath79_ip2_handler = ar913x_ip2_handler;
348                 ath79_ip3_handler = ar913x_ip3_handler;
349         } else if (soc_is_ar933x()) {
350                 ath79_ip2_handler = ar933x_ip2_handler;
351                 ath79_ip3_handler = ar933x_ip3_handler;
352         } else if (soc_is_ar934x()) {
353                 ath79_ip2_handler = ath79_default_ip2_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;
358         } else {
359                 BUG();
360         }
361
362         mips_cpu_irq_init();
363         ath79_misc_irq_init();
364
365         if (soc_is_ar934x())
366                 ar934x_ip2_irq_init();
367         else if (soc_is_qca955x())
368                 qca955x_irq_init();
369 }