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