FreeBSD/Linux Kernel Cross Reference
sys/dev/bhnd/bcma/bcma.c
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);
Cache object: 9c225a44bb5c47375c165edfa5c4b466
|