1 /*- 2 * Copyright (c) 2015-2016 Landon Fuller <landon@landonf.org> 3 * Copyright (c) 2017 The FreeBSD Foundation 4 * All rights reserved. 5 * 6 * Portions of this software were developed by Landon Fuller 7 * under sponsorship from 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 * without modification. 15 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 16 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 17 * redistribution must be conditioned upon including a substantially 18 * similar Disclaimer requirement for further binary redistribution. 19 * 20 * NO WARRANTY 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 24 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 25 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 26 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 29 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 * THE POSSIBILITY OF SUCH DAMAGES. 32 */ 33 34 #include <sys/cdefs.h> 35 __FBSDID("$FreeBSD$"); 36 37 /* 38 * PCI-specific implementation for the BHNDB bridge driver. 39 * 40 * Provides support for bridging from a PCI parent bus to a BHND-compatible 41 * bus (e.g. bcma or siba) via a Broadcom PCI core configured in end-point 42 * mode. 43 * 44 * This driver handles all initial generic host-level PCI interactions with a 45 * PCI/PCIe bridge core operating in endpoint mode. Once the bridged bhnd(4) 46 * bus has been enumerated, this driver works in tandem with a core-specific 47 * bhnd_pci_hostb driver to manage the PCI core. 48 */ 49 50 #include <sys/param.h> 51 #include <sys/kernel.h> 52 #include <sys/bus.h> 53 #include <sys/limits.h> 54 #include <sys/malloc.h> 55 #include <sys/module.h> 56 #include <sys/systm.h> 57 58 #include <dev/pci/pcireg.h> 59 #include <dev/pci/pcivar.h> 60 61 #include <dev/bhnd/bhnd.h> 62 #include <dev/bhnd/bhndreg.h> 63 64 #include <dev/bhnd/bhnd_erom.h> 65 #include <dev/bhnd/bhnd_eromvar.h> 66 67 #include <dev/bhnd/cores/pci/bhnd_pcireg.h> 68 69 #include "bhndb_pcireg.h" 70 #include "bhndb_pcivar.h" 71 #include "bhndb_private.h" 72 73 struct bhndb_pci_eio; 74 75 static int bhndb_pci_init_msi(struct bhndb_pci_softc *sc); 76 static int bhndb_pci_read_core_table(device_t dev, 77 struct bhnd_chipid *chipid, 78 struct bhnd_core_info **cores, u_int *ncores, 79 bhnd_erom_class_t **eromcls); 80 static int bhndb_pci_add_children(struct bhndb_pci_softc *sc); 81 82 static bool bhndb_is_pcie_attached(device_t dev); 83 84 static int bhndb_enable_pci_clocks(device_t dev); 85 static int bhndb_disable_pci_clocks(device_t dev); 86 87 static int bhndb_pci_compat_setregwin(device_t dev, 88 device_t pci_dev, const struct bhndb_regwin *, 89 bhnd_addr_t); 90 static int bhndb_pci_fast_setregwin(device_t dev, device_t pci_dev, 91 const struct bhndb_regwin *, bhnd_addr_t); 92 93 static void bhndb_init_sromless_pci_config( 94 struct bhndb_pci_softc *sc); 95 96 static bus_addr_t bhndb_pci_sprom_addr(struct bhndb_pci_softc *sc); 97 static bus_size_t bhndb_pci_sprom_size(struct bhndb_pci_softc *sc); 98 99 static int bhndb_pci_eio_init(struct bhndb_pci_eio *pio, 100 device_t dev, device_t pci_dev, 101 struct bhndb_host_resources *hr); 102 static int bhndb_pci_eio_map(struct bhnd_erom_io *eio, 103 bhnd_addr_t addr, bhnd_size_t size); 104 static uint32_t bhndb_pci_eio_read(struct bhnd_erom_io *eio, 105 bhnd_size_t offset, u_int width); 106 107 #define BHNDB_PCI_MSI_COUNT 1 108 109 /* bhndb_pci erom I/O implementation */ 110 struct bhndb_pci_eio { 111 struct bhnd_erom_io eio; 112 device_t dev; /**< bridge device */ 113 device_t pci_dev; /**< parent PCI device */ 114 struct bhndb_host_resources *hr; /**< borrowed reference to host resources */ 115 const struct bhndb_regwin *win; /**< mapped register window, or NULL */ 116 struct resource *res; /**< resource containing the register window, or NULL if no window mapped */ 117 bhnd_addr_t res_target; /**< current target address (if mapped) */ 118 bool mapped; /**< true if a valid mapping exists, false otherwise */ 119 bhnd_addr_t addr; /**< mapped address */ 120 bhnd_size_t size; /**< mapped size */ 121 }; 122 123 /** 124 * Default bhndb_pci implementation of device_probe(). 125 * 126 * Verifies that the parent is a PCI/PCIe device. 127 */ 128 static int 129 bhndb_pci_probe(device_t dev) 130 { 131 device_t parent; 132 devclass_t parent_bus; 133 devclass_t pci; 134 135 /* Our parent must be a PCI/PCIe device. */ 136 pci = devclass_find("pci"); 137 parent = device_get_parent(dev); 138 parent_bus = device_get_devclass(device_get_parent(parent)); 139 140 if (parent_bus != pci) 141 return (ENXIO); 142 143 device_set_desc(dev, "PCI-BHND bridge"); 144 145 return (BUS_PROBE_DEFAULT); 146 } 147 148 /* Configure MSI interrupts */ 149 static int 150 bhndb_pci_init_msi(struct bhndb_pci_softc *sc) 151 { 152 int error; 153 154 /* Is MSI available? */ 155 if (pci_msi_count(sc->parent) < BHNDB_PCI_MSI_COUNT) 156 return (ENXIO); 157 158 /* Allocate expected message count */ 159 sc->intr.msi_count = BHNDB_PCI_MSI_COUNT; 160 if ((error = pci_alloc_msi(sc->parent, &sc->intr.msi_count))) { 161 device_printf(sc->dev, "failed to allocate MSI interrupts: " 162 "%d\n", error); 163 return (error); 164 } 165 166 if (sc->intr.msi_count < BHNDB_PCI_MSI_COUNT) 167 return (ENXIO); 168 169 /* MSI uses resource IDs starting at 1 */ 170 sc->intr.intr_rid = 1; 171 172 return (0); 173 } 174 175 static int 176 bhndb_pci_attach(device_t dev) 177 { 178 struct bhndb_pci_softc *sc; 179 struct bhnd_chipid cid; 180 struct bhnd_core_info *cores, hostb_core; 181 bhnd_erom_class_t *erom_class; 182 u_int ncores; 183 int error, reg; 184 185 sc = device_get_softc(dev); 186 sc->dev = dev; 187 sc->parent = device_get_parent(dev); 188 sc->set_regwin = NULL; 189 190 cores = NULL; 191 192 /* Enable PCI bus mastering */ 193 pci_enable_busmaster(sc->parent); 194 195 /* Set up PCI interrupt handling */ 196 if (bhndb_pci_init_msi(sc) == 0) { 197 device_printf(dev, "Using MSI interrupts on %s\n", 198 device_get_nameunit(sc->parent)); 199 } else { 200 device_printf(dev, "Using INTx interrupts on %s\n", 201 device_get_nameunit(sc->parent)); 202 sc->intr.intr_rid = 0; 203 } 204 205 /* Determine our bridge device class */ 206 sc->pci_devclass = BHND_DEVCLASS_PCI; 207 if (pci_find_cap(sc->parent, PCIY_EXPRESS, ®) == 0) 208 sc->pci_devclass = BHND_DEVCLASS_PCIE; 209 else 210 sc->pci_devclass = BHND_DEVCLASS_PCI; 211 212 /* Enable clocks (if required by this hardware) */ 213 if ((error = bhndb_enable_pci_clocks(sc->dev))) 214 goto cleanup; 215 216 /* Identify the chip and enumerate the bridged cores */ 217 error = bhndb_pci_read_core_table(dev, &cid, &cores, &ncores, 218 &erom_class); 219 if (error) 220 goto cleanup; 221 222 /* Select the appropriate register window handler */ 223 if (cid.chip_type == BHND_CHIPTYPE_SIBA) { 224 sc->set_regwin = bhndb_pci_compat_setregwin; 225 } else { 226 sc->set_regwin = bhndb_pci_fast_setregwin; 227 } 228 229 /* Determine our host bridge core */ 230 error = bhndb_find_hostb_core(cores, ncores, sc->pci_devclass, 231 &hostb_core); 232 if (error) 233 goto cleanup; 234 235 /* Perform bridge attach */ 236 error = bhndb_attach(dev, &cid, cores, ncores, &hostb_core, erom_class); 237 if (error) 238 goto cleanup; 239 240 /* Fix-up power on defaults for SROM-less devices. */ 241 bhndb_init_sromless_pci_config(sc); 242 243 /* Add any additional child devices */ 244 if ((error = bhndb_pci_add_children(sc))) 245 goto cleanup; 246 247 /* Probe and attach our children */ 248 if ((error = bus_generic_attach(dev))) 249 goto cleanup; 250 251 free(cores, M_BHND); 252 253 return (0); 254 255 cleanup: 256 device_delete_children(dev); 257 bhndb_disable_pci_clocks(sc->dev); 258 259 if (sc->intr.msi_count > 0) 260 pci_release_msi(dev); 261 262 if (cores != NULL) 263 free(cores, M_BHND); 264 265 pci_disable_busmaster(sc->parent); 266 267 return (error); 268 } 269 270 static int 271 bhndb_pci_detach(device_t dev) 272 { 273 struct bhndb_pci_softc *sc; 274 int error; 275 276 sc = device_get_softc(dev); 277 278 /* Attempt to detach our children */ 279 if ((error = bus_generic_detach(dev))) 280 return (error); 281 282 /* Perform generic bridge detach */ 283 if ((error = bhndb_generic_detach(dev))) 284 return (error); 285 286 /* Disable clocks (if required by this hardware) */ 287 if ((error = bhndb_disable_pci_clocks(sc->dev))) 288 return (error); 289 290 /* Release MSI interrupts */ 291 if (sc->intr.msi_count > 0) 292 pci_release_msi(dev); 293 294 /* Disable PCI bus mastering */ 295 pci_disable_busmaster(sc->parent); 296 297 return (0); 298 } 299 300 /** 301 * Use the generic PCI bridge hardware configuration to enumerate the bridged 302 * bhnd(4) bus' core table. 303 * 304 * @note This function may be safely called prior to device attach, (e.g. 305 * from DEVICE_PROBE). 306 * @note This function requires exclusive ownership over allocating and 307 * configuring host bridge resources, and should only be called prior to 308 * completion of device attach and full configuration of the bridge. 309 * 310 * @param dev The bhndb_pci bridge device. 311 * @param[out] chipid On success, the parsed chip identification. 312 * @param[out] cores On success, the enumerated core table. The 313 * caller is responsible for freeing this table via 314 * bhndb_pci_free_core_table(). 315 * @param[out] ncores On success, the number of cores found in 316 * @p cores. 317 * @param[out] eromcls On success, a pointer to the erom class used to 318 * parse the device enumeration table. This 319 * argument may be NULL if the class is not 320 * desired. 321 * 322 * @retval 0 success 323 * @retval non-zero if enumerating the bridged bhnd(4) bus fails, a regular 324 * unix error code will be returned. 325 */ 326 static int 327 bhndb_pci_read_core_table(device_t dev, struct bhnd_chipid *chipid, 328 struct bhnd_core_info **cores, u_int *ncores, 329 bhnd_erom_class_t **eromcls) 330 { 331 const struct bhndb_hwcfg *cfg; 332 struct bhndb_host_resources *hr; 333 struct bhndb_pci_eio pio; 334 struct bhnd_core_info *erom_cores; 335 const struct bhnd_chipid *hint; 336 struct bhnd_chipid cid; 337 bhnd_erom_class_t *erom_class; 338 bhnd_erom_t *erom; 339 device_t parent_dev; 340 u_int erom_ncores; 341 int error; 342 343 parent_dev = device_get_parent(dev); 344 erom = NULL; 345 erom_cores = NULL; 346 347 /* Fetch our chipid hint (if any) and generic hardware configuration */ 348 cfg = BHNDB_BUS_GET_GENERIC_HWCFG(parent_dev, dev); 349 hint = BHNDB_BUS_GET_CHIPID(parent_dev, dev); 350 351 /* Allocate our host resources */ 352 if ((error = bhndb_alloc_host_resources(parent_dev, cfg, &hr))) 353 return (error); 354 355 /* Initialize our erom I/O state */ 356 if ((error = bhndb_pci_eio_init(&pio, dev, parent_dev, hr))) 357 goto failed; 358 359 /* Map the first bus core from our bridged bhnd(4) bus */ 360 error = bhndb_pci_eio_map(&pio.eio, BHND_DEFAULT_CHIPC_ADDR, 361 BHND_DEFAULT_CORE_SIZE); 362 if (error) 363 goto failed; 364 365 /* Probe for a usable EROM class, and read the chip identifier */ 366 erom_class = bhnd_erom_probe_driver_classes(device_get_devclass(dev), 367 &pio.eio, hint, &cid); 368 if (erom_class == NULL) { 369 device_printf(dev, "device enumeration unsupported; no " 370 "compatible driver found\n"); 371 372 error = ENXIO; 373 goto failed; 374 } 375 376 /* Allocate EROM parser */ 377 if ((erom = bhnd_erom_alloc(erom_class, &cid, &pio.eio)) == NULL) { 378 device_printf(dev, "failed to allocate device enumeration " 379 "table parser\n"); 380 error = ENXIO; 381 goto failed; 382 } 383 384 /* Read the full core table */ 385 error = bhnd_erom_get_core_table(erom, &erom_cores, &erom_ncores); 386 if (error) { 387 device_printf(dev, "error fetching core table: %d\n", error); 388 goto failed; 389 } 390 391 /* Provide the results to our caller */ 392 *cores = malloc(sizeof(erom_cores[0]) * erom_ncores, M_BHND, M_WAITOK); 393 memcpy(*cores, erom_cores, sizeof(erom_cores[0]) * erom_ncores); 394 *ncores = erom_ncores; 395 396 *chipid = cid; 397 if (eromcls != NULL) 398 *eromcls = erom_class; 399 400 /* Clean up */ 401 bhnd_erom_free_core_table(erom, erom_cores); 402 bhnd_erom_free(erom); 403 bhndb_release_host_resources(hr); 404 405 return (0); 406 407 failed: 408 if (erom_cores != NULL) 409 bhnd_erom_free_core_table(erom, erom_cores); 410 411 if (erom != NULL) 412 bhnd_erom_free(erom); 413 414 bhndb_release_host_resources(hr); 415 return (error); 416 } 417 418 static int 419 bhndb_pci_add_children(struct bhndb_pci_softc *sc) 420 { 421 bus_size_t nv_sz; 422 int error; 423 424 /** 425 * If SPROM is mapped directly into BAR0, add child NVRAM 426 * device. 427 */ 428 nv_sz = bhndb_pci_sprom_size(sc); 429 if (nv_sz > 0) { 430 struct bhndb_devinfo *dinfo; 431 device_t child; 432 433 if (bootverbose) { 434 device_printf(sc->dev, "found SPROM (%ju bytes)\n", 435 (uintmax_t)nv_sz); 436 } 437 438 /* Add sprom device, ordered early enough to be available 439 * before the bridged bhnd(4) bus is attached. */ 440 child = BUS_ADD_CHILD(sc->dev, 441 BHND_PROBE_ROOT + BHND_PROBE_ORDER_EARLY, "bhnd_nvram", -1); 442 if (child == NULL) { 443 device_printf(sc->dev, "failed to add sprom device\n"); 444 return (ENXIO); 445 } 446 447 /* Initialize device address space and resource covering the 448 * BAR0 SPROM shadow. */ 449 dinfo = device_get_ivars(child); 450 dinfo->addrspace = BHNDB_ADDRSPACE_NATIVE; 451 452 error = bus_set_resource(child, SYS_RES_MEMORY, 0, 453 bhndb_pci_sprom_addr(sc), nv_sz); 454 if (error) { 455 device_printf(sc->dev, 456 "failed to register sprom resources\n"); 457 return (error); 458 } 459 } 460 461 return (0); 462 } 463 464 static const struct bhndb_regwin * 465 bhndb_pci_sprom_regwin(struct bhndb_pci_softc *sc) 466 { 467 struct bhndb_resources *bres; 468 const struct bhndb_hwcfg *cfg; 469 const struct bhndb_regwin *sprom_win; 470 471 bres = sc->bhndb.bus_res; 472 cfg = bres->cfg; 473 474 sprom_win = bhndb_regwin_find_type(cfg->register_windows, 475 BHNDB_REGWIN_T_SPROM, BHNDB_PCI_V0_BAR0_SPROM_SIZE); 476 477 return (sprom_win); 478 } 479 480 static bus_addr_t 481 bhndb_pci_sprom_addr(struct bhndb_pci_softc *sc) 482 { 483 const struct bhndb_regwin *sprom_win; 484 struct resource *r; 485 486 /* Fetch the SPROM register window */ 487 sprom_win = bhndb_pci_sprom_regwin(sc); 488 KASSERT(sprom_win != NULL, ("requested sprom address on PCI_V2+")); 489 490 /* Fetch the associated resource */ 491 r = bhndb_host_resource_for_regwin(sc->bhndb.bus_res->res, sprom_win); 492 KASSERT(r != NULL, ("missing resource for sprom window\n")); 493 494 return (rman_get_start(r) + sprom_win->win_offset); 495 } 496 497 static bus_size_t 498 bhndb_pci_sprom_size(struct bhndb_pci_softc *sc) 499 { 500 const struct bhndb_regwin *sprom_win; 501 uint32_t sctl; 502 bus_size_t sprom_sz; 503 504 sprom_win = bhndb_pci_sprom_regwin(sc); 505 506 /* PCI_V2 and later devices map SPROM/OTP via ChipCommon */ 507 if (sprom_win == NULL) 508 return (0); 509 510 /* Determine SPROM size */ 511 sctl = pci_read_config(sc->parent, BHNDB_PCI_SPROM_CONTROL, 4); 512 if (sctl & BHNDB_PCI_SPROM_BLANK) 513 return (0); 514 515 switch (sctl & BHNDB_PCI_SPROM_SZ_MASK) { 516 case BHNDB_PCI_SPROM_SZ_1KB: 517 sprom_sz = (1 * 1024); 518 break; 519 520 case BHNDB_PCI_SPROM_SZ_4KB: 521 sprom_sz = (4 * 1024); 522 break; 523 524 case BHNDB_PCI_SPROM_SZ_16KB: 525 sprom_sz = (16 * 1024); 526 break; 527 528 case BHNDB_PCI_SPROM_SZ_RESERVED: 529 default: 530 device_printf(sc->dev, "invalid PCI sprom size 0x%x\n", sctl); 531 return (0); 532 } 533 534 if (sprom_sz > sprom_win->win_size) { 535 device_printf(sc->dev, 536 "PCI sprom size (0x%x) overruns defined register window\n", 537 sctl); 538 return (0); 539 } 540 541 return (sprom_sz); 542 } 543 544 /* 545 * On devices without a SROM, the PCI(e) cores will be initialized with 546 * their Power-on-Reset defaults; this can leave two of the BAR0 PCI windows 547 * mapped to the wrong core. 548 * 549 * This function updates the SROM shadow to point the BAR0 windows at the 550 * current PCI core. 551 * 552 * Applies to all PCI/PCIe revisions. 553 */ 554 static void 555 bhndb_init_sromless_pci_config(struct bhndb_pci_softc *sc) 556 { 557 struct bhndb_resources *bres; 558 const struct bhndb_hwcfg *cfg; 559 const struct bhndb_regwin *win; 560 struct bhnd_core_info hostb_core; 561 struct resource *core_regs; 562 bus_size_t srom_offset; 563 u_int pci_cidx, sprom_cidx; 564 uint16_t val; 565 int error; 566 567 bres = sc->bhndb.bus_res; 568 cfg = bres->cfg; 569 570 /* Find our hostb core */ 571 error = BHNDB_GET_HOSTB_CORE(sc->dev, sc->bhndb.bus_dev, &hostb_core); 572 if (error) { 573 device_printf(sc->dev, "no host bridge device found\n"); 574 return; 575 } 576 577 if (hostb_core.vendor != BHND_MFGID_BCM) 578 return; 579 580 switch (hostb_core.device) { 581 case BHND_COREID_PCI: 582 srom_offset = BHND_PCI_SRSH_PI_OFFSET; 583 break; 584 case BHND_COREID_PCIE: 585 srom_offset = BHND_PCIE_SRSH_PI_OFFSET; 586 break; 587 default: 588 device_printf(sc->dev, "unsupported PCI host bridge device\n"); 589 return; 590 } 591 592 /* Locate the static register window mapping the PCI core */ 593 win = bhndb_regwin_find_core(cfg->register_windows, sc->pci_devclass, 594 0, BHND_PORT_DEVICE, 0, 0); 595 if (win == NULL) { 596 device_printf(sc->dev, "missing PCI core register window\n"); 597 return; 598 } 599 600 /* Fetch the resource containing the register window */ 601 core_regs = bhndb_host_resource_for_regwin(bres->res, win); 602 if (core_regs == NULL) { 603 device_printf(sc->dev, "missing PCI core register resource\n"); 604 return; 605 } 606 607 /* Fetch the SPROM's configured core index */ 608 val = bus_read_2(core_regs, win->win_offset + srom_offset); 609 sprom_cidx = (val & BHND_PCI_SRSH_PI_MASK) >> BHND_PCI_SRSH_PI_SHIFT; 610 611 /* If it doesn't match host bridge's core index, update the index 612 * value */ 613 pci_cidx = hostb_core.core_idx; 614 if (sprom_cidx != pci_cidx) { 615 val &= ~BHND_PCI_SRSH_PI_MASK; 616 val |= (pci_cidx << BHND_PCI_SRSH_PI_SHIFT); 617 bus_write_2(core_regs, 618 win->win_offset + srom_offset, val); 619 } 620 } 621 622 static int 623 bhndb_pci_resume(device_t dev) 624 { 625 struct bhndb_pci_softc *sc; 626 int error; 627 628 sc = device_get_softc(dev); 629 630 /* Enable clocks (if supported by this hardware) */ 631 if ((error = bhndb_enable_pci_clocks(sc->dev))) 632 return (error); 633 634 /* Perform resume */ 635 return (bhndb_generic_resume(dev)); 636 } 637 638 static int 639 bhndb_pci_suspend(device_t dev) 640 { 641 struct bhndb_pci_softc *sc; 642 int error; 643 644 sc = device_get_softc(dev); 645 646 /* Disable clocks (if supported by this hardware) */ 647 if ((error = bhndb_disable_pci_clocks(sc->dev))) 648 return (error); 649 650 /* Perform suspend */ 651 return (bhndb_generic_suspend(dev)); 652 } 653 654 static int 655 bhndb_pci_set_window_addr(device_t dev, const struct bhndb_regwin *rw, 656 bhnd_addr_t addr) 657 { 658 struct bhndb_pci_softc *sc = device_get_softc(dev); 659 return (sc->set_regwin(sc->dev, sc->parent, rw, addr)); 660 } 661 662 /** 663 * A siba(4) and bcma(4)-compatible bhndb_set_window_addr implementation. 664 * 665 * On siba(4) devices, it's possible that writing a PCI window register may 666 * not succeed; it's necessary to immediately read the configuration register 667 * and retry if not set to the desired value. 668 * 669 * This is not necessary on bcma(4) devices, but other than the overhead of 670 * validating the register, there's no harm in performing the verification. 671 */ 672 static int 673 bhndb_pci_compat_setregwin(device_t dev, device_t pci_dev, 674 const struct bhndb_regwin *rw, bhnd_addr_t addr) 675 { 676 int error; 677 int reg; 678 679 if (rw->win_type != BHNDB_REGWIN_T_DYN) 680 return (ENODEV); 681 682 reg = rw->d.dyn.cfg_offset; 683 for (u_int i = 0; i < BHNDB_PCI_BARCTRL_WRITE_RETRY; i++) { 684 if ((error = bhndb_pci_fast_setregwin(dev, pci_dev, rw, addr))) 685 return (error); 686 687 if (pci_read_config(pci_dev, reg, 4) == addr) 688 return (0); 689 690 DELAY(10); 691 } 692 693 /* Unable to set window */ 694 return (ENODEV); 695 } 696 697 /** 698 * A bcma(4)-only bhndb_set_window_addr implementation. 699 */ 700 static int 701 bhndb_pci_fast_setregwin(device_t dev, device_t pci_dev, 702 const struct bhndb_regwin *rw, bhnd_addr_t addr) 703 { 704 /* The PCI bridge core only supports 32-bit addressing, regardless 705 * of the bus' support for 64-bit addressing */ 706 if (addr > UINT32_MAX) 707 return (ERANGE); 708 709 switch (rw->win_type) { 710 case BHNDB_REGWIN_T_DYN: 711 /* Addresses must be page aligned */ 712 if (addr % rw->win_size != 0) 713 return (EINVAL); 714 715 pci_write_config(pci_dev, rw->d.dyn.cfg_offset, addr, 4); 716 break; 717 default: 718 return (ENODEV); 719 } 720 721 return (0); 722 } 723 724 static int 725 bhndb_pci_populate_board_info(device_t dev, device_t child, 726 struct bhnd_board_info *info) 727 { 728 struct bhndb_pci_softc *sc; 729 730 sc = device_get_softc(dev); 731 732 /* 733 * On a subset of Apple BCM4360 modules, always prefer the 734 * PCI subdevice to the SPROM-supplied boardtype. 735 * 736 * TODO: 737 * 738 * Broadcom's own drivers implement this override, and then later use 739 * the remapped BCM4360 board type to determine the required 740 * board-specific workarounds. 741 * 742 * Without access to this hardware, it's unclear why this mapping 743 * is done, and we must do the same. If we can survey the hardware 744 * in question, it may be possible to replace this behavior with 745 * explicit references to the SPROM-supplied boardtype(s) in our 746 * quirk definitions. 747 */ 748 if (pci_get_subvendor(sc->parent) == PCI_VENDOR_APPLE) { 749 switch (info->board_type) { 750 case BHND_BOARD_BCM94360X29C: 751 case BHND_BOARD_BCM94360X29CP2: 752 case BHND_BOARD_BCM94360X51: 753 case BHND_BOARD_BCM94360X51P2: 754 info->board_type = 0; /* allow override below */ 755 break; 756 default: 757 break; 758 } 759 } 760 761 /* If NVRAM did not supply vendor/type info, provide the PCI 762 * subvendor/subdevice values. */ 763 if (info->board_vendor == 0) 764 info->board_vendor = pci_get_subvendor(sc->parent); 765 766 if (info->board_type == 0) 767 info->board_type = pci_get_subdevice(sc->parent); 768 769 return (0); 770 } 771 772 /** 773 * Return true if the bridge device @p bhndb is attached via PCIe, 774 * false otherwise. 775 * 776 * @param dev The bhndb bridge device 777 */ 778 static bool 779 bhndb_is_pcie_attached(device_t dev) 780 { 781 int reg; 782 783 if (pci_find_cap(device_get_parent(dev), PCIY_EXPRESS, ®) == 0) 784 return (true); 785 786 return (false); 787 } 788 789 /** 790 * Enable externally managed clocks, if required. 791 * 792 * Some PCI chipsets (BCM4306, possibly others) chips do not support 793 * the idle low-power clock. Clocking must be bootstrapped at 794 * attach/resume by directly adjusting GPIO registers exposed in the 795 * PCI config space, and correspondingly, explicitly shutdown at 796 * detach/suspend. 797 * 798 * @note This function may be safely called prior to device attach, (e.g. 799 * from DEVICE_PROBE). 800 * 801 * @param dev The bhndb bridge device 802 */ 803 static int 804 bhndb_enable_pci_clocks(device_t dev) 805 { 806 device_t pci_dev; 807 uint32_t gpio_in, gpio_out, gpio_en; 808 uint32_t gpio_flags; 809 uint16_t pci_status; 810 811 pci_dev = device_get_parent(dev); 812 813 /* Only supported and required on PCI devices */ 814 if (!bhndb_is_pcie_attached(dev)) 815 return (0); 816 817 /* Read state of XTAL pin */ 818 gpio_in = pci_read_config(pci_dev, BHNDB_PCI_GPIO_IN, 4); 819 if (gpio_in & BHNDB_PCI_GPIO_XTAL_ON) 820 return (0); /* already enabled */ 821 822 /* Fetch current config */ 823 gpio_out = pci_read_config(pci_dev, BHNDB_PCI_GPIO_OUT, 4); 824 gpio_en = pci_read_config(pci_dev, BHNDB_PCI_GPIO_OUTEN, 4); 825 826 /* Set PLL_OFF/XTAL_ON pins to HIGH and enable both pins */ 827 gpio_flags = (BHNDB_PCI_GPIO_PLL_OFF|BHNDB_PCI_GPIO_XTAL_ON); 828 gpio_out |= gpio_flags; 829 gpio_en |= gpio_flags; 830 831 pci_write_config(pci_dev, BHNDB_PCI_GPIO_OUT, gpio_out, 4); 832 pci_write_config(pci_dev, BHNDB_PCI_GPIO_OUTEN, gpio_en, 4); 833 DELAY(1000); 834 835 /* Reset PLL_OFF */ 836 gpio_out &= ~BHNDB_PCI_GPIO_PLL_OFF; 837 pci_write_config(pci_dev, BHNDB_PCI_GPIO_OUT, gpio_out, 4); 838 DELAY(5000); 839 840 /* Clear any PCI 'sent target-abort' flag. */ 841 pci_status = pci_read_config(pci_dev, PCIR_STATUS, 2); 842 pci_status &= ~PCIM_STATUS_STABORT; 843 pci_write_config(pci_dev, PCIR_STATUS, pci_status, 2); 844 845 return (0); 846 } 847 848 /** 849 * Disable externally managed clocks, if required. 850 * 851 * This function may be safely called prior to device attach, (e.g. 852 * from DEVICE_PROBE). 853 * 854 * @param dev The bhndb bridge device 855 */ 856 static int 857 bhndb_disable_pci_clocks(device_t dev) 858 { 859 device_t pci_dev; 860 uint32_t gpio_out, gpio_en; 861 862 pci_dev = device_get_parent(dev); 863 864 /* Only supported and required on PCI devices */ 865 if (bhndb_is_pcie_attached(dev)) 866 return (0); 867 868 /* Fetch current config */ 869 gpio_out = pci_read_config(pci_dev, BHNDB_PCI_GPIO_OUT, 4); 870 gpio_en = pci_read_config(pci_dev, BHNDB_PCI_GPIO_OUTEN, 4); 871 872 /* Set PLL_OFF to HIGH, XTAL_ON to LOW. */ 873 gpio_out &= ~BHNDB_PCI_GPIO_XTAL_ON; 874 gpio_out |= BHNDB_PCI_GPIO_PLL_OFF; 875 pci_write_config(pci_dev, BHNDB_PCI_GPIO_OUT, gpio_out, 4); 876 877 /* Enable both output pins */ 878 gpio_en |= (BHNDB_PCI_GPIO_PLL_OFF|BHNDB_PCI_GPIO_XTAL_ON); 879 pci_write_config(pci_dev, BHNDB_PCI_GPIO_OUTEN, gpio_en, 4); 880 881 return (0); 882 } 883 884 static bhnd_clksrc 885 bhndb_pci_pwrctl_get_clksrc(device_t dev, device_t child, 886 bhnd_clock clock) 887 { 888 struct bhndb_pci_softc *sc; 889 uint32_t gpio_out; 890 891 sc = device_get_softc(dev); 892 893 /* Only supported on PCI devices */ 894 if (bhndb_is_pcie_attached(sc->dev)) 895 return (ENODEV); 896 897 /* Only ILP is supported */ 898 if (clock != BHND_CLOCK_ILP) 899 return (ENXIO); 900 901 gpio_out = pci_read_config(sc->parent, BHNDB_PCI_GPIO_OUT, 4); 902 if (gpio_out & BHNDB_PCI_GPIO_SCS) 903 return (BHND_CLKSRC_PCI); 904 else 905 return (BHND_CLKSRC_XTAL); 906 } 907 908 static int 909 bhndb_pci_pwrctl_gate_clock(device_t dev, device_t child, 910 bhnd_clock clock) 911 { 912 struct bhndb_pci_softc *sc = device_get_softc(dev); 913 914 /* Only supported on PCI devices */ 915 if (bhndb_is_pcie_attached(sc->dev)) 916 return (ENODEV); 917 918 /* Only HT is supported */ 919 if (clock != BHND_CLOCK_HT) 920 return (ENXIO); 921 922 return (bhndb_disable_pci_clocks(sc->dev)); 923 } 924 925 static int 926 bhndb_pci_pwrctl_ungate_clock(device_t dev, device_t child, 927 bhnd_clock clock) 928 { 929 struct bhndb_pci_softc *sc = device_get_softc(dev); 930 931 /* Only supported on PCI devices */ 932 if (bhndb_is_pcie_attached(sc->dev)) 933 return (ENODEV); 934 935 /* Only HT is supported */ 936 if (clock != BHND_CLOCK_HT) 937 return (ENXIO); 938 939 return (bhndb_enable_pci_clocks(sc->dev)); 940 } 941 942 static int 943 bhndb_pci_assign_intr(device_t dev, device_t child, int rid) 944 { 945 struct bhndb_pci_softc *sc; 946 rman_res_t start, count; 947 int error; 948 949 sc = device_get_softc(dev); 950 951 /* Is the rid valid? */ 952 if (rid >= bhnd_get_intr_count(child)) 953 return (EINVAL); 954 955 /* Fetch our common PCI interrupt's start/count. */ 956 error = bus_get_resource(sc->parent, SYS_RES_IRQ, sc->intr.intr_rid, 957 &start, &count); 958 if (error) 959 return (error); 960 961 /* Add to child's resource list */ 962 return (bus_set_resource(child, SYS_RES_IRQ, rid, start, count)); 963 } 964 965 /** 966 * Initialize a new bhndb PCI bridge EROM I/O instance. This EROM I/O 967 * implementation supports mapping of the device enumeration table via the 968 * @p hr host resources. 969 * 970 * @param pio The instance to be initialized. 971 * @param dev The bridge device. 972 * @param pci_dev The bridge's parent PCI device. 973 * @param hr The host resources to be used to map the device 974 * enumeration table. 975 */ 976 static int 977 bhndb_pci_eio_init(struct bhndb_pci_eio *pio, device_t dev, device_t pci_dev, 978 struct bhndb_host_resources *hr) 979 { 980 memset(&pio->eio, sizeof(pio->eio), 0); 981 pio->eio.map = bhndb_pci_eio_map; 982 pio->eio.read = bhndb_pci_eio_read; 983 pio->eio.fini = NULL; 984 985 pio->dev = dev; 986 pio->pci_dev = pci_dev; 987 pio->hr = hr; 988 pio->win = NULL; 989 pio->res = NULL; 990 991 return (0); 992 } 993 994 /** 995 * Attempt to adjust the dynamic register window backing @p pio to permit 996 * reading @p size bytes at @p addr. 997 * 998 * If @p addr or @p size fall outside the existing mapped range, or if 999 * @p pio is not backed by a dynamic register window, ENXIO will be returned. 1000 * 1001 * @param pio The bhndb PCI erom I/O state to be modified. 1002 * @param addr The address to be include 1003 */ 1004 static int 1005 bhndb_pci_eio_adjust_mapping(struct bhndb_pci_eio *pio, bhnd_addr_t addr, 1006 bhnd_size_t size) 1007 { 1008 bhnd_addr_t target; 1009 bhnd_size_t offset; 1010 int error; 1011 1012 1013 KASSERT(pio->win != NULL, ("missing register window")); 1014 KASSERT(pio->res != NULL, ("missing regwin resource")); 1015 KASSERT(pio->win->win_type == BHNDB_REGWIN_T_DYN, 1016 ("unexpected window type %d", pio->win->win_type)); 1017 1018 /* The requested subrange must fall within the total mapped range */ 1019 if (addr < pio->addr || (addr - pio->addr) > pio->size || 1020 size > pio->size || (addr - pio->addr) - pio->size < size) 1021 { 1022 return (ENXIO); 1023 } 1024 1025 /* Do we already have a useable mapping? */ 1026 if (addr >= pio->res_target && 1027 addr <= pio->res_target + pio->win->win_size && 1028 (pio->res_target + pio->win->win_size) - addr >= size) 1029 { 1030 return (0); 1031 } 1032 1033 /* Page-align the target address */ 1034 offset = addr % pio->win->win_size; 1035 target = addr - offset; 1036 1037 /* Configure the register window */ 1038 error = bhndb_pci_compat_setregwin(pio->dev, pio->pci_dev, pio->win, 1039 target); 1040 if (error) { 1041 device_printf(pio->dev, "failed to configure dynamic register " 1042 "window: %d\n", error); 1043 return (error); 1044 } 1045 1046 pio->res_target = target; 1047 return (0); 1048 } 1049 1050 /* bhnd_erom_io_map() implementation */ 1051 static int 1052 bhndb_pci_eio_map(struct bhnd_erom_io *eio, bhnd_addr_t addr, 1053 bhnd_size_t size) 1054 { 1055 struct bhndb_pci_eio *pio; 1056 const struct bhndb_regwin *regwin; 1057 struct resource *r; 1058 bhnd_addr_t target; 1059 bhnd_size_t offset; 1060 int error; 1061 1062 pio = (struct bhndb_pci_eio *)eio; 1063 1064 /* Locate a useable dynamic register window */ 1065 regwin = bhndb_regwin_find_type(pio->hr->cfg->register_windows, 1066 BHNDB_REGWIN_T_DYN, MIN(size, BHND_DEFAULT_CORE_SIZE)); 1067 if (regwin == NULL) { 1068 device_printf(pio->dev, "unable to map %#jx+%#jx; no " 1069 "usable dynamic register window found\n", addr, size); 1070 return (ENXIO); 1071 } 1072 1073 /* Locate the host resource mapping our register window */ 1074 if ((r = bhndb_host_resource_for_regwin(pio->hr, regwin)) == NULL) { 1075 device_printf(pio->dev, "unable to map %#jx+%#jx; no " 1076 "usable register resource found\n", addr, size); 1077 return (ENXIO); 1078 } 1079 1080 /* Page-align the target address */ 1081 offset = addr % regwin->win_size; 1082 target = addr - offset; 1083 1084 /* Configure the register window */ 1085 error = bhndb_pci_compat_setregwin(pio->dev, pio->pci_dev, regwin, 1086 target); 1087 if (error) { 1088 device_printf(pio->dev, "failed to configure dynamic register " 1089 "window: %d\n", error); 1090 return (error); 1091 } 1092 1093 /* Update our mapping state */ 1094 pio->win = regwin; 1095 pio->res = r; 1096 pio->addr = addr; 1097 pio->size = size; 1098 pio->res_target = target; 1099 1100 return (0); 1101 } 1102 1103 /* bhnd_erom_io_read() implementation */ 1104 static uint32_t 1105 bhndb_pci_eio_read(struct bhnd_erom_io *eio, bhnd_size_t offset, u_int width) 1106 { 1107 struct bhndb_pci_eio *pio; 1108 bhnd_addr_t addr; 1109 bus_size_t res_offset; 1110 int error; 1111 1112 pio = (struct bhndb_pci_eio *)eio; 1113 1114 /* Calculate absolute address */ 1115 if (BHND_SIZE_MAX - offset < pio->addr) { 1116 device_printf(pio->dev, "invalid offset %#jx+%#jx\n", pio->addr, 1117 offset); 1118 return (UINT32_MAX); 1119 } 1120 1121 addr = pio->addr + offset; 1122 1123 /* Adjust the mapping for our read */ 1124 if ((error = bhndb_pci_eio_adjust_mapping(pio, addr, width))) { 1125 device_printf(pio->dev, "failed to adjust register mapping: " 1126 "%d\n", error); 1127 return (UINT32_MAX); 1128 } 1129 1130 KASSERT(pio->res_target <= addr, ("invalid mapping (%#jx vs. %#jx)", 1131 pio->res_target, addr)); 1132 1133 /* Determine the actual read offset within our register window 1134 * resource */ 1135 res_offset = (addr - pio->res_target) + pio->win->win_offset; 1136 1137 /* Perform our read */ 1138 switch (width) { 1139 case 1: 1140 return (bus_read_1(pio->res, res_offset)); 1141 case 2: 1142 return (bus_read_2(pio->res, res_offset)); 1143 case 4: 1144 return (bus_read_4(pio->res, res_offset)); 1145 default: 1146 panic("unsupported width: %u", width); 1147 } 1148 } 1149 1150 static device_method_t bhndb_pci_methods[] = { 1151 /* Device interface */ 1152 DEVMETHOD(device_probe, bhndb_pci_probe), 1153 DEVMETHOD(device_attach, bhndb_pci_attach), 1154 DEVMETHOD(device_resume, bhndb_pci_resume), 1155 DEVMETHOD(device_suspend, bhndb_pci_suspend), 1156 DEVMETHOD(device_detach, bhndb_pci_detach), 1157 1158 /* BHND interface */ 1159 DEVMETHOD(bhnd_bus_assign_intr, bhndb_pci_assign_intr), 1160 1161 DEVMETHOD(bhnd_bus_pwrctl_get_clksrc, bhndb_pci_pwrctl_get_clksrc), 1162 DEVMETHOD(bhnd_bus_pwrctl_gate_clock, bhndb_pci_pwrctl_gate_clock), 1163 DEVMETHOD(bhnd_bus_pwrctl_ungate_clock, bhndb_pci_pwrctl_ungate_clock), 1164 1165 /* BHNDB interface */ 1166 DEVMETHOD(bhndb_set_window_addr, bhndb_pci_set_window_addr), 1167 DEVMETHOD(bhndb_populate_board_info, bhndb_pci_populate_board_info), 1168 1169 DEVMETHOD_END 1170 }; 1171 1172 DEFINE_CLASS_1(bhndb, bhndb_pci_driver, bhndb_pci_methods, 1173 sizeof(struct bhndb_pci_softc), bhndb_driver); 1174 1175 MODULE_VERSION(bhndb_pci, 1); 1176 MODULE_DEPEND(bhndb_pci, bhnd_pci_hostb, 1, 1, 1); 1177 MODULE_DEPEND(bhndb_pci, pci, 1, 1, 1); 1178 MODULE_DEPEND(bhndb_pci, bhndb, 1, 1, 1); 1179 MODULE_DEPEND(bhndb_pci, bhnd, 1, 1, 1); 1180