]> Pileus Git - ~andy/linux/blob - arch/mips/ath79/irq.c
MIPS: ath79: add clock setup code for the QCA955X SoCs
[~andy/linux] / 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() || soc_is_ar933x() || soc_is_ar934x())
107                 ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack;
108         else
109                 BUG();
110
111         for (i = ATH79_MISC_IRQ_BASE;
112              i < ATH79_MISC_IRQ_BASE + ATH79_MISC_IRQ_COUNT; i++) {
113                 irq_set_chip_and_handler(i, &ath79_misc_irq_chip,
114                                          handle_level_irq);
115         }
116
117         irq_set_chained_handler(ATH79_CPU_IRQ(6), ath79_misc_irq_handler);
118 }
119
120 static void ar934x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc)
121 {
122         u32 status;
123
124         disable_irq_nosync(irq);
125
126         status = ath79_reset_rr(AR934X_RESET_REG_PCIE_WMAC_INT_STATUS);
127
128         if (status & AR934X_PCIE_WMAC_INT_PCIE_ALL) {
129                 ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_PCIE);
130                 generic_handle_irq(ATH79_IP2_IRQ(0));
131         } else if (status & AR934X_PCIE_WMAC_INT_WMAC_ALL) {
132                 ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_WMAC);
133                 generic_handle_irq(ATH79_IP2_IRQ(1));
134         } else {
135                 spurious_interrupt();
136         }
137
138         enable_irq(irq);
139 }
140
141 static void ar934x_ip2_irq_init(void)
142 {
143         int i;
144
145         for (i = ATH79_IP2_IRQ_BASE;
146              i < ATH79_IP2_IRQ_BASE + ATH79_IP2_IRQ_COUNT; i++)
147                 irq_set_chip_and_handler(i, &dummy_irq_chip,
148                                          handle_level_irq);
149
150         irq_set_chained_handler(ATH79_CPU_IRQ(2), ar934x_ip2_irq_dispatch);
151 }
152
153 asmlinkage void plat_irq_dispatch(void)
154 {
155         unsigned long pending;
156
157         pending = read_c0_status() & read_c0_cause() & ST0_IM;
158
159         if (pending & STATUSF_IP7)
160                 do_IRQ(ATH79_CPU_IRQ(7));
161
162         else if (pending & STATUSF_IP2)
163                 ath79_ip2_handler();
164
165         else if (pending & STATUSF_IP4)
166                 do_IRQ(ATH79_CPU_IRQ(4));
167
168         else if (pending & STATUSF_IP5)
169                 do_IRQ(ATH79_CPU_IRQ(5));
170
171         else if (pending & STATUSF_IP3)
172                 ath79_ip3_handler();
173
174         else if (pending & STATUSF_IP6)
175                 do_IRQ(ATH79_CPU_IRQ(6));
176
177         else
178                 spurious_interrupt();
179 }
180
181 /*
182  * The IP2/IP3 lines are tied to a PCI/WMAC/USB device. Drivers for
183  * these devices typically allocate coherent DMA memory, however the
184  * DMA controller may still have some unsynchronized data in the FIFO.
185  * Issue a flush in the handlers to ensure that the driver sees
186  * the update.
187  */
188 static void ar71xx_ip2_handler(void)
189 {
190         ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_PCI);
191         do_IRQ(ATH79_CPU_IRQ(2));
192 }
193
194 static void ar724x_ip2_handler(void)
195 {
196         ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_PCIE);
197         do_IRQ(ATH79_CPU_IRQ(2));
198 }
199
200 static void ar913x_ip2_handler(void)
201 {
202         ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_WMAC);
203         do_IRQ(ATH79_CPU_IRQ(2));
204 }
205
206 static void ar933x_ip2_handler(void)
207 {
208         ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_WMAC);
209         do_IRQ(ATH79_CPU_IRQ(2));
210 }
211
212 static void ar934x_ip2_handler(void)
213 {
214         do_IRQ(ATH79_CPU_IRQ(2));
215 }
216
217 static void ar71xx_ip3_handler(void)
218 {
219         ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_USB);
220         do_IRQ(ATH79_CPU_IRQ(3));
221 }
222
223 static void ar724x_ip3_handler(void)
224 {
225         ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_USB);
226         do_IRQ(ATH79_CPU_IRQ(3));
227 }
228
229 static void ar913x_ip3_handler(void)
230 {
231         ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_USB);
232         do_IRQ(ATH79_CPU_IRQ(3));
233 }
234
235 static void ar933x_ip3_handler(void)
236 {
237         ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_USB);
238         do_IRQ(ATH79_CPU_IRQ(3));
239 }
240
241 static void ar934x_ip3_handler(void)
242 {
243         ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_USB);
244         do_IRQ(ATH79_CPU_IRQ(3));
245 }
246
247 void __init arch_init_irq(void)
248 {
249         if (soc_is_ar71xx()) {
250                 ath79_ip2_handler = ar71xx_ip2_handler;
251                 ath79_ip3_handler = ar71xx_ip3_handler;
252         } else if (soc_is_ar724x()) {
253                 ath79_ip2_handler = ar724x_ip2_handler;
254                 ath79_ip3_handler = ar724x_ip3_handler;
255         } else if (soc_is_ar913x()) {
256                 ath79_ip2_handler = ar913x_ip2_handler;
257                 ath79_ip3_handler = ar913x_ip3_handler;
258         } else if (soc_is_ar933x()) {
259                 ath79_ip2_handler = ar933x_ip2_handler;
260                 ath79_ip3_handler = ar933x_ip3_handler;
261         } else if (soc_is_ar934x()) {
262                 ath79_ip2_handler = ar934x_ip2_handler;
263                 ath79_ip3_handler = ar934x_ip3_handler;
264         } else {
265                 BUG();
266         }
267
268         cp0_perfcount_irq = ATH79_MISC_IRQ(5);
269         mips_cpu_irq_init();
270         ath79_misc_irq_init();
271
272         if (soc_is_ar934x())
273                 ar934x_ip2_irq_init();
274 }