1 /* $NetBSD: ralink_intr.c,v 1.7 2021/01/04 18:14:38 thorpej Exp $ */
2 /*-
3 * Copyright (c) 2011 CradlePoint Technology, Inc.
4 * All rights reserved.
5 *
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY CRADLEPOINT TECHNOLOGY, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #define __INTR_PRIVATE
30
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: ralink_intr.c,v 1.7 2021/01/04 18:14:38 thorpej Exp $");
33
34 #include <sys/param.h>
35 #include <sys/bus.h>
36 #include <sys/device.h>
37 #include <sys/intr.h>
38 #include <sys/kernel.h>
39 #include <sys/kmem.h>
40 #include <sys/systm.h>
41
42 #include <mips/locore.h>
43
44 #include <mips/ralink/ralink_reg.h>
45 #include <mips/ralink/ralink_var.h>
46
47 static int ra_pic_intr(void *arg);
48
49 /*
50 * evbmips spl integration:
51 * this is a mask of bits to clear in the SR when we go to a
52 * given hardware interrupt priority level.
53 */
54 static const struct ipl_sr_map ralink_ipl_sr_map = {
55 .sr_bits = {
56 [IPL_NONE] = 0,
57 [IPL_SOFTCLOCK] = MIPS_SOFT_INT_MASK_0,
58 [IPL_SOFTBIO] = MIPS_SOFT_INT_MASK_0,
59 [IPL_SOFTNET] = MIPS_SOFT_INT_MASK,
60 [IPL_SOFTSERIAL] = MIPS_SOFT_INT_MASK,
61 [IPL_VM] = MIPS_INT_MASK ^ MIPS_INT_MASK_5,
62 [IPL_SCHED] = MIPS_INT_MASK,
63 [IPL_DDB] = MIPS_INT_MASK,
64 [IPL_HIGH] = MIPS_INT_MASK,
65 },
66 };
67
68
69 /*
70 * RT3052 Interrupt Block Definitions
71 *
72 * HW_INT0 - Low Priority Chip Interrupts (Lowest Priority)
73 * HW_INT1 - High Priority Chip Interrupts
74 * HW_INT2 - PCIe/PCI (3883 only)
75 * HW_INT3 - Frame Engine
76 * HW_INT4 - 802.11n NIC
77 * HW_INT5 - Timer Interrupt (Highest Priority)
78 *
79 * HW_INT0 and HW_INT1 can be configured to fire with any of the other
80 * interrupts on chip. They can be masked for either INT0 or INT1
81 * but not both.
82 *
83 * SYSCTL
84 * TIMER0
85 * WDTIMER
86 * ILLACC
87 * PCM
88 * UARTF
89 * PIO
90 * DMA
91 * NAND
92 * PERF
93 * I2S
94 * UARTL
95 * ETHSW
96 * USB
97 */
98
99 struct ra_intr {
100 LIST_HEAD(, evbmips_intrhand) intr_list;
101 struct evcnt intr_evcnt;
102 };
103
104 /*
105 * ordering for ra_intrtab[] and ra_intr_names[]
106 * corresponds to the RA_IRQ_* definitions
107 * which include the CPU intrs and the PIC intrs
108 */
109 static struct ra_intr ra_intrtab[RA_IRQ_MAX];
110 static const char * const ra_intr_names[RA_IRQ_MAX] = {
111 /* CPU interrupts */
112 [RA_IRQ_LOW] = "intr 0 (lowpri)",
113 [RA_IRQ_HIGH] = "intr 1 (highpri)",
114 [RA_IRQ_PCI] = "intr 2 (pci)",
115 [RA_IRQ_FENGINE]= "intr 3 (frame)",
116 [RA_IRQ_WLAN] = "intr 4 (wlan)",
117 [RA_IRQ_TIMER] = "intr 5 (timer)",
118
119 /* Interrupt controller */
120 [RA_IRQ_SYSCTL] = "intc sysctl",
121 [RA_IRQ_TIMER0] = "intc timer0",
122 [RA_IRQ_WDOG] = "intc wdog",
123 [RA_IRQ_ILLACC] = "intc illacc",
124 [RA_IRQ_PCM] = "intc pcm",
125 [RA_IRQ_UARTF] = "intc uartf",
126 [RA_IRQ_PIO] = "intc gpio",
127 [RA_IRQ_DMA] = "intc dma",
128 [RA_IRQ_NAND] = "intc nand",
129 [RA_IRQ_PERF] = "intc pef",
130 [RA_IRQ_I2S] = "intc i2s",
131 [RA_IRQ_SPI] = "intc spi",
132 [RA_IRQ_UARTL] = "intc uartl",
133 [RA_IRQ_CRYPTO] = "intc crypto",
134 [RA_IRQ_SDHC] = "intc sdhc",
135 [RA_IRQ_R2P] = "intc r2p",
136 [RA_IRQ_ETHSW] = "intc ethsw",
137 [RA_IRQ_USB] = "intc usb",
138 [RA_IRQ_UDEV] = "intc udev",
139 [RA_IRQ_UART1] = "intc uart1",
140 [RA_IRQ_UART2] = "intc uart2",
141 };
142
143 /* determine if irq belongs to the PIC */
144 #define PIC_IRQ_P(irq) ((irq) > RA_IRQ_TIMER)
145
146 /* map the IRQ num to PIC reg bits */
147 static const uint8_t irq2bit[RA_IRQ_MAX] = {
148 /* CPU interrupts */
149 [RA_IRQ_LOW] = -1,
150 [RA_IRQ_HIGH] = -1,
151 [RA_IRQ_PCI] = -1,
152 [RA_IRQ_FENGINE]= -1,
153 [RA_IRQ_WLAN] = -1,
154 [RA_IRQ_TIMER] = -1,
155
156 /* Interrupt controller */
157 [RA_IRQ_SYSCTL] = INT_SYSCTL,
158 [RA_IRQ_TIMER0] = INT_TIMER0,
159 [RA_IRQ_WDOG] = INT_WDOG,
160 [RA_IRQ_ILLACC] = INT_ILLACC,
161 [RA_IRQ_PCM] = INT_PCM,
162 [RA_IRQ_UARTF] = INT_UARTF,
163 [RA_IRQ_PIO] = INT_PIO,
164 [RA_IRQ_DMA] = INT_DMA,
165 [RA_IRQ_NAND] = INT_NAND,
166 [RA_IRQ_PERF] = INT_PERF,
167 [RA_IRQ_I2S] = INT_I2S,
168 [RA_IRQ_SPI] = INT_SPI,
169 [RA_IRQ_UARTL] = INT_UARTL,
170 #ifdef INT_UART1
171 [RA_IRQ_UART1] = INT_UART1,
172 #endif
173 #ifdef INT_UART2
174 [RA_IRQ_UART2] = INT_UART2,
175 #endif
176 [RA_IRQ_CRYPTO] = INT_CRYPTO,
177 [RA_IRQ_SDHC] = INT_SDHC,
178 [RA_IRQ_R2P] = INT_R2P,
179 [RA_IRQ_ETHSW] = INT_ETHSW,
180 [RA_IRQ_USB] = INT_USB,
181 [RA_IRQ_UDEV] = INT_UDEV
182 };
183
184 /* map the PIC reg bits to IRQ num */
185 static const uint8_t bit2irq[32] = {
186 [INT_SYSCTL] = RA_IRQ_SYSCTL,
187 [INT_TIMER0] = RA_IRQ_TIMER0,
188 [INT_WDOG] = RA_IRQ_WDOG,
189 [INT_ILLACC] = RA_IRQ_ILLACC,
190 [INT_PCM] = RA_IRQ_PCM,
191 [INT_UARTF] = RA_IRQ_UARTF,
192 [INT_PIO] = RA_IRQ_PIO,
193 [INT_DMA] = RA_IRQ_DMA,
194 [INT_NAND] = RA_IRQ_NAND,
195 [INT_PERF] = RA_IRQ_PERF,
196 [INT_I2S] = RA_IRQ_I2S,
197 [INT_SPI] = RA_IRQ_SPI,
198 [INT_UARTL] = RA_IRQ_UARTL,
199 #ifdef INT_UART1
200 [INT_UART1] = RA_IRQ_UART1,
201 #endif
202 #ifdef INT_UART2
203 [INT_UART2] = RA_IRQ_UART2,
204 #endif
205 [INT_CRYPTO] = RA_IRQ_CRYPTO,
206 [INT_SDHC] = RA_IRQ_SDHC,
207 [INT_R2P] = RA_IRQ_R2P,
208 [INT_ETHSW] = RA_IRQ_ETHSW,
209 [INT_USB] = RA_IRQ_USB,
210 [INT_UDEV] = RA_IRQ_UDEV
211 };
212
213
214
215 static inline uint32_t
intctl_read(u_int offset)216 intctl_read(u_int offset)
217 {
218 return *RA_IOREG_VADDR(RA_INTCTL_BASE, offset);
219 }
220
221 static inline void
intctl_write(u_int offset,uint32_t val)222 intctl_write(u_int offset, uint32_t val)
223 {
224 *RA_IOREG_VADDR(RA_INTCTL_BASE, offset) = val;
225 }
226
227
228 void
evbmips_intr_init(void)229 evbmips_intr_init(void)
230 {
231 ipl_sr_map = ralink_ipl_sr_map;
232
233 for (int irq=0; irq < RA_IRQ_MAX; irq++) {
234 LIST_INIT(&ra_intrtab[irq].intr_list);
235 if (PIC_IRQ_P(irq)) {
236 evcnt_attach_dynamic(&ra_intrtab[irq].intr_evcnt,
237 EVCNT_TYPE_INTR, NULL, "pic",
238 ra_intr_names[irq]);
239 } else {
240 evcnt_attach_dynamic(&ra_intrtab[irq].intr_evcnt,
241 EVCNT_TYPE_INTR, NULL, "cpu0",
242 ra_intr_names[irq]);
243 }
244 }
245
246 /*
247 * make sure we start without any misc interrupts enabled,
248 * but the block enabled
249 */
250 intctl_write(RA_INTCTL_DISABLE, ~0);
251 intctl_write(RA_INTCTL_ENABLE, INT_GLOBAL_EN);
252
253 /*
254 * establish the low/high priority cpu interrupts.
255 * note here we pass the value of the priority as the argument
256 * so it is passed to ra_pic_intr() correctly.
257 */
258 ra_intr_establish(RA_IRQ_HIGH, ra_pic_intr,
259 (void *)1, 1);
260 ra_intr_establish(RA_IRQ_LOW, ra_pic_intr,
261 (void *)0, 0);
262 }
263
264
265 void *
ra_intr_establish(int intr,int (* func)(void *),void * arg,int priority)266 ra_intr_establish(int intr, int (*func)(void *), void *arg, int priority)
267 {
268 struct evbmips_intrhand *ih;
269
270 ih = kmem_alloc(sizeof(*ih), KM_SLEEP);
271 ih->ih_func = func;
272 ih->ih_arg = arg;
273 ih->ih_irq = intr;
274
275 const int s = splhigh();
276
277 LIST_INSERT_HEAD(&ra_intrtab[intr].intr_list, ih, ih_q);
278
279 if (PIC_IRQ_P(intr)) {
280 /* irq belongs to the PIC */
281 uint32_t r;
282 r = intctl_read(RA_INTCTL_TYPE);
283 r |= (priority << irq2bit[intr]);
284 intctl_write(RA_INTCTL_TYPE, r);
285 r = intctl_read(RA_INTCTL_ENABLE);
286 r |= (1 << irq2bit[intr]);
287 intctl_write(RA_INTCTL_ENABLE, r);
288 }
289
290 splx(s);
291
292 return ih;
293 }
294
295 void
ra_intr_disestablish(void * arg)296 ra_intr_disestablish(void *arg)
297 {
298 struct evbmips_intrhand * const ih = arg;
299
300 const int s = splhigh();
301
302 LIST_REMOVE(ih, ih_q);
303 if (PIC_IRQ_P(ih->ih_irq) &&
304 LIST_EMPTY(&ra_intrtab[ih->ih_irq].intr_list)) {
305 uint32_t r;
306 r = intctl_read(RA_INTCTL_DISABLE);
307 r &= ~(1 << irq2bit[ih->ih_irq]);
308 intctl_write(RA_INTCTL_DISABLE, r);
309 }
310
311 splx(s);
312
313 kmem_free(ih, sizeof(*ih));
314 }
315
316 /*
317 * ra_pic_intr - service PIC interrupts
318 *
319 * caller handles priority by the calling this function w/ PRI_HIGH first
320 */
321 static int
ra_pic_intr(void * arg)322 ra_pic_intr(void *arg)
323 {
324 const int priority = (intptr_t)arg;
325 const u_int off = (priority == 0) ?
326 RA_INTCTL_IRQ0STAT : RA_INTCTL_IRQ1STAT;
327 uint32_t pending = intctl_read(off);
328
329 while (pending != 0) {
330 const u_int bitno = 31 - __builtin_clz(pending);
331 pending ^= (1 << bitno);
332 const int irq = bit2irq[bitno];
333 KASSERT(PIC_IRQ_P(irq));
334 ra_intrtab[irq].intr_evcnt.ev_count++;
335 struct evbmips_intrhand *ih;
336 LIST_FOREACH(ih, &ra_intrtab[irq].intr_list, ih_q)
337 (*ih->ih_func)(ih->ih_arg);
338 }
339
340 return 1;
341 }
342
343 /*
344 * evbmips_iointr - process CPU interrupts
345 *
346 * we only see IRQ 4..0 here as IRQ 5 is handled
347 * in the generic MIPS code for the timer
348 */
349 void
evbmips_iointr(int ipl,uint32_t ipending,struct clockframe * cf)350 evbmips_iointr(int ipl, uint32_t ipending, struct clockframe *cf)
351 {
352 while (ipending != 0) {
353 const u_int bitno = 31 - __builtin_clz(ipending);
354 ipending ^= (1 << bitno);
355 const int irq = bitno - (31 - __builtin_clz(MIPS_INT_MASK_0));
356 KASSERT(!PIC_IRQ_P(irq));
357 ra_intrtab[irq].intr_evcnt.ev_count++;
358 struct evbmips_intrhand *ih;
359 LIST_FOREACH(ih, &ra_intrtab[irq].intr_list, ih_q)
360 (*ih->ih_func)(ih->ih_arg);
361 }
362 }
363