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_alloc_resource(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; 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 /* Skip disabled entries */ 462 if (adm & SIBA_AM_ADEN) 463 continue; 464 465 /* Parse the value */ 466 if ((error = siba_parse_admatch(adm, &addr, &size))) { 467 device_printf(dev, "failed to decode address " 468 " match register value 0x%x\n", adm); 469 return (error); 470 } 471 472 /* If this is the device's core/enumeration addrespace, 473 * reserve the Sonics configuration register blocks for the 474 * use of our bus. */ 475 bus_reserved = 0; 476 if (sid == SIBA_ADDRSPACE_CORE) 477 bus_reserved = cid->num_cfg_blocks * SIBA_CFG_SIZE; 478 479 /* Append the region info */ 480 error = siba_append_dinfo_region(di, BHND_PORT_DEVICE, 0, 481 region_num, sid, addr, size, bus_reserved); 482 if (error) 483 return (error); 484 485 486 region_num++; 487 } 488 489 return (0); 490 } 491 492 /** 493 * Scan the core table and add all valid discovered cores to 494 * the bus. 495 * 496 * @param dev The siba bus device. 497 * @param chipid The chip identifier, if the device does not provide a 498 * ChipCommon core. Should o NULL otherwise. 499 */ 500 int 501 siba_add_children(device_t dev, const struct bhnd_chipid *chipid) 502 { 503 struct bhnd_chipid ccid; 504 struct bhnd_core_info *cores; 505 struct siba_devinfo *dinfo; 506 struct resource *r; 507 int rid; 508 int error; 509 510 dinfo = NULL; 511 cores = NULL; 512 r = NULL; 513 514 /* 515 * Try to determine the number of device cores via the ChipCommon 516 * identification registers. 517 * 518 * A small number of very early devices do not include a ChipCommon 519 * core, in which case our caller must supply the chip identification 520 * information via a non-NULL chipid parameter. 521 */ 522 if (chipid == NULL) { 523 uint32_t idhigh, ccreg; 524 uint16_t vendor, device; 525 uint8_t ccrev; 526 527 /* Map the first core's register block. If the ChipCommon core 528 * exists, it will always be the first core. */ 529 rid = 0; 530 r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 531 SIBA_CORE_ADDR(0), SIBA_CORE_SIZE, 532 SIBA_CORE_ADDR(0) + SIBA_CORE_SIZE - 1, 533 RF_ACTIVE); 534 535 /* Identify the core */ 536 idhigh = bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDHIGH)); 537 vendor = SIBA_REG_GET(idhigh, IDH_VENDOR); 538 device = SIBA_REG_GET(idhigh, IDH_DEVICE); 539 ccrev = SIBA_IDH_CORE_REV(idhigh); 540 541 if (vendor != OCP_VENDOR_BCM || device != BHND_COREID_CC) { 542 device_printf(dev, 543 "cannot identify device: no chipcommon core " 544 "found\n"); 545 error = ENXIO; 546 goto cleanup; 547 } 548 549 /* Identify the chipset */ 550 ccreg = bus_read_4(r, CHIPC_ID); 551 ccid = bhnd_parse_chipid(ccreg, SIBA_ENUM_ADDR); 552 553 if (!CHIPC_NCORES_MIN_HWREV(ccrev)) { 554 switch (device) { 555 case BHND_CHIPID_BCM4306: 556 ccid.ncores = 6; 557 break; 558 case BHND_CHIPID_BCM4704: 559 ccid.ncores = 9; 560 break; 561 case BHND_CHIPID_BCM5365: 562 /* 563 * BCM5365 does support ID_NUMCORE in at least 564 * some of its revisions, but for unknown 565 * reasons, Broadcom's drivers always exclude 566 * the ChipCommon revision (0x5) used by BCM5365 567 * from the set of revisions supporting 568 * ID_NUMCORE, and instead supply a fixed value. 569 * 570 * Presumably, at least some of these devices 571 * shipped with a broken ID_NUMCORE value. 572 */ 573 ccid.ncores = 7; 574 break; 575 default: 576 device_printf(dev, "unable to determine core " 577 "count for unrecognized chipset 0x%hx\n", 578 ccid.chip_id); 579 error = ENXIO; 580 goto cleanup; 581 } 582 } 583 584 chipid = &ccid; 585 bus_release_resource(dev, SYS_RES_MEMORY, rid, r); 586 } 587 588 /* Allocate our temporary core table and enumerate all cores */ 589 cores = malloc(sizeof(*cores) * chipid->ncores, M_BHND, M_NOWAIT); 590 if (cores == NULL) 591 return (ENOMEM); 592 593 /* Add all cores. */ 594 for (u_int i = 0; i < chipid->ncores; i++) { 595 struct siba_core_id cid; 596 device_t child; 597 uint32_t idhigh, idlow; 598 rman_res_t r_count, r_end, r_start; 599 600 /* Map the core's register block */ 601 rid = 0; 602 r_start = SIBA_CORE_ADDR(i); 603 r_count = SIBA_CORE_SIZE; 604 r_end = r_start + SIBA_CORE_SIZE - 1; 605 r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, r_start, 606 r_end, r_count, RF_ACTIVE); 607 if (r == NULL) { 608 error = ENXIO; 609 goto cleanup; 610 } 611 612 /* Read the core info */ 613 idhigh = bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDHIGH)); 614 idlow = bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDLOW)); 615 616 cid = siba_parse_core_id(idhigh, idlow, i, 0); 617 cores[i] = cid.core_info; 618 619 /* Determine unit number */ 620 for (u_int j = 0; j < i; j++) { 621 if (cores[j].vendor == cores[i].vendor && 622 cores[j].device == cores[i].device) 623 cores[i].unit++; 624 } 625 626 /* Allocate per-device bus info */ 627 dinfo = siba_alloc_dinfo(dev, &cid); 628 if (dinfo == NULL) { 629 error = ENXIO; 630 goto cleanup; 631 } 632 633 /* Register the core's address space(s). */ 634 if ((error = siba_register_addrspaces(dev, dinfo, r))) 635 goto cleanup; 636 637 /* Add the child device */ 638 child = device_add_child(dev, NULL, -1); 639 if (child == NULL) { 640 error = ENXIO; 641 goto cleanup; 642 } 643 644 /* The child device now owns the dinfo pointer */ 645 device_set_ivars(child, dinfo); 646 dinfo = NULL; 647 648 /* If pins are floating or the hardware is otherwise 649 * unpopulated, the device shouldn't be used. */ 650 if (bhnd_is_hw_disabled(child)) 651 device_disable(child); 652 653 /* Release our resource */ 654 bus_release_resource(dev, SYS_RES_MEMORY, rid, r); 655 r = NULL; 656 } 657 658 cleanup: 659 if (cores != NULL) 660 free(cores, M_BHND); 661 662 if (dinfo != NULL) 663 siba_free_dinfo(dev, dinfo); 664 665 if (r != NULL) 666 bus_release_resource(dev, SYS_RES_MEMORY, rid, r); 667 668 return (error); 669 } 670 671 static device_method_t siba_methods[] = { 672 /* Device interface */ 673 DEVMETHOD(device_probe, siba_probe), 674 DEVMETHOD(device_attach, siba_attach), 675 DEVMETHOD(device_detach, siba_detach), 676 DEVMETHOD(device_resume, siba_resume), 677 DEVMETHOD(device_suspend, siba_suspend), 678 679 /* Bus interface */ 680 DEVMETHOD(bus_child_deleted, siba_child_deleted), 681 DEVMETHOD(bus_read_ivar, siba_read_ivar), 682 DEVMETHOD(bus_write_ivar, siba_write_ivar), 683 DEVMETHOD(bus_get_resource_list, siba_get_resource_list), 684 685 /* BHND interface */ 686 DEVMETHOD(bhnd_bus_find_hostb_device, siba_find_hostb_device), 687 DEVMETHOD(bhnd_bus_reset_core, siba_reset_core), 688 DEVMETHOD(bhnd_bus_suspend_core, siba_suspend_core), 689 DEVMETHOD(bhnd_bus_get_port_count, siba_get_port_count), 690 DEVMETHOD(bhnd_bus_get_region_count, siba_get_region_count), 691 DEVMETHOD(bhnd_bus_get_port_rid, siba_get_port_rid), 692 DEVMETHOD(bhnd_bus_decode_port_rid, siba_decode_port_rid), 693 DEVMETHOD(bhnd_bus_get_region_addr, siba_get_region_addr), 694 695 DEVMETHOD_END 696 }; 697 698 DEFINE_CLASS_1(bhnd, siba_driver, siba_methods, sizeof(struct siba_softc), bhnd_driver); 699 700 MODULE_VERSION(siba, 1); 701 MODULE_DEPEND(siba, bhnd, 1, 1, 1); 702