gic.c revision 299117
1/*- 2 * Copyright (c) 2011 The FreeBSD Foundation 3 * All rights reserved. 4 * 5 * Developed by Damjan Marion <damjan.marion@gmail.com> 6 * 7 * Based on OMAP4 GIC code by Ben Gray 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of the company nor the name of the author may be used to 18 * endorse or promote products derived from this software without specific 19 * prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#include <sys/cdefs.h> 35__FBSDID("$FreeBSD: head/sys/arm/arm/gic.c 299117 2016-05-05 13:31:19Z skra $"); 36 37#include "opt_platform.h" 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/bus.h> 42#include <sys/kernel.h> 43#include <sys/ktr.h> 44#include <sys/module.h> 45#include <sys/malloc.h> 46#include <sys/rman.h> 47#include <sys/pcpu.h> 48#include <sys/proc.h> 49#include <sys/cpuset.h> 50#include <sys/lock.h> 51#include <sys/mutex.h> 52#include <sys/smp.h> 53#ifdef INTRNG 54#include <sys/sched.h> 55#endif 56#include <machine/bus.h> 57#include <machine/intr.h> 58#include <machine/smp.h> 59 60#include <dev/fdt/fdt_common.h> 61#include <dev/ofw/openfirm.h> 62#include <dev/ofw/ofw_bus.h> 63#include <dev/ofw/ofw_bus_subr.h> 64 65#ifdef INTRNG 66#include "pic_if.h" 67#endif 68 69#define GIC_DEBUG_SPURIOUS 70 71/* We are using GICv2 register naming */ 72 73/* Distributor Registers */ 74#define GICD_CTLR 0x000 /* v1 ICDDCR */ 75#define GICD_TYPER 0x004 /* v1 ICDICTR */ 76#define GICD_IIDR 0x008 /* v1 ICDIIDR */ 77#define GICD_IGROUPR(n) (0x0080 + ((n) * 4)) /* v1 ICDISER */ 78#define GICD_ISENABLER(n) (0x0100 + ((n) * 4)) /* v1 ICDISER */ 79#define GICD_ICENABLER(n) (0x0180 + ((n) * 4)) /* v1 ICDICER */ 80#define GICD_ISPENDR(n) (0x0200 + ((n) * 4)) /* v1 ICDISPR */ 81#define GICD_ICPENDR(n) (0x0280 + ((n) * 4)) /* v1 ICDICPR */ 82#define GICD_ICACTIVER(n) (0x0380 + ((n) * 4)) /* v1 ICDABR */ 83#define GICD_IPRIORITYR(n) (0x0400 + ((n) * 4)) /* v1 ICDIPR */ 84#define GICD_ITARGETSR(n) (0x0800 + ((n) * 4)) /* v1 ICDIPTR */ 85#define GICD_ICFGR(n) (0x0C00 + ((n) * 4)) /* v1 ICDICFR */ 86#define GICD_SGIR(n) (0x0F00 + ((n) * 4)) /* v1 ICDSGIR */ 87#define GICD_SGI_TARGET_SHIFT 16 88 89/* CPU Registers */ 90#define GICC_CTLR 0x0000 /* v1 ICCICR */ 91#define GICC_PMR 0x0004 /* v1 ICCPMR */ 92#define GICC_BPR 0x0008 /* v1 ICCBPR */ 93#define GICC_IAR 0x000C /* v1 ICCIAR */ 94#define GICC_EOIR 0x0010 /* v1 ICCEOIR */ 95#define GICC_RPR 0x0014 /* v1 ICCRPR */ 96#define GICC_HPPIR 0x0018 /* v1 ICCHPIR */ 97#define GICC_ABPR 0x001C /* v1 ICCABPR */ 98#define GICC_IIDR 0x00FC /* v1 ICCIIDR*/ 99 100#define GIC_FIRST_SGI 0 /* Irqs 0-15 are SGIs/IPIs. */ 101#define GIC_LAST_SGI 15 102#define GIC_FIRST_PPI 16 /* Irqs 16-31 are private (per */ 103#define GIC_LAST_PPI 31 /* core) peripheral interrupts. */ 104#define GIC_FIRST_SPI 32 /* Irqs 32+ are shared peripherals. */ 105 106/* First bit is a polarity bit (0 - low, 1 - high) */ 107#define GICD_ICFGR_POL_LOW (0 << 0) 108#define GICD_ICFGR_POL_HIGH (1 << 0) 109#define GICD_ICFGR_POL_MASK 0x1 110/* Second bit is a trigger bit (0 - level, 1 - edge) */ 111#define GICD_ICFGR_TRIG_LVL (0 << 1) 112#define GICD_ICFGR_TRIG_EDGE (1 << 1) 113#define GICD_ICFGR_TRIG_MASK 0x2 114 115#ifndef GIC_DEFAULT_ICFGR_INIT 116#define GIC_DEFAULT_ICFGR_INIT 0x00000000 117#endif 118 119#ifdef INTRNG 120struct gic_irqsrc { 121 struct intr_irqsrc gi_isrc; 122 uint32_t gi_irq; 123 enum intr_polarity gi_pol; 124 enum intr_trigger gi_trig; 125#define GI_FLAG_EARLY_EOI (1 << 0) 126 u_int gi_flags; 127}; 128 129static u_int gic_irq_cpu; 130static int arm_gic_intr(void *); 131static int arm_gic_bind_intr(device_t dev, struct intr_irqsrc *isrc); 132 133#ifdef SMP 134static u_int sgi_to_ipi[GIC_LAST_SGI - GIC_FIRST_SGI + 1]; 135static u_int sgi_first_unused = GIC_FIRST_SGI; 136#endif 137#endif 138 139#ifdef INTRNG 140struct arm_gic_range { 141 uint64_t bus; 142 uint64_t host; 143 uint64_t size; 144}; 145 146struct arm_gic_devinfo { 147 struct ofw_bus_devinfo obdinfo; 148 struct resource_list rl; 149}; 150#endif 151 152struct arm_gic_softc { 153 device_t gic_dev; 154#ifdef INTRNG 155 void * gic_intrhand; 156 struct gic_irqsrc * gic_irqs; 157#endif 158 struct resource * gic_res[3]; 159 bus_space_tag_t gic_c_bst; 160 bus_space_tag_t gic_d_bst; 161 bus_space_handle_t gic_c_bsh; 162 bus_space_handle_t gic_d_bsh; 163 uint8_t ver; 164 struct mtx mutex; 165 uint32_t nirqs; 166#ifdef GIC_DEBUG_SPURIOUS 167 uint32_t last_irq[MAXCPU]; 168#endif 169 170#ifdef INTRNG 171 /* FDT child data */ 172 pcell_t addr_cells; 173 pcell_t size_cells; 174 int nranges; 175 struct arm_gic_range * ranges; 176#endif 177}; 178 179#ifdef INTRNG 180#define GIC_INTR_ISRC(sc, irq) (&sc->gic_irqs[irq].gi_isrc) 181#endif 182 183static struct resource_spec arm_gic_spec[] = { 184 { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* Distributor registers */ 185 { SYS_RES_MEMORY, 1, RF_ACTIVE }, /* CPU Interrupt Intf. registers */ 186#ifdef INTRNG 187 { SYS_RES_IRQ, 0, RF_ACTIVE | RF_OPTIONAL }, /* Parent interrupt */ 188#endif 189 { -1, 0 } 190}; 191 192static u_int arm_gic_map[MAXCPU]; 193 194static struct arm_gic_softc *gic_sc = NULL; 195 196#define gic_c_read_4(_sc, _reg) \ 197 bus_space_read_4((_sc)->gic_c_bst, (_sc)->gic_c_bsh, (_reg)) 198#define gic_c_write_4(_sc, _reg, _val) \ 199 bus_space_write_4((_sc)->gic_c_bst, (_sc)->gic_c_bsh, (_reg), (_val)) 200#define gic_d_read_4(_sc, _reg) \ 201 bus_space_read_4((_sc)->gic_d_bst, (_sc)->gic_d_bsh, (_reg)) 202#define gic_d_write_1(_sc, _reg, _val) \ 203 bus_space_write_1((_sc)->gic_d_bst, (_sc)->gic_d_bsh, (_reg), (_val)) 204#define gic_d_write_4(_sc, _reg, _val) \ 205 bus_space_write_4((_sc)->gic_d_bst, (_sc)->gic_d_bsh, (_reg), (_val)) 206 207#ifndef INTRNG 208static int gic_config_irq(int irq, enum intr_trigger trig, 209 enum intr_polarity pol); 210static void gic_post_filter(void *); 211#endif 212 213static struct ofw_compat_data compat_data[] = { 214 {"arm,gic", true}, /* Non-standard, used in FreeBSD dts. */ 215 {"arm,gic-400", true}, 216 {"arm,cortex-a15-gic", true}, 217 {"arm,cortex-a9-gic", true}, 218 {"arm,cortex-a7-gic", true}, 219 {"arm,arm11mp-gic", true}, 220 {"brcm,brahma-b15-gic", true}, 221 {"qcom,msm-qgic2", true}, 222 {NULL, false} 223}; 224 225static int 226arm_gic_probe(device_t dev) 227{ 228 229 if (!ofw_bus_status_okay(dev)) 230 return (ENXIO); 231 232 if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) 233 return (ENXIO); 234 device_set_desc(dev, "ARM Generic Interrupt Controller"); 235 return (BUS_PROBE_DEFAULT); 236} 237 238#ifdef INTRNG 239static inline void 240gic_irq_unmask(struct arm_gic_softc *sc, u_int irq) 241{ 242 243 gic_d_write_4(sc, GICD_ISENABLER(irq >> 5), (1UL << (irq & 0x1F))); 244} 245 246static inline void 247gic_irq_mask(struct arm_gic_softc *sc, u_int irq) 248{ 249 250 gic_d_write_4(sc, GICD_ICENABLER(irq >> 5), (1UL << (irq & 0x1F))); 251} 252#endif 253 254static uint8_t 255gic_cpu_mask(struct arm_gic_softc *sc) 256{ 257 uint32_t mask; 258 int i; 259 260 /* Read the current cpuid mask by reading ITARGETSR{0..7} */ 261 for (i = 0; i < 8; i++) { 262 mask = gic_d_read_4(sc, GICD_ITARGETSR(i)); 263 if (mask != 0) 264 break; 265 } 266 /* No mask found, assume we are on CPU interface 0 */ 267 if (mask == 0) 268 return (1); 269 270 /* Collect the mask in the lower byte */ 271 mask |= mask >> 16; 272 mask |= mask >> 8; 273 274 return (mask); 275} 276 277#ifdef SMP 278#ifdef INTRNG 279static void 280arm_gic_init_secondary(device_t dev) 281{ 282 struct arm_gic_softc *sc = device_get_softc(dev); 283 u_int irq, cpu; 284 285 /* Set the mask so we can find this CPU to send it IPIs */ 286 cpu = PCPU_GET(cpuid); 287 arm_gic_map[cpu] = gic_cpu_mask(sc); 288 289 for (irq = 0; irq < sc->nirqs; irq += 4) 290 gic_d_write_4(sc, GICD_IPRIORITYR(irq >> 2), 0); 291 292 /* Set all the interrupts to be in Group 0 (secure) */ 293 for (irq = 0; irq < sc->nirqs; irq += 32) { 294 gic_d_write_4(sc, GICD_IGROUPR(irq >> 5), 0); 295 } 296 297 /* Enable CPU interface */ 298 gic_c_write_4(sc, GICC_CTLR, 1); 299 300 /* Set priority mask register. */ 301 gic_c_write_4(sc, GICC_PMR, 0xff); 302 303 /* Enable interrupt distribution */ 304 gic_d_write_4(sc, GICD_CTLR, 0x01); 305 306 /* Unmask attached SGI interrupts. */ 307 for (irq = GIC_FIRST_SGI; irq <= GIC_LAST_SGI; irq++) 308 if (intr_isrc_init_on_cpu(GIC_INTR_ISRC(sc, irq), cpu)) 309 gic_irq_unmask(sc, irq); 310 311 /* Unmask attached PPI interrupts. */ 312 for (irq = GIC_FIRST_PPI; irq <= GIC_LAST_PPI; irq++) 313 if (intr_isrc_init_on_cpu(GIC_INTR_ISRC(sc, irq), cpu)) 314 gic_irq_unmask(sc, irq); 315} 316#else 317static void 318arm_gic_init_secondary(device_t dev) 319{ 320 struct arm_gic_softc *sc = device_get_softc(dev); 321 int i; 322 323 /* Set the mask so we can find this CPU to send it IPIs */ 324 arm_gic_map[PCPU_GET(cpuid)] = gic_cpu_mask(sc); 325 326 for (i = 0; i < sc->nirqs; i += 4) 327 gic_d_write_4(sc, GICD_IPRIORITYR(i >> 2), 0); 328 329 /* Set all the interrupts to be in Group 0 (secure) */ 330 for (i = 0; i < sc->nirqs; i += 32) { 331 gic_d_write_4(sc, GICD_IGROUPR(i >> 5), 0); 332 } 333 334 /* Enable CPU interface */ 335 gic_c_write_4(sc, GICC_CTLR, 1); 336 337 /* Set priority mask register. */ 338 gic_c_write_4(sc, GICC_PMR, 0xff); 339 340 /* Enable interrupt distribution */ 341 gic_d_write_4(sc, GICD_CTLR, 0x01); 342 343 /* 344 * Activate the timer interrupts: virtual, secure, and non-secure. 345 */ 346 gic_d_write_4(sc, GICD_ISENABLER(27 >> 5), (1UL << (27 & 0x1F))); 347 gic_d_write_4(sc, GICD_ISENABLER(29 >> 5), (1UL << (29 & 0x1F))); 348 gic_d_write_4(sc, GICD_ISENABLER(30 >> 5), (1UL << (30 & 0x1F))); 349} 350#endif /* INTRNG */ 351#endif /* SMP */ 352 353#ifndef INTRNG 354int 355gic_decode_fdt(phandle_t iparent, pcell_t *intr, int *interrupt, 356 int *trig, int *pol) 357{ 358 static u_int num_intr_cells; 359 static phandle_t self; 360 struct ofw_compat_data *ocd; 361 362 if (self == 0) { 363 for (ocd = compat_data; ocd->ocd_str != NULL; ocd++) { 364 if (fdt_is_compatible(iparent, ocd->ocd_str)) { 365 self = iparent; 366 break; 367 } 368 } 369 } 370 if (self != iparent) 371 return (ENXIO); 372 373 if (num_intr_cells == 0) { 374 if (OF_searchencprop(OF_node_from_xref(iparent), 375 "#interrupt-cells", &num_intr_cells, 376 sizeof(num_intr_cells)) == -1) { 377 num_intr_cells = 1; 378 } 379 } 380 381 if (num_intr_cells == 1) { 382 *interrupt = fdt32_to_cpu(intr[0]); 383 *trig = INTR_TRIGGER_CONFORM; 384 *pol = INTR_POLARITY_CONFORM; 385 } else { 386 if (fdt32_to_cpu(intr[0]) == 0) 387 *interrupt = fdt32_to_cpu(intr[1]) + GIC_FIRST_SPI; 388 else 389 *interrupt = fdt32_to_cpu(intr[1]) + GIC_FIRST_PPI; 390 /* 391 * In intr[2], bits[3:0] are trigger type and level flags. 392 * 1 = low-to-high edge triggered 393 * 2 = high-to-low edge triggered 394 * 4 = active high level-sensitive 395 * 8 = active low level-sensitive 396 * The hardware only supports active-high-level or rising-edge 397 * for SPIs 398 */ 399 if (*interrupt >= GIC_FIRST_SPI && 400 fdt32_to_cpu(intr[2]) & 0x0a) { 401 printf("unsupported trigger/polarity configuration " 402 "0x%02x\n", fdt32_to_cpu(intr[2]) & 0x0f); 403 } 404 *pol = INTR_POLARITY_CONFORM; 405 if (fdt32_to_cpu(intr[2]) & 0x03) 406 *trig = INTR_TRIGGER_EDGE; 407 else 408 *trig = INTR_TRIGGER_LEVEL; 409 } 410 return (0); 411} 412#endif 413 414#ifdef INTRNG 415static inline intptr_t 416gic_xref(device_t dev) 417{ 418#ifdef FDT 419 return (OF_xref_from_node(ofw_bus_get_node(dev))); 420#else 421 return (0); 422#endif 423} 424 425static int 426arm_gic_register_isrcs(struct arm_gic_softc *sc, uint32_t num) 427{ 428 int error; 429 uint32_t irq; 430 struct gic_irqsrc *irqs; 431 struct intr_irqsrc *isrc; 432 const char *name; 433 434 irqs = malloc(num * sizeof(struct gic_irqsrc), M_DEVBUF, 435 M_WAITOK | M_ZERO); 436 437 name = device_get_nameunit(sc->gic_dev); 438 for (irq = 0; irq < num; irq++) { 439 irqs[irq].gi_irq = irq; 440 irqs[irq].gi_pol = INTR_POLARITY_CONFORM; 441 irqs[irq].gi_trig = INTR_TRIGGER_CONFORM; 442 443 isrc = &irqs[irq].gi_isrc; 444 if (irq <= GIC_LAST_SGI) { 445 error = intr_isrc_register(isrc, sc->gic_dev, 446 INTR_ISRCF_IPI, "%s,i%u", name, irq - GIC_FIRST_SGI); 447 } else if (irq <= GIC_LAST_PPI) { 448 error = intr_isrc_register(isrc, sc->gic_dev, 449 INTR_ISRCF_PPI, "%s,p%u", name, irq - GIC_FIRST_PPI); 450 } else { 451 error = intr_isrc_register(isrc, sc->gic_dev, 0, 452 "%s,s%u", name, irq - GIC_FIRST_SPI); 453 } 454 if (error != 0) { 455 /* XXX call intr_isrc_deregister() */ 456 free(irqs, M_DEVBUF); 457 return (error); 458 } 459 } 460 sc->gic_irqs = irqs; 461 sc->nirqs = num; 462 return (0); 463} 464 465static int 466arm_gic_fill_ranges(phandle_t node, struct arm_gic_softc *sc) 467{ 468 pcell_t host_cells; 469 cell_t *base_ranges; 470 ssize_t nbase_ranges; 471 int i, j, k; 472 473 host_cells = 1; 474 OF_getencprop(OF_parent(node), "#address-cells", &host_cells, 475 sizeof(host_cells)); 476 sc->addr_cells = 2; 477 OF_getencprop(node, "#address-cells", &sc->addr_cells, 478 sizeof(sc->addr_cells)); 479 sc->size_cells = 2; 480 OF_getencprop(node, "#size-cells", &sc->size_cells, 481 sizeof(sc->size_cells)); 482 483 nbase_ranges = OF_getproplen(node, "ranges"); 484 if (nbase_ranges < 0) 485 return (-1); 486 sc->nranges = nbase_ranges / sizeof(cell_t) / 487 (sc->addr_cells + host_cells + sc->size_cells); 488 if (sc->nranges == 0) 489 return (0); 490 491 sc->ranges = malloc(sc->nranges * sizeof(sc->ranges[0]), 492 M_DEVBUF, M_WAITOK); 493 base_ranges = malloc(nbase_ranges, M_DEVBUF, M_WAITOK); 494 OF_getencprop(node, "ranges", base_ranges, nbase_ranges); 495 496 for (i = 0, j = 0; i < sc->nranges; i++) { 497 sc->ranges[i].bus = 0; 498 for (k = 0; k < sc->addr_cells; k++) { 499 sc->ranges[i].bus <<= 32; 500 sc->ranges[i].bus |= base_ranges[j++]; 501 } 502 sc->ranges[i].host = 0; 503 for (k = 0; k < host_cells; k++) { 504 sc->ranges[i].host <<= 32; 505 sc->ranges[i].host |= base_ranges[j++]; 506 } 507 sc->ranges[i].size = 0; 508 for (k = 0; k < sc->size_cells; k++) { 509 sc->ranges[i].size <<= 32; 510 sc->ranges[i].size |= base_ranges[j++]; 511 } 512 } 513 514 free(base_ranges, M_DEVBUF); 515 return (sc->nranges); 516} 517 518static bool 519arm_gic_add_children(device_t dev) 520{ 521 struct arm_gic_softc *sc; 522 struct arm_gic_devinfo *dinfo; 523 phandle_t child, node; 524 device_t cdev; 525 526 sc = device_get_softc(dev); 527 node = ofw_bus_get_node(dev); 528 529 /* If we have no children don't probe for them */ 530 child = OF_child(node); 531 if (child == 0) 532 return (false); 533 534 if (arm_gic_fill_ranges(node, sc) < 0) { 535 device_printf(dev, "Have a child, but no ranges\n"); 536 return (false); 537 } 538 539 for (; child != 0; child = OF_peer(child)) { 540 dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_WAITOK | M_ZERO); 541 542 if (ofw_bus_gen_setup_devinfo(&dinfo->obdinfo, child) != 0) { 543 free(dinfo, M_DEVBUF); 544 continue; 545 } 546 547 resource_list_init(&dinfo->rl); 548 ofw_bus_reg_to_rl(dev, child, sc->addr_cells, 549 sc->size_cells, &dinfo->rl); 550 551 cdev = device_add_child(dev, NULL, -1); 552 if (cdev == NULL) { 553 device_printf(dev, "<%s>: device_add_child failed\n", 554 dinfo->obdinfo.obd_name); 555 resource_list_free(&dinfo->rl); 556 ofw_bus_gen_destroy_devinfo(&dinfo->obdinfo); 557 free(dinfo, M_DEVBUF); 558 continue; 559 } 560 device_set_ivars(cdev, dinfo); 561 } 562 563 return (true); 564} 565#endif 566 567static int 568arm_gic_attach(device_t dev) 569{ 570 struct arm_gic_softc *sc; 571 int i; 572 uint32_t icciidr, mask, nirqs; 573#ifdef INTRNG 574 phandle_t pxref; 575 intptr_t xref = gic_xref(dev); 576#endif 577 578 if (gic_sc) 579 return (ENXIO); 580 581 sc = device_get_softc(dev); 582 583 if (bus_alloc_resources(dev, arm_gic_spec, sc->gic_res)) { 584 device_printf(dev, "could not allocate resources\n"); 585 return (ENXIO); 586 } 587 588 sc->gic_dev = dev; 589 gic_sc = sc; 590 591 /* Initialize mutex */ 592 mtx_init(&sc->mutex, "GIC lock", "", MTX_SPIN); 593 594 /* Distributor Interface */ 595 sc->gic_d_bst = rman_get_bustag(sc->gic_res[0]); 596 sc->gic_d_bsh = rman_get_bushandle(sc->gic_res[0]); 597 598 /* CPU Interface */ 599 sc->gic_c_bst = rman_get_bustag(sc->gic_res[1]); 600 sc->gic_c_bsh = rman_get_bushandle(sc->gic_res[1]); 601 602 /* Disable interrupt forwarding to the CPU interface */ 603 gic_d_write_4(sc, GICD_CTLR, 0x00); 604 605 /* Get the number of interrupts */ 606 nirqs = gic_d_read_4(sc, GICD_TYPER); 607 nirqs = 32 * ((nirqs & 0x1f) + 1); 608 609#ifdef INTRNG 610 if (arm_gic_register_isrcs(sc, nirqs)) { 611 device_printf(dev, "could not register irqs\n"); 612 goto cleanup; 613 } 614#else 615 sc->nirqs = nirqs; 616 617 /* Set up function pointers */ 618 arm_post_filter = gic_post_filter; 619 arm_config_irq = gic_config_irq; 620#endif 621 622 icciidr = gic_c_read_4(sc, GICC_IIDR); 623 device_printf(dev,"pn 0x%x, arch 0x%x, rev 0x%x, implementer 0x%x irqs %u\n", 624 icciidr>>20, (icciidr>>16) & 0xF, (icciidr>>12) & 0xf, 625 (icciidr & 0xfff), sc->nirqs); 626 627 /* Set all global interrupts to be level triggered, active low. */ 628 for (i = 32; i < sc->nirqs; i += 16) { 629 gic_d_write_4(sc, GICD_ICFGR(i >> 4), GIC_DEFAULT_ICFGR_INIT); 630 } 631 632 /* Disable all interrupts. */ 633 for (i = 32; i < sc->nirqs; i += 32) { 634 gic_d_write_4(sc, GICD_ICENABLER(i >> 5), 0xFFFFFFFF); 635 } 636 637 /* Find the current cpu mask */ 638 mask = gic_cpu_mask(sc); 639 /* Set the mask so we can find this CPU to send it IPIs */ 640 arm_gic_map[PCPU_GET(cpuid)] = mask; 641 /* Set all four targets to this cpu */ 642 mask |= mask << 8; 643 mask |= mask << 16; 644 645 for (i = 0; i < sc->nirqs; i += 4) { 646 gic_d_write_4(sc, GICD_IPRIORITYR(i >> 2), 0); 647 if (i > 32) { 648 gic_d_write_4(sc, GICD_ITARGETSR(i >> 2), mask); 649 } 650 } 651 652 /* Set all the interrupts to be in Group 0 (secure) */ 653 for (i = 0; i < sc->nirqs; i += 32) { 654 gic_d_write_4(sc, GICD_IGROUPR(i >> 5), 0); 655 } 656 657 /* Enable CPU interface */ 658 gic_c_write_4(sc, GICC_CTLR, 1); 659 660 /* Set priority mask register. */ 661 gic_c_write_4(sc, GICC_PMR, 0xff); 662 663 /* Enable interrupt distribution */ 664 gic_d_write_4(sc, GICD_CTLR, 0x01); 665#ifndef INTRNG 666 return (0); 667#else 668 /* 669 * Now, when everything is initialized, it's right time to 670 * register interrupt controller to interrupt framefork. 671 */ 672 if (intr_pic_register(dev, xref) != 0) { 673 device_printf(dev, "could not register PIC\n"); 674 goto cleanup; 675 } 676 677 /* 678 * Controller is root if: 679 * - doesn't have interrupt parent 680 * - his interrupt parent is this controller 681 */ 682 pxref = ofw_bus_find_iparent(ofw_bus_get_node(dev)); 683 if (pxref == 0 || xref == pxref) { 684 if (intr_pic_claim_root(dev, xref, arm_gic_intr, sc, 685 GIC_LAST_SGI - GIC_FIRST_SGI + 1) != 0) { 686 device_printf(dev, "could not set PIC as a root\n"); 687 intr_pic_deregister(dev, xref); 688 goto cleanup; 689 } 690 } else { 691 if (sc->gic_res[2] == NULL) { 692 device_printf(dev, 693 "not root PIC must have defined interrupt\n"); 694 intr_pic_deregister(dev, xref); 695 goto cleanup; 696 } 697 if (bus_setup_intr(dev, sc->gic_res[2], INTR_TYPE_CLK, 698 arm_gic_intr, NULL, sc, &sc->gic_intrhand)) { 699 device_printf(dev, "could not setup irq handler\n"); 700 intr_pic_deregister(dev, xref); 701 goto cleanup; 702 } 703 } 704 705 OF_device_register_xref(xref, dev); 706 707 /* If we have children probe and attach them */ 708 if (arm_gic_add_children(dev)) { 709 bus_generic_probe(dev); 710 return (bus_generic_attach(dev)); 711 } 712 713 return (0); 714 715cleanup: 716 /* 717 * XXX - not implemented arm_gic_detach() should be called ! 718 */ 719 if (sc->gic_irqs != NULL) 720 free(sc->gic_irqs, M_DEVBUF); 721 bus_release_resources(dev, arm_gic_spec, sc->gic_res); 722 return(ENXIO); 723#endif 724} 725 726#ifdef INTRNG 727static struct resource * 728arm_gic_alloc_resource(device_t bus, device_t child, int type, int *rid, 729 rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) 730{ 731 struct arm_gic_softc *sc; 732 struct arm_gic_devinfo *di; 733 struct resource_list_entry *rle; 734 int j; 735 736 KASSERT(type == SYS_RES_MEMORY, ("Invalid resoure type %x", type)); 737 738 sc = device_get_softc(bus); 739 740 /* 741 * Request for the default allocation with a given rid: use resource 742 * list stored in the local device info. 743 */ 744 if (RMAN_IS_DEFAULT_RANGE(start, end)) { 745 if ((di = device_get_ivars(child)) == NULL) 746 return (NULL); 747 748 if (type == SYS_RES_IOPORT) 749 type = SYS_RES_MEMORY; 750 751 rle = resource_list_find(&di->rl, type, *rid); 752 if (rle == NULL) { 753 if (bootverbose) 754 device_printf(bus, "no default resources for " 755 "rid = %d, type = %d\n", *rid, type); 756 return (NULL); 757 } 758 start = rle->start; 759 end = rle->end; 760 count = rle->count; 761 } 762 763 /* Remap through ranges property */ 764 for (j = 0; j < sc->nranges; j++) { 765 if (start >= sc->ranges[j].bus && end < 766 sc->ranges[j].bus + sc->ranges[j].size) { 767 start -= sc->ranges[j].bus; 768 start += sc->ranges[j].host; 769 end -= sc->ranges[j].bus; 770 end += sc->ranges[j].host; 771 break; 772 } 773 } 774 if (j == sc->nranges && sc->nranges != 0) { 775 if (bootverbose) 776 device_printf(bus, "Could not map resource " 777 "%#jx-%#jx\n", (uintmax_t)start, (uintmax_t)end); 778 779 return (NULL); 780 } 781 782 return (bus_generic_alloc_resource(bus, child, type, rid, start, end, 783 count, flags)); 784} 785 786static const struct ofw_bus_devinfo * 787arm_gic_ofw_get_devinfo(device_t bus __unused, device_t child) 788{ 789 struct arm_gic_devinfo *di; 790 791 di = device_get_ivars(child); 792 793 return (&di->obdinfo); 794} 795 796static int 797arm_gic_intr(void *arg) 798{ 799 struct arm_gic_softc *sc = arg; 800 struct gic_irqsrc *gi; 801 uint32_t irq_active_reg, irq; 802 struct trapframe *tf; 803 804 irq_active_reg = gic_c_read_4(sc, GICC_IAR); 805 irq = irq_active_reg & 0x3FF; 806 807 /* 808 * 1. We do EOI here because recent read value from active interrupt 809 * register must be used for it. Another approach is to save this 810 * value into associated interrupt source. 811 * 2. EOI must be done on same CPU where interrupt has fired. Thus 812 * we must ensure that interrupted thread does not migrate to 813 * another CPU. 814 * 3. EOI cannot be delayed by any preemption which could happen on 815 * critical_exit() used in MI intr code, when interrupt thread is 816 * scheduled. See next point. 817 * 4. IPI_RENDEZVOUS assumes that no preemption is permitted during 818 * an action and any use of critical_exit() could break this 819 * assumption. See comments within smp_rendezvous_action(). 820 * 5. We always return FILTER_HANDLED as this is an interrupt 821 * controller dispatch function. Otherwise, in cascaded interrupt 822 * case, the whole interrupt subtree would be masked. 823 */ 824 825 if (irq >= sc->nirqs) { 826#ifdef GIC_DEBUG_SPURIOUS 827 device_printf(sc->gic_dev, 828 "Spurious interrupt detected: last irq: %d on CPU%d\n", 829 sc->last_irq[PCPU_GET(cpuid)], PCPU_GET(cpuid)); 830#endif 831 return (FILTER_HANDLED); 832 } 833 834 tf = curthread->td_intr_frame; 835dispatch_irq: 836 gi = sc->gic_irqs + irq; 837 /* 838 * Note that GIC_FIRST_SGI is zero and is not used in 'if' statement 839 * as compiler complains that comparing u_int >= 0 is always true. 840 */ 841 if (irq <= GIC_LAST_SGI) { 842#ifdef SMP 843 /* Call EOI for all IPI before dispatch. */ 844 gic_c_write_4(sc, GICC_EOIR, irq_active_reg); 845 intr_ipi_dispatch(sgi_to_ipi[gi->gi_irq], tf); 846 goto next_irq; 847#else 848 device_printf(sc->gic_dev, "SGI %u on UP system detected\n", 849 irq - GIC_FIRST_SGI); 850 gic_c_write_4(sc, GICC_EOIR, irq_active_reg); 851 goto next_irq; 852#endif 853 } 854 855#ifdef GIC_DEBUG_SPURIOUS 856 sc->last_irq[PCPU_GET(cpuid)] = irq; 857#endif 858 if ((gi->gi_flags & GI_FLAG_EARLY_EOI) == GI_FLAG_EARLY_EOI) 859 gic_c_write_4(sc, GICC_EOIR, irq_active_reg); 860 861 if (intr_isrc_dispatch(&gi->gi_isrc, tf) != 0) { 862 gic_irq_mask(sc, irq); 863 if ((gi->gi_flags & GI_FLAG_EARLY_EOI) != GI_FLAG_EARLY_EOI) 864 gic_c_write_4(sc, GICC_EOIR, irq_active_reg); 865 device_printf(sc->gic_dev, "Stray irq %u disabled\n", irq); 866 } 867 868next_irq: 869 arm_irq_memory_barrier(irq); 870 irq_active_reg = gic_c_read_4(sc, GICC_IAR); 871 irq = irq_active_reg & 0x3FF; 872 if (irq < sc->nirqs) 873 goto dispatch_irq; 874 875 return (FILTER_HANDLED); 876} 877 878static void 879gic_config(struct arm_gic_softc *sc, u_int irq, enum intr_trigger trig, 880 enum intr_polarity pol) 881{ 882 uint32_t reg; 883 uint32_t mask; 884 885 if (irq < GIC_FIRST_SPI) 886 return; 887 888 mtx_lock_spin(&sc->mutex); 889 890 reg = gic_d_read_4(sc, GICD_ICFGR(irq >> 4)); 891 mask = (reg >> 2*(irq % 16)) & 0x3; 892 893 if (pol == INTR_POLARITY_LOW) { 894 mask &= ~GICD_ICFGR_POL_MASK; 895 mask |= GICD_ICFGR_POL_LOW; 896 } else if (pol == INTR_POLARITY_HIGH) { 897 mask &= ~GICD_ICFGR_POL_MASK; 898 mask |= GICD_ICFGR_POL_HIGH; 899 } 900 901 if (trig == INTR_TRIGGER_LEVEL) { 902 mask &= ~GICD_ICFGR_TRIG_MASK; 903 mask |= GICD_ICFGR_TRIG_LVL; 904 } else if (trig == INTR_TRIGGER_EDGE) { 905 mask &= ~GICD_ICFGR_TRIG_MASK; 906 mask |= GICD_ICFGR_TRIG_EDGE; 907 } 908 909 /* Set mask */ 910 reg = reg & ~(0x3 << 2*(irq % 16)); 911 reg = reg | (mask << 2*(irq % 16)); 912 gic_d_write_4(sc, GICD_ICFGR(irq >> 4), reg); 913 914 mtx_unlock_spin(&sc->mutex); 915} 916 917static int 918gic_bind(struct arm_gic_softc *sc, u_int irq, cpuset_t *cpus) 919{ 920 uint32_t cpu, end, mask; 921 922 end = min(mp_ncpus, 8); 923 for (cpu = end; cpu < MAXCPU; cpu++) 924 if (CPU_ISSET(cpu, cpus)) 925 return (EINVAL); 926 927 for (mask = 0, cpu = 0; cpu < end; cpu++) 928 if (CPU_ISSET(cpu, cpus)) 929 mask |= 1 << cpu; 930 931 gic_d_write_1(sc, GICD_ITARGETSR(0) + irq, mask); 932 return (0); 933} 934 935#ifdef FDT 936static int 937gic_map_fdt(device_t dev, u_int ncells, pcell_t *cells, u_int *irqp, 938 enum intr_polarity *polp, enum intr_trigger *trigp) 939{ 940 941 if (ncells == 1) { 942 *irqp = cells[0]; 943 *polp = INTR_POLARITY_CONFORM; 944 *trigp = INTR_TRIGGER_CONFORM; 945 return (0); 946 } 947 if (ncells == 3) { 948 u_int irq, tripol; 949 950 /* 951 * The 1st cell is the interrupt type: 952 * 0 = SPI 953 * 1 = PPI 954 * The 2nd cell contains the interrupt number: 955 * [0 - 987] for SPI 956 * [0 - 15] for PPI 957 * The 3rd cell is the flags, encoded as follows: 958 * bits[3:0] trigger type and level flags 959 * 1 = low-to-high edge triggered 960 * 2 = high-to-low edge triggered 961 * 4 = active high level-sensitive 962 * 8 = active low level-sensitive 963 * bits[15:8] PPI interrupt cpu mask 964 * Each bit corresponds to each of the 8 possible cpus 965 * attached to the GIC. A bit set to '1' indicated 966 * the interrupt is wired to that CPU. 967 */ 968 switch (cells[0]) { 969 case 0: 970 irq = GIC_FIRST_SPI + cells[1]; 971 /* SPI irq is checked later. */ 972 break; 973 case 1: 974 irq = GIC_FIRST_PPI + cells[1]; 975 if (irq > GIC_LAST_PPI) { 976 device_printf(dev, "unsupported PPI interrupt " 977 "number %u\n", cells[1]); 978 return (EINVAL); 979 } 980 break; 981 default: 982 device_printf(dev, "unsupported interrupt type " 983 "configuration %u\n", cells[0]); 984 return (EINVAL); 985 } 986 987 tripol = cells[2] & 0xff; 988 if (tripol & 0xf0 || (tripol & 0x0a && cells[0] == 0)) 989 device_printf(dev, "unsupported trigger/polarity " 990 "configuration 0x%02x\n", tripol); 991 992 *irqp = irq; 993 *polp = INTR_POLARITY_CONFORM; 994 *trigp = tripol & 0x03 ? INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL; 995 return (0); 996 } 997 return (EINVAL); 998} 999#endif 1000 1001static int 1002gic_map_intr(device_t dev, struct intr_map_data *data, u_int *irqp, 1003 enum intr_polarity *polp, enum intr_trigger *trigp) 1004{ 1005 u_int irq; 1006 enum intr_polarity pol; 1007 enum intr_trigger trig; 1008 struct arm_gic_softc *sc; 1009#ifdef FDT 1010 struct intr_map_data_fdt *daf; 1011#endif 1012 1013 sc = device_get_softc(dev); 1014 switch (data->type) { 1015#ifdef FDT 1016 case INTR_MAP_DATA_FDT: 1017 daf = (struct intr_map_data_fdt *)data; 1018 if (gic_map_fdt(dev, daf->ncells, daf->cells, &irq, &pol, 1019 &trig) != 0) 1020 return (EINVAL); 1021 break; 1022#endif 1023 default: 1024 return (ENOTSUP); 1025 } 1026 1027 if (irq >= sc->nirqs) 1028 return (EINVAL); 1029 if (pol != INTR_POLARITY_CONFORM && pol != INTR_POLARITY_LOW && 1030 pol != INTR_POLARITY_HIGH) 1031 return (EINVAL); 1032 if (trig != INTR_TRIGGER_CONFORM && trig != INTR_TRIGGER_EDGE && 1033 trig != INTR_TRIGGER_LEVEL) 1034 return (EINVAL); 1035 1036 *irqp = irq; 1037 if (polp != NULL) 1038 *polp = pol; 1039 if (trigp != NULL) 1040 *trigp = trig; 1041 return (0); 1042} 1043 1044static int 1045arm_gic_map_intr(device_t dev, struct intr_map_data *data, 1046 struct intr_irqsrc **isrcp) 1047{ 1048 int error; 1049 u_int irq; 1050 struct arm_gic_softc *sc; 1051 1052 error = gic_map_intr(dev, data, &irq, NULL, NULL); 1053 if (error == 0) { 1054 sc = device_get_softc(dev); 1055 *isrcp = GIC_INTR_ISRC(sc, irq); 1056 } 1057 return (error); 1058} 1059 1060static int 1061arm_gic_setup_intr(device_t dev, struct intr_irqsrc *isrc, 1062 struct resource *res, struct intr_map_data *data) 1063{ 1064 struct arm_gic_softc *sc = device_get_softc(dev); 1065 struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc; 1066 u_int irq; 1067 enum intr_trigger trig; 1068 enum intr_polarity pol; 1069 1070 if (data == NULL) 1071 return (ENOTSUP); 1072 1073 /* Get config for resource. */ 1074 if (gic_map_intr(dev, data, &irq, &pol, &trig)) 1075 return (EINVAL); 1076 1077 if (gi->gi_irq != irq) 1078 return (EINVAL); 1079 1080 /* Compare config if this is not first setup. */ 1081 if (isrc->isrc_handlers != 0) { 1082 if ((pol != INTR_POLARITY_CONFORM && pol != gi->gi_pol) || 1083 (trig != INTR_TRIGGER_CONFORM && trig != gi->gi_trig)) 1084 return (EINVAL); 1085 else 1086 return (0); 1087 } 1088 1089 if (pol == INTR_POLARITY_CONFORM) 1090 pol = INTR_POLARITY_LOW; /* just pick some */ 1091 if (trig == INTR_TRIGGER_CONFORM) 1092 trig = INTR_TRIGGER_EDGE; /* just pick some */ 1093 1094 gi->gi_pol = pol; 1095 gi->gi_trig = trig; 1096 /* Edge triggered interrupts need an early EOI sent */ 1097 if (gi->gi_pol == INTR_TRIGGER_EDGE) 1098 gi->gi_flags |= GI_FLAG_EARLY_EOI; 1099 1100 /* 1101 * XXX - In case that per CPU interrupt is going to be enabled in time 1102 * when SMP is already started, we need some IPI call which 1103 * enables it on others CPUs. Further, it's more complicated as 1104 * pic_enable_source() and pic_disable_source() should act on 1105 * per CPU basis only. Thus, it should be solved here somehow. 1106 */ 1107 if (isrc->isrc_flags & INTR_ISRCF_PPI) 1108 CPU_SET(PCPU_GET(cpuid), &isrc->isrc_cpu); 1109 1110 gic_config(sc, gi->gi_irq, trig, pol); 1111 arm_gic_bind_intr(dev, isrc); 1112 return (0); 1113} 1114 1115static int 1116arm_gic_teardown_intr(device_t dev, struct intr_irqsrc *isrc, 1117 struct resource *res, struct intr_map_data *data) 1118{ 1119 struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc; 1120 1121 if (isrc->isrc_handlers == 0) { 1122 gi->gi_pol = INTR_POLARITY_CONFORM; 1123 gi->gi_trig = INTR_TRIGGER_CONFORM; 1124 } 1125 return (0); 1126} 1127 1128static void 1129arm_gic_enable_intr(device_t dev, struct intr_irqsrc *isrc) 1130{ 1131 struct arm_gic_softc *sc = device_get_softc(dev); 1132 struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc; 1133 1134 arm_irq_memory_barrier(gi->gi_irq); 1135 gic_irq_unmask(sc, gi->gi_irq); 1136} 1137 1138static void 1139arm_gic_disable_intr(device_t dev, struct intr_irqsrc *isrc) 1140{ 1141 struct arm_gic_softc *sc = device_get_softc(dev); 1142 struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc; 1143 1144 gic_irq_mask(sc, gi->gi_irq); 1145} 1146 1147static void 1148arm_gic_pre_ithread(device_t dev, struct intr_irqsrc *isrc) 1149{ 1150 struct arm_gic_softc *sc = device_get_softc(dev); 1151 struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc; 1152 1153 arm_gic_disable_intr(dev, isrc); 1154 gic_c_write_4(sc, GICC_EOIR, gi->gi_irq); 1155} 1156 1157static void 1158arm_gic_post_ithread(device_t dev, struct intr_irqsrc *isrc) 1159{ 1160 1161 arm_irq_memory_barrier(0); 1162 arm_gic_enable_intr(dev, isrc); 1163} 1164 1165static void 1166arm_gic_post_filter(device_t dev, struct intr_irqsrc *isrc) 1167{ 1168 struct arm_gic_softc *sc = device_get_softc(dev); 1169 struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc; 1170 1171 /* EOI for edge-triggered done earlier. */ 1172 if ((gi->gi_flags & GI_FLAG_EARLY_EOI) == GI_FLAG_EARLY_EOI) 1173 return; 1174 1175 arm_irq_memory_barrier(0); 1176 gic_c_write_4(sc, GICC_EOIR, gi->gi_irq); 1177} 1178 1179static int 1180arm_gic_bind_intr(device_t dev, struct intr_irqsrc *isrc) 1181{ 1182 struct arm_gic_softc *sc = device_get_softc(dev); 1183 struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc; 1184 1185 if (gi->gi_irq < GIC_FIRST_SPI) 1186 return (EINVAL); 1187 1188 if (CPU_EMPTY(&isrc->isrc_cpu)) { 1189 gic_irq_cpu = intr_irq_next_cpu(gic_irq_cpu, &all_cpus); 1190 CPU_SETOF(gic_irq_cpu, &isrc->isrc_cpu); 1191 } 1192 return (gic_bind(sc, gi->gi_irq, &isrc->isrc_cpu)); 1193} 1194 1195#ifdef SMP 1196static void 1197arm_gic_ipi_send(device_t dev, struct intr_irqsrc *isrc, cpuset_t cpus, 1198 u_int ipi) 1199{ 1200 struct arm_gic_softc *sc = device_get_softc(dev); 1201 struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc; 1202 uint32_t val = 0, i; 1203 1204 for (i = 0; i < MAXCPU; i++) 1205 if (CPU_ISSET(i, &cpus)) 1206 val |= arm_gic_map[i] << GICD_SGI_TARGET_SHIFT; 1207 1208 gic_d_write_4(sc, GICD_SGIR(0), val | gi->gi_irq); 1209} 1210 1211static int 1212arm_gic_ipi_setup(device_t dev, u_int ipi, struct intr_irqsrc **isrcp) 1213{ 1214 struct intr_irqsrc *isrc; 1215 struct arm_gic_softc *sc = device_get_softc(dev); 1216 1217 if (sgi_first_unused > GIC_LAST_SGI) 1218 return (ENOSPC); 1219 1220 isrc = GIC_INTR_ISRC(sc, sgi_first_unused); 1221 sgi_to_ipi[sgi_first_unused++] = ipi; 1222 1223 CPU_SET(PCPU_GET(cpuid), &isrc->isrc_cpu); 1224 1225 *isrcp = isrc; 1226 return (0); 1227} 1228#endif 1229#else 1230static int 1231arm_gic_next_irq(struct arm_gic_softc *sc, int last_irq) 1232{ 1233 uint32_t active_irq; 1234 1235 active_irq = gic_c_read_4(sc, GICC_IAR); 1236 1237 /* 1238 * Immediately EOIR the SGIs, because doing so requires the other 1239 * bits (ie CPU number), not just the IRQ number, and we do not 1240 * have this information later. 1241 */ 1242 if ((active_irq & 0x3ff) <= GIC_LAST_SGI) 1243 gic_c_write_4(sc, GICC_EOIR, active_irq); 1244 active_irq &= 0x3FF; 1245 1246 if (active_irq == 0x3FF) { 1247 if (last_irq == -1) 1248 device_printf(sc->gic_dev, 1249 "Spurious interrupt detected\n"); 1250 return -1; 1251 } 1252 1253 return active_irq; 1254} 1255 1256static int 1257arm_gic_config(device_t dev, int irq, enum intr_trigger trig, 1258 enum intr_polarity pol) 1259{ 1260 struct arm_gic_softc *sc = device_get_softc(dev); 1261 uint32_t reg; 1262 uint32_t mask; 1263 1264 /* Function is public-accessible, so validate input arguments */ 1265 if ((irq < 0) || (irq >= sc->nirqs)) 1266 goto invalid_args; 1267 if ((trig != INTR_TRIGGER_EDGE) && (trig != INTR_TRIGGER_LEVEL) && 1268 (trig != INTR_TRIGGER_CONFORM)) 1269 goto invalid_args; 1270 if ((pol != INTR_POLARITY_HIGH) && (pol != INTR_POLARITY_LOW) && 1271 (pol != INTR_POLARITY_CONFORM)) 1272 goto invalid_args; 1273 1274 mtx_lock_spin(&sc->mutex); 1275 1276 reg = gic_d_read_4(sc, GICD_ICFGR(irq >> 4)); 1277 mask = (reg >> 2*(irq % 16)) & 0x3; 1278 1279 if (pol == INTR_POLARITY_LOW) { 1280 mask &= ~GICD_ICFGR_POL_MASK; 1281 mask |= GICD_ICFGR_POL_LOW; 1282 } else if (pol == INTR_POLARITY_HIGH) { 1283 mask &= ~GICD_ICFGR_POL_MASK; 1284 mask |= GICD_ICFGR_POL_HIGH; 1285 } 1286 1287 if (trig == INTR_TRIGGER_LEVEL) { 1288 mask &= ~GICD_ICFGR_TRIG_MASK; 1289 mask |= GICD_ICFGR_TRIG_LVL; 1290 } else if (trig == INTR_TRIGGER_EDGE) { 1291 mask &= ~GICD_ICFGR_TRIG_MASK; 1292 mask |= GICD_ICFGR_TRIG_EDGE; 1293 } 1294 1295 /* Set mask */ 1296 reg = reg & ~(0x3 << 2*(irq % 16)); 1297 reg = reg | (mask << 2*(irq % 16)); 1298 gic_d_write_4(sc, GICD_ICFGR(irq >> 4), reg); 1299 1300 mtx_unlock_spin(&sc->mutex); 1301 1302 return (0); 1303 1304invalid_args: 1305 device_printf(dev, "gic_config_irg, invalid parameters\n"); 1306 return (EINVAL); 1307} 1308 1309 1310static void 1311arm_gic_mask(device_t dev, int irq) 1312{ 1313 struct arm_gic_softc *sc = device_get_softc(dev); 1314 1315 gic_d_write_4(sc, GICD_ICENABLER(irq >> 5), (1UL << (irq & 0x1F))); 1316 gic_c_write_4(sc, GICC_EOIR, irq); /* XXX - not allowed */ 1317} 1318 1319static void 1320arm_gic_unmask(device_t dev, int irq) 1321{ 1322 struct arm_gic_softc *sc = device_get_softc(dev); 1323 1324 if (irq > GIC_LAST_SGI) 1325 arm_irq_memory_barrier(irq); 1326 1327 gic_d_write_4(sc, GICD_ISENABLER(irq >> 5), (1UL << (irq & 0x1F))); 1328} 1329 1330#ifdef SMP 1331static void 1332arm_gic_ipi_send(device_t dev, cpuset_t cpus, u_int ipi) 1333{ 1334 struct arm_gic_softc *sc = device_get_softc(dev); 1335 uint32_t val = 0, i; 1336 1337 for (i = 0; i < MAXCPU; i++) 1338 if (CPU_ISSET(i, &cpus)) 1339 val |= arm_gic_map[i] << GICD_SGI_TARGET_SHIFT; 1340 1341 gic_d_write_4(sc, GICD_SGIR(0), val | ipi); 1342} 1343 1344static int 1345arm_gic_ipi_read(device_t dev, int i) 1346{ 1347 1348 if (i != -1) { 1349 /* 1350 * The intr code will automagically give the frame pointer 1351 * if the interrupt argument is 0. 1352 */ 1353 if ((unsigned int)i > 16) 1354 return (0); 1355 return (i); 1356 } 1357 1358 return (0x3ff); 1359} 1360 1361static void 1362arm_gic_ipi_clear(device_t dev, int ipi) 1363{ 1364 /* no-op */ 1365} 1366#endif 1367 1368static void 1369gic_post_filter(void *arg) 1370{ 1371 struct arm_gic_softc *sc = gic_sc; 1372 uintptr_t irq = (uintptr_t) arg; 1373 1374 if (irq > GIC_LAST_SGI) 1375 arm_irq_memory_barrier(irq); 1376 gic_c_write_4(sc, GICC_EOIR, irq); 1377} 1378 1379static int 1380gic_config_irq(int irq, enum intr_trigger trig, enum intr_polarity pol) 1381{ 1382 1383 return (arm_gic_config(gic_sc->gic_dev, irq, trig, pol)); 1384} 1385 1386void 1387arm_mask_irq(uintptr_t nb) 1388{ 1389 1390 arm_gic_mask(gic_sc->gic_dev, nb); 1391} 1392 1393void 1394arm_unmask_irq(uintptr_t nb) 1395{ 1396 1397 arm_gic_unmask(gic_sc->gic_dev, nb); 1398} 1399 1400int 1401arm_get_next_irq(int last_irq) 1402{ 1403 1404 return (arm_gic_next_irq(gic_sc, last_irq)); 1405} 1406 1407#ifdef SMP 1408void 1409intr_pic_init_secondary(void) 1410{ 1411 1412 arm_gic_init_secondary(gic_sc->gic_dev); 1413} 1414 1415void 1416pic_ipi_send(cpuset_t cpus, u_int ipi) 1417{ 1418 1419 arm_gic_ipi_send(gic_sc->gic_dev, cpus, ipi); 1420} 1421 1422int 1423pic_ipi_read(int i) 1424{ 1425 1426 return (arm_gic_ipi_read(gic_sc->gic_dev, i)); 1427} 1428 1429void 1430pic_ipi_clear(int ipi) 1431{ 1432 1433 arm_gic_ipi_clear(gic_sc->gic_dev, ipi); 1434} 1435#endif 1436#endif /* INTRNG */ 1437 1438static device_method_t arm_gic_methods[] = { 1439 /* Device interface */ 1440 DEVMETHOD(device_probe, arm_gic_probe), 1441 DEVMETHOD(device_attach, arm_gic_attach), 1442 1443#ifdef INTRNG 1444 /* Bus interface */ 1445 DEVMETHOD(bus_add_child, bus_generic_add_child), 1446 DEVMETHOD(bus_alloc_resource, arm_gic_alloc_resource), 1447 DEVMETHOD(bus_release_resource, bus_generic_release_resource), 1448 DEVMETHOD(bus_activate_resource,bus_generic_activate_resource), 1449 1450 /* ofw_bus interface */ 1451 DEVMETHOD(ofw_bus_get_devinfo, arm_gic_ofw_get_devinfo), 1452 DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), 1453 DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), 1454 DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), 1455 DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), 1456 DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), 1457 1458 /* Interrupt controller interface */ 1459 DEVMETHOD(pic_disable_intr, arm_gic_disable_intr), 1460 DEVMETHOD(pic_enable_intr, arm_gic_enable_intr), 1461 DEVMETHOD(pic_map_intr, arm_gic_map_intr), 1462 DEVMETHOD(pic_setup_intr, arm_gic_setup_intr), 1463 DEVMETHOD(pic_teardown_intr, arm_gic_teardown_intr), 1464 DEVMETHOD(pic_post_filter, arm_gic_post_filter), 1465 DEVMETHOD(pic_post_ithread, arm_gic_post_ithread), 1466 DEVMETHOD(pic_pre_ithread, arm_gic_pre_ithread), 1467#ifdef SMP 1468 DEVMETHOD(pic_bind_intr, arm_gic_bind_intr), 1469 DEVMETHOD(pic_init_secondary, arm_gic_init_secondary), 1470 DEVMETHOD(pic_ipi_send, arm_gic_ipi_send), 1471 DEVMETHOD(pic_ipi_setup, arm_gic_ipi_setup), 1472#endif 1473#endif 1474 { 0, 0 } 1475}; 1476 1477static driver_t arm_gic_driver = { 1478 "gic", 1479 arm_gic_methods, 1480 sizeof(struct arm_gic_softc), 1481}; 1482 1483static devclass_t arm_gic_devclass; 1484 1485EARLY_DRIVER_MODULE(gic, simplebus, arm_gic_driver, arm_gic_devclass, 0, 0, 1486 BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); 1487EARLY_DRIVER_MODULE(gic, ofwbus, arm_gic_driver, arm_gic_devclass, 0, 0, 1488 BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); 1489 1490#ifdef INTRNG 1491/* 1492 * GICv2m support -- the GICv2 MSI/MSI-X controller. 1493 */ 1494 1495#define GICV2M_MSI_TYPER 0x008 1496#define MSI_TYPER_SPI_BASE(x) (((x) >> 16) & 0x3ff) 1497#define MSI_TYPER_SPI_COUNT(x) (((x) >> 0) & 0x3ff) 1498#define GICv2M_MSI_SETSPI_NS 0x040 1499#define GICV2M_MSI_IIDR 0xFCC 1500 1501struct arm_gicv2m_softc { 1502 struct resource *sc_mem; 1503 struct mtx sc_mutex; 1504 u_int sc_spi_start; 1505 u_int sc_spi_count; 1506 u_int sc_spi_offset; 1507}; 1508 1509static struct ofw_compat_data gicv2m_compat_data[] = { 1510 {"arm,gic-v2m-frame", true}, 1511 {NULL, false} 1512}; 1513 1514static int 1515arm_gicv2m_probe(device_t dev) 1516{ 1517 1518 if (!ofw_bus_status_okay(dev)) 1519 return (ENXIO); 1520 1521 if (!ofw_bus_search_compatible(dev, gicv2m_compat_data)->ocd_data) 1522 return (ENXIO); 1523 1524 device_set_desc(dev, "ARM Generic Interrupt Controller MSI/MSIX"); 1525 return (BUS_PROBE_DEFAULT); 1526} 1527 1528static int 1529arm_gicv2m_attach(device_t dev) 1530{ 1531 struct arm_gicv2m_softc *sc; 1532 uint32_t typer; 1533 int rid; 1534 1535 sc = device_get_softc(dev); 1536 1537 rid = 0; 1538 sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 1539 RF_ACTIVE); 1540 if (sc->sc_mem == NULL) { 1541 device_printf(dev, "Unable to allocate resources\n"); 1542 return (ENXIO); 1543 } 1544 1545 typer = bus_read_4(sc->sc_mem, GICV2M_MSI_TYPER); 1546 sc->sc_spi_start = MSI_TYPER_SPI_BASE(typer); 1547 sc->sc_spi_count = MSI_TYPER_SPI_COUNT(typer); 1548 1549 mtx_init(&sc->sc_mutex, "GICv2m lock", "", MTX_DEF); 1550 1551 if (bootverbose) 1552 device_printf(dev, "using spi %u to %u\n", sc->sc_spi_start, 1553 sc->sc_spi_start + sc->sc_spi_count - 1); 1554 1555 return (0); 1556} 1557 1558static device_method_t arm_gicv2m_methods[] = { 1559 /* Device interface */ 1560 DEVMETHOD(device_probe, arm_gicv2m_probe), 1561 DEVMETHOD(device_attach, arm_gicv2m_attach), 1562 1563 /* End */ 1564 DEVMETHOD_END 1565}; 1566 1567DEFINE_CLASS_0(gicv2m, arm_gicv2m_driver, arm_gicv2m_methods, 1568 sizeof(struct arm_gicv2m_softc)); 1569 1570static devclass_t arm_gicv2m_devclass; 1571 1572EARLY_DRIVER_MODULE(gicv2m, gic, arm_gicv2m_driver, 1573 arm_gicv2m_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); 1574#endif 1575