• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ath79_misc_irq_handler(unsigned int irq,struct irq_desc * desc)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 
ar71xx_misc_irq_unmask(struct irq_data * d)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 
ar71xx_misc_irq_mask(struct irq_data * d)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 
ar724x_misc_irq_ack(struct irq_data * d)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 
ath79_misc_irq_init(void)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 
ar934x_ip2_irq_dispatch(unsigned int irq,struct irq_desc * desc)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 
ar934x_ip2_irq_init(void)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 
qca955x_ip2_irq_dispatch(unsigned int irq,struct irq_desc * desc)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 
qca955x_ip3_irq_dispatch(unsigned int irq,struct irq_desc * desc)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 
qca955x_irq_init(void)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 
plat_irq_dispatch(void)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 
ath79_default_ip2_handler(void)274 static void ath79_default_ip2_handler(void)
275 {
276 	do_IRQ(ATH79_CPU_IRQ(2));
277 }
278 
ath79_default_ip3_handler(void)279 static void ath79_default_ip3_handler(void)
280 {
281 	do_IRQ(ATH79_CPU_IRQ(3));
282 }
283 
ar71xx_ip2_handler(void)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 
ar724x_ip2_handler(void)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 
ar913x_ip2_handler(void)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 
ar933x_ip2_handler(void)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 
ar71xx_ip3_handler(void)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 
ar724x_ip3_handler(void)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 
ar913x_ip3_handler(void)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 
ar933x_ip3_handler(void)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 
ar934x_ip3_handler(void)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 
arch_init_irq(void)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 	cp0_perfcount_irq = ATH79_MISC_IRQ(5);
363 	mips_cpu_irq_init();
364 	ath79_misc_irq_init();
365 
366 	if (soc_is_ar934x())
367 		ar934x_ip2_irq_init();
368 	else if (soc_is_qca955x())
369 		qca955x_irq_init();
370 }
371