1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2015-2016 Landon Fuller <landonf@FreeBSD.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 __FBSDID("$FreeBSD$"); 38 39 /* 40 * Broadcom Home Networking Division (HND) Bus Driver. 41 * 42 * The Broadcom HND family of devices consists of both SoCs and host-connected 43 * networking chipsets containing a common family of Broadcom IP cores, 44 * including an integrated MIPS and/or ARM cores. 45 * 46 * HND devices expose a nearly identical interface whether accessible over a 47 * native SoC interconnect, or when connected via a host interface such as 48 * PCIe. As a result, the majority of hardware support code should be re-usable 49 * across host drivers for HND networking chipsets, as well as FreeBSD support 50 * for Broadcom MIPS/ARM HND SoCs. 51 * 52 * Earlier HND models used the siba(4) on-chip interconnect, while later models 53 * use bcma(4); the programming model is almost entirely independent 54 * of the actual underlying interconect. 55 */ 56 57 #include <sys/param.h> 58 #include <sys/kernel.h> 59 #include <sys/bus.h> 60 #include <sys/module.h> 61 #include <sys/sbuf.h> 62 #include <sys/systm.h> 63 64 #include <machine/bus.h> 65 #include <sys/rman.h> 66 #include <machine/resource.h> 67 68 #include <dev/bhnd/cores/pmu/bhnd_pmu.h> 69 70 #include "bhnd_chipc_if.h" 71 #include "bhnd_nvram_if.h" 72 73 #include "bhnd.h" 74 #include "bhndreg.h" 75 #include "bhndvar.h" 76 77 #include "bhnd_private.h" 78 79 MALLOC_DEFINE(M_BHND, "bhnd", "bhnd bus data structures"); 80 81 /** 82 * bhnd_generic_probe_nomatch() reporting configuration. 83 */ 84 static const struct bhnd_nomatch { 85 uint16_t vendor; /**< core designer */ 86 uint16_t device; /**< core id */ 87 bool if_verbose; /**< print when bootverbose is set. */ 88 } bhnd_nomatch_table[] = { 89 { BHND_MFGID_ARM, BHND_COREID_OOB_ROUTER, true }, 90 { BHND_MFGID_ARM, BHND_COREID_EROM, true }, 91 { BHND_MFGID_ARM, BHND_COREID_PL301, true }, 92 { BHND_MFGID_ARM, BHND_COREID_APB_BRIDGE, true }, 93 { BHND_MFGID_ARM, BHND_COREID_AXI_UNMAPPED, false }, 94 { BHND_MFGID_INVALID, BHND_COREID_INVALID, false } 95 }; 96 97 static int bhnd_delete_children(struct bhnd_softc *sc); 98 99 /** 100 * Default bhnd(4) bus driver implementation of DEVICE_ATTACH(). 101 * 102 * This implementation calls device_probe_and_attach() for each of the device's 103 * children, in bhnd probe order. 104 */ 105 int 106 bhnd_generic_attach(device_t dev) 107 { 108 struct bhnd_softc *sc; 109 int error; 110 111 if (device_is_attached(dev)) 112 return (EBUSY); 113 114 sc = device_get_softc(dev); 115 sc->dev = dev; 116 117 /* Probe and attach all children */ 118 if ((error = bhnd_bus_probe_children(dev))) { 119 bhnd_delete_children(sc); 120 return (error); 121 } 122 123 return (0); 124 } 125 126 /** 127 * Detach and delete all children, in reverse of their attach order. 128 */ 129 static int 130 bhnd_delete_children(struct bhnd_softc *sc) 131 { 132 device_t *devs; 133 int ndevs; 134 int error; 135 136 /* Fetch children in detach order */ 137 error = bhnd_bus_get_children(sc->dev, &devs, &ndevs, 138 BHND_DEVICE_ORDER_DETACH); 139 if (error) 140 return (error); 141 142 /* Perform detach */ 143 for (int i = 0; i < ndevs; i++) { 144 device_t child = devs[i]; 145 146 /* Terminate on first error */ 147 if ((error = device_delete_child(sc->dev, child))) 148 goto cleanup; 149 } 150 151 cleanup: 152 bhnd_bus_free_children(devs); 153 return (error); 154 } 155 156 /** 157 * Default bhnd(4) bus driver implementation of DEVICE_DETACH(). 158 * 159 * This implementation calls device_detach() for each of the device's 160 * children, in reverse bhnd probe order, terminating if any call to 161 * device_detach() fails. 162 */ 163 int 164 bhnd_generic_detach(device_t dev) 165 { 166 struct bhnd_softc *sc; 167 int error; 168 169 if (!device_is_attached(dev)) 170 return (EBUSY); 171 172 sc = device_get_softc(dev); 173 174 if ((error = bhnd_delete_children(sc))) 175 return (error); 176 177 return (0); 178 } 179 180 /** 181 * Default bhnd(4) bus driver implementation of DEVICE_SHUTDOWN(). 182 * 183 * This implementation calls device_shutdown() for each of the device's 184 * children, in reverse bhnd probe order, terminating if any call to 185 * device_shutdown() fails. 186 */ 187 int 188 bhnd_generic_shutdown(device_t dev) 189 { 190 device_t *devs; 191 int ndevs; 192 int error; 193 194 if (!device_is_attached(dev)) 195 return (EBUSY); 196 197 /* Fetch children in detach order */ 198 error = bhnd_bus_get_children(dev, &devs, &ndevs, 199 BHND_DEVICE_ORDER_DETACH); 200 if (error) 201 return (error); 202 203 /* Perform shutdown */ 204 for (int i = 0; i < ndevs; i++) { 205 device_t child = devs[i]; 206 207 /* Terminate on first error */ 208 if ((error = device_shutdown(child))) 209 goto cleanup; 210 } 211 212 cleanup: 213 bhnd_bus_free_children(devs); 214 return (error); 215 } 216 217 /** 218 * Default bhnd(4) bus driver implementation of DEVICE_RESUME(). 219 * 220 * This implementation calls BUS_RESUME_CHILD() for each of the device's 221 * children in bhnd probe order, terminating if any call to BUS_RESUME_CHILD() 222 * fails. 223 */ 224 int 225 bhnd_generic_resume(device_t dev) 226 { 227 device_t *devs; 228 int ndevs; 229 int error; 230 231 if (!device_is_attached(dev)) 232 return (EBUSY); 233 234 /* Fetch children in attach order */ 235 error = bhnd_bus_get_children(dev, &devs, &ndevs, 236 BHND_DEVICE_ORDER_ATTACH); 237 if (error) 238 return (error); 239 240 /* Perform resume */ 241 for (int i = 0; i < ndevs; i++) { 242 device_t child = devs[i]; 243 244 /* Terminate on first error */ 245 if ((error = BUS_RESUME_CHILD(device_get_parent(child), child))) 246 goto cleanup; 247 } 248 249 cleanup: 250 bhnd_bus_free_children(devs); 251 return (error); 252 } 253 254 /** 255 * Default bhnd(4) bus driver implementation of DEVICE_SUSPEND(). 256 * 257 * This implementation calls BUS_SUSPEND_CHILD() for each of the device's 258 * children in reverse bhnd probe order. If any call to BUS_SUSPEND_CHILD() 259 * fails, the suspend operation is terminated and any devices that were 260 * suspended are resumed immediately by calling their BUS_RESUME_CHILD() 261 * methods. 262 */ 263 int 264 bhnd_generic_suspend(device_t dev) 265 { 266 device_t *devs; 267 int ndevs; 268 int error; 269 270 if (!device_is_attached(dev)) 271 return (EBUSY); 272 273 /* Fetch children in detach order */ 274 error = bhnd_bus_get_children(dev, &devs, &ndevs, 275 BHND_DEVICE_ORDER_DETACH); 276 if (error) 277 return (error); 278 279 /* Perform suspend */ 280 for (int i = 0; i < ndevs; i++) { 281 device_t child = devs[i]; 282 error = BUS_SUSPEND_CHILD(device_get_parent(child), child); 283 284 /* On error, resume suspended devices and then terminate */ 285 if (error) { 286 for (int j = 0; j < i; j++) { 287 BUS_RESUME_CHILD(device_get_parent(devs[j]), 288 devs[j]); 289 } 290 291 goto cleanup; 292 } 293 } 294 295 cleanup: 296 bhnd_bus_free_children(devs); 297 return (error); 298 } 299 300 /** 301 * Default bhnd(4) bus driver implementation of BHND_BUS_GET_PROBE_ORDER(). 302 * 303 * This implementation determines probe ordering based on the device's class 304 * and other properties, including whether the device is serving as a host 305 * bridge. 306 */ 307 int 308 bhnd_generic_get_probe_order(device_t dev, device_t child) 309 { 310 switch (bhnd_get_class(child)) { 311 case BHND_DEVCLASS_CC: 312 /* Must be early enough to provide NVRAM access to the 313 * host bridge */ 314 return (BHND_PROBE_ROOT + BHND_PROBE_ORDER_FIRST); 315 316 case BHND_DEVCLASS_CC_B: 317 /* fall through */ 318 case BHND_DEVCLASS_PMU: 319 return (BHND_PROBE_BUS + BHND_PROBE_ORDER_EARLY); 320 321 case BHND_DEVCLASS_SOC_ROUTER: 322 return (BHND_PROBE_BUS + BHND_PROBE_ORDER_LATE); 323 324 case BHND_DEVCLASS_SOC_BRIDGE: 325 return (BHND_PROBE_BUS + BHND_PROBE_ORDER_LAST); 326 327 case BHND_DEVCLASS_CPU: 328 return (BHND_PROBE_CPU + BHND_PROBE_ORDER_FIRST); 329 330 case BHND_DEVCLASS_RAM: 331 /* fall through */ 332 case BHND_DEVCLASS_MEMC: 333 return (BHND_PROBE_CPU + BHND_PROBE_ORDER_EARLY); 334 335 case BHND_DEVCLASS_NVRAM: 336 return (BHND_PROBE_RESOURCE + BHND_PROBE_ORDER_EARLY); 337 338 case BHND_DEVCLASS_PCI: 339 case BHND_DEVCLASS_PCIE: 340 case BHND_DEVCLASS_PCCARD: 341 case BHND_DEVCLASS_ENET: 342 case BHND_DEVCLASS_ENET_MAC: 343 case BHND_DEVCLASS_ENET_PHY: 344 case BHND_DEVCLASS_WLAN: 345 case BHND_DEVCLASS_WLAN_MAC: 346 case BHND_DEVCLASS_WLAN_PHY: 347 case BHND_DEVCLASS_EROM: 348 case BHND_DEVCLASS_OTHER: 349 case BHND_DEVCLASS_INVALID: 350 if (bhnd_bus_find_hostb_device(dev) == child) 351 return (BHND_PROBE_ROOT + BHND_PROBE_ORDER_EARLY); 352 353 return (BHND_PROBE_DEFAULT); 354 default: 355 return (BHND_PROBE_DEFAULT); 356 } 357 } 358 359 /** 360 * Default bhnd(4) bus driver implementation of BHND_BUS_ALLOC_PMU(). 361 */ 362 int 363 bhnd_generic_alloc_pmu(device_t dev, device_t child) 364 { 365 struct bhnd_softc *sc; 366 struct bhnd_resource *r; 367 struct bhnd_core_clkctl *clkctl; 368 struct resource_list *rl; 369 struct resource_list_entry *rle; 370 device_t pmu_dev; 371 bhnd_addr_t r_addr; 372 bhnd_size_t r_size; 373 bus_size_t pmu_regs; 374 u_int max_latency; 375 int error; 376 377 bus_topo_assert(); 378 379 if (device_get_parent(child) != dev) 380 return (EINVAL); 381 382 sc = device_get_softc(dev); 383 clkctl = bhnd_get_pmu_info(child); 384 pmu_regs = BHND_CLK_CTL_ST; 385 386 /* already allocated? */ 387 if (clkctl != NULL) { 388 panic("duplicate PMU allocation for %s", 389 device_get_nameunit(child)); 390 } 391 392 /* Determine address+size of the core's PMU register block */ 393 error = bhnd_get_region_addr(child, BHND_PORT_DEVICE, 0, 0, &r_addr, 394 &r_size); 395 if (error) { 396 device_printf(sc->dev, "error fetching register block info for " 397 "%s: %d\n", device_get_nameunit(child), error); 398 return (error); 399 } 400 401 if (r_size < (pmu_regs + sizeof(uint32_t))) { 402 device_printf(sc->dev, "pmu offset %#jx would overrun %s " 403 "register block\n", (uintmax_t)pmu_regs, 404 device_get_nameunit(child)); 405 return (ENODEV); 406 } 407 408 /* Locate actual resource containing the core's register block */ 409 if ((rl = BUS_GET_RESOURCE_LIST(dev, child)) == NULL) { 410 device_printf(dev, "NULL resource list returned for %s\n", 411 device_get_nameunit(child)); 412 return (ENXIO); 413 } 414 415 if ((rle = resource_list_find(rl, SYS_RES_MEMORY, 0)) == NULL) { 416 device_printf(dev, "cannot locate core register resource " 417 "for %s\n", device_get_nameunit(child)); 418 return (ENXIO); 419 } 420 421 if (rle->res == NULL) { 422 device_printf(dev, "core register resource unallocated for " 423 "%s\n", device_get_nameunit(child)); 424 return (ENXIO); 425 } 426 427 if (r_addr+pmu_regs < rman_get_start(rle->res) || 428 r_addr+pmu_regs >= rman_get_end(rle->res)) 429 { 430 device_printf(dev, "core register resource does not map PMU " 431 "registers at %#jx\n for %s\n", r_addr+pmu_regs, 432 device_get_nameunit(child)); 433 return (ENXIO); 434 } 435 436 /* Adjust PMU register offset relative to the actual start address 437 * of the core's register block allocation. 438 * 439 * XXX: The saved offset will be invalid if bus_adjust_resource is 440 * used to modify the resource's start address. 441 */ 442 if (rman_get_start(rle->res) > r_addr) 443 pmu_regs -= rman_get_start(rle->res) - r_addr; 444 else 445 pmu_regs -= r_addr - rman_get_start(rle->res); 446 447 /* Retain a PMU reference for the clkctl instance state */ 448 pmu_dev = bhnd_retain_provider(child, BHND_SERVICE_PMU); 449 if (pmu_dev == NULL) { 450 device_printf(sc->dev, "PMU not found\n"); 451 return (ENXIO); 452 } 453 454 /* Fetch the maximum transition latency from our PMU */ 455 max_latency = bhnd_pmu_get_max_transition_latency(pmu_dev); 456 457 /* Allocate a new bhnd_resource wrapping the standard resource we 458 * fetched from the resource list; we'll free this in 459 * bhnd_generic_release_pmu() */ 460 r = malloc(sizeof(struct bhnd_resource), M_BHND, M_NOWAIT); 461 if (r == NULL) { 462 bhnd_release_provider(child, pmu_dev, BHND_SERVICE_PMU); 463 return (ENOMEM); 464 } 465 466 r->res = rle->res; 467 r->direct = ((rman_get_flags(rle->res) & RF_ACTIVE) != 0); 468 469 /* Allocate the clkctl instance */ 470 clkctl = bhnd_alloc_core_clkctl(child, pmu_dev, r, pmu_regs, 471 max_latency); 472 if (clkctl == NULL) { 473 free(r, M_BHND); 474 bhnd_release_provider(child, pmu_dev, BHND_SERVICE_PMU); 475 return (ENOMEM); 476 } 477 478 bhnd_set_pmu_info(child, clkctl); 479 return (0); 480 } 481 482 /** 483 * Default bhnd(4) bus driver implementation of BHND_BUS_RELEASE_PMU(). 484 */ 485 int 486 bhnd_generic_release_pmu(device_t dev, device_t child) 487 { 488 struct bhnd_core_clkctl *clkctl; 489 struct bhnd_resource *r; 490 device_t pmu_dev; 491 492 bus_topo_assert(); 493 494 if (device_get_parent(child) != dev) 495 return (EINVAL); 496 497 clkctl = bhnd_get_pmu_info(child); 498 if (clkctl == NULL) 499 panic("pmu over-release for %s", device_get_nameunit(child)); 500 501 /* Clear all FORCE, AREQ, and ERSRC flags, unless we're already in 502 * RESET. Suspending a core clears clkctl automatically (and attempting 503 * to access the PMU registers in a suspended core will trigger a 504 * system livelock). */ 505 if (!bhnd_is_hw_suspended(clkctl->cc_dev)) { 506 BHND_CLKCTL_LOCK(clkctl); 507 508 /* Clear all FORCE, AREQ, and ERSRC flags */ 509 BHND_CLKCTL_SET_4(clkctl, 0x0, BHND_CCS_FORCE_MASK | 510 BHND_CCS_AREQ_MASK | BHND_CCS_ERSRC_REQ_MASK); 511 512 BHND_CLKCTL_UNLOCK(clkctl); 513 } 514 515 /* Clear child's PMU info reference */ 516 bhnd_set_pmu_info(child, NULL); 517 518 /* Before freeing the clkctl instance, save a pointer to resources we 519 * need to clean up manually */ 520 r = clkctl->cc_res; 521 pmu_dev = clkctl->cc_pmu_dev; 522 523 /* Free the clkctl instance */ 524 bhnd_free_core_clkctl(clkctl); 525 526 /* Free the child's bhnd resource wrapper */ 527 free(r, M_BHND); 528 529 /* Release the child's PMU provider reference */ 530 bhnd_release_provider(child, pmu_dev, BHND_SERVICE_PMU); 531 532 return (0); 533 } 534 535 /** 536 * Default bhnd(4) bus driver implementation of BHND_BUS_GET_CLOCK_LATENCY(). 537 */ 538 int 539 bhnd_generic_get_clock_latency(device_t dev, device_t child, bhnd_clock clock, 540 u_int *latency) 541 { 542 struct bhnd_core_clkctl *clkctl; 543 544 if (device_get_parent(child) != dev) 545 return (EINVAL); 546 547 if ((clkctl = bhnd_get_pmu_info(child)) == NULL) 548 panic("no active PMU allocation"); 549 550 return (bhnd_pmu_get_clock_latency(clkctl->cc_pmu_dev, clock, latency)); 551 } 552 553 /** 554 * Default bhnd(4) bus driver implementation of BHND_BUS_GET_CLOCK_FREQ(). 555 */ 556 int 557 bhnd_generic_get_clock_freq(device_t dev, device_t child, bhnd_clock clock, 558 u_int *freq) 559 { 560 struct bhnd_core_clkctl *clkctl; 561 562 if (device_get_parent(child) != dev) 563 return (EINVAL); 564 565 if ((clkctl = bhnd_get_pmu_info(child)) == NULL) 566 panic("no active PMU allocation"); 567 568 return (bhnd_pmu_get_clock_freq(clkctl->cc_pmu_dev, clock, freq)); 569 } 570 571 /** 572 * Default bhnd(4) bus driver implementation of BHND_BUS_REQUEST_CLOCK(). 573 */ 574 int 575 bhnd_generic_request_clock(device_t dev, device_t child, bhnd_clock clock) 576 { 577 struct bhnd_core_clkctl *clkctl; 578 uint32_t avail; 579 uint32_t req; 580 int error; 581 582 if (device_get_parent(child) != dev) 583 return (EINVAL); 584 585 if ((clkctl = bhnd_get_pmu_info(child)) == NULL) 586 panic("no active PMU allocation"); 587 588 BHND_ASSERT_CLKCTL_AVAIL(clkctl); 589 590 avail = 0x0; 591 req = 0x0; 592 593 switch (clock) { 594 case BHND_CLOCK_DYN: 595 break; 596 case BHND_CLOCK_ILP: 597 req |= BHND_CCS_FORCEILP; 598 break; 599 case BHND_CLOCK_ALP: 600 req |= BHND_CCS_FORCEALP; 601 avail |= BHND_CCS_ALPAVAIL; 602 break; 603 case BHND_CLOCK_HT: 604 req |= BHND_CCS_FORCEHT; 605 avail |= BHND_CCS_HTAVAIL; 606 break; 607 default: 608 device_printf(dev, "%s requested unknown clock: %#x\n", 609 device_get_nameunit(clkctl->cc_dev), clock); 610 return (ENODEV); 611 } 612 613 BHND_CLKCTL_LOCK(clkctl); 614 615 /* Issue request */ 616 BHND_CLKCTL_SET_4(clkctl, req, BHND_CCS_FORCE_MASK); 617 618 /* Wait for clock availability */ 619 error = bhnd_core_clkctl_wait(clkctl, avail, avail); 620 621 BHND_CLKCTL_UNLOCK(clkctl); 622 623 return (error); 624 } 625 626 /** 627 * Default bhnd(4) bus driver implementation of BHND_BUS_ENABLE_CLOCKS(). 628 */ 629 int 630 bhnd_generic_enable_clocks(device_t dev, device_t child, uint32_t clocks) 631 { 632 struct bhnd_core_clkctl *clkctl; 633 uint32_t avail; 634 uint32_t req; 635 int error; 636 637 if (device_get_parent(child) != dev) 638 return (EINVAL); 639 640 if ((clkctl = bhnd_get_pmu_info(child)) == NULL) 641 panic("no active PMU allocation"); 642 643 BHND_ASSERT_CLKCTL_AVAIL(clkctl); 644 645 avail = 0x0; 646 req = 0x0; 647 648 /* Build clock request flags */ 649 if (clocks & BHND_CLOCK_DYN) /* nothing to enable */ 650 clocks &= ~BHND_CLOCK_DYN; 651 652 if (clocks & BHND_CLOCK_ILP) /* nothing to enable */ 653 clocks &= ~BHND_CLOCK_ILP; 654 655 if (clocks & BHND_CLOCK_ALP) { 656 req |= BHND_CCS_ALPAREQ; 657 avail |= BHND_CCS_ALPAVAIL; 658 clocks &= ~BHND_CLOCK_ALP; 659 } 660 661 if (clocks & BHND_CLOCK_HT) { 662 req |= BHND_CCS_HTAREQ; 663 avail |= BHND_CCS_HTAVAIL; 664 clocks &= ~BHND_CLOCK_HT; 665 } 666 667 /* Check for unknown clock values */ 668 if (clocks != 0x0) { 669 device_printf(dev, "%s requested unknown clocks: %#x\n", 670 device_get_nameunit(clkctl->cc_dev), clocks); 671 return (ENODEV); 672 } 673 674 BHND_CLKCTL_LOCK(clkctl); 675 676 /* Issue request */ 677 BHND_CLKCTL_SET_4(clkctl, req, BHND_CCS_AREQ_MASK); 678 679 /* Wait for clock availability */ 680 error = bhnd_core_clkctl_wait(clkctl, avail, avail); 681 682 BHND_CLKCTL_UNLOCK(clkctl); 683 684 return (error); 685 } 686 687 /** 688 * Default bhnd(4) bus driver implementation of BHND_BUS_REQUEST_EXT_RSRC(). 689 */ 690 int 691 bhnd_generic_request_ext_rsrc(device_t dev, device_t child, u_int rsrc) 692 { 693 struct bhnd_core_clkctl *clkctl; 694 uint32_t req; 695 uint32_t avail; 696 int error; 697 698 if (device_get_parent(child) != dev) 699 return (EINVAL); 700 701 if ((clkctl = bhnd_get_pmu_info(child)) == NULL) 702 panic("no active PMU allocation"); 703 704 BHND_ASSERT_CLKCTL_AVAIL(clkctl); 705 706 if (rsrc > BHND_CCS_ERSRC_MAX) 707 return (EINVAL); 708 709 req = BHND_CCS_SET_BITS((1<<rsrc), BHND_CCS_ERSRC_REQ); 710 avail = BHND_CCS_SET_BITS((1<<rsrc), BHND_CCS_ERSRC_STS); 711 712 BHND_CLKCTL_LOCK(clkctl); 713 714 /* Write request */ 715 BHND_CLKCTL_SET_4(clkctl, req, req); 716 717 /* Wait for resource availability */ 718 error = bhnd_core_clkctl_wait(clkctl, avail, avail); 719 720 BHND_CLKCTL_UNLOCK(clkctl); 721 722 return (error); 723 } 724 725 /** 726 * Default bhnd(4) bus driver implementation of BHND_BUS_RELEASE_EXT_RSRC(). 727 */ 728 int 729 bhnd_generic_release_ext_rsrc(device_t dev, device_t child, u_int rsrc) 730 { 731 struct bhnd_core_clkctl *clkctl; 732 uint32_t mask; 733 734 if (device_get_parent(child) != dev) 735 return (EINVAL); 736 737 if ((clkctl = bhnd_get_pmu_info(child)) == NULL) 738 panic("no active PMU allocation"); 739 740 BHND_ASSERT_CLKCTL_AVAIL(clkctl); 741 742 if (rsrc > BHND_CCS_ERSRC_MAX) 743 return (EINVAL); 744 745 mask = BHND_CCS_SET_BITS((1<<rsrc), BHND_CCS_ERSRC_REQ); 746 747 /* Clear request */ 748 BHND_CLKCTL_LOCK(clkctl); 749 BHND_CLKCTL_SET_4(clkctl, 0x0, mask); 750 BHND_CLKCTL_UNLOCK(clkctl); 751 752 return (0); 753 } 754 755 /** 756 * Default bhnd(4) bus driver implementation of BHND_BUS_IS_REGION_VALID(). 757 * 758 * This implementation assumes that port and region numbers are 0-indexed and 759 * are allocated non-sparsely, using BHND_BUS_GET_PORT_COUNT() and 760 * BHND_BUS_GET_REGION_COUNT() to determine if @p port and @p region fall 761 * within the defined range. 762 */ 763 static bool 764 bhnd_generic_is_region_valid(device_t dev, device_t child, 765 bhnd_port_type type, u_int port, u_int region) 766 { 767 if (port >= bhnd_get_port_count(child, type)) 768 return (false); 769 770 if (region >= bhnd_get_region_count(child, type, port)) 771 return (false); 772 773 return (true); 774 } 775 776 /** 777 * Default bhnd(4) bus driver implementation of BHND_BUS_GET_NVRAM_VAR(). 778 * 779 * This implementation searches @p dev for a registered NVRAM child device. 780 * 781 * If no NVRAM device is registered with @p dev, the request is delegated to 782 * the BHND_BUS_GET_NVRAM_VAR() method on the parent of @p dev. 783 */ 784 int 785 bhnd_generic_get_nvram_var(device_t dev, device_t child, const char *name, 786 void *buf, size_t *size, bhnd_nvram_type type) 787 { 788 device_t nvram, parent; 789 int error; 790 791 /* If a NVRAM device is available, consult it first */ 792 nvram = bhnd_retain_provider(child, BHND_SERVICE_NVRAM); 793 if (nvram != NULL) { 794 error = BHND_NVRAM_GETVAR(nvram, name, buf, size, type); 795 bhnd_release_provider(child, nvram, BHND_SERVICE_NVRAM); 796 return (error); 797 } 798 799 /* Otherwise, try to delegate to parent */ 800 if ((parent = device_get_parent(dev)) == NULL) 801 return (ENODEV); 802 803 return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), child, 804 name, buf, size, type)); 805 } 806 807 /** 808 * Default bhnd(4) bus driver implementation of BUS_PRINT_CHILD(). 809 * 810 * This implementation requests the device's struct resource_list via 811 * BUS_GET_RESOURCE_LIST. 812 */ 813 int 814 bhnd_generic_print_child(device_t dev, device_t child) 815 { 816 struct resource_list *rl; 817 int retval = 0; 818 819 retval += bus_print_child_header(dev, child); 820 821 rl = BUS_GET_RESOURCE_LIST(dev, child); 822 823 if (rl != NULL) { 824 retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, 825 "%#jx"); 826 827 retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, 828 "%#jd"); 829 } 830 831 retval += printf(" at core %u", bhnd_get_core_index(child)); 832 833 retval += bus_print_child_domain(dev, child); 834 retval += bus_print_child_footer(dev, child); 835 836 return (retval); 837 } 838 839 /** 840 * Default bhnd(4) bus driver implementation of BUS_PROBE_NOMATCH(). 841 * 842 * This implementation requests the device's struct resource_list via 843 * BUS_GET_RESOURCE_LIST. 844 */ 845 void 846 bhnd_generic_probe_nomatch(device_t dev, device_t child) 847 { 848 struct resource_list *rl; 849 const struct bhnd_nomatch *nm; 850 bool report; 851 852 /* Fetch reporting configuration for this device */ 853 report = true; 854 for (nm = bhnd_nomatch_table; nm->device != BHND_COREID_INVALID; nm++) { 855 if (nm->vendor != bhnd_get_vendor(child)) 856 continue; 857 858 if (nm->device != bhnd_get_device(child)) 859 continue; 860 861 report = false; 862 if (bootverbose && nm->if_verbose) 863 report = true; 864 break; 865 } 866 867 if (!report) 868 return; 869 870 /* Print the non-matched device info */ 871 device_printf(dev, "<%s %s, rev %hhu>", bhnd_get_vendor_name(child), 872 bhnd_get_device_name(child), bhnd_get_hwrev(child)); 873 874 rl = BUS_GET_RESOURCE_LIST(dev, child); 875 if (rl != NULL) { 876 resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx"); 877 resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%#jd"); 878 } 879 880 printf(" at core %u (no driver attached)\n", 881 bhnd_get_core_index(child)); 882 } 883 884 static int 885 bhnd_child_pnpinfo(device_t dev, device_t child, struct sbuf *sb) 886 { 887 if (device_get_parent(child) != dev) 888 return (BUS_CHILD_PNPINFO(device_get_parent(dev), child, sb)); 889 890 sbuf_printf(sb, "vendor=0x%hx device=0x%hx rev=0x%hhx", 891 bhnd_get_vendor(child), bhnd_get_device(child), 892 bhnd_get_hwrev(child)); 893 894 return (0); 895 } 896 897 static int 898 bhnd_child_location(device_t dev, device_t child, struct sbuf *sb) 899 { 900 bhnd_addr_t addr; 901 bhnd_size_t size; 902 903 if (device_get_parent(child) != dev) 904 return (BUS_CHILD_LOCATION(device_get_parent(dev), child, sb)); 905 906 if (bhnd_get_region_addr(child, BHND_PORT_DEVICE, 0, 0, &addr, &size)) 907 return (0); 908 909 sbuf_printf(sb, "port0.0=0x%llx", (unsigned long long) addr); 910 return (0); 911 } 912 913 /** 914 * Default bhnd(4) bus driver implementation of BUS_CHILD_DELETED(). 915 * 916 * This implementation manages internal bhnd(4) state, and must be called 917 * by subclassing drivers. 918 */ 919 void 920 bhnd_generic_child_deleted(device_t dev, device_t child) 921 { 922 923 /* Free device info */ 924 if (bhnd_get_pmu_info(child) != NULL) { 925 /* Releasing PMU requests automatically would be nice, 926 * but we can't reference per-core PMU register 927 * resource after driver detach */ 928 panic("%s leaked device pmu state\n", 929 device_get_nameunit(child)); 930 } 931 } 932 933 /** 934 * Helper function for implementing BUS_SUSPEND_CHILD(). 935 * 936 * TODO: Power management 937 * 938 * If @p child is not a direct child of @p dev, suspension is delegated to 939 * the @p dev parent. 940 */ 941 int 942 bhnd_generic_suspend_child(device_t dev, device_t child) 943 { 944 if (device_get_parent(child) != dev) 945 BUS_SUSPEND_CHILD(device_get_parent(dev), child); 946 947 return bus_generic_suspend_child(dev, child); 948 } 949 950 /** 951 * Helper function for implementing BUS_RESUME_CHILD(). 952 * 953 * TODO: Power management 954 * 955 * If @p child is not a direct child of @p dev, suspension is delegated to 956 * the @p dev parent. 957 */ 958 int 959 bhnd_generic_resume_child(device_t dev, device_t child) 960 { 961 if (device_get_parent(child) != dev) 962 BUS_RESUME_CHILD(device_get_parent(dev), child); 963 964 return bus_generic_resume_child(dev, child); 965 } 966 967 /** 968 * Default bhnd(4) bus driver implementation of BUS_SETUP_INTR(). 969 * 970 * This implementation of BUS_SETUP_INTR() will delegate interrupt setup 971 * to the parent of @p dev, if any. 972 */ 973 int 974 bhnd_generic_setup_intr(device_t dev, device_t child, struct resource *irq, 975 int flags, driver_filter_t *filter, driver_intr_t *intr, void *arg, 976 void **cookiep) 977 { 978 return (bus_generic_setup_intr(dev, child, irq, flags, filter, intr, 979 arg, cookiep)); 980 } 981 982 /* 983 * Delegate all indirect I/O to the parent device. When inherited by 984 * non-bridged bus implementations, resources will never be marked as 985 * indirect, and these methods will never be called. 986 */ 987 #define BHND_IO_READ(_type, _name, _method) \ 988 static _type \ 989 bhnd_read_ ## _name (device_t dev, device_t child, \ 990 struct bhnd_resource *r, bus_size_t offset) \ 991 { \ 992 return (BHND_BUS_READ_ ## _method( \ 993 device_get_parent(dev), child, r, offset)); \ 994 } 995 996 #define BHND_IO_WRITE(_type, _name, _method) \ 997 static void \ 998 bhnd_write_ ## _name (device_t dev, device_t child, \ 999 struct bhnd_resource *r, bus_size_t offset, _type value) \ 1000 { \ 1001 return (BHND_BUS_WRITE_ ## _method( \ 1002 device_get_parent(dev), child, r, offset, \ 1003 value)); \ 1004 } 1005 1006 #define BHND_IO_MISC(_type, _op, _method) \ 1007 static void \ 1008 bhnd_ ## _op (device_t dev, device_t child, \ 1009 struct bhnd_resource *r, bus_size_t offset, _type datap, \ 1010 bus_size_t count) \ 1011 { \ 1012 BHND_BUS_ ## _method(device_get_parent(dev), child, r, \ 1013 offset, datap, count); \ 1014 } 1015 1016 #define BHND_IO_METHODS(_type, _size) \ 1017 BHND_IO_READ(_type, _size, _size) \ 1018 BHND_IO_WRITE(_type, _size, _size) \ 1019 \ 1020 BHND_IO_READ(_type, stream_ ## _size, STREAM_ ## _size) \ 1021 BHND_IO_WRITE(_type, stream_ ## _size, STREAM_ ## _size) \ 1022 \ 1023 BHND_IO_MISC(_type*, read_multi_ ## _size, \ 1024 READ_MULTI_ ## _size) \ 1025 BHND_IO_MISC(_type*, write_multi_ ## _size, \ 1026 WRITE_MULTI_ ## _size) \ 1027 \ 1028 BHND_IO_MISC(_type*, read_multi_stream_ ## _size, \ 1029 READ_MULTI_STREAM_ ## _size) \ 1030 BHND_IO_MISC(_type*, write_multi_stream_ ## _size, \ 1031 WRITE_MULTI_STREAM_ ## _size) \ 1032 \ 1033 BHND_IO_MISC(_type, set_multi_ ## _size, SET_MULTI_ ## _size) \ 1034 BHND_IO_MISC(_type, set_region_ ## _size, SET_REGION_ ## _size) \ 1035 \ 1036 BHND_IO_MISC(_type*, read_region_ ## _size, \ 1037 READ_REGION_ ## _size) \ 1038 BHND_IO_MISC(_type*, write_region_ ## _size, \ 1039 WRITE_REGION_ ## _size) \ 1040 \ 1041 BHND_IO_MISC(_type*, read_region_stream_ ## _size, \ 1042 READ_REGION_STREAM_ ## _size) \ 1043 BHND_IO_MISC(_type*, write_region_stream_ ## _size, \ 1044 WRITE_REGION_STREAM_ ## _size) \ 1045 1046 BHND_IO_METHODS(uint8_t, 1); 1047 BHND_IO_METHODS(uint16_t, 2); 1048 BHND_IO_METHODS(uint32_t, 4); 1049 1050 static void 1051 bhnd_barrier(device_t dev, device_t child, struct bhnd_resource *r, 1052 bus_size_t offset, bus_size_t length, int flags) 1053 { 1054 BHND_BUS_BARRIER(device_get_parent(dev), child, r, offset, length, 1055 flags); 1056 } 1057 1058 static device_method_t bhnd_methods[] = { 1059 /* Device interface */ \ 1060 DEVMETHOD(device_attach, bhnd_generic_attach), 1061 DEVMETHOD(device_detach, bhnd_generic_detach), 1062 DEVMETHOD(device_shutdown, bhnd_generic_shutdown), 1063 DEVMETHOD(device_suspend, bhnd_generic_suspend), 1064 DEVMETHOD(device_resume, bhnd_generic_resume), 1065 1066 /* Bus interface */ 1067 DEVMETHOD(bus_child_deleted, bhnd_generic_child_deleted), 1068 DEVMETHOD(bus_probe_nomatch, bhnd_generic_probe_nomatch), 1069 DEVMETHOD(bus_print_child, bhnd_generic_print_child), 1070 DEVMETHOD(bus_child_pnpinfo, bhnd_child_pnpinfo), 1071 DEVMETHOD(bus_child_location, bhnd_child_location), 1072 1073 DEVMETHOD(bus_suspend_child, bhnd_generic_suspend_child), 1074 DEVMETHOD(bus_resume_child, bhnd_generic_resume_child), 1075 1076 DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource), 1077 DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), 1078 DEVMETHOD(bus_delete_resource, bus_generic_rl_delete_resource), 1079 DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource), 1080 DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource), 1081 DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource), 1082 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 1083 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 1084 1085 DEVMETHOD(bus_setup_intr, bhnd_generic_setup_intr), 1086 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 1087 DEVMETHOD(bus_config_intr, bus_generic_config_intr), 1088 DEVMETHOD(bus_bind_intr, bus_generic_bind_intr), 1089 DEVMETHOD(bus_describe_intr, bus_generic_describe_intr), 1090 1091 DEVMETHOD(bus_get_dma_tag, bus_generic_get_dma_tag), 1092 1093 /* BHND interface */ 1094 DEVMETHOD(bhnd_bus_get_chipid, bhnd_bus_generic_get_chipid), 1095 DEVMETHOD(bhnd_bus_is_hw_disabled, bhnd_bus_generic_is_hw_disabled), 1096 1097 DEVMETHOD(bhnd_bus_get_probe_order, bhnd_generic_get_probe_order), 1098 1099 DEVMETHOD(bhnd_bus_alloc_pmu, bhnd_generic_alloc_pmu), 1100 DEVMETHOD(bhnd_bus_release_pmu, bhnd_generic_release_pmu), 1101 DEVMETHOD(bhnd_bus_request_clock, bhnd_generic_request_clock), 1102 DEVMETHOD(bhnd_bus_enable_clocks, bhnd_generic_enable_clocks), 1103 DEVMETHOD(bhnd_bus_request_ext_rsrc, bhnd_generic_request_ext_rsrc), 1104 DEVMETHOD(bhnd_bus_release_ext_rsrc, bhnd_generic_release_ext_rsrc), 1105 DEVMETHOD(bhnd_bus_get_clock_latency, bhnd_generic_get_clock_latency), 1106 DEVMETHOD(bhnd_bus_get_clock_freq, bhnd_generic_get_clock_freq), 1107 1108 DEVMETHOD(bhnd_bus_is_region_valid, bhnd_generic_is_region_valid), 1109 DEVMETHOD(bhnd_bus_get_nvram_var, bhnd_generic_get_nvram_var), 1110 1111 /* BHND interface (bus I/O) */ 1112 DEVMETHOD(bhnd_bus_read_1, bhnd_read_1), 1113 DEVMETHOD(bhnd_bus_read_2, bhnd_read_2), 1114 DEVMETHOD(bhnd_bus_read_4, bhnd_read_4), 1115 DEVMETHOD(bhnd_bus_write_1, bhnd_write_1), 1116 DEVMETHOD(bhnd_bus_write_2, bhnd_write_2), 1117 DEVMETHOD(bhnd_bus_write_4, bhnd_write_4), 1118 1119 DEVMETHOD(bhnd_bus_read_stream_1, bhnd_read_stream_1), 1120 DEVMETHOD(bhnd_bus_read_stream_2, bhnd_read_stream_2), 1121 DEVMETHOD(bhnd_bus_read_stream_4, bhnd_read_stream_4), 1122 DEVMETHOD(bhnd_bus_write_stream_1, bhnd_write_stream_1), 1123 DEVMETHOD(bhnd_bus_write_stream_2, bhnd_write_stream_2), 1124 DEVMETHOD(bhnd_bus_write_stream_4, bhnd_write_stream_4), 1125 1126 DEVMETHOD(bhnd_bus_read_multi_1, bhnd_read_multi_1), 1127 DEVMETHOD(bhnd_bus_read_multi_2, bhnd_read_multi_2), 1128 DEVMETHOD(bhnd_bus_read_multi_4, bhnd_read_multi_4), 1129 DEVMETHOD(bhnd_bus_write_multi_1, bhnd_write_multi_1), 1130 DEVMETHOD(bhnd_bus_write_multi_2, bhnd_write_multi_2), 1131 DEVMETHOD(bhnd_bus_write_multi_4, bhnd_write_multi_4), 1132 1133 DEVMETHOD(bhnd_bus_read_multi_stream_1, bhnd_read_multi_stream_1), 1134 DEVMETHOD(bhnd_bus_read_multi_stream_2, bhnd_read_multi_stream_2), 1135 DEVMETHOD(bhnd_bus_read_multi_stream_4, bhnd_read_multi_stream_4), 1136 DEVMETHOD(bhnd_bus_write_multi_stream_1,bhnd_write_multi_stream_1), 1137 DEVMETHOD(bhnd_bus_write_multi_stream_2,bhnd_write_multi_stream_2), 1138 DEVMETHOD(bhnd_bus_write_multi_stream_4,bhnd_write_multi_stream_4), 1139 1140 DEVMETHOD(bhnd_bus_set_multi_1, bhnd_set_multi_1), 1141 DEVMETHOD(bhnd_bus_set_multi_2, bhnd_set_multi_2), 1142 DEVMETHOD(bhnd_bus_set_multi_4, bhnd_set_multi_4), 1143 1144 DEVMETHOD(bhnd_bus_set_region_1, bhnd_set_region_1), 1145 DEVMETHOD(bhnd_bus_set_region_2, bhnd_set_region_2), 1146 DEVMETHOD(bhnd_bus_set_region_4, bhnd_set_region_4), 1147 1148 DEVMETHOD(bhnd_bus_read_region_1, bhnd_read_region_1), 1149 DEVMETHOD(bhnd_bus_read_region_2, bhnd_read_region_2), 1150 DEVMETHOD(bhnd_bus_read_region_4, bhnd_read_region_4), 1151 DEVMETHOD(bhnd_bus_write_region_1, bhnd_write_region_1), 1152 DEVMETHOD(bhnd_bus_write_region_2, bhnd_write_region_2), 1153 DEVMETHOD(bhnd_bus_write_region_4, bhnd_write_region_4), 1154 1155 DEVMETHOD(bhnd_bus_read_region_stream_1,bhnd_read_region_stream_1), 1156 DEVMETHOD(bhnd_bus_read_region_stream_2,bhnd_read_region_stream_2), 1157 DEVMETHOD(bhnd_bus_read_region_stream_4,bhnd_read_region_stream_4), 1158 DEVMETHOD(bhnd_bus_write_region_stream_1, bhnd_write_region_stream_1), 1159 DEVMETHOD(bhnd_bus_write_region_stream_2, bhnd_write_region_stream_2), 1160 DEVMETHOD(bhnd_bus_write_region_stream_4, bhnd_write_region_stream_4), 1161 1162 DEVMETHOD(bhnd_bus_barrier, bhnd_barrier), 1163 1164 DEVMETHOD_END 1165 }; 1166 1167 DEFINE_CLASS_0(bhnd, bhnd_driver, bhnd_methods, sizeof(struct bhnd_softc)); 1168 MODULE_VERSION(bhnd, 1); 1169