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