1 /*- 2 * Copyright (c) 2015 Landon Fuller <landon@landonf.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer, 10 * without modification. 11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13 * redistribution must be conditioned upon including a substantially 14 * similar Disclaimer requirement for further binary redistribution. 15 * 16 * NO WARRANTY 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 * THE POSSIBILITY OF SUCH DAMAGES. 28 */ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 #include <sys/param.h> 34 #include <sys/bus.h> 35 #include <sys/kernel.h> 36 #include <sys/malloc.h> 37 #include <sys/module.h> 38 #include <sys/systm.h> 39 40 #include <machine/bus.h> 41 42 #include <dev/bhnd/cores/chipc/chipcreg.h> 43 44 #include "sibareg.h" 45 #include "sibavar.h" 46 47 int 48 siba_probe(device_t dev) 49 { 50 device_set_desc(dev, "SIBA BHND bus"); 51 return (BUS_PROBE_DEFAULT); 52 } 53 54 int 55 siba_attach(device_t dev) 56 { 57 struct siba_devinfo *dinfo; 58 struct siba_softc *sc; 59 device_t *devs; 60 int ndevs; 61 int error; 62 63 sc = device_get_softc(dev); 64 sc->dev = dev; 65 66 /* Fetch references to the siba SIBA_CFG* blocks for all 67 * registered devices */ 68 if ((error = device_get_children(dev, &devs, &ndevs))) 69 return (error); 70 71 for (int i = 0; i < ndevs; i++) { 72 struct siba_addrspace *addrspace; 73 struct siba_port *port; 74 75 dinfo = device_get_ivars(devs[i]); 76 77 KASSERT(!device_is_suspended(devs[i]), 78 ("siba(4) stateful suspend handling requires that devices " 79 "not be suspended before siba_attach()")); 80 81 /* Fetch the core register address space */ 82 port = siba_dinfo_get_port(dinfo, BHND_PORT_DEVICE, 0); 83 if (port == NULL) { 84 error = ENXIO; 85 goto cleanup; 86 } 87 88 addrspace = siba_find_port_addrspace(port, SIBA_ADDRSPACE_CORE); 89 if (addrspace == NULL) { 90 error = ENXIO; 91 goto cleanup; 92 } 93 94 /* 95 * Map the per-core configuration blocks 96 */ 97 KASSERT(dinfo->core_id.num_cfg_blocks <= SIBA_CFG_NUM_MAX, 98 ("config block count %u out of range", 99 dinfo->core_id.num_cfg_blocks)); 100 101 for (u_int cfgidx = 0; cfgidx < dinfo->core_id.num_cfg_blocks; 102 cfgidx++) 103 { 104 rman_res_t r_start, r_count, r_end; 105 106 /* Determine the config block's address range; configuration 107 * blocks are allocated starting at SIBA_CFG0_OFFSET, 108 * growing downwards. */ 109 r_start = addrspace->sa_base + SIBA_CFG0_OFFSET; 110 r_start -= cfgidx * SIBA_CFG_SIZE; 111 112 r_count = SIBA_CFG_SIZE; 113 r_end = r_start + r_count - 1; 114 115 /* Allocate the config resource */ 116 dinfo->cfg_rid[cfgidx] = 0; 117 dinfo->cfg[cfgidx] = BHND_BUS_ALLOC_RESOURCE(dev, dev, 118 SYS_RES_MEMORY, &dinfo->cfg_rid[cfgidx], r_start, 119 r_end, r_count, RF_ACTIVE); 120 121 if (dinfo->cfg[cfgidx] == NULL) { 122 device_printf(dev, "failed allocating CFG_%u for " 123 "core %d\n", cfgidx, i); 124 error = ENXIO; 125 goto cleanup; 126 } 127 } 128 } 129 130 cleanup: 131 free(devs, M_BHND); 132 if (error) 133 return (error); 134 135 /* Delegate remainder to standard bhnd method implementation */ 136 return (bhnd_generic_attach(dev)); 137 } 138 139 int 140 siba_detach(device_t dev) 141 { 142 return (bhnd_generic_detach(dev)); 143 } 144 145 int 146 siba_resume(device_t dev) 147 { 148 return (bhnd_generic_resume(dev)); 149 } 150 151 int 152 siba_suspend(device_t dev) 153 { 154 return (bhnd_generic_suspend(dev)); 155 } 156 157 static int 158 siba_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) 159 { 160 const struct siba_devinfo *dinfo; 161 const struct bhnd_core_info *cfg; 162 163 dinfo = device_get_ivars(child); 164 cfg = &dinfo->core_id.core_info; 165 166 switch (index) { 167 case BHND_IVAR_VENDOR: 168 *result = cfg->vendor; 169 return (0); 170 case BHND_IVAR_DEVICE: 171 *result = cfg->device; 172 return (0); 173 case BHND_IVAR_HWREV: 174 *result = cfg->hwrev; 175 return (0); 176 case BHND_IVAR_DEVICE_CLASS: 177 *result = bhnd_core_class(cfg); 178 return (0); 179 case BHND_IVAR_VENDOR_NAME: 180 *result = (uintptr_t) bhnd_vendor_name(cfg->vendor); 181 return (0); 182 case BHND_IVAR_DEVICE_NAME: 183 *result = (uintptr_t) bhnd_core_name(cfg); 184 return (0); 185 case BHND_IVAR_CORE_INDEX: 186 *result = cfg->core_idx; 187 return (0); 188 case BHND_IVAR_CORE_UNIT: 189 *result = cfg->unit; 190 return (0); 191 default: 192 return (ENOENT); 193 } 194 } 195 196 static int 197 siba_write_ivar(device_t dev, device_t child, int index, uintptr_t value) 198 { 199 switch (index) { 200 case BHND_IVAR_VENDOR: 201 case BHND_IVAR_DEVICE: 202 case BHND_IVAR_HWREV: 203 case BHND_IVAR_DEVICE_CLASS: 204 case BHND_IVAR_VENDOR_NAME: 205 case BHND_IVAR_DEVICE_NAME: 206 case BHND_IVAR_CORE_INDEX: 207 case BHND_IVAR_CORE_UNIT: 208 return (EINVAL); 209 default: 210 return (ENOENT); 211 } 212 } 213 214 static void 215 siba_child_deleted(device_t dev, device_t child) 216 { 217 struct siba_devinfo *dinfo = device_get_ivars(child); 218 if (dinfo != NULL) 219 siba_free_dinfo(dev, dinfo); 220 } 221 222 static struct resource_list * 223 siba_get_resource_list(device_t dev, device_t child) 224 { 225 struct siba_devinfo *dinfo = device_get_ivars(child); 226 return (&dinfo->resources); 227 } 228 229 static device_t 230 siba_find_hostb_device(device_t dev) 231 { 232 struct siba_softc *sc = device_get_softc(dev); 233 234 /* This is set (or not) by the concrete siba driver subclass. */ 235 return (sc->hostb_dev); 236 } 237 238 static int 239 siba_reset_core(device_t dev, device_t child, uint16_t flags) 240 { 241 struct siba_devinfo *dinfo; 242 243 if (device_get_parent(child) != dev) 244 BHND_BUS_RESET_CORE(device_get_parent(dev), child, flags); 245 246 dinfo = device_get_ivars(child); 247 248 /* Can't reset the core without access to the CFG0 registers */ 249 if (dinfo->cfg[0] == NULL) 250 return (ENODEV); 251 252 // TODO - perform reset 253 254 return (ENXIO); 255 } 256 257 static int 258 siba_suspend_core(device_t dev, device_t child) 259 { 260 struct siba_devinfo *dinfo; 261 262 if (device_get_parent(child) != dev) 263 BHND_BUS_SUSPEND_CORE(device_get_parent(dev), child); 264 265 dinfo = device_get_ivars(child); 266 267 /* Can't suspend the core without access to the CFG0 registers */ 268 if (dinfo->cfg[0] == NULL) 269 return (ENODEV); 270 271 // TODO - perform suspend 272 273 return (ENXIO); 274 } 275 276 277 static u_int 278 siba_get_port_count(device_t dev, device_t child, bhnd_port_type type) 279 { 280 struct siba_devinfo *dinfo; 281 282 /* delegate non-bus-attached devices to our parent */ 283 if (device_get_parent(child) != dev) 284 return (BHND_BUS_GET_PORT_COUNT(device_get_parent(dev), child, 285 type)); 286 287 dinfo = device_get_ivars(child); 288 289 /* We advertise exactly one port of any type */ 290 if (siba_dinfo_get_port(dinfo, type, 0) != NULL) 291 return (1); 292 293 return (0); 294 } 295 296 static u_int 297 siba_get_region_count(device_t dev, device_t child, bhnd_port_type type, 298 u_int port_num) 299 { 300 struct siba_devinfo *dinfo; 301 struct siba_port *port; 302 303 /* delegate non-bus-attached devices to our parent */ 304 if (device_get_parent(child) != dev) 305 return (BHND_BUS_GET_REGION_COUNT(device_get_parent(dev), child, 306 type, port_num)); 307 308 dinfo = device_get_ivars(child); 309 port = siba_dinfo_get_port(dinfo, type, port_num); 310 if (port == NULL) 311 return (0); 312 313 return (port->sp_num_addrs); 314 } 315 316 static int 317 siba_get_port_rid(device_t dev, device_t child, bhnd_port_type port_type, 318 u_int port_num, u_int region_num) 319 { 320 struct siba_devinfo *dinfo; 321 struct siba_port *port; 322 struct siba_addrspace *addrspace; 323 324 /* delegate non-bus-attached devices to our parent */ 325 if (device_get_parent(child) != dev) 326 return (BHND_BUS_GET_PORT_RID(device_get_parent(dev), child, 327 port_type, port_num, region_num)); 328 329 dinfo = device_get_ivars(child); 330 port = siba_dinfo_get_port(dinfo, port_type, port_num); 331 if (port == NULL) 332 return (-1); 333 334 STAILQ_FOREACH(addrspace, &port->sp_addrs, sa_link) { 335 if (addrspace->sa_region_num == region_num) 336 return (addrspace->sa_rid); 337 } 338 339 /* not found */ 340 return (-1); 341 } 342 343 static int 344 siba_decode_port_rid(device_t dev, device_t child, int type, int rid, 345 bhnd_port_type *port_type, u_int *port_num, u_int *region_num) 346 { 347 struct siba_devinfo *dinfo; 348 struct siba_port *port; 349 struct siba_addrspace *addrspace; 350 351 /* delegate non-bus-attached devices to our parent */ 352 if (device_get_parent(child) != dev) 353 return (BHND_BUS_DECODE_PORT_RID(device_get_parent(dev), child, 354 type, rid, port_type, port_num, region_num)); 355 356 dinfo = device_get_ivars(child); 357 358 /* Ports are always memory mapped */ 359 if (type != SYS_RES_MEMORY) 360 return (EINVAL); 361 362 /* Starting with the most likely device list, search all three port 363 * lists */ 364 bhnd_port_type types[] = { 365 BHND_PORT_DEVICE, 366 BHND_PORT_AGENT, 367 BHND_PORT_BRIDGE 368 }; 369 370 for (int i = 0; i < nitems(types); i++) { 371 port = siba_dinfo_get_port(dinfo, types[i], 0); 372 if (port == NULL) 373 continue; 374 375 STAILQ_FOREACH(addrspace, &port->sp_addrs, sa_link) { 376 if (addrspace->sa_rid != rid) 377 continue; 378 379 *port_type = port->sp_type; 380 *port_num = port->sp_num; 381 *region_num = addrspace->sa_region_num; 382 } 383 } 384 385 return (ENOENT); 386 } 387 388 static int 389 siba_get_region_addr(device_t dev, device_t child, bhnd_port_type port_type, 390 u_int port_num, u_int region_num, bhnd_addr_t *addr, bhnd_size_t *size) 391 { 392 struct siba_devinfo *dinfo; 393 struct siba_port *port; 394 struct siba_addrspace *addrspace; 395 396 /* delegate non-bus-attached devices to our parent */ 397 if (device_get_parent(child) != dev) { 398 return (BHND_BUS_GET_REGION_ADDR(device_get_parent(dev), child, 399 port_type, port_num, region_num, addr, size)); 400 } 401 402 dinfo = device_get_ivars(child); 403 port = siba_dinfo_get_port(dinfo, port_type, port_num); 404 if (port == NULL) 405 return (ENOENT); 406 407 STAILQ_FOREACH(addrspace, &port->sp_addrs, sa_link) { 408 if (addrspace->sa_region_num != region_num) 409 continue; 410 411 *addr = addrspace->sa_base; 412 *size = addrspace->sa_size - addrspace->sa_bus_reserved; 413 return (0); 414 } 415 416 return (ENOENT); 417 } 418 419 420 /** 421 * Register all address space mappings for @p di. 422 * 423 * @param dev The siba bus device. 424 * @param di The device info instance on which to register all address 425 * space entries. 426 * @param r A resource mapping the enumeration table block for @p di. 427 */ 428 static int 429 siba_register_addrspaces(device_t dev, struct siba_devinfo *di, 430 struct resource *r) 431 { 432 struct siba_core_id *cid; 433 uint32_t addr; 434 uint32_t size; 435 u_int region_num; 436 int error; 437 438 cid = &di->core_id; 439 440 /* Region numbers must be assigned in order, but our siba address 441 * space IDs may be sparsely allocated; thus, we track 442 * the region index separately. */ 443 region_num = 0; 444 445 /* Register the device address space entries */ 446 for (uint8_t sid = 0; sid < di->core_id.num_addrspace; sid++) { 447 uint32_t adm; 448 u_int adm_offset; 449 uint32_t bus_reserved; 450 451 /* Determine the register offset */ 452 adm_offset = siba_admatch_offset(sid); 453 if (adm_offset == 0) { 454 device_printf(dev, "addrspace %hhu is unsupported", sid); 455 return (ENODEV); 456 } 457 458 /* Fetch the address match register value */ 459 adm = bus_read_4(r, adm_offset); 460 461 /* Parse the value */ 462 if ((error = siba_parse_admatch(adm, &addr, &size))) { 463 device_printf(dev, "failed to decode address " 464 " match register value 0x%x\n", adm); 465 return (error); 466 } 467 468 /* If this is the device's core/enumeration addrespace, 469 * reserve the Sonics configuration register blocks for the 470 * use of our bus. */ 471 bus_reserved = 0; 472 if (sid == SIBA_ADDRSPACE_CORE) 473 bus_reserved = cid->num_cfg_blocks * SIBA_CFG_SIZE; 474 475 /* Append the region info */ 476 error = siba_append_dinfo_region(di, BHND_PORT_DEVICE, 0, 477 region_num, sid, addr, size, bus_reserved); 478 if (error) 479 return (error); 480 481 482 region_num++; 483 } 484 485 return (0); 486 } 487 488 /** 489 * Scan the core table and add all valid discovered cores to 490 * the bus. 491 * 492 * @param dev The siba bus device. 493 * @param chipid The chip identifier, if the device does not provide a 494 * ChipCommon core. Should o NULL otherwise. 495 */ 496 int 497 siba_add_children(device_t dev, const struct bhnd_chipid *chipid) 498 { 499 struct bhnd_chipid ccid; 500 struct bhnd_core_info *cores; 501 struct siba_devinfo *dinfo; 502 struct resource *r; 503 int rid; 504 int error; 505 506 dinfo = NULL; 507 cores = NULL; 508 r = NULL; 509 510 /* 511 * Try to determine the number of device cores via the ChipCommon 512 * identification registers. 513 * 514 * A small number of very early devices do not include a ChipCommon 515 * core, in which case our caller must supply the chip identification 516 * information via a non-NULL chipid parameter. 517 */ 518 if (chipid == NULL) { 519 uint32_t idhigh, ccreg; 520 uint16_t vendor, device; 521 uint8_t ccrev; 522 523 /* Map the first core's register block. If the ChipCommon core 524 * exists, it will always be the first core. */ 525 rid = 0; 526 r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 527 SIBA_CORE_ADDR(0), SIBA_CORE_SIZE, 528 SIBA_CORE_ADDR(0) + SIBA_CORE_SIZE - 1, 529 RF_ACTIVE); 530 531 /* Identify the core */ 532 idhigh = bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDHIGH)); 533 vendor = SIBA_REG_GET(idhigh, IDH_VENDOR); 534 device = SIBA_REG_GET(idhigh, IDH_DEVICE); 535 ccrev = SIBA_IDH_CORE_REV(idhigh); 536 537 if (vendor != OCP_VENDOR_BCM || device != BHND_COREID_CC) { 538 device_printf(dev, 539 "cannot identify device: no chipcommon core " 540 "found\n"); 541 error = ENXIO; 542 goto cleanup; 543 } 544 545 /* Identify the chipset */ 546 ccreg = bus_read_4(r, CHIPC_ID); 547 ccid = bhnd_parse_chipid(ccreg, SIBA_ENUM_ADDR); 548 549 if (!CHIPC_NCORES_MIN_HWREV(ccrev)) { 550 switch (ccid.chip_id) { 551 case BHND_CHIPID_BCM4306: 552 ccid.ncores = 6; 553 break; 554 case BHND_CHIPID_BCM4704: 555 ccid.ncores = 9; 556 break; 557 case BHND_CHIPID_BCM5365: 558 /* 559 * BCM5365 does support ID_NUMCORE in at least 560 * some of its revisions, but for unknown 561 * reasons, Broadcom's drivers always exclude 562 * the ChipCommon revision (0x5) used by BCM5365 563 * from the set of revisions supporting 564 * ID_NUMCORE, and instead supply a fixed value. 565 * 566 * Presumably, at least some of these devices 567 * shipped with a broken ID_NUMCORE value. 568 */ 569 ccid.ncores = 7; 570 break; 571 default: 572 device_printf(dev, "unable to determine core " 573 "count for unrecognized chipset 0x%hx\n", 574 ccid.chip_id); 575 error = ENXIO; 576 goto cleanup; 577 } 578 } 579 580 chipid = &ccid; 581 bus_release_resource(dev, SYS_RES_MEMORY, rid, r); 582 } 583 584 /* Allocate our temporary core table and enumerate all cores */ 585 cores = malloc(sizeof(*cores) * chipid->ncores, M_BHND, M_NOWAIT); 586 if (cores == NULL) 587 return (ENOMEM); 588 589 /* Add all cores. */ 590 for (u_int i = 0; i < chipid->ncores; i++) { 591 struct siba_core_id cid; 592 device_t child; 593 uint32_t idhigh, idlow; 594 rman_res_t r_count, r_end, r_start; 595 596 /* Map the core's register block */ 597 rid = 0; 598 r_start = SIBA_CORE_ADDR(i); 599 r_count = SIBA_CORE_SIZE; 600 r_end = r_start + SIBA_CORE_SIZE - 1; 601 r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, r_start, 602 r_end, r_count, RF_ACTIVE); 603 if (r == NULL) { 604 error = ENXIO; 605 goto cleanup; 606 } 607 608 /* Read the core info */ 609 idhigh = bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDHIGH)); 610 idlow = bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDLOW)); 611 612 cid = siba_parse_core_id(idhigh, idlow, i, 0); 613 cores[i] = cid.core_info; 614 615 /* Determine unit number */ 616 for (u_int j = 0; j < i; j++) { 617 if (cores[j].vendor == cores[i].vendor && 618 cores[j].device == cores[i].device) 619 cores[i].unit++; 620 } 621 622 /* Allocate per-device bus info */ 623 dinfo = siba_alloc_dinfo(dev, &cid); 624 if (dinfo == NULL) { 625 error = ENXIO; 626 goto cleanup; 627 } 628 629 /* Register the core's address space(s). */ 630 if ((error = siba_register_addrspaces(dev, dinfo, r))) 631 goto cleanup; 632 633 /* Add the child device */ 634 child = device_add_child(dev, NULL, -1); 635 if (child == NULL) { 636 error = ENXIO; 637 goto cleanup; 638 } 639 640 /* The child device now owns the dinfo pointer */ 641 device_set_ivars(child, dinfo); 642 dinfo = NULL; 643 644 /* If pins are floating or the hardware is otherwise 645 * unpopulated, the device shouldn't be used. */ 646 if (bhnd_is_hw_disabled(child)) 647 device_disable(child); 648 649 /* Release our resource */ 650 bus_release_resource(dev, SYS_RES_MEMORY, rid, r); 651 r = NULL; 652 } 653 654 cleanup: 655 if (cores != NULL) 656 free(cores, M_BHND); 657 658 if (dinfo != NULL) 659 siba_free_dinfo(dev, dinfo); 660 661 if (r != NULL) 662 bus_release_resource(dev, SYS_RES_MEMORY, rid, r); 663 664 return (error); 665 } 666 667 static device_method_t siba_methods[] = { 668 /* Device interface */ 669 DEVMETHOD(device_probe, siba_probe), 670 DEVMETHOD(device_attach, siba_attach), 671 DEVMETHOD(device_detach, siba_detach), 672 DEVMETHOD(device_resume, siba_resume), 673 DEVMETHOD(device_suspend, siba_suspend), 674 675 /* Bus interface */ 676 DEVMETHOD(bus_child_deleted, siba_child_deleted), 677 DEVMETHOD(bus_read_ivar, siba_read_ivar), 678 DEVMETHOD(bus_write_ivar, siba_write_ivar), 679 DEVMETHOD(bus_get_resource_list, siba_get_resource_list), 680 681 /* BHND interface */ 682 DEVMETHOD(bhnd_bus_find_hostb_device, siba_find_hostb_device), 683 DEVMETHOD(bhnd_bus_reset_core, siba_reset_core), 684 DEVMETHOD(bhnd_bus_suspend_core, siba_suspend_core), 685 DEVMETHOD(bhnd_bus_get_port_count, siba_get_port_count), 686 DEVMETHOD(bhnd_bus_get_region_count, siba_get_region_count), 687 DEVMETHOD(bhnd_bus_get_port_rid, siba_get_port_rid), 688 DEVMETHOD(bhnd_bus_decode_port_rid, siba_decode_port_rid), 689 DEVMETHOD(bhnd_bus_get_region_addr, siba_get_region_addr), 690 691 DEVMETHOD_END 692 }; 693 694 DEFINE_CLASS_1(bhnd, siba_driver, siba_methods, sizeof(struct siba_softc), bhnd_driver); 695 696 MODULE_VERSION(siba, 1); 697 MODULE_DEPEND(siba, bhnd, 1, 1, 1); 698