1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2015-2016 Landon Fuller <landon@landonf.org> 5 * Copyright (c) 2017 The FreeBSD Foundation 6 * All rights reserved. 7 * 8 * Portions of this software were developed by Landon Fuller 9 * under sponsorship from the FreeBSD Foundation. 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 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 19 * redistribution must be conditioned upon including a substantially 20 * similar Disclaimer requirement for further binary redistribution. 21 * 22 * NO WARRANTY 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 26 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 27 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 28 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 31 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 33 * THE POSSIBILITY OF SUCH DAMAGES. 34 */ 35 36 #include <sys/cdefs.h> 37 #include <sys/param.h> 38 #include <sys/bus.h> 39 #include <sys/refcount.h> 40 #include <sys/systm.h> 41 42 #include <machine/bus.h> 43 #include <sys/rman.h> 44 #include <machine/resource.h> 45 46 #include <dev/bhnd/siba/sibareg.h> 47 48 #include <dev/bhnd/cores/chipc/chipcreg.h> 49 50 #include "nvram/bhnd_nvram.h" 51 52 #include "bhnd_chipc_if.h" 53 54 #include "bhnd_nvram_if.h" 55 #include "bhnd_nvram_map.h" 56 57 #include "bhndreg.h" 58 #include "bhndvar.h" 59 #include "bhnd_private.h" 60 61 static void bhnd_service_registry_free_entry( 62 struct bhnd_service_entry *entry); 63 64 static int compare_ascending_probe_order(const void *lhs, const void *rhs); 65 static int compare_descending_probe_order(const void *lhs, 66 const void *rhs); 67 68 /* BHND core device description table. */ 69 static const struct bhnd_core_desc { 70 uint16_t vendor; 71 uint16_t device; 72 bhnd_devclass_t class; 73 const char *desc; 74 } bhnd_core_descs[] = { 75 #define BHND_CDESC(_mfg, _cid, _cls, _desc) \ 76 { BHND_MFGID_ ## _mfg, BHND_COREID_ ## _cid, \ 77 BHND_DEVCLASS_ ## _cls, _desc } 78 79 BHND_CDESC(BCM, CC, CC, "ChipCommon I/O Controller"), 80 BHND_CDESC(BCM, ILINE20, OTHER, "iLine20 HPNA"), 81 BHND_CDESC(BCM, SRAM, RAM, "SRAM"), 82 BHND_CDESC(BCM, SDRAM, RAM, "SDRAM"), 83 BHND_CDESC(BCM, PCI, PCI, "PCI Bridge"), 84 BHND_CDESC(BCM, MIPS, CPU, "BMIPS CPU"), 85 BHND_CDESC(BCM, ENET, ENET_MAC, "Fast Ethernet MAC"), 86 BHND_CDESC(BCM, V90_CODEC, SOFTMODEM, "V.90 SoftModem Codec"), 87 BHND_CDESC(BCM, USB, USB_DUAL, "USB 1.1 Device/Host Controller"), 88 BHND_CDESC(BCM, ADSL, OTHER, "ADSL Core"), 89 BHND_CDESC(BCM, ILINE100, OTHER, "iLine100 HPNA"), 90 BHND_CDESC(BCM, IPSEC, OTHER, "IPsec Accelerator"), 91 BHND_CDESC(BCM, UTOPIA, OTHER, "UTOPIA ATM Core"), 92 BHND_CDESC(BCM, PCMCIA, PCCARD, "PCMCIA Bridge"), 93 BHND_CDESC(BCM, SOCRAM, RAM, "Internal Memory"), 94 BHND_CDESC(BCM, MEMC, MEMC, "MEMC SDRAM Controller"), 95 BHND_CDESC(BCM, OFDM, OTHER, "OFDM PHY"), 96 BHND_CDESC(BCM, EXTIF, OTHER, "External Interface"), 97 BHND_CDESC(BCM, D11, WLAN, "802.11 MAC/PHY/Radio"), 98 BHND_CDESC(BCM, APHY, WLAN_PHY, "802.11a PHY"), 99 BHND_CDESC(BCM, BPHY, WLAN_PHY, "802.11b PHY"), 100 BHND_CDESC(BCM, GPHY, WLAN_PHY, "802.11g PHY"), 101 BHND_CDESC(BCM, MIPS33, CPU, "BMIPS33 CPU"), 102 BHND_CDESC(BCM, USB11H, USB_HOST, "USB 1.1 Host Controller"), 103 BHND_CDESC(BCM, USB11D, USB_DEV, "USB 1.1 Device Controller"), 104 BHND_CDESC(BCM, USB20H, USB_HOST, "USB 2.0 Host Controller"), 105 BHND_CDESC(BCM, USB20D, USB_DEV, "USB 2.0 Device Controller"), 106 BHND_CDESC(BCM, SDIOH, OTHER, "SDIO Host Controller"), 107 BHND_CDESC(BCM, ROBO, OTHER, "RoboSwitch"), 108 BHND_CDESC(BCM, ATA100, OTHER, "Parallel ATA Controller"), 109 BHND_CDESC(BCM, SATAXOR, OTHER, "SATA DMA/XOR Controller"), 110 BHND_CDESC(BCM, GIGETH, ENET_MAC, "Gigabit Ethernet MAC"), 111 BHND_CDESC(BCM, PCIE, PCIE, "PCIe Bridge"), 112 BHND_CDESC(BCM, NPHY, WLAN_PHY, "802.11n 2x2 PHY"), 113 BHND_CDESC(BCM, SRAMC, MEMC, "SRAM Controller"), 114 BHND_CDESC(BCM, MINIMAC, OTHER, "MINI MAC/PHY"), 115 BHND_CDESC(BCM, ARM11, CPU, "ARM1176 CPU"), 116 BHND_CDESC(BCM, ARM7S, CPU, "ARM7TDMI-S CPU"), 117 BHND_CDESC(BCM, LPPHY, WLAN_PHY, "802.11a/b/g PHY"), 118 BHND_CDESC(BCM, PMU, PMU, "PMU"), 119 BHND_CDESC(BCM, SSNPHY, WLAN_PHY, "802.11n Single-Stream PHY"), 120 BHND_CDESC(BCM, SDIOD, OTHER, "SDIO Device Core"), 121 BHND_CDESC(BCM, ARMCM3, CPU, "ARM Cortex-M3 CPU"), 122 BHND_CDESC(BCM, HTPHY, WLAN_PHY, "802.11n 4x4 PHY"), 123 BHND_CDESC(MIPS,MIPS74K, CPU, "MIPS74k CPU"), 124 BHND_CDESC(BCM, GMAC, ENET_MAC, "Gigabit MAC core"), 125 BHND_CDESC(BCM, DMEMC, MEMC, "DDR1/DDR2 Memory Controller"), 126 BHND_CDESC(BCM, PCIERC, OTHER, "PCIe Root Complex"), 127 BHND_CDESC(BCM, OCP, SOC_BRIDGE, "OCP to OCP Bridge"), 128 BHND_CDESC(BCM, SC, OTHER, "Shared Common Core"), 129 BHND_CDESC(BCM, AHB, SOC_BRIDGE, "OCP to AHB Bridge"), 130 BHND_CDESC(BCM, SPIH, OTHER, "SPI Host Controller"), 131 BHND_CDESC(BCM, I2S, OTHER, "I2S Digital Audio Interface"), 132 BHND_CDESC(BCM, DMEMS, MEMC, "SDR/DDR1 Memory Controller"), 133 BHND_CDESC(BCM, UBUS_SHIM, OTHER, "BCM6362/UBUS WLAN SHIM"), 134 BHND_CDESC(BCM, PCIE2, PCIE, "PCIe Bridge (Gen2)"), 135 136 BHND_CDESC(ARM, APB_BRIDGE, SOC_BRIDGE, "BP135 AMBA3 AXI to APB Bridge"), 137 BHND_CDESC(ARM, PL301, SOC_ROUTER, "PL301 AMBA3 Interconnect"), 138 BHND_CDESC(ARM, EROM, EROM, "PL366 Device Enumeration ROM"), 139 BHND_CDESC(ARM, OOB_ROUTER, OTHER, "PL367 OOB Interrupt Router"), 140 BHND_CDESC(ARM, AXI_UNMAPPED, OTHER, "Unmapped Address Ranges"), 141 142 BHND_CDESC(BCM, 4706_CC, CC, "ChipCommon I/O Controller"), 143 BHND_CDESC(BCM, NS_PCIE2, PCIE, "PCIe Bridge (Gen2)"), 144 BHND_CDESC(BCM, NS_DMA, OTHER, "DMA engine"), 145 BHND_CDESC(BCM, NS_SDIO, OTHER, "SDIO 3.0 Host Controller"), 146 BHND_CDESC(BCM, NS_USB20H, USB_HOST, "USB 2.0 Host Controller"), 147 BHND_CDESC(BCM, NS_USB30H, USB_HOST, "USB 3.0 Host Controller"), 148 BHND_CDESC(BCM, NS_A9JTAG, OTHER, "ARM Cortex A9 JTAG Interface"), 149 BHND_CDESC(BCM, NS_DDR23_MEMC, MEMC, "Denali DDR2/DD3 Memory Controller"), 150 BHND_CDESC(BCM, NS_ROM, NVRAM, "System ROM"), 151 BHND_CDESC(BCM, NS_NAND, NVRAM, "NAND Flash Controller"), 152 BHND_CDESC(BCM, NS_QSPI, NVRAM, "QSPI Flash Controller"), 153 BHND_CDESC(BCM, NS_CC_B, CC_B, "ChipCommon B Auxiliary I/O Controller"), 154 BHND_CDESC(BCM, 4706_SOCRAM, RAM, "Internal Memory"), 155 BHND_CDESC(BCM, IHOST_ARMCA9, CPU, "ARM Cortex A9 CPU"), 156 BHND_CDESC(BCM, 4706_GMAC_CMN, ENET, "Gigabit MAC (Common)"), 157 BHND_CDESC(BCM, 4706_GMAC, ENET_MAC, "Gigabit MAC"), 158 BHND_CDESC(BCM, AMEMC, MEMC, "Denali DDR1/DDR2 Memory Controller"), 159 #undef BHND_CDESC 160 161 /* Derived from inspection of the BCM4331 cores that provide PrimeCell 162 * IDs. Due to lack of documentation, the surmised device name/purpose 163 * provided here may be incorrect. */ 164 { BHND_MFGID_ARM, BHND_PRIMEID_EROM, BHND_DEVCLASS_OTHER, 165 "PL364 Device Enumeration ROM" }, 166 { BHND_MFGID_ARM, BHND_PRIMEID_SWRAP, BHND_DEVCLASS_OTHER, 167 "PL368 Device Management Interface" }, 168 { BHND_MFGID_ARM, BHND_PRIMEID_MWRAP, BHND_DEVCLASS_OTHER, 169 "PL369 Device Management Interface" }, 170 { 0, 0, 0, NULL } 171 }; 172 173 static const struct bhnd_device_quirk bhnd_chipc_clkctl_quirks[]; 174 static const struct bhnd_device_quirk bhnd_pcmcia_clkctl_quirks[]; 175 176 /** 177 * Device table entries for core-specific CLKCTL quirk lookup. 178 */ 179 static const struct bhnd_device bhnd_clkctl_devices[] = { 180 BHND_DEVICE(BCM, CC, NULL, bhnd_chipc_clkctl_quirks), 181 BHND_DEVICE(BCM, PCMCIA, NULL, bhnd_pcmcia_clkctl_quirks), 182 BHND_DEVICE_END, 183 }; 184 185 /** ChipCommon CLKCTL quirks */ 186 static const struct bhnd_device_quirk bhnd_chipc_clkctl_quirks[] = { 187 /* HTAVAIL/ALPAVAIL are bitswapped in chipc's CLKCTL */ 188 BHND_CHIP_QUIRK(4328, HWREV_ANY, BHND_CLKCTL_QUIRK_CCS0), 189 BHND_CHIP_QUIRK(5354, HWREV_ANY, BHND_CLKCTL_QUIRK_CCS0), 190 BHND_DEVICE_QUIRK_END 191 }; 192 193 /** PCMCIA CLKCTL quirks */ 194 static const struct bhnd_device_quirk bhnd_pcmcia_clkctl_quirks[] = { 195 /* HTAVAIL/ALPAVAIL are bitswapped in pcmcia's CLKCTL */ 196 BHND_CHIP_QUIRK(4328, HWREV_ANY, BHND_CLKCTL_QUIRK_CCS0), 197 BHND_CHIP_QUIRK(5354, HWREV_ANY, BHND_CLKCTL_QUIRK_CCS0), 198 BHND_DEVICE_QUIRK_END 199 }; 200 201 /** 202 * Return the name for a given JEP106 manufacturer ID. 203 * 204 * @param vendor A JEP106 Manufacturer ID, including the non-standard ARM 4-bit 205 * JEP106 continuation code. 206 */ 207 const char * 208 bhnd_vendor_name(uint16_t vendor) 209 { 210 switch (vendor) { 211 case BHND_MFGID_ARM: 212 return "ARM"; 213 case BHND_MFGID_BCM: 214 return "Broadcom"; 215 case BHND_MFGID_MIPS: 216 return "MIPS"; 217 default: 218 return "unknown"; 219 } 220 } 221 222 /** 223 * Return the name of a port type. 224 * 225 * @param port_type The port type to look up. 226 */ 227 const char * 228 bhnd_port_type_name(bhnd_port_type port_type) 229 { 230 switch (port_type) { 231 case BHND_PORT_DEVICE: 232 return ("device"); 233 case BHND_PORT_BRIDGE: 234 return ("bridge"); 235 case BHND_PORT_AGENT: 236 return ("agent"); 237 default: 238 return "unknown"; 239 } 240 } 241 242 /** 243 * Return the name of an NVRAM source. 244 * 245 * @param nvram_src The NVRAM source type to look up. 246 */ 247 const char * 248 bhnd_nvram_src_name(bhnd_nvram_src nvram_src) 249 { 250 switch (nvram_src) { 251 case BHND_NVRAM_SRC_FLASH: 252 return ("flash"); 253 case BHND_NVRAM_SRC_OTP: 254 return ("OTP"); 255 case BHND_NVRAM_SRC_SPROM: 256 return ("SPROM"); 257 case BHND_NVRAM_SRC_UNKNOWN: 258 return ("none"); 259 default: 260 return ("unknown"); 261 } 262 } 263 264 static const struct bhnd_core_desc * 265 bhnd_find_core_desc(uint16_t vendor, uint16_t device) 266 { 267 for (u_int i = 0; bhnd_core_descs[i].desc != NULL; i++) { 268 if (bhnd_core_descs[i].vendor != vendor) 269 continue; 270 271 if (bhnd_core_descs[i].device != device) 272 continue; 273 274 return (&bhnd_core_descs[i]); 275 } 276 277 return (NULL); 278 } 279 280 /** 281 * Return a human-readable name for a BHND core. 282 * 283 * @param vendor The core designer's JEDEC-106 Manufacturer ID. 284 * @param device The core identifier. 285 */ 286 const char * 287 bhnd_find_core_name(uint16_t vendor, uint16_t device) 288 { 289 const struct bhnd_core_desc *desc; 290 291 if ((desc = bhnd_find_core_desc(vendor, device)) == NULL) 292 return ("unknown"); 293 294 return desc->desc; 295 } 296 297 /** 298 * Return the device class for a BHND core. 299 * 300 * @param vendor The core designer's JEDEC-106 Manufacturer ID. 301 * @param device The core identifier. 302 */ 303 bhnd_devclass_t 304 bhnd_find_core_class(uint16_t vendor, uint16_t device) 305 { 306 const struct bhnd_core_desc *desc; 307 308 if ((desc = bhnd_find_core_desc(vendor, device)) == NULL) 309 return (BHND_DEVCLASS_OTHER); 310 311 return desc->class; 312 } 313 314 /** 315 * Return a human-readable name for a BHND core. 316 * 317 * @param ci The core's info record. 318 */ 319 const char * 320 bhnd_core_name(const struct bhnd_core_info *ci) 321 { 322 return bhnd_find_core_name(ci->vendor, ci->device); 323 } 324 325 /** 326 * Return the device class for a BHND core. 327 * 328 * @param ci The core's info record. 329 */ 330 bhnd_devclass_t 331 bhnd_core_class(const struct bhnd_core_info *ci) 332 { 333 return bhnd_find_core_class(ci->vendor, ci->device); 334 } 335 336 /** 337 * Write a human readable name representation of the given 338 * BHND_CHIPID_* constant to @p buffer. 339 * 340 * @param buffer Output buffer, or NULL to compute the required size. 341 * @param size Capacity of @p buffer, in bytes. 342 * @param chip_id Chip ID to be formatted. 343 * 344 * @return The required number of bytes on success, or a negative integer on 345 * failure. No more than @p size-1 characters be written, with the @p size'th 346 * set to '\0'. 347 * 348 * @sa BHND_CHIPID_MAX_NAMELEN 349 */ 350 int 351 bhnd_format_chip_id(char *buffer, size_t size, uint16_t chip_id) 352 { 353 /* All hex formatted IDs are within the range of 0x4000-0x9C3F (40000-1) */ 354 if (chip_id >= 0x4000 && chip_id <= 0x9C3F) 355 return (snprintf(buffer, size, "BCM%hX", chip_id)); 356 else 357 return (snprintf(buffer, size, "BCM%hu", chip_id)); 358 } 359 360 /** 361 * Return a core info record populated from a bhnd-attached @p dev. 362 * 363 * @param dev A bhnd device. 364 * 365 * @return A core info record for @p dev. 366 */ 367 struct bhnd_core_info 368 bhnd_get_core_info(device_t dev) { 369 return (struct bhnd_core_info) { 370 .vendor = bhnd_get_vendor(dev), 371 .device = bhnd_get_device(dev), 372 .hwrev = bhnd_get_hwrev(dev), 373 .core_idx = bhnd_get_core_index(dev), 374 .unit = bhnd_get_core_unit(dev) 375 }; 376 } 377 378 /** 379 * Find a @p class child device with @p unit on @p bus. 380 * 381 * @param bus The bhnd-compatible bus to be searched. 382 * @param class The device class to match on. 383 * @param unit The core unit number; specify -1 to return the first match 384 * regardless of unit number. 385 * 386 * @retval device_t if a matching child device is found. 387 * @retval NULL if no matching child device is found. 388 */ 389 device_t 390 bhnd_bus_find_child(device_t bus, bhnd_devclass_t class, int unit) 391 { 392 struct bhnd_core_match md = { 393 BHND_MATCH_CORE_CLASS(class), 394 BHND_MATCH_CORE_UNIT(unit) 395 }; 396 397 if (unit == -1) 398 md.m.match.core_unit = 0; 399 400 return bhnd_bus_match_child(bus, &md); 401 } 402 403 /** 404 * Find the first child device on @p bus that matches @p desc. 405 * 406 * @param bus The bhnd-compatible bus to be searched. 407 * @param desc A match descriptor. 408 * 409 * @retval device_t if a matching child device is found. 410 * @retval NULL if no matching child device is found. 411 */ 412 device_t 413 bhnd_bus_match_child(device_t bus, const struct bhnd_core_match *desc) 414 { 415 device_t *devlistp; 416 device_t match; 417 int devcnt; 418 int error; 419 420 error = device_get_children(bus, &devlistp, &devcnt); 421 if (error != 0) 422 return (NULL); 423 424 match = NULL; 425 for (int i = 0; i < devcnt; i++) { 426 struct bhnd_core_info ci = bhnd_get_core_info(devlistp[i]); 427 428 if (bhnd_core_matches(&ci, desc)) { 429 match = devlistp[i]; 430 goto done; 431 } 432 } 433 434 done: 435 free(devlistp, M_TEMP); 436 return match; 437 } 438 439 /** 440 * Retrieve an ordered list of all device instances currently connected to 441 * @p bus, returning a pointer to the array in @p devlistp and the count 442 * in @p ndevs. 443 * 444 * The memory allocated for the table must be freed via 445 * bhnd_bus_free_children(). 446 * 447 * @param bus The bhnd-compatible bus to be queried. 448 * @param[out] devlist The array of devices. 449 * @param[out] devcount The number of devices in @p devlistp 450 * @param order The order in which devices will be returned 451 * in @p devlist. 452 * 453 * @retval 0 success 454 * @retval non-zero if an error occurs, a regular unix error code will 455 * be returned. 456 */ 457 int 458 bhnd_bus_get_children(device_t bus, device_t **devlist, int *devcount, 459 bhnd_device_order order) 460 { 461 int error; 462 463 /* Fetch device array */ 464 if ((error = device_get_children(bus, devlist, devcount))) 465 return (error); 466 467 /* Perform requested sorting */ 468 if ((error = bhnd_sort_devices(*devlist, *devcount, order))) { 469 bhnd_bus_free_children(*devlist); 470 return (error); 471 } 472 473 return (0); 474 } 475 476 /** 477 * Free any memory allocated in a previous call to bhnd_bus_get_children(). 478 * 479 * @param devlist The device array returned by bhnd_bus_get_children(). 480 */ 481 void 482 bhnd_bus_free_children(device_t *devlist) 483 { 484 free(devlist, M_TEMP); 485 } 486 487 /** 488 * Perform in-place sorting of an array of bhnd device instances. 489 * 490 * @param devlist An array of bhnd devices. 491 * @param devcount The number of devices in @p devs. 492 * @param order The sort order to be used. 493 * 494 * @retval 0 success 495 * @retval EINVAL if the sort order is unknown. 496 */ 497 int 498 bhnd_sort_devices(device_t *devlist, size_t devcount, bhnd_device_order order) 499 { 500 int (*compare)(const void *, const void *); 501 502 switch (order) { 503 case BHND_DEVICE_ORDER_ATTACH: 504 compare = compare_ascending_probe_order; 505 break; 506 case BHND_DEVICE_ORDER_DETACH: 507 compare = compare_descending_probe_order; 508 break; 509 default: 510 printf("unknown sort order: %d\n", order); 511 return (EINVAL); 512 } 513 514 qsort(devlist, devcount, sizeof(*devlist), compare); 515 return (0); 516 } 517 518 /* 519 * Ascending comparison of bhnd device's probe order. 520 */ 521 static int 522 compare_ascending_probe_order(const void *lhs, const void *rhs) 523 { 524 device_t ldev, rdev; 525 int lorder, rorder; 526 527 ldev = (*(const device_t *) lhs); 528 rdev = (*(const device_t *) rhs); 529 530 lorder = BHND_BUS_GET_PROBE_ORDER(device_get_parent(ldev), ldev); 531 rorder = BHND_BUS_GET_PROBE_ORDER(device_get_parent(rdev), rdev); 532 533 if (lorder < rorder) { 534 return (-1); 535 } else if (lorder > rorder) { 536 return (1); 537 } else { 538 return (0); 539 } 540 } 541 542 /* 543 * Descending comparison of bhnd device's probe order. 544 */ 545 static int 546 compare_descending_probe_order(const void *lhs, const void *rhs) 547 { 548 return (compare_ascending_probe_order(rhs, lhs)); 549 } 550 551 /** 552 * Call device_probe_and_attach() for each of the bhnd bus device's 553 * children, in bhnd attach order. 554 * 555 * @param bus The bhnd-compatible bus for which all children should be probed 556 * and attached. 557 */ 558 int 559 bhnd_bus_probe_children(device_t bus) 560 { 561 device_t *devs; 562 int ndevs; 563 int error; 564 565 /* Fetch children in attach order */ 566 error = bhnd_bus_get_children(bus, &devs, &ndevs, 567 BHND_DEVICE_ORDER_ATTACH); 568 if (error) 569 return (error); 570 571 /* Probe and attach all children */ 572 for (int i = 0; i < ndevs; i++) { 573 device_t child = devs[i]; 574 device_probe_and_attach(child); 575 } 576 577 bhnd_bus_free_children(devs); 578 579 return (0); 580 } 581 582 /** 583 * Walk up the bhnd device hierarchy to locate the root device 584 * to which the bhndb bridge is attached. 585 * 586 * This can be used from within bhnd host bridge drivers to locate the 587 * actual upstream host device. 588 * 589 * @param dev A bhnd device. 590 * @param bus_class The expected bus (e.g. "pci") to which the bridge root 591 * should be attached. 592 * 593 * @retval device_t if a matching parent device is found. 594 * @retval NULL if @p dev is not attached via a bhndb bus. 595 * @retval NULL if no parent device is attached via @p bus_class. 596 */ 597 device_t 598 bhnd_find_bridge_root(device_t dev, devclass_t bus_class) 599 { 600 devclass_t bhndb_class; 601 device_t parent; 602 603 KASSERT(device_get_devclass(device_get_parent(dev)) == 604 devclass_find("bhnd"), 605 ("%s not a bhnd device", device_get_nameunit(dev))); 606 607 bhndb_class = devclass_find("bhndb"); 608 609 /* Walk the device tree until we hit a bridge */ 610 parent = dev; 611 while ((parent = device_get_parent(parent)) != NULL) { 612 if (device_get_devclass(parent) == bhndb_class) 613 break; 614 } 615 616 /* No bridge? */ 617 if (parent == NULL) 618 return (NULL); 619 620 /* Search for a parent attached to the expected bus class */ 621 while ((parent = device_get_parent(parent)) != NULL) { 622 device_t bus; 623 624 bus = device_get_parent(parent); 625 if (bus != NULL && device_get_devclass(bus) == bus_class) 626 return (parent); 627 } 628 629 /* Not found */ 630 return (NULL); 631 } 632 633 /** 634 * Find the first core in @p cores that matches @p desc. 635 * 636 * @param cores The table to search. 637 * @param num_cores The length of @p cores. 638 * @param desc A match descriptor. 639 * 640 * @retval bhnd_core_info if a matching core is found. 641 * @retval NULL if no matching core is found. 642 */ 643 const struct bhnd_core_info * 644 bhnd_match_core(const struct bhnd_core_info *cores, u_int num_cores, 645 const struct bhnd_core_match *desc) 646 { 647 for (u_int i = 0; i < num_cores; i++) { 648 if (bhnd_core_matches(&cores[i], desc)) 649 return &cores[i]; 650 } 651 652 return (NULL); 653 } 654 655 /** 656 * Find the first core in @p cores with the given @p class. 657 * 658 * @param cores The table to search. 659 * @param num_cores The length of @p cores. 660 * @param class The device class to match on. 661 * 662 * @retval non-NULL if a matching core is found. 663 * @retval NULL if no matching core is found. 664 */ 665 const struct bhnd_core_info * 666 bhnd_find_core(const struct bhnd_core_info *cores, u_int num_cores, 667 bhnd_devclass_t class) 668 { 669 struct bhnd_core_match md = { 670 BHND_MATCH_CORE_CLASS(class) 671 }; 672 673 return bhnd_match_core(cores, num_cores, &md); 674 } 675 676 /** 677 * Create an equality match descriptor for @p core. 678 * 679 * @param core The core info to be matched on. 680 * 681 * @return an equality match descriptor for @p core. 682 */ 683 struct bhnd_core_match 684 bhnd_core_get_match_desc(const struct bhnd_core_info *core) 685 { 686 return ((struct bhnd_core_match) { 687 BHND_MATCH_CORE_VENDOR(core->vendor), 688 BHND_MATCH_CORE_ID(core->device), 689 BHND_MATCH_CORE_REV(HWREV_EQ(core->hwrev)), 690 BHND_MATCH_CORE_CLASS(bhnd_core_class(core)), 691 BHND_MATCH_CORE_IDX(core->core_idx), 692 BHND_MATCH_CORE_UNIT(core->unit) 693 }); 694 } 695 696 /** 697 * Return true if the @p lhs is equal to @p rhs. 698 * 699 * @param lhs The first bhnd core descriptor to compare. 700 * @param rhs The second bhnd core descriptor to compare. 701 * 702 * @retval true if @p lhs is equal to @p rhs 703 * @retval false if @p lhs is not equal to @p rhs 704 */ 705 bool 706 bhnd_cores_equal(const struct bhnd_core_info *lhs, 707 const struct bhnd_core_info *rhs) 708 { 709 struct bhnd_core_match md; 710 711 /* Use an equality match descriptor to perform the comparison */ 712 md = bhnd_core_get_match_desc(rhs); 713 return (bhnd_core_matches(lhs, &md)); 714 } 715 716 /** 717 * Return true if the @p core matches @p desc. 718 * 719 * @param core A bhnd core descriptor. 720 * @param desc A match descriptor to compare against @p core. 721 * 722 * @retval true if @p core matches @p match. 723 * @retval false if @p core does not match @p match. 724 */ 725 bool 726 bhnd_core_matches(const struct bhnd_core_info *core, 727 const struct bhnd_core_match *desc) 728 { 729 if (desc->m.match.core_vendor && desc->core_vendor != core->vendor) 730 return (false); 731 732 if (desc->m.match.core_id && desc->core_id != core->device) 733 return (false); 734 735 if (desc->m.match.core_unit && desc->core_unit != core->unit) 736 return (false); 737 738 if (desc->m.match.core_rev && 739 !bhnd_hwrev_matches(core->hwrev, &desc->core_rev)) 740 return (false); 741 742 if (desc->m.match.core_idx && desc->core_idx != core->core_idx) 743 return (false); 744 745 if (desc->m.match.core_class && 746 desc->core_class != bhnd_core_class(core)) 747 return (false); 748 749 return true; 750 } 751 752 /** 753 * Return true if the @p chip matches @p desc. 754 * 755 * @param chip A bhnd chip identifier. 756 * @param desc A match descriptor to compare against @p chip. 757 * 758 * @retval true if @p chip matches @p match. 759 * @retval false if @p chip does not match @p match. 760 */ 761 bool 762 bhnd_chip_matches(const struct bhnd_chipid *chip, 763 const struct bhnd_chip_match *desc) 764 { 765 if (desc->m.match.chip_id && chip->chip_id != desc->chip_id) 766 return (false); 767 768 if (desc->m.match.chip_pkg && chip->chip_pkg != desc->chip_pkg) 769 return (false); 770 771 if (desc->m.match.chip_rev && 772 !bhnd_hwrev_matches(chip->chip_rev, &desc->chip_rev)) 773 return (false); 774 775 if (desc->m.match.chip_type && chip->chip_type != desc->chip_type) 776 return (false); 777 778 return (true); 779 } 780 781 /** 782 * Return true if the @p board matches @p desc. 783 * 784 * @param board The bhnd board info. 785 * @param desc A match descriptor to compare against @p board. 786 * 787 * @retval true if @p chip matches @p match. 788 * @retval false if @p chip does not match @p match. 789 */ 790 bool 791 bhnd_board_matches(const struct bhnd_board_info *board, 792 const struct bhnd_board_match *desc) 793 { 794 if (desc->m.match.board_srom_rev && 795 !bhnd_hwrev_matches(board->board_srom_rev, &desc->board_srom_rev)) 796 return (false); 797 798 if (desc->m.match.board_vendor && 799 board->board_vendor != desc->board_vendor) 800 return (false); 801 802 if (desc->m.match.board_type && board->board_type != desc->board_type) 803 return (false); 804 805 if (desc->m.match.board_devid && 806 board->board_devid != desc->board_devid) 807 return (false); 808 809 if (desc->m.match.board_rev && 810 !bhnd_hwrev_matches(board->board_rev, &desc->board_rev)) 811 return (false); 812 813 return (true); 814 } 815 816 /** 817 * Return true if the @p hwrev matches @p desc. 818 * 819 * @param hwrev A bhnd hardware revision. 820 * @param desc A match descriptor to compare against @p core. 821 * 822 * @retval true if @p hwrev matches @p match. 823 * @retval false if @p hwrev does not match @p match. 824 */ 825 bool 826 bhnd_hwrev_matches(uint16_t hwrev, const struct bhnd_hwrev_match *desc) 827 { 828 if (desc->start != BHND_HWREV_INVALID && 829 desc->start > hwrev) 830 return false; 831 832 if (desc->end != BHND_HWREV_INVALID && 833 desc->end < hwrev) 834 return false; 835 836 return true; 837 } 838 839 /** 840 * Return true if the @p dev matches @p desc. 841 * 842 * @param dev A bhnd device. 843 * @param desc A match descriptor to compare against @p dev. 844 * 845 * @retval true if @p dev matches @p match. 846 * @retval false if @p dev does not match @p match. 847 */ 848 bool 849 bhnd_device_matches(device_t dev, const struct bhnd_device_match *desc) 850 { 851 struct bhnd_core_info core; 852 const struct bhnd_chipid *chip; 853 struct bhnd_board_info board; 854 device_t parent; 855 int error; 856 857 /* Construct individual match descriptors */ 858 struct bhnd_core_match m_core = { _BHND_CORE_MATCH_COPY(desc) }; 859 struct bhnd_chip_match m_chip = { _BHND_CHIP_MATCH_COPY(desc) }; 860 struct bhnd_board_match m_board = { _BHND_BOARD_MATCH_COPY(desc) }; 861 862 /* Fetch and match core info */ 863 if (m_core.m.match_flags) { 864 /* Only applicable to bhnd-attached cores */ 865 parent = device_get_parent(dev); 866 if (device_get_devclass(parent) != devclass_find("bhnd")) { 867 device_printf(dev, "attempting to match core " 868 "attributes against non-core device\n"); 869 return (false); 870 } 871 872 core = bhnd_get_core_info(dev); 873 if (!bhnd_core_matches(&core, &m_core)) 874 return (false); 875 } 876 877 /* Fetch and match chip info */ 878 if (m_chip.m.match_flags) { 879 chip = bhnd_get_chipid(dev); 880 881 if (!bhnd_chip_matches(chip, &m_chip)) 882 return (false); 883 } 884 885 /* Fetch and match board info. 886 * 887 * This is not available until after NVRAM is up; earlier device 888 * matches should not include board requirements */ 889 if (m_board.m.match_flags) { 890 if ((error = bhnd_read_board_info(dev, &board))) { 891 device_printf(dev, "failed to read required board info " 892 "during device matching: %d\n", error); 893 return (false); 894 } 895 896 if (!bhnd_board_matches(&board, &m_board)) 897 return (false); 898 } 899 900 /* All matched */ 901 return (true); 902 } 903 904 /** 905 * Search @p table for an entry matching @p dev. 906 * 907 * @param dev A bhnd device to match against @p table. 908 * @param table The device table to search. 909 * @param entry_size The @p table entry size, in bytes. 910 * 911 * @retval non-NULL the first matching device, if any. 912 * @retval NULL if no matching device is found in @p table. 913 */ 914 const struct bhnd_device * 915 bhnd_device_lookup(device_t dev, const struct bhnd_device *table, 916 size_t entry_size) 917 { 918 const struct bhnd_device *entry; 919 device_t hostb, parent; 920 bhnd_attach_type attach_type; 921 uint32_t dflags; 922 923 parent = device_get_parent(dev); 924 hostb = bhnd_bus_find_hostb_device(parent); 925 attach_type = bhnd_get_attach_type(dev); 926 927 for (entry = table; !BHND_DEVICE_IS_END(entry); entry = 928 (const struct bhnd_device *) ((const char *) entry + entry_size)) 929 { 930 /* match core info */ 931 if (!bhnd_device_matches(dev, &entry->core)) 932 continue; 933 934 /* match device flags */ 935 dflags = entry->device_flags; 936 937 /* hostb implies BHND_ATTACH_ADAPTER requirement */ 938 if (dflags & BHND_DF_HOSTB) 939 dflags |= BHND_DF_ADAPTER; 940 941 if (dflags & BHND_DF_ADAPTER) 942 if (attach_type != BHND_ATTACH_ADAPTER) 943 continue; 944 945 if (dflags & BHND_DF_HOSTB) 946 if (dev != hostb) 947 continue; 948 949 if (dflags & BHND_DF_SOC) 950 if (attach_type != BHND_ATTACH_NATIVE) 951 continue; 952 953 /* device found */ 954 return (entry); 955 } 956 957 /* not found */ 958 return (NULL); 959 } 960 961 /** 962 * Scan the device @p table for all quirk flags applicable to @p dev. 963 * 964 * @param dev A bhnd device to match against @p table. 965 * @param table The device table to search. 966 * @param entry_size The @p table entry size, in bytes. 967 * 968 * @return all matching quirk flags. 969 */ 970 uint32_t 971 bhnd_device_quirks(device_t dev, const struct bhnd_device *table, 972 size_t entry_size) 973 { 974 const struct bhnd_device *dent; 975 const struct bhnd_device_quirk *qent, *qtable; 976 uint32_t quirks; 977 978 /* Locate the device entry */ 979 if ((dent = bhnd_device_lookup(dev, table, entry_size)) == NULL) 980 return (0); 981 982 /* Quirks table is optional */ 983 qtable = dent->quirks_table; 984 if (qtable == NULL) 985 return (0); 986 987 /* Collect matching device quirk entries */ 988 quirks = 0; 989 for (qent = qtable; !BHND_DEVICE_QUIRK_IS_END(qent); qent++) { 990 if (bhnd_device_matches(dev, &qent->desc)) 991 quirks |= qent->quirks; 992 } 993 994 return (quirks); 995 } 996 997 /** 998 * Allocate bhnd(4) resources defined in @p rs from a parent bus. 999 * 1000 * @param dev The device requesting ownership of the resources. 1001 * @param rs A standard bus resource specification. This will be updated 1002 * with the allocated resource's RIDs. 1003 * @param res On success, the allocated bhnd resources. 1004 * 1005 * @retval 0 success 1006 * @retval non-zero if allocation of any non-RF_OPTIONAL resource fails, 1007 * all allocated resources will be released and a regular 1008 * unix error code will be returned. 1009 */ 1010 int 1011 bhnd_alloc_resources(device_t dev, struct resource_spec *rs, 1012 struct bhnd_resource **res) 1013 { 1014 /* Initialize output array */ 1015 for (u_int i = 0; rs[i].type != -1; i++) 1016 res[i] = NULL; 1017 1018 for (u_int i = 0; rs[i].type != -1; i++) { 1019 res[i] = bhnd_alloc_resource_any(dev, rs[i].type, &rs[i].rid, 1020 rs[i].flags); 1021 1022 /* Clean up all allocations on failure */ 1023 if (res[i] == NULL && !(rs[i].flags & RF_OPTIONAL)) { 1024 bhnd_release_resources(dev, rs, res); 1025 return (ENXIO); 1026 } 1027 } 1028 1029 return (0); 1030 } 1031 1032 /** 1033 * Release bhnd(4) resources defined in @p rs from a parent bus. 1034 * 1035 * @param dev The device that owns the resources. 1036 * @param rs A standard bus resource specification previously initialized 1037 * by @p bhnd_alloc_resources. 1038 * @param res The bhnd resources to be released. 1039 */ 1040 void 1041 bhnd_release_resources(device_t dev, const struct resource_spec *rs, 1042 struct bhnd_resource **res) 1043 { 1044 for (u_int i = 0; rs[i].type != -1; i++) { 1045 if (res[i] == NULL) 1046 continue; 1047 1048 bhnd_release_resource(dev, rs[i].type, rs[i].rid, res[i]); 1049 res[i] = NULL; 1050 } 1051 } 1052 1053 /** 1054 * Allocate and return a new per-core PMU clock control/status (clkctl) 1055 * instance for @p dev. 1056 * 1057 * @param dev The bhnd(4) core device mapped by @p r. 1058 * @param pmu_dev The bhnd(4) PMU device, implmenting the bhnd_pmu_if 1059 * interface. The caller is responsible for ensuring that 1060 * this reference remains valid for the lifetime of the 1061 * returned clkctl instance. 1062 * @param r A resource mapping the core's clock control register 1063 * (see BHND_CLK_CTL_ST). The caller is responsible for 1064 * ensuring that this resource remains valid for the 1065 * lifetime of the returned clkctl instance. 1066 * @param offset The offset to the clock control register within @p r. 1067 * @param max_latency The PMU's maximum state transition latency in 1068 * microseconds; this upper bound will be used to busy-wait 1069 * on PMU state transitions. 1070 * 1071 * @retval non-NULL success 1072 * @retval NULL if allocation fails. 1073 * 1074 */ 1075 struct bhnd_core_clkctl * 1076 bhnd_alloc_core_clkctl(device_t dev, device_t pmu_dev, struct bhnd_resource *r, 1077 bus_size_t offset, u_int max_latency) 1078 { 1079 struct bhnd_core_clkctl *clkctl; 1080 1081 clkctl = malloc(sizeof(*clkctl), M_BHND, M_ZERO | M_NOWAIT); 1082 if (clkctl == NULL) 1083 return (NULL); 1084 1085 clkctl->cc_dev = dev; 1086 clkctl->cc_pmu_dev = pmu_dev; 1087 clkctl->cc_res = r; 1088 clkctl->cc_res_offset = offset; 1089 clkctl->cc_max_latency = max_latency; 1090 clkctl->cc_quirks = bhnd_device_quirks(dev, bhnd_clkctl_devices, 1091 sizeof(bhnd_clkctl_devices[0])); 1092 1093 BHND_CLKCTL_LOCK_INIT(clkctl); 1094 1095 return (clkctl); 1096 } 1097 1098 /** 1099 * Free a clkctl instance previously allocated via bhnd_alloc_core_clkctl(). 1100 * 1101 * @param clkctl The clkctl instance to be freed. 1102 */ 1103 void 1104 bhnd_free_core_clkctl(struct bhnd_core_clkctl *clkctl) 1105 { 1106 BHND_CLKCTL_LOCK_DESTROY(clkctl); 1107 1108 free(clkctl, M_BHND); 1109 } 1110 1111 /** 1112 * Wait for the per-core clock status to be equal to @p value after 1113 * applying @p mask, timing out after the maximum transition latency is reached. 1114 * 1115 * @param clkctl Per-core clkctl state to be queryied. 1116 * @param value Value to wait for. 1117 * @param mask Mask to apply prior to value comparison. 1118 * 1119 * @retval 0 success 1120 * @retval ETIMEDOUT if the PMU's maximum transition delay is reached before 1121 * the clock status matches @p value and @p mask. 1122 */ 1123 int 1124 bhnd_core_clkctl_wait(struct bhnd_core_clkctl *clkctl, uint32_t value, 1125 uint32_t mask) 1126 { 1127 uint32_t clkst; 1128 1129 BHND_CLKCTL_LOCK_ASSERT(clkctl, MA_OWNED); 1130 1131 /* Bitswapped HTAVAIL/ALPAVAIL work-around */ 1132 if (clkctl->cc_quirks & BHND_CLKCTL_QUIRK_CCS0) { 1133 uint32_t fmask, fval; 1134 1135 fmask = mask & ~(BHND_CCS_HTAVAIL | BHND_CCS_ALPAVAIL); 1136 fval = value & ~(BHND_CCS_HTAVAIL | BHND_CCS_ALPAVAIL); 1137 1138 if (mask & BHND_CCS_HTAVAIL) 1139 fmask |= BHND_CCS0_HTAVAIL; 1140 if (value & BHND_CCS_HTAVAIL) 1141 fval |= BHND_CCS0_HTAVAIL; 1142 1143 if (mask & BHND_CCS_ALPAVAIL) 1144 fmask |= BHND_CCS0_ALPAVAIL; 1145 if (value & BHND_CCS_ALPAVAIL) 1146 fval |= BHND_CCS0_ALPAVAIL; 1147 1148 mask = fmask; 1149 value = fval; 1150 } 1151 1152 for (u_int i = 0; i < clkctl->cc_max_latency; i += 10) { 1153 clkst = bhnd_bus_read_4(clkctl->cc_res, clkctl->cc_res_offset); 1154 if ((clkst & mask) == (value & mask)) 1155 return (0); 1156 1157 DELAY(10); 1158 } 1159 1160 device_printf(clkctl->cc_dev, "clkst wait timeout (value=%#x, " 1161 "mask=%#x)\n", value, mask); 1162 1163 return (ETIMEDOUT); 1164 } 1165 1166 /** 1167 * Read an NVRAM variable's NUL-terminated string value. 1168 * 1169 * @param dev A bhnd bus child device. 1170 * @param name The NVRAM variable name. 1171 * @param[out] buf A buffer large enough to hold @p len bytes. On 1172 * success, the NUL-terminated string value will be 1173 * written to this buffer. This argment may be NULL if 1174 * the value is not desired. 1175 * @param len The maximum capacity of @p buf. 1176 * @param[out] rlen On success, will be set to the actual size of 1177 * the requested value (including NUL termination). This 1178 * argment may be NULL if the size is not desired. 1179 * 1180 * @retval 0 success 1181 * @retval ENOENT The requested variable was not found. 1182 * @retval ENODEV No valid NVRAM source could be found. 1183 * @retval ENOMEM If @p buf is non-NULL and a buffer of @p len is too 1184 * small to hold the requested value. 1185 * @retval EFTYPE If the variable data cannot be coerced to a valid 1186 * string representation. 1187 * @retval ERANGE If value coercion would overflow @p type. 1188 * @retval non-zero If reading @p name otherwise fails, a regular unix 1189 * error code will be returned. 1190 */ 1191 int 1192 bhnd_nvram_getvar_str(device_t dev, const char *name, char *buf, size_t len, 1193 size_t *rlen) 1194 { 1195 size_t larg; 1196 int error; 1197 1198 larg = len; 1199 error = bhnd_nvram_getvar(dev, name, buf, &larg, 1200 BHND_NVRAM_TYPE_STRING); 1201 if (rlen != NULL) 1202 *rlen = larg; 1203 1204 return (error); 1205 } 1206 1207 /** 1208 * Read an NVRAM variable's unsigned integer value. 1209 * 1210 * @param dev A bhnd bus child device. 1211 * @param name The NVRAM variable name. 1212 * @param[out] value On success, the requested value will be written 1213 * to this pointer. 1214 * @param width The output integer type width (1, 2, or 1215 * 4 bytes). 1216 * 1217 * @retval 0 success 1218 * @retval ENOENT The requested variable was not found. 1219 * @retval ENODEV No valid NVRAM source could be found. 1220 * @retval EFTYPE If the variable data cannot be coerced to a 1221 * a valid unsigned integer representation. 1222 * @retval ERANGE If value coercion would overflow (or underflow) an 1223 * unsigned representation of the given @p width. 1224 * @retval non-zero If reading @p name otherwise fails, a regular unix 1225 * error code will be returned. 1226 */ 1227 int 1228 bhnd_nvram_getvar_uint(device_t dev, const char *name, void *value, int width) 1229 { 1230 bhnd_nvram_type type; 1231 size_t len; 1232 1233 switch (width) { 1234 case 1: 1235 type = BHND_NVRAM_TYPE_UINT8; 1236 break; 1237 case 2: 1238 type = BHND_NVRAM_TYPE_UINT16; 1239 break; 1240 case 4: 1241 type = BHND_NVRAM_TYPE_UINT32; 1242 break; 1243 default: 1244 device_printf(dev, "unsupported NVRAM integer width: %d\n", 1245 width); 1246 return (EINVAL); 1247 } 1248 1249 len = width; 1250 return (bhnd_nvram_getvar(dev, name, value, &len, type)); 1251 } 1252 1253 /** 1254 * Read an NVRAM variable's unsigned 8-bit integer value. 1255 * 1256 * @param dev A bhnd bus child device. 1257 * @param name The NVRAM variable name. 1258 * @param[out] value On success, the requested value will be written 1259 * to this pointer. 1260 * 1261 * @retval 0 success 1262 * @retval ENOENT The requested variable was not found. 1263 * @retval ENODEV No valid NVRAM source could be found. 1264 * @retval EFTYPE If the variable data cannot be coerced to a 1265 * a valid unsigned integer representation. 1266 * @retval ERANGE If value coercion would overflow (or underflow) uint8_t. 1267 * @retval non-zero If reading @p name otherwise fails, a regular unix 1268 * error code will be returned. 1269 */ 1270 int 1271 bhnd_nvram_getvar_uint8(device_t dev, const char *name, uint8_t *value) 1272 { 1273 return (bhnd_nvram_getvar_uint(dev, name, value, sizeof(*value))); 1274 } 1275 1276 /** 1277 * Read an NVRAM variable's unsigned 16-bit integer value. 1278 * 1279 * @param dev A bhnd bus child device. 1280 * @param name The NVRAM variable name. 1281 * @param[out] value On success, the requested value will be written 1282 * to this pointer. 1283 * 1284 * @retval 0 success 1285 * @retval ENOENT The requested variable was not found. 1286 * @retval ENODEV No valid NVRAM source could be found. 1287 * @retval EFTYPE If the variable data cannot be coerced to a 1288 * a valid unsigned integer representation. 1289 * @retval ERANGE If value coercion would overflow (or underflow) 1290 * uint16_t. 1291 * @retval non-zero If reading @p name otherwise fails, a regular unix 1292 * error code will be returned. 1293 */ 1294 int 1295 bhnd_nvram_getvar_uint16(device_t dev, const char *name, uint16_t *value) 1296 { 1297 return (bhnd_nvram_getvar_uint(dev, name, value, sizeof(*value))); 1298 } 1299 1300 /** 1301 * Read an NVRAM variable's unsigned 32-bit integer value. 1302 * 1303 * @param dev A bhnd bus child device. 1304 * @param name The NVRAM variable name. 1305 * @param[out] value On success, the requested value will be written 1306 * to this pointer. 1307 * 1308 * @retval 0 success 1309 * @retval ENOENT The requested variable was not found. 1310 * @retval ENODEV No valid NVRAM source could be found. 1311 * @retval EFTYPE If the variable data cannot be coerced to a 1312 * a valid unsigned integer representation. 1313 * @retval ERANGE If value coercion would overflow (or underflow) 1314 * uint32_t. 1315 * @retval non-zero If reading @p name otherwise fails, a regular unix 1316 * error code will be returned. 1317 */ 1318 int 1319 bhnd_nvram_getvar_uint32(device_t dev, const char *name, uint32_t *value) 1320 { 1321 return (bhnd_nvram_getvar_uint(dev, name, value, sizeof(*value))); 1322 } 1323 1324 /** 1325 * Read an NVRAM variable's signed integer value. 1326 * 1327 * @param dev A bhnd bus child device. 1328 * @param name The NVRAM variable name. 1329 * @param[out] value On success, the requested value will be written 1330 * to this pointer. 1331 * @param width The output integer type width (1, 2, or 1332 * 4 bytes). 1333 * 1334 * @retval 0 success 1335 * @retval ENOENT The requested variable was not found. 1336 * @retval ENODEV No valid NVRAM source could be found. 1337 * @retval EFTYPE If the variable data cannot be coerced to a 1338 * a valid integer representation. 1339 * @retval ERANGE If value coercion would overflow (or underflow) an 1340 * signed representation of the given @p width. 1341 * @retval non-zero If reading @p name otherwise fails, a regular unix 1342 * error code will be returned. 1343 */ 1344 int 1345 bhnd_nvram_getvar_int(device_t dev, const char *name, void *value, int width) 1346 { 1347 bhnd_nvram_type type; 1348 size_t len; 1349 1350 switch (width) { 1351 case 1: 1352 type = BHND_NVRAM_TYPE_INT8; 1353 break; 1354 case 2: 1355 type = BHND_NVRAM_TYPE_INT16; 1356 break; 1357 case 4: 1358 type = BHND_NVRAM_TYPE_INT32; 1359 break; 1360 default: 1361 device_printf(dev, "unsupported NVRAM integer width: %d\n", 1362 width); 1363 return (EINVAL); 1364 } 1365 1366 len = width; 1367 return (bhnd_nvram_getvar(dev, name, value, &len, type)); 1368 } 1369 1370 /** 1371 * Read an NVRAM variable's signed 8-bit integer value. 1372 * 1373 * @param dev A bhnd bus child device. 1374 * @param name The NVRAM variable name. 1375 * @param[out] value On success, the requested value will be written 1376 * to this pointer. 1377 * 1378 * @retval 0 success 1379 * @retval ENOENT The requested variable was not found. 1380 * @retval ENODEV No valid NVRAM source could be found. 1381 * @retval EFTYPE If the variable data cannot be coerced to a 1382 * a valid integer representation. 1383 * @retval ERANGE If value coercion would overflow (or underflow) int8_t. 1384 * @retval non-zero If reading @p name otherwise fails, a regular unix 1385 * error code will be returned. 1386 */ 1387 int 1388 bhnd_nvram_getvar_int8(device_t dev, const char *name, int8_t *value) 1389 { 1390 return (bhnd_nvram_getvar_int(dev, name, value, sizeof(*value))); 1391 } 1392 1393 /** 1394 * Read an NVRAM variable's signed 16-bit integer value. 1395 * 1396 * @param dev A bhnd bus child device. 1397 * @param name The NVRAM variable name. 1398 * @param[out] value On success, the requested value will be written 1399 * to this pointer. 1400 * 1401 * @retval 0 success 1402 * @retval ENOENT The requested variable was not found. 1403 * @retval ENODEV No valid NVRAM source could be found. 1404 * @retval EFTYPE If the variable data cannot be coerced to a 1405 * a valid integer representation. 1406 * @retval ERANGE If value coercion would overflow (or underflow) 1407 * int16_t. 1408 * @retval non-zero If reading @p name otherwise fails, a regular unix 1409 * error code will be returned. 1410 */ 1411 int 1412 bhnd_nvram_getvar_int16(device_t dev, const char *name, int16_t *value) 1413 { 1414 return (bhnd_nvram_getvar_int(dev, name, value, sizeof(*value))); 1415 } 1416 1417 /** 1418 * Read an NVRAM variable's signed 32-bit integer value. 1419 * 1420 * @param dev A bhnd bus child device. 1421 * @param name The NVRAM variable name. 1422 * @param[out] value On success, the requested value will be written 1423 * to this pointer. 1424 * 1425 * @retval 0 success 1426 * @retval ENOENT The requested variable was not found. 1427 * @retval ENODEV No valid NVRAM source could be found. 1428 * @retval EFTYPE If the variable data cannot be coerced to a 1429 * a valid integer representation. 1430 * @retval ERANGE If value coercion would overflow (or underflow) 1431 * int32_t. 1432 * @retval non-zero If reading @p name otherwise fails, a regular unix 1433 * error code will be returned. 1434 */ 1435 int 1436 bhnd_nvram_getvar_int32(device_t dev, const char *name, int32_t *value) 1437 { 1438 return (bhnd_nvram_getvar_int(dev, name, value, sizeof(*value))); 1439 } 1440 1441 /** 1442 * Read an NVRAM variable's array value. 1443 * 1444 * @param dev A bhnd bus child device. 1445 * @param name The NVRAM variable name. 1446 * @param[out] buf A buffer large enough to hold @p size bytes. 1447 * On success, the requested value will be written 1448 * to this buffer. 1449 * @param[in,out] size The required number of bytes to write to 1450 * @p buf. 1451 * @param type The desired array element data representation. 1452 * 1453 * @retval 0 success 1454 * @retval ENOENT The requested variable was not found. 1455 * @retval ENODEV No valid NVRAM source could be found. 1456 * @retval ENXIO If less than @p size bytes are available. 1457 * @retval ENOMEM If a buffer of @p size is too small to hold the 1458 * requested value. 1459 * @retval EFTYPE If the variable data cannot be coerced to a 1460 * a valid instance of @p type. 1461 * @retval ERANGE If value coercion would overflow (or underflow) a 1462 * representation of @p type. 1463 * @retval non-zero If reading @p name otherwise fails, a regular unix 1464 * error code will be returned. 1465 */ 1466 int 1467 bhnd_nvram_getvar_array(device_t dev, const char *name, void *buf, size_t size, 1468 bhnd_nvram_type type) 1469 { 1470 size_t nbytes; 1471 int error; 1472 1473 /* Attempt read */ 1474 nbytes = size; 1475 if ((error = bhnd_nvram_getvar(dev, name, buf, &nbytes, type))) 1476 return (error); 1477 1478 /* Verify that the expected number of bytes were fetched */ 1479 if (nbytes < size) 1480 return (ENXIO); 1481 1482 return (0); 1483 } 1484 1485 /** 1486 * Initialize a service provider registry. 1487 * 1488 * @param bsr The service registry to initialize. 1489 * 1490 * @retval 0 success 1491 * @retval non-zero if an error occurs initializing the service registry, 1492 * a regular unix error code will be returned. 1493 1494 */ 1495 int 1496 bhnd_service_registry_init(struct bhnd_service_registry *bsr) 1497 { 1498 STAILQ_INIT(&bsr->entries); 1499 mtx_init(&bsr->lock, "bhnd_service_registry lock", NULL, MTX_DEF); 1500 1501 return (0); 1502 } 1503 1504 /** 1505 * Release all resources held by @p bsr. 1506 * 1507 * @param bsr A service registry instance previously successfully 1508 * initialized via bhnd_service_registry_init(). 1509 * 1510 * @retval 0 success 1511 * @retval EBUSY if active references to service providers registered 1512 * with @p bsr exist. 1513 */ 1514 int 1515 bhnd_service_registry_fini(struct bhnd_service_registry *bsr) 1516 { 1517 struct bhnd_service_entry *entry, *enext; 1518 1519 /* Remove everthing we can */ 1520 mtx_lock(&bsr->lock); 1521 STAILQ_FOREACH_SAFE(entry, &bsr->entries, link, enext) { 1522 if (entry->refs > 0) 1523 continue; 1524 1525 STAILQ_REMOVE(&bsr->entries, entry, bhnd_service_entry, link); 1526 free(entry, M_BHND); 1527 } 1528 1529 if (!STAILQ_EMPTY(&bsr->entries)) { 1530 mtx_unlock(&bsr->lock); 1531 return (EBUSY); 1532 } 1533 mtx_unlock(&bsr->lock); 1534 1535 mtx_destroy(&bsr->lock); 1536 return (0); 1537 } 1538 1539 /** 1540 * Register a @p provider for the given @p service. 1541 * 1542 * @param bsr Service registry to be modified. 1543 * @param provider Service provider to register. 1544 * @param service Service for which @p provider will be registered. 1545 * @param flags Service provider flags (see BHND_SPF_*). 1546 * 1547 * @retval 0 success 1548 * @retval EEXIST if an entry for @p service already exists. 1549 * @retval EINVAL if @p service is BHND_SERVICE_ANY. 1550 * @retval non-zero if registering @p provider otherwise fails, a regular 1551 * unix error code will be returned. 1552 */ 1553 int 1554 bhnd_service_registry_add(struct bhnd_service_registry *bsr, device_t provider, 1555 bhnd_service_t service, uint32_t flags) 1556 { 1557 struct bhnd_service_entry *entry; 1558 1559 if (service == BHND_SERVICE_ANY) 1560 return (EINVAL); 1561 1562 mtx_lock(&bsr->lock); 1563 1564 /* Is a service provider already registered? */ 1565 STAILQ_FOREACH(entry, &bsr->entries, link) { 1566 if (entry->service == service) { 1567 mtx_unlock(&bsr->lock); 1568 return (EEXIST); 1569 } 1570 } 1571 1572 /* Initialize and insert our new entry */ 1573 entry = malloc(sizeof(*entry), M_BHND, M_NOWAIT); 1574 if (entry == NULL) { 1575 mtx_unlock(&bsr->lock); 1576 return (ENOMEM); 1577 } 1578 1579 entry->provider = provider; 1580 entry->service = service; 1581 entry->flags = flags; 1582 refcount_init(&entry->refs, 0); 1583 1584 STAILQ_INSERT_HEAD(&bsr->entries, entry, link); 1585 1586 mtx_unlock(&bsr->lock); 1587 return (0); 1588 } 1589 1590 /** 1591 * Free an unreferenced registry entry. 1592 * 1593 * @param entry The entry to be deallocated. 1594 */ 1595 static void 1596 bhnd_service_registry_free_entry(struct bhnd_service_entry *entry) 1597 { 1598 KASSERT(entry->refs == 0, ("provider has active references")); 1599 free(entry, M_BHND); 1600 } 1601 1602 /** 1603 * Attempt to remove the @p service provider registration for @p provider. 1604 * 1605 * @param bsr The service registry to be modified. 1606 * @param provider The service provider to be deregistered. 1607 * @param service The service for which @p provider will be deregistered, 1608 * or BHND_SERVICE_ANY to remove all service 1609 * registrations for @p provider. 1610 * 1611 * @retval 0 success 1612 * @retval EBUSY if active references to @p provider exist; see 1613 * bhnd_service_registry_retain() and 1614 * bhnd_service_registry_release(). 1615 */ 1616 int 1617 bhnd_service_registry_remove(struct bhnd_service_registry *bsr, 1618 device_t provider, bhnd_service_t service) 1619 { 1620 struct bhnd_service_entry *entry, *enext; 1621 1622 mtx_lock(&bsr->lock); 1623 1624 #define BHND_PROV_MATCH(_e) \ 1625 ((_e)->provider == provider && \ 1626 (service == BHND_SERVICE_ANY || (_e)->service == service)) 1627 1628 /* Validate matching provider entries before making any 1629 * modifications */ 1630 STAILQ_FOREACH(entry, &bsr->entries, link) { 1631 /* Skip non-matching entries */ 1632 if (!BHND_PROV_MATCH(entry)) 1633 continue; 1634 1635 /* Entry is in use? */ 1636 if (entry->refs > 0) { 1637 mtx_unlock(&bsr->lock); 1638 return (EBUSY); 1639 } 1640 } 1641 1642 /* We can now safely remove matching entries */ 1643 STAILQ_FOREACH_SAFE(entry, &bsr->entries, link, enext) { 1644 /* Skip non-matching entries */ 1645 if (!BHND_PROV_MATCH(entry)) 1646 continue; 1647 1648 /* Remove from list */ 1649 STAILQ_REMOVE(&bsr->entries, entry, bhnd_service_entry, link); 1650 1651 /* Free provider entry */ 1652 bhnd_service_registry_free_entry(entry); 1653 } 1654 #undef BHND_PROV_MATCH 1655 1656 mtx_unlock(&bsr->lock); 1657 return (0); 1658 } 1659 1660 /** 1661 * Retain and return a reference to a registered @p service provider, if any. 1662 * 1663 * @param bsr The service registry to be queried. 1664 * @param service The service for which a provider should be returned. 1665 * 1666 * On success, the caller assumes ownership the returned provider, and 1667 * is responsible for releasing this reference via 1668 * bhnd_service_registry_release(). 1669 * 1670 * @retval device_t success 1671 * @retval NULL if no provider is registered for @p service. 1672 */ 1673 device_t 1674 bhnd_service_registry_retain(struct bhnd_service_registry *bsr, 1675 bhnd_service_t service) 1676 { 1677 struct bhnd_service_entry *entry; 1678 1679 mtx_lock(&bsr->lock); 1680 STAILQ_FOREACH(entry, &bsr->entries, link) { 1681 if (entry->service != service) 1682 continue; 1683 1684 /* With a live refcount, entry is gauranteed to remain alive 1685 * after we release our lock */ 1686 refcount_acquire(&entry->refs); 1687 1688 mtx_unlock(&bsr->lock); 1689 return (entry->provider); 1690 } 1691 mtx_unlock(&bsr->lock); 1692 1693 /* Not found */ 1694 return (NULL); 1695 } 1696 1697 /** 1698 * Release a reference to a service provider previously returned by 1699 * bhnd_service_registry_retain(). 1700 * 1701 * If this is the last reference to an inherited service provider registration 1702 * (see BHND_SPF_INHERITED), the registration will also be removed, and 1703 * true will be returned. 1704 * 1705 * @param bsr The service registry from which @p provider 1706 * was returned. 1707 * @param provider The provider to be released. 1708 * @param service The service for which @p provider was previously 1709 * retained. 1710 * @retval true The inherited service provider registration was removed; 1711 * the caller should release its own reference to the 1712 * provider. 1713 * @retval false The service provider was not inherited, or active 1714 * references to the provider remain. 1715 * 1716 * @see BHND_SPF_INHERITED 1717 */ 1718 bool 1719 bhnd_service_registry_release(struct bhnd_service_registry *bsr, 1720 device_t provider, bhnd_service_t service) 1721 { 1722 struct bhnd_service_entry *entry; 1723 1724 /* Exclusive lock, as we need to prevent any new references to the 1725 * entry from being taken if it's to be removed */ 1726 mtx_lock(&bsr->lock); 1727 STAILQ_FOREACH(entry, &bsr->entries, link) { 1728 bool removed; 1729 1730 if (entry->provider != provider) 1731 continue; 1732 1733 if (entry->service != service) 1734 continue; 1735 1736 if (refcount_release(&entry->refs) && 1737 (entry->flags & BHND_SPF_INHERITED)) 1738 { 1739 /* If an inherited entry is no longer actively 1740 * referenced, remove the local registration and inform 1741 * the caller. */ 1742 STAILQ_REMOVE(&bsr->entries, entry, bhnd_service_entry, 1743 link); 1744 bhnd_service_registry_free_entry(entry); 1745 removed = true; 1746 } else { 1747 removed = false; 1748 } 1749 1750 mtx_unlock(&bsr->lock); 1751 return (removed); 1752 } 1753 1754 /* Caller owns a reference, but no such provider is registered? */ 1755 panic("invalid service provider reference"); 1756 } 1757 1758 /** 1759 * Using the bhnd(4) bus-level core information and a custom core name, 1760 * populate @p dev's device description. 1761 * 1762 * @param dev A bhnd-bus attached device. 1763 * @param dev_name The core's name (e.g. "SDIO Device Core"). 1764 */ 1765 void 1766 bhnd_set_custom_core_desc(device_t dev, const char *dev_name) 1767 { 1768 const char *vendor_name; 1769 char *desc; 1770 1771 vendor_name = bhnd_get_vendor_name(dev); 1772 asprintf(&desc, M_BHND, "%s %s, rev %hhu", vendor_name, dev_name, 1773 bhnd_get_hwrev(dev)); 1774 1775 if (desc != NULL) { 1776 device_set_desc_copy(dev, desc); 1777 free(desc, M_BHND); 1778 } else { 1779 device_set_desc(dev, dev_name); 1780 } 1781 } 1782 1783 /** 1784 * Using the bhnd(4) bus-level core information, populate @p dev's device 1785 * description. 1786 * 1787 * @param dev A bhnd-bus attached device. 1788 */ 1789 void 1790 bhnd_set_default_core_desc(device_t dev) 1791 { 1792 bhnd_set_custom_core_desc(dev, bhnd_get_device_name(dev)); 1793 } 1794 1795 /** 1796 * Using the bhnd @p chip_id, populate the bhnd(4) bus @p dev's device 1797 * description. 1798 * 1799 * @param dev A bhnd-bus attached device. 1800 * @param chip_id The chip identification. 1801 */ 1802 void 1803 bhnd_set_default_bus_desc(device_t dev, const struct bhnd_chipid *chip_id) 1804 { 1805 const char *bus_name; 1806 char *desc; 1807 char chip_name[BHND_CHIPID_MAX_NAMELEN]; 1808 1809 /* Determine chip type's bus name */ 1810 switch (chip_id->chip_type) { 1811 case BHND_CHIPTYPE_SIBA: 1812 bus_name = "SIBA bus"; 1813 break; 1814 case BHND_CHIPTYPE_BCMA: 1815 case BHND_CHIPTYPE_BCMA_ALT: 1816 bus_name = "BCMA bus"; 1817 break; 1818 case BHND_CHIPTYPE_UBUS: 1819 bus_name = "UBUS bus"; 1820 break; 1821 default: 1822 bus_name = "Unknown Type"; 1823 break; 1824 } 1825 1826 /* Format chip name */ 1827 bhnd_format_chip_id(chip_name, sizeof(chip_name), 1828 chip_id->chip_id); 1829 1830 /* Format and set device description */ 1831 asprintf(&desc, M_BHND, "%s %s", chip_name, bus_name); 1832 if (desc != NULL) { 1833 device_set_desc_copy(dev, desc); 1834 free(desc, M_BHND); 1835 } else { 1836 device_set_desc(dev, bus_name); 1837 } 1838 1839 } 1840 1841 /** 1842 * Helper function for implementing BHND_BUS_REGISTER_PROVIDER(). 1843 * 1844 * This implementation delegates the request to the BHND_BUS_REGISTER_PROVIDER() 1845 * method on the parent of @p dev. If no parent exists, the implementation 1846 * will return an error. 1847 */ 1848 int 1849 bhnd_bus_generic_register_provider(device_t dev, device_t child, 1850 device_t provider, bhnd_service_t service) 1851 { 1852 device_t parent = device_get_parent(dev); 1853 1854 if (parent != NULL) { 1855 return (BHND_BUS_REGISTER_PROVIDER(parent, child, 1856 provider, service)); 1857 } 1858 1859 return (ENXIO); 1860 } 1861 1862 /** 1863 * Helper function for implementing BHND_BUS_DEREGISTER_PROVIDER(). 1864 * 1865 * This implementation delegates the request to the 1866 * BHND_BUS_DEREGISTER_PROVIDER() method on the parent of @p dev. If no parent 1867 * exists, the implementation will panic. 1868 */ 1869 int 1870 bhnd_bus_generic_deregister_provider(device_t dev, device_t child, 1871 device_t provider, bhnd_service_t service) 1872 { 1873 device_t parent = device_get_parent(dev); 1874 1875 if (parent != NULL) { 1876 return (BHND_BUS_DEREGISTER_PROVIDER(parent, child, 1877 provider, service)); 1878 } 1879 1880 panic("missing BHND_BUS_DEREGISTER_PROVIDER()"); 1881 } 1882 1883 /** 1884 * Helper function for implementing BHND_BUS_RETAIN_PROVIDER(). 1885 * 1886 * This implementation delegates the request to the 1887 * BHND_BUS_DEREGISTER_PROVIDER() method on the parent of @p dev. If no parent 1888 * exists, the implementation will return NULL. 1889 */ 1890 device_t 1891 bhnd_bus_generic_retain_provider(device_t dev, device_t child, 1892 bhnd_service_t service) 1893 { 1894 device_t parent = device_get_parent(dev); 1895 1896 if (parent != NULL) { 1897 return (BHND_BUS_RETAIN_PROVIDER(parent, child, 1898 service)); 1899 } 1900 1901 return (NULL); 1902 } 1903 1904 /** 1905 * Helper function for implementing BHND_BUS_RELEASE_PROVIDER(). 1906 * 1907 * This implementation delegates the request to the 1908 * BHND_BUS_DEREGISTER_PROVIDER() method on the parent of @p dev. If no parent 1909 * exists, the implementation will panic. 1910 */ 1911 void 1912 bhnd_bus_generic_release_provider(device_t dev, device_t child, 1913 device_t provider, bhnd_service_t service) 1914 { 1915 device_t parent = device_get_parent(dev); 1916 1917 if (parent != NULL) { 1918 return (BHND_BUS_RELEASE_PROVIDER(parent, child, 1919 provider, service)); 1920 } 1921 1922 panic("missing BHND_BUS_RELEASE_PROVIDER()"); 1923 } 1924 1925 /** 1926 * Helper function for implementing BHND_BUS_REGISTER_PROVIDER(). 1927 * 1928 * This implementation uses the bhnd_service_registry_add() function to 1929 * do most of the work. It calls BHND_BUS_GET_SERVICE_REGISTRY() to find 1930 * a suitable service registry to edit. 1931 */ 1932 int 1933 bhnd_bus_generic_sr_register_provider(device_t dev, device_t child, 1934 device_t provider, bhnd_service_t service) 1935 { 1936 struct bhnd_service_registry *bsr; 1937 1938 bsr = BHND_BUS_GET_SERVICE_REGISTRY(dev, child); 1939 1940 KASSERT(bsr != NULL, ("NULL service registry")); 1941 1942 return (bhnd_service_registry_add(bsr, provider, service, 0)); 1943 } 1944 1945 /** 1946 * Helper function for implementing BHND_BUS_DEREGISTER_PROVIDER(). 1947 * 1948 * This implementation uses the bhnd_service_registry_remove() function to 1949 * do most of the work. It calls BHND_BUS_GET_SERVICE_REGISTRY() to find 1950 * a suitable service registry to edit. 1951 */ 1952 int 1953 bhnd_bus_generic_sr_deregister_provider(device_t dev, device_t child, 1954 device_t provider, bhnd_service_t service) 1955 { 1956 struct bhnd_service_registry *bsr; 1957 1958 bsr = BHND_BUS_GET_SERVICE_REGISTRY(dev, child); 1959 1960 KASSERT(bsr != NULL, ("NULL service registry")); 1961 1962 return (bhnd_service_registry_remove(bsr, provider, service)); 1963 } 1964 1965 /** 1966 * Helper function for implementing BHND_BUS_RETAIN_PROVIDER(). 1967 * 1968 * This implementation uses the bhnd_service_registry_retain() function to 1969 * do most of the work. It calls BHND_BUS_GET_SERVICE_REGISTRY() to find 1970 * a suitable service registry. 1971 * 1972 * If a local provider for the service is not available, and a parent device is 1973 * available, this implementation will attempt to fetch and locally register 1974 * a service provider reference from the parent of @p dev. 1975 */ 1976 device_t 1977 bhnd_bus_generic_sr_retain_provider(device_t dev, device_t child, 1978 bhnd_service_t service) 1979 { 1980 struct bhnd_service_registry *bsr; 1981 device_t parent, provider; 1982 int error; 1983 1984 bsr = BHND_BUS_GET_SERVICE_REGISTRY(dev, child); 1985 KASSERT(bsr != NULL, ("NULL service registry")); 1986 1987 /* 1988 * Attempt to fetch a service provider reference from either the local 1989 * service registry, or if not found, from our parent. 1990 * 1991 * If we fetch a provider from our parent, we register the provider 1992 * with the local service registry to prevent conflicting local 1993 * registrations from being added. 1994 */ 1995 while (1) { 1996 /* Check the local service registry first */ 1997 provider = bhnd_service_registry_retain(bsr, service); 1998 if (provider != NULL) 1999 return (provider); 2000 2001 /* Otherwise, try to delegate to our parent (if any) */ 2002 if ((parent = device_get_parent(dev)) == NULL) 2003 return (NULL); 2004 2005 provider = BHND_BUS_RETAIN_PROVIDER(parent, dev, service); 2006 if (provider == NULL) 2007 return (NULL); 2008 2009 /* Register the inherited service registration with the local 2010 * registry */ 2011 error = bhnd_service_registry_add(bsr, provider, service, 2012 BHND_SPF_INHERITED); 2013 if (error) { 2014 BHND_BUS_RELEASE_PROVIDER(parent, dev, provider, 2015 service); 2016 if (error == EEXIST) { 2017 /* A valid service provider was registered 2018 * concurrently; retry fetching from the local 2019 * registry */ 2020 continue; 2021 } 2022 2023 device_printf(dev, "failed to register service " 2024 "provider: %d\n", error); 2025 return (NULL); 2026 } 2027 } 2028 } 2029 2030 /** 2031 * Helper function for implementing BHND_BUS_RELEASE_PROVIDER(). 2032 * 2033 * This implementation uses the bhnd_service_registry_release() function to 2034 * do most of the work. It calls BHND_BUS_GET_SERVICE_REGISTRY() to find 2035 * a suitable service registry. 2036 */ 2037 void 2038 bhnd_bus_generic_sr_release_provider(device_t dev, device_t child, 2039 device_t provider, bhnd_service_t service) 2040 { 2041 struct bhnd_service_registry *bsr; 2042 2043 bsr = BHND_BUS_GET_SERVICE_REGISTRY(dev, child); 2044 KASSERT(bsr != NULL, ("NULL service registry")); 2045 2046 /* Release the provider reference; if the refcount hits zero on an 2047 * inherited reference, true will be returned, and we need to drop 2048 * our own bus reference to the provider */ 2049 if (!bhnd_service_registry_release(bsr, provider, service)) 2050 return; 2051 2052 /* Drop our reference to the borrowed provider */ 2053 BHND_BUS_RELEASE_PROVIDER(device_get_parent(dev), dev, provider, 2054 service); 2055 } 2056 2057 /** 2058 * Helper function for implementing BHND_BUS_IS_HW_DISABLED(). 2059 * 2060 * If a parent device is available, this implementation delegates the 2061 * request to the BHND_BUS_IS_HW_DISABLED() method on the parent of @p dev. 2062 * 2063 * If no parent device is available (i.e. on a the bus root), the hardware 2064 * is assumed to be usable and false is returned. 2065 */ 2066 bool 2067 bhnd_bus_generic_is_hw_disabled(device_t dev, device_t child) 2068 { 2069 if (device_get_parent(dev) != NULL) 2070 return (BHND_BUS_IS_HW_DISABLED(device_get_parent(dev), child)); 2071 2072 return (false); 2073 } 2074 2075 /** 2076 * Helper function for implementing BHND_BUS_GET_CHIPID(). 2077 * 2078 * This implementation delegates the request to the BHND_BUS_GET_CHIPID() 2079 * method on the parent of @p dev. If no parent exists, the implementation 2080 * will panic. 2081 */ 2082 const struct bhnd_chipid * 2083 bhnd_bus_generic_get_chipid(device_t dev, device_t child) 2084 { 2085 if (device_get_parent(dev) != NULL) 2086 return (BHND_BUS_GET_CHIPID(device_get_parent(dev), child)); 2087 2088 panic("missing BHND_BUS_GET_CHIPID()"); 2089 } 2090 2091 /** 2092 * Helper function for implementing BHND_BUS_GET_DMA_TRANSLATION(). 2093 * 2094 * If a parent device is available, this implementation delegates the 2095 * request to the BHND_BUS_GET_DMA_TRANSLATION() method on the parent of @p dev. 2096 * 2097 * If no parent device is available, this implementation will panic. 2098 */ 2099 int 2100 bhnd_bus_generic_get_dma_translation(device_t dev, device_t child, u_int width, 2101 uint32_t flags, bus_dma_tag_t *dmat, 2102 struct bhnd_dma_translation *translation) 2103 { 2104 if (device_get_parent(dev) != NULL) { 2105 return (BHND_BUS_GET_DMA_TRANSLATION(device_get_parent(dev), 2106 child, width, flags, dmat, translation)); 2107 } 2108 2109 panic("missing BHND_BUS_GET_DMA_TRANSLATION()"); 2110 } 2111 2112 /* nvram board_info population macros for bhnd_bus_generic_read_board_info() */ 2113 #define BHND_GV(_dest, _name) \ 2114 bhnd_nvram_getvar_uint(child, BHND_NVAR_ ## _name, &_dest, \ 2115 sizeof(_dest)) 2116 2117 #define REQ_BHND_GV(_dest, _name) do { \ 2118 if ((error = BHND_GV(_dest, _name))) { \ 2119 device_printf(dev, \ 2120 "error reading " __STRING(_name) ": %d\n", error); \ 2121 return (error); \ 2122 } \ 2123 } while(0) 2124 2125 #define OPT_BHND_GV(_dest, _name, _default) do { \ 2126 if ((error = BHND_GV(_dest, _name))) { \ 2127 if (error != ENOENT) { \ 2128 device_printf(dev, \ 2129 "error reading " \ 2130 __STRING(_name) ": %d\n", error); \ 2131 return (error); \ 2132 } \ 2133 _dest = _default; \ 2134 } \ 2135 } while(0) 2136 2137 /** 2138 * Helper function for implementing BHND_BUS_READ_BOARDINFO(). 2139 * 2140 * This implementation populates @p info with information from NVRAM, 2141 * defaulting board_vendor and board_type fields to 0 if the 2142 * requested variables cannot be found. 2143 * 2144 * This behavior is correct for most SoCs, but must be overridden on 2145 * bridged (PCI, PCMCIA, etc) devices to produce a complete bhnd_board_info 2146 * result. 2147 */ 2148 int 2149 bhnd_bus_generic_read_board_info(device_t dev, device_t child, 2150 struct bhnd_board_info *info) 2151 { 2152 int error; 2153 2154 OPT_BHND_GV(info->board_vendor, BOARDVENDOR, 0); 2155 OPT_BHND_GV(info->board_type, BOARDTYPE, 0); /* srom >= 2 */ 2156 OPT_BHND_GV(info->board_devid, DEVID, 0); /* srom >= 8 */ 2157 REQ_BHND_GV(info->board_rev, BOARDREV); 2158 OPT_BHND_GV(info->board_srom_rev,SROMREV, 0); /* missing in 2159 some SoC 2160 NVRAM */ 2161 REQ_BHND_GV(info->board_flags, BOARDFLAGS); 2162 OPT_BHND_GV(info->board_flags2, BOARDFLAGS2, 0); /* srom >= 4 */ 2163 OPT_BHND_GV(info->board_flags3, BOARDFLAGS3, 0); /* srom >= 11 */ 2164 2165 return (0); 2166 } 2167 2168 #undef BHND_GV 2169 #undef BHND_GV_REQ 2170 #undef BHND_GV_OPT 2171 2172 /** 2173 * Helper function for implementing BHND_BUS_GET_NVRAM_VAR(). 2174 * 2175 * This implementation searches @p dev for a usable NVRAM child device. 2176 * 2177 * If no usable child device is found on @p dev, the request is delegated to 2178 * the BHND_BUS_GET_NVRAM_VAR() method on the parent of @p dev. 2179 */ 2180 int 2181 bhnd_bus_generic_get_nvram_var(device_t dev, device_t child, const char *name, 2182 void *buf, size_t *size, bhnd_nvram_type type) 2183 { 2184 device_t nvram; 2185 device_t parent; 2186 2187 bus_topo_assert(); 2188 2189 /* Look for a directly-attached NVRAM child */ 2190 if ((nvram = device_find_child(dev, "bhnd_nvram", -1)) != NULL) 2191 return BHND_NVRAM_GETVAR(nvram, name, buf, size, type); 2192 2193 /* Try to delegate to parent */ 2194 if ((parent = device_get_parent(dev)) == NULL) 2195 return (ENODEV); 2196 2197 return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), child, 2198 name, buf, size, type)); 2199 } 2200 2201 /** 2202 * Helper function for implementing BHND_BUS_ALLOC_RESOURCE(). 2203 * 2204 * This implementation of BHND_BUS_ALLOC_RESOURCE() delegates allocation 2205 * of the underlying resource to BUS_ALLOC_RESOURCE(), and activation 2206 * to @p dev's BHND_BUS_ACTIVATE_RESOURCE(). 2207 */ 2208 struct bhnd_resource * 2209 bhnd_bus_generic_alloc_resource(device_t dev, device_t child, int type, 2210 int *rid, rman_res_t start, rman_res_t end, rman_res_t count, 2211 u_int flags) 2212 { 2213 struct bhnd_resource *br; 2214 struct resource *res; 2215 int error; 2216 2217 br = NULL; 2218 res = NULL; 2219 2220 /* Allocate the real bus resource (without activating it) */ 2221 res = BUS_ALLOC_RESOURCE(dev, child, type, rid, start, end, count, 2222 (flags & ~RF_ACTIVE)); 2223 if (res == NULL) 2224 return (NULL); 2225 2226 /* Allocate our bhnd resource wrapper. */ 2227 br = malloc(sizeof(struct bhnd_resource), M_BHND, M_NOWAIT); 2228 if (br == NULL) 2229 goto failed; 2230 2231 br->direct = false; 2232 br->res = res; 2233 2234 /* Attempt activation */ 2235 if (flags & RF_ACTIVE) { 2236 error = BHND_BUS_ACTIVATE_RESOURCE(dev, child, type, *rid, br); 2237 if (error) 2238 goto failed; 2239 } 2240 2241 return (br); 2242 2243 failed: 2244 if (res != NULL) 2245 BUS_RELEASE_RESOURCE(dev, child, type, *rid, res); 2246 2247 free(br, M_BHND); 2248 return (NULL); 2249 } 2250 2251 /** 2252 * Helper function for implementing BHND_BUS_RELEASE_RESOURCE(). 2253 * 2254 * This implementation of BHND_BUS_RELEASE_RESOURCE() delegates release of 2255 * the backing resource to BUS_RELEASE_RESOURCE(). 2256 */ 2257 int 2258 bhnd_bus_generic_release_resource(device_t dev, device_t child, int type, 2259 int rid, struct bhnd_resource *r) 2260 { 2261 int error; 2262 2263 if ((error = BUS_RELEASE_RESOURCE(dev, child, type, rid, r->res))) 2264 return (error); 2265 2266 free(r, M_BHND); 2267 return (0); 2268 } 2269 2270 /** 2271 * Helper function for implementing BHND_BUS_ACTIVATE_RESOURCE(). 2272 * 2273 * This implementation of BHND_BUS_ACTIVATE_RESOURCE() first calls the 2274 * BHND_BUS_ACTIVATE_RESOURCE() method of the parent of @p dev. 2275 * 2276 * If this fails, and if @p dev is the direct parent of @p child, standard 2277 * resource activation is attempted via bus_activate_resource(). This enables 2278 * direct use of the bhnd(4) resource APIs on devices that may not be attached 2279 * to a parent bhnd bus or bridge. 2280 */ 2281 int 2282 bhnd_bus_generic_activate_resource(device_t dev, device_t child, int type, 2283 int rid, struct bhnd_resource *r) 2284 { 2285 int error; 2286 bool passthrough; 2287 2288 passthrough = (device_get_parent(child) != dev); 2289 2290 /* Try to delegate to the parent */ 2291 if (device_get_parent(dev) != NULL) { 2292 error = BHND_BUS_ACTIVATE_RESOURCE(device_get_parent(dev), 2293 child, type, rid, r); 2294 } else { 2295 error = ENODEV; 2296 } 2297 2298 /* If bhnd(4) activation has failed and we're the child's direct 2299 * parent, try falling back on standard resource activation. 2300 */ 2301 if (error && !passthrough) { 2302 error = bus_activate_resource(child, type, rid, r->res); 2303 if (!error) 2304 r->direct = true; 2305 } 2306 2307 return (error); 2308 } 2309 2310 /** 2311 * Helper function for implementing BHND_BUS_DEACTIVATE_RESOURCE(). 2312 * 2313 * This implementation of BHND_BUS_ACTIVATE_RESOURCE() simply calls the 2314 * BHND_BUS_ACTIVATE_RESOURCE() method of the parent of @p dev. 2315 */ 2316 int 2317 bhnd_bus_generic_deactivate_resource(device_t dev, device_t child, 2318 int type, int rid, struct bhnd_resource *r) 2319 { 2320 if (device_get_parent(dev) != NULL) 2321 return (BHND_BUS_DEACTIVATE_RESOURCE(device_get_parent(dev), 2322 child, type, rid, r)); 2323 2324 return (EINVAL); 2325 } 2326 2327 /** 2328 * Helper function for implementing BHND_BUS_GET_INTR_DOMAIN(). 2329 * 2330 * This implementation simply returns the address of nearest bhnd(4) bus, 2331 * which may be @p dev; this behavior may be incompatible with FDT/OFW targets. 2332 */ 2333 uintptr_t 2334 bhnd_bus_generic_get_intr_domain(device_t dev, device_t child, bool self) 2335 { 2336 return ((uintptr_t)dev); 2337 } 2338