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