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 int 220 siba_reset_core(device_t dev, device_t child, uint16_t flags) 221 { 222 struct siba_devinfo *dinfo; 223 224 if (device_get_parent(child) != dev) 225 BHND_BUS_RESET_CORE(device_get_parent(dev), child, flags); 226 227 dinfo = device_get_ivars(child); 228 229 /* Can't reset the core without access to the CFG0 registers */ 230 if (dinfo->cfg[0] == NULL) 231 return (ENODEV); 232 233 // TODO - perform reset 234 235 return (ENXIO); 236 } 237 238 static int 239 siba_suspend_core(device_t dev, device_t child) 240 { 241 struct siba_devinfo *dinfo; 242 243 if (device_get_parent(child) != dev) 244 BHND_BUS_SUSPEND_CORE(device_get_parent(dev), child); 245 246 dinfo = device_get_ivars(child); 247 248 /* Can't suspend the core without access to the CFG0 registers */ 249 if (dinfo->cfg[0] == NULL) 250 return (ENODEV); 251 252 // TODO - perform suspend 253 254 return (ENXIO); 255 } 256 257 258 static u_int 259 siba_get_port_count(device_t dev, device_t child, bhnd_port_type type) 260 { 261 struct siba_devinfo *dinfo; 262 263 /* delegate non-bus-attached devices to our parent */ 264 if (device_get_parent(child) != dev) 265 return (BHND_BUS_GET_PORT_COUNT(device_get_parent(dev), child, 266 type)); 267 268 dinfo = device_get_ivars(child); 269 270 /* We advertise exactly one port of any type */ 271 if (siba_dinfo_get_port(dinfo, type, 0) != NULL) 272 return (1); 273 274 return (0); 275 } 276 277 static u_int 278 siba_get_region_count(device_t dev, device_t child, bhnd_port_type type, 279 u_int port_num) 280 { 281 struct siba_devinfo *dinfo; 282 struct siba_port *port; 283 284 /* delegate non-bus-attached devices to our parent */ 285 if (device_get_parent(child) != dev) 286 return (BHND_BUS_GET_REGION_COUNT(device_get_parent(dev), child, 287 type, port_num)); 288 289 dinfo = device_get_ivars(child); 290 port = siba_dinfo_get_port(dinfo, type, port_num); 291 if (port == NULL) 292 return (0); 293 294 return (port->sp_num_addrs); 295 } 296 297 static int 298 siba_get_port_rid(device_t dev, device_t child, bhnd_port_type port_type, 299 u_int port_num, u_int region_num) 300 { 301 struct siba_devinfo *dinfo; 302 struct siba_port *port; 303 struct siba_addrspace *addrspace; 304 305 /* delegate non-bus-attached devices to our parent */ 306 if (device_get_parent(child) != dev) 307 return (BHND_BUS_GET_PORT_RID(device_get_parent(dev), child, 308 port_type, port_num, region_num)); 309 310 dinfo = device_get_ivars(child); 311 port = siba_dinfo_get_port(dinfo, port_type, port_num); 312 if (port == NULL) 313 return (-1); 314 315 STAILQ_FOREACH(addrspace, &port->sp_addrs, sa_link) { 316 if (addrspace->sa_region_num == region_num) 317 return (addrspace->sa_rid); 318 } 319 320 /* not found */ 321 return (-1); 322 } 323 324 static int 325 siba_decode_port_rid(device_t dev, device_t child, int type, int rid, 326 bhnd_port_type *port_type, u_int *port_num, u_int *region_num) 327 { 328 struct siba_devinfo *dinfo; 329 struct siba_port *port; 330 struct siba_addrspace *addrspace; 331 332 /* delegate non-bus-attached devices to our parent */ 333 if (device_get_parent(child) != dev) 334 return (BHND_BUS_DECODE_PORT_RID(device_get_parent(dev), child, 335 type, rid, port_type, port_num, region_num)); 336 337 dinfo = device_get_ivars(child); 338 339 /* Ports are always memory mapped */ 340 if (type != SYS_RES_MEMORY) 341 return (EINVAL); 342 343 /* Starting with the most likely device list, search all three port 344 * lists */ 345 bhnd_port_type types[] = { 346 BHND_PORT_DEVICE, 347 BHND_PORT_AGENT, 348 BHND_PORT_BRIDGE 349 }; 350 351 for (int i = 0; i < nitems(types); i++) { 352 port = siba_dinfo_get_port(dinfo, types[i], 0); 353 if (port == NULL) 354 continue; 355 356 STAILQ_FOREACH(addrspace, &port->sp_addrs, sa_link) { 357 if (addrspace->sa_rid != rid) 358 continue; 359 360 *port_type = port->sp_type; 361 *port_num = port->sp_num; 362 *region_num = addrspace->sa_region_num; 363 } 364 } 365 366 return (ENOENT); 367 } 368 369 static int 370 siba_get_region_addr(device_t dev, device_t child, bhnd_port_type port_type, 371 u_int port_num, u_int region_num, bhnd_addr_t *addr, bhnd_size_t *size) 372 { 373 struct siba_devinfo *dinfo; 374 struct siba_port *port; 375 struct siba_addrspace *addrspace; 376 377 /* delegate non-bus-attached devices to our parent */ 378 if (device_get_parent(child) != dev) { 379 return (BHND_BUS_GET_REGION_ADDR(device_get_parent(dev), child, 380 port_type, port_num, region_num, addr, size)); 381 } 382 383 dinfo = device_get_ivars(child); 384 port = siba_dinfo_get_port(dinfo, port_type, port_num); 385 if (port == NULL) 386 return (ENOENT); 387 388 STAILQ_FOREACH(addrspace, &port->sp_addrs, sa_link) { 389 if (addrspace->sa_region_num != region_num) 390 continue; 391 392 *addr = addrspace->sa_base; 393 *size = addrspace->sa_size; 394 return (0); 395 } 396 397 return (ENOENT); 398 } 399 400 401 /** 402 * Register all address space mappings for @p di. 403 * 404 * @param dev The siba bus device. 405 * @param di The device info instance on which to register all address 406 * space entries. 407 * @param r A resource mapping the enumeration table block for @p di. 408 */ 409 static int 410 siba_register_addrspaces(device_t dev, struct siba_devinfo *di, 411 struct resource *r) 412 { 413 struct siba_core_id *cid; 414 uint32_t addr; 415 uint32_t size; 416 u_int region_num; 417 int error; 418 419 cid = &di->core_id; 420 421 /* Region numbers must be assigned in order, but our siba address 422 * space IDs may be sparsely allocated; thus, we track 423 * the region index seperately. */ 424 region_num = 0; 425 426 /* Register the device address space entries */ 427 for (uint8_t sid = 0; sid < di->core_id.num_addrspace; sid++) { 428 uint32_t adm; 429 u_int adm_offset; 430 uint32_t bus_reserved; 431 432 /* Determine the register offset */ 433 adm_offset = siba_admatch_offset(sid); 434 if (adm_offset == 0) { 435 device_printf(dev, "addrspace %hhu is unsupported", sid); 436 return (ENODEV); 437 } 438 439 /* Fetch the address match register value */ 440 adm = bus_read_4(r, adm_offset); 441 442 /* Skip disabled entries */ 443 if (adm & SIBA_AM_ADEN) 444 continue; 445 446 /* Parse the value */ 447 if ((error = siba_parse_admatch(adm, &addr, &size))) { 448 device_printf(dev, "failed to decode address " 449 " match register value 0x%x\n", adm); 450 return (error); 451 } 452 453 /* If this is the device's core/enumeration addrespace, 454 * reserve the Sonics configuration register blocks for the 455 * use of our bus. */ 456 bus_reserved = 0; 457 if (sid == SIBA_ADDRSPACE_CORE) 458 bus_reserved = cid->num_cfg_blocks * SIBA_CFG_SIZE; 459 460 /* Append the region info */ 461 error = siba_append_dinfo_region(di, BHND_PORT_DEVICE, 0, 462 region_num, sid, addr, size, bus_reserved); 463 if (error) 464 return (error); 465 466 467 region_num++; 468 } 469 470 return (0); 471 } 472 473 /** 474 * Scan the core table and add all valid discovered cores to 475 * the bus. 476 * 477 * @param dev The siba bus device. 478 * @param chipid The chip identifier, if the device does not provide a 479 * ChipCommon core. Should o NULL otherwise. 480 */ 481 int 482 siba_add_children(device_t dev, const struct bhnd_chipid *chipid) 483 { 484 struct bhnd_chipid ccid; 485 struct bhnd_core_info *cores; 486 struct siba_devinfo *dinfo; 487 struct resource *r; 488 int rid; 489 int error; 490 491 dinfo = NULL; 492 cores = NULL; 493 r = NULL; 494 495 /* 496 * Try to determine the number of device cores via the ChipCommon 497 * identification registers. 498 * 499 * A small number of very early devices do not include a ChipCommon 500 * core, in which case our caller must supply the chip identification 501 * information via a non-NULL chipid parameter. 502 */ 503 if (chipid == NULL) { 504 uint32_t idhigh, ccreg; 505 uint16_t vendor, device; 506 uint8_t ccrev; 507 508 /* Map the first core's register block. If the ChipCommon core 509 * exists, it will always be the first core. */ 510 rid = 0; 511 r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 512 SIBA_CORE_ADDR(0), SIBA_CORE_SIZE, 513 SIBA_CORE_ADDR(0) + SIBA_CORE_SIZE - 1, 514 RF_ACTIVE); 515 516 /* Identify the core */ 517 idhigh = bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDHIGH)); 518 vendor = SIBA_REG_GET(idhigh, IDH_VENDOR); 519 device = SIBA_REG_GET(idhigh, IDH_DEVICE); 520 ccrev = SIBA_IDH_CORE_REV(idhigh); 521 522 if (vendor != OCP_VENDOR_BCM || device != BHND_COREID_CC) { 523 device_printf(dev, 524 "cannot identify device: no chipcommon core " 525 "found\n"); 526 error = ENXIO; 527 goto cleanup; 528 } 529 530 /* Identify the chipset */ 531 ccreg = bus_read_4(r, CHIPC_ID); 532 ccid = bhnd_parse_chipid(ccreg, SIBA_ENUM_ADDR); 533 534 if (!CHIPC_NCORES_MIN_HWREV(ccrev)) { 535 switch (device) { 536 case BHND_CHIPID_BCM4306: 537 ccid.ncores = 6; 538 break; 539 case BHND_CHIPID_BCM4704: 540 ccid.ncores = 9; 541 break; 542 case BHND_CHIPID_BCM5365: 543 /* 544 * BCM5365 does support ID_NUMCORE in at least 545 * some of its revisions, but for unknown 546 * reasons, Broadcom's drivers always exclude 547 * the ChipCommon revision (0x5) used by BCM5365 548 * from the set of revisions supporting 549 * ID_NUMCORE, and instead supply a fixed value. 550 * 551 * Presumably, at least some of these devices 552 * shipped with a broken ID_NUMCORE value. 553 */ 554 ccid.ncores = 7; 555 break; 556 default: 557 device_printf(dev, "unable to determine core " 558 "count for unrecognized chipset 0x%hx\n", 559 ccid.chip_id); 560 error = ENXIO; 561 goto cleanup; 562 } 563 } 564 565 chipid = &ccid; 566 bus_release_resource(dev, SYS_RES_MEMORY, rid, r); 567 } 568 569 /* Allocate our temporary core table and enumerate all cores */ 570 cores = malloc(sizeof(*cores) * chipid->ncores, M_BHND, M_NOWAIT); 571 if (cores == NULL) 572 return (ENOMEM); 573 574 /* Add all cores. */ 575 for (u_int i = 0; i < chipid->ncores; i++) { 576 struct siba_core_id cid; 577 device_t child; 578 uint32_t idhigh, idlow; 579 rman_res_t r_count, r_end, r_start; 580 581 /* Map the core's register block */ 582 rid = 0; 583 r_start = SIBA_CORE_ADDR(i); 584 r_count = SIBA_CORE_SIZE; 585 r_end = r_start + SIBA_CORE_SIZE - 1; 586 r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, r_start, 587 r_end, r_count, RF_ACTIVE); 588 if (r == NULL) { 589 error = ENXIO; 590 goto cleanup; 591 } 592 593 /* Read the core info */ 594 idhigh = bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDHIGH)); 595 idlow = bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDLOW)); 596 597 cid = siba_parse_core_id(idhigh, idlow, i, 0); 598 cores[i] = cid.core_info; 599 600 /* Determine unit number */ 601 for (u_int j = 0; j < i; j++) { 602 if (cores[j].vendor == cores[i].vendor && 603 cores[j].device == cores[i].device) 604 cores[i].unit++; 605 } 606 607 /* Allocate per-device bus info */ 608 dinfo = siba_alloc_dinfo(dev, &cid); 609 if (dinfo == NULL) { 610 error = ENXIO; 611 goto cleanup; 612 } 613 614 /* Register the core's address space(s). */ 615 if ((error = siba_register_addrspaces(dev, dinfo, r))) 616 goto cleanup; 617 618 /* Add the child device */ 619 child = device_add_child(dev, NULL, -1); 620 if (child == NULL) { 621 error = ENXIO; 622 goto cleanup; 623 } 624 625 /* The child device now owns the dinfo pointer */ 626 device_set_ivars(child, dinfo); 627 dinfo = NULL; 628 629 /* If pins are floating or the hardware is otherwise 630 * unpopulated, the device shouldn't be used. */ 631 if (bhnd_is_hw_disabled(child)) 632 device_disable(child); 633 634 /* Release our resource */ 635 bus_release_resource(dev, SYS_RES_MEMORY, rid, r); 636 r = NULL; 637 } 638 639 cleanup: 640 if (cores != NULL) 641 free(cores, M_BHND); 642 643 if (dinfo != NULL) 644 siba_free_dinfo(dev, dinfo); 645 646 if (r != NULL) 647 bus_release_resource(dev, SYS_RES_MEMORY, rid, r); 648 649 return (error); 650 } 651 652 static device_method_t siba_methods[] = { 653 /* Device interface */ 654 DEVMETHOD(device_probe, siba_probe), 655 DEVMETHOD(device_attach, siba_attach), 656 DEVMETHOD(device_detach, siba_detach), 657 658 /* Bus interface */ 659 DEVMETHOD(bus_child_deleted, siba_child_deleted), 660 DEVMETHOD(bus_read_ivar, siba_read_ivar), 661 DEVMETHOD(bus_write_ivar, siba_write_ivar), 662 DEVMETHOD(bus_get_resource_list, siba_get_resource_list), 663 664 /* BHND interface */ 665 DEVMETHOD(bhnd_bus_reset_core, siba_reset_core), 666 DEVMETHOD(bhnd_bus_suspend_core, siba_suspend_core), 667 DEVMETHOD(bhnd_bus_get_port_count, siba_get_port_count), 668 DEVMETHOD(bhnd_bus_get_region_count, siba_get_region_count), 669 DEVMETHOD(bhnd_bus_get_port_rid, siba_get_port_rid), 670 DEVMETHOD(bhnd_bus_decode_port_rid, siba_decode_port_rid), 671 DEVMETHOD(bhnd_bus_get_region_addr, siba_get_region_addr), 672 673 DEVMETHOD_END 674 }; 675 676 DEFINE_CLASS_1(bhnd, siba_driver, siba_methods, sizeof(struct siba_softc), bhnd_driver); 677 678 MODULE_VERSION(siba, 1); 679 MODULE_DEPEND(siba, bhnd, 1, 1, 1); 680