1 /* 2 * Copyright 2015 Andrew Turner. 3 * Copyright 2016 Svatopluk Kraus 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: 9 * 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 THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE 20 * 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 23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include "opt_platform.h" 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/bus.h> 37 #include <sys/cpuset.h> 38 #include <sys/kernel.h> 39 #include <sys/module.h> 40 #include <sys/proc.h> 41 #include <sys/rman.h> 42 #ifdef SMP 43 #include <sys/smp.h> 44 #endif 45 46 #include <machine/bus.h> 47 #include <machine/intr.h> 48 #include <machine/resource.h> 49 #ifdef SMP 50 #include <machine/smp.h> 51 #endif 52 53 #include <dev/ofw/ofw_bus_subr.h> 54 #include <dev/ofw/ofw_bus.h> 55 56 #ifdef INTRNG 57 #include "pic_if.h" 58 #else 59 #include <arm/broadcom/bcm2835/bcm2836.h> 60 61 #define ARM_LOCAL_BASE 0x40000000 62 #define ARM_LOCAL_SIZE 0x00001000 63 64 #define ARM_LOCAL_CONTROL 0x00 65 #define ARM_LOCAL_PRESCALER 0x08 66 #define PRESCALER_19_2 0x80000000 /* 19.2 MHz */ 67 #define ARM_LOCAL_INT_TIMER(n) (0x40 + (n) * 4) 68 #define ARM_LOCAL_INT_MAILBOX(n) (0x50 + (n) * 4) 69 #define ARM_LOCAL_INT_PENDING(n) (0x60 + (n) * 4) 70 #define INT_PENDING_MASK 0x011f 71 #define MAILBOX0_IRQ 4 72 #define MAILBOX0_IRQEN (1 << 0) 73 #endif 74 75 #ifdef INTRNG 76 #define BCM_LINTC_CONTROL_REG 0x00 77 #define BCM_LINTC_PRESCALER_REG 0x08 78 #define BCM_LINTC_GPU_ROUTING_REG 0x0c 79 #define BCM_LINTC_PMU_ROUTING_SET_REG 0x10 80 #define BCM_LINTC_PMU_ROUTING_CLR_REG 0x14 81 #define BCM_LINTC_TIMER_CFG_REG(n) (0x40 + (n) * 4) 82 #define BCM_LINTC_MBOX_CFG_REG(n) (0x50 + (n) * 4) 83 #define BCM_LINTC_PENDING_REG(n) (0x60 + (n) * 4) 84 #define BCM_LINTC_MBOX0_SET_REG(n) (0x80 + (n) * 16) 85 #define BCM_LINTC_MBOX1_SET_REG(n) (0x84 + (n) * 16) 86 #define BCM_LINTC_MBOX2_SET_REG(n) (0x88 + (n) * 16) 87 #define BCM_LINTC_MBOX3_SET_REG(n) (0x8C + (n) * 16) 88 #define BCM_LINTC_MBOX0_CLR_REG(n) (0xC0 + (n) * 16) 89 #define BCM_LINTC_MBOX1_CLR_REG(n) (0xC4 + (n) * 16) 90 #define BCM_LINTC_MBOX2_CLR_REG(n) (0xC8 + (n) * 16) 91 #define BCM_LINTC_MBOX3_CLR_REG(n) (0xCC + (n) * 16) 92 93 /* Prescaler Register */ 94 #define BCM_LINTC_PSR_19_2 0x80000000 /* 19.2 MHz */ 95 96 /* GPU Interrupt Routing Register */ 97 #define BCM_LINTC_GIRR_IRQ_CORE(n) (n) 98 #define BCM_LINTC_GIRR_FIQ_CORE(n) ((n) << 2) 99 100 /* PMU Interrupt Routing Register */ 101 #define BCM_LINTC_PIRR_IRQ_EN_CORE(n) (1 << (n)) 102 #define BCM_LINTC_PIRR_FIQ_EN_CORE(n) (1 << ((n) + 4)) 103 104 /* Timer Config Register */ 105 #define BCM_LINTC_TCR_IRQ_EN_TIMER(n) (1 << (n)) 106 #define BCM_LINTC_TCR_FIQ_EN_TIMER(n) (1 << ((n) + 4)) 107 108 /* MBOX Config Register */ 109 #define BCM_LINTC_MCR_IRQ_EN_MBOX(n) (1 << (n)) 110 #define BCM_LINTC_MCR_FIQ_EN_MBOX(n) (1 << ((n) + 4)) 111 112 #define BCM_LINTC_CNTPSIRQ_IRQ 0 113 #define BCM_LINTC_CNTPNSIRQ_IRQ 1 114 #define BCM_LINTC_CNTHPIRQ_IRQ 2 115 #define BCM_LINTC_CNTVIRQ_IRQ 3 116 #define BCM_LINTC_MBOX0_IRQ 4 117 #define BCM_LINTC_MBOX1_IRQ 5 118 #define BCM_LINTC_MBOX2_IRQ 6 119 #define BCM_LINTC_MBOX3_IRQ 7 120 #define BCM_LINTC_GPU_IRQ 8 121 #define BCM_LINTC_PMU_IRQ 9 122 #define BCM_LINTC_AXI_IRQ 10 123 #define BCM_LINTC_LTIMER_IRQ 11 124 125 #define BCM_LINTC_NIRQS 12 126 127 #define BCM_LINTC_TIMER0_IRQ BCM_LINTC_CNTPSIRQ_IRQ 128 #define BCM_LINTC_TIMER1_IRQ BCM_LINTC_CNTPNSIRQ_IRQ 129 #define BCM_LINTC_TIMER2_IRQ BCM_LINTC_CNTHPIRQ_IRQ 130 #define BCM_LINTC_TIMER3_IRQ BCM_LINTC_CNTVIRQ_IRQ 131 132 #define BCM_LINTC_TIMER0_IRQ_MASK (1 << BCM_LINTC_TIMER0_IRQ) 133 #define BCM_LINTC_TIMER1_IRQ_MASK (1 << BCM_LINTC_TIMER1_IRQ) 134 #define BCM_LINTC_TIMER2_IRQ_MASK (1 << BCM_LINTC_TIMER2_IRQ) 135 #define BCM_LINTC_TIMER3_IRQ_MASK (1 << BCM_LINTC_TIMER3_IRQ) 136 #define BCM_LINTC_MBOX0_IRQ_MASK (1 << BCM_LINTC_MBOX0_IRQ) 137 #define BCM_LINTC_GPU_IRQ_MASK (1 << BCM_LINTC_GPU_IRQ) 138 #define BCM_LINTC_PMU_IRQ_MASK (1 << BCM_LINTC_PMU_IRQ) 139 140 #define BCM_LINTC_UP_PENDING_MASK \ 141 (BCM_LINTC_TIMER0_IRQ_MASK | \ 142 BCM_LINTC_TIMER1_IRQ_MASK | \ 143 BCM_LINTC_TIMER2_IRQ_MASK | \ 144 BCM_LINTC_TIMER3_IRQ_MASK | \ 145 BCM_LINTC_GPU_IRQ_MASK | \ 146 BCM_LINTC_PMU_IRQ_MASK) 147 148 #define BCM_LINTC_SMP_PENDING_MASK \ 149 (BCM_LINTC_UP_PENDING_MASK | \ 150 BCM_LINTC_MBOX0_IRQ_MASK) 151 152 #ifdef SMP 153 #define BCM_LINTC_PENDING_MASK BCM_LINTC_SMP_PENDING_MASK 154 #else 155 #define BCM_LINTC_PENDING_MASK BCM_LINTC_UP_PENDING_MASK 156 #endif 157 158 struct bcm_lintc_irqsrc { 159 struct intr_irqsrc bli_isrc; 160 u_int bli_irq; 161 union { 162 u_int bli_mask; /* for timers */ 163 u_int bli_value; /* for GPU */ 164 }; 165 }; 166 167 struct bcm_lintc_softc { 168 device_t bls_dev; 169 struct mtx bls_mtx; 170 struct resource * bls_mem; 171 bus_space_tag_t bls_bst; 172 bus_space_handle_t bls_bsh; 173 struct bcm_lintc_irqsrc bls_isrcs[BCM_LINTC_NIRQS]; 174 }; 175 176 static struct bcm_lintc_softc *bcm_lintc_sc; 177 178 #ifdef SMP 179 #define BCM_LINTC_NIPIS 32 /* only mailbox 0 is used for IPI */ 180 CTASSERT(INTR_IPI_COUNT <= BCM_LINTC_NIPIS); 181 #endif 182 183 #define BCM_LINTC_LOCK(sc) mtx_lock_spin(&(sc)->bls_mtx) 184 #define BCM_LINTC_UNLOCK(sc) mtx_unlock_spin(&(sc)->bls_mtx) 185 #define BCM_LINTC_LOCK_INIT(sc) mtx_init(&(sc)->bls_mtx, \ 186 device_get_nameunit((sc)->bls_dev), "bmc_local_intc", MTX_SPIN) 187 #define BCM_LINTC_LOCK_DESTROY(sc) mtx_destroy(&(sc)->bls_mtx) 188 189 #define bcm_lintc_read_4(sc, reg) \ 190 bus_space_read_4((sc)->bls_bst, (sc)->bls_bsh, (reg)) 191 #define bcm_lintc_write_4(sc, reg, val) \ 192 bus_space_write_4((sc)->bls_bst, (sc)->bls_bsh, (reg), (val)) 193 194 static inline void 195 bcm_lintc_rwreg_clr(struct bcm_lintc_softc *sc, uint32_t reg, 196 uint32_t mask) 197 { 198 199 bcm_lintc_write_4(sc, reg, bcm_lintc_read_4(sc, reg) & ~mask); 200 } 201 202 static inline void 203 bcm_lintc_rwreg_set(struct bcm_lintc_softc *sc, uint32_t reg, 204 uint32_t mask) 205 { 206 207 bcm_lintc_write_4(sc, reg, bcm_lintc_read_4(sc, reg) | mask); 208 } 209 210 static void 211 bcm_lintc_timer_mask(struct bcm_lintc_softc *sc, struct bcm_lintc_irqsrc *bli) 212 { 213 cpuset_t *cpus; 214 uint32_t cpu; 215 216 cpus = &bli->bli_isrc.isrc_cpu; 217 218 BCM_LINTC_LOCK(sc); 219 for (cpu = 0; cpu < 4; cpu++) 220 if (CPU_ISSET(cpu, cpus)) 221 bcm_lintc_rwreg_clr(sc, BCM_LINTC_TIMER_CFG_REG(cpu), 222 bli->bli_mask); 223 BCM_LINTC_UNLOCK(sc); 224 } 225 226 static void 227 bcm_lintc_timer_unmask(struct bcm_lintc_softc *sc, struct bcm_lintc_irqsrc *bli) 228 { 229 cpuset_t *cpus; 230 uint32_t cpu; 231 232 cpus = &bli->bli_isrc.isrc_cpu; 233 234 BCM_LINTC_LOCK(sc); 235 for (cpu = 0; cpu < 4; cpu++) 236 if (CPU_ISSET(cpu, cpus)) 237 bcm_lintc_rwreg_set(sc, BCM_LINTC_TIMER_CFG_REG(cpu), 238 bli->bli_mask); 239 BCM_LINTC_UNLOCK(sc); 240 } 241 242 static inline void 243 bcm_lintc_gpu_mask(struct bcm_lintc_softc *sc, struct bcm_lintc_irqsrc *bli) 244 { 245 246 /* It's accessed just and only by one core. */ 247 bcm_lintc_write_4(sc, BCM_LINTC_GPU_ROUTING_REG, 0); 248 } 249 250 static inline void 251 bcm_lintc_gpu_unmask(struct bcm_lintc_softc *sc, struct bcm_lintc_irqsrc *bli) 252 { 253 254 /* It's accessed just and only by one core. */ 255 bcm_lintc_write_4(sc, BCM_LINTC_GPU_ROUTING_REG, bli->bli_value); 256 } 257 258 static inline void 259 bcm_lintc_pmu_mask(struct bcm_lintc_softc *sc, struct bcm_lintc_irqsrc *bli) 260 { 261 cpuset_t *cpus; 262 uint32_t cpu, mask; 263 264 mask = 0; 265 cpus = &bli->bli_isrc.isrc_cpu; 266 267 BCM_LINTC_LOCK(sc); 268 for (cpu = 0; cpu < 4; cpu++) 269 if (CPU_ISSET(cpu, cpus)) 270 mask |= BCM_LINTC_PIRR_IRQ_EN_CORE(cpu); 271 /* Write-clear register. */ 272 bcm_lintc_write_4(sc, BCM_LINTC_PMU_ROUTING_CLR_REG, mask); 273 BCM_LINTC_UNLOCK(sc); 274 } 275 276 static inline void 277 bcm_lintc_pmu_unmask(struct bcm_lintc_softc *sc, struct bcm_lintc_irqsrc *bli) 278 { 279 cpuset_t *cpus; 280 uint32_t cpu, mask; 281 282 mask = 0; 283 cpus = &bli->bli_isrc.isrc_cpu; 284 285 BCM_LINTC_LOCK(sc); 286 for (cpu = 0; cpu < 4; cpu++) 287 if (CPU_ISSET(cpu, cpus)) 288 mask |= BCM_LINTC_PIRR_IRQ_EN_CORE(cpu); 289 /* Write-set register. */ 290 bcm_lintc_write_4(sc, BCM_LINTC_PMU_ROUTING_SET_REG, mask); 291 BCM_LINTC_UNLOCK(sc); 292 } 293 294 static void 295 bcm_lintc_mask(struct bcm_lintc_softc *sc, struct bcm_lintc_irqsrc *bli) 296 { 297 298 switch (bli->bli_irq) { 299 case BCM_LINTC_TIMER0_IRQ: 300 case BCM_LINTC_TIMER1_IRQ: 301 case BCM_LINTC_TIMER2_IRQ: 302 case BCM_LINTC_TIMER3_IRQ: 303 bcm_lintc_timer_mask(sc, bli); 304 return; 305 case BCM_LINTC_MBOX0_IRQ: 306 case BCM_LINTC_MBOX1_IRQ: 307 case BCM_LINTC_MBOX2_IRQ: 308 case BCM_LINTC_MBOX3_IRQ: 309 return; 310 case BCM_LINTC_GPU_IRQ: 311 bcm_lintc_gpu_mask(sc, bli); 312 return; 313 case BCM_LINTC_PMU_IRQ: 314 bcm_lintc_pmu_mask(sc, bli); 315 return; 316 default: 317 panic("%s: not implemented for irq %u", __func__, bli->bli_irq); 318 } 319 } 320 321 static void 322 bcm_lintc_unmask(struct bcm_lintc_softc *sc, struct bcm_lintc_irqsrc *bli) 323 { 324 325 switch (bli->bli_irq) { 326 case BCM_LINTC_TIMER0_IRQ: 327 case BCM_LINTC_TIMER1_IRQ: 328 case BCM_LINTC_TIMER2_IRQ: 329 case BCM_LINTC_TIMER3_IRQ: 330 bcm_lintc_timer_unmask(sc, bli); 331 return; 332 case BCM_LINTC_MBOX0_IRQ: 333 case BCM_LINTC_MBOX1_IRQ: 334 case BCM_LINTC_MBOX2_IRQ: 335 case BCM_LINTC_MBOX3_IRQ: 336 return; 337 case BCM_LINTC_GPU_IRQ: 338 bcm_lintc_gpu_unmask(sc, bli); 339 return; 340 case BCM_LINTC_PMU_IRQ: 341 bcm_lintc_pmu_unmask(sc, bli); 342 return; 343 default: 344 panic("%s: not implemented for irq %u", __func__, bli->bli_irq); 345 } 346 } 347 348 #ifdef SMP 349 static inline void 350 bcm_lintc_ipi_write(struct bcm_lintc_softc *sc, cpuset_t cpus, u_int ipi) 351 { 352 u_int cpu; 353 uint32_t mask; 354 355 mask = 1 << ipi; 356 for (cpu = 0; cpu < mp_ncpus; cpu++) 357 if (CPU_ISSET(cpu, &cpus)) 358 bcm_lintc_write_4(sc, BCM_LINTC_MBOX0_SET_REG(cpu), 359 mask); 360 } 361 362 static inline void 363 bcm_lintc_ipi_dispatch(struct bcm_lintc_softc *sc, u_int cpu, 364 struct trapframe *tf) 365 { 366 u_int ipi; 367 uint32_t mask; 368 369 mask = bcm_lintc_read_4(sc, BCM_LINTC_MBOX0_CLR_REG(cpu)); 370 if (mask == 0) { 371 device_printf(sc->bls_dev, "Spurious ipi detected\n"); 372 return; 373 } 374 375 for (ipi = 0; mask != 0; mask >>= 1, ipi++) { 376 if ((mask & 0x01) == 0) 377 continue; 378 /* 379 * Clear an IPI before dispatching to not miss anyone 380 * and make sure that it's observed by everybody. 381 */ 382 bcm_lintc_write_4(sc, BCM_LINTC_MBOX0_CLR_REG(cpu), 1 << ipi); 383 dsb(); 384 intr_ipi_dispatch(ipi, tf); 385 } 386 } 387 #endif 388 389 static inline void 390 bcm_lintc_irq_dispatch(struct bcm_lintc_softc *sc, u_int irq, 391 struct trapframe *tf) 392 { 393 struct bcm_lintc_irqsrc *bli; 394 395 bli = &sc->bls_isrcs[irq]; 396 if (intr_isrc_dispatch(&bli->bli_isrc, tf) != 0) 397 device_printf(sc->bls_dev, "Stray irq %u detected\n", irq); 398 } 399 400 static int 401 bcm_lintc_intr(void *arg) 402 { 403 struct bcm_lintc_softc *sc; 404 u_int cpu; 405 uint32_t num, reg; 406 struct trapframe *tf; 407 408 sc = arg; 409 cpu = PCPU_GET(cpuid); 410 tf = curthread->td_intr_frame; 411 412 for (num = 0; ; num++) { 413 reg = bcm_lintc_read_4(sc, BCM_LINTC_PENDING_REG(cpu)); 414 if ((reg & BCM_LINTC_PENDING_MASK) == 0) 415 break; 416 #ifdef SMP 417 if (reg & BCM_LINTC_MBOX0_IRQ_MASK) 418 bcm_lintc_ipi_dispatch(sc, cpu, tf); 419 #endif 420 if (reg & BCM_LINTC_TIMER0_IRQ_MASK) 421 bcm_lintc_irq_dispatch(sc, BCM_LINTC_TIMER0_IRQ, tf); 422 if (reg & BCM_LINTC_TIMER1_IRQ_MASK) 423 bcm_lintc_irq_dispatch(sc, BCM_LINTC_TIMER1_IRQ, tf); 424 if (reg & BCM_LINTC_TIMER2_IRQ_MASK) 425 bcm_lintc_irq_dispatch(sc, BCM_LINTC_TIMER2_IRQ, tf); 426 if (reg & BCM_LINTC_TIMER3_IRQ_MASK) 427 bcm_lintc_irq_dispatch(sc, BCM_LINTC_TIMER3_IRQ, tf); 428 if (reg & BCM_LINTC_GPU_IRQ_MASK) 429 bcm_lintc_irq_dispatch(sc, BCM_LINTC_GPU_IRQ, tf); 430 if (reg & BCM_LINTC_PMU_IRQ_MASK) 431 bcm_lintc_irq_dispatch(sc, BCM_LINTC_PMU_IRQ, tf); 432 433 arm_irq_memory_barrier(0); /* XXX */ 434 } 435 reg &= ~BCM_LINTC_PENDING_MASK; 436 if (reg != 0) 437 device_printf(sc->bls_dev, "Unknown interrupt(s) %x\n", reg); 438 else if (num == 0) 439 device_printf(sc->bls_dev, "Spurious interrupt detected\n"); 440 441 return (FILTER_HANDLED); 442 } 443 444 static void 445 bcm_lintc_disable_intr(device_t dev, struct intr_irqsrc *isrc) 446 { 447 448 bcm_lintc_mask(device_get_softc(dev), (struct bcm_lintc_irqsrc *)isrc); 449 } 450 451 static void 452 bcm_lintc_enable_intr(device_t dev, struct intr_irqsrc *isrc) 453 { 454 struct bcm_lintc_irqsrc *bli = (struct bcm_lintc_irqsrc *)isrc; 455 456 arm_irq_memory_barrier(bli->bli_irq); 457 bcm_lintc_unmask(device_get_softc(dev), bli); 458 } 459 460 static int 461 bcm_lintc_map_intr(device_t dev, struct intr_map_data *data, 462 struct intr_irqsrc **isrcp) 463 { 464 struct intr_map_data_fdt *daf; 465 struct bcm_lintc_softc *sc; 466 467 if (data->type != INTR_MAP_DATA_FDT) 468 return (ENOTSUP); 469 470 daf = (struct intr_map_data_fdt *)data; 471 if (daf->ncells != 1 || daf->cells[0] >= BCM_LINTC_NIRQS) 472 return (EINVAL); 473 474 sc = device_get_softc(dev); 475 *isrcp = &sc->bls_isrcs[daf->cells[0]].bli_isrc; 476 return (0); 477 } 478 479 static void 480 bcm_lintc_pre_ithread(device_t dev, struct intr_irqsrc *isrc) 481 { 482 struct bcm_lintc_irqsrc *bli = (struct bcm_lintc_irqsrc *)isrc; 483 484 if (bli->bli_irq == BCM_LINTC_GPU_IRQ) 485 bcm_lintc_gpu_mask(device_get_softc(dev), bli); 486 else { 487 /* 488 * Handler for PPI interrupt does not make sense much unless 489 * there is one bound ithread for each core for it. Thus the 490 * interrupt can be masked on current core only while ithread 491 * bounded to this core ensures unmasking on the same core. 492 */ 493 panic ("%s: handlers are not supported", __func__); 494 } 495 } 496 497 static void 498 bcm_lintc_post_ithread(device_t dev, struct intr_irqsrc *isrc) 499 { 500 struct bcm_lintc_irqsrc *bli = (struct bcm_lintc_irqsrc *)isrc; 501 502 if (bli->bli_irq == BCM_LINTC_GPU_IRQ) 503 bcm_lintc_gpu_unmask(device_get_softc(dev), bli); 504 else { 505 /* See comment in bcm_lintc_pre_ithread(). */ 506 panic ("%s: handlers are not supported", __func__); 507 } 508 } 509 510 static void 511 bcm_lintc_post_filter(device_t dev, struct intr_irqsrc *isrc) 512 { 513 } 514 515 static int 516 bcm_lintc_setup_intr(device_t dev, struct intr_irqsrc *isrc, 517 struct resource *res, struct intr_map_data *data) 518 { 519 struct bcm_lintc_softc *sc; 520 521 if (isrc->isrc_handlers == 0 && isrc->isrc_flags & INTR_ISRCF_PPI) { 522 sc = device_get_softc(dev); 523 BCM_LINTC_LOCK(sc); 524 CPU_SET(PCPU_GET(cpuid), &isrc->isrc_cpu); 525 BCM_LINTC_UNLOCK(sc); 526 } 527 return (0); 528 } 529 530 #ifdef SMP 531 static void 532 bcm_lintc_init_rwreg_on_ap(struct bcm_lintc_softc *sc, u_int cpu, u_int irq, 533 uint32_t reg, uint32_t mask) 534 { 535 536 if (intr_isrc_init_on_cpu(&sc->bls_isrcs[irq].bli_isrc, cpu)) 537 bcm_lintc_rwreg_set(sc, reg, mask); 538 } 539 540 static void 541 bcm_lintc_init_pmu_on_ap(struct bcm_lintc_softc *sc, u_int cpu) 542 { 543 struct intr_irqsrc *isrc = &sc->bls_isrcs[BCM_LINTC_PMU_IRQ].bli_isrc; 544 545 if (intr_isrc_init_on_cpu(isrc, cpu)) { 546 /* Write-set register. */ 547 bcm_lintc_write_4(sc, BCM_LINTC_PMU_ROUTING_SET_REG, 548 BCM_LINTC_PIRR_IRQ_EN_CORE(cpu)); 549 } 550 } 551 552 static void 553 bcm_lintc_init_secondary(device_t dev) 554 { 555 u_int cpu; 556 struct bcm_lintc_softc *sc; 557 558 cpu = PCPU_GET(cpuid); 559 sc = device_get_softc(dev); 560 561 BCM_LINTC_LOCK(sc); 562 bcm_lintc_init_rwreg_on_ap(sc, cpu, BCM_LINTC_TIMER0_IRQ, 563 BCM_LINTC_TIMER_CFG_REG(cpu), BCM_LINTC_TCR_IRQ_EN_TIMER(0)); 564 bcm_lintc_init_rwreg_on_ap(sc, cpu, BCM_LINTC_TIMER1_IRQ, 565 BCM_LINTC_TIMER_CFG_REG(cpu), BCM_LINTC_TCR_IRQ_EN_TIMER(1)); 566 bcm_lintc_init_rwreg_on_ap(sc, cpu, BCM_LINTC_TIMER2_IRQ, 567 BCM_LINTC_TIMER_CFG_REG(cpu), BCM_LINTC_TCR_IRQ_EN_TIMER(2)); 568 bcm_lintc_init_rwreg_on_ap(sc, cpu, BCM_LINTC_TIMER3_IRQ, 569 BCM_LINTC_TIMER_CFG_REG(cpu), BCM_LINTC_TCR_IRQ_EN_TIMER(3)); 570 bcm_lintc_init_pmu_on_ap(sc, cpu); 571 BCM_LINTC_UNLOCK(sc); 572 } 573 574 static void 575 bcm_lintc_ipi_send(device_t dev, struct intr_irqsrc *isrc, cpuset_t cpus, 576 u_int ipi) 577 { 578 struct bcm_lintc_softc *sc = device_get_softc(dev); 579 580 KASSERT(isrc == &sc->bls_isrcs[BCM_LINTC_MBOX0_IRQ].bli_isrc, 581 ("%s: bad ISRC %p argument", __func__, isrc)); 582 bcm_lintc_ipi_write(sc, cpus, ipi); 583 } 584 585 static int 586 bcm_lintc_ipi_setup(device_t dev, u_int ipi, struct intr_irqsrc **isrcp) 587 { 588 struct bcm_lintc_softc *sc = device_get_softc(dev); 589 590 KASSERT(ipi < BCM_LINTC_NIPIS, ("%s: too high ipi %u", __func__, ipi)); 591 592 *isrcp = &sc->bls_isrcs[BCM_LINTC_MBOX0_IRQ].bli_isrc; 593 return (0); 594 } 595 #endif 596 597 static int 598 bcm_lintc_pic_attach(struct bcm_lintc_softc *sc) 599 { 600 struct bcm_lintc_irqsrc *bisrcs; 601 struct intr_pic *pic; 602 int error; 603 u_int flags; 604 uint32_t irq; 605 const char *name; 606 intptr_t xref; 607 608 bisrcs = sc->bls_isrcs; 609 name = device_get_nameunit(sc->bls_dev); 610 for (irq = 0; irq < BCM_LINTC_NIRQS; irq++) { 611 bisrcs[irq].bli_irq = irq; 612 switch (irq) { 613 case BCM_LINTC_TIMER0_IRQ: 614 bisrcs[irq].bli_mask = BCM_LINTC_TCR_IRQ_EN_TIMER(0); 615 flags = INTR_ISRCF_PPI; 616 break; 617 case BCM_LINTC_TIMER1_IRQ: 618 bisrcs[irq].bli_mask = BCM_LINTC_TCR_IRQ_EN_TIMER(1); 619 flags = INTR_ISRCF_PPI; 620 break; 621 case BCM_LINTC_TIMER2_IRQ: 622 bisrcs[irq].bli_mask = BCM_LINTC_TCR_IRQ_EN_TIMER(2); 623 flags = INTR_ISRCF_PPI; 624 break; 625 case BCM_LINTC_TIMER3_IRQ: 626 bisrcs[irq].bli_mask = BCM_LINTC_TCR_IRQ_EN_TIMER(3); 627 flags = INTR_ISRCF_PPI; 628 break; 629 case BCM_LINTC_MBOX0_IRQ: 630 case BCM_LINTC_MBOX1_IRQ: 631 case BCM_LINTC_MBOX2_IRQ: 632 case BCM_LINTC_MBOX3_IRQ: 633 bisrcs[irq].bli_value = 0; /* not used */ 634 flags = INTR_ISRCF_IPI; 635 break; 636 case BCM_LINTC_GPU_IRQ: 637 bisrcs[irq].bli_value = BCM_LINTC_GIRR_IRQ_CORE(0); 638 flags = 0; 639 break; 640 case BCM_LINTC_PMU_IRQ: 641 bisrcs[irq].bli_value = 0; /* not used */ 642 flags = INTR_ISRCF_PPI; 643 break; 644 default: 645 bisrcs[irq].bli_value = 0; /* not used */ 646 flags = 0; 647 break; 648 } 649 650 error = intr_isrc_register(&bisrcs[irq].bli_isrc, sc->bls_dev, 651 flags, "%s,%u", name, irq); 652 if (error != 0) 653 return (error); 654 } 655 656 xref = OF_xref_from_node(ofw_bus_get_node(sc->bls_dev)); 657 pic = intr_pic_register(sc->bls_dev, xref); 658 if (pic == NULL) 659 return (ENXIO); 660 661 return (intr_pic_claim_root(sc->bls_dev, xref, bcm_lintc_intr, sc, 0)); 662 } 663 664 static int 665 bcm_lintc_probe(device_t dev) 666 { 667 668 if (!ofw_bus_status_okay(dev)) 669 return (ENXIO); 670 671 if (!ofw_bus_is_compatible(dev, "brcm,bcm2836-l1-intc")) 672 return (ENXIO); 673 device_set_desc(dev, "BCM2836 Interrupt Controller"); 674 return (BUS_PROBE_DEFAULT); 675 } 676 677 static int 678 bcm_lintc_attach(device_t dev) 679 { 680 struct bcm_lintc_softc *sc; 681 int cpu, rid; 682 683 sc = device_get_softc(dev); 684 685 sc->bls_dev = dev; 686 if (bcm_lintc_sc != NULL) 687 return (ENXIO); 688 689 rid = 0; 690 sc->bls_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 691 RF_ACTIVE); 692 if (sc->bls_mem == NULL) { 693 device_printf(dev, "could not allocate memory resource\n"); 694 return (ENXIO); 695 } 696 697 sc->bls_bst = rman_get_bustag(sc->bls_mem); 698 sc->bls_bsh = rman_get_bushandle(sc->bls_mem); 699 700 bcm_lintc_write_4(sc, BCM_LINTC_CONTROL_REG, 0); 701 bcm_lintc_write_4(sc, BCM_LINTC_PRESCALER_REG, BCM_LINTC_PSR_19_2); 702 703 /* Disable all timers on all cores. */ 704 for (cpu = 0; cpu < 4; cpu++) 705 bcm_lintc_write_4(sc, BCM_LINTC_TIMER_CFG_REG(cpu), 0); 706 707 #ifdef SMP 708 /* Enable mailbox 0 on all cores used for IPI. */ 709 for (cpu = 0; cpu < 4; cpu++) 710 bcm_lintc_write_4(sc, BCM_LINTC_MBOX_CFG_REG(cpu), 711 BCM_LINTC_MCR_IRQ_EN_MBOX(0)); 712 #endif 713 714 if (bcm_lintc_pic_attach(sc) != 0) { 715 device_printf(dev, "could not attach PIC\n"); 716 return (ENXIO); 717 } 718 719 BCM_LINTC_LOCK_INIT(sc); 720 bcm_lintc_sc = sc; 721 return (0); 722 } 723 724 static device_method_t bcm_lintc_methods[] = { 725 DEVMETHOD(device_probe, bcm_lintc_probe), 726 DEVMETHOD(device_attach, bcm_lintc_attach), 727 728 DEVMETHOD(pic_disable_intr, bcm_lintc_disable_intr), 729 DEVMETHOD(pic_enable_intr, bcm_lintc_enable_intr), 730 DEVMETHOD(pic_map_intr, bcm_lintc_map_intr), 731 DEVMETHOD(pic_post_filter, bcm_lintc_post_filter), 732 DEVMETHOD(pic_post_ithread, bcm_lintc_post_ithread), 733 DEVMETHOD(pic_pre_ithread, bcm_lintc_pre_ithread), 734 DEVMETHOD(pic_setup_intr, bcm_lintc_setup_intr), 735 #ifdef SMP 736 DEVMETHOD(pic_init_secondary, bcm_lintc_init_secondary), 737 DEVMETHOD(pic_ipi_send, bcm_lintc_ipi_send), 738 DEVMETHOD(pic_ipi_setup, bcm_lintc_ipi_setup), 739 #endif 740 741 DEVMETHOD_END 742 }; 743 744 static driver_t bcm_lintc_driver = { 745 "local_intc", 746 bcm_lintc_methods, 747 sizeof(struct bcm_lintc_softc), 748 }; 749 750 static devclass_t bcm_lintc_devclass; 751 752 EARLY_DRIVER_MODULE(local_intc, simplebus, bcm_lintc_driver, bcm_lintc_devclass, 753 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); 754 #else 755 /* 756 * A driver for features of the bcm2836. 757 */ 758 759 struct bcm2836_softc { 760 device_t sc_dev; 761 struct resource *sc_mem; 762 }; 763 764 static device_identify_t bcm2836_identify; 765 static device_probe_t bcm2836_probe; 766 static device_attach_t bcm2836_attach; 767 768 struct bcm2836_softc *softc; 769 770 static void 771 bcm2836_identify(driver_t *driver, device_t parent) 772 { 773 774 if (BUS_ADD_CHILD(parent, 0, "bcm2836", -1) == NULL) 775 device_printf(parent, "add child failed\n"); 776 } 777 778 static int 779 bcm2836_probe(device_t dev) 780 { 781 782 if (softc != NULL) 783 return (ENXIO); 784 785 device_set_desc(dev, "Broadcom bcm2836"); 786 787 return (BUS_PROBE_DEFAULT); 788 } 789 790 static int 791 bcm2836_attach(device_t dev) 792 { 793 int i, rid; 794 795 softc = device_get_softc(dev); 796 softc->sc_dev = dev; 797 798 rid = 0; 799 softc->sc_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 800 ARM_LOCAL_BASE, ARM_LOCAL_BASE + ARM_LOCAL_SIZE, ARM_LOCAL_SIZE, 801 RF_ACTIVE); 802 if (softc->sc_mem == NULL) { 803 device_printf(dev, "could not allocate memory resource\n"); 804 return (ENXIO); 805 } 806 807 bus_write_4(softc->sc_mem, ARM_LOCAL_CONTROL, 0); 808 bus_write_4(softc->sc_mem, ARM_LOCAL_PRESCALER, PRESCALER_19_2); 809 810 for (i = 0; i < 4; i++) 811 bus_write_4(softc->sc_mem, ARM_LOCAL_INT_TIMER(i), 0); 812 813 for (i = 0; i < 4; i++) 814 bus_write_4(softc->sc_mem, ARM_LOCAL_INT_MAILBOX(i), 1); 815 816 return (0); 817 } 818 819 int 820 bcm2836_get_next_irq(int last_irq) 821 { 822 uint32_t reg; 823 int cpu; 824 int irq; 825 826 cpu = PCPU_GET(cpuid); 827 828 reg = bus_read_4(softc->sc_mem, ARM_LOCAL_INT_PENDING(cpu)); 829 reg &= INT_PENDING_MASK; 830 if (reg == 0) 831 return (-1); 832 833 irq = ffs(reg) - 1; 834 835 return (irq); 836 } 837 838 void 839 bcm2836_mask_irq(uintptr_t irq) 840 { 841 uint32_t reg; 842 #ifdef SMP 843 int cpu; 844 #endif 845 int i; 846 847 if (irq < MAILBOX0_IRQ) { 848 for (i = 0; i < 4; i++) { 849 reg = bus_read_4(softc->sc_mem, 850 ARM_LOCAL_INT_TIMER(i)); 851 reg &= ~(1 << irq); 852 bus_write_4(softc->sc_mem, 853 ARM_LOCAL_INT_TIMER(i), reg); 854 } 855 #ifdef SMP 856 } else if (irq == MAILBOX0_IRQ) { 857 /* Mailbox 0 for IPI */ 858 cpu = PCPU_GET(cpuid); 859 reg = bus_read_4(softc->sc_mem, ARM_LOCAL_INT_MAILBOX(cpu)); 860 reg &= ~MAILBOX0_IRQEN; 861 bus_write_4(softc->sc_mem, ARM_LOCAL_INT_MAILBOX(cpu), reg); 862 #endif 863 } 864 } 865 866 void 867 bcm2836_unmask_irq(uintptr_t irq) 868 { 869 uint32_t reg; 870 #ifdef SMP 871 int cpu; 872 #endif 873 int i; 874 875 if (irq < MAILBOX0_IRQ) { 876 for (i = 0; i < 4; i++) { 877 reg = bus_read_4(softc->sc_mem, 878 ARM_LOCAL_INT_TIMER(i)); 879 reg |= (1 << irq); 880 bus_write_4(softc->sc_mem, 881 ARM_LOCAL_INT_TIMER(i), reg); 882 } 883 #ifdef SMP 884 } else if (irq == MAILBOX0_IRQ) { 885 /* Mailbox 0 for IPI */ 886 cpu = PCPU_GET(cpuid); 887 reg = bus_read_4(softc->sc_mem, ARM_LOCAL_INT_MAILBOX(cpu)); 888 reg |= MAILBOX0_IRQEN; 889 bus_write_4(softc->sc_mem, ARM_LOCAL_INT_MAILBOX(cpu), reg); 890 #endif 891 } 892 } 893 894 static device_method_t bcm2836_methods[] = { 895 /* Device interface */ 896 DEVMETHOD(device_identify, bcm2836_identify), 897 DEVMETHOD(device_probe, bcm2836_probe), 898 DEVMETHOD(device_attach, bcm2836_attach), 899 900 DEVMETHOD_END 901 }; 902 903 static devclass_t bcm2836_devclass; 904 905 static driver_t bcm2836_driver = { 906 "bcm2836", 907 bcm2836_methods, 908 sizeof(struct bcm2836_softc), 909 }; 910 911 EARLY_DRIVER_MODULE(bcm2836, nexus, bcm2836_driver, bcm2836_devclass, 0, 0, 912 BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); 913 #endif 914