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/pmu/bhnd_pmu.h> 43 44 #include "bcma_dmp.h" 45 46 #include "bcma_eromreg.h" 47 #include "bcma_eromvar.h" 48 49 #include "bcmavar.h" 50 51 /* RID used when allocating EROM table */ 52 #define BCMA_EROM_RID 0 53 54 static bhnd_erom_class_t * 55 bcma_get_erom_class(driver_t *driver) 56 { 57 return (&bcma_erom_parser); 58 } 59 60 int 61 bcma_probe(device_t dev) 62 { 63 device_set_desc(dev, "BCMA BHND bus"); 64 return (BUS_PROBE_DEFAULT); 65 } 66 67 /** 68 * Default bcma(4) bus driver implementation of DEVICE_ATTACH(). 69 * 70 * This implementation initializes internal bcma(4) state and performs 71 * bus enumeration, and must be called by subclassing drivers in 72 * DEVICE_ATTACH() before any other bus methods. 73 */ 74 int 75 bcma_attach(device_t dev) 76 { 77 int error; 78 79 /* Enumerate children */ 80 if ((error = bcma_add_children(dev))) { 81 device_delete_children(dev); 82 return (error); 83 } 84 85 return (0); 86 } 87 88 int 89 bcma_detach(device_t dev) 90 { 91 return (bhnd_generic_detach(dev)); 92 } 93 94 static device_t 95 bcma_add_child(device_t dev, u_int order, const char *name, int unit) 96 { 97 struct bcma_devinfo *dinfo; 98 device_t child; 99 100 child = device_add_child_ordered(dev, order, name, unit); 101 if (child == NULL) 102 return (NULL); 103 104 if ((dinfo = bcma_alloc_dinfo(dev)) == NULL) { 105 device_delete_child(dev, child); 106 return (NULL); 107 } 108 109 device_set_ivars(child, dinfo); 110 111 return (child); 112 } 113 114 static void 115 bcma_child_deleted(device_t dev, device_t child) 116 { 117 struct bhnd_softc *sc; 118 struct bcma_devinfo *dinfo; 119 120 sc = device_get_softc(dev); 121 122 /* Call required bhnd(4) implementation */ 123 bhnd_generic_child_deleted(dev, child); 124 125 /* Free bcma device info */ 126 if ((dinfo = device_get_ivars(child)) != NULL) 127 bcma_free_dinfo(dev, dinfo); 128 129 device_set_ivars(child, NULL); 130 } 131 132 static int 133 bcma_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) 134 { 135 const struct bcma_devinfo *dinfo; 136 const struct bhnd_core_info *ci; 137 138 dinfo = device_get_ivars(child); 139 ci = &dinfo->corecfg->core_info; 140 141 switch (index) { 142 case BHND_IVAR_VENDOR: 143 *result = ci->vendor; 144 return (0); 145 case BHND_IVAR_DEVICE: 146 *result = ci->device; 147 return (0); 148 case BHND_IVAR_HWREV: 149 *result = ci->hwrev; 150 return (0); 151 case BHND_IVAR_DEVICE_CLASS: 152 *result = bhnd_core_class(ci); 153 return (0); 154 case BHND_IVAR_VENDOR_NAME: 155 *result = (uintptr_t) bhnd_vendor_name(ci->vendor); 156 return (0); 157 case BHND_IVAR_DEVICE_NAME: 158 *result = (uintptr_t) bhnd_core_name(ci); 159 return (0); 160 case BHND_IVAR_CORE_INDEX: 161 *result = ci->core_idx; 162 return (0); 163 case BHND_IVAR_CORE_UNIT: 164 *result = ci->unit; 165 return (0); 166 case BHND_IVAR_PMU_INFO: 167 *result = (uintptr_t) dinfo->pmu_info; 168 return (0); 169 default: 170 return (ENOENT); 171 } 172 } 173 174 static int 175 bcma_write_ivar(device_t dev, device_t child, int index, uintptr_t value) 176 { 177 struct bcma_devinfo *dinfo; 178 179 dinfo = device_get_ivars(child); 180 181 switch (index) { 182 case BHND_IVAR_VENDOR: 183 case BHND_IVAR_DEVICE: 184 case BHND_IVAR_HWREV: 185 case BHND_IVAR_DEVICE_CLASS: 186 case BHND_IVAR_VENDOR_NAME: 187 case BHND_IVAR_DEVICE_NAME: 188 case BHND_IVAR_CORE_INDEX: 189 case BHND_IVAR_CORE_UNIT: 190 return (EINVAL); 191 case BHND_IVAR_PMU_INFO: 192 dinfo->pmu_info = (struct bhnd_core_pmu_info *) value; 193 return (0); 194 default: 195 return (ENOENT); 196 } 197 } 198 199 static struct resource_list * 200 bcma_get_resource_list(device_t dev, device_t child) 201 { 202 struct bcma_devinfo *dinfo = device_get_ivars(child); 203 return (&dinfo->resources); 204 } 205 206 static int 207 bcma_read_iost(device_t dev, device_t child, uint16_t *iost) 208 { 209 uint32_t value; 210 int error; 211 212 if ((error = bhnd_read_config(child, BCMA_DMP_IOSTATUS, &value, 4))) 213 return (error); 214 215 /* Return only the bottom 16 bits */ 216 *iost = (value & BCMA_DMP_IOST_MASK); 217 return (0); 218 } 219 220 static int 221 bcma_read_ioctl(device_t dev, device_t child, uint16_t *ioctl) 222 { 223 uint32_t value; 224 int error; 225 226 if ((error = bhnd_read_config(child, BCMA_DMP_IOCTRL, &value, 4))) 227 return (error); 228 229 /* Return only the bottom 16 bits */ 230 *ioctl = (value & BCMA_DMP_IOCTRL_MASK); 231 return (0); 232 } 233 234 static int 235 bcma_write_ioctl(device_t dev, device_t child, uint16_t value, uint16_t mask) 236 { 237 struct bcma_devinfo *dinfo; 238 struct bhnd_resource *r; 239 uint32_t ioctl; 240 241 if (device_get_parent(child) != dev) 242 return (EINVAL); 243 244 dinfo = device_get_ivars(child); 245 if ((r = dinfo->res_agent) == NULL) 246 return (ENODEV); 247 248 /* Write new value */ 249 ioctl = bhnd_bus_read_4(r, BCMA_DMP_IOCTRL); 250 ioctl &= ~(BCMA_DMP_IOCTRL_MASK & mask); 251 ioctl |= (value & mask); 252 253 bhnd_bus_write_4(r, BCMA_DMP_IOCTRL, ioctl); 254 255 /* Perform read-back and wait for completion */ 256 bhnd_bus_read_4(r, BCMA_DMP_IOCTRL); 257 DELAY(10); 258 259 return (0); 260 } 261 262 static bool 263 bcma_is_hw_suspended(device_t dev, device_t child) 264 { 265 uint32_t rst; 266 uint16_t ioctl; 267 int error; 268 269 /* Is core held in RESET? */ 270 error = bhnd_read_config(child, BCMA_DMP_RESETCTRL, &rst, 4); 271 if (error) { 272 device_printf(child, "error reading HW reset state: %d\n", 273 error); 274 return (true); 275 } 276 277 if (rst & BMCA_DMP_RC_RESET) 278 return (true); 279 280 /* Is core clocked? */ 281 error = bhnd_read_ioctl(child, &ioctl); 282 if (error) { 283 device_printf(child, "error reading HW ioctl register: %d\n", 284 error); 285 return (true); 286 } 287 288 if (!(ioctl & BHND_IOCTL_CLK_EN)) 289 return (true); 290 291 return (false); 292 } 293 294 static int 295 bcma_reset_hw(device_t dev, device_t child, uint16_t ioctl) 296 { 297 struct bcma_devinfo *dinfo; 298 struct bhnd_core_pmu_info *pm; 299 struct bhnd_resource *r; 300 int error; 301 302 if (device_get_parent(child) != dev) 303 return (EINVAL); 304 305 dinfo = device_get_ivars(child); 306 pm = dinfo->pmu_info; 307 308 /* We require exclusive control over BHND_IOCTL_CLK_EN and 309 * BHND_IOCTL_CLK_FORCE. */ 310 if (ioctl & (BHND_IOCTL_CLK_EN | BHND_IOCTL_CLK_FORCE)) 311 return (EINVAL); 312 313 /* Can't suspend the core without access to the agent registers */ 314 if ((r = dinfo->res_agent) == NULL) 315 return (ENODEV); 316 317 /* Place core into known RESET state */ 318 if ((error = BHND_BUS_SUSPEND_HW(dev, child))) 319 return (error); 320 321 /* 322 * Leaving the core in reset: 323 * - Set the caller's IOCTL flags 324 * - Enable clocks 325 * - Force clock distribution to ensure propagation throughout the 326 * core. 327 */ 328 error = bhnd_write_ioctl(child, 329 ioctl | BHND_IOCTL_CLK_EN | BHND_IOCTL_CLK_FORCE, UINT16_MAX); 330 if (error) 331 return (error); 332 333 /* Bring the core out of reset */ 334 if ((error = bcma_dmp_write_reset(child, dinfo, 0x0))) 335 return (error); 336 337 /* Disable forced clock gating (leaving clock enabled) */ 338 error = bhnd_write_ioctl(child, 0x0, BHND_IOCTL_CLK_FORCE); 339 if (error) 340 return (error); 341 342 return (0); 343 } 344 345 static int 346 bcma_suspend_hw(device_t dev, device_t child) 347 { 348 struct bcma_devinfo *dinfo; 349 struct bhnd_core_pmu_info *pm; 350 struct bhnd_resource *r; 351 uint32_t rst; 352 int error; 353 354 if (device_get_parent(child) != dev) 355 return (EINVAL); 356 357 dinfo = device_get_ivars(child); 358 pm = dinfo->pmu_info; 359 360 /* Can't suspend the core without access to the agent registers */ 361 if ((r = dinfo->res_agent) == NULL) 362 return (ENODEV); 363 364 /* Wait for any pending reset operations to clear */ 365 if ((error = bcma_dmp_wait_reset(child, dinfo))) 366 return (error); 367 368 /* Already in reset? */ 369 rst = bhnd_bus_read_4(r, BCMA_DMP_RESETCTRL); 370 if (rst & BMCA_DMP_RC_RESET) 371 return (0); 372 373 /* Put core into reset */ 374 if ((error = bcma_dmp_write_reset(child, dinfo, BMCA_DMP_RC_RESET))) 375 return (error); 376 377 /* Clear core flags */ 378 if ((error = bhnd_write_ioctl(child, 0x0, UINT16_MAX))) 379 return (error); 380 381 /* Inform PMU that all outstanding request state should be discarded */ 382 if (pm != NULL) { 383 if ((error = BHND_PMU_CORE_RELEASE(pm->pm_pmu, pm))) 384 return (error); 385 } 386 387 return (0); 388 } 389 390 static int 391 bcma_read_config(device_t dev, device_t child, bus_size_t offset, void *value, 392 u_int width) 393 { 394 struct bcma_devinfo *dinfo; 395 struct bhnd_resource *r; 396 397 /* Must be a directly attached child core */ 398 if (device_get_parent(child) != dev) 399 return (EINVAL); 400 401 /* Fetch the agent registers */ 402 dinfo = device_get_ivars(child); 403 if ((r = dinfo->res_agent) == NULL) 404 return (ENODEV); 405 406 /* Verify bounds */ 407 if (offset > rman_get_size(r->res)) 408 return (EFAULT); 409 410 if (rman_get_size(r->res) - offset < width) 411 return (EFAULT); 412 413 switch (width) { 414 case 1: 415 *((uint8_t *)value) = bhnd_bus_read_1(r, offset); 416 return (0); 417 case 2: 418 *((uint16_t *)value) = bhnd_bus_read_2(r, offset); 419 return (0); 420 case 4: 421 *((uint32_t *)value) = bhnd_bus_read_4(r, offset); 422 return (0); 423 default: 424 return (EINVAL); 425 } 426 } 427 428 static int 429 bcma_write_config(device_t dev, device_t child, bus_size_t offset, 430 const void *value, u_int width) 431 { 432 struct bcma_devinfo *dinfo; 433 struct bhnd_resource *r; 434 435 /* Must be a directly attached child core */ 436 if (device_get_parent(child) != dev) 437 return (EINVAL); 438 439 /* Fetch the agent registers */ 440 dinfo = device_get_ivars(child); 441 if ((r = dinfo->res_agent) == NULL) 442 return (ENODEV); 443 444 /* Verify bounds */ 445 if (offset > rman_get_size(r->res)) 446 return (EFAULT); 447 448 if (rman_get_size(r->res) - offset < width) 449 return (EFAULT); 450 451 switch (width) { 452 case 1: 453 bhnd_bus_write_1(r, offset, *(const uint8_t *)value); 454 return (0); 455 case 2: 456 bhnd_bus_write_2(r, offset, *(const uint16_t *)value); 457 return (0); 458 case 4: 459 bhnd_bus_write_4(r, offset, *(const uint32_t *)value); 460 return (0); 461 default: 462 return (EINVAL); 463 } 464 } 465 466 static u_int 467 bcma_get_port_count(device_t dev, device_t child, bhnd_port_type type) 468 { 469 struct bcma_devinfo *dinfo; 470 471 /* delegate non-bus-attached devices to our parent */ 472 if (device_get_parent(child) != dev) 473 return (BHND_BUS_GET_PORT_COUNT(device_get_parent(dev), child, 474 type)); 475 476 dinfo = device_get_ivars(child); 477 switch (type) { 478 case BHND_PORT_DEVICE: 479 return (dinfo->corecfg->num_dev_ports); 480 case BHND_PORT_BRIDGE: 481 return (dinfo->corecfg->num_bridge_ports); 482 case BHND_PORT_AGENT: 483 return (dinfo->corecfg->num_wrapper_ports); 484 default: 485 device_printf(dev, "%s: unknown type (%d)\n", 486 __func__, 487 type); 488 return (0); 489 } 490 } 491 492 static u_int 493 bcma_get_region_count(device_t dev, device_t child, bhnd_port_type type, 494 u_int port_num) 495 { 496 struct bcma_devinfo *dinfo; 497 struct bcma_sport_list *ports; 498 struct bcma_sport *port; 499 500 /* delegate non-bus-attached devices to our parent */ 501 if (device_get_parent(child) != dev) 502 return (BHND_BUS_GET_REGION_COUNT(device_get_parent(dev), child, 503 type, port_num)); 504 505 dinfo = device_get_ivars(child); 506 ports = bcma_corecfg_get_port_list(dinfo->corecfg, type); 507 508 STAILQ_FOREACH(port, ports, sp_link) { 509 if (port->sp_num == port_num) 510 return (port->sp_num_maps); 511 } 512 513 /* not found */ 514 return (0); 515 } 516 517 static int 518 bcma_get_port_rid(device_t dev, device_t child, bhnd_port_type port_type, 519 u_int port_num, u_int region_num) 520 { 521 struct bcma_devinfo *dinfo; 522 struct bcma_map *map; 523 struct bcma_sport_list *ports; 524 struct bcma_sport *port; 525 526 dinfo = device_get_ivars(child); 527 ports = bcma_corecfg_get_port_list(dinfo->corecfg, port_type); 528 529 STAILQ_FOREACH(port, ports, sp_link) { 530 if (port->sp_num != port_num) 531 continue; 532 533 STAILQ_FOREACH(map, &port->sp_maps, m_link) 534 if (map->m_region_num == region_num) 535 return map->m_rid; 536 } 537 538 return -1; 539 } 540 541 static int 542 bcma_decode_port_rid(device_t dev, device_t child, int type, int rid, 543 bhnd_port_type *port_type, u_int *port_num, u_int *region_num) 544 { 545 struct bcma_devinfo *dinfo; 546 struct bcma_map *map; 547 struct bcma_sport_list *ports; 548 struct bcma_sport *port; 549 550 dinfo = device_get_ivars(child); 551 552 /* Ports are always memory mapped */ 553 if (type != SYS_RES_MEMORY) 554 return (EINVAL); 555 556 /* Starting with the most likely device list, search all three port 557 * lists */ 558 bhnd_port_type types[] = { 559 BHND_PORT_DEVICE, 560 BHND_PORT_AGENT, 561 BHND_PORT_BRIDGE 562 }; 563 564 for (int i = 0; i < nitems(types); i++) { 565 ports = bcma_corecfg_get_port_list(dinfo->corecfg, types[i]); 566 567 STAILQ_FOREACH(port, ports, sp_link) { 568 STAILQ_FOREACH(map, &port->sp_maps, m_link) { 569 if (map->m_rid != rid) 570 continue; 571 572 *port_type = port->sp_type; 573 *port_num = port->sp_num; 574 *region_num = map->m_region_num; 575 return (0); 576 } 577 } 578 } 579 580 return (ENOENT); 581 } 582 583 static int 584 bcma_get_region_addr(device_t dev, device_t child, bhnd_port_type port_type, 585 u_int port_num, u_int region_num, bhnd_addr_t *addr, bhnd_size_t *size) 586 { 587 struct bcma_devinfo *dinfo; 588 struct bcma_map *map; 589 struct bcma_sport_list *ports; 590 struct bcma_sport *port; 591 592 dinfo = device_get_ivars(child); 593 ports = bcma_corecfg_get_port_list(dinfo->corecfg, port_type); 594 595 /* Search the port list */ 596 STAILQ_FOREACH(port, ports, sp_link) { 597 if (port->sp_num != port_num) 598 continue; 599 600 STAILQ_FOREACH(map, &port->sp_maps, m_link) { 601 if (map->m_region_num != region_num) 602 continue; 603 604 /* Found! */ 605 *addr = map->m_base; 606 *size = map->m_size; 607 return (0); 608 } 609 } 610 611 return (ENOENT); 612 } 613 614 /** 615 * Default bcma(4) bus driver implementation of BHND_BUS_GET_INTR_COUNT(). 616 * 617 * This implementation consults @p child's agent register block, 618 * returning the number of interrupt output lines routed to @p child. 619 */ 620 int 621 bcma_get_intr_count(device_t dev, device_t child) 622 { 623 struct bcma_devinfo *dinfo; 624 uint32_t dmpcfg, oobw; 625 626 dinfo = device_get_ivars(child); 627 628 /* Agent block must be mapped */ 629 if (dinfo->res_agent == NULL) 630 return (0); 631 632 /* Agent must support OOB */ 633 dmpcfg = bhnd_bus_read_4(dinfo->res_agent, BCMA_DMP_CONFIG); 634 if (!BCMA_DMP_GET_FLAG(dmpcfg, BCMA_DMP_CFG_OOB)) 635 return (0); 636 637 /* Return OOB width as interrupt count */ 638 oobw = bhnd_bus_read_4(dinfo->res_agent, 639 BCMA_DMP_OOB_OUTWIDTH(BCMA_OOB_BANK_INTR)); 640 if (oobw > BCMA_OOB_NUM_SEL) { 641 device_printf(dev, "ignoring invalid OOBOUTWIDTH for core %u: " 642 "%#x\n", BCMA_DINFO_COREIDX(dinfo), oobw); 643 return (0); 644 } 645 646 return (oobw); 647 } 648 649 /** 650 * Default bcma(4) bus driver implementation of BHND_BUS_GET_CORE_IVEC(). 651 * 652 * This implementation consults @p child's agent register block, 653 * returning the interrupt output line routed to @p child, at OOB selector 654 * @p intr. 655 */ 656 int 657 bcma_get_core_ivec(device_t dev, device_t child, u_int intr, uint32_t *ivec) 658 { 659 struct bcma_devinfo *dinfo; 660 uint32_t oobsel; 661 662 dinfo = device_get_ivars(child); 663 664 /* Interrupt ID must be valid. */ 665 if (intr >= bcma_get_intr_count(dev, child)) 666 return (ENXIO); 667 668 /* Fetch OOBSEL busline value */ 669 KASSERT(dinfo->res_agent != NULL, ("missing agent registers")); 670 oobsel = bhnd_bus_read_4(dinfo->res_agent, BCMA_DMP_OOBSELOUT( 671 BCMA_OOB_BANK_INTR, intr)); 672 *ivec = (oobsel >> BCMA_DMP_OOBSEL_SHIFT(intr)) & 673 BCMA_DMP_OOBSEL_BUSLINE_MASK; 674 675 return (0); 676 } 677 678 /** 679 * Scan the device enumeration ROM table, adding all valid discovered cores to 680 * the bus. 681 * 682 * @param bus The bcma bus. 683 */ 684 int 685 bcma_add_children(device_t bus) 686 { 687 bhnd_erom_t *erom; 688 struct bcma_erom *bcma_erom; 689 const struct bhnd_chipid *cid; 690 struct bcma_corecfg *corecfg; 691 struct bcma_devinfo *dinfo; 692 device_t child; 693 int error; 694 695 cid = BHND_BUS_GET_CHIPID(bus, bus); 696 corecfg = NULL; 697 698 /* Allocate our EROM parser */ 699 erom = bhnd_erom_alloc(&bcma_erom_parser, cid, bus, BCMA_EROM_RID); 700 if (erom == NULL) 701 return (ENODEV); 702 703 /* Add all cores. */ 704 bcma_erom = (struct bcma_erom *)erom; 705 while ((error = bcma_erom_next_corecfg(bcma_erom, &corecfg)) == 0) { 706 int nintr; 707 708 /* Add the child device */ 709 child = BUS_ADD_CHILD(bus, 0, NULL, -1); 710 if (child == NULL) { 711 error = ENXIO; 712 goto cleanup; 713 } 714 715 /* Initialize device ivars */ 716 dinfo = device_get_ivars(child); 717 if ((error = bcma_init_dinfo(bus, dinfo, corecfg))) 718 goto cleanup; 719 720 /* The dinfo instance now owns the corecfg value */ 721 corecfg = NULL; 722 723 /* Allocate device's agent registers, if any */ 724 if ((error = bcma_dinfo_alloc_agent(bus, child, dinfo))) 725 goto cleanup; 726 727 /* Assign interrupts */ 728 nintr = bhnd_get_intr_count(child); 729 for (int rid = 0; rid < nintr; rid++) { 730 error = BHND_BUS_ASSIGN_INTR(bus, child, rid); 731 if (error) { 732 device_printf(bus, "failed to assign interrupt " 733 "%d to core %u: %d\n", rid, 734 BCMA_DINFO_COREIDX(dinfo), error); 735 } 736 } 737 738 /* If pins are floating or the hardware is otherwise 739 * unpopulated, the device shouldn't be used. */ 740 if (bhnd_is_hw_disabled(child)) 741 device_disable(child); 742 743 /* Issue bus callback for fully initialized child. */ 744 BHND_BUS_CHILD_ADDED(bus, child); 745 } 746 747 /* EOF while parsing cores is expected */ 748 if (error == ENOENT) 749 error = 0; 750 751 cleanup: 752 bhnd_erom_free(erom); 753 754 if (corecfg != NULL) 755 bcma_free_corecfg(corecfg); 756 757 if (error) 758 device_delete_children(bus); 759 760 return (error); 761 } 762 763 764 static device_method_t bcma_methods[] = { 765 /* Device interface */ 766 DEVMETHOD(device_probe, bcma_probe), 767 DEVMETHOD(device_attach, bcma_attach), 768 DEVMETHOD(device_detach, bcma_detach), 769 770 /* Bus interface */ 771 DEVMETHOD(bus_add_child, bcma_add_child), 772 DEVMETHOD(bus_child_deleted, bcma_child_deleted), 773 DEVMETHOD(bus_read_ivar, bcma_read_ivar), 774 DEVMETHOD(bus_write_ivar, bcma_write_ivar), 775 DEVMETHOD(bus_get_resource_list, bcma_get_resource_list), 776 777 /* BHND interface */ 778 DEVMETHOD(bhnd_bus_get_erom_class, bcma_get_erom_class), 779 DEVMETHOD(bhnd_bus_read_ioctl, bcma_read_ioctl), 780 DEVMETHOD(bhnd_bus_write_ioctl, bcma_write_ioctl), 781 DEVMETHOD(bhnd_bus_read_iost, bcma_read_iost), 782 DEVMETHOD(bhnd_bus_is_hw_suspended, bcma_is_hw_suspended), 783 DEVMETHOD(bhnd_bus_reset_hw, bcma_reset_hw), 784 DEVMETHOD(bhnd_bus_suspend_hw, bcma_suspend_hw), 785 DEVMETHOD(bhnd_bus_read_config, bcma_read_config), 786 DEVMETHOD(bhnd_bus_write_config, bcma_write_config), 787 DEVMETHOD(bhnd_bus_get_port_count, bcma_get_port_count), 788 DEVMETHOD(bhnd_bus_get_region_count, bcma_get_region_count), 789 DEVMETHOD(bhnd_bus_get_port_rid, bcma_get_port_rid), 790 DEVMETHOD(bhnd_bus_decode_port_rid, bcma_decode_port_rid), 791 DEVMETHOD(bhnd_bus_get_region_addr, bcma_get_region_addr), 792 DEVMETHOD(bhnd_bus_get_intr_count, bcma_get_intr_count), 793 DEVMETHOD(bhnd_bus_get_core_ivec, bcma_get_core_ivec), 794 795 DEVMETHOD_END 796 }; 797 798 DEFINE_CLASS_1(bhnd, bcma_driver, bcma_methods, sizeof(struct bcma_softc), bhnd_driver); 799 MODULE_VERSION(bcma, 1); 800 MODULE_DEPEND(bcma, bhnd, 1, 1, 1); 801