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
64MALLOC_DEFINE(M_BHND, "bhnd", "bhnd bus data structures");
65
66/**
67 * bhnd_generic_probe_nomatch() reporting configuration.
68 */
69static 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
83static int	compare_ascending_probe_order(const void *lhs,
84		    const void *rhs);
85static 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 */
94int
95bhnd_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 */
124int
125bhnd_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
147cleanup:
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 */
159int
160bhnd_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
182cleanup:
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 */
194int
195bhnd_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
216cleanup:
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 */
230int
231bhnd_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
260cleanup:
261	free(devs, M_TEMP);
262	return (error);
263}
264
265/*
266 * Ascending comparison of bhnd device's probe order.
267 */
268static int
269compare_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 */
292static int
293compare_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 */
305int
306bhnd_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 */
365static bool
366bhnd_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 */
384int
385bhnd_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 */
412void
413bhnd_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 */
452static int
453bhnd_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 */
471static int
472bhnd_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 * Default bhnd(4) bus driver implementation of BUS_ADD_CHILD().
497 *
498 * This implementation manages internal bhnd(4) state, and must be called
499 * by subclassing drivers.
500 */
501device_t
502bhnd_generic_add_child(device_t dev, u_int order, const char *name, int unit)
503{
504	struct bhnd_devinfo	*dinfo;
505	device_t		 child;
506
507	child = device_add_child_ordered(dev, order, name, unit);
508	if (child == NULL)
509		return (NULL);
510
511	if ((dinfo = BHND_BUS_ALLOC_DEVINFO(dev)) == NULL) {
512		device_delete_child(dev, child);
513		return (NULL);
514	}
515
516	device_set_ivars(child, dinfo);
517
518	/* Inform concrete bus driver. */
519	BHND_BUS_CHILD_ADDED(dev, child);
520
521	return (child);
522}
523
524/**
525 * Default bhnd(4) bus driver implementation of BUS_CHILD_DELETED().
526 *
527 * This implementation manages internal bhnd(4) state, and must be called
528 * by subclassing drivers.
529 */
530void
531bhnd_generic_child_deleted(device_t dev, device_t child)
532{
533	struct bhnd_softc	*sc;
534	struct bhnd_devinfo	*dinfo;
535
536	sc = device_get_softc(dev);
537
538	/* Free device info */
539	if ((dinfo = device_get_ivars(child)) != NULL)
540		BHND_BUS_FREE_DEVINFO(dev, dinfo);
541}
542
543/**
544 * Helper function for implementing BUS_SUSPEND_CHILD().
545 *
546 * TODO: Power management
547 *
548 * If @p child is not a direct child of @p dev, suspension is delegated to
549 * the @p dev parent.
550 */
551int
552bhnd_generic_suspend_child(device_t dev, device_t child)
553{
554	if (device_get_parent(child) != dev)
555		BUS_SUSPEND_CHILD(device_get_parent(dev), child);
556
557	return bus_generic_suspend_child(dev, child);
558}
559
560/**
561 * Helper function for implementing BUS_RESUME_CHILD().
562 *
563 * TODO: Power management
564 *
565 * If @p child is not a direct child of @p dev, suspension is delegated to
566 * the @p dev parent.
567 */
568int
569bhnd_generic_resume_child(device_t dev, device_t child)
570{
571	if (device_get_parent(child) != dev)
572		BUS_RESUME_CHILD(device_get_parent(dev), child);
573
574	return bus_generic_resume_child(dev, child);
575}
576
577/*
578 * Delegate all indirect I/O to the parent device. When inherited by
579 * non-bridged bus implementations, resources will never be marked as
580 * indirect, and these methods will never be called.
581 */
582#define	BHND_IO_READ(_type, _name, _method)				\
583static _type								\
584bhnd_read_ ## _name (device_t dev, device_t child,			\
585    struct bhnd_resource *r, bus_size_t offset)				\
586{									\
587	return (BHND_BUS_READ_ ## _method(				\
588		    device_get_parent(dev), child, r, offset));		\
589}
590
591#define	BHND_IO_WRITE(_type, _name, _method)				\
592static void								\
593bhnd_write_ ## _name (device_t dev, device_t child,			\
594    struct bhnd_resource *r, bus_size_t offset, _type value)		\
595{									\
596	return (BHND_BUS_WRITE_ ## _method(				\
597		    device_get_parent(dev), child, r, offset,		\
598		    value));	\
599}
600
601#define	BHND_IO_MISC(_type, _op, _method)				\
602static void								\
603bhnd_ ## _op (device_t dev, device_t child,				\
604    struct bhnd_resource *r, bus_size_t offset, _type datap,		\
605    bus_size_t count)							\
606{									\
607	BHND_BUS_ ## _method(device_get_parent(dev), child, r,		\
608	    offset, datap, count);					\
609}
610
611#define	BHND_IO_METHODS(_type, _size)					\
612	BHND_IO_READ(_type, _size, _size)				\
613	BHND_IO_WRITE(_type, _size, _size)				\
614									\
615	BHND_IO_READ(_type, stream_ ## _size, STREAM_ ## _size)		\
616	BHND_IO_WRITE(_type, stream_ ## _size, STREAM_ ## _size)	\
617									\
618	BHND_IO_MISC(_type*, read_multi_ ## _size,			\
619	    READ_MULTI_ ## _size)					\
620	BHND_IO_MISC(_type*, write_multi_ ## _size,			\
621	    WRITE_MULTI_ ## _size)					\
622									\
623	BHND_IO_MISC(_type*, read_multi_stream_ ## _size,		\
624	   READ_MULTI_STREAM_ ## _size)					\
625	BHND_IO_MISC(_type*, write_multi_stream_ ## _size,		\
626	   WRITE_MULTI_STREAM_ ## _size)				\
627									\
628	BHND_IO_MISC(_type, set_multi_ ## _size, SET_MULTI_ ## _size)	\
629	BHND_IO_MISC(_type, set_region_ ## _size, SET_REGION_ ## _size)	\
630									\
631	BHND_IO_MISC(_type*, read_region_ ## _size,			\
632	    READ_REGION_ ## _size)					\
633	BHND_IO_MISC(_type*, write_region_ ## _size,			\
634	    WRITE_REGION_ ## _size)					\
635									\
636	BHND_IO_MISC(_type*, read_region_stream_ ## _size,		\
637	    READ_REGION_STREAM_ ## _size)				\
638	BHND_IO_MISC(_type*, write_region_stream_ ## _size,		\
639	    WRITE_REGION_STREAM_ ## _size)				\
640
641BHND_IO_METHODS(uint8_t, 1);
642BHND_IO_METHODS(uint16_t, 2);
643BHND_IO_METHODS(uint32_t, 4);
644
645static void
646bhnd_barrier(device_t dev, device_t child, struct bhnd_resource *r,
647    bus_size_t offset, bus_size_t length, int flags)
648{
649	BHND_BUS_BARRIER(device_get_parent(dev), child, r, offset, length,
650	    flags);
651}
652
653static device_method_t bhnd_methods[] = {
654	/* Device interface */ \
655	DEVMETHOD(device_attach,		bhnd_generic_attach),
656	DEVMETHOD(device_detach,		bhnd_generic_detach),
657	DEVMETHOD(device_shutdown,		bhnd_generic_shutdown),
658	DEVMETHOD(device_suspend,		bhnd_generic_suspend),
659	DEVMETHOD(device_resume,		bhnd_generic_resume),
660
661	/* Bus interface */
662	DEVMETHOD(bus_add_child,		bhnd_generic_add_child),
663	DEVMETHOD(bus_child_deleted,		bhnd_generic_child_deleted),
664	DEVMETHOD(bus_probe_nomatch,		bhnd_generic_probe_nomatch),
665	DEVMETHOD(bus_print_child,		bhnd_generic_print_child),
666	DEVMETHOD(bus_child_pnpinfo_str,	bhnd_child_pnpinfo_str),
667	DEVMETHOD(bus_child_location_str,	bhnd_child_location_str),
668
669	DEVMETHOD(bus_suspend_child,		bhnd_generic_suspend_child),
670	DEVMETHOD(bus_resume_child,		bhnd_generic_resume_child),
671
672	DEVMETHOD(bus_set_resource,		bus_generic_rl_set_resource),
673	DEVMETHOD(bus_get_resource,		bus_generic_rl_get_resource),
674	DEVMETHOD(bus_delete_resource,		bus_generic_rl_delete_resource),
675	DEVMETHOD(bus_alloc_resource,		bus_generic_rl_alloc_resource),
676	DEVMETHOD(bus_adjust_resource,		bus_generic_adjust_resource),
677	DEVMETHOD(bus_release_resource,		bus_generic_rl_release_resource),
678	DEVMETHOD(bus_activate_resource,	bus_generic_activate_resource),
679	DEVMETHOD(bus_deactivate_resource,	bus_generic_deactivate_resource),
680
681	DEVMETHOD(bus_setup_intr,		bus_generic_setup_intr),
682	DEVMETHOD(bus_teardown_intr,		bus_generic_teardown_intr),
683	DEVMETHOD(bus_config_intr,		bus_generic_config_intr),
684	DEVMETHOD(bus_bind_intr,		bus_generic_bind_intr),
685	DEVMETHOD(bus_describe_intr,		bus_generic_describe_intr),
686
687	DEVMETHOD(bus_get_dma_tag,		bus_generic_get_dma_tag),
688
689	/* BHND interface */
690	DEVMETHOD(bhnd_bus_get_chipid,		bhnd_bus_generic_get_chipid),
691	DEVMETHOD(bhnd_bus_get_probe_order,	bhnd_generic_get_probe_order),
692	DEVMETHOD(bhnd_bus_is_region_valid,	bhnd_generic_is_region_valid),
693	DEVMETHOD(bhnd_bus_is_hw_disabled,	bhnd_bus_generic_is_hw_disabled),
694	DEVMETHOD(bhnd_bus_get_nvram_var,	bhnd_bus_generic_get_nvram_var),
695
696	/* BHND interface (bus I/O) */
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
704	DEVMETHOD(bhnd_bus_read_stream_1,	bhnd_read_stream_1),
705	DEVMETHOD(bhnd_bus_read_stream_2,	bhnd_read_stream_2),
706	DEVMETHOD(bhnd_bus_read_stream_4,	bhnd_read_stream_4),
707	DEVMETHOD(bhnd_bus_write_stream_1,	bhnd_write_stream_1),
708	DEVMETHOD(bhnd_bus_write_stream_2,	bhnd_write_stream_2),
709	DEVMETHOD(bhnd_bus_write_stream_4,	bhnd_write_stream_4),
710
711	DEVMETHOD(bhnd_bus_read_multi_1,	bhnd_read_multi_1),
712	DEVMETHOD(bhnd_bus_read_multi_2,	bhnd_read_multi_2),
713	DEVMETHOD(bhnd_bus_read_multi_4,	bhnd_read_multi_4),
714	DEVMETHOD(bhnd_bus_write_multi_1,	bhnd_write_multi_1),
715	DEVMETHOD(bhnd_bus_write_multi_2,	bhnd_write_multi_2),
716	DEVMETHOD(bhnd_bus_write_multi_4,	bhnd_write_multi_4),
717
718	DEVMETHOD(bhnd_bus_read_multi_stream_1,	bhnd_read_multi_stream_1),
719	DEVMETHOD(bhnd_bus_read_multi_stream_2,	bhnd_read_multi_stream_2),
720	DEVMETHOD(bhnd_bus_read_multi_stream_4,	bhnd_read_multi_stream_4),
721	DEVMETHOD(bhnd_bus_write_multi_stream_1,bhnd_write_multi_stream_1),
722	DEVMETHOD(bhnd_bus_write_multi_stream_2,bhnd_write_multi_stream_2),
723	DEVMETHOD(bhnd_bus_write_multi_stream_4,bhnd_write_multi_stream_4),
724
725	DEVMETHOD(bhnd_bus_set_multi_1,		bhnd_set_multi_1),
726	DEVMETHOD(bhnd_bus_set_multi_2,		bhnd_set_multi_2),
727	DEVMETHOD(bhnd_bus_set_multi_4,		bhnd_set_multi_4),
728
729	DEVMETHOD(bhnd_bus_set_region_1,	bhnd_set_region_1),
730	DEVMETHOD(bhnd_bus_set_region_2,	bhnd_set_region_2),
731	DEVMETHOD(bhnd_bus_set_region_4,	bhnd_set_region_4),
732
733	DEVMETHOD(bhnd_bus_read_region_1,	bhnd_read_region_1),
734	DEVMETHOD(bhnd_bus_read_region_2,	bhnd_read_region_2),
735	DEVMETHOD(bhnd_bus_read_region_4,	bhnd_read_region_4),
736	DEVMETHOD(bhnd_bus_write_region_1,	bhnd_write_region_1),
737	DEVMETHOD(bhnd_bus_write_region_2,	bhnd_write_region_2),
738	DEVMETHOD(bhnd_bus_write_region_4,	bhnd_write_region_4),
739
740	DEVMETHOD(bhnd_bus_read_region_stream_1,bhnd_read_region_stream_1),
741	DEVMETHOD(bhnd_bus_read_region_stream_2,bhnd_read_region_stream_2),
742	DEVMETHOD(bhnd_bus_read_region_stream_4,bhnd_read_region_stream_4),
743	DEVMETHOD(bhnd_bus_write_region_stream_1, bhnd_write_region_stream_1),
744	DEVMETHOD(bhnd_bus_write_region_stream_2, bhnd_write_region_stream_2),
745	DEVMETHOD(bhnd_bus_write_region_stream_4, bhnd_write_region_stream_4),
746
747	DEVMETHOD(bhnd_bus_barrier,			bhnd_barrier),
748
749	DEVMETHOD_END
750};
751
752devclass_t bhnd_devclass;	/**< bhnd bus. */
753devclass_t bhnd_hostb_devclass;	/**< bhnd bus host bridge. */
754devclass_t bhnd_nvram_devclass;	/**< bhnd NVRAM device */
755
756DEFINE_CLASS_0(bhnd, bhnd_driver, bhnd_methods, sizeof(struct bhnd_softc));
757MODULE_VERSION(bhnd, 1);
758