1 /*- 2 * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com> 3 * Copyright (c) 2014 The FreeBSD Foundation 4 * All rights reserved. 5 * 6 * This software was developed by Semihalf under 7 * the sponsorship of the FreeBSD Foundation. 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 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 /* Generic ECAM PCIe driver */ 32 33 #include <sys/cdefs.h> 34 __FBSDID("$FreeBSD$"); 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/malloc.h> 39 #include <sys/kernel.h> 40 #include <sys/rman.h> 41 #include <sys/module.h> 42 #include <sys/bus.h> 43 #include <sys/endian.h> 44 #include <sys/cpuset.h> 45 #include <sys/rwlock.h> 46 47 #include <dev/ofw/openfirm.h> 48 #include <dev/ofw/ofw_bus.h> 49 #include <dev/ofw/ofw_bus_subr.h> 50 #include <dev/ofw/ofw_pci.h> 51 #include <dev/pci/pcivar.h> 52 #include <dev/pci/pcireg.h> 53 #include <dev/pci/pcib_private.h> 54 55 #include <machine/cpu.h> 56 #include <machine/bus.h> 57 #include <machine/intr.h> 58 #include <vm/vm_page.h> 59 60 #include "pcib_if.h" 61 62 /* Assembling ECAM Configuration Address */ 63 #define PCIE_BUS_SHIFT 20 64 #define PCIE_SLOT_SHIFT 15 65 #define PCIE_FUNC_SHIFT 12 66 #define PCIE_BUS_MASK 0xFF 67 #define PCIE_SLOT_MASK 0x1F 68 #define PCIE_FUNC_MASK 0x07 69 #define PCIE_REG_MASK 0xFFF 70 71 #define PCIE_ADDR_OFFSET(bus, slot, func, reg) \ 72 ((((bus) & PCIE_BUS_MASK) << PCIE_BUS_SHIFT) | \ 73 (((slot) & PCIE_SLOT_MASK) << PCIE_SLOT_SHIFT) | \ 74 (((func) & PCIE_FUNC_MASK) << PCIE_FUNC_SHIFT) | \ 75 ((reg) & PCIE_REG_MASK)) 76 77 #define MAX_RANGES_TUPLES 5 78 #define MIN_RANGES_TUPLES 2 79 80 #define PCI_IO_WINDOW_OFFSET 0x1000 81 82 #define SPACE_CODE_SHIFT 24 83 #define SPACE_CODE_MASK 0x3 84 #define SPACE_CODE_IO_SPACE 0x1 85 #define PROPS_CELL_SIZE 1 86 #define PCI_ADDR_CELL_SIZE 2 87 88 struct pcie_range { 89 uint64_t pci_base; 90 uint64_t phys_base; 91 uint64_t size; 92 uint64_t flags; 93 #define FLAG_IO (1 << 0) 94 #define FLAG_MEM (1 << 1) 95 }; 96 97 struct generic_pcie_softc { 98 struct pcie_range ranges[MAX_RANGES_TUPLES]; 99 int nranges; 100 struct rman mem_rman; 101 struct rman io_rman; 102 struct resource *res; 103 struct resource *res1; 104 int ecam; 105 bus_space_tag_t bst; 106 bus_space_handle_t bsh; 107 device_t dev; 108 bus_space_handle_t ioh; 109 struct ofw_bus_iinfo pci_iinfo; 110 }; 111 112 /* Forward prototypes */ 113 114 static int generic_pcie_probe(device_t dev); 115 static int generic_pcie_attach(device_t dev); 116 static int parse_pci_mem_ranges(struct generic_pcie_softc *sc); 117 static uint32_t generic_pcie_read_config(device_t dev, u_int bus, u_int slot, 118 u_int func, u_int reg, int bytes); 119 static void generic_pcie_write_config(device_t dev, u_int bus, u_int slot, 120 u_int func, u_int reg, uint32_t val, int bytes); 121 static int generic_pcie_maxslots(device_t dev); 122 static int generic_pcie_read_ivar(device_t dev, device_t child, int index, 123 uintptr_t *result); 124 static int generic_pcie_write_ivar(device_t dev, device_t child, int index, 125 uintptr_t value); 126 static struct resource *generic_pcie_alloc_resource(device_t dev, 127 device_t child, int type, int *rid, rman_res_t start, rman_res_t end, 128 rman_res_t count, u_int flags); 129 static int generic_pcie_release_resource(device_t dev, device_t child, 130 int type, int rid, struct resource *res); 131 132 static int 133 generic_pcie_probe(device_t dev) 134 { 135 136 if (!ofw_bus_status_okay(dev)) 137 return (ENXIO); 138 139 if (ofw_bus_is_compatible(dev, "pci-host-ecam-generic")) { 140 device_set_desc(dev, "Generic PCI host controller"); 141 return (BUS_PROBE_DEFAULT); 142 } 143 144 return (ENXIO); 145 } 146 147 static int 148 generic_pcie_attach(device_t dev) 149 { 150 struct generic_pcie_softc *sc; 151 uint64_t phys_base; 152 uint64_t pci_base; 153 uint64_t size; 154 int error; 155 int tuple; 156 int rid; 157 158 sc = device_get_softc(dev); 159 sc->dev = dev; 160 161 rid = 0; 162 sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); 163 if (sc->res == NULL) { 164 device_printf(dev, "could not map memory.\n"); 165 return (ENXIO); 166 } 167 168 sc->bst = rman_get_bustag(sc->res); 169 sc->bsh = rman_get_bushandle(sc->res); 170 171 sc->mem_rman.rm_type = RMAN_ARRAY; 172 sc->mem_rman.rm_descr = "PCIe Memory"; 173 sc->io_rman.rm_type = RMAN_ARRAY; 174 sc->io_rman.rm_descr = "PCIe IO window"; 175 176 /* Retrieve 'ranges' property from FDT */ 177 if (bootverbose) 178 device_printf(dev, "parsing FDT for ECAM%d:\n", 179 sc->ecam); 180 if (parse_pci_mem_ranges(sc)) 181 return (ENXIO); 182 183 /* Initialize rman and allocate memory regions */ 184 error = rman_init(&sc->mem_rman); 185 if (error) { 186 device_printf(dev, "rman_init() failed. error = %d\n", error); 187 return (error); 188 } 189 190 error = rman_init(&sc->io_rman); 191 if (error) { 192 device_printf(dev, "rman_init() failed. error = %d\n", error); 193 return (error); 194 } 195 196 for (tuple = 0; tuple < MAX_RANGES_TUPLES; tuple++) { 197 phys_base = sc->ranges[tuple].phys_base; 198 pci_base = sc->ranges[tuple].pci_base; 199 size = sc->ranges[tuple].size; 200 if (phys_base == 0 || size == 0) 201 continue; /* empty range element */ 202 if (sc->ranges[tuple].flags & FLAG_MEM) { 203 error = rman_manage_region(&sc->mem_rman, 204 phys_base, 205 phys_base + size); 206 } else if (sc->ranges[tuple].flags & FLAG_IO) { 207 error = rman_manage_region(&sc->io_rman, 208 pci_base + PCI_IO_WINDOW_OFFSET, 209 pci_base + PCI_IO_WINDOW_OFFSET + size); 210 } else 211 continue; 212 if (error) { 213 device_printf(dev, "rman_manage_region() failed." 214 "error = %d\n", error); 215 rman_fini(&sc->mem_rman); 216 return (error); 217 } 218 } 219 220 ofw_bus_setup_iinfo(ofw_bus_get_node(dev), &sc->pci_iinfo, 221 sizeof(cell_t)); 222 223 224 device_add_child(dev, "pci", -1); 225 return (bus_generic_attach(dev)); 226 } 227 228 static int 229 parse_pci_mem_ranges(struct generic_pcie_softc *sc) 230 { 231 pcell_t pci_addr_cells, parent_addr_cells; 232 pcell_t attributes, size_cells; 233 cell_t *base_ranges; 234 int nbase_ranges; 235 phandle_t node; 236 int i, j, k; 237 int tuple; 238 239 node = ofw_bus_get_node(sc->dev); 240 241 OF_getencprop(node, "#address-cells", &pci_addr_cells, 242 sizeof(pci_addr_cells)); 243 OF_getencprop(node, "#size-cells", &size_cells, 244 sizeof(size_cells)); 245 OF_getencprop(OF_parent(node), "#address-cells", &parent_addr_cells, 246 sizeof(parent_addr_cells)); 247 248 if (parent_addr_cells != 2 || pci_addr_cells != 3 || size_cells != 2) { 249 device_printf(sc->dev, 250 "Unexpected number of address or size cells in FDT\n"); 251 return (ENXIO); 252 } 253 254 nbase_ranges = OF_getproplen(node, "ranges"); 255 sc->nranges = nbase_ranges / sizeof(cell_t) / 256 (parent_addr_cells + pci_addr_cells + size_cells); 257 base_ranges = malloc(nbase_ranges, M_DEVBUF, M_WAITOK); 258 OF_getencprop(node, "ranges", base_ranges, nbase_ranges); 259 260 for (i = 0, j = 0; i < sc->nranges; i++) { 261 attributes = (base_ranges[j++] >> SPACE_CODE_SHIFT) & \ 262 SPACE_CODE_MASK; 263 if (attributes == SPACE_CODE_IO_SPACE) { 264 sc->ranges[i].flags |= FLAG_IO; 265 } else { 266 sc->ranges[i].flags |= FLAG_MEM; 267 } 268 269 sc->ranges[i].pci_base = 0; 270 for (k = 0; k < (pci_addr_cells - 1); k++) { 271 sc->ranges[i].pci_base <<= 32; 272 sc->ranges[i].pci_base |= base_ranges[j++]; 273 } 274 sc->ranges[i].phys_base = 0; 275 for (k = 0; k < parent_addr_cells; k++) { 276 sc->ranges[i].phys_base <<= 32; 277 sc->ranges[i].phys_base |= base_ranges[j++]; 278 } 279 sc->ranges[i].size = 0; 280 for (k = 0; k < size_cells; k++) { 281 sc->ranges[i].size <<= 32; 282 sc->ranges[i].size |= base_ranges[j++]; 283 } 284 } 285 286 for (; i < MAX_RANGES_TUPLES; i++) { 287 /* zero-fill remaining tuples to mark empty elements in array */ 288 sc->ranges[i].pci_base = 0; 289 sc->ranges[i].phys_base = 0; 290 sc->ranges[i].size = 0; 291 } 292 293 if (bootverbose) { 294 for (tuple = 0; tuple < MAX_RANGES_TUPLES; tuple++) { 295 device_printf(sc->dev, 296 "\tPCI addr: 0x%jx, CPU addr: 0x%jx, Size: 0x%jx\n", 297 sc->ranges[tuple].pci_base, 298 sc->ranges[tuple].phys_base, 299 sc->ranges[tuple].size); 300 } 301 } 302 303 free(base_ranges, M_DEVBUF); 304 return (0); 305 } 306 307 static uint32_t 308 generic_pcie_read_config(device_t dev, u_int bus, u_int slot, 309 u_int func, u_int reg, int bytes) 310 { 311 struct generic_pcie_softc *sc; 312 bus_space_handle_t h; 313 bus_space_tag_t t; 314 uint64_t offset; 315 uint32_t data; 316 317 if (bus > 255 || slot > 31 || func > 7 || reg > 4095) 318 return (~0U); 319 320 sc = device_get_softc(dev); 321 322 offset = PCIE_ADDR_OFFSET(bus, slot, func, reg); 323 t = sc->bst; 324 h = sc->bsh; 325 326 switch (bytes) { 327 case 1: 328 data = bus_space_read_1(t, h, offset); 329 break; 330 case 2: 331 data = le16toh(bus_space_read_2(t, h, offset)); 332 break; 333 case 4: 334 data = le32toh(bus_space_read_4(t, h, offset)); 335 break; 336 default: 337 return (~0U); 338 } 339 340 return (data); 341 } 342 343 static void 344 generic_pcie_write_config(device_t dev, u_int bus, u_int slot, 345 u_int func, u_int reg, uint32_t val, int bytes) 346 { 347 struct generic_pcie_softc *sc; 348 bus_space_handle_t h; 349 bus_space_tag_t t; 350 uint64_t offset; 351 352 if (bus > 255 || slot > 31 || func > 7 || reg > 4095) 353 return; 354 355 sc = device_get_softc(dev); 356 357 offset = PCIE_ADDR_OFFSET(bus, slot, func, reg); 358 359 t = sc->bst; 360 h = sc->bsh; 361 362 switch (bytes) { 363 case 1: 364 bus_space_write_1(t, h, offset, val); 365 break; 366 case 2: 367 bus_space_write_2(t, h, offset, htole16(val)); 368 break; 369 case 4: 370 bus_space_write_4(t, h, offset, htole32(val)); 371 break; 372 default: 373 return; 374 } 375 } 376 377 static int 378 generic_pcie_maxslots(device_t dev) 379 { 380 381 return (31); /* max slots per bus acc. to standard */ 382 } 383 384 static int 385 generic_pcie_route_interrupt(device_t bus, device_t dev, int pin) 386 { 387 struct generic_pcie_softc *sc; 388 struct ofw_pci_register reg; 389 uint32_t pintr, mintr[2]; 390 phandle_t iparent; 391 int intrcells; 392 393 sc = device_get_softc(bus); 394 pintr = pin; 395 396 bzero(®, sizeof(reg)); 397 reg.phys_hi = (pci_get_bus(dev) << OFW_PCI_PHYS_HI_BUSSHIFT) | 398 (pci_get_slot(dev) << OFW_PCI_PHYS_HI_DEVICESHIFT) | 399 (pci_get_function(dev) << OFW_PCI_PHYS_HI_FUNCTIONSHIFT); 400 401 intrcells = ofw_bus_lookup_imap(ofw_bus_get_node(dev), 402 &sc->pci_iinfo, ®, sizeof(reg), &pintr, sizeof(pintr), 403 mintr, sizeof(mintr), &iparent); 404 if (intrcells) { 405 pintr = ofw_bus_map_intr(dev, iparent, intrcells, mintr); 406 return (pintr); 407 } 408 409 device_printf(bus, "could not route pin %d for device %d.%d\n", 410 pin, pci_get_slot(dev), pci_get_function(dev)); 411 return (PCI_INVALID_IRQ); 412 } 413 414 415 static int 416 generic_pcie_read_ivar(device_t dev, device_t child, int index, 417 uintptr_t *result) 418 { 419 struct generic_pcie_softc *sc; 420 int secondary_bus; 421 422 sc = device_get_softc(dev); 423 424 if (index == PCIB_IVAR_BUS) { 425 /* this pcib adds only pci bus 0 as child */ 426 secondary_bus = 0; 427 *result = secondary_bus; 428 return (0); 429 430 } 431 432 if (index == PCIB_IVAR_DOMAIN) { 433 *result = sc->ecam; 434 return (0); 435 } 436 437 device_printf(dev, "ERROR: Unknown index.\n"); 438 return (ENOENT); 439 } 440 441 static int 442 generic_pcie_write_ivar(device_t dev, device_t child, int index, 443 uintptr_t value) 444 { 445 446 return (ENOENT); 447 } 448 449 static struct rman * 450 generic_pcie_rman(struct generic_pcie_softc *sc, int type) 451 { 452 453 switch (type) { 454 case SYS_RES_IOPORT: 455 return (&sc->io_rman); 456 case SYS_RES_MEMORY: 457 return (&sc->mem_rman); 458 default: 459 break; 460 } 461 462 return (NULL); 463 } 464 465 static int 466 generic_pcie_release_resource(device_t dev, device_t child, int type, 467 int rid, struct resource *res) 468 { 469 struct generic_pcie_softc *sc; 470 struct rman *rm; 471 472 sc = device_get_softc(dev); 473 474 rm = generic_pcie_rman(sc, type); 475 if (rm != NULL) { 476 KASSERT(rman_is_region_manager(res, rm), ("rman mismatch")); 477 rman_release_resource(res); 478 } 479 480 return (bus_generic_release_resource(dev, child, type, rid, res)); 481 } 482 483 static struct resource * 484 generic_pcie_alloc_resource(device_t dev, device_t child, int type, int *rid, 485 rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) 486 { 487 struct generic_pcie_softc *sc; 488 struct resource *res; 489 struct rman *rm; 490 491 sc = device_get_softc(dev); 492 493 rm = generic_pcie_rman(sc, type); 494 if (rm == NULL) 495 return (BUS_ALLOC_RESOURCE(device_get_parent(dev), dev, 496 type, rid, start, end, count, flags)); 497 498 if (bootverbose) { 499 device_printf(dev, 500 "rman_reserve_resource: start=%#lx, end=%#lx, count=%#lx\n", 501 start, end, count); 502 } 503 504 res = rman_reserve_resource(rm, start, end, count, flags, child); 505 if (res == NULL) 506 goto fail; 507 508 rman_set_rid(res, *rid); 509 510 if (flags & RF_ACTIVE) 511 if (bus_activate_resource(child, type, *rid, res)) { 512 rman_release_resource(res); 513 goto fail; 514 } 515 516 return (res); 517 518 fail: 519 if (bootverbose) { 520 device_printf(dev, "%s FAIL: type=%d, rid=%d, " 521 "start=%016lx, end=%016lx, count=%016lx, flags=%x\n", 522 __func__, type, *rid, start, end, count, flags); 523 } 524 525 return (NULL); 526 } 527 528 static int 529 generic_pcie_adjust_resource(device_t dev, device_t child, int type, 530 struct resource *res, rman_res_t start, rman_res_t end) 531 { 532 struct generic_pcie_softc *sc; 533 struct rman *rm; 534 535 sc = device_get_softc(dev); 536 537 rm = generic_pcie_rman(sc, type); 538 if (rm != NULL) 539 return (rman_adjust_resource(res, start, end)); 540 return (bus_generic_adjust_resource(dev, child, type, res, start, end)); 541 } 542 543 static int 544 generic_pcie_activate_resource(device_t dev, device_t child, int type, int rid, 545 struct resource *r) 546 { 547 struct generic_pcie_softc *sc; 548 uint64_t phys_base; 549 uint64_t pci_base; 550 uint64_t size; 551 int found; 552 int res; 553 int i; 554 555 sc = device_get_softc(dev); 556 557 if ((res = rman_activate_resource(r)) != 0) 558 return (res); 559 560 switch(type) { 561 case SYS_RES_IOPORT: 562 found = 0; 563 for (i = 0; i < MAX_RANGES_TUPLES; i++) { 564 pci_base = sc->ranges[i].pci_base; 565 phys_base = sc->ranges[i].phys_base; 566 size = sc->ranges[i].size; 567 568 if ((rid > pci_base) && (rid < (pci_base + size))) { 569 found = 1; 570 break; 571 } 572 } 573 if (found) { 574 rman_set_start(r, rman_get_start(r) + phys_base); 575 BUS_ACTIVATE_RESOURCE(device_get_parent(dev), child, 576 type, rid, r); 577 } else { 578 device_printf(dev, "Failed to activate IOPORT resource\n"); 579 res = 0; 580 } 581 break; 582 case SYS_RES_MEMORY: 583 BUS_ACTIVATE_RESOURCE(device_get_parent(dev), child, type, rid, r); 584 break; 585 default: 586 break; 587 } 588 589 return (res); 590 } 591 592 static int 593 generic_pcie_deactivate_resource(device_t dev, device_t child, int type, int rid, 594 struct resource *r) 595 { 596 struct generic_pcie_softc *sc; 597 vm_offset_t vaddr; 598 int res; 599 600 sc = device_get_softc(dev); 601 602 if ((res = rman_deactivate_resource(r)) != 0) 603 return (res); 604 605 switch(type) { 606 case SYS_RES_IOPORT: 607 case SYS_RES_MEMORY: 608 vaddr = (vm_offset_t)rman_get_virtual(r); 609 pmap_unmapdev(vaddr, rman_get_size(r)); 610 break; 611 default: 612 break; 613 } 614 615 return (res); 616 } 617 618 static device_method_t generic_pcie_methods[] = { 619 DEVMETHOD(device_probe, generic_pcie_probe), 620 DEVMETHOD(device_attach, generic_pcie_attach), 621 DEVMETHOD(bus_read_ivar, generic_pcie_read_ivar), 622 DEVMETHOD(bus_write_ivar, generic_pcie_write_ivar), 623 DEVMETHOD(bus_alloc_resource, generic_pcie_alloc_resource), 624 DEVMETHOD(bus_adjust_resource, generic_pcie_adjust_resource), 625 DEVMETHOD(bus_release_resource, generic_pcie_release_resource), 626 DEVMETHOD(bus_activate_resource, generic_pcie_activate_resource), 627 DEVMETHOD(bus_deactivate_resource, generic_pcie_deactivate_resource), 628 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 629 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 630 631 /* pcib interface */ 632 DEVMETHOD(pcib_maxslots, generic_pcie_maxslots), 633 DEVMETHOD(pcib_route_interrupt, generic_pcie_route_interrupt), 634 DEVMETHOD(pcib_read_config, generic_pcie_read_config), 635 DEVMETHOD(pcib_write_config, generic_pcie_write_config), 636 #if defined(__aarch64__) 637 DEVMETHOD(pcib_alloc_msi, arm_alloc_msi), 638 DEVMETHOD(pcib_release_msi, arm_release_msi), 639 DEVMETHOD(pcib_alloc_msix, arm_alloc_msix), 640 DEVMETHOD(pcib_release_msix, arm_release_msix), 641 DEVMETHOD(pcib_map_msi, arm_map_msi), 642 #endif 643 644 DEVMETHOD_END 645 }; 646 647 static driver_t generic_pcie_driver = { 648 "pcib", 649 generic_pcie_methods, 650 sizeof(struct generic_pcie_softc), 651 }; 652 653 static devclass_t generic_pcie_devclass; 654 655 DRIVER_MODULE(pcib, simplebus, generic_pcie_driver, 656 generic_pcie_devclass, 0, 0); 657 DRIVER_MODULE(pcib, ofwbus, generic_pcie_driver, 658 generic_pcie_devclass, 0, 0); 659