xref: /freebsd/sys/dev/bhnd/bhnd.c (revision 243e928310d073338c5ec089f0dce238a80b9866)
1 /*-
2  * Copyright (c) 2015 Landon Fuller <landon@landonf.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer,
10  *    without modification.
11  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13  *    redistribution must be conditioned upon including a substantially
14  *    similar Disclaimer requirement for further binary redistribution.
15  *
16  * NO WARRANTY
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27  * THE POSSIBILITY OF SUCH DAMAGES.
28  */
29 
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32 
33 /*
34  * Broadcom Home Networking Division (HND) Bus Driver.
35  *
36  * The Broadcom HND family of devices consists of both SoCs and host-connected
37  * networking chipsets containing a common family of Broadcom IP cores,
38  * including an integrated MIPS and/or ARM cores.
39  *
40  * HND devices expose a nearly identical interface whether accessible over a
41  * native SoC interconnect, or when connected via a host interface such as
42  * PCIe. As a result, the majority of hardware support code should be re-usable
43  * across host drivers for HND networking chipsets, as well as FreeBSD support
44  * for Broadcom MIPS/ARM HND SoCs.
45  *
46  * Earlier HND models used the siba(4) on-chip interconnect, while later models
47  * use bcma(4); the programming model is almost entirely independent
48  * of the actual underlying interconect.
49  */
50 
51 #include <sys/param.h>
52 #include <sys/kernel.h>
53 #include <sys/bus.h>
54 #include <sys/module.h>
55 #include <sys/systm.h>
56 
57 #include <machine/bus.h>
58 #include <sys/rman.h>
59 #include <machine/resource.h>
60 
61 #include "bhnd.h"
62 #include "bhndvar.h"
63 
64 MALLOC_DEFINE(M_BHND, "bhnd", "bhnd bus data structures");
65 
66 /**
67  * bhnd_generic_probe_nomatch() reporting configuration.
68  */
69 static const struct bhnd_nomatch {
70 	uint16_t	vendor;		/**< core designer */
71 	uint16_t	device;		/**< core id */
72 	bool		if_verbose;	/**< print when bootverbose is set. */
73 } bhnd_nomatch_table[] = {
74 	{ BHND_MFGID_ARM,	BHND_COREID_OOB_ROUTER,		true	},
75 	{ BHND_MFGID_ARM,	BHND_COREID_EROM,		true	},
76 	{ BHND_MFGID_ARM,	BHND_COREID_PL301,		true	},
77 	{ BHND_MFGID_ARM,	BHND_COREID_APB_BRIDGE,		true	},
78 	{ BHND_MFGID_ARM,	BHND_COREID_AXI_UNMAPPED,	false	},
79 
80 	{ BHND_MFGID_INVALID,	BHND_COREID_INVALID,		false	}
81 };
82 
83 static int	compare_ascending_probe_order(const void *lhs,
84 		    const void *rhs);
85 static int	compare_descending_probe_order(const void *lhs,
86 		    const void *rhs);
87 
88 /**
89  * Default bhnd(4) bus driver implementation of DEVICE_ATTACH().
90  *
91  * This implementation calls device_probe_and_attach() for each of the device's
92  * children, in bhnd probe order.
93  */
94 int
95 bhnd_generic_attach(device_t dev)
96 {
97 	device_t	*devs;
98 	int		 ndevs;
99 	int		 error;
100 
101 	if (device_is_attached(dev))
102 		return (EBUSY);
103 
104 	if ((error = device_get_children(dev, &devs, &ndevs)))
105 		return (error);
106 
107 	qsort(devs, ndevs, sizeof(*devs), compare_ascending_probe_order);
108 	for (int i = 0; i < ndevs; i++) {
109 		device_t child = devs[i];
110 		device_probe_and_attach(child);
111 	}
112 
113 	free(devs, M_TEMP);
114 	return (0);
115 }
116 
117 /**
118  * Default bhnd(4) bus driver implementation of DEVICE_DETACH().
119  *
120  * This implementation calls device_detach() for each of the device's
121  * children, in reverse bhnd probe order, terminating if any call to
122  * device_detach() fails.
123  */
124 int
125 bhnd_generic_detach(device_t dev)
126 {
127 	device_t	*devs;
128 	int		 ndevs;
129 	int		 error;
130 
131 	if (!device_is_attached(dev))
132 		return (EBUSY);
133 
134 	if ((error = device_get_children(dev, &devs, &ndevs)))
135 		return (error);
136 
137 	/* Detach in the reverse of attach order */
138 	qsort(devs, ndevs, sizeof(*devs), compare_descending_probe_order);
139 	for (int i = 0; i < ndevs; i++) {
140 		device_t child = devs[i];
141 
142 		/* Terminate on first error */
143 		if ((error = device_detach(child)))
144 			goto cleanup;
145 	}
146 
147 cleanup:
148 	free(devs, M_TEMP);
149 	return (error);
150 }
151 
152 /**
153  * Default bhnd(4) bus driver implementation of DEVICE_SHUTDOWN().
154  *
155  * This implementation calls device_shutdown() for each of the device's
156  * children, in reverse bhnd probe order, terminating if any call to
157  * device_shutdown() fails.
158  */
159 int
160 bhnd_generic_shutdown(device_t dev)
161 {
162 	device_t	*devs;
163 	int		 ndevs;
164 	int		 error;
165 
166 	if (!device_is_attached(dev))
167 		return (EBUSY);
168 
169 	if ((error = device_get_children(dev, &devs, &ndevs)))
170 		return (error);
171 
172 	/* Shutdown in the reverse of attach order */
173 	qsort(devs, ndevs, sizeof(*devs), compare_descending_probe_order);
174 	for (int i = 0; i < ndevs; i++) {
175 		device_t child = devs[i];
176 
177 		/* Terminate on first error */
178 		if ((error = device_shutdown(child)))
179 			goto cleanup;
180 	}
181 
182 cleanup:
183 	free(devs, M_TEMP);
184 	return (error);
185 }
186 
187 /**
188  * Default bhnd(4) bus driver implementation of DEVICE_RESUME().
189  *
190  * This implementation calls BUS_RESUME_CHILD() for each of the device's
191  * children in bhnd probe order, terminating if any call to BUS_RESUME_CHILD()
192  * fails.
193  */
194 int
195 bhnd_generic_resume(device_t dev)
196 {
197 	device_t	*devs;
198 	int		 ndevs;
199 	int		 error;
200 
201 	if (!device_is_attached(dev))
202 		return (EBUSY);
203 
204 	if ((error = device_get_children(dev, &devs, &ndevs)))
205 		return (error);
206 
207 	qsort(devs, ndevs, sizeof(*devs), compare_ascending_probe_order);
208 	for (int i = 0; i < ndevs; i++) {
209 		device_t child = devs[i];
210 
211 		/* Terminate on first error */
212 		if ((error = BUS_RESUME_CHILD(device_get_parent(child), child)))
213 			goto cleanup;
214 	}
215 
216 cleanup:
217 	free(devs, M_TEMP);
218 	return (error);
219 }
220 
221 /**
222  * Default bhnd(4) bus driver implementation of DEVICE_SUSPEND().
223  *
224  * This implementation calls BUS_SUSPEND_CHILD() for each of the device's
225  * children in reverse bhnd probe order. If any call to BUS_SUSPEND_CHILD()
226  * fails, the suspend operation is terminated and any devices that were
227  * suspended are resumed immediately by calling their BUS_RESUME_CHILD()
228  * methods.
229  */
230 int
231 bhnd_generic_suspend(device_t dev)
232 {
233 	device_t	*devs;
234 	int		 ndevs;
235 	int		 error;
236 
237 	if (!device_is_attached(dev))
238 		return (EBUSY);
239 
240 	if ((error = device_get_children(dev, &devs, &ndevs)))
241 		return (error);
242 
243 	/* Suspend in the reverse of attach order */
244 	qsort(devs, ndevs, sizeof(*devs), compare_descending_probe_order);
245 	for (int i = 0; i < ndevs; i++) {
246 		device_t child = devs[i];
247 		error = BUS_SUSPEND_CHILD(device_get_parent(child), child);
248 
249 		/* On error, resume suspended devices and then terminate */
250 		if (error) {
251 			for (int j = 0; j < i; j++) {
252 				BUS_RESUME_CHILD(device_get_parent(devs[j]),
253 				    devs[j]);
254 			}
255 
256 			goto cleanup;
257 		}
258 	}
259 
260 cleanup:
261 	free(devs, M_TEMP);
262 	return (error);
263 }
264 
265 /*
266  * Ascending comparison of bhnd device's probe order.
267  */
268 static int
269 compare_ascending_probe_order(const void *lhs, const void *rhs)
270 {
271 	device_t	ldev, rdev;
272 	int		lorder, rorder;
273 
274 	ldev = (*(const device_t *) lhs);
275 	rdev = (*(const device_t *) rhs);
276 
277 	lorder = BHND_BUS_GET_PROBE_ORDER(device_get_parent(ldev), ldev);
278 	rorder = BHND_BUS_GET_PROBE_ORDER(device_get_parent(rdev), rdev);
279 
280 	if (lorder < rorder) {
281 		return (-1);
282 	} else if (lorder > rorder) {
283 		return (1);
284 	} else {
285 		return (0);
286 	}
287 }
288 
289 /*
290  * Descending comparison of bhnd device's probe order.
291  */
292 static int
293 compare_descending_probe_order(const void *lhs, const void *rhs)
294 {
295 	return (compare_ascending_probe_order(rhs, lhs));
296 }
297 
298 /**
299  * Default bhnd(4) bus driver implementation of BHND_BUS_GET_PROBE_ORDER().
300  *
301  * This implementation determines probe ordering based on the device's class
302  * and other properties, including whether the device is serving as a host
303  * bridge.
304  */
305 int
306 bhnd_generic_get_probe_order(device_t dev, device_t child)
307 {
308 	switch (bhnd_get_class(child)) {
309 	case BHND_DEVCLASS_CC:
310 		/* Must be early enough to provide NVRAM access to the
311 		 * host bridge */
312 		return (BHND_PROBE_ROOT + BHND_PROBE_ORDER_FIRST);
313 
314 	case BHND_DEVCLASS_CC_B:
315 		/* fall through */
316 	case BHND_DEVCLASS_PMU:
317 		return (BHND_PROBE_BUS + BHND_PROBE_ORDER_EARLY);
318 
319 	case BHND_DEVCLASS_SOC_ROUTER:
320 		return (BHND_PROBE_BUS + BHND_PROBE_ORDER_LATE);
321 
322 	case BHND_DEVCLASS_SOC_BRIDGE:
323 		return (BHND_PROBE_BUS + BHND_PROBE_ORDER_LAST);
324 
325 	case BHND_DEVCLASS_CPU:
326 		return (BHND_PROBE_CPU + BHND_PROBE_ORDER_FIRST);
327 
328 	case BHND_DEVCLASS_RAM:
329 		/* fall through */
330 	case BHND_DEVCLASS_MEMC:
331 		return (BHND_PROBE_CPU + BHND_PROBE_ORDER_EARLY);
332 
333 	case BHND_DEVCLASS_NVRAM:
334 		return (BHND_PROBE_RESOURCE + BHND_PROBE_ORDER_EARLY);
335 
336 	case BHND_DEVCLASS_PCI:
337 	case BHND_DEVCLASS_PCIE:
338 	case BHND_DEVCLASS_PCCARD:
339 	case BHND_DEVCLASS_ENET:
340 	case BHND_DEVCLASS_ENET_MAC:
341 	case BHND_DEVCLASS_ENET_PHY:
342 	case BHND_DEVCLASS_WLAN:
343 	case BHND_DEVCLASS_WLAN_MAC:
344 	case BHND_DEVCLASS_WLAN_PHY:
345 	case BHND_DEVCLASS_EROM:
346 	case BHND_DEVCLASS_OTHER:
347 	case BHND_DEVCLASS_INVALID:
348 		if (bhnd_find_hostb_device(dev) == child)
349 			return (BHND_PROBE_ROOT + BHND_PROBE_ORDER_EARLY);
350 
351 		return (BHND_PROBE_DEFAULT);
352 	default:
353 		return (BHND_PROBE_DEFAULT);
354 	}
355 }
356 
357 /**
358  * Default bhnd(4) bus driver implementation of BHND_BUS_IS_REGION_VALID().
359  *
360  * This implementation assumes that port and region numbers are 0-indexed and
361  * are allocated non-sparsely, using BHND_BUS_GET_PORT_COUNT() and
362  * BHND_BUS_GET_REGION_COUNT() to determine if @p port and @p region fall
363  * within the defined range.
364  */
365 static bool
366 bhnd_generic_is_region_valid(device_t dev, device_t child,
367     bhnd_port_type type, u_int port, u_int region)
368 {
369 	if (port >= bhnd_get_port_count(child, type))
370 		return (false);
371 
372 	if (region >= bhnd_get_region_count(child, type, port))
373 		return (false);
374 
375 	return (true);
376 }
377 
378 /**
379  * Default bhnd(4) bus driver implementation of BUS_PRINT_CHILD().
380  *
381  * This implementation requests the device's struct resource_list via
382  * BUS_GET_RESOURCE_LIST.
383  */
384 int
385 bhnd_generic_print_child(device_t dev, device_t child)
386 {
387 	struct resource_list	*rl;
388 	int			retval = 0;
389 
390 	retval += bus_print_child_header(dev, child);
391 
392 	rl = BUS_GET_RESOURCE_LIST(dev, child);
393 	if (rl != NULL) {
394 		retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY,
395 		    "%#jx");
396 	}
397 
398 	retval += printf(" at core %u", bhnd_get_core_index(child));
399 
400 	retval += bus_print_child_domain(dev, child);
401 	retval += bus_print_child_footer(dev, child);
402 
403 	return (retval);
404 }
405 
406 /**
407  * Default bhnd(4) bus driver implementation of BUS_PROBE_NOMATCH().
408  *
409  * This implementation requests the device's struct resource_list via
410  * BUS_GET_RESOURCE_LIST.
411  */
412 void
413 bhnd_generic_probe_nomatch(device_t dev, device_t child)
414 {
415 	struct resource_list		*rl;
416 	const struct bhnd_nomatch	*nm;
417 	bool				 report;
418 
419 	/* Fetch reporting configuration for this device */
420 	report = true;
421 	for (nm = bhnd_nomatch_table; nm->device != BHND_COREID_INVALID; nm++) {
422 		if (nm->vendor != bhnd_get_vendor(child))
423 			continue;
424 
425 		if (nm->device != bhnd_get_device(child))
426 			continue;
427 
428 		report = false;
429 		if (bootverbose && nm->if_verbose)
430 			report = true;
431 		break;
432 	}
433 
434 	if (!report)
435 		return;
436 
437 	/* Print the non-matched device info */
438 	device_printf(dev, "<%s %s>", bhnd_get_vendor_name(child),
439 		bhnd_get_device_name(child));
440 
441 	rl = BUS_GET_RESOURCE_LIST(dev, child);
442 	if (rl != NULL)
443 		resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
444 
445 	printf(" at core %u (no driver attached)\n",
446 	    bhnd_get_core_index(child));
447 }
448 
449 /**
450  * Default implementation of BUS_CHILD_PNPINFO_STR().
451  */
452 static int
453 bhnd_child_pnpinfo_str(device_t dev, device_t child, char *buf,
454     size_t buflen)
455 {
456 	if (device_get_parent(child) != dev) {
457 		return (BUS_CHILD_PNPINFO_STR(device_get_parent(dev), child,
458 		    buf, buflen));
459 	}
460 
461 	snprintf(buf, buflen, "vendor=0x%hx device=0x%hx rev=0x%hhx",
462 	    bhnd_get_vendor(child), bhnd_get_device(child),
463 	    bhnd_get_hwrev(child));
464 
465 	return (0);
466 }
467 
468 /**
469  * Default implementation of BUS_CHILD_LOCATION_STR().
470  */
471 static int
472 bhnd_child_location_str(device_t dev, device_t child, char *buf,
473     size_t buflen)
474 {
475 	bhnd_addr_t	addr;
476 	bhnd_size_t	size;
477 
478 	if (device_get_parent(child) != dev) {
479 		return (BUS_CHILD_LOCATION_STR(device_get_parent(dev), child,
480 		    buf, buflen));
481 	}
482 
483 
484 	if (bhnd_get_region_addr(child, BHND_PORT_DEVICE, 0, 0, &addr, &size)) {
485 		/* No device default port/region */
486 		if (buflen > 0)
487 			*buf = '\0';
488 		return (0);
489 	}
490 
491 	snprintf(buf, buflen, "port0.0=0x%llx", (unsigned long long) addr);
492 	return (0);
493 }
494 
495 /**
496  * Helper function for implementing BUS_SUSPEND_CHILD().
497  *
498  * TODO: Power management
499  *
500  * If @p child is not a direct child of @p dev, suspension is delegated to
501  * the @p dev parent.
502  */
503 int
504 bhnd_generic_suspend_child(device_t dev, device_t child)
505 {
506 	if (device_get_parent(child) != dev)
507 		BUS_SUSPEND_CHILD(device_get_parent(dev), child);
508 
509 	return bus_generic_suspend_child(dev, child);
510 }
511 
512 /**
513  * Helper function for implementing BUS_RESUME_CHILD().
514  *
515  * TODO: Power management
516  *
517  * If @p child is not a direct child of @p dev, suspension is delegated to
518  * the @p dev parent.
519  */
520 int
521 bhnd_generic_resume_child(device_t dev, device_t child)
522 {
523 	if (device_get_parent(child) != dev)
524 		BUS_RESUME_CHILD(device_get_parent(dev), child);
525 
526 	return bus_generic_resume_child(dev, child);
527 }
528 
529 /*
530  * Delegate all indirect I/O to the parent device. When inherited by
531  * non-bridged bus implementations, resources will never be marked as
532  * indirect, and these methods will never be called.
533  */
534 #define	BHND_IO_READ(_type, _name, _method)				\
535 static _type								\
536 bhnd_read_ ## _name (device_t dev, device_t child,			\
537     struct bhnd_resource *r, bus_size_t offset)				\
538 {									\
539 	return (BHND_BUS_READ_ ## _method(				\
540 		    device_get_parent(dev), child, r, offset));		\
541 }
542 
543 #define	BHND_IO_WRITE(_type, _name, _method)				\
544 static void								\
545 bhnd_write_ ## _name (device_t dev, device_t child,			\
546     struct bhnd_resource *r, bus_size_t offset, _type value)		\
547 {									\
548 	return (BHND_BUS_WRITE_ ## _method(				\
549 		    device_get_parent(dev), child, r, offset,		\
550 		    value));	\
551 }
552 
553 #define	BHND_IO_MISC(_type, _op, _method)				\
554 static void								\
555 bhnd_ ## _op (device_t dev, device_t child,				\
556     struct bhnd_resource *r, bus_size_t offset, _type datap,		\
557     bus_size_t count)							\
558 {									\
559 	BHND_BUS_ ## _method(device_get_parent(dev), child, r,		\
560 	    offset, datap, count);					\
561 }
562 
563 #define	BHND_IO_METHODS(_type, _size)					\
564 	BHND_IO_READ(_type, _size, _size)				\
565 	BHND_IO_WRITE(_type, _size, _size)				\
566 									\
567 	BHND_IO_READ(_type, stream_ ## _size, STREAM_ ## _size)		\
568 	BHND_IO_WRITE(_type, stream_ ## _size, STREAM_ ## _size)	\
569 									\
570 	BHND_IO_MISC(_type*, read_multi_ ## _size,			\
571 	    READ_MULTI_ ## _size)					\
572 	BHND_IO_MISC(_type*, write_multi_ ## _size,			\
573 	    WRITE_MULTI_ ## _size)					\
574 									\
575 	BHND_IO_MISC(_type*, read_multi_stream_ ## _size,		\
576 	   READ_MULTI_STREAM_ ## _size)					\
577 	BHND_IO_MISC(_type*, write_multi_stream_ ## _size,		\
578 	   WRITE_MULTI_STREAM_ ## _size)				\
579 									\
580 	BHND_IO_MISC(_type, set_multi_ ## _size, SET_MULTI_ ## _size)	\
581 	BHND_IO_MISC(_type, set_region_ ## _size, SET_REGION_ ## _size)	\
582 									\
583 	BHND_IO_MISC(_type*, read_region_ ## _size,			\
584 	    READ_REGION_ ## _size)					\
585 	BHND_IO_MISC(_type*, write_region_ ## _size,			\
586 	    WRITE_REGION_ ## _size)					\
587 									\
588 	BHND_IO_MISC(_type*, read_region_stream_ ## _size,		\
589 	    READ_REGION_STREAM_ ## _size)				\
590 	BHND_IO_MISC(_type*, write_region_stream_ ## _size,		\
591 	    WRITE_REGION_STREAM_ ## _size)				\
592 
593 BHND_IO_METHODS(uint8_t, 1);
594 BHND_IO_METHODS(uint16_t, 2);
595 BHND_IO_METHODS(uint32_t, 4);
596 
597 static void
598 bhnd_barrier(device_t dev, device_t child, struct bhnd_resource *r,
599     bus_size_t offset, bus_size_t length, int flags)
600 {
601 	BHND_BUS_BARRIER(device_get_parent(dev), child, r, offset, length,
602 	    flags);
603 }
604 
605 static device_method_t bhnd_methods[] = {
606 	/* Device interface */ \
607 	DEVMETHOD(device_attach,		bhnd_generic_attach),
608 	DEVMETHOD(device_detach,		bhnd_generic_detach),
609 	DEVMETHOD(device_shutdown,		bhnd_generic_shutdown),
610 	DEVMETHOD(device_suspend,		bhnd_generic_suspend),
611 	DEVMETHOD(device_resume,		bhnd_generic_resume),
612 
613 	/* Bus interface */
614 	DEVMETHOD(bus_probe_nomatch,		bhnd_generic_probe_nomatch),
615 	DEVMETHOD(bus_print_child,		bhnd_generic_print_child),
616 	DEVMETHOD(bus_child_pnpinfo_str,	bhnd_child_pnpinfo_str),
617 	DEVMETHOD(bus_child_location_str,	bhnd_child_location_str),
618 
619 	DEVMETHOD(bus_suspend_child,		bhnd_generic_suspend_child),
620 	DEVMETHOD(bus_resume_child,		bhnd_generic_resume_child),
621 
622 	DEVMETHOD(bus_set_resource,		bus_generic_rl_set_resource),
623 	DEVMETHOD(bus_get_resource,		bus_generic_rl_get_resource),
624 	DEVMETHOD(bus_delete_resource,		bus_generic_rl_delete_resource),
625 	DEVMETHOD(bus_alloc_resource,		bus_generic_rl_alloc_resource),
626 	DEVMETHOD(bus_adjust_resource,		bus_generic_adjust_resource),
627 	DEVMETHOD(bus_release_resource,		bus_generic_rl_release_resource),
628 	DEVMETHOD(bus_activate_resource,	bus_generic_activate_resource),
629 	DEVMETHOD(bus_deactivate_resource,	bus_generic_deactivate_resource),
630 
631 	DEVMETHOD(bus_setup_intr,		bus_generic_setup_intr),
632 	DEVMETHOD(bus_teardown_intr,		bus_generic_teardown_intr),
633 	DEVMETHOD(bus_config_intr,		bus_generic_config_intr),
634 	DEVMETHOD(bus_bind_intr,		bus_generic_bind_intr),
635 	DEVMETHOD(bus_describe_intr,		bus_generic_describe_intr),
636 
637 	DEVMETHOD(bus_get_dma_tag,		bus_generic_get_dma_tag),
638 
639 	/* BHND interface */
640 	DEVMETHOD(bhnd_bus_get_chipid,		bhnd_bus_generic_get_chipid),
641 	DEVMETHOD(bhnd_bus_get_probe_order,	bhnd_generic_get_probe_order),
642 	DEVMETHOD(bhnd_bus_is_region_valid,	bhnd_generic_is_region_valid),
643 	DEVMETHOD(bhnd_bus_is_hw_disabled,	bhnd_bus_generic_is_hw_disabled),
644 	DEVMETHOD(bhnd_bus_get_nvram_var,	bhnd_bus_generic_get_nvram_var),
645 
646 	/* BHND interface (bus I/O) */
647 	DEVMETHOD(bhnd_bus_read_1,		bhnd_read_1),
648 	DEVMETHOD(bhnd_bus_read_2,		bhnd_read_2),
649 	DEVMETHOD(bhnd_bus_read_4,		bhnd_read_4),
650 	DEVMETHOD(bhnd_bus_write_1,		bhnd_write_1),
651 	DEVMETHOD(bhnd_bus_write_2,		bhnd_write_2),
652 	DEVMETHOD(bhnd_bus_write_4,		bhnd_write_4),
653 
654 	DEVMETHOD(bhnd_bus_read_stream_1,	bhnd_read_stream_1),
655 	DEVMETHOD(bhnd_bus_read_stream_2,	bhnd_read_stream_2),
656 	DEVMETHOD(bhnd_bus_read_stream_4,	bhnd_read_stream_4),
657 	DEVMETHOD(bhnd_bus_write_stream_1,	bhnd_write_stream_1),
658 	DEVMETHOD(bhnd_bus_write_stream_2,	bhnd_write_stream_2),
659 	DEVMETHOD(bhnd_bus_write_stream_4,	bhnd_write_stream_4),
660 
661 	DEVMETHOD(bhnd_bus_read_multi_1,	bhnd_read_multi_1),
662 	DEVMETHOD(bhnd_bus_read_multi_2,	bhnd_read_multi_2),
663 	DEVMETHOD(bhnd_bus_read_multi_4,	bhnd_read_multi_4),
664 	DEVMETHOD(bhnd_bus_write_multi_1,	bhnd_write_multi_1),
665 	DEVMETHOD(bhnd_bus_write_multi_2,	bhnd_write_multi_2),
666 	DEVMETHOD(bhnd_bus_write_multi_4,	bhnd_write_multi_4),
667 
668 	DEVMETHOD(bhnd_bus_read_multi_stream_1,	bhnd_read_multi_stream_1),
669 	DEVMETHOD(bhnd_bus_read_multi_stream_2,	bhnd_read_multi_stream_2),
670 	DEVMETHOD(bhnd_bus_read_multi_stream_4,	bhnd_read_multi_stream_4),
671 	DEVMETHOD(bhnd_bus_write_multi_stream_1,bhnd_write_multi_stream_1),
672 	DEVMETHOD(bhnd_bus_write_multi_stream_2,bhnd_write_multi_stream_2),
673 	DEVMETHOD(bhnd_bus_write_multi_stream_4,bhnd_write_multi_stream_4),
674 
675 	DEVMETHOD(bhnd_bus_set_multi_1,		bhnd_set_multi_1),
676 	DEVMETHOD(bhnd_bus_set_multi_2,		bhnd_set_multi_2),
677 	DEVMETHOD(bhnd_bus_set_multi_4,		bhnd_set_multi_4),
678 
679 	DEVMETHOD(bhnd_bus_set_region_1,	bhnd_set_region_1),
680 	DEVMETHOD(bhnd_bus_set_region_2,	bhnd_set_region_2),
681 	DEVMETHOD(bhnd_bus_set_region_4,	bhnd_set_region_4),
682 
683 	DEVMETHOD(bhnd_bus_read_region_1,	bhnd_read_region_1),
684 	DEVMETHOD(bhnd_bus_read_region_2,	bhnd_read_region_2),
685 	DEVMETHOD(bhnd_bus_read_region_4,	bhnd_read_region_4),
686 	DEVMETHOD(bhnd_bus_write_region_1,	bhnd_write_region_1),
687 	DEVMETHOD(bhnd_bus_write_region_2,	bhnd_write_region_2),
688 	DEVMETHOD(bhnd_bus_write_region_4,	bhnd_write_region_4),
689 
690 	DEVMETHOD(bhnd_bus_read_region_stream_1,bhnd_read_region_stream_1),
691 	DEVMETHOD(bhnd_bus_read_region_stream_2,bhnd_read_region_stream_2),
692 	DEVMETHOD(bhnd_bus_read_region_stream_4,bhnd_read_region_stream_4),
693 	DEVMETHOD(bhnd_bus_write_region_stream_1, bhnd_write_region_stream_1),
694 	DEVMETHOD(bhnd_bus_write_region_stream_2, bhnd_write_region_stream_2),
695 	DEVMETHOD(bhnd_bus_write_region_stream_4, bhnd_write_region_stream_4),
696 
697 	DEVMETHOD(bhnd_bus_barrier,			bhnd_barrier),
698 
699 	DEVMETHOD_END
700 };
701 
702 devclass_t bhnd_devclass;	/**< bhnd bus. */
703 devclass_t bhnd_hostb_devclass;	/**< bhnd bus host bridge. */
704 devclass_t bhnd_nvram_devclass;	/**< bhnd NVRAM device */
705 
706 DEFINE_CLASS_0(bhnd, bhnd_driver, bhnd_methods, sizeof(struct bhnd_softc));
707 MODULE_VERSION(bhnd, 1);
708