1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2020 Ruslan Bukin <br@bsdpad.com> 5 * 6 * This software was developed by SRI International and the University of 7 * Cambridge Computer Laboratory (Department of Computer Science and 8 * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 9 * DARPA SSITH research programme. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #include "opt_platform.h" 34 35 #include <sys/cdefs.h> 36 __FBSDID("$FreeBSD$"); 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/malloc.h> 41 #include <sys/types.h> 42 #include <sys/sysctl.h> 43 #include <sys/kernel.h> 44 #include <sys/rman.h> 45 #include <sys/module.h> 46 #include <sys/bus.h> 47 #include <sys/endian.h> 48 #include <sys/cpuset.h> 49 #include <sys/mutex.h> 50 #include <sys/proc.h> 51 52 #include <machine/intr.h> 53 #include <machine/bus.h> 54 55 #include <vm/vm.h> 56 #include <vm/vm_extern.h> 57 #include <vm/vm_kern.h> 58 #include <vm/pmap.h> 59 60 #include <dev/ofw/openfirm.h> 61 #include <dev/ofw/ofw_bus.h> 62 #include <dev/ofw/ofw_bus_subr.h> 63 64 #include <dev/pci/pcireg.h> 65 #include <dev/pci/pcivar.h> 66 #include <dev/pci/pci_host_generic.h> 67 #include <dev/pci/pci_host_generic_fdt.h> 68 #include <dev/pci/pcib_private.h> 69 70 #include "xlnx_pcib.h" 71 72 #include "ofw_bus_if.h" 73 #include "msi_if.h" 74 #include "pcib_if.h" 75 #include "pic_if.h" 76 77 #define XLNX_PCIB_MAX_MSI 64 78 79 static int xlnx_pcib_fdt_attach(device_t); 80 static int xlnx_pcib_fdt_probe(device_t); 81 static int xlnx_pcib_fdt_get_id(device_t, device_t, enum pci_id_type, 82 uintptr_t *); 83 static void xlnx_pcib_msi_mask(device_t dev, struct intr_irqsrc *isrc, 84 bool mask); 85 86 struct xlnx_pcib_softc { 87 struct generic_pcie_fdt_softc fdt_sc; 88 struct resource *res[4]; 89 struct mtx mtx; 90 vm_offset_t msi_page; 91 struct xlnx_pcib_irqsrc *isrcs; 92 device_t dev; 93 void *intr_cookie[3]; 94 }; 95 96 static struct resource_spec xlnx_pcib_spec[] = { 97 { SYS_RES_MEMORY, 0, RF_ACTIVE }, 98 { SYS_RES_IRQ, 0, RF_ACTIVE }, 99 { SYS_RES_IRQ, 1, RF_ACTIVE }, 100 { SYS_RES_IRQ, 2, RF_ACTIVE }, 101 { -1, 0 } 102 }; 103 104 struct xlnx_pcib_irqsrc { 105 struct intr_irqsrc isrc; 106 u_int irq; 107 #define XLNX_IRQ_FLAG_USED (1 << 0) 108 u_int flags; 109 }; 110 111 static void 112 xlnx_pcib_clear_err_interrupts(struct generic_pcie_core_softc *sc) 113 { 114 uint32_t reg; 115 116 reg = bus_read_4(sc->res, XLNX_PCIE_RPERRFRR); 117 118 if (reg & RPERRFRR_VALID) { 119 device_printf(sc->dev, "Requested ID: %x\n", 120 reg & RPERRFRR_REQ_ID_M); 121 bus_write_4(sc->res, XLNX_PCIE_RPERRFRR, ~0U); 122 } 123 } 124 125 static int 126 xlnx_pcib_intr(void *arg) 127 { 128 struct generic_pcie_fdt_softc *fdt_sc; 129 struct generic_pcie_core_softc *sc; 130 struct xlnx_pcib_softc *xlnx_sc; 131 uint32_t val, mask, status; 132 133 xlnx_sc = arg; 134 fdt_sc = &xlnx_sc->fdt_sc; 135 sc = &fdt_sc->base; 136 137 val = bus_read_4(sc->res, XLNX_PCIE_IDR); 138 mask = bus_read_4(sc->res, XLNX_PCIE_IMR); 139 140 status = val & mask; 141 if (!status) 142 return (FILTER_HANDLED); 143 144 if (status & IMR_LINK_DOWN) 145 device_printf(sc->dev, "Link down"); 146 147 if (status & IMR_HOT_RESET) 148 device_printf(sc->dev, "Hot reset"); 149 150 if (status & IMR_CORRECTABLE) 151 xlnx_pcib_clear_err_interrupts(sc); 152 153 if (status & IMR_FATAL) 154 xlnx_pcib_clear_err_interrupts(sc); 155 156 if (status & IMR_NON_FATAL) 157 xlnx_pcib_clear_err_interrupts(sc); 158 159 if (status & IMR_MSI) { 160 device_printf(sc->dev, "MSI interrupt"); 161 162 /* FIFO mode MSI not implemented. */ 163 } 164 165 if (status & IMR_INTX) { 166 device_printf(sc->dev, "INTx received"); 167 168 /* Not implemented. */ 169 } 170 171 if (status & IMR_SLAVE_UNSUPP_REQ) 172 device_printf(sc->dev, "Slave unsupported request"); 173 174 if (status & IMR_SLAVE_UNEXP_COMPL) 175 device_printf(sc->dev, "Slave unexpected completion"); 176 177 if (status & IMR_SLAVE_COMPL_TIMOUT) 178 device_printf(sc->dev, "Slave completion timeout"); 179 180 if (status & IMR_SLAVE_ERROR_POISON) 181 device_printf(sc->dev, "Slave error poison"); 182 183 if (status & IMR_SLAVE_COMPL_ABORT) 184 device_printf(sc->dev, "Slave completion abort"); 185 186 if (status & IMR_SLAVE_ILLEG_BURST) 187 device_printf(sc->dev, "Slave illegal burst"); 188 189 if (status & IMR_MASTER_DECERR) 190 device_printf(sc->dev, "Master decode error"); 191 192 if (status & IMR_MASTER_SLVERR) 193 device_printf(sc->dev, "Master slave error"); 194 195 bus_write_4(sc->res, XLNX_PCIE_IDR, val); 196 197 return (FILTER_HANDLED); 198 } 199 200 static void 201 xlnx_pcib_handle_msi_intr(void *arg, int msireg) 202 { 203 struct generic_pcie_fdt_softc *fdt_sc; 204 struct generic_pcie_core_softc *sc; 205 struct xlnx_pcib_softc *xlnx_sc; 206 struct xlnx_pcib_irqsrc *xi; 207 struct trapframe *tf; 208 int irq; 209 int reg; 210 int i; 211 212 xlnx_sc = arg; 213 fdt_sc = &xlnx_sc->fdt_sc; 214 sc = &fdt_sc->base; 215 tf = curthread->td_intr_frame; 216 217 do { 218 reg = bus_read_4(sc->res, msireg); 219 220 for (i = 0; i < sizeof(uint32_t) * 8; i++) { 221 if (reg & (1 << i)) { 222 bus_write_4(sc->res, msireg, (1 << i)); 223 224 irq = i; 225 if (msireg == XLNX_PCIE_RPMSIID2) 226 irq += 32; 227 228 xi = &xlnx_sc->isrcs[irq]; 229 if (intr_isrc_dispatch(&xi->isrc, tf) != 0) { 230 /* Disable stray. */ 231 xlnx_pcib_msi_mask(sc->dev, 232 &xi->isrc, 1); 233 device_printf(sc->dev, 234 "Stray irq %u disabled\n", irq); 235 } 236 } 237 } 238 } while (reg != 0); 239 } 240 241 static int 242 xlnx_pcib_msi0_intr(void *arg) 243 { 244 245 xlnx_pcib_handle_msi_intr(arg, XLNX_PCIE_RPMSIID1); 246 247 return (FILTER_HANDLED); 248 } 249 250 static int 251 xlnx_pcib_msi1_intr(void *arg) 252 { 253 254 xlnx_pcib_handle_msi_intr(arg, XLNX_PCIE_RPMSIID2); 255 256 return (FILTER_HANDLED); 257 } 258 259 static int 260 xlnx_pcib_register_msi(struct xlnx_pcib_softc *sc) 261 { 262 const char *name; 263 int error; 264 int irq; 265 266 sc->isrcs = malloc(sizeof(*sc->isrcs) * XLNX_PCIB_MAX_MSI, M_DEVBUF, 267 M_WAITOK | M_ZERO); 268 269 name = device_get_nameunit(sc->dev); 270 271 for (irq = 0; irq < XLNX_PCIB_MAX_MSI; irq++) { 272 sc->isrcs[irq].irq = irq; 273 error = intr_isrc_register(&sc->isrcs[irq].isrc, 274 sc->dev, 0, "%s,%u", name, irq); 275 if (error != 0) 276 return (error); /* XXX deregister ISRCs */ 277 } 278 279 if (intr_msi_register(sc->dev, 280 OF_xref_from_node(ofw_bus_get_node(sc->dev))) != 0) 281 return (ENXIO); 282 283 return (0); 284 } 285 286 static void 287 xlnx_pcib_init(struct xlnx_pcib_softc *sc) 288 { 289 bus_addr_t addr; 290 int reg; 291 292 /* Disable interrupts. */ 293 bus_write_4(sc->res[0], XLNX_PCIE_IMR, 0); 294 295 /* Clear pending interrupts.*/ 296 reg = bus_read_4(sc->res[0], XLNX_PCIE_IDR); 297 bus_write_4(sc->res[0], XLNX_PCIE_IDR, reg); 298 299 /* Setup an MSI page. */ 300 sc->msi_page = kmem_alloc_contig(PAGE_SIZE, M_WAITOK, 0, 301 BUS_SPACE_MAXADDR, PAGE_SIZE, 0, VM_MEMATTR_DEFAULT); 302 addr = vtophys(sc->msi_page); 303 bus_write_4(sc->res[0], XLNX_PCIE_RPMSIBR1, (addr >> 32)); 304 bus_write_4(sc->res[0], XLNX_PCIE_RPMSIBR2, (addr >> 0)); 305 306 /* Enable the bridge. */ 307 reg = bus_read_4(sc->res[0], XLNX_PCIE_RPSCR); 308 reg |= RPSCR_BE; 309 bus_write_4(sc->res[0], XLNX_PCIE_RPSCR, reg); 310 311 /* Enable interrupts. */ 312 reg = IMR_LINK_DOWN 313 | IMR_HOT_RESET 314 | IMR_CFG_COMPL_STATUS_M 315 | IMR_CFG_TIMEOUT 316 | IMR_CORRECTABLE 317 | IMR_NON_FATAL 318 | IMR_FATAL 319 | IMR_INTX 320 | IMR_MSI 321 | IMR_SLAVE_UNSUPP_REQ 322 | IMR_SLAVE_UNEXP_COMPL 323 | IMR_SLAVE_COMPL_TIMOUT 324 | IMR_SLAVE_ERROR_POISON 325 | IMR_SLAVE_COMPL_ABORT 326 | IMR_SLAVE_ILLEG_BURST 327 | IMR_MASTER_DECERR 328 | IMR_MASTER_SLVERR; 329 bus_write_4(sc->res[0], XLNX_PCIE_IMR, reg); 330 } 331 332 static int 333 xlnx_pcib_fdt_probe(device_t dev) 334 { 335 336 if (!ofw_bus_status_okay(dev)) 337 return (ENXIO); 338 339 if (ofw_bus_is_compatible(dev, "xlnx,xdma-host-3.00")) { 340 device_set_desc(dev, "Xilinx XDMA PCIe Controller"); 341 return (BUS_PROBE_DEFAULT); 342 } 343 344 return (ENXIO); 345 } 346 347 static int 348 xlnx_pcib_fdt_attach(device_t dev) 349 { 350 struct xlnx_pcib_softc *sc; 351 int error; 352 353 sc = device_get_softc(dev); 354 sc->dev = dev; 355 356 mtx_init(&sc->mtx, "msi_mtx", NULL, MTX_DEF); 357 358 if (bus_alloc_resources(dev, xlnx_pcib_spec, sc->res)) { 359 device_printf(dev, "could not allocate resources\n"); 360 return (ENXIO); 361 } 362 363 /* Setup MISC interrupt handler. */ 364 error = bus_setup_intr(dev, sc->res[1], INTR_TYPE_MISC | INTR_MPSAFE, 365 xlnx_pcib_intr, NULL, sc, &sc->intr_cookie[0]); 366 if (error != 0) { 367 device_printf(dev, "could not setup interrupt handler.\n"); 368 return (ENXIO); 369 } 370 371 /* Setup MSI0 interrupt handler. */ 372 error = bus_setup_intr(dev, sc->res[2], INTR_TYPE_MISC | INTR_MPSAFE, 373 xlnx_pcib_msi0_intr, NULL, sc, &sc->intr_cookie[1]); 374 if (error != 0) { 375 device_printf(dev, "could not setup interrupt handler.\n"); 376 return (ENXIO); 377 } 378 379 /* Setup MSI1 interrupt handler. */ 380 error = bus_setup_intr(dev, sc->res[3], INTR_TYPE_MISC | INTR_MPSAFE, 381 xlnx_pcib_msi1_intr, NULL, sc, &sc->intr_cookie[2]); 382 if (error != 0) { 383 device_printf(dev, "could not setup interrupt handler.\n"); 384 return (ENXIO); 385 } 386 387 xlnx_pcib_init(sc); 388 389 /* 390 * Allow the core driver to map registers. 391 * We will be accessing the device memory using core_softc. 392 */ 393 bus_release_resources(dev, xlnx_pcib_spec, sc->res); 394 395 error = xlnx_pcib_register_msi(sc); 396 if (error) 397 return (error); 398 399 return (pci_host_generic_fdt_attach(dev)); 400 } 401 402 static int 403 xlnx_pcib_fdt_get_id(device_t pci, device_t child, enum pci_id_type type, 404 uintptr_t *id) 405 { 406 phandle_t node; 407 int bsf; 408 409 if (type != PCI_ID_MSI) 410 return (pcib_get_id(pci, child, type, id)); 411 412 node = ofw_bus_get_node(pci); 413 if (OF_hasprop(node, "msi-map")) 414 return (generic_pcie_get_id(pci, child, type, id)); 415 416 bsf = pci_get_rid(child); 417 *id = (pci_get_domain(child) << PCI_RID_DOMAIN_SHIFT) | bsf; 418 419 return (0); 420 } 421 422 static int 423 xlnx_pcib_req_valid(struct generic_pcie_core_softc *sc, 424 u_int bus, u_int slot, u_int func, u_int reg) 425 { 426 bus_space_handle_t h; 427 bus_space_tag_t t; 428 uint32_t val; 429 430 t = sc->bst; 431 h = sc->bsh; 432 433 if ((bus < sc->bus_start) || (bus > sc->bus_end)) 434 return (0); 435 if ((slot > PCI_SLOTMAX) || (func > PCI_FUNCMAX) || 436 (reg > PCIE_REGMAX)) 437 return (0); 438 439 if (bus == 0 && slot > 0) 440 return (0); 441 442 val = bus_space_read_4(t, h, XLNX_PCIE_PHYSCR); 443 if ((val & PHYSCR_LINK_UP) == 0) { 444 /* Link is down */ 445 return (0); 446 } 447 448 /* Valid */ 449 450 return (1); 451 } 452 453 static uint32_t 454 xlnx_pcib_read_config(device_t dev, u_int bus, u_int slot, 455 u_int func, u_int reg, int bytes) 456 { 457 struct generic_pcie_fdt_softc *fdt_sc; 458 struct xlnx_pcib_softc *xlnx_sc; 459 struct generic_pcie_core_softc *sc; 460 bus_space_handle_t h; 461 bus_space_tag_t t; 462 uint64_t offset; 463 uint32_t data; 464 465 xlnx_sc = device_get_softc(dev); 466 fdt_sc = &xlnx_sc->fdt_sc; 467 sc = &fdt_sc->base; 468 469 if (!xlnx_pcib_req_valid(sc, bus, slot, func, reg)) 470 return (~0U); 471 472 offset = PCIE_ADDR_OFFSET(bus - sc->bus_start, slot, func, reg); 473 t = sc->bst; 474 h = sc->bsh; 475 476 data = bus_space_read_4(t, h, offset & ~3); 477 478 switch (bytes) { 479 case 1: 480 data >>= (offset & 3) * 8; 481 data &= 0xff; 482 break; 483 case 2: 484 data >>= (offset & 3) * 8; 485 data = le16toh(data); 486 break; 487 case 4: 488 data = le32toh(data); 489 break; 490 default: 491 return (~0U); 492 } 493 494 return (data); 495 } 496 497 static void 498 xlnx_pcib_write_config(device_t dev, u_int bus, u_int slot, 499 u_int func, u_int reg, uint32_t val, int bytes) 500 { 501 struct generic_pcie_fdt_softc *fdt_sc; 502 struct xlnx_pcib_softc *xlnx_sc; 503 struct generic_pcie_core_softc *sc; 504 bus_space_handle_t h; 505 bus_space_tag_t t; 506 uint64_t offset; 507 uint32_t data; 508 509 xlnx_sc = device_get_softc(dev); 510 fdt_sc = &xlnx_sc->fdt_sc; 511 sc = &fdt_sc->base; 512 513 if (!xlnx_pcib_req_valid(sc, bus, slot, func, reg)) 514 return; 515 516 offset = PCIE_ADDR_OFFSET(bus - sc->bus_start, slot, func, reg); 517 518 t = sc->bst; 519 h = sc->bsh; 520 521 /* 522 * 32-bit access used due to a bug in the Xilinx bridge that 523 * requires to write primary and secondary buses in one blast. 524 * 525 * TODO: This is probably wrong on big-endian. 526 */ 527 switch (bytes) { 528 case 1: 529 data = bus_space_read_4(t, h, offset & ~3); 530 data &= ~(0xff << ((offset & 3) * 8)); 531 data |= (val & 0xff) << ((offset & 3) * 8); 532 bus_space_write_4(t, h, offset & ~3, htole32(data)); 533 break; 534 case 2: 535 data = bus_space_read_4(t, h, offset & ~3); 536 data &= ~(0xffff << ((offset & 3) * 8)); 537 data |= (val & 0xffff) << ((offset & 3) * 8); 538 bus_space_write_4(t, h, offset & ~3, htole32(data)); 539 break; 540 case 4: 541 bus_space_write_4(t, h, offset, htole32(val)); 542 break; 543 default: 544 return; 545 } 546 } 547 548 static int 549 xlnx_pcib_alloc_msi(device_t pci, device_t child, int count, int maxcount, 550 int *irqs) 551 { 552 phandle_t msi_parent; 553 554 ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child), &msi_parent, 555 NULL); 556 msi_parent = OF_xref_from_node(ofw_bus_get_node(pci)); 557 return (intr_alloc_msi(pci, child, msi_parent, count, maxcount, 558 irqs)); 559 } 560 561 static int 562 xlnx_pcib_release_msi(device_t pci, device_t child, int count, int *irqs) 563 { 564 phandle_t msi_parent; 565 566 ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child), &msi_parent, 567 NULL); 568 msi_parent = OF_xref_from_node(ofw_bus_get_node(pci)); 569 return (intr_release_msi(pci, child, msi_parent, count, irqs)); 570 } 571 572 static int 573 xlnx_pcib_map_msi(device_t pci, device_t child, int irq, uint64_t *addr, 574 uint32_t *data) 575 { 576 phandle_t msi_parent; 577 578 ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child), &msi_parent, 579 NULL); 580 msi_parent = OF_xref_from_node(ofw_bus_get_node(pci)); 581 return (intr_map_msi(pci, child, msi_parent, irq, addr, data)); 582 } 583 584 static int 585 xlnx_pcib_msi_alloc_msi(device_t dev, device_t child, int count, int maxcount, 586 device_t *pic, struct intr_irqsrc **srcs) 587 { 588 struct xlnx_pcib_softc *sc; 589 int irq, end_irq, i; 590 bool found; 591 592 sc = device_get_softc(dev); 593 594 mtx_lock(&sc->mtx); 595 596 found = false; 597 598 for (irq = 0; (irq + count - 1) < XLNX_PCIB_MAX_MSI; irq++) { 599 /* Assume the range is valid. */ 600 found = true; 601 602 /* Check this range is valid. */ 603 for (end_irq = irq; end_irq < irq + count; end_irq++) { 604 if (sc->isrcs[end_irq].flags & XLNX_IRQ_FLAG_USED) { 605 /* This is already used. */ 606 found = false; 607 break; 608 } 609 } 610 611 if (found) 612 break; 613 } 614 615 if (!found || irq == (XLNX_PCIB_MAX_MSI - 1)) { 616 /* Not enough interrupts were found. */ 617 mtx_unlock(&sc->mtx); 618 return (ENXIO); 619 } 620 621 /* Mark the interrupt as used. */ 622 for (i = 0; i < count; i++) 623 sc->isrcs[irq + i].flags |= XLNX_IRQ_FLAG_USED; 624 625 mtx_unlock(&sc->mtx); 626 627 for (i = 0; i < count; i++) 628 srcs[i] = (struct intr_irqsrc *)&sc->isrcs[irq + i]; 629 630 *pic = device_get_parent(dev); 631 632 return (0); 633 } 634 635 static int 636 xlnx_pcib_msi_release_msi(device_t dev, device_t child, int count, 637 struct intr_irqsrc **isrc) 638 { 639 struct xlnx_pcib_softc *sc; 640 struct xlnx_pcib_irqsrc *xi; 641 int i; 642 643 sc = device_get_softc(dev); 644 mtx_lock(&sc->mtx); 645 for (i = 0; i < count; i++) { 646 xi = (struct xlnx_pcib_irqsrc *)isrc[i]; 647 648 KASSERT(xi->flags & XLNX_IRQ_FLAG_USED, 649 ("%s: Releasing an unused MSI interrupt", __func__)); 650 651 xi->flags &= ~XLNX_IRQ_FLAG_USED; 652 } 653 654 mtx_unlock(&sc->mtx); 655 return (0); 656 } 657 658 static int 659 xlnx_pcib_msi_map_msi(device_t dev, device_t child, struct intr_irqsrc *isrc, 660 uint64_t *addr, uint32_t *data) 661 { 662 struct xlnx_pcib_softc *sc; 663 struct xlnx_pcib_irqsrc *xi; 664 665 sc = device_get_softc(dev); 666 xi = (struct xlnx_pcib_irqsrc *)isrc; 667 668 *addr = vtophys(sc->msi_page); 669 *data = xi->irq; 670 671 return (0); 672 } 673 674 static void 675 xlnx_pcib_msi_mask(device_t dev, struct intr_irqsrc *isrc, bool mask) 676 { 677 struct generic_pcie_fdt_softc *fdt_sc; 678 struct generic_pcie_core_softc *sc; 679 struct xlnx_pcib_softc *xlnx_sc; 680 struct xlnx_pcib_irqsrc *xi; 681 uint32_t msireg, irq; 682 uint32_t reg; 683 684 xlnx_sc = device_get_softc(dev); 685 fdt_sc = &xlnx_sc->fdt_sc; 686 sc = &fdt_sc->base; 687 688 xi = (struct xlnx_pcib_irqsrc *)isrc; 689 690 irq = xi->irq; 691 if (irq < 32) 692 msireg = XLNX_PCIE_RPMSIID1_MASK; 693 else 694 msireg = XLNX_PCIE_RPMSIID2_MASK; 695 696 reg = bus_read_4(sc->res, msireg); 697 if (mask) 698 reg &= ~(1 << irq); 699 else 700 reg |= (1 << irq); 701 bus_write_4(sc->res, msireg, reg); 702 } 703 704 static void 705 xlnx_pcib_msi_disable_intr(device_t dev, struct intr_irqsrc *isrc) 706 { 707 708 xlnx_pcib_msi_mask(dev, isrc, true); 709 } 710 711 static void 712 xlnx_pcib_msi_enable_intr(device_t dev, struct intr_irqsrc *isrc) 713 { 714 715 xlnx_pcib_msi_mask(dev, isrc, false); 716 } 717 718 static void 719 xlnx_pcib_msi_post_filter(device_t dev, struct intr_irqsrc *isrc) 720 { 721 722 } 723 724 static void 725 xlnx_pcib_msi_post_ithread(device_t dev, struct intr_irqsrc *isrc) 726 { 727 728 xlnx_pcib_msi_mask(dev, isrc, false); 729 } 730 731 static void 732 xlnx_pcib_msi_pre_ithread(device_t dev, struct intr_irqsrc *isrc) 733 { 734 735 xlnx_pcib_msi_mask(dev, isrc, true); 736 } 737 738 static int 739 xlnx_pcib_msi_setup_intr(device_t dev, struct intr_irqsrc *isrc, 740 struct resource *res, struct intr_map_data *data) 741 { 742 743 return (0); 744 } 745 746 static int 747 xlnx_pcib_msi_teardown_intr(device_t dev, struct intr_irqsrc *isrc, 748 struct resource *res, struct intr_map_data *data) 749 { 750 751 return (0); 752 } 753 754 static device_method_t xlnx_pcib_fdt_methods[] = { 755 /* Device interface */ 756 DEVMETHOD(device_probe, xlnx_pcib_fdt_probe), 757 DEVMETHOD(device_attach, xlnx_pcib_fdt_attach), 758 759 /* pcib interface */ 760 DEVMETHOD(pcib_get_id, xlnx_pcib_fdt_get_id), 761 DEVMETHOD(pcib_read_config, xlnx_pcib_read_config), 762 DEVMETHOD(pcib_write_config, xlnx_pcib_write_config), 763 DEVMETHOD(pcib_alloc_msi, xlnx_pcib_alloc_msi), 764 DEVMETHOD(pcib_release_msi, xlnx_pcib_release_msi), 765 DEVMETHOD(pcib_map_msi, xlnx_pcib_map_msi), 766 767 /* MSI interface */ 768 DEVMETHOD(msi_alloc_msi, xlnx_pcib_msi_alloc_msi), 769 DEVMETHOD(msi_release_msi, xlnx_pcib_msi_release_msi), 770 DEVMETHOD(msi_map_msi, xlnx_pcib_msi_map_msi), 771 772 /* Interrupt controller interface */ 773 DEVMETHOD(pic_disable_intr, xlnx_pcib_msi_disable_intr), 774 DEVMETHOD(pic_enable_intr, xlnx_pcib_msi_enable_intr), 775 DEVMETHOD(pic_setup_intr, xlnx_pcib_msi_setup_intr), 776 DEVMETHOD(pic_teardown_intr, xlnx_pcib_msi_teardown_intr), 777 DEVMETHOD(pic_post_filter, xlnx_pcib_msi_post_filter), 778 DEVMETHOD(pic_post_ithread, xlnx_pcib_msi_post_ithread), 779 DEVMETHOD(pic_pre_ithread, xlnx_pcib_msi_pre_ithread), 780 781 /* End */ 782 DEVMETHOD_END 783 }; 784 785 DEFINE_CLASS_1(pcib, xlnx_pcib_fdt_driver, xlnx_pcib_fdt_methods, 786 sizeof(struct xlnx_pcib_softc), generic_pcie_fdt_driver); 787 788 DRIVER_MODULE(xlnx_pcib, simplebus, xlnx_pcib_fdt_driver, 0, 0); 789 DRIVER_MODULE(xlnx_pcib, ofwbus, xlnx_pcib_fdt_driver, 0, 0); 790