xref: /freebsd/sys/dev/bhnd/bhnd.c (revision 20f8619da05e2775ef7b381c5df080d621fa8332)
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 "nvram/bhnd_nvram.h"
62 
63 #include "bhnd_chipc_if.h"
64 #include "bhnd_nvram_if.h"
65 
66 #include "bhnd.h"
67 #include "bhndvar.h"
68 
69 MALLOC_DEFINE(M_BHND, "bhnd", "bhnd bus data structures");
70 
71 /**
72  * bhnd_generic_probe_nomatch() reporting configuration.
73  */
74 static const struct bhnd_nomatch {
75 	uint16_t	vendor;		/**< core designer */
76 	uint16_t	device;		/**< core id */
77 	bool		if_verbose;	/**< print when bootverbose is set. */
78 } bhnd_nomatch_table[] = {
79 	{ BHND_MFGID_ARM,	BHND_COREID_OOB_ROUTER,		true	},
80 	{ BHND_MFGID_ARM,	BHND_COREID_EROM,		true	},
81 	{ BHND_MFGID_ARM,	BHND_COREID_PL301,		true	},
82 	{ BHND_MFGID_ARM,	BHND_COREID_APB_BRIDGE,		true	},
83 	{ BHND_MFGID_ARM,	BHND_COREID_AXI_UNMAPPED,	false	},
84 
85 	{ BHND_MFGID_INVALID,	BHND_COREID_INVALID,		false	}
86 };
87 
88 static device_t	find_nvram_child(device_t dev);
89 
90 static int	compare_ascending_probe_order(const void *lhs,
91 		    const void *rhs);
92 static int	compare_descending_probe_order(const void *lhs,
93 		    const void *rhs);
94 
95 /**
96  * Default bhnd(4) bus driver implementation of DEVICE_ATTACH().
97  *
98  * This implementation calls device_probe_and_attach() for each of the device's
99  * children, in bhnd probe order.
100  */
101 int
102 bhnd_generic_attach(device_t dev)
103 {
104 	device_t	*devs;
105 	int		 ndevs;
106 	int		 error;
107 
108 	if (device_is_attached(dev))
109 		return (EBUSY);
110 
111 	if ((error = device_get_children(dev, &devs, &ndevs)))
112 		return (error);
113 
114 	qsort(devs, ndevs, sizeof(*devs), compare_ascending_probe_order);
115 	for (int i = 0; i < ndevs; i++) {
116 		device_t child = devs[i];
117 		device_probe_and_attach(child);
118 	}
119 
120 	free(devs, M_TEMP);
121 	return (0);
122 }
123 
124 /**
125  * Default bhnd(4) bus driver implementation of DEVICE_DETACH().
126  *
127  * This implementation calls device_detach() for each of the the device's
128  * children, in reverse bhnd probe order, terminating if any call to
129  * device_detach() fails.
130  */
131 int
132 bhnd_generic_detach(device_t dev)
133 {
134 	device_t	*devs;
135 	int		 ndevs;
136 	int		 error;
137 
138 	if (!device_is_attached(dev))
139 		return (EBUSY);
140 
141 	if ((error = device_get_children(dev, &devs, &ndevs)))
142 		return (error);
143 
144 	/* Detach in the reverse of attach order */
145 	qsort(devs, ndevs, sizeof(*devs), compare_descending_probe_order);
146 	for (int i = 0; i < ndevs; i++) {
147 		device_t child = devs[i];
148 
149 		/* Terminate on first error */
150 		if ((error = device_detach(child)))
151 			goto cleanup;
152 	}
153 
154 cleanup:
155 	free(devs, M_TEMP);
156 	return (error);
157 }
158 
159 /**
160  * Default bhnd(4) bus driver implementation of DEVICE_SHUTDOWN().
161  *
162  * This implementation calls device_shutdown() for each of the device's
163  * children, in reverse bhnd probe order, terminating if any call to
164  * device_shutdown() fails.
165  */
166 int
167 bhnd_generic_shutdown(device_t dev)
168 {
169 	device_t	*devs;
170 	int		 ndevs;
171 	int		 error;
172 
173 	if (!device_is_attached(dev))
174 		return (EBUSY);
175 
176 	if ((error = device_get_children(dev, &devs, &ndevs)))
177 		return (error);
178 
179 	/* Shutdown in the reverse of attach order */
180 	qsort(devs, ndevs, sizeof(*devs), compare_descending_probe_order);
181 	for (int i = 0; i < ndevs; i++) {
182 		device_t child = devs[i];
183 
184 		/* Terminate on first error */
185 		if ((error = device_shutdown(child)))
186 			goto cleanup;
187 	}
188 
189 cleanup:
190 	free(devs, M_TEMP);
191 	return (error);
192 }
193 
194 /**
195  * Default bhnd(4) bus driver implementation of DEVICE_RESUME().
196  *
197  * This implementation calls BUS_RESUME_CHILD() for each of the device's
198  * children in bhnd probe order, terminating if any call to BUS_RESUME_CHILD()
199  * fails.
200  */
201 int
202 bhnd_generic_resume(device_t dev)
203 {
204 	device_t	*devs;
205 	int		 ndevs;
206 	int		 error;
207 
208 	if (!device_is_attached(dev))
209 		return (EBUSY);
210 
211 	if ((error = device_get_children(dev, &devs, &ndevs)))
212 		return (error);
213 
214 	qsort(devs, ndevs, sizeof(*devs), compare_ascending_probe_order);
215 	for (int i = 0; i < ndevs; i++) {
216 		device_t child = devs[i];
217 
218 		/* Terminate on first error */
219 		if ((error = BUS_RESUME_CHILD(device_get_parent(child), child)))
220 			goto cleanup;
221 	}
222 
223 cleanup:
224 	free(devs, M_TEMP);
225 	return (error);
226 }
227 
228 /**
229  * Default bhnd(4) bus driver implementation of DEVICE_SUSPEND().
230  *
231  * This implementation calls BUS_SUSPEND_CHILD() for each of the device's
232  * children in reverse bhnd probe order. If any call to BUS_SUSPEND_CHILD()
233  * fails, the suspend operation is terminated and any devices that were
234  * suspended are resumed immediately by calling their BUS_RESUME_CHILD()
235  * methods.
236  */
237 int
238 bhnd_generic_suspend(device_t dev)
239 {
240 	device_t	*devs;
241 	int		 ndevs;
242 	int		 error;
243 
244 	if (!device_is_attached(dev))
245 		return (EBUSY);
246 
247 	if ((error = device_get_children(dev, &devs, &ndevs)))
248 		return (error);
249 
250 	/* Suspend in the reverse of attach order */
251 	qsort(devs, ndevs, sizeof(*devs), compare_descending_probe_order);
252 	for (int i = 0; i < ndevs; i++) {
253 		device_t child = devs[i];
254 		error = BUS_SUSPEND_CHILD(device_get_parent(child), child);
255 
256 		/* On error, resume suspended devices and then terminate */
257 		if (error) {
258 			for (int j = 0; j < i; j++) {
259 				BUS_RESUME_CHILD(device_get_parent(devs[j]),
260 				    devs[j]);
261 			}
262 
263 			goto cleanup;
264 		}
265 	}
266 
267 cleanup:
268 	free(devs, M_TEMP);
269 	return (error);
270 }
271 
272 /*
273  * Ascending comparison of bhnd device's probe order.
274  */
275 static int
276 compare_ascending_probe_order(const void *lhs, const void *rhs)
277 {
278 	device_t	ldev, rdev;
279 	int		lorder, rorder;
280 
281 	ldev = (*(const device_t *) lhs);
282 	rdev = (*(const device_t *) rhs);
283 
284 	lorder = BHND_BUS_GET_PROBE_ORDER(device_get_parent(ldev), ldev);
285 	rorder = BHND_BUS_GET_PROBE_ORDER(device_get_parent(rdev), rdev);
286 
287 	if (lorder < rorder) {
288 		return (-1);
289 	} else if (lorder > rorder) {
290 		return (1);
291 	} else {
292 		return (0);
293 	}
294 }
295 
296 /*
297  * Descending comparison of bhnd device's probe order.
298  */
299 static int
300 compare_descending_probe_order(const void *lhs, const void *rhs)
301 {
302 	return (compare_ascending_probe_order(rhs, lhs));
303 }
304 
305 /**
306  * Default bhnd(4) bus driver implementation of BHND_BUS_GET_PROBE_ORDER().
307  *
308  * This implementation determines probe ordering based on the device's class
309  * and other properties, including whether the device is serving as a host
310  * bridge.
311  */
312 int
313 bhnd_generic_get_probe_order(device_t dev, device_t child)
314 {
315 	switch (bhnd_get_class(child)) {
316 	case BHND_DEVCLASS_CC:
317 		return (BHND_PROBE_BUS + BHND_PROBE_ORDER_FIRST);
318 
319 	case BHND_DEVCLASS_CC_B:
320 		/* fall through */
321 	case BHND_DEVCLASS_PMU:
322 		return (BHND_PROBE_BUS + BHND_PROBE_ORDER_EARLY);
323 
324 	case BHND_DEVCLASS_SOC_ROUTER:
325 		return (BHND_PROBE_BUS + BHND_PROBE_ORDER_LATE);
326 
327 	case BHND_DEVCLASS_SOC_BRIDGE:
328 		return (BHND_PROBE_BUS + BHND_PROBE_ORDER_LAST);
329 
330 	case BHND_DEVCLASS_CPU:
331 		return (BHND_PROBE_CPU + BHND_PROBE_ORDER_FIRST);
332 
333 	case BHND_DEVCLASS_RAM:
334 		/* fall through */
335 	case BHND_DEVCLASS_MEMC:
336 		return (BHND_PROBE_CPU + BHND_PROBE_ORDER_EARLY);
337 
338 	case BHND_DEVCLASS_NVRAM:
339 		return (BHND_PROBE_RESOURCE + BHND_PROBE_ORDER_EARLY);
340 
341 	case BHND_DEVCLASS_PCI:
342 	case BHND_DEVCLASS_PCIE:
343 	case BHND_DEVCLASS_PCCARD:
344 	case BHND_DEVCLASS_ENET:
345 	case BHND_DEVCLASS_ENET_MAC:
346 	case BHND_DEVCLASS_ENET_PHY:
347 	case BHND_DEVCLASS_WLAN:
348 	case BHND_DEVCLASS_WLAN_MAC:
349 	case BHND_DEVCLASS_WLAN_PHY:
350 	case BHND_DEVCLASS_EROM:
351 	case BHND_DEVCLASS_OTHER:
352 	case BHND_DEVCLASS_INVALID:
353 		if (bhnd_find_hostb_device(dev) == child)
354 			return (BHND_PROBE_ROOT + BHND_PROBE_ORDER_EARLY);
355 
356 		return (BHND_PROBE_DEFAULT);
357 	default:
358 		return (BHND_PROBE_DEFAULT);
359 	}
360 }
361 
362 /**
363  * Default bhnd(4) bus driver implementation of BHND_BUS_IS_REGION_VALID().
364  *
365  * This implementation assumes that port and region numbers are 0-indexed and
366  * are allocated non-sparsely, using BHND_BUS_GET_PORT_COUNT() and
367  * BHND_BUS_GET_REGION_COUNT() to determine if @p port and @p region fall
368  * within the defined range.
369  */
370 static bool
371 bhnd_generic_is_region_valid(device_t dev, device_t child,
372     bhnd_port_type type, u_int port, u_int region)
373 {
374 	if (port >= bhnd_get_port_count(child, type))
375 		return (false);
376 
377 	if (region >= bhnd_get_region_count(child, type, port))
378 		return (false);
379 
380 	return (true);
381 }
382 
383 /**
384  * Find an NVRAM child device on @p dev, if any.
385  *
386  * @retval device_t An NVRAM device.
387  * @retval NULL If no NVRAM device is found.
388  */
389 static device_t
390 find_nvram_child(device_t dev)
391 {
392 	device_t	chipc, nvram;
393 
394 	/* Look for a directly-attached NVRAM child */
395 	nvram = device_find_child(dev, "bhnd_nvram", 0);
396 	if (nvram != NULL)
397 		return (nvram);
398 
399 	/* Remaining checks are only applicable when searching a bhnd(4)
400 	 * bus. */
401 	if (device_get_devclass(dev) != bhnd_devclass)
402 		return (NULL);
403 
404 	/* Look for a ChipCommon device */
405 	if ((chipc = bhnd_find_child(dev, BHND_DEVCLASS_CC, -1)) != NULL) {
406 		bhnd_nvram_src_t src;
407 
408 		/* Query the NVRAM source and determine whether it's
409 		 * accessible via the ChipCommon device */
410 		src = BHND_CHIPC_NVRAM_SRC(chipc);
411 		if (BHND_NVRAM_SRC_CC(src))
412 			return (chipc);
413 	}
414 
415 	/* Not found */
416 	return (NULL);
417 }
418 
419 /**
420  * Default bhnd(4) bus driver implementation of BHND_BUS_GET_NVRAM_VAR().
421  *
422  * This implementation searches @p dev for a usable NVRAM child device:
423  * - The first child device implementing the bhnd_nvram devclass is
424  *   returned, otherwise
425  * - If @p dev is a bhnd(4) bus, a ChipCommon core that advertises an
426  *   attached NVRAM source.
427  *
428  * If no usable child device is found on @p dev, the request is delegated to
429  * the BHND_BUS_GET_NVRAM_VAR() method on the parent of @p dev.
430  */
431 static int
432 bhnd_generic_get_nvram_var(device_t dev, device_t child, const char *name,
433     void *buf, size_t *size)
434 {
435 	device_t nvram;
436 
437 	/* Try to find an NVRAM device applicable to @p child */
438 	if ((nvram = find_nvram_child(dev)) == NULL)
439 		return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), child,
440 		    name, buf, size));
441 
442 	return BHND_NVRAM_GETVAR(nvram, name, buf, size);
443 }
444 
445 /**
446  * Default bhnd(4) bus driver implementation of BUS_PRINT_CHILD().
447  *
448  * This implementation requests the device's struct resource_list via
449  * BUS_GET_RESOURCE_LIST.
450  */
451 int
452 bhnd_generic_print_child(device_t dev, device_t child)
453 {
454 	struct resource_list	*rl;
455 	int			retval = 0;
456 
457 	retval += bus_print_child_header(dev, child);
458 
459 	rl = BUS_GET_RESOURCE_LIST(dev, child);
460 	if (rl != NULL) {
461 		retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY,
462 		    "%#jx");
463 	}
464 
465 	retval += printf(" at core %u", bhnd_get_core_index(child));
466 
467 	retval += bus_print_child_domain(dev, child);
468 	retval += bus_print_child_footer(dev, child);
469 
470 	return (retval);
471 }
472 
473 /**
474  * Default bhnd(4) bus driver implementation of BUS_PROBE_NOMATCH().
475  *
476  * This implementation requests the device's struct resource_list via
477  * BUS_GET_RESOURCE_LIST.
478  */
479 void
480 bhnd_generic_probe_nomatch(device_t dev, device_t child)
481 {
482 	struct resource_list		*rl;
483 	const struct bhnd_nomatch	*nm;
484 	bool				 report;
485 
486 	/* Fetch reporting configuration for this device */
487 	report = true;
488 	for (nm = bhnd_nomatch_table; nm->device != BHND_COREID_INVALID; nm++) {
489 		if (nm->vendor != bhnd_get_vendor(child))
490 			continue;
491 
492 		if (nm->device != bhnd_get_device(child))
493 			continue;
494 
495 		report = false;
496 		if (bootverbose && nm->if_verbose)
497 			report = true;
498 		break;
499 	}
500 
501 	if (!report)
502 		return;
503 
504 	/* Print the non-matched device info */
505 	device_printf(dev, "<%s %s>", bhnd_get_vendor_name(child),
506 		bhnd_get_device_name(child));
507 
508 	rl = BUS_GET_RESOURCE_LIST(dev, child);
509 	if (rl != NULL)
510 		resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
511 
512 	printf(" at core %u (no driver attached)\n",
513 	    bhnd_get_core_index(child));
514 }
515 
516 /**
517  * Default implementation of BUS_CHILD_PNPINFO_STR().
518  */
519 static int
520 bhnd_child_pnpinfo_str(device_t dev, device_t child, char *buf,
521     size_t buflen)
522 {
523 	if (device_get_parent(child) != dev) {
524 		return (BUS_CHILD_PNPINFO_STR(device_get_parent(dev), child,
525 		    buf, buflen));
526 	}
527 
528 	snprintf(buf, buflen, "vendor=0x%hx device=0x%hx rev=0x%hhx",
529 	    bhnd_get_vendor(child), bhnd_get_device(child),
530 	    bhnd_get_hwrev(child));
531 
532 	return (0);
533 }
534 
535 /**
536  * Default implementation of BUS_CHILD_LOCATION_STR().
537  */
538 static int
539 bhnd_child_location_str(device_t dev, device_t child, char *buf,
540     size_t buflen)
541 {
542 	bhnd_addr_t	addr;
543 	bhnd_size_t	size;
544 
545 	if (device_get_parent(child) != dev) {
546 		return (BUS_CHILD_LOCATION_STR(device_get_parent(dev), child,
547 		    buf, buflen));
548 	}
549 
550 
551 	if (bhnd_get_region_addr(child, BHND_PORT_DEVICE, 0, 0, &addr, &size)) {
552 		/* No device default port/region */
553 		if (buflen > 0)
554 			*buf = '\0';
555 		return (0);
556 	}
557 
558 	snprintf(buf, buflen, "port0.0=0x%llx", (unsigned long long) addr);
559 	return (0);
560 }
561 
562 /**
563  * Helper function for implementing BUS_SUSPEND_CHILD().
564  *
565  * TODO: Power management
566  *
567  * If @p child is not a direct child of @p dev, suspension is delegated to
568  * the @p dev parent.
569  */
570 int
571 bhnd_generic_suspend_child(device_t dev, device_t child)
572 {
573 	if (device_get_parent(child) != dev)
574 		BUS_SUSPEND_CHILD(device_get_parent(dev), child);
575 
576 	return bus_generic_suspend_child(dev, child);
577 }
578 
579 /**
580  * Helper function for implementing BUS_RESUME_CHILD().
581  *
582  * TODO: Power management
583  *
584  * If @p child is not a direct child of @p dev, suspension is delegated to
585  * the @p dev parent.
586  */
587 int
588 bhnd_generic_resume_child(device_t dev, device_t child)
589 {
590 	if (device_get_parent(child) != dev)
591 		BUS_RESUME_CHILD(device_get_parent(dev), child);
592 
593 	return bus_generic_resume_child(dev, child);
594 }
595 
596 /*
597  * Delegate all indirect I/O to the parent device. When inherited by
598  * non-bridged bus implementations, resources will never be marked as
599  * indirect, and these methods should never be called.
600  */
601 #define	BHND_IO_READ(_type, _name, _method)			\
602 static _type							\
603 bhnd_read_ ## _name (device_t dev, device_t child,		\
604     struct bhnd_resource *r, bus_size_t offset)			\
605 {								\
606 	return (BHND_BUS_READ_ ## _method(			\
607 		    device_get_parent(dev), child, r, offset));	\
608 }
609 
610 #define	BHND_IO_WRITE(_type, _name, _method)			\
611 static void							\
612 bhnd_write_ ## _name (device_t dev, device_t child,		\
613     struct bhnd_resource *r, bus_size_t offset, _type value)	\
614 {								\
615 	return (BHND_BUS_WRITE_ ## _method(			\
616 		    device_get_parent(dev), child, r, offset,	\
617 		    value));	\
618 }
619 
620 #define	BHND_IO_MULTI(_type, _rw, _name, _method)			\
621 static void								\
622 bhnd_ ## _rw ## _multi_ ## _name (device_t dev, device_t child,	\
623     struct bhnd_resource *r, bus_size_t offset, _type *datap,		\
624     bus_size_t count)							\
625 {									\
626 	BHND_BUS_ ## _method(device_get_parent(dev), child, r,		\
627 	    offset, datap, count);					\
628 }
629 
630 #define	BHND_IO_METHODS(_type, _size)					\
631 	BHND_IO_READ(_type, _size, _size)				\
632 	BHND_IO_WRITE(_type, _size, _size)				\
633 									\
634 	BHND_IO_READ(_type, stream_ ## _size, STREAM_ ## _size)		\
635 	BHND_IO_WRITE(_type, stream_ ## _size, STREAM_ ## _size)	\
636 									\
637 	BHND_IO_MULTI(_type, read, _size, READ_MULTI_ ## _size)		\
638 	BHND_IO_MULTI(_type, write, _size, WRITE_MULTI_ ## _size)	\
639 									\
640 	BHND_IO_MULTI(_type, read, stream_ ## _size,			\
641 	   READ_MULTI_STREAM_ ## _size)					\
642 	BHND_IO_MULTI(_type, write, stream_ ## _size,			\
643 	   WRITE_MULTI_STREAM_ ## _size)				\
644 
645 BHND_IO_METHODS(uint8_t, 1);
646 BHND_IO_METHODS(uint16_t, 2);
647 BHND_IO_METHODS(uint32_t, 4);
648 
649 static void
650 bhnd_barrier(device_t dev, device_t child, struct bhnd_resource *r,
651     bus_size_t offset, bus_size_t length, int flags)
652 {
653 	BHND_BUS_BARRIER(device_get_parent(dev), child, r, offset, length,
654 	    flags);
655 }
656 
657 static device_method_t bhnd_methods[] = {
658 	/* Device interface */ \
659 	DEVMETHOD(device_attach,		bhnd_generic_attach),
660 	DEVMETHOD(device_detach,		bhnd_generic_detach),
661 	DEVMETHOD(device_shutdown,		bhnd_generic_shutdown),
662 	DEVMETHOD(device_suspend,		bhnd_generic_suspend),
663 	DEVMETHOD(device_resume,		bhnd_generic_resume),
664 
665 	/* Bus interface */
666 	DEVMETHOD(bus_probe_nomatch,		bhnd_generic_probe_nomatch),
667 	DEVMETHOD(bus_print_child,		bhnd_generic_print_child),
668 	DEVMETHOD(bus_child_pnpinfo_str,	bhnd_child_pnpinfo_str),
669 	DEVMETHOD(bus_child_location_str,	bhnd_child_location_str),
670 
671 	DEVMETHOD(bus_suspend_child,		bhnd_generic_suspend_child),
672 	DEVMETHOD(bus_resume_child,		bhnd_generic_resume_child),
673 
674 	DEVMETHOD(bus_set_resource,		bus_generic_rl_set_resource),
675 	DEVMETHOD(bus_get_resource,		bus_generic_rl_get_resource),
676 	DEVMETHOD(bus_delete_resource,		bus_generic_rl_delete_resource),
677 	DEVMETHOD(bus_alloc_resource,		bus_generic_rl_alloc_resource),
678 	DEVMETHOD(bus_adjust_resource,		bus_generic_adjust_resource),
679 	DEVMETHOD(bus_release_resource,		bus_generic_rl_release_resource),
680 	DEVMETHOD(bus_activate_resource,	bus_generic_activate_resource),
681 	DEVMETHOD(bus_deactivate_resource,	bus_generic_deactivate_resource),
682 
683 	DEVMETHOD(bus_setup_intr,		bus_generic_setup_intr),
684 	DEVMETHOD(bus_teardown_intr,		bus_generic_teardown_intr),
685 	DEVMETHOD(bus_config_intr,		bus_generic_config_intr),
686 	DEVMETHOD(bus_bind_intr,		bus_generic_bind_intr),
687 	DEVMETHOD(bus_describe_intr,		bus_generic_describe_intr),
688 
689 	DEVMETHOD(bus_get_dma_tag,		bus_generic_get_dma_tag),
690 
691 	/* BHND interface */
692 	DEVMETHOD(bhnd_bus_get_chipid,		bhnd_bus_generic_get_chipid),
693 	DEVMETHOD(bhnd_bus_get_probe_order,	bhnd_generic_get_probe_order),
694 	DEVMETHOD(bhnd_bus_is_region_valid,	bhnd_generic_is_region_valid),
695 	DEVMETHOD(bhnd_bus_is_hw_disabled,	bhnd_bus_generic_is_hw_disabled),
696 	DEVMETHOD(bhnd_bus_get_nvram_var,	bhnd_generic_get_nvram_var),
697 	DEVMETHOD(bhnd_bus_read_1,		bhnd_read_1),
698 	DEVMETHOD(bhnd_bus_read_2,		bhnd_read_2),
699 	DEVMETHOD(bhnd_bus_read_4,		bhnd_read_4),
700 	DEVMETHOD(bhnd_bus_write_1,		bhnd_write_1),
701 	DEVMETHOD(bhnd_bus_write_2,		bhnd_write_2),
702 	DEVMETHOD(bhnd_bus_write_4,		bhnd_write_4),
703 	DEVMETHOD(bhnd_bus_read_stream_1,	bhnd_read_stream_1),
704 	DEVMETHOD(bhnd_bus_read_stream_2,	bhnd_read_stream_2),
705 	DEVMETHOD(bhnd_bus_read_stream_4,	bhnd_read_stream_4),
706 	DEVMETHOD(bhnd_bus_write_stream_1,	bhnd_write_stream_1),
707 	DEVMETHOD(bhnd_bus_write_stream_2,	bhnd_write_stream_2),
708 	DEVMETHOD(bhnd_bus_write_stream_4,	bhnd_write_stream_4),
709 
710 	DEVMETHOD(bhnd_bus_read_multi_1,	bhnd_read_multi_1),
711 	DEVMETHOD(bhnd_bus_read_multi_2,	bhnd_read_multi_2),
712 	DEVMETHOD(bhnd_bus_read_multi_4,	bhnd_read_multi_4),
713 	DEVMETHOD(bhnd_bus_write_multi_1,	bhnd_write_multi_1),
714 	DEVMETHOD(bhnd_bus_write_multi_2,	bhnd_write_multi_2),
715 	DEVMETHOD(bhnd_bus_write_multi_4,	bhnd_write_multi_4),
716 
717 	DEVMETHOD(bhnd_bus_read_multi_stream_1,	bhnd_read_multi_stream_1),
718 	DEVMETHOD(bhnd_bus_read_multi_stream_2,	bhnd_read_multi_stream_2),
719 	DEVMETHOD(bhnd_bus_read_multi_stream_4,	bhnd_read_multi_stream_4),
720 	DEVMETHOD(bhnd_bus_write_multi_stream_1,bhnd_write_multi_stream_1),
721 	DEVMETHOD(bhnd_bus_write_multi_stream_2,bhnd_write_multi_stream_2),
722 	DEVMETHOD(bhnd_bus_write_multi_stream_4,bhnd_write_multi_stream_4),
723 
724 	DEVMETHOD(bhnd_bus_barrier,		bhnd_barrier),
725 
726 	DEVMETHOD_END
727 };
728 
729 devclass_t bhnd_devclass;	/**< bhnd bus. */
730 devclass_t bhnd_hostb_devclass;	/**< bhnd bus host bridge. */
731 devclass_t bhnd_nvram_devclass;	/**< bhnd NVRAM device */
732 
733 DEFINE_CLASS_0(bhnd, bhnd_driver, bhnd_methods, sizeof(struct bhnd_softc));
734 MODULE_VERSION(bhnd, 1);
735