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 int error; 602 u_int flags; 603 uint32_t irq; 604 const char *name; 605 intptr_t xref; 606 607 bisrcs = sc->bls_isrcs; 608 name = device_get_nameunit(sc->bls_dev); 609 for (irq = 0; irq < BCM_LINTC_NIRQS; irq++) { 610 bisrcs[irq].bli_irq = irq; 611 switch (irq) { 612 case BCM_LINTC_TIMER0_IRQ: 613 bisrcs[irq].bli_mask = BCM_LINTC_TCR_IRQ_EN_TIMER(0); 614 flags = INTR_ISRCF_PPI; 615 break; 616 case BCM_LINTC_TIMER1_IRQ: 617 bisrcs[irq].bli_mask = BCM_LINTC_TCR_IRQ_EN_TIMER(1); 618 flags = INTR_ISRCF_PPI; 619 break; 620 case BCM_LINTC_TIMER2_IRQ: 621 bisrcs[irq].bli_mask = BCM_LINTC_TCR_IRQ_EN_TIMER(2); 622 flags = INTR_ISRCF_PPI; 623 break; 624 case BCM_LINTC_TIMER3_IRQ: 625 bisrcs[irq].bli_mask = BCM_LINTC_TCR_IRQ_EN_TIMER(3); 626 flags = INTR_ISRCF_PPI; 627 break; 628 case BCM_LINTC_MBOX0_IRQ: 629 case BCM_LINTC_MBOX1_IRQ: 630 case BCM_LINTC_MBOX2_IRQ: 631 case BCM_LINTC_MBOX3_IRQ: 632 bisrcs[irq].bli_value = 0; /* not used */ 633 flags = INTR_ISRCF_IPI; 634 break; 635 case BCM_LINTC_GPU_IRQ: 636 bisrcs[irq].bli_value = BCM_LINTC_GIRR_IRQ_CORE(0); 637 flags = 0; 638 break; 639 case BCM_LINTC_PMU_IRQ: 640 bisrcs[irq].bli_value = 0; /* not used */ 641 flags = INTR_ISRCF_PPI; 642 break; 643 default: 644 bisrcs[irq].bli_value = 0; /* not used */ 645 flags = 0; 646 break; 647 } 648 649 error = intr_isrc_register(&bisrcs[irq].bli_isrc, sc->bls_dev, 650 flags, "%s,%u", name, irq); 651 if (error != 0) 652 return (error); 653 } 654 655 xref = OF_xref_from_node(ofw_bus_get_node(sc->bls_dev)); 656 error = intr_pic_register(sc->bls_dev, xref); 657 if (error != 0) 658 return (error); 659 660 return (intr_pic_claim_root(sc->bls_dev, xref, bcm_lintc_intr, sc, 0)); 661 } 662 663 static int 664 bcm_lintc_probe(device_t dev) 665 { 666 667 if (!ofw_bus_status_okay(dev)) 668 return (ENXIO); 669 670 if (!ofw_bus_is_compatible(dev, "brcm,bcm2836-l1-intc")) 671 return (ENXIO); 672 device_set_desc(dev, "BCM2836 Interrupt Controller"); 673 return (BUS_PROBE_DEFAULT); 674 } 675 676 static int 677 bcm_lintc_attach(device_t dev) 678 { 679 struct bcm_lintc_softc *sc; 680 int cpu, rid; 681 682 sc = device_get_softc(dev); 683 684 sc->bls_dev = dev; 685 if (bcm_lintc_sc != NULL) 686 return (ENXIO); 687 688 rid = 0; 689 sc->bls_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 690 RF_ACTIVE); 691 if (sc->bls_mem == NULL) { 692 device_printf(dev, "could not allocate memory resource\n"); 693 return (ENXIO); 694 } 695 696 sc->bls_bst = rman_get_bustag(sc->bls_mem); 697 sc->bls_bsh = rman_get_bushandle(sc->bls_mem); 698 699 bcm_lintc_write_4(sc, BCM_LINTC_CONTROL_REG, 0); 700 bcm_lintc_write_4(sc, BCM_LINTC_PRESCALER_REG, BCM_LINTC_PSR_19_2); 701 702 /* Disable all timers on all cores. */ 703 for (cpu = 0; cpu < 4; cpu++) 704 bcm_lintc_write_4(sc, BCM_LINTC_TIMER_CFG_REG(cpu), 0); 705 706 #ifdef SMP 707 /* Enable mailbox 0 on all cores used for IPI. */ 708 for (cpu = 0; cpu < 4; cpu++) 709 bcm_lintc_write_4(sc, BCM_LINTC_MBOX_CFG_REG(cpu), 710 BCM_LINTC_MCR_IRQ_EN_MBOX(0)); 711 #endif 712 713 if (bcm_lintc_pic_attach(sc) != 0) { 714 device_printf(dev, "could not attach PIC\n"); 715 return (ENXIO); 716 } 717 718 BCM_LINTC_LOCK_INIT(sc); 719 bcm_lintc_sc = sc; 720 return (0); 721 } 722 723 static device_method_t bcm_lintc_methods[] = { 724 DEVMETHOD(device_probe, bcm_lintc_probe), 725 DEVMETHOD(device_attach, bcm_lintc_attach), 726 727 DEVMETHOD(pic_disable_intr, bcm_lintc_disable_intr), 728 DEVMETHOD(pic_enable_intr, bcm_lintc_enable_intr), 729 DEVMETHOD(pic_map_intr, bcm_lintc_map_intr), 730 DEVMETHOD(pic_post_filter, bcm_lintc_post_filter), 731 DEVMETHOD(pic_post_ithread, bcm_lintc_post_ithread), 732 DEVMETHOD(pic_pre_ithread, bcm_lintc_pre_ithread), 733 DEVMETHOD(pic_setup_intr, bcm_lintc_setup_intr), 734 #ifdef SMP 735 DEVMETHOD(pic_init_secondary, bcm_lintc_init_secondary), 736 DEVMETHOD(pic_ipi_send, bcm_lintc_ipi_send), 737 DEVMETHOD(pic_ipi_setup, bcm_lintc_ipi_setup), 738 #endif 739 740 DEVMETHOD_END 741 }; 742 743 static driver_t bcm_lintc_driver = { 744 "local_intc", 745 bcm_lintc_methods, 746 sizeof(struct bcm_lintc_softc), 747 }; 748 749 static devclass_t bcm_lintc_devclass; 750 751 EARLY_DRIVER_MODULE(local_intc, simplebus, bcm_lintc_driver, bcm_lintc_devclass, 752 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); 753 #else 754 /* 755 * A driver for features of the bcm2836. 756 */ 757 758 struct bcm2836_softc { 759 device_t sc_dev; 760 struct resource *sc_mem; 761 }; 762 763 static device_identify_t bcm2836_identify; 764 static device_probe_t bcm2836_probe; 765 static device_attach_t bcm2836_attach; 766 767 struct bcm2836_softc *softc; 768 769 static void 770 bcm2836_identify(driver_t *driver, device_t parent) 771 { 772 773 if (BUS_ADD_CHILD(parent, 0, "bcm2836", -1) == NULL) 774 device_printf(parent, "add child failed\n"); 775 } 776 777 static int 778 bcm2836_probe(device_t dev) 779 { 780 781 if (softc != NULL) 782 return (ENXIO); 783 784 device_set_desc(dev, "Broadcom bcm2836"); 785 786 return (BUS_PROBE_DEFAULT); 787 } 788 789 static int 790 bcm2836_attach(device_t dev) 791 { 792 int i, rid; 793 794 softc = device_get_softc(dev); 795 softc->sc_dev = dev; 796 797 rid = 0; 798 softc->sc_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 799 ARM_LOCAL_BASE, ARM_LOCAL_BASE + ARM_LOCAL_SIZE, ARM_LOCAL_SIZE, 800 RF_ACTIVE); 801 if (softc->sc_mem == NULL) { 802 device_printf(dev, "could not allocate memory resource\n"); 803 return (ENXIO); 804 } 805 806 bus_write_4(softc->sc_mem, ARM_LOCAL_CONTROL, 0); 807 bus_write_4(softc->sc_mem, ARM_LOCAL_PRESCALER, PRESCALER_19_2); 808 809 for (i = 0; i < 4; i++) 810 bus_write_4(softc->sc_mem, ARM_LOCAL_INT_TIMER(i), 0); 811 812 for (i = 0; i < 4; i++) 813 bus_write_4(softc->sc_mem, ARM_LOCAL_INT_MAILBOX(i), 1); 814 815 return (0); 816 } 817 818 int 819 bcm2836_get_next_irq(int last_irq) 820 { 821 uint32_t reg; 822 int cpu; 823 int irq; 824 825 cpu = PCPU_GET(cpuid); 826 827 reg = bus_read_4(softc->sc_mem, ARM_LOCAL_INT_PENDING(cpu)); 828 reg &= INT_PENDING_MASK; 829 if (reg == 0) 830 return (-1); 831 832 irq = ffs(reg) - 1; 833 834 return (irq); 835 } 836 837 void 838 bcm2836_mask_irq(uintptr_t irq) 839 { 840 uint32_t reg; 841 #ifdef SMP 842 int cpu; 843 #endif 844 int i; 845 846 if (irq < MAILBOX0_IRQ) { 847 for (i = 0; i < 4; i++) { 848 reg = bus_read_4(softc->sc_mem, 849 ARM_LOCAL_INT_TIMER(i)); 850 reg &= ~(1 << irq); 851 bus_write_4(softc->sc_mem, 852 ARM_LOCAL_INT_TIMER(i), reg); 853 } 854 #ifdef SMP 855 } else if (irq == MAILBOX0_IRQ) { 856 /* Mailbox 0 for IPI */ 857 cpu = PCPU_GET(cpuid); 858 reg = bus_read_4(softc->sc_mem, ARM_LOCAL_INT_MAILBOX(cpu)); 859 reg &= ~MAILBOX0_IRQEN; 860 bus_write_4(softc->sc_mem, ARM_LOCAL_INT_MAILBOX(cpu), reg); 861 #endif 862 } 863 } 864 865 void 866 bcm2836_unmask_irq(uintptr_t irq) 867 { 868 uint32_t reg; 869 #ifdef SMP 870 int cpu; 871 #endif 872 int i; 873 874 if (irq < MAILBOX0_IRQ) { 875 for (i = 0; i < 4; i++) { 876 reg = bus_read_4(softc->sc_mem, 877 ARM_LOCAL_INT_TIMER(i)); 878 reg |= (1 << irq); 879 bus_write_4(softc->sc_mem, 880 ARM_LOCAL_INT_TIMER(i), reg); 881 } 882 #ifdef SMP 883 } else if (irq == MAILBOX0_IRQ) { 884 /* Mailbox 0 for IPI */ 885 cpu = PCPU_GET(cpuid); 886 reg = bus_read_4(softc->sc_mem, ARM_LOCAL_INT_MAILBOX(cpu)); 887 reg |= MAILBOX0_IRQEN; 888 bus_write_4(softc->sc_mem, ARM_LOCAL_INT_MAILBOX(cpu), reg); 889 #endif 890 } 891 } 892 893 static device_method_t bcm2836_methods[] = { 894 /* Device interface */ 895 DEVMETHOD(device_identify, bcm2836_identify), 896 DEVMETHOD(device_probe, bcm2836_probe), 897 DEVMETHOD(device_attach, bcm2836_attach), 898 899 DEVMETHOD_END 900 }; 901 902 static devclass_t bcm2836_devclass; 903 904 static driver_t bcm2836_driver = { 905 "bcm2836", 906 bcm2836_methods, 907 sizeof(struct bcm2836_softc), 908 }; 909 910 EARLY_DRIVER_MODULE(bcm2836, nexus, bcm2836_driver, bcm2836_devclass, 0, 0, 911 BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); 912 #endif 913