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 47int 48siba_probe(device_t dev) 49{ 50 device_set_desc(dev, "SIBA BHND bus"); 51 return (BUS_PROBE_DEFAULT); 52} 53 54int 55siba_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 125cleanup: 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 134int 135siba_detach(device_t dev) 136{ 137 return (bhnd_generic_detach(dev)); 138} 139 140int 141siba_resume(device_t dev) 142{ 143 return (bhnd_generic_resume(dev)); 144} 145 146int 147siba_suspend(device_t dev) 148{ 149 return (bhnd_generic_suspend(dev)); 150} 151 152static int 153siba_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 191static int 192siba_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 209static struct resource_list * 210siba_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 216static device_t 217siba_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 225static int 226siba_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 244static int 245siba_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 264static u_int 265siba_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 278static u_int 279siba_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 296static int 297siba_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 316static int 317siba_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 347static int 348siba_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 */ 379static int 380siba_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 431static struct bhnd_devinfo * 432siba_alloc_bhnd_dinfo(device_t dev) 433{ 434 struct siba_devinfo *dinfo = siba_alloc_dinfo(dev); 435 return ((struct bhnd_devinfo *)dinfo); 436} 437 438static void 439siba_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 */ 452int 453siba_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 608cleanup: 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 618static 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 646DEFINE_CLASS_1(bhnd, siba_driver, siba_methods, sizeof(struct siba_softc), bhnd_driver); 647 648MODULE_VERSION(siba, 1); 649MODULE_DEPEND(siba, bhnd, 1, 1, 1); 650