]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/bhnd/bcma/bcma.c
Upgrade our copies of clang, llvm, lld, lldb, compiler-rt and libc++ to
[FreeBSD/FreeBSD.git] / 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 bhnd_softc       *sc;
124         struct bcma_devinfo     *dinfo;
125
126         sc = device_get_softc(dev);
127
128         /* Call required bhnd(4) implementation */
129         bhnd_generic_child_deleted(dev, child);
130
131         /* Free bcma device info */
132         if ((dinfo = device_get_ivars(child)) != NULL)
133                 bcma_free_dinfo(dev, child, dinfo);
134
135         device_set_ivars(child, NULL);
136 }
137
138 static int
139 bcma_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
140 {
141         const struct bcma_devinfo *dinfo;
142         const struct bhnd_core_info *ci;
143         
144         dinfo = device_get_ivars(child);
145         ci = &dinfo->corecfg->core_info;
146         
147         switch (index) {
148         case BHND_IVAR_VENDOR:
149                 *result = ci->vendor;
150                 return (0);
151         case BHND_IVAR_DEVICE:
152                 *result = ci->device;
153                 return (0);
154         case BHND_IVAR_HWREV:
155                 *result = ci->hwrev;
156                 return (0);
157         case BHND_IVAR_DEVICE_CLASS:
158                 *result = bhnd_core_class(ci);
159                 return (0);
160         case BHND_IVAR_VENDOR_NAME:
161                 *result = (uintptr_t) bhnd_vendor_name(ci->vendor);
162                 return (0);
163         case BHND_IVAR_DEVICE_NAME:
164                 *result = (uintptr_t) bhnd_core_name(ci);
165                 return (0);
166         case BHND_IVAR_CORE_INDEX:
167                 *result = ci->core_idx;
168                 return (0);
169         case BHND_IVAR_CORE_UNIT:
170                 *result = ci->unit;
171                 return (0);
172         case BHND_IVAR_PMU_INFO:
173                 *result = (uintptr_t) dinfo->pmu_info;
174                 return (0);
175         default:
176                 return (ENOENT);
177         }
178 }
179
180 static int
181 bcma_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
182 {
183         struct bcma_devinfo *dinfo;
184
185         dinfo = device_get_ivars(child);
186
187         switch (index) {
188         case BHND_IVAR_VENDOR:
189         case BHND_IVAR_DEVICE:
190         case BHND_IVAR_HWREV:
191         case BHND_IVAR_DEVICE_CLASS:
192         case BHND_IVAR_VENDOR_NAME:
193         case BHND_IVAR_DEVICE_NAME:
194         case BHND_IVAR_CORE_INDEX:
195         case BHND_IVAR_CORE_UNIT:
196                 return (EINVAL);
197         case BHND_IVAR_PMU_INFO:
198                 dinfo->pmu_info = (void *)value;
199                 return (0);
200         default:
201                 return (ENOENT);
202         }
203 }
204
205 static struct resource_list *
206 bcma_get_resource_list(device_t dev, device_t child)
207 {
208         struct bcma_devinfo *dinfo = device_get_ivars(child);
209         return (&dinfo->resources);
210 }
211
212 static int
213 bcma_read_iost(device_t dev, device_t child, uint16_t *iost)
214 {
215         uint32_t        value;
216         int             error;
217
218         if ((error = bhnd_read_config(child, BCMA_DMP_IOSTATUS, &value, 4)))
219                 return (error);
220
221         /* Return only the bottom 16 bits */
222         *iost = (value & BCMA_DMP_IOST_MASK);
223         return (0);
224 }
225
226 static int
227 bcma_read_ioctl(device_t dev, device_t child, uint16_t *ioctl)
228 {
229         uint32_t        value;
230         int             error;
231
232         if ((error = bhnd_read_config(child, BCMA_DMP_IOCTRL, &value, 4)))
233                 return (error);
234
235         /* Return only the bottom 16 bits */
236         *ioctl = (value & BCMA_DMP_IOCTRL_MASK);
237         return (0);
238 }
239
240 static int
241 bcma_write_ioctl(device_t dev, device_t child, uint16_t value, uint16_t mask)
242 {
243         struct bcma_devinfo     *dinfo;
244         struct bhnd_resource    *r;
245         uint32_t                 ioctl;
246
247         if (device_get_parent(child) != dev)
248                 return (EINVAL);
249
250         dinfo = device_get_ivars(child);
251         if ((r = dinfo->res_agent) == NULL)
252                 return (ENODEV);
253
254         /* Write new value */
255         ioctl = bhnd_bus_read_4(r, BCMA_DMP_IOCTRL);
256         ioctl &= ~(BCMA_DMP_IOCTRL_MASK & mask);
257         ioctl |= (value & mask);
258
259         bhnd_bus_write_4(r, BCMA_DMP_IOCTRL, ioctl);
260
261         /* Perform read-back and wait for completion */
262         bhnd_bus_read_4(r, BCMA_DMP_IOCTRL);
263         DELAY(10);
264
265         return (0);
266 }
267
268 static bool
269 bcma_is_hw_suspended(device_t dev, device_t child)
270 {
271         uint32_t        rst;
272         uint16_t        ioctl;
273         int             error;
274
275         /* Is core held in RESET? */
276         error = bhnd_read_config(child, BCMA_DMP_RESETCTRL, &rst, 4);
277         if (error) {
278                 device_printf(child, "error reading HW reset state: %d\n",
279                     error);
280                 return (true);
281         }
282
283         if (rst & BCMA_DMP_RC_RESET)
284                 return (true);
285
286         /* Is core clocked? */
287         error = bhnd_read_ioctl(child, &ioctl);
288         if (error) {
289                 device_printf(child, "error reading HW ioctl register: %d\n",
290                     error);
291                 return (true);
292         }
293
294         if (!(ioctl & BHND_IOCTL_CLK_EN))
295                 return (true);
296
297         return (false);
298 }
299
300 static int
301 bcma_reset_hw(device_t dev, device_t child, uint16_t ioctl,
302     uint16_t reset_ioctl)
303 {
304         struct bcma_devinfo     *dinfo;
305         struct bhnd_resource    *r;
306         uint16_t                 clkflags;
307         int                      error;
308
309         if (device_get_parent(child) != dev)
310                 return (EINVAL);
311
312         dinfo = device_get_ivars(child);
313
314         /* We require exclusive control over BHND_IOCTL_CLK_(EN|FORCE) */
315         clkflags = BHND_IOCTL_CLK_EN | BHND_IOCTL_CLK_FORCE;
316         if (ioctl & clkflags)
317                 return (EINVAL);
318
319         /* Can't suspend the core without access to the agent registers */
320         if ((r = dinfo->res_agent) == NULL)
321                 return (ENODEV);
322
323         /* Place core into known RESET state */
324         if ((error = bhnd_suspend_hw(child, reset_ioctl)))
325                 return (error);
326
327         /*
328          * Leaving the core in reset:
329          * - Set the caller's IOCTL flags
330          * - Enable clocks
331          * - Force clock distribution to ensure propagation throughout the
332          *   core.
333          */
334         if ((error = bhnd_write_ioctl(child, ioctl | clkflags, UINT16_MAX)))
335                 return (error);
336
337         /* Bring the core out of reset */
338         if ((error = bcma_dmp_write_reset(child, dinfo, 0x0)))
339                 return (error);
340
341         /* Disable forced clock gating (leaving clock enabled) */
342         error = bhnd_write_ioctl(child, 0x0, BHND_IOCTL_CLK_FORCE);
343         if (error)
344                 return (error);
345
346         return (0);
347 }
348
349 static int
350 bcma_suspend_hw(device_t dev, device_t child, uint16_t ioctl)
351 {
352         struct bcma_devinfo     *dinfo;
353         struct bhnd_resource    *r;
354         uint16_t                 clkflags;
355         int                      error;
356
357         if (device_get_parent(child) != dev)
358                 return (EINVAL);
359
360         dinfo = device_get_ivars(child);
361
362         /* We require exclusive control over BHND_IOCTL_CLK_(EN|FORCE) */
363         clkflags = BHND_IOCTL_CLK_EN | BHND_IOCTL_CLK_FORCE;
364         if (ioctl & clkflags)
365                 return (EINVAL);
366
367         /* Can't suspend the core without access to the agent registers */
368         if ((r = dinfo->res_agent) == NULL)
369                 return (ENODEV);
370
371         /* Wait for any pending reset operations to clear */
372         if ((error = bcma_dmp_wait_reset(child, dinfo)))
373                 return (error);
374
375         /* Put core into reset (if not already in reset) */
376         if ((error = bcma_dmp_write_reset(child, dinfo, BCMA_DMP_RC_RESET)))
377                 return (error);
378
379         /* Write core flags (and clear CLK_EN/CLK_FORCE) */
380         if ((error = bhnd_write_ioctl(child, ioctl, ~clkflags)))
381                 return (error);
382
383         return (0);
384 }
385
386 static int
387 bcma_read_config(device_t dev, device_t child, bus_size_t offset, void *value,
388     u_int width)
389 {
390         struct bcma_devinfo     *dinfo;
391         struct bhnd_resource    *r;
392
393         /* Must be a directly attached child core */
394         if (device_get_parent(child) != dev)
395                 return (EINVAL);
396
397         /* Fetch the agent registers */
398         dinfo = device_get_ivars(child);
399         if ((r = dinfo->res_agent) == NULL)
400                 return (ENODEV);
401
402         /* Verify bounds */
403         if (offset > rman_get_size(r->res))
404                 return (EFAULT);
405
406         if (rman_get_size(r->res) - offset < width)
407                 return (EFAULT);
408
409         switch (width) {
410         case 1:
411                 *((uint8_t *)value) = bhnd_bus_read_1(r, offset);
412                 return (0);
413         case 2:
414                 *((uint16_t *)value) = bhnd_bus_read_2(r, offset);
415                 return (0);
416         case 4:
417                 *((uint32_t *)value) = bhnd_bus_read_4(r, offset);
418                 return (0);
419         default:
420                 return (EINVAL);
421         }
422 }
423
424 static int
425 bcma_write_config(device_t dev, device_t child, bus_size_t offset,
426     const void *value, u_int width)
427 {
428         struct bcma_devinfo     *dinfo;
429         struct bhnd_resource    *r;
430
431         /* Must be a directly attached child core */
432         if (device_get_parent(child) != dev)
433                 return (EINVAL);
434
435         /* Fetch the agent registers */
436         dinfo = device_get_ivars(child);
437         if ((r = dinfo->res_agent) == NULL)
438                 return (ENODEV);
439
440         /* Verify bounds */
441         if (offset > rman_get_size(r->res))
442                 return (EFAULT);
443
444         if (rman_get_size(r->res) - offset < width)
445                 return (EFAULT);
446
447         switch (width) {
448         case 1:
449                 bhnd_bus_write_1(r, offset, *(const uint8_t *)value);
450                 return (0);
451         case 2:
452                 bhnd_bus_write_2(r, offset, *(const uint16_t *)value);
453                 return (0);
454         case 4:
455                 bhnd_bus_write_4(r, offset, *(const uint32_t *)value);
456                 return (0);
457         default:
458                 return (EINVAL);
459         }
460 }
461
462 static u_int
463 bcma_get_port_count(device_t dev, device_t child, bhnd_port_type type)
464 {
465         struct bcma_devinfo *dinfo;
466
467         /* delegate non-bus-attached devices to our parent */
468         if (device_get_parent(child) != dev)
469                 return (BHND_BUS_GET_PORT_COUNT(device_get_parent(dev), child,
470                     type));
471
472         dinfo = device_get_ivars(child);
473         switch (type) {
474         case BHND_PORT_DEVICE:
475                 return (dinfo->corecfg->num_dev_ports);
476         case BHND_PORT_BRIDGE:
477                 return (dinfo->corecfg->num_bridge_ports);
478         case BHND_PORT_AGENT:
479                 return (dinfo->corecfg->num_wrapper_ports);
480         default:
481                 device_printf(dev, "%s: unknown type (%d)\n",
482                     __func__,
483                     type);
484                 return (0);
485         }
486 }
487
488 static u_int
489 bcma_get_region_count(device_t dev, device_t child, bhnd_port_type type,
490     u_int port_num)
491 {
492         struct bcma_devinfo     *dinfo;
493         struct bcma_sport_list  *ports;
494         struct bcma_sport       *port;
495
496         /* delegate non-bus-attached devices to our parent */
497         if (device_get_parent(child) != dev)
498                 return (BHND_BUS_GET_REGION_COUNT(device_get_parent(dev), child,
499                     type, port_num));
500
501         dinfo = device_get_ivars(child);
502         ports = bcma_corecfg_get_port_list(dinfo->corecfg, type);
503         
504         STAILQ_FOREACH(port, ports, sp_link) {
505                 if (port->sp_num == port_num)
506                         return (port->sp_num_maps);
507         }
508
509         /* not found */
510         return (0);
511 }
512
513 static int
514 bcma_get_port_rid(device_t dev, device_t child, bhnd_port_type port_type,
515     u_int port_num, u_int region_num)
516 {
517         struct bcma_devinfo     *dinfo;
518         struct bcma_map         *map;
519         struct bcma_sport_list  *ports;
520         struct bcma_sport       *port;
521         
522         dinfo = device_get_ivars(child);
523         ports = bcma_corecfg_get_port_list(dinfo->corecfg, port_type);
524
525         STAILQ_FOREACH(port, ports, sp_link) {
526                 if (port->sp_num != port_num)
527                         continue;
528
529                 STAILQ_FOREACH(map, &port->sp_maps, m_link)
530                         if (map->m_region_num == region_num)
531                                 return map->m_rid;
532         }
533
534         return -1;
535 }
536
537 static int
538 bcma_decode_port_rid(device_t dev, device_t child, int type, int rid,
539     bhnd_port_type *port_type, u_int *port_num, u_int *region_num)
540 {
541         struct bcma_devinfo     *dinfo;
542         struct bcma_map         *map;
543         struct bcma_sport_list  *ports;
544         struct bcma_sport       *port;
545
546         dinfo = device_get_ivars(child);
547
548         /* Ports are always memory mapped */
549         if (type != SYS_RES_MEMORY)
550                 return (EINVAL);
551
552         /* Starting with the most likely device list, search all three port
553          * lists */
554         bhnd_port_type types[] = {
555             BHND_PORT_DEVICE, 
556             BHND_PORT_AGENT,
557             BHND_PORT_BRIDGE
558         };
559
560         for (int i = 0; i < nitems(types); i++) {
561                 ports = bcma_corecfg_get_port_list(dinfo->corecfg, types[i]);
562
563                 STAILQ_FOREACH(port, ports, sp_link) {
564                         STAILQ_FOREACH(map, &port->sp_maps, m_link) {
565                                 if (map->m_rid != rid)
566                                         continue;
567
568                                 *port_type = port->sp_type;
569                                 *port_num = port->sp_num;
570                                 *region_num = map->m_region_num;
571                                 return (0);
572                         }
573                 }
574         }
575
576         return (ENOENT);
577 }
578
579 static int
580 bcma_get_region_addr(device_t dev, device_t child, bhnd_port_type port_type,
581     u_int port_num, u_int region_num, bhnd_addr_t *addr, bhnd_size_t *size)
582 {
583         struct bcma_devinfo     *dinfo;
584         struct bcma_map         *map;
585         struct bcma_sport_list  *ports;
586         struct bcma_sport       *port;
587         
588         dinfo = device_get_ivars(child);
589         ports = bcma_corecfg_get_port_list(dinfo->corecfg, port_type);
590
591         /* Search the port list */
592         STAILQ_FOREACH(port, ports, sp_link) {
593                 if (port->sp_num != port_num)
594                         continue;
595
596                 STAILQ_FOREACH(map, &port->sp_maps, m_link) {
597                         if (map->m_region_num != region_num)
598                                 continue;
599
600                         /* Found! */
601                         *addr = map->m_base;
602                         *size = map->m_size;
603                         return (0);
604                 }
605         }
606
607         return (ENOENT);
608 }
609
610 /**
611  * Default bcma(4) bus driver implementation of BHND_BUS_GET_INTR_COUNT().
612  */
613 u_int
614 bcma_get_intr_count(device_t dev, device_t child)
615 {
616         struct bcma_devinfo *dinfo;
617
618         /* delegate non-bus-attached devices to our parent */
619         if (device_get_parent(child) != dev)
620                 return (BHND_BUS_GET_INTR_COUNT(device_get_parent(dev), child));
621
622         dinfo = device_get_ivars(child);
623         return (dinfo->num_intrs);
624 }
625
626 /**
627  * Default bcma(4) bus driver implementation of BHND_BUS_GET_INTR_IVEC().
628  */
629 int
630 bcma_get_intr_ivec(device_t dev, device_t child, u_int intr, u_int *ivec)
631 {
632         struct bcma_devinfo     *dinfo;
633         struct bcma_intr        *desc;
634
635         /* delegate non-bus-attached devices to our parent */
636         if (device_get_parent(child) != dev) {
637                 return (BHND_BUS_GET_INTR_IVEC(device_get_parent(dev), child,
638                     intr, ivec));
639         }
640
641         dinfo = device_get_ivars(child);
642
643         STAILQ_FOREACH(desc, &dinfo->intrs, i_link) {
644                 if (desc->i_sel == intr) {
645                         *ivec = desc->i_busline;
646                         return (0);
647                 }
648         }
649
650         /* Not found */
651         return (ENXIO);
652 }
653
654 /**
655  * Scan the device enumeration ROM table, adding all valid discovered cores to
656  * the bus.
657  * 
658  * @param bus The bcma bus.
659  */
660 int
661 bcma_add_children(device_t bus)
662 {
663         bhnd_erom_t                     *erom;
664         struct bcma_erom                *bcma_erom;
665         struct bhnd_erom_io             *eio;
666         const struct bhnd_chipid        *cid;
667         struct bcma_corecfg             *corecfg;
668         struct bcma_devinfo             *dinfo;
669         device_t                         child;
670         int                              error;
671
672         cid = BHND_BUS_GET_CHIPID(bus, bus);
673         corecfg = NULL;
674
675         /* Allocate our EROM parser */
676         eio = bhnd_erom_iores_new(bus, BCMA_EROM_RID);
677         erom = bhnd_erom_alloc(&bcma_erom_parser, cid, eio);
678         if (erom == NULL) {
679                 bhnd_erom_io_fini(eio);
680                 return (ENODEV);
681         }
682
683         /* Add all cores. */
684         bcma_erom = (struct bcma_erom *)erom;
685         while ((error = bcma_erom_next_corecfg(bcma_erom, &corecfg)) == 0) {
686                 /* Add the child device */
687                 child = BUS_ADD_CHILD(bus, 0, NULL, -1);
688                 if (child == NULL) {
689                         error = ENXIO;
690                         goto cleanup;
691                 }
692
693                 /* Initialize device ivars */
694                 dinfo = device_get_ivars(child);
695                 if ((error = bcma_init_dinfo(bus, child, dinfo, corecfg)))
696                         goto cleanup;
697
698                 /* The dinfo instance now owns the corecfg value */
699                 corecfg = NULL;
700
701                 /* If pins are floating or the hardware is otherwise
702                  * unpopulated, the device shouldn't be used. */
703                 if (bhnd_is_hw_disabled(child))
704                         device_disable(child);
705
706                 /* Issue bus callback for fully initialized child. */
707                 BHND_BUS_CHILD_ADDED(bus, child);
708         }
709
710         /* EOF while parsing cores is expected */
711         if (error == ENOENT)
712                 error = 0;
713         
714 cleanup:
715         bhnd_erom_free(erom);
716
717         if (corecfg != NULL)
718                 bcma_free_corecfg(corecfg);
719
720         if (error)
721                 device_delete_children(bus);
722
723         return (error);
724 }
725
726
727 static device_method_t bcma_methods[] = {
728         /* Device interface */
729         DEVMETHOD(device_probe,                 bcma_probe),
730         DEVMETHOD(device_attach,                bcma_attach),
731         DEVMETHOD(device_detach,                bcma_detach),
732         
733         /* Bus interface */
734         DEVMETHOD(bus_add_child,                bcma_add_child),
735         DEVMETHOD(bus_child_deleted,            bcma_child_deleted),
736         DEVMETHOD(bus_read_ivar,                bcma_read_ivar),
737         DEVMETHOD(bus_write_ivar,               bcma_write_ivar),
738         DEVMETHOD(bus_get_resource_list,        bcma_get_resource_list),
739
740         /* BHND interface */
741         DEVMETHOD(bhnd_bus_get_erom_class,      bcma_get_erom_class),
742         DEVMETHOD(bhnd_bus_read_ioctl,          bcma_read_ioctl),
743         DEVMETHOD(bhnd_bus_write_ioctl,         bcma_write_ioctl),
744         DEVMETHOD(bhnd_bus_read_iost,           bcma_read_iost),
745         DEVMETHOD(bhnd_bus_is_hw_suspended,     bcma_is_hw_suspended),
746         DEVMETHOD(bhnd_bus_reset_hw,            bcma_reset_hw),
747         DEVMETHOD(bhnd_bus_suspend_hw,          bcma_suspend_hw),
748         DEVMETHOD(bhnd_bus_read_config,         bcma_read_config),
749         DEVMETHOD(bhnd_bus_write_config,        bcma_write_config),
750         DEVMETHOD(bhnd_bus_get_port_count,      bcma_get_port_count),
751         DEVMETHOD(bhnd_bus_get_region_count,    bcma_get_region_count),
752         DEVMETHOD(bhnd_bus_get_port_rid,        bcma_get_port_rid),
753         DEVMETHOD(bhnd_bus_decode_port_rid,     bcma_decode_port_rid),
754         DEVMETHOD(bhnd_bus_get_region_addr,     bcma_get_region_addr),
755         DEVMETHOD(bhnd_bus_get_intr_count,      bcma_get_intr_count),
756         DEVMETHOD(bhnd_bus_get_intr_ivec,       bcma_get_intr_ivec),
757
758         DEVMETHOD_END
759 };
760
761 DEFINE_CLASS_1(bhnd, bcma_driver, bcma_methods, sizeof(struct bcma_softc), bhnd_driver);
762 MODULE_VERSION(bcma, 1);
763 MODULE_DEPEND(bcma, bhnd, 1, 1, 1);