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