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 216 intctl_read(u_int offset) 217 { 218 return *RA_IOREG_VADDR(RA_INTCTL_BASE, offset); 219 } 220 221 static inline void 222 intctl_write(u_int offset, uint32_t val) 223 { 224 *RA_IOREG_VADDR(RA_INTCTL_BASE, offset) = val; 225 } 226 227 228 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 * 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 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 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 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