Merge branch 'for-3.5-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj...
[firefly-linux-kernel-4.4.55.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 & MISC_INT_UART)
39                 generic_handle_irq(ATH79_MISC_IRQ_UART);
40
41         else if (pending & MISC_INT_DMA)
42                 generic_handle_irq(ATH79_MISC_IRQ_DMA);
43
44         else if (pending & MISC_INT_PERFC)
45                 generic_handle_irq(ATH79_MISC_IRQ_PERFC);
46
47         else if (pending & MISC_INT_TIMER)
48                 generic_handle_irq(ATH79_MISC_IRQ_TIMER);
49
50         else if (pending & MISC_INT_TIMER2)
51                 generic_handle_irq(ATH79_MISC_IRQ_TIMER2);
52
53         else if (pending & MISC_INT_TIMER3)
54                 generic_handle_irq(ATH79_MISC_IRQ_TIMER3);
55
56         else if (pending & MISC_INT_TIMER4)
57                 generic_handle_irq(ATH79_MISC_IRQ_TIMER4);
58
59         else if (pending & MISC_INT_OHCI)
60                 generic_handle_irq(ATH79_MISC_IRQ_OHCI);
61
62         else if (pending & MISC_INT_ERROR)
63                 generic_handle_irq(ATH79_MISC_IRQ_ERROR);
64
65         else if (pending & MISC_INT_GPIO)
66                 generic_handle_irq(ATH79_MISC_IRQ_GPIO);
67
68         else if (pending & MISC_INT_WDOG)
69                 generic_handle_irq(ATH79_MISC_IRQ_WDOG);
70
71         else if (pending & MISC_INT_ETHSW)
72                 generic_handle_irq(ATH79_MISC_IRQ_ETHSW);
73
74         else
75                 spurious_interrupt();
76 }
77
78 static void ar71xx_misc_irq_unmask(struct irq_data *d)
79 {
80         unsigned int irq = d->irq - ATH79_MISC_IRQ_BASE;
81         void __iomem *base = ath79_reset_base;
82         u32 t;
83
84         t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
85         __raw_writel(t | (1 << irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE);
86
87         /* flush write */
88         __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
89 }
90
91 static void ar71xx_misc_irq_mask(struct irq_data *d)
92 {
93         unsigned int irq = d->irq - ATH79_MISC_IRQ_BASE;
94         void __iomem *base = ath79_reset_base;
95         u32 t;
96
97         t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
98         __raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE);
99
100         /* flush write */
101         __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
102 }
103
104 static void ar724x_misc_irq_ack(struct irq_data *d)
105 {
106         unsigned int irq = d->irq - ATH79_MISC_IRQ_BASE;
107         void __iomem *base = ath79_reset_base;
108         u32 t;
109
110         t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS);
111         __raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_MISC_INT_STATUS);
112
113         /* flush write */
114         __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS);
115 }
116
117 static struct irq_chip ath79_misc_irq_chip = {
118         .name           = "MISC",
119         .irq_unmask     = ar71xx_misc_irq_unmask,
120         .irq_mask       = ar71xx_misc_irq_mask,
121 };
122
123 static void __init ath79_misc_irq_init(void)
124 {
125         void __iomem *base = ath79_reset_base;
126         int i;
127
128         __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_ENABLE);
129         __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS);
130
131         if (soc_is_ar71xx() || soc_is_ar913x())
132                 ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask;
133         else if (soc_is_ar724x() || soc_is_ar933x() || soc_is_ar934x())
134                 ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack;
135         else
136                 BUG();
137
138         for (i = ATH79_MISC_IRQ_BASE;
139              i < ATH79_MISC_IRQ_BASE + ATH79_MISC_IRQ_COUNT; i++) {
140                 irq_set_chip_and_handler(i, &ath79_misc_irq_chip,
141                                          handle_level_irq);
142         }
143
144         irq_set_chained_handler(ATH79_CPU_IRQ_MISC, ath79_misc_irq_handler);
145 }
146
147 static void ar934x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc)
148 {
149         u32 status;
150
151         disable_irq_nosync(irq);
152
153         status = ath79_reset_rr(AR934X_RESET_REG_PCIE_WMAC_INT_STATUS);
154
155         if (status & AR934X_PCIE_WMAC_INT_PCIE_ALL) {
156                 ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_PCIE);
157                 generic_handle_irq(ATH79_IP2_IRQ(0));
158         } else if (status & AR934X_PCIE_WMAC_INT_WMAC_ALL) {
159                 ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_WMAC);
160                 generic_handle_irq(ATH79_IP2_IRQ(1));
161         } else {
162                 spurious_interrupt();
163         }
164
165         enable_irq(irq);
166 }
167
168 static void ar934x_ip2_irq_init(void)
169 {
170         int i;
171
172         for (i = ATH79_IP2_IRQ_BASE;
173              i < ATH79_IP2_IRQ_BASE + ATH79_IP2_IRQ_COUNT; i++)
174                 irq_set_chip_and_handler(i, &dummy_irq_chip,
175                                          handle_level_irq);
176
177         irq_set_chained_handler(ATH79_CPU_IRQ_IP2, ar934x_ip2_irq_dispatch);
178 }
179
180 asmlinkage void plat_irq_dispatch(void)
181 {
182         unsigned long pending;
183
184         pending = read_c0_status() & read_c0_cause() & ST0_IM;
185
186         if (pending & STATUSF_IP7)
187                 do_IRQ(ATH79_CPU_IRQ_TIMER);
188
189         else if (pending & STATUSF_IP2)
190                 ath79_ip2_handler();
191
192         else if (pending & STATUSF_IP4)
193                 do_IRQ(ATH79_CPU_IRQ_GE0);
194
195         else if (pending & STATUSF_IP5)
196                 do_IRQ(ATH79_CPU_IRQ_GE1);
197
198         else if (pending & STATUSF_IP3)
199                 ath79_ip3_handler();
200
201         else if (pending & STATUSF_IP6)
202                 do_IRQ(ATH79_CPU_IRQ_MISC);
203
204         else
205                 spurious_interrupt();
206 }
207
208 /*
209  * The IP2/IP3 lines are tied to a PCI/WMAC/USB device. Drivers for
210  * these devices typically allocate coherent DMA memory, however the
211  * DMA controller may still have some unsynchronized data in the FIFO.
212  * Issue a flush in the handlers to ensure that the driver sees
213  * the update.
214  */
215 static void ar71xx_ip2_handler(void)
216 {
217         ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_PCI);
218         do_IRQ(ATH79_CPU_IRQ_IP2);
219 }
220
221 static void ar724x_ip2_handler(void)
222 {
223         ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_PCIE);
224         do_IRQ(ATH79_CPU_IRQ_IP2);
225 }
226
227 static void ar913x_ip2_handler(void)
228 {
229         ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_WMAC);
230         do_IRQ(ATH79_CPU_IRQ_IP2);
231 }
232
233 static void ar933x_ip2_handler(void)
234 {
235         ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_WMAC);
236         do_IRQ(ATH79_CPU_IRQ_IP2);
237 }
238
239 static void ar934x_ip2_handler(void)
240 {
241         do_IRQ(ATH79_CPU_IRQ_IP2);
242 }
243
244 static void ar71xx_ip3_handler(void)
245 {
246         ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_USB);
247         do_IRQ(ATH79_CPU_IRQ_USB);
248 }
249
250 static void ar724x_ip3_handler(void)
251 {
252         ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_USB);
253         do_IRQ(ATH79_CPU_IRQ_USB);
254 }
255
256 static void ar913x_ip3_handler(void)
257 {
258         ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_USB);
259         do_IRQ(ATH79_CPU_IRQ_USB);
260 }
261
262 static void ar933x_ip3_handler(void)
263 {
264         ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_USB);
265         do_IRQ(ATH79_CPU_IRQ_USB);
266 }
267
268 static void ar934x_ip3_handler(void)
269 {
270         ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_USB);
271         do_IRQ(ATH79_CPU_IRQ_USB);
272 }
273
274 void __init arch_init_irq(void)
275 {
276         if (soc_is_ar71xx()) {
277                 ath79_ip2_handler = ar71xx_ip2_handler;
278                 ath79_ip3_handler = ar71xx_ip3_handler;
279         } else if (soc_is_ar724x()) {
280                 ath79_ip2_handler = ar724x_ip2_handler;
281                 ath79_ip3_handler = ar724x_ip3_handler;
282         } else if (soc_is_ar913x()) {
283                 ath79_ip2_handler = ar913x_ip2_handler;
284                 ath79_ip3_handler = ar913x_ip3_handler;
285         } else if (soc_is_ar933x()) {
286                 ath79_ip2_handler = ar933x_ip2_handler;
287                 ath79_ip3_handler = ar933x_ip3_handler;
288         } else if (soc_is_ar934x()) {
289                 ath79_ip2_handler = ar934x_ip2_handler;
290                 ath79_ip3_handler = ar934x_ip3_handler;
291         } else {
292                 BUG();
293         }
294
295         cp0_perfcount_irq = ATH79_MISC_IRQ_PERFC;
296         mips_cpu_irq_init();
297         ath79_misc_irq_init();
298
299         if (soc_is_ar934x())
300                 ar934x_ip2_irq_init();
301 }