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