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