1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2015-2016 Landon Fuller <landon@landonf.org> 5 * Copyright (c) 2017 The FreeBSD Foundation 6 * All rights reserved. 7 * 8 * Portions of this software were developed by Landon Fuller 9 * under sponsorship from the FreeBSD Foundation. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 19 * redistribution must be conditioned upon including a substantially 20 * similar Disclaimer requirement for further binary redistribution. 21 * 22 * NO WARRANTY 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 26 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 27 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 28 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 31 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 33 * THE POSSIBILITY OF SUCH DAMAGES. 34 */ 35 36 #include <sys/cdefs.h> 37 __FBSDID("$FreeBSD$"); 38 39 #include <sys/param.h> 40 #include <sys/bus.h> 41 #include <sys/kernel.h> 42 #include <sys/malloc.h> 43 #include <sys/module.h> 44 #include <sys/systm.h> 45 46 #include <machine/bus.h> 47 48 #include <dev/bhnd/cores/pmu/bhnd_pmu.h> 49 50 #include "bcma_dmp.h" 51 52 #include "bcma_eromreg.h" 53 #include "bcma_eromvar.h" 54 55 #include "bcmavar.h" 56 57 /* RID used when allocating EROM table */ 58 #define BCMA_EROM_RID 0 59 60 static bhnd_erom_class_t * 61 bcma_get_erom_class(driver_t *driver) 62 { 63 return (&bcma_erom_parser); 64 } 65 66 int 67 bcma_probe(device_t dev) 68 { 69 device_set_desc(dev, "BCMA BHND bus"); 70 return (BUS_PROBE_DEFAULT); 71 } 72 73 /** 74 * Default bcma(4) bus driver implementation of DEVICE_ATTACH(). 75 * 76 * This implementation initializes internal bcma(4) state and performs 77 * bus enumeration, and must be called by subclassing drivers in 78 * DEVICE_ATTACH() before any other bus methods. 79 */ 80 int 81 bcma_attach(device_t dev) 82 { 83 int error; 84 85 /* Enumerate children */ 86 if ((error = bcma_add_children(dev))) { 87 device_delete_children(dev); 88 return (error); 89 } 90 91 return (0); 92 } 93 94 int 95 bcma_detach(device_t dev) 96 { 97 return (bhnd_generic_detach(dev)); 98 } 99 100 static device_t 101 bcma_add_child(device_t dev, u_int order, const char *name, int unit) 102 { 103 struct bcma_devinfo *dinfo; 104 device_t child; 105 106 child = device_add_child_ordered(dev, order, name, unit); 107 if (child == NULL) 108 return (NULL); 109 110 if ((dinfo = bcma_alloc_dinfo(dev)) == NULL) { 111 device_delete_child(dev, child); 112 return (NULL); 113 } 114 115 device_set_ivars(child, dinfo); 116 117 return (child); 118 } 119 120 static void 121 bcma_child_deleted(device_t dev, device_t child) 122 { 123 struct bcma_devinfo *dinfo; 124 125 /* Call required bhnd(4) implementation */ 126 bhnd_generic_child_deleted(dev, child); 127 128 /* Free bcma device info */ 129 if ((dinfo = device_get_ivars(child)) != NULL) 130 bcma_free_dinfo(dev, child, dinfo); 131 132 device_set_ivars(child, NULL); 133 } 134 135 static int 136 bcma_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) 137 { 138 const struct bcma_devinfo *dinfo; 139 const struct bhnd_core_info *ci; 140 141 dinfo = device_get_ivars(child); 142 ci = &dinfo->corecfg->core_info; 143 144 switch (index) { 145 case BHND_IVAR_VENDOR: 146 *result = ci->vendor; 147 return (0); 148 case BHND_IVAR_DEVICE: 149 *result = ci->device; 150 return (0); 151 case BHND_IVAR_HWREV: 152 *result = ci->hwrev; 153 return (0); 154 case BHND_IVAR_DEVICE_CLASS: 155 *result = bhnd_core_class(ci); 156 return (0); 157 case BHND_IVAR_VENDOR_NAME: 158 *result = (uintptr_t) bhnd_vendor_name(ci->vendor); 159 return (0); 160 case BHND_IVAR_DEVICE_NAME: 161 *result = (uintptr_t) bhnd_core_name(ci); 162 return (0); 163 case BHND_IVAR_CORE_INDEX: 164 *result = ci->core_idx; 165 return (0); 166 case BHND_IVAR_CORE_UNIT: 167 *result = ci->unit; 168 return (0); 169 case BHND_IVAR_PMU_INFO: 170 *result = (uintptr_t) dinfo->pmu_info; 171 return (0); 172 default: 173 return (ENOENT); 174 } 175 } 176 177 static int 178 bcma_write_ivar(device_t dev, device_t child, int index, uintptr_t value) 179 { 180 struct bcma_devinfo *dinfo; 181 182 dinfo = device_get_ivars(child); 183 184 switch (index) { 185 case BHND_IVAR_VENDOR: 186 case BHND_IVAR_DEVICE: 187 case BHND_IVAR_HWREV: 188 case BHND_IVAR_DEVICE_CLASS: 189 case BHND_IVAR_VENDOR_NAME: 190 case BHND_IVAR_DEVICE_NAME: 191 case BHND_IVAR_CORE_INDEX: 192 case BHND_IVAR_CORE_UNIT: 193 return (EINVAL); 194 case BHND_IVAR_PMU_INFO: 195 dinfo->pmu_info = (void *)value; 196 return (0); 197 default: 198 return (ENOENT); 199 } 200 } 201 202 static struct resource_list * 203 bcma_get_resource_list(device_t dev, device_t child) 204 { 205 struct bcma_devinfo *dinfo = device_get_ivars(child); 206 return (&dinfo->resources); 207 } 208 209 static int 210 bcma_read_iost(device_t dev, device_t child, uint16_t *iost) 211 { 212 uint32_t value; 213 int error; 214 215 if ((error = bhnd_read_config(child, BCMA_DMP_IOSTATUS, &value, 4))) 216 return (error); 217 218 /* Return only the bottom 16 bits */ 219 *iost = (value & BCMA_DMP_IOST_MASK); 220 return (0); 221 } 222 223 static int 224 bcma_read_ioctl(device_t dev, device_t child, uint16_t *ioctl) 225 { 226 uint32_t value; 227 int error; 228 229 if ((error = bhnd_read_config(child, BCMA_DMP_IOCTRL, &value, 4))) 230 return (error); 231 232 /* Return only the bottom 16 bits */ 233 *ioctl = (value & BCMA_DMP_IOCTRL_MASK); 234 return (0); 235 } 236 237 static int 238 bcma_write_ioctl(device_t dev, device_t child, uint16_t value, uint16_t mask) 239 { 240 struct bcma_devinfo *dinfo; 241 struct bhnd_resource *r; 242 uint32_t ioctl; 243 244 if (device_get_parent(child) != dev) 245 return (EINVAL); 246 247 dinfo = device_get_ivars(child); 248 if ((r = dinfo->res_agent) == NULL) 249 return (ENODEV); 250 251 /* Write new value */ 252 ioctl = bhnd_bus_read_4(r, BCMA_DMP_IOCTRL); 253 ioctl &= ~(BCMA_DMP_IOCTRL_MASK & mask); 254 ioctl |= (value & mask); 255 256 bhnd_bus_write_4(r, BCMA_DMP_IOCTRL, ioctl); 257 258 /* Perform read-back and wait for completion */ 259 bhnd_bus_read_4(r, BCMA_DMP_IOCTRL); 260 DELAY(10); 261 262 return (0); 263 } 264 265 static bool 266 bcma_is_hw_suspended(device_t dev, device_t child) 267 { 268 uint32_t rst; 269 uint16_t ioctl; 270 int error; 271 272 /* Is core held in RESET? */ 273 error = bhnd_read_config(child, BCMA_DMP_RESETCTRL, &rst, 4); 274 if (error) { 275 device_printf(child, "error reading HW reset state: %d\n", 276 error); 277 return (true); 278 } 279 280 if (rst & BCMA_DMP_RC_RESET) 281 return (true); 282 283 /* Is core clocked? */ 284 error = bhnd_read_ioctl(child, &ioctl); 285 if (error) { 286 device_printf(child, "error reading HW ioctl register: %d\n", 287 error); 288 return (true); 289 } 290 291 if (!(ioctl & BHND_IOCTL_CLK_EN)) 292 return (true); 293 294 return (false); 295 } 296 297 static int 298 bcma_reset_hw(device_t dev, device_t child, uint16_t ioctl, 299 uint16_t reset_ioctl) 300 { 301 struct bcma_devinfo *dinfo; 302 struct bhnd_resource *r; 303 uint16_t clkflags; 304 int error; 305 306 if (device_get_parent(child) != dev) 307 return (EINVAL); 308 309 dinfo = device_get_ivars(child); 310 311 /* We require exclusive control over BHND_IOCTL_CLK_(EN|FORCE) */ 312 clkflags = BHND_IOCTL_CLK_EN | BHND_IOCTL_CLK_FORCE; 313 if (ioctl & clkflags) 314 return (EINVAL); 315 316 /* Can't suspend the core without access to the agent registers */ 317 if ((r = dinfo->res_agent) == NULL) 318 return (ENODEV); 319 320 /* Place core into known RESET state */ 321 if ((error = bhnd_suspend_hw(child, reset_ioctl))) 322 return (error); 323 324 /* 325 * Leaving the core in reset: 326 * - Set the caller's IOCTL flags 327 * - Enable clocks 328 * - Force clock distribution to ensure propagation throughout the 329 * core. 330 */ 331 if ((error = bhnd_write_ioctl(child, ioctl | clkflags, UINT16_MAX))) 332 return (error); 333 334 /* Bring the core out of reset */ 335 if ((error = bcma_dmp_write_reset(child, dinfo, 0x0))) 336 return (error); 337 338 /* Disable forced clock gating (leaving clock enabled) */ 339 error = bhnd_write_ioctl(child, 0x0, BHND_IOCTL_CLK_FORCE); 340 if (error) 341 return (error); 342 343 return (0); 344 } 345 346 static int 347 bcma_suspend_hw(device_t dev, device_t child, uint16_t ioctl) 348 { 349 struct bcma_devinfo *dinfo; 350 struct bhnd_resource *r; 351 uint16_t clkflags; 352 int error; 353 354 if (device_get_parent(child) != dev) 355 return (EINVAL); 356 357 dinfo = device_get_ivars(child); 358 359 /* We require exclusive control over BHND_IOCTL_CLK_(EN|FORCE) */ 360 clkflags = BHND_IOCTL_CLK_EN | BHND_IOCTL_CLK_FORCE; 361 if (ioctl & clkflags) 362 return (EINVAL); 363 364 /* Can't suspend the core without access to the agent registers */ 365 if ((r = dinfo->res_agent) == NULL) 366 return (ENODEV); 367 368 /* Wait for any pending reset operations to clear */ 369 if ((error = bcma_dmp_wait_reset(child, dinfo))) 370 return (error); 371 372 /* Put core into reset (if not already in reset) */ 373 if ((error = bcma_dmp_write_reset(child, dinfo, BCMA_DMP_RC_RESET))) 374 return (error); 375 376 /* Write core flags (and clear CLK_EN/CLK_FORCE) */ 377 if ((error = bhnd_write_ioctl(child, ioctl, ~clkflags))) 378 return (error); 379 380 return (0); 381 } 382 383 static int 384 bcma_read_config(device_t dev, device_t child, bus_size_t offset, void *value, 385 u_int width) 386 { 387 struct bcma_devinfo *dinfo; 388 struct bhnd_resource *r; 389 390 /* Must be a directly attached child core */ 391 if (device_get_parent(child) != dev) 392 return (EINVAL); 393 394 /* Fetch the agent registers */ 395 dinfo = device_get_ivars(child); 396 if ((r = dinfo->res_agent) == NULL) 397 return (ENODEV); 398 399 /* Verify bounds */ 400 if (offset > rman_get_size(r->res)) 401 return (EFAULT); 402 403 if (rman_get_size(r->res) - offset < width) 404 return (EFAULT); 405 406 switch (width) { 407 case 1: 408 *((uint8_t *)value) = bhnd_bus_read_1(r, offset); 409 return (0); 410 case 2: 411 *((uint16_t *)value) = bhnd_bus_read_2(r, offset); 412 return (0); 413 case 4: 414 *((uint32_t *)value) = bhnd_bus_read_4(r, offset); 415 return (0); 416 default: 417 return (EINVAL); 418 } 419 } 420 421 static int 422 bcma_write_config(device_t dev, device_t child, bus_size_t offset, 423 const void *value, u_int width) 424 { 425 struct bcma_devinfo *dinfo; 426 struct bhnd_resource *r; 427 428 /* Must be a directly attached child core */ 429 if (device_get_parent(child) != dev) 430 return (EINVAL); 431 432 /* Fetch the agent registers */ 433 dinfo = device_get_ivars(child); 434 if ((r = dinfo->res_agent) == NULL) 435 return (ENODEV); 436 437 /* Verify bounds */ 438 if (offset > rman_get_size(r->res)) 439 return (EFAULT); 440 441 if (rman_get_size(r->res) - offset < width) 442 return (EFAULT); 443 444 switch (width) { 445 case 1: 446 bhnd_bus_write_1(r, offset, *(const uint8_t *)value); 447 return (0); 448 case 2: 449 bhnd_bus_write_2(r, offset, *(const uint16_t *)value); 450 return (0); 451 case 4: 452 bhnd_bus_write_4(r, offset, *(const uint32_t *)value); 453 return (0); 454 default: 455 return (EINVAL); 456 } 457 } 458 459 static u_int 460 bcma_get_port_count(device_t dev, device_t child, bhnd_port_type type) 461 { 462 struct bcma_devinfo *dinfo; 463 464 /* delegate non-bus-attached devices to our parent */ 465 if (device_get_parent(child) != dev) 466 return (BHND_BUS_GET_PORT_COUNT(device_get_parent(dev), child, 467 type)); 468 469 dinfo = device_get_ivars(child); 470 switch (type) { 471 case BHND_PORT_DEVICE: 472 return (dinfo->corecfg->num_dev_ports); 473 case BHND_PORT_BRIDGE: 474 return (dinfo->corecfg->num_bridge_ports); 475 case BHND_PORT_AGENT: 476 return (dinfo->corecfg->num_wrapper_ports); 477 default: 478 device_printf(dev, "%s: unknown type (%d)\n", 479 __func__, 480 type); 481 return (0); 482 } 483 } 484 485 static u_int 486 bcma_get_region_count(device_t dev, device_t child, bhnd_port_type type, 487 u_int port_num) 488 { 489 struct bcma_devinfo *dinfo; 490 struct bcma_sport_list *ports; 491 struct bcma_sport *port; 492 493 /* delegate non-bus-attached devices to our parent */ 494 if (device_get_parent(child) != dev) 495 return (BHND_BUS_GET_REGION_COUNT(device_get_parent(dev), child, 496 type, port_num)); 497 498 dinfo = device_get_ivars(child); 499 ports = bcma_corecfg_get_port_list(dinfo->corecfg, type); 500 501 STAILQ_FOREACH(port, ports, sp_link) { 502 if (port->sp_num == port_num) 503 return (port->sp_num_maps); 504 } 505 506 /* not found */ 507 return (0); 508 } 509 510 static int 511 bcma_get_port_rid(device_t dev, device_t child, bhnd_port_type port_type, 512 u_int port_num, u_int region_num) 513 { 514 struct bcma_devinfo *dinfo; 515 struct bcma_map *map; 516 struct bcma_sport_list *ports; 517 struct bcma_sport *port; 518 519 dinfo = device_get_ivars(child); 520 ports = bcma_corecfg_get_port_list(dinfo->corecfg, port_type); 521 522 STAILQ_FOREACH(port, ports, sp_link) { 523 if (port->sp_num != port_num) 524 continue; 525 526 STAILQ_FOREACH(map, &port->sp_maps, m_link) 527 if (map->m_region_num == region_num) 528 return map->m_rid; 529 } 530 531 return -1; 532 } 533 534 static int 535 bcma_decode_port_rid(device_t dev, device_t child, int type, int rid, 536 bhnd_port_type *port_type, u_int *port_num, u_int *region_num) 537 { 538 struct bcma_devinfo *dinfo; 539 struct bcma_map *map; 540 struct bcma_sport_list *ports; 541 struct bcma_sport *port; 542 543 dinfo = device_get_ivars(child); 544 545 /* Ports are always memory mapped */ 546 if (type != SYS_RES_MEMORY) 547 return (EINVAL); 548 549 /* Starting with the most likely device list, search all three port 550 * lists */ 551 bhnd_port_type types[] = { 552 BHND_PORT_DEVICE, 553 BHND_PORT_AGENT, 554 BHND_PORT_BRIDGE 555 }; 556 557 for (int i = 0; i < nitems(types); i++) { 558 ports = bcma_corecfg_get_port_list(dinfo->corecfg, types[i]); 559 560 STAILQ_FOREACH(port, ports, sp_link) { 561 STAILQ_FOREACH(map, &port->sp_maps, m_link) { 562 if (map->m_rid != rid) 563 continue; 564 565 *port_type = port->sp_type; 566 *port_num = port->sp_num; 567 *region_num = map->m_region_num; 568 return (0); 569 } 570 } 571 } 572 573 return (ENOENT); 574 } 575 576 static int 577 bcma_get_region_addr(device_t dev, device_t child, bhnd_port_type port_type, 578 u_int port_num, u_int region_num, bhnd_addr_t *addr, bhnd_size_t *size) 579 { 580 struct bcma_devinfo *dinfo; 581 struct bcma_map *map; 582 struct bcma_sport_list *ports; 583 struct bcma_sport *port; 584 585 dinfo = device_get_ivars(child); 586 ports = bcma_corecfg_get_port_list(dinfo->corecfg, port_type); 587 588 /* Search the port list */ 589 STAILQ_FOREACH(port, ports, sp_link) { 590 if (port->sp_num != port_num) 591 continue; 592 593 STAILQ_FOREACH(map, &port->sp_maps, m_link) { 594 if (map->m_region_num != region_num) 595 continue; 596 597 /* Found! */ 598 *addr = map->m_base; 599 *size = map->m_size; 600 return (0); 601 } 602 } 603 604 return (ENOENT); 605 } 606 607 /** 608 * Default bcma(4) bus driver implementation of BHND_BUS_GET_INTR_COUNT(). 609 */ 610 u_int 611 bcma_get_intr_count(device_t dev, device_t child) 612 { 613 struct bcma_devinfo *dinfo; 614 615 /* delegate non-bus-attached devices to our parent */ 616 if (device_get_parent(child) != dev) 617 return (BHND_BUS_GET_INTR_COUNT(device_get_parent(dev), child)); 618 619 dinfo = device_get_ivars(child); 620 return (dinfo->num_intrs); 621 } 622 623 /** 624 * Default bcma(4) bus driver implementation of BHND_BUS_GET_INTR_IVEC(). 625 */ 626 int 627 bcma_get_intr_ivec(device_t dev, device_t child, u_int intr, u_int *ivec) 628 { 629 struct bcma_devinfo *dinfo; 630 struct bcma_intr *desc; 631 632 /* delegate non-bus-attached devices to our parent */ 633 if (device_get_parent(child) != dev) { 634 return (BHND_BUS_GET_INTR_IVEC(device_get_parent(dev), child, 635 intr, ivec)); 636 } 637 638 dinfo = device_get_ivars(child); 639 640 STAILQ_FOREACH(desc, &dinfo->intrs, i_link) { 641 if (desc->i_sel == intr) { 642 *ivec = desc->i_busline; 643 return (0); 644 } 645 } 646 647 /* Not found */ 648 return (ENXIO); 649 } 650 651 /** 652 * Scan the device enumeration ROM table, adding all valid discovered cores to 653 * the bus. 654 * 655 * @param bus The bcma bus. 656 */ 657 int 658 bcma_add_children(device_t bus) 659 { 660 bhnd_erom_t *erom; 661 struct bcma_erom *bcma_erom; 662 struct bhnd_erom_io *eio; 663 const struct bhnd_chipid *cid; 664 struct bcma_corecfg *corecfg; 665 struct bcma_devinfo *dinfo; 666 device_t child; 667 int error; 668 669 cid = BHND_BUS_GET_CHIPID(bus, bus); 670 corecfg = NULL; 671 672 /* Allocate our EROM parser */ 673 eio = bhnd_erom_iores_new(bus, BCMA_EROM_RID); 674 erom = bhnd_erom_alloc(&bcma_erom_parser, cid, eio); 675 if (erom == NULL) { 676 bhnd_erom_io_fini(eio); 677 return (ENODEV); 678 } 679 680 /* Add all cores. */ 681 bcma_erom = (struct bcma_erom *)erom; 682 while ((error = bcma_erom_next_corecfg(bcma_erom, &corecfg)) == 0) { 683 /* Add the child device */ 684 child = BUS_ADD_CHILD(bus, 0, NULL, -1); 685 if (child == NULL) { 686 error = ENXIO; 687 goto cleanup; 688 } 689 690 /* Initialize device ivars */ 691 dinfo = device_get_ivars(child); 692 if ((error = bcma_init_dinfo(bus, child, dinfo, corecfg))) 693 goto cleanup; 694 695 /* The dinfo instance now owns the corecfg value */ 696 corecfg = NULL; 697 698 /* If pins are floating or the hardware is otherwise 699 * unpopulated, the device shouldn't be used. */ 700 if (bhnd_is_hw_disabled(child)) 701 device_disable(child); 702 703 /* Issue bus callback for fully initialized child. */ 704 BHND_BUS_CHILD_ADDED(bus, child); 705 } 706 707 /* EOF while parsing cores is expected */ 708 if (error == ENOENT) 709 error = 0; 710 711 cleanup: 712 bhnd_erom_free(erom); 713 714 if (corecfg != NULL) 715 bcma_free_corecfg(corecfg); 716 717 if (error) 718 device_delete_children(bus); 719 720 return (error); 721 } 722 723 static device_method_t bcma_methods[] = { 724 /* Device interface */ 725 DEVMETHOD(device_probe, bcma_probe), 726 DEVMETHOD(device_attach, bcma_attach), 727 DEVMETHOD(device_detach, bcma_detach), 728 729 /* Bus interface */ 730 DEVMETHOD(bus_add_child, bcma_add_child), 731 DEVMETHOD(bus_child_deleted, bcma_child_deleted), 732 DEVMETHOD(bus_read_ivar, bcma_read_ivar), 733 DEVMETHOD(bus_write_ivar, bcma_write_ivar), 734 DEVMETHOD(bus_get_resource_list, bcma_get_resource_list), 735 736 /* BHND interface */ 737 DEVMETHOD(bhnd_bus_get_erom_class, bcma_get_erom_class), 738 DEVMETHOD(bhnd_bus_read_ioctl, bcma_read_ioctl), 739 DEVMETHOD(bhnd_bus_write_ioctl, bcma_write_ioctl), 740 DEVMETHOD(bhnd_bus_read_iost, bcma_read_iost), 741 DEVMETHOD(bhnd_bus_is_hw_suspended, bcma_is_hw_suspended), 742 DEVMETHOD(bhnd_bus_reset_hw, bcma_reset_hw), 743 DEVMETHOD(bhnd_bus_suspend_hw, bcma_suspend_hw), 744 DEVMETHOD(bhnd_bus_read_config, bcma_read_config), 745 DEVMETHOD(bhnd_bus_write_config, bcma_write_config), 746 DEVMETHOD(bhnd_bus_get_port_count, bcma_get_port_count), 747 DEVMETHOD(bhnd_bus_get_region_count, bcma_get_region_count), 748 DEVMETHOD(bhnd_bus_get_port_rid, bcma_get_port_rid), 749 DEVMETHOD(bhnd_bus_decode_port_rid, bcma_decode_port_rid), 750 DEVMETHOD(bhnd_bus_get_region_addr, bcma_get_region_addr), 751 DEVMETHOD(bhnd_bus_get_intr_count, bcma_get_intr_count), 752 DEVMETHOD(bhnd_bus_get_intr_ivec, bcma_get_intr_ivec), 753 754 DEVMETHOD_END 755 }; 756 757 DEFINE_CLASS_1(bhnd, bcma_driver, bcma_methods, sizeof(struct bcma_softc), bhnd_driver); 758 MODULE_VERSION(bcma, 1); 759 MODULE_DEPEND(bcma, bhnd, 1, 1, 1); 760