xref: /freebsd/sys/dev/bhnd/bhnd.c (revision fdedcd9f95e22a3e443cdd4b3df5d58de6ac6c28)
14ad7e9b0SAdrian Chadd /*-
24ad7e9b0SAdrian Chadd  * Copyright (c) 2015 Landon Fuller <landon@landonf.org>
34ad7e9b0SAdrian Chadd  * All rights reserved.
44ad7e9b0SAdrian Chadd  *
54ad7e9b0SAdrian Chadd  * Redistribution and use in source and binary forms, with or without
64ad7e9b0SAdrian Chadd  * modification, are permitted provided that the following conditions
74ad7e9b0SAdrian Chadd  * are met:
84ad7e9b0SAdrian Chadd  * 1. Redistributions of source code must retain the above copyright
94ad7e9b0SAdrian Chadd  *    notice, this list of conditions and the following disclaimer,
104ad7e9b0SAdrian Chadd  *    without modification.
114ad7e9b0SAdrian Chadd  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
124ad7e9b0SAdrian Chadd  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
134ad7e9b0SAdrian Chadd  *    redistribution must be conditioned upon including a substantially
144ad7e9b0SAdrian Chadd  *    similar Disclaimer requirement for further binary redistribution.
154ad7e9b0SAdrian Chadd  *
164ad7e9b0SAdrian Chadd  * NO WARRANTY
174ad7e9b0SAdrian Chadd  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
184ad7e9b0SAdrian Chadd  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
194ad7e9b0SAdrian Chadd  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
204ad7e9b0SAdrian Chadd  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
214ad7e9b0SAdrian Chadd  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
224ad7e9b0SAdrian Chadd  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
234ad7e9b0SAdrian Chadd  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
244ad7e9b0SAdrian Chadd  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
254ad7e9b0SAdrian Chadd  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
264ad7e9b0SAdrian Chadd  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
274ad7e9b0SAdrian Chadd  * THE POSSIBILITY OF SUCH DAMAGES.
284ad7e9b0SAdrian Chadd  */
294ad7e9b0SAdrian Chadd 
304ad7e9b0SAdrian Chadd #include <sys/cdefs.h>
314ad7e9b0SAdrian Chadd __FBSDID("$FreeBSD$");
324ad7e9b0SAdrian Chadd 
334ad7e9b0SAdrian Chadd /*
344ad7e9b0SAdrian Chadd  * Broadcom Home Networking Division (HND) Bus Driver.
354ad7e9b0SAdrian Chadd  *
364ad7e9b0SAdrian Chadd  * The Broadcom HND family of devices consists of both SoCs and host-connected
374ad7e9b0SAdrian Chadd  * networking chipsets containing a common family of Broadcom IP cores,
384ad7e9b0SAdrian Chadd  * including an integrated MIPS and/or ARM cores.
394ad7e9b0SAdrian Chadd  *
404ad7e9b0SAdrian Chadd  * HND devices expose a nearly identical interface whether accessible over a
414ad7e9b0SAdrian Chadd  * native SoC interconnect, or when connected via a host interface such as
424ad7e9b0SAdrian Chadd  * PCIe. As a result, the majority of hardware support code should be re-usable
434ad7e9b0SAdrian Chadd  * across host drivers for HND networking chipsets, as well as FreeBSD support
444ad7e9b0SAdrian Chadd  * for Broadcom MIPS/ARM HND SoCs.
454ad7e9b0SAdrian Chadd  *
464ad7e9b0SAdrian Chadd  * Earlier HND models used the siba(4) on-chip interconnect, while later models
474ad7e9b0SAdrian Chadd  * use bcma(4); the programming model is almost entirely independent
484ad7e9b0SAdrian Chadd  * of the actual underlying interconect.
494ad7e9b0SAdrian Chadd  */
504ad7e9b0SAdrian Chadd 
514ad7e9b0SAdrian Chadd #include <sys/param.h>
524ad7e9b0SAdrian Chadd #include <sys/kernel.h>
534ad7e9b0SAdrian Chadd #include <sys/bus.h>
544ad7e9b0SAdrian Chadd #include <sys/module.h>
554ad7e9b0SAdrian Chadd #include <sys/systm.h>
564ad7e9b0SAdrian Chadd 
574ad7e9b0SAdrian Chadd #include <machine/bus.h>
584ad7e9b0SAdrian Chadd #include <sys/rman.h>
594ad7e9b0SAdrian Chadd #include <machine/resource.h>
604ad7e9b0SAdrian Chadd 
61*fdedcd9fSLandon J. Fuller #include <dev/bhnd/cores/chipc/chipcvar.h>
62*fdedcd9fSLandon J. Fuller 
63*fdedcd9fSLandon J. Fuller #include "bhnd_chipc_if.h"
64*fdedcd9fSLandon J. Fuller #include "bhnd_nvram_if.h"
65*fdedcd9fSLandon J. Fuller 
664ad7e9b0SAdrian Chadd #include "bhnd.h"
674ad7e9b0SAdrian Chadd #include "bhndvar.h"
684ad7e9b0SAdrian Chadd 
694ad7e9b0SAdrian Chadd MALLOC_DEFINE(M_BHND, "bhnd", "bhnd bus data structures");
704ad7e9b0SAdrian Chadd 
71*fdedcd9fSLandon J. Fuller /* Bus pass at which all bus-required children must be available, and
72*fdedcd9fSLandon J. Fuller  * attachment may be finalized. */
73*fdedcd9fSLandon J. Fuller #define	BHND_FINISH_ATTACH_PASS	BUS_PASS_DEFAULT
74*fdedcd9fSLandon J. Fuller 
754ad7e9b0SAdrian Chadd /**
764ad7e9b0SAdrian Chadd  * bhnd_generic_probe_nomatch() reporting configuration.
774ad7e9b0SAdrian Chadd  */
784ad7e9b0SAdrian Chadd static const struct bhnd_nomatch {
794ad7e9b0SAdrian Chadd 	uint16_t	vendor;		/**< core designer */
804ad7e9b0SAdrian Chadd 	uint16_t	device;		/**< core id */
814ad7e9b0SAdrian Chadd 	bool		if_verbose;	/**< print when bootverbose is set. */
824ad7e9b0SAdrian Chadd } bhnd_nomatch_table[] = {
834ad7e9b0SAdrian Chadd 	{ BHND_MFGID_ARM,	BHND_COREID_OOB_ROUTER,		true	},
844ad7e9b0SAdrian Chadd 	{ BHND_MFGID_ARM,	BHND_COREID_EROM,		true	},
854ad7e9b0SAdrian Chadd 	{ BHND_MFGID_ARM,	BHND_COREID_PL301,		true	},
864ad7e9b0SAdrian Chadd 	{ BHND_MFGID_ARM,	BHND_COREID_APB_BRIDGE,		true	},
874ad7e9b0SAdrian Chadd 	{ BHND_MFGID_ARM,	BHND_COREID_AXI_UNMAPPED,	false	},
884ad7e9b0SAdrian Chadd 
894ad7e9b0SAdrian Chadd 	{ BHND_MFGID_INVALID,	BHND_COREID_INVALID,		false	}
904ad7e9b0SAdrian Chadd };
914ad7e9b0SAdrian Chadd 
92*fdedcd9fSLandon J. Fuller 
93*fdedcd9fSLandon J. Fuller static int			 bhnd_delete_children(struct bhnd_softc *sc);
94*fdedcd9fSLandon J. Fuller 
95*fdedcd9fSLandon J. Fuller static int			 bhnd_finish_attach(struct bhnd_softc *sc);
96*fdedcd9fSLandon J. Fuller 
97*fdedcd9fSLandon J. Fuller static device_t			 bhnd_find_chipc(struct bhnd_softc *sc);
98*fdedcd9fSLandon J. Fuller static struct chipc_caps	*bhnd_find_chipc_caps(struct bhnd_softc *sc);
99*fdedcd9fSLandon J. Fuller static device_t			 bhnd_find_platform_dev(struct bhnd_softc *sc,
100*fdedcd9fSLandon J. Fuller 				     const char *classname);
101*fdedcd9fSLandon J. Fuller static device_t			 bhnd_find_pmu(struct bhnd_softc *sc);
102*fdedcd9fSLandon J. Fuller static device_t			 bhnd_find_nvram(struct bhnd_softc *sc);
103*fdedcd9fSLandon J. Fuller 
1044ad7e9b0SAdrian Chadd static int			 compare_ascending_probe_order(const void *lhs,
1054ad7e9b0SAdrian Chadd 				     const void *rhs);
1064ad7e9b0SAdrian Chadd static int			 compare_descending_probe_order(const void *lhs,
1074ad7e9b0SAdrian Chadd 				     const void *rhs);
1084ad7e9b0SAdrian Chadd 
1094ad7e9b0SAdrian Chadd /**
110386fb140SAdrian Chadd  * Default bhnd(4) bus driver implementation of DEVICE_ATTACH().
1114ad7e9b0SAdrian Chadd  *
112386fb140SAdrian Chadd  * This implementation calls device_probe_and_attach() for each of the device's
113386fb140SAdrian Chadd  * children, in bhnd probe order.
1144ad7e9b0SAdrian Chadd  */
1154ad7e9b0SAdrian Chadd int
1164ad7e9b0SAdrian Chadd bhnd_generic_attach(device_t dev)
1174ad7e9b0SAdrian Chadd {
118*fdedcd9fSLandon J. Fuller 	struct bhnd_softc	*sc;
1194ad7e9b0SAdrian Chadd 	device_t		*devs;
1204ad7e9b0SAdrian Chadd 	int			 ndevs;
1214ad7e9b0SAdrian Chadd 	int			 error;
1224ad7e9b0SAdrian Chadd 
1234ad7e9b0SAdrian Chadd 	if (device_is_attached(dev))
1244ad7e9b0SAdrian Chadd 		return (EBUSY);
1254ad7e9b0SAdrian Chadd 
126*fdedcd9fSLandon J. Fuller 	sc = device_get_softc(dev);
127*fdedcd9fSLandon J. Fuller 	sc->dev = dev;
128*fdedcd9fSLandon J. Fuller 
1294ad7e9b0SAdrian Chadd 	if ((error = device_get_children(dev, &devs, &ndevs)))
1304ad7e9b0SAdrian Chadd 		return (error);
1314ad7e9b0SAdrian Chadd 
132*fdedcd9fSLandon J. Fuller 	/* Probe and attach all children */
1334ad7e9b0SAdrian Chadd 	qsort(devs, ndevs, sizeof(*devs), compare_ascending_probe_order);
1344ad7e9b0SAdrian Chadd 	for (int i = 0; i < ndevs; i++) {
1354ad7e9b0SAdrian Chadd 		device_t child = devs[i];
1364ad7e9b0SAdrian Chadd 		device_probe_and_attach(child);
1374ad7e9b0SAdrian Chadd 	}
1384ad7e9b0SAdrian Chadd 
139*fdedcd9fSLandon J. Fuller 	/* Try to finalize attachment */
140*fdedcd9fSLandon J. Fuller 	if (bus_current_pass >= BHND_FINISH_ATTACH_PASS) {
141*fdedcd9fSLandon J. Fuller 		if ((error = bhnd_finish_attach(sc)))
142*fdedcd9fSLandon J. Fuller 			goto cleanup;
143*fdedcd9fSLandon J. Fuller 	}
144*fdedcd9fSLandon J. Fuller 
145*fdedcd9fSLandon J. Fuller cleanup:
1464ad7e9b0SAdrian Chadd 	free(devs, M_TEMP);
147*fdedcd9fSLandon J. Fuller 
148*fdedcd9fSLandon J. Fuller 	if (error)
149*fdedcd9fSLandon J. Fuller 		bhnd_delete_children(sc);
150*fdedcd9fSLandon J. Fuller 
151*fdedcd9fSLandon J. Fuller 	return (error);
152*fdedcd9fSLandon J. Fuller }
153*fdedcd9fSLandon J. Fuller 
154*fdedcd9fSLandon J. Fuller /**
155*fdedcd9fSLandon J. Fuller  * Detach and delete all children, in reverse of their attach order.
156*fdedcd9fSLandon J. Fuller  */
157*fdedcd9fSLandon J. Fuller static int
158*fdedcd9fSLandon J. Fuller bhnd_delete_children(struct bhnd_softc *sc)
159*fdedcd9fSLandon J. Fuller {
160*fdedcd9fSLandon J. Fuller 	device_t		*devs;
161*fdedcd9fSLandon J. Fuller 	int			 ndevs;
162*fdedcd9fSLandon J. Fuller 	int			 error;
163*fdedcd9fSLandon J. Fuller 
164*fdedcd9fSLandon J. Fuller 	if ((error = device_get_children(sc->dev, &devs, &ndevs)))
165*fdedcd9fSLandon J. Fuller 		return (error);
166*fdedcd9fSLandon J. Fuller 
167*fdedcd9fSLandon J. Fuller 	/* Detach in the reverse of attach order */
168*fdedcd9fSLandon J. Fuller 	qsort(devs, ndevs, sizeof(*devs), compare_descending_probe_order);
169*fdedcd9fSLandon J. Fuller 	for (int i = 0; i < ndevs; i++) {
170*fdedcd9fSLandon J. Fuller 		device_t child = devs[i];
171*fdedcd9fSLandon J. Fuller 
172*fdedcd9fSLandon J. Fuller 		/* Terminate on first error */
173*fdedcd9fSLandon J. Fuller 		if ((error = device_delete_child(sc->dev, child)))
174*fdedcd9fSLandon J. Fuller 			goto cleanup;
175*fdedcd9fSLandon J. Fuller 	}
176*fdedcd9fSLandon J. Fuller 
177*fdedcd9fSLandon J. Fuller cleanup:
178*fdedcd9fSLandon J. Fuller 	free(devs, M_TEMP);
179*fdedcd9fSLandon J. Fuller 	return (error);
1804ad7e9b0SAdrian Chadd }
1814ad7e9b0SAdrian Chadd 
1824ad7e9b0SAdrian Chadd /**
183386fb140SAdrian Chadd  * Default bhnd(4) bus driver implementation of DEVICE_DETACH().
1844ad7e9b0SAdrian Chadd  *
185cef367e6SEitan Adler  * This implementation calls device_detach() for each of the device's
186386fb140SAdrian Chadd  * children, in reverse bhnd probe order, terminating if any call to
187386fb140SAdrian Chadd  * device_detach() fails.
1884ad7e9b0SAdrian Chadd  */
1894ad7e9b0SAdrian Chadd int
1904ad7e9b0SAdrian Chadd bhnd_generic_detach(device_t dev)
1914ad7e9b0SAdrian Chadd {
192*fdedcd9fSLandon J. Fuller 	struct bhnd_softc	*sc;
1934ad7e9b0SAdrian Chadd 
1944ad7e9b0SAdrian Chadd 	if (!device_is_attached(dev))
1954ad7e9b0SAdrian Chadd 		return (EBUSY);
1964ad7e9b0SAdrian Chadd 
197*fdedcd9fSLandon J. Fuller 	sc = device_get_softc(dev);
198*fdedcd9fSLandon J. Fuller 	return (bhnd_delete_children(sc));
1994ad7e9b0SAdrian Chadd }
2004ad7e9b0SAdrian Chadd 
2014ad7e9b0SAdrian Chadd /**
202386fb140SAdrian Chadd  * Default bhnd(4) bus driver implementation of DEVICE_SHUTDOWN().
2034ad7e9b0SAdrian Chadd  *
204386fb140SAdrian Chadd  * This implementation calls device_shutdown() for each of the device's
205386fb140SAdrian Chadd  * children, in reverse bhnd probe order, terminating if any call to
206386fb140SAdrian Chadd  * device_shutdown() fails.
2074ad7e9b0SAdrian Chadd  */
2084ad7e9b0SAdrian Chadd int
2094ad7e9b0SAdrian Chadd bhnd_generic_shutdown(device_t dev)
2104ad7e9b0SAdrian Chadd {
2114ad7e9b0SAdrian Chadd 	device_t	*devs;
2124ad7e9b0SAdrian Chadd 	int		 ndevs;
2134ad7e9b0SAdrian Chadd 	int		 error;
2144ad7e9b0SAdrian Chadd 
2154ad7e9b0SAdrian Chadd 	if (!device_is_attached(dev))
2164ad7e9b0SAdrian Chadd 		return (EBUSY);
2174ad7e9b0SAdrian Chadd 
2184ad7e9b0SAdrian Chadd 	if ((error = device_get_children(dev, &devs, &ndevs)))
2194ad7e9b0SAdrian Chadd 		return (error);
2204ad7e9b0SAdrian Chadd 
2214ad7e9b0SAdrian Chadd 	/* Shutdown in the reverse of attach order */
2224ad7e9b0SAdrian Chadd 	qsort(devs, ndevs, sizeof(*devs), compare_descending_probe_order);
2234ad7e9b0SAdrian Chadd 	for (int i = 0; i < ndevs; i++) {
2244ad7e9b0SAdrian Chadd 		device_t child = devs[i];
2254ad7e9b0SAdrian Chadd 
2264ad7e9b0SAdrian Chadd 		/* Terminate on first error */
2274ad7e9b0SAdrian Chadd 		if ((error = device_shutdown(child)))
2284ad7e9b0SAdrian Chadd 			goto cleanup;
2294ad7e9b0SAdrian Chadd 	}
2304ad7e9b0SAdrian Chadd 
2314ad7e9b0SAdrian Chadd cleanup:
2324ad7e9b0SAdrian Chadd 	free(devs, M_TEMP);
2334ad7e9b0SAdrian Chadd 	return (error);
2344ad7e9b0SAdrian Chadd }
2354ad7e9b0SAdrian Chadd 
2364ad7e9b0SAdrian Chadd /**
237386fb140SAdrian Chadd  * Default bhnd(4) bus driver implementation of DEVICE_RESUME().
2384ad7e9b0SAdrian Chadd  *
239386fb140SAdrian Chadd  * This implementation calls BUS_RESUME_CHILD() for each of the device's
240386fb140SAdrian Chadd  * children in bhnd probe order, terminating if any call to BUS_RESUME_CHILD()
241386fb140SAdrian Chadd  * fails.
2424ad7e9b0SAdrian Chadd  */
2434ad7e9b0SAdrian Chadd int
2444ad7e9b0SAdrian Chadd bhnd_generic_resume(device_t dev)
2454ad7e9b0SAdrian Chadd {
2464ad7e9b0SAdrian Chadd 	device_t	*devs;
2474ad7e9b0SAdrian Chadd 	int		 ndevs;
2484ad7e9b0SAdrian Chadd 	int		 error;
2494ad7e9b0SAdrian Chadd 
2504ad7e9b0SAdrian Chadd 	if (!device_is_attached(dev))
2514ad7e9b0SAdrian Chadd 		return (EBUSY);
2524ad7e9b0SAdrian Chadd 
2534ad7e9b0SAdrian Chadd 	if ((error = device_get_children(dev, &devs, &ndevs)))
2544ad7e9b0SAdrian Chadd 		return (error);
2554ad7e9b0SAdrian Chadd 
2564ad7e9b0SAdrian Chadd 	qsort(devs, ndevs, sizeof(*devs), compare_ascending_probe_order);
2574ad7e9b0SAdrian Chadd 	for (int i = 0; i < ndevs; i++) {
2584ad7e9b0SAdrian Chadd 		device_t child = devs[i];
2594ad7e9b0SAdrian Chadd 
2604ad7e9b0SAdrian Chadd 		/* Terminate on first error */
2614ad7e9b0SAdrian Chadd 		if ((error = BUS_RESUME_CHILD(device_get_parent(child), child)))
2624ad7e9b0SAdrian Chadd 			goto cleanup;
2634ad7e9b0SAdrian Chadd 	}
2644ad7e9b0SAdrian Chadd 
2654ad7e9b0SAdrian Chadd cleanup:
2664ad7e9b0SAdrian Chadd 	free(devs, M_TEMP);
2674ad7e9b0SAdrian Chadd 	return (error);
2684ad7e9b0SAdrian Chadd }
2694ad7e9b0SAdrian Chadd 
2704ad7e9b0SAdrian Chadd /**
271386fb140SAdrian Chadd  * Default bhnd(4) bus driver implementation of DEVICE_SUSPEND().
2724ad7e9b0SAdrian Chadd  *
273386fb140SAdrian Chadd  * This implementation calls BUS_SUSPEND_CHILD() for each of the device's
274386fb140SAdrian Chadd  * children in reverse bhnd probe order. If any call to BUS_SUSPEND_CHILD()
275386fb140SAdrian Chadd  * fails, the suspend operation is terminated and any devices that were
276386fb140SAdrian Chadd  * suspended are resumed immediately by calling their BUS_RESUME_CHILD()
277386fb140SAdrian Chadd  * methods.
2784ad7e9b0SAdrian Chadd  */
2794ad7e9b0SAdrian Chadd int
2804ad7e9b0SAdrian Chadd bhnd_generic_suspend(device_t dev)
2814ad7e9b0SAdrian Chadd {
2824ad7e9b0SAdrian Chadd 	device_t	*devs;
2834ad7e9b0SAdrian Chadd 	int		 ndevs;
2844ad7e9b0SAdrian Chadd 	int		 error;
2854ad7e9b0SAdrian Chadd 
2864ad7e9b0SAdrian Chadd 	if (!device_is_attached(dev))
2874ad7e9b0SAdrian Chadd 		return (EBUSY);
2884ad7e9b0SAdrian Chadd 
2894ad7e9b0SAdrian Chadd 	if ((error = device_get_children(dev, &devs, &ndevs)))
2904ad7e9b0SAdrian Chadd 		return (error);
2914ad7e9b0SAdrian Chadd 
2924ad7e9b0SAdrian Chadd 	/* Suspend in the reverse of attach order */
2934ad7e9b0SAdrian Chadd 	qsort(devs, ndevs, sizeof(*devs), compare_descending_probe_order);
2944ad7e9b0SAdrian Chadd 	for (int i = 0; i < ndevs; i++) {
2954ad7e9b0SAdrian Chadd 		device_t child = devs[i];
2964ad7e9b0SAdrian Chadd 		error = BUS_SUSPEND_CHILD(device_get_parent(child), child);
2974ad7e9b0SAdrian Chadd 
2984ad7e9b0SAdrian Chadd 		/* On error, resume suspended devices and then terminate */
2994ad7e9b0SAdrian Chadd 		if (error) {
3004ad7e9b0SAdrian Chadd 			for (int j = 0; j < i; j++) {
3014ad7e9b0SAdrian Chadd 				BUS_RESUME_CHILD(device_get_parent(devs[j]),
3024ad7e9b0SAdrian Chadd 				    devs[j]);
3034ad7e9b0SAdrian Chadd 			}
3044ad7e9b0SAdrian Chadd 
3054ad7e9b0SAdrian Chadd 			goto cleanup;
3064ad7e9b0SAdrian Chadd 		}
3074ad7e9b0SAdrian Chadd 	}
3084ad7e9b0SAdrian Chadd 
3094ad7e9b0SAdrian Chadd cleanup:
3104ad7e9b0SAdrian Chadd 	free(devs, M_TEMP);
3114ad7e9b0SAdrian Chadd 	return (error);
3124ad7e9b0SAdrian Chadd }
3134ad7e9b0SAdrian Chadd 
314*fdedcd9fSLandon J. Fuller static void
315*fdedcd9fSLandon J. Fuller bhnd_new_pass(device_t dev)
316*fdedcd9fSLandon J. Fuller {
317*fdedcd9fSLandon J. Fuller 	struct bhnd_softc	*sc;
318*fdedcd9fSLandon J. Fuller 	int			 error;
319*fdedcd9fSLandon J. Fuller 
320*fdedcd9fSLandon J. Fuller 	sc = device_get_softc(dev);
321*fdedcd9fSLandon J. Fuller 
322*fdedcd9fSLandon J. Fuller 	/* Attach any permissible children */
323*fdedcd9fSLandon J. Fuller 	bus_generic_new_pass(dev);
324*fdedcd9fSLandon J. Fuller 
325*fdedcd9fSLandon J. Fuller 	/* Finalize attachment */
326*fdedcd9fSLandon J. Fuller 	if (!sc->attach_done && bus_current_pass >= BHND_FINISH_ATTACH_PASS) {
327*fdedcd9fSLandon J. Fuller 		if ((error = bhnd_finish_attach(sc))) {
328*fdedcd9fSLandon J. Fuller 			panic("bhnd_finish_attach() failed: %d", error);
329*fdedcd9fSLandon J. Fuller 		}
330*fdedcd9fSLandon J. Fuller 	}
331*fdedcd9fSLandon J. Fuller }
332*fdedcd9fSLandon J. Fuller 
333*fdedcd9fSLandon J. Fuller /*
334*fdedcd9fSLandon J. Fuller  * Finish any pending bus attachment operations.
335*fdedcd9fSLandon J. Fuller  *
336*fdedcd9fSLandon J. Fuller  * When attached as a SoC bus (as opposed to a bridged WiFi device), our
337*fdedcd9fSLandon J. Fuller  * platform devices may not be attached until later bus passes, necessitating
338*fdedcd9fSLandon J. Fuller  * delayed initialization on our part.
339*fdedcd9fSLandon J. Fuller  */
340*fdedcd9fSLandon J. Fuller static int
341*fdedcd9fSLandon J. Fuller bhnd_finish_attach(struct bhnd_softc *sc)
342*fdedcd9fSLandon J. Fuller {
343*fdedcd9fSLandon J. Fuller 	struct chipc_caps	*ccaps;
344*fdedcd9fSLandon J. Fuller 
345*fdedcd9fSLandon J. Fuller 	GIANT_REQUIRED;	/* newbus */
346*fdedcd9fSLandon J. Fuller 
347*fdedcd9fSLandon J. Fuller 	KASSERT(bus_current_pass >= BHND_FINISH_ATTACH_PASS,
348*fdedcd9fSLandon J. Fuller 	    ("bhnd_finish_attach() called in pass %d", bus_current_pass));
349*fdedcd9fSLandon J. Fuller 
350*fdedcd9fSLandon J. Fuller 	KASSERT(!sc->attach_done, ("duplicate call to bhnd_finish_attach()"));
351*fdedcd9fSLandon J. Fuller 
352*fdedcd9fSLandon J. Fuller 	/* Locate chipc device */
353*fdedcd9fSLandon J. Fuller 	if ((sc->chipc_dev = bhnd_find_chipc(sc)) == NULL) {
354*fdedcd9fSLandon J. Fuller 		device_printf(sc->dev, "error: ChipCommon device not found\n");
355*fdedcd9fSLandon J. Fuller 		return (ENXIO);
356*fdedcd9fSLandon J. Fuller 	}
357*fdedcd9fSLandon J. Fuller 
358*fdedcd9fSLandon J. Fuller 	ccaps = BHND_CHIPC_GET_CAPS(sc->chipc_dev);
359*fdedcd9fSLandon J. Fuller 
360*fdedcd9fSLandon J. Fuller 	/* Look for NVRAM device */
361*fdedcd9fSLandon J. Fuller 	if (ccaps->nvram_src != BHND_NVRAM_SRC_UNKNOWN) {
362*fdedcd9fSLandon J. Fuller 		if ((sc->nvram_dev = bhnd_find_nvram(sc)) == NULL) {
363*fdedcd9fSLandon J. Fuller 			device_printf(sc->dev,
364*fdedcd9fSLandon J. Fuller 			    "warning: %s NVRAM device not found\n",
365*fdedcd9fSLandon J. Fuller 			    bhnd_nvram_src_name(ccaps->nvram_src));
366*fdedcd9fSLandon J. Fuller 		}
367*fdedcd9fSLandon J. Fuller 	}
368*fdedcd9fSLandon J. Fuller 
369*fdedcd9fSLandon J. Fuller 	/* Look for a PMU  */
370*fdedcd9fSLandon J. Fuller 	if (ccaps->pmu) {
371*fdedcd9fSLandon J. Fuller 		if ((sc->pmu_dev = bhnd_find_pmu(sc)) == NULL) {
372*fdedcd9fSLandon J. Fuller 			device_printf(sc->dev,
373*fdedcd9fSLandon J. Fuller 			    "warning: PMU device not found\n");
374*fdedcd9fSLandon J. Fuller 		}
375*fdedcd9fSLandon J. Fuller 	}
376*fdedcd9fSLandon J. Fuller 
377*fdedcd9fSLandon J. Fuller 	/* Mark attach as completed */
378*fdedcd9fSLandon J. Fuller 	sc->attach_done = true;
379*fdedcd9fSLandon J. Fuller 
380*fdedcd9fSLandon J. Fuller 	return (0);
381*fdedcd9fSLandon J. Fuller }
382*fdedcd9fSLandon J. Fuller 
383*fdedcd9fSLandon J. Fuller /* Locate the ChipCommon core. */
384*fdedcd9fSLandon J. Fuller static device_t
385*fdedcd9fSLandon J. Fuller bhnd_find_chipc(struct bhnd_softc *sc)
386*fdedcd9fSLandon J. Fuller {
387*fdedcd9fSLandon J. Fuller 	device_t chipc;
388*fdedcd9fSLandon J. Fuller 
389*fdedcd9fSLandon J. Fuller         /* Make sure we're holding Giant for newbus */
390*fdedcd9fSLandon J. Fuller 	GIANT_REQUIRED;
391*fdedcd9fSLandon J. Fuller 
392*fdedcd9fSLandon J. Fuller 	/* chipc_dev is initialized during attachment */
393*fdedcd9fSLandon J. Fuller 	if (sc->attach_done) {
394*fdedcd9fSLandon J. Fuller 		if ((chipc = sc->chipc_dev) == NULL)
395*fdedcd9fSLandon J. Fuller 			return (NULL);
396*fdedcd9fSLandon J. Fuller 
397*fdedcd9fSLandon J. Fuller 		goto found;
398*fdedcd9fSLandon J. Fuller 	}
399*fdedcd9fSLandon J. Fuller 
400*fdedcd9fSLandon J. Fuller 	/* Locate chipc core with a core unit of 0 */
401*fdedcd9fSLandon J. Fuller 	chipc = bhnd_find_child(sc->dev, BHND_DEVCLASS_CC, 0);
402*fdedcd9fSLandon J. Fuller 	if (chipc == NULL)
403*fdedcd9fSLandon J. Fuller 		return (NULL);
404*fdedcd9fSLandon J. Fuller 
405*fdedcd9fSLandon J. Fuller found:
406*fdedcd9fSLandon J. Fuller 	if (device_get_state(chipc) < DS_ATTACHING) {
407*fdedcd9fSLandon J. Fuller 		device_printf(sc->dev, "chipc found, but did not attach\n");
408*fdedcd9fSLandon J. Fuller 		return (NULL);
409*fdedcd9fSLandon J. Fuller 	}
410*fdedcd9fSLandon J. Fuller 
411*fdedcd9fSLandon J. Fuller 	return (chipc);
412*fdedcd9fSLandon J. Fuller }
413*fdedcd9fSLandon J. Fuller 
414*fdedcd9fSLandon J. Fuller /* Locate the ChipCommon core and return the device capabilities  */
415*fdedcd9fSLandon J. Fuller static struct chipc_caps *
416*fdedcd9fSLandon J. Fuller bhnd_find_chipc_caps(struct bhnd_softc *sc)
417*fdedcd9fSLandon J. Fuller {
418*fdedcd9fSLandon J. Fuller 	device_t chipc;
419*fdedcd9fSLandon J. Fuller 
420*fdedcd9fSLandon J. Fuller 	if ((chipc = bhnd_find_chipc(sc)) == NULL) {
421*fdedcd9fSLandon J. Fuller 		device_printf(sc->dev,
422*fdedcd9fSLandon J. Fuller 		    "chipc unavailable; cannot fetch capabilities\n");
423*fdedcd9fSLandon J. Fuller 		return (NULL);
424*fdedcd9fSLandon J. Fuller 	}
425*fdedcd9fSLandon J. Fuller 
426*fdedcd9fSLandon J. Fuller 	return (BHND_CHIPC_GET_CAPS(chipc));
427*fdedcd9fSLandon J. Fuller }
428*fdedcd9fSLandon J. Fuller 
429*fdedcd9fSLandon J. Fuller /**
430*fdedcd9fSLandon J. Fuller  * Find an attached platform device on @p dev, searching first for cores
431*fdedcd9fSLandon J. Fuller  * matching @p classname, and if not found, searching the children of the first
432*fdedcd9fSLandon J. Fuller  * bhnd_chipc device on the bus.
433*fdedcd9fSLandon J. Fuller  *
434*fdedcd9fSLandon J. Fuller  * @param sc Driver state.
435*fdedcd9fSLandon J. Fuller  * @param chipc Attached ChipCommon device.
436*fdedcd9fSLandon J. Fuller  * @param classname Device class to search for.
437*fdedcd9fSLandon J. Fuller  *
438*fdedcd9fSLandon J. Fuller  * @retval device_t A matching device.
439*fdedcd9fSLandon J. Fuller  * @retval NULL If no matching device is found.
440*fdedcd9fSLandon J. Fuller  */
441*fdedcd9fSLandon J. Fuller static device_t
442*fdedcd9fSLandon J. Fuller bhnd_find_platform_dev(struct bhnd_softc *sc, const char *classname)
443*fdedcd9fSLandon J. Fuller {
444*fdedcd9fSLandon J. Fuller 	device_t chipc, child;
445*fdedcd9fSLandon J. Fuller 
446*fdedcd9fSLandon J. Fuller         /* Make sure we're holding Giant for newbus */
447*fdedcd9fSLandon J. Fuller 	GIANT_REQUIRED;
448*fdedcd9fSLandon J. Fuller 
449*fdedcd9fSLandon J. Fuller 	/* Look for a directly-attached child */
450*fdedcd9fSLandon J. Fuller 	child = device_find_child(sc->dev, classname, -1);
451*fdedcd9fSLandon J. Fuller 	if (child != NULL)
452*fdedcd9fSLandon J. Fuller 		goto found;
453*fdedcd9fSLandon J. Fuller 
454*fdedcd9fSLandon J. Fuller 	/* Look for the first matching ChipCommon child */
455*fdedcd9fSLandon J. Fuller 	if ((chipc = bhnd_find_chipc(sc)) == NULL) {
456*fdedcd9fSLandon J. Fuller 		device_printf(sc->dev,
457*fdedcd9fSLandon J. Fuller 		    "chipc unavailable; cannot locate %s\n", classname);
458*fdedcd9fSLandon J. Fuller 		return (NULL);
459*fdedcd9fSLandon J. Fuller 	}
460*fdedcd9fSLandon J. Fuller 
461*fdedcd9fSLandon J. Fuller 	child = device_find_child(chipc, classname, -1);
462*fdedcd9fSLandon J. Fuller 	if (child == NULL)
463*fdedcd9fSLandon J. Fuller 		return (NULL);
464*fdedcd9fSLandon J. Fuller 
465*fdedcd9fSLandon J. Fuller found:
466*fdedcd9fSLandon J. Fuller 	if (device_get_state(child) < DS_ATTACHING)
467*fdedcd9fSLandon J. Fuller 		return (NULL);
468*fdedcd9fSLandon J. Fuller 
469*fdedcd9fSLandon J. Fuller 	return (child);
470*fdedcd9fSLandon J. Fuller }
471*fdedcd9fSLandon J. Fuller 
472*fdedcd9fSLandon J. Fuller /* Locate the PMU device, if any */
473*fdedcd9fSLandon J. Fuller static device_t
474*fdedcd9fSLandon J. Fuller bhnd_find_pmu(struct bhnd_softc *sc)
475*fdedcd9fSLandon J. Fuller {
476*fdedcd9fSLandon J. Fuller 	struct chipc_caps	*ccaps;
477*fdedcd9fSLandon J. Fuller 
478*fdedcd9fSLandon J. Fuller         /* Make sure we're holding Giant for newbus */
479*fdedcd9fSLandon J. Fuller 	GIANT_REQUIRED;
480*fdedcd9fSLandon J. Fuller 
481*fdedcd9fSLandon J. Fuller 	/* pmu_dev is initialized during attachment */
482*fdedcd9fSLandon J. Fuller 	if (sc->attach_done) {
483*fdedcd9fSLandon J. Fuller 		if (sc->pmu_dev == NULL)
484*fdedcd9fSLandon J. Fuller 			return (NULL);
485*fdedcd9fSLandon J. Fuller 
486*fdedcd9fSLandon J. Fuller 		if (device_get_state(sc->pmu_dev) < DS_ATTACHING)
487*fdedcd9fSLandon J. Fuller 			return (NULL);
488*fdedcd9fSLandon J. Fuller 
489*fdedcd9fSLandon J. Fuller 		return (sc->pmu_dev);
490*fdedcd9fSLandon J. Fuller 	}
491*fdedcd9fSLandon J. Fuller 
492*fdedcd9fSLandon J. Fuller 	if ((ccaps = bhnd_find_chipc_caps(sc)) == NULL)
493*fdedcd9fSLandon J. Fuller 		return (NULL);
494*fdedcd9fSLandon J. Fuller 
495*fdedcd9fSLandon J. Fuller 	if (!ccaps->pmu)
496*fdedcd9fSLandon J. Fuller 		return (NULL);
497*fdedcd9fSLandon J. Fuller 
498*fdedcd9fSLandon J. Fuller 	return (bhnd_find_platform_dev(sc, "bhnd_pmu"));
499*fdedcd9fSLandon J. Fuller }
500*fdedcd9fSLandon J. Fuller 
501*fdedcd9fSLandon J. Fuller /* Locate the NVRAM device, if any */
502*fdedcd9fSLandon J. Fuller static device_t
503*fdedcd9fSLandon J. Fuller bhnd_find_nvram(struct bhnd_softc *sc)
504*fdedcd9fSLandon J. Fuller {
505*fdedcd9fSLandon J. Fuller 	struct chipc_caps *ccaps;
506*fdedcd9fSLandon J. Fuller 
507*fdedcd9fSLandon J. Fuller         /* Make sure we're holding Giant for newbus */
508*fdedcd9fSLandon J. Fuller 	GIANT_REQUIRED;
509*fdedcd9fSLandon J. Fuller 
510*fdedcd9fSLandon J. Fuller 
511*fdedcd9fSLandon J. Fuller 	/* nvram_dev is initialized during attachment */
512*fdedcd9fSLandon J. Fuller 	if (sc->attach_done) {
513*fdedcd9fSLandon J. Fuller 		if (sc->nvram_dev == NULL)
514*fdedcd9fSLandon J. Fuller 			return (NULL);
515*fdedcd9fSLandon J. Fuller 
516*fdedcd9fSLandon J. Fuller 		if (device_get_state(sc->nvram_dev) < DS_ATTACHING)
517*fdedcd9fSLandon J. Fuller 			return (NULL);
518*fdedcd9fSLandon J. Fuller 
519*fdedcd9fSLandon J. Fuller 		return (sc->nvram_dev);
520*fdedcd9fSLandon J. Fuller 	}
521*fdedcd9fSLandon J. Fuller 
522*fdedcd9fSLandon J. Fuller 	if ((ccaps = bhnd_find_chipc_caps(sc)) == NULL)
523*fdedcd9fSLandon J. Fuller 		return (NULL);
524*fdedcd9fSLandon J. Fuller 
525*fdedcd9fSLandon J. Fuller 	if (ccaps->nvram_src == BHND_NVRAM_SRC_UNKNOWN)
526*fdedcd9fSLandon J. Fuller 		return (NULL);
527*fdedcd9fSLandon J. Fuller 
528*fdedcd9fSLandon J. Fuller 	return (bhnd_find_platform_dev(sc, "bhnd_nvram"));
529*fdedcd9fSLandon J. Fuller }
530*fdedcd9fSLandon J. Fuller 
5314ad7e9b0SAdrian Chadd /*
5324ad7e9b0SAdrian Chadd  * Ascending comparison of bhnd device's probe order.
5334ad7e9b0SAdrian Chadd  */
5344ad7e9b0SAdrian Chadd static int
5354ad7e9b0SAdrian Chadd compare_ascending_probe_order(const void *lhs, const void *rhs)
5364ad7e9b0SAdrian Chadd {
5374ad7e9b0SAdrian Chadd 	device_t	ldev, rdev;
5384ad7e9b0SAdrian Chadd 	int		lorder, rorder;
5394ad7e9b0SAdrian Chadd 
5404ad7e9b0SAdrian Chadd 	ldev = (*(const device_t *) lhs);
5414ad7e9b0SAdrian Chadd 	rdev = (*(const device_t *) rhs);
5424ad7e9b0SAdrian Chadd 
5434ad7e9b0SAdrian Chadd 	lorder = BHND_BUS_GET_PROBE_ORDER(device_get_parent(ldev), ldev);
5444ad7e9b0SAdrian Chadd 	rorder = BHND_BUS_GET_PROBE_ORDER(device_get_parent(rdev), rdev);
5454ad7e9b0SAdrian Chadd 
5464ad7e9b0SAdrian Chadd 	if (lorder < rorder) {
5474ad7e9b0SAdrian Chadd 		return (-1);
5484ad7e9b0SAdrian Chadd 	} else if (lorder > rorder) {
5494ad7e9b0SAdrian Chadd 		return (1);
5504ad7e9b0SAdrian Chadd 	} else {
5514ad7e9b0SAdrian Chadd 		return (0);
5524ad7e9b0SAdrian Chadd 	}
5534ad7e9b0SAdrian Chadd }
5544ad7e9b0SAdrian Chadd 
5554ad7e9b0SAdrian Chadd /*
5564ad7e9b0SAdrian Chadd  * Descending comparison of bhnd device's probe order.
5574ad7e9b0SAdrian Chadd  */
5584ad7e9b0SAdrian Chadd static int
5594ad7e9b0SAdrian Chadd compare_descending_probe_order(const void *lhs, const void *rhs)
5604ad7e9b0SAdrian Chadd {
5614ad7e9b0SAdrian Chadd 	return (compare_ascending_probe_order(rhs, lhs));
5624ad7e9b0SAdrian Chadd }
5634ad7e9b0SAdrian Chadd 
5644ad7e9b0SAdrian Chadd /**
565386fb140SAdrian Chadd  * Default bhnd(4) bus driver implementation of BHND_BUS_GET_PROBE_ORDER().
5664ad7e9b0SAdrian Chadd  *
5674ad7e9b0SAdrian Chadd  * This implementation determines probe ordering based on the device's class
5684ad7e9b0SAdrian Chadd  * and other properties, including whether the device is serving as a host
5694ad7e9b0SAdrian Chadd  * bridge.
5704ad7e9b0SAdrian Chadd  */
5714ad7e9b0SAdrian Chadd int
5724ad7e9b0SAdrian Chadd bhnd_generic_get_probe_order(device_t dev, device_t child)
5734ad7e9b0SAdrian Chadd {
5744ad7e9b0SAdrian Chadd 	switch (bhnd_get_class(child)) {
5754ad7e9b0SAdrian Chadd 	case BHND_DEVCLASS_CC:
576d567592bSAdrian Chadd 		/* Must be early enough to provide NVRAM access to the
577d567592bSAdrian Chadd 		 * host bridge */
578d567592bSAdrian Chadd 		return (BHND_PROBE_ROOT + BHND_PROBE_ORDER_FIRST);
5794ad7e9b0SAdrian Chadd 
5804ad7e9b0SAdrian Chadd 	case BHND_DEVCLASS_CC_B:
5814ad7e9b0SAdrian Chadd 		/* fall through */
5824ad7e9b0SAdrian Chadd 	case BHND_DEVCLASS_PMU:
5834ad7e9b0SAdrian Chadd 		return (BHND_PROBE_BUS + BHND_PROBE_ORDER_EARLY);
5844ad7e9b0SAdrian Chadd 
5854ad7e9b0SAdrian Chadd 	case BHND_DEVCLASS_SOC_ROUTER:
5864ad7e9b0SAdrian Chadd 		return (BHND_PROBE_BUS + BHND_PROBE_ORDER_LATE);
5874ad7e9b0SAdrian Chadd 
5884ad7e9b0SAdrian Chadd 	case BHND_DEVCLASS_SOC_BRIDGE:
5894ad7e9b0SAdrian Chadd 		return (BHND_PROBE_BUS + BHND_PROBE_ORDER_LAST);
5904ad7e9b0SAdrian Chadd 
5914ad7e9b0SAdrian Chadd 	case BHND_DEVCLASS_CPU:
5924ad7e9b0SAdrian Chadd 		return (BHND_PROBE_CPU + BHND_PROBE_ORDER_FIRST);
5934ad7e9b0SAdrian Chadd 
5944ad7e9b0SAdrian Chadd 	case BHND_DEVCLASS_RAM:
5954ad7e9b0SAdrian Chadd 		/* fall through */
5964ad7e9b0SAdrian Chadd 	case BHND_DEVCLASS_MEMC:
5974ad7e9b0SAdrian Chadd 		return (BHND_PROBE_CPU + BHND_PROBE_ORDER_EARLY);
5984ad7e9b0SAdrian Chadd 
5994ad7e9b0SAdrian Chadd 	case BHND_DEVCLASS_NVRAM:
6004ad7e9b0SAdrian Chadd 		return (BHND_PROBE_RESOURCE + BHND_PROBE_ORDER_EARLY);
6014ad7e9b0SAdrian Chadd 
6024ad7e9b0SAdrian Chadd 	case BHND_DEVCLASS_PCI:
6034ad7e9b0SAdrian Chadd 	case BHND_DEVCLASS_PCIE:
6044ad7e9b0SAdrian Chadd 	case BHND_DEVCLASS_PCCARD:
6054ad7e9b0SAdrian Chadd 	case BHND_DEVCLASS_ENET:
6064ad7e9b0SAdrian Chadd 	case BHND_DEVCLASS_ENET_MAC:
6074ad7e9b0SAdrian Chadd 	case BHND_DEVCLASS_ENET_PHY:
6084ad7e9b0SAdrian Chadd 	case BHND_DEVCLASS_WLAN:
6094ad7e9b0SAdrian Chadd 	case BHND_DEVCLASS_WLAN_MAC:
6104ad7e9b0SAdrian Chadd 	case BHND_DEVCLASS_WLAN_PHY:
6114ad7e9b0SAdrian Chadd 	case BHND_DEVCLASS_EROM:
6124ad7e9b0SAdrian Chadd 	case BHND_DEVCLASS_OTHER:
6134ad7e9b0SAdrian Chadd 	case BHND_DEVCLASS_INVALID:
614d9352570SAdrian Chadd 		if (bhnd_find_hostb_device(dev) == child)
6154ad7e9b0SAdrian Chadd 			return (BHND_PROBE_ROOT + BHND_PROBE_ORDER_EARLY);
6164ad7e9b0SAdrian Chadd 
6174ad7e9b0SAdrian Chadd 		return (BHND_PROBE_DEFAULT);
618054ae231SAdrian Chadd 	default:
619054ae231SAdrian Chadd 		return (BHND_PROBE_DEFAULT);
6204ad7e9b0SAdrian Chadd 	}
6214ad7e9b0SAdrian Chadd }
6224ad7e9b0SAdrian Chadd 
6234ad7e9b0SAdrian Chadd /**
624386fb140SAdrian Chadd  * Default bhnd(4) bus driver implementation of BHND_BUS_IS_REGION_VALID().
6254ad7e9b0SAdrian Chadd  *
6264ad7e9b0SAdrian Chadd  * This implementation assumes that port and region numbers are 0-indexed and
6274ad7e9b0SAdrian Chadd  * are allocated non-sparsely, using BHND_BUS_GET_PORT_COUNT() and
6284ad7e9b0SAdrian Chadd  * BHND_BUS_GET_REGION_COUNT() to determine if @p port and @p region fall
6294ad7e9b0SAdrian Chadd  * within the defined range.
6304ad7e9b0SAdrian Chadd  */
631386fb140SAdrian Chadd static bool
6324ad7e9b0SAdrian Chadd bhnd_generic_is_region_valid(device_t dev, device_t child,
6334ad7e9b0SAdrian Chadd     bhnd_port_type type, u_int port, u_int region)
6344ad7e9b0SAdrian Chadd {
6354ad7e9b0SAdrian Chadd 	if (port >= bhnd_get_port_count(child, type))
6364ad7e9b0SAdrian Chadd 		return (false);
6374ad7e9b0SAdrian Chadd 
6384ad7e9b0SAdrian Chadd 	if (region >= bhnd_get_region_count(child, type, port))
6394ad7e9b0SAdrian Chadd 		return (false);
6404ad7e9b0SAdrian Chadd 
6414ad7e9b0SAdrian Chadd 	return (true);
6424ad7e9b0SAdrian Chadd }
6434ad7e9b0SAdrian Chadd 
6444ad7e9b0SAdrian Chadd /**
645*fdedcd9fSLandon J. Fuller  * Default bhnd(4) bus driver implementation of BHND_BUS_GET_NVRAM_VAR().
646*fdedcd9fSLandon J. Fuller  *
647*fdedcd9fSLandon J. Fuller  * This implementation searches @p dev for a usable NVRAM child device.
648*fdedcd9fSLandon J. Fuller  *
649*fdedcd9fSLandon J. Fuller  * If no usable child device is found on @p dev, the request is delegated to
650*fdedcd9fSLandon J. Fuller  * the BHND_BUS_GET_NVRAM_VAR() method on the parent of @p dev.
651*fdedcd9fSLandon J. Fuller  */
652*fdedcd9fSLandon J. Fuller int
653*fdedcd9fSLandon J. Fuller bhnd_generic_get_nvram_var(device_t dev, device_t child, const char *name,
654*fdedcd9fSLandon J. Fuller     void *buf, size_t *size)
655*fdedcd9fSLandon J. Fuller {
656*fdedcd9fSLandon J. Fuller 	struct bhnd_softc	*sc;
657*fdedcd9fSLandon J. Fuller 	device_t		 nvram, parent;
658*fdedcd9fSLandon J. Fuller 
659*fdedcd9fSLandon J. Fuller 	sc = device_get_softc(dev);
660*fdedcd9fSLandon J. Fuller 
661*fdedcd9fSLandon J. Fuller 	/* If a NVRAM device is available, consult it first */
662*fdedcd9fSLandon J. Fuller 	if ((nvram = bhnd_find_nvram(sc)) != NULL)
663*fdedcd9fSLandon J. Fuller 		return BHND_NVRAM_GETVAR(nvram, name, buf, size);
664*fdedcd9fSLandon J. Fuller 
665*fdedcd9fSLandon J. Fuller 	/* Otherwise, try to delegate to parent */
666*fdedcd9fSLandon J. Fuller 	if ((parent = device_get_parent(dev)) == NULL)
667*fdedcd9fSLandon J. Fuller 		return (ENODEV);
668*fdedcd9fSLandon J. Fuller 
669*fdedcd9fSLandon J. Fuller 	return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), child,
670*fdedcd9fSLandon J. Fuller 	    name, buf, size));
671*fdedcd9fSLandon J. Fuller }
672*fdedcd9fSLandon J. Fuller 
673*fdedcd9fSLandon J. Fuller /**
674386fb140SAdrian Chadd  * Default bhnd(4) bus driver implementation of BUS_PRINT_CHILD().
6754ad7e9b0SAdrian Chadd  *
6764ad7e9b0SAdrian Chadd  * This implementation requests the device's struct resource_list via
6774ad7e9b0SAdrian Chadd  * BUS_GET_RESOURCE_LIST.
6784ad7e9b0SAdrian Chadd  */
6794ad7e9b0SAdrian Chadd int
6804ad7e9b0SAdrian Chadd bhnd_generic_print_child(device_t dev, device_t child)
6814ad7e9b0SAdrian Chadd {
6824ad7e9b0SAdrian Chadd 	struct resource_list	*rl;
6834ad7e9b0SAdrian Chadd 	int			retval = 0;
6844ad7e9b0SAdrian Chadd 
6854ad7e9b0SAdrian Chadd 	retval += bus_print_child_header(dev, child);
6864ad7e9b0SAdrian Chadd 
6874ad7e9b0SAdrian Chadd 	rl = BUS_GET_RESOURCE_LIST(dev, child);
6884ad7e9b0SAdrian Chadd 	if (rl != NULL) {
6894ad7e9b0SAdrian Chadd 		retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY,
690f8fd3fb5SJustin Hibbits 		    "%#jx");
6914ad7e9b0SAdrian Chadd 	}
6924ad7e9b0SAdrian Chadd 
6934ad7e9b0SAdrian Chadd 	retval += printf(" at core %u", bhnd_get_core_index(child));
6944ad7e9b0SAdrian Chadd 
6954ad7e9b0SAdrian Chadd 	retval += bus_print_child_domain(dev, child);
6964ad7e9b0SAdrian Chadd 	retval += bus_print_child_footer(dev, child);
6974ad7e9b0SAdrian Chadd 
6984ad7e9b0SAdrian Chadd 	return (retval);
6994ad7e9b0SAdrian Chadd }
7004ad7e9b0SAdrian Chadd 
7014ad7e9b0SAdrian Chadd /**
702386fb140SAdrian Chadd  * Default bhnd(4) bus driver implementation of BUS_PROBE_NOMATCH().
7034ad7e9b0SAdrian Chadd  *
7044ad7e9b0SAdrian Chadd  * This implementation requests the device's struct resource_list via
7054ad7e9b0SAdrian Chadd  * BUS_GET_RESOURCE_LIST.
7064ad7e9b0SAdrian Chadd  */
7074ad7e9b0SAdrian Chadd void
7084ad7e9b0SAdrian Chadd bhnd_generic_probe_nomatch(device_t dev, device_t child)
7094ad7e9b0SAdrian Chadd {
7104ad7e9b0SAdrian Chadd 	struct resource_list		*rl;
7114ad7e9b0SAdrian Chadd 	const struct bhnd_nomatch	*nm;
7124ad7e9b0SAdrian Chadd 	bool				 report;
7134ad7e9b0SAdrian Chadd 
7144ad7e9b0SAdrian Chadd 	/* Fetch reporting configuration for this device */
7154ad7e9b0SAdrian Chadd 	report = true;
7164ad7e9b0SAdrian Chadd 	for (nm = bhnd_nomatch_table; nm->device != BHND_COREID_INVALID; nm++) {
7174ad7e9b0SAdrian Chadd 		if (nm->vendor != bhnd_get_vendor(child))
7184ad7e9b0SAdrian Chadd 			continue;
7194ad7e9b0SAdrian Chadd 
7204ad7e9b0SAdrian Chadd 		if (nm->device != bhnd_get_device(child))
7214ad7e9b0SAdrian Chadd 			continue;
7224ad7e9b0SAdrian Chadd 
7234ad7e9b0SAdrian Chadd 		report = false;
7244ad7e9b0SAdrian Chadd 		if (bootverbose && nm->if_verbose)
7254ad7e9b0SAdrian Chadd 			report = true;
7264ad7e9b0SAdrian Chadd 		break;
7274ad7e9b0SAdrian Chadd 	}
7284ad7e9b0SAdrian Chadd 
7294ad7e9b0SAdrian Chadd 	if (!report)
7304ad7e9b0SAdrian Chadd 		return;
7314ad7e9b0SAdrian Chadd 
7324ad7e9b0SAdrian Chadd 	/* Print the non-matched device info */
7334ad7e9b0SAdrian Chadd 	device_printf(dev, "<%s %s>", bhnd_get_vendor_name(child),
7344ad7e9b0SAdrian Chadd 		bhnd_get_device_name(child));
7354ad7e9b0SAdrian Chadd 
7364ad7e9b0SAdrian Chadd 	rl = BUS_GET_RESOURCE_LIST(dev, child);
7374ad7e9b0SAdrian Chadd 	if (rl != NULL)
738f8fd3fb5SJustin Hibbits 		resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
7394ad7e9b0SAdrian Chadd 
7404ad7e9b0SAdrian Chadd 	printf(" at core %u (no driver attached)\n",
7414ad7e9b0SAdrian Chadd 	    bhnd_get_core_index(child));
7424ad7e9b0SAdrian Chadd }
7434ad7e9b0SAdrian Chadd 
7444ad7e9b0SAdrian Chadd /**
7454ad7e9b0SAdrian Chadd  * Default implementation of BUS_CHILD_PNPINFO_STR().
7464ad7e9b0SAdrian Chadd  */
7474ad7e9b0SAdrian Chadd static int
7484ad7e9b0SAdrian Chadd bhnd_child_pnpinfo_str(device_t dev, device_t child, char *buf,
7494ad7e9b0SAdrian Chadd     size_t buflen)
7504ad7e9b0SAdrian Chadd {
7514ad7e9b0SAdrian Chadd 	if (device_get_parent(child) != dev) {
7524ad7e9b0SAdrian Chadd 		return (BUS_CHILD_PNPINFO_STR(device_get_parent(dev), child,
7534ad7e9b0SAdrian Chadd 		    buf, buflen));
7544ad7e9b0SAdrian Chadd 	}
7554ad7e9b0SAdrian Chadd 
7564ad7e9b0SAdrian Chadd 	snprintf(buf, buflen, "vendor=0x%hx device=0x%hx rev=0x%hhx",
7574ad7e9b0SAdrian Chadd 	    bhnd_get_vendor(child), bhnd_get_device(child),
7584ad7e9b0SAdrian Chadd 	    bhnd_get_hwrev(child));
7594ad7e9b0SAdrian Chadd 
7604ad7e9b0SAdrian Chadd 	return (0);
7614ad7e9b0SAdrian Chadd }
7624ad7e9b0SAdrian Chadd 
7634ad7e9b0SAdrian Chadd /**
764386fb140SAdrian Chadd  * Default implementation of BUS_CHILD_LOCATION_STR().
7654ad7e9b0SAdrian Chadd  */
7664ad7e9b0SAdrian Chadd static int
7674ad7e9b0SAdrian Chadd bhnd_child_location_str(device_t dev, device_t child, char *buf,
7684ad7e9b0SAdrian Chadd     size_t buflen)
7694ad7e9b0SAdrian Chadd {
7704ad7e9b0SAdrian Chadd 	bhnd_addr_t	addr;
7714ad7e9b0SAdrian Chadd 	bhnd_size_t	size;
7724ad7e9b0SAdrian Chadd 
7734ad7e9b0SAdrian Chadd 	if (device_get_parent(child) != dev) {
7744ad7e9b0SAdrian Chadd 		return (BUS_CHILD_LOCATION_STR(device_get_parent(dev), child,
7754ad7e9b0SAdrian Chadd 		    buf, buflen));
7764ad7e9b0SAdrian Chadd 	}
7774ad7e9b0SAdrian Chadd 
7784ad7e9b0SAdrian Chadd 
7794ad7e9b0SAdrian Chadd 	if (bhnd_get_region_addr(child, BHND_PORT_DEVICE, 0, 0, &addr, &size)) {
7804ad7e9b0SAdrian Chadd 		/* No device default port/region */
7814ad7e9b0SAdrian Chadd 		if (buflen > 0)
7824ad7e9b0SAdrian Chadd 			*buf = '\0';
7834ad7e9b0SAdrian Chadd 		return (0);
7844ad7e9b0SAdrian Chadd 	}
7854ad7e9b0SAdrian Chadd 
7864ad7e9b0SAdrian Chadd 	snprintf(buf, buflen, "port0.0=0x%llx", (unsigned long long) addr);
7874ad7e9b0SAdrian Chadd 	return (0);
7884ad7e9b0SAdrian Chadd }
7894ad7e9b0SAdrian Chadd 
7904ad7e9b0SAdrian Chadd /**
791688fc8c0SLandon J. Fuller  * Default bhnd(4) bus driver implementation of BUS_ADD_CHILD().
792688fc8c0SLandon J. Fuller  *
793688fc8c0SLandon J. Fuller  * This implementation manages internal bhnd(4) state, and must be called
794688fc8c0SLandon J. Fuller  * by subclassing drivers.
795688fc8c0SLandon J. Fuller  */
796688fc8c0SLandon J. Fuller device_t
797688fc8c0SLandon J. Fuller bhnd_generic_add_child(device_t dev, u_int order, const char *name, int unit)
798688fc8c0SLandon J. Fuller {
799688fc8c0SLandon J. Fuller 	struct bhnd_devinfo	*dinfo;
800688fc8c0SLandon J. Fuller 	device_t		 child;
801688fc8c0SLandon J. Fuller 
802688fc8c0SLandon J. Fuller 	child = device_add_child_ordered(dev, order, name, unit);
803688fc8c0SLandon J. Fuller 	if (child == NULL)
804688fc8c0SLandon J. Fuller 		return (NULL);
805688fc8c0SLandon J. Fuller 
806688fc8c0SLandon J. Fuller 	if ((dinfo = BHND_BUS_ALLOC_DEVINFO(dev)) == NULL) {
807688fc8c0SLandon J. Fuller 		device_delete_child(dev, child);
808688fc8c0SLandon J. Fuller 		return (NULL);
809688fc8c0SLandon J. Fuller 	}
810688fc8c0SLandon J. Fuller 
811688fc8c0SLandon J. Fuller 	device_set_ivars(child, dinfo);
812688fc8c0SLandon J. Fuller 
813688fc8c0SLandon J. Fuller 	/* Inform concrete bus driver. */
814688fc8c0SLandon J. Fuller 	BHND_BUS_CHILD_ADDED(dev, child);
815688fc8c0SLandon J. Fuller 
816688fc8c0SLandon J. Fuller 	return (child);
817688fc8c0SLandon J. Fuller }
818688fc8c0SLandon J. Fuller 
819688fc8c0SLandon J. Fuller /**
820688fc8c0SLandon J. Fuller  * Default bhnd(4) bus driver implementation of BUS_CHILD_DELETED().
821688fc8c0SLandon J. Fuller  *
822688fc8c0SLandon J. Fuller  * This implementation manages internal bhnd(4) state, and must be called
823688fc8c0SLandon J. Fuller  * by subclassing drivers.
824688fc8c0SLandon J. Fuller  */
825688fc8c0SLandon J. Fuller void
826688fc8c0SLandon J. Fuller bhnd_generic_child_deleted(device_t dev, device_t child)
827688fc8c0SLandon J. Fuller {
828688fc8c0SLandon J. Fuller 	struct bhnd_softc	*sc;
829688fc8c0SLandon J. Fuller 	struct bhnd_devinfo	*dinfo;
830688fc8c0SLandon J. Fuller 
831688fc8c0SLandon J. Fuller 	sc = device_get_softc(dev);
832688fc8c0SLandon J. Fuller 
833688fc8c0SLandon J. Fuller 	/* Free device info */
834688fc8c0SLandon J. Fuller 	if ((dinfo = device_get_ivars(child)) != NULL)
835688fc8c0SLandon J. Fuller 		BHND_BUS_FREE_DEVINFO(dev, dinfo);
836*fdedcd9fSLandon J. Fuller 
837*fdedcd9fSLandon J. Fuller 	/* Clean up platform device references */
838*fdedcd9fSLandon J. Fuller 	if (sc->chipc_dev == child) {
839*fdedcd9fSLandon J. Fuller 		sc->chipc_dev = NULL;
840*fdedcd9fSLandon J. Fuller 	} else if (sc->nvram_dev == child) {
841*fdedcd9fSLandon J. Fuller 		sc->nvram_dev = NULL;
842*fdedcd9fSLandon J. Fuller 	} else if (sc->pmu_dev == child) {
843*fdedcd9fSLandon J. Fuller 		sc->pmu_dev = NULL;
844*fdedcd9fSLandon J. Fuller 	}
845688fc8c0SLandon J. Fuller }
846688fc8c0SLandon J. Fuller 
847688fc8c0SLandon J. Fuller /**
8484ad7e9b0SAdrian Chadd  * Helper function for implementing BUS_SUSPEND_CHILD().
8494ad7e9b0SAdrian Chadd  *
8504ad7e9b0SAdrian Chadd  * TODO: Power management
8514ad7e9b0SAdrian Chadd  *
8524ad7e9b0SAdrian Chadd  * If @p child is not a direct child of @p dev, suspension is delegated to
8534ad7e9b0SAdrian Chadd  * the @p dev parent.
8544ad7e9b0SAdrian Chadd  */
8554ad7e9b0SAdrian Chadd int
8564ad7e9b0SAdrian Chadd bhnd_generic_suspend_child(device_t dev, device_t child)
8574ad7e9b0SAdrian Chadd {
8584ad7e9b0SAdrian Chadd 	if (device_get_parent(child) != dev)
8594ad7e9b0SAdrian Chadd 		BUS_SUSPEND_CHILD(device_get_parent(dev), child);
8604ad7e9b0SAdrian Chadd 
8614ad7e9b0SAdrian Chadd 	return bus_generic_suspend_child(dev, child);
8624ad7e9b0SAdrian Chadd }
8634ad7e9b0SAdrian Chadd 
8644ad7e9b0SAdrian Chadd /**
8654ad7e9b0SAdrian Chadd  * Helper function for implementing BUS_RESUME_CHILD().
8664ad7e9b0SAdrian Chadd  *
8674ad7e9b0SAdrian Chadd  * TODO: Power management
8684ad7e9b0SAdrian Chadd  *
8694ad7e9b0SAdrian Chadd  * If @p child is not a direct child of @p dev, suspension is delegated to
8704ad7e9b0SAdrian Chadd  * the @p dev parent.
8714ad7e9b0SAdrian Chadd  */
8724ad7e9b0SAdrian Chadd int
8734ad7e9b0SAdrian Chadd bhnd_generic_resume_child(device_t dev, device_t child)
8744ad7e9b0SAdrian Chadd {
8754ad7e9b0SAdrian Chadd 	if (device_get_parent(child) != dev)
8764ad7e9b0SAdrian Chadd 		BUS_RESUME_CHILD(device_get_parent(dev), child);
8774ad7e9b0SAdrian Chadd 
8784ad7e9b0SAdrian Chadd 	return bus_generic_resume_child(dev, child);
8794ad7e9b0SAdrian Chadd }
8804ad7e9b0SAdrian Chadd 
8814ad7e9b0SAdrian Chadd /*
8824ad7e9b0SAdrian Chadd  * Delegate all indirect I/O to the parent device. When inherited by
8834ad7e9b0SAdrian Chadd  * non-bridged bus implementations, resources will never be marked as
8840e141e3cSAdrian Chadd  * indirect, and these methods will never be called.
8854ad7e9b0SAdrian Chadd  */
886a73ac06dSAdrian Chadd #define	BHND_IO_READ(_type, _name, _method)				\
887a73ac06dSAdrian Chadd static _type								\
888a73ac06dSAdrian Chadd bhnd_read_ ## _name (device_t dev, device_t child,			\
889a73ac06dSAdrian Chadd     struct bhnd_resource *r, bus_size_t offset)				\
890a73ac06dSAdrian Chadd {									\
891a73ac06dSAdrian Chadd 	return (BHND_BUS_READ_ ## _method(				\
892a73ac06dSAdrian Chadd 		    device_get_parent(dev), child, r, offset));		\
8934ad7e9b0SAdrian Chadd }
8944ad7e9b0SAdrian Chadd 
895a73ac06dSAdrian Chadd #define	BHND_IO_WRITE(_type, _name, _method)				\
896a73ac06dSAdrian Chadd static void								\
897a73ac06dSAdrian Chadd bhnd_write_ ## _name (device_t dev, device_t child,			\
898a73ac06dSAdrian Chadd     struct bhnd_resource *r, bus_size_t offset, _type value)		\
899a73ac06dSAdrian Chadd {									\
900a73ac06dSAdrian Chadd 	return (BHND_BUS_WRITE_ ## _method(				\
901a73ac06dSAdrian Chadd 		    device_get_parent(dev), child, r, offset,		\
902a73ac06dSAdrian Chadd 		    value));	\
9034ad7e9b0SAdrian Chadd }
9044ad7e9b0SAdrian Chadd 
9050e141e3cSAdrian Chadd #define	BHND_IO_MISC(_type, _op, _method)				\
906a73ac06dSAdrian Chadd static void								\
9070e141e3cSAdrian Chadd bhnd_ ## _op (device_t dev, device_t child,				\
9080e141e3cSAdrian Chadd     struct bhnd_resource *r, bus_size_t offset, _type datap,		\
909a73ac06dSAdrian Chadd     bus_size_t count)							\
910a73ac06dSAdrian Chadd {									\
911a73ac06dSAdrian Chadd 	BHND_BUS_ ## _method(device_get_parent(dev), child, r,		\
912a73ac06dSAdrian Chadd 	    offset, datap, count);					\
9134ad7e9b0SAdrian Chadd }
9144ad7e9b0SAdrian Chadd 
915a73ac06dSAdrian Chadd #define	BHND_IO_METHODS(_type, _size)					\
916a73ac06dSAdrian Chadd 	BHND_IO_READ(_type, _size, _size)				\
917a73ac06dSAdrian Chadd 	BHND_IO_WRITE(_type, _size, _size)				\
918a73ac06dSAdrian Chadd 									\
919a73ac06dSAdrian Chadd 	BHND_IO_READ(_type, stream_ ## _size, STREAM_ ## _size)		\
920a73ac06dSAdrian Chadd 	BHND_IO_WRITE(_type, stream_ ## _size, STREAM_ ## _size)	\
921a73ac06dSAdrian Chadd 									\
9220e141e3cSAdrian Chadd 	BHND_IO_MISC(_type*, read_multi_ ## _size,			\
9230e141e3cSAdrian Chadd 	    READ_MULTI_ ## _size)					\
9240e141e3cSAdrian Chadd 	BHND_IO_MISC(_type*, write_multi_ ## _size,			\
9250e141e3cSAdrian Chadd 	    WRITE_MULTI_ ## _size)					\
926a73ac06dSAdrian Chadd 									\
9270e141e3cSAdrian Chadd 	BHND_IO_MISC(_type*, read_multi_stream_ ## _size,		\
928a73ac06dSAdrian Chadd 	   READ_MULTI_STREAM_ ## _size)					\
9290e141e3cSAdrian Chadd 	BHND_IO_MISC(_type*, write_multi_stream_ ## _size,		\
930a73ac06dSAdrian Chadd 	   WRITE_MULTI_STREAM_ ## _size)				\
9310e141e3cSAdrian Chadd 									\
9320e141e3cSAdrian Chadd 	BHND_IO_MISC(_type, set_multi_ ## _size, SET_MULTI_ ## _size)	\
9330e141e3cSAdrian Chadd 	BHND_IO_MISC(_type, set_region_ ## _size, SET_REGION_ ## _size)	\
9340e141e3cSAdrian Chadd 									\
9350e141e3cSAdrian Chadd 	BHND_IO_MISC(_type*, read_region_ ## _size,			\
9360e141e3cSAdrian Chadd 	    READ_REGION_ ## _size)					\
9370e141e3cSAdrian Chadd 	BHND_IO_MISC(_type*, write_region_ ## _size,			\
9380e141e3cSAdrian Chadd 	    WRITE_REGION_ ## _size)					\
9390e141e3cSAdrian Chadd 									\
9400e141e3cSAdrian Chadd 	BHND_IO_MISC(_type*, read_region_stream_ ## _size,		\
9410e141e3cSAdrian Chadd 	    READ_REGION_STREAM_ ## _size)				\
9420e141e3cSAdrian Chadd 	BHND_IO_MISC(_type*, write_region_stream_ ## _size,		\
9430e141e3cSAdrian Chadd 	    WRITE_REGION_STREAM_ ## _size)				\
9444ad7e9b0SAdrian Chadd 
945a73ac06dSAdrian Chadd BHND_IO_METHODS(uint8_t, 1);
946a73ac06dSAdrian Chadd BHND_IO_METHODS(uint16_t, 2);
947a73ac06dSAdrian Chadd BHND_IO_METHODS(uint32_t, 4);
9484ad7e9b0SAdrian Chadd 
9494ad7e9b0SAdrian Chadd static void
9504ad7e9b0SAdrian Chadd bhnd_barrier(device_t dev, device_t child, struct bhnd_resource *r,
9514ad7e9b0SAdrian Chadd     bus_size_t offset, bus_size_t length, int flags)
9524ad7e9b0SAdrian Chadd {
9534ad7e9b0SAdrian Chadd 	BHND_BUS_BARRIER(device_get_parent(dev), child, r, offset, length,
9544ad7e9b0SAdrian Chadd 	    flags);
9554ad7e9b0SAdrian Chadd }
9564ad7e9b0SAdrian Chadd 
9574ad7e9b0SAdrian Chadd static device_method_t bhnd_methods[] = {
9584ad7e9b0SAdrian Chadd 	/* Device interface */ \
9594ad7e9b0SAdrian Chadd 	DEVMETHOD(device_attach,		bhnd_generic_attach),
9604ad7e9b0SAdrian Chadd 	DEVMETHOD(device_detach,		bhnd_generic_detach),
9614ad7e9b0SAdrian Chadd 	DEVMETHOD(device_shutdown,		bhnd_generic_shutdown),
9624ad7e9b0SAdrian Chadd 	DEVMETHOD(device_suspend,		bhnd_generic_suspend),
9634ad7e9b0SAdrian Chadd 	DEVMETHOD(device_resume,		bhnd_generic_resume),
9644ad7e9b0SAdrian Chadd 
9654ad7e9b0SAdrian Chadd 	/* Bus interface */
966*fdedcd9fSLandon J. Fuller 	DEVMETHOD(bus_new_pass,			bhnd_new_pass),
967688fc8c0SLandon J. Fuller 	DEVMETHOD(bus_add_child,		bhnd_generic_add_child),
968688fc8c0SLandon J. Fuller 	DEVMETHOD(bus_child_deleted,		bhnd_generic_child_deleted),
9694ad7e9b0SAdrian Chadd 	DEVMETHOD(bus_probe_nomatch,		bhnd_generic_probe_nomatch),
9704ad7e9b0SAdrian Chadd 	DEVMETHOD(bus_print_child,		bhnd_generic_print_child),
9714ad7e9b0SAdrian Chadd 	DEVMETHOD(bus_child_pnpinfo_str,	bhnd_child_pnpinfo_str),
9724ad7e9b0SAdrian Chadd 	DEVMETHOD(bus_child_location_str,	bhnd_child_location_str),
9734ad7e9b0SAdrian Chadd 
9744ad7e9b0SAdrian Chadd 	DEVMETHOD(bus_suspend_child,		bhnd_generic_suspend_child),
9754ad7e9b0SAdrian Chadd 	DEVMETHOD(bus_resume_child,		bhnd_generic_resume_child),
9764ad7e9b0SAdrian Chadd 
9774ad7e9b0SAdrian Chadd 	DEVMETHOD(bus_set_resource,		bus_generic_rl_set_resource),
9784ad7e9b0SAdrian Chadd 	DEVMETHOD(bus_get_resource,		bus_generic_rl_get_resource),
9794ad7e9b0SAdrian Chadd 	DEVMETHOD(bus_delete_resource,		bus_generic_rl_delete_resource),
9804ad7e9b0SAdrian Chadd 	DEVMETHOD(bus_alloc_resource,		bus_generic_rl_alloc_resource),
9814ad7e9b0SAdrian Chadd 	DEVMETHOD(bus_adjust_resource,		bus_generic_adjust_resource),
9824ad7e9b0SAdrian Chadd 	DEVMETHOD(bus_release_resource,		bus_generic_rl_release_resource),
9834ad7e9b0SAdrian Chadd 	DEVMETHOD(bus_activate_resource,	bus_generic_activate_resource),
9844ad7e9b0SAdrian Chadd 	DEVMETHOD(bus_deactivate_resource,	bus_generic_deactivate_resource),
9854ad7e9b0SAdrian Chadd 
9864ad7e9b0SAdrian Chadd 	DEVMETHOD(bus_setup_intr,		bus_generic_setup_intr),
9874ad7e9b0SAdrian Chadd 	DEVMETHOD(bus_teardown_intr,		bus_generic_teardown_intr),
9884ad7e9b0SAdrian Chadd 	DEVMETHOD(bus_config_intr,		bus_generic_config_intr),
9894ad7e9b0SAdrian Chadd 	DEVMETHOD(bus_bind_intr,		bus_generic_bind_intr),
9904ad7e9b0SAdrian Chadd 	DEVMETHOD(bus_describe_intr,		bus_generic_describe_intr),
9914ad7e9b0SAdrian Chadd 
9924ad7e9b0SAdrian Chadd 	DEVMETHOD(bus_get_dma_tag,		bus_generic_get_dma_tag),
9934ad7e9b0SAdrian Chadd 
9944ad7e9b0SAdrian Chadd 	/* BHND interface */
995386fb140SAdrian Chadd 	DEVMETHOD(bhnd_bus_get_chipid,		bhnd_bus_generic_get_chipid),
9964ad7e9b0SAdrian Chadd 	DEVMETHOD(bhnd_bus_get_probe_order,	bhnd_generic_get_probe_order),
997386fb140SAdrian Chadd 	DEVMETHOD(bhnd_bus_is_region_valid,	bhnd_generic_is_region_valid),
998386fb140SAdrian Chadd 	DEVMETHOD(bhnd_bus_is_hw_disabled,	bhnd_bus_generic_is_hw_disabled),
999*fdedcd9fSLandon J. Fuller 	DEVMETHOD(bhnd_bus_get_nvram_var,	bhnd_generic_get_nvram_var),
10000e141e3cSAdrian Chadd 
10010e141e3cSAdrian Chadd 	/* BHND interface (bus I/O) */
10024ad7e9b0SAdrian Chadd 	DEVMETHOD(bhnd_bus_read_1,		bhnd_read_1),
10034ad7e9b0SAdrian Chadd 	DEVMETHOD(bhnd_bus_read_2,		bhnd_read_2),
10044ad7e9b0SAdrian Chadd 	DEVMETHOD(bhnd_bus_read_4,		bhnd_read_4),
10054ad7e9b0SAdrian Chadd 	DEVMETHOD(bhnd_bus_write_1,		bhnd_write_1),
10064ad7e9b0SAdrian Chadd 	DEVMETHOD(bhnd_bus_write_2,		bhnd_write_2),
10074ad7e9b0SAdrian Chadd 	DEVMETHOD(bhnd_bus_write_4,		bhnd_write_4),
10080e141e3cSAdrian Chadd 
1009a73ac06dSAdrian Chadd 	DEVMETHOD(bhnd_bus_read_stream_1,	bhnd_read_stream_1),
1010a73ac06dSAdrian Chadd 	DEVMETHOD(bhnd_bus_read_stream_2,	bhnd_read_stream_2),
1011a73ac06dSAdrian Chadd 	DEVMETHOD(bhnd_bus_read_stream_4,	bhnd_read_stream_4),
1012a73ac06dSAdrian Chadd 	DEVMETHOD(bhnd_bus_write_stream_1,	bhnd_write_stream_1),
1013a73ac06dSAdrian Chadd 	DEVMETHOD(bhnd_bus_write_stream_2,	bhnd_write_stream_2),
1014a73ac06dSAdrian Chadd 	DEVMETHOD(bhnd_bus_write_stream_4,	bhnd_write_stream_4),
1015a73ac06dSAdrian Chadd 
1016a73ac06dSAdrian Chadd 	DEVMETHOD(bhnd_bus_read_multi_1,	bhnd_read_multi_1),
1017a73ac06dSAdrian Chadd 	DEVMETHOD(bhnd_bus_read_multi_2,	bhnd_read_multi_2),
1018a73ac06dSAdrian Chadd 	DEVMETHOD(bhnd_bus_read_multi_4,	bhnd_read_multi_4),
1019a73ac06dSAdrian Chadd 	DEVMETHOD(bhnd_bus_write_multi_1,	bhnd_write_multi_1),
1020a73ac06dSAdrian Chadd 	DEVMETHOD(bhnd_bus_write_multi_2,	bhnd_write_multi_2),
1021a73ac06dSAdrian Chadd 	DEVMETHOD(bhnd_bus_write_multi_4,	bhnd_write_multi_4),
1022a73ac06dSAdrian Chadd 
1023a73ac06dSAdrian Chadd 	DEVMETHOD(bhnd_bus_read_multi_stream_1,	bhnd_read_multi_stream_1),
1024a73ac06dSAdrian Chadd 	DEVMETHOD(bhnd_bus_read_multi_stream_2,	bhnd_read_multi_stream_2),
1025a73ac06dSAdrian Chadd 	DEVMETHOD(bhnd_bus_read_multi_stream_4,	bhnd_read_multi_stream_4),
1026a73ac06dSAdrian Chadd 	DEVMETHOD(bhnd_bus_write_multi_stream_1,bhnd_write_multi_stream_1),
1027a73ac06dSAdrian Chadd 	DEVMETHOD(bhnd_bus_write_multi_stream_2,bhnd_write_multi_stream_2),
1028a73ac06dSAdrian Chadd 	DEVMETHOD(bhnd_bus_write_multi_stream_4,bhnd_write_multi_stream_4),
1029a73ac06dSAdrian Chadd 
10300e141e3cSAdrian Chadd 	DEVMETHOD(bhnd_bus_set_multi_1,		bhnd_set_multi_1),
10310e141e3cSAdrian Chadd 	DEVMETHOD(bhnd_bus_set_multi_2,		bhnd_set_multi_2),
10320e141e3cSAdrian Chadd 	DEVMETHOD(bhnd_bus_set_multi_4,		bhnd_set_multi_4),
10330e141e3cSAdrian Chadd 
10340e141e3cSAdrian Chadd 	DEVMETHOD(bhnd_bus_set_region_1,	bhnd_set_region_1),
10350e141e3cSAdrian Chadd 	DEVMETHOD(bhnd_bus_set_region_2,	bhnd_set_region_2),
10360e141e3cSAdrian Chadd 	DEVMETHOD(bhnd_bus_set_region_4,	bhnd_set_region_4),
10370e141e3cSAdrian Chadd 
10380e141e3cSAdrian Chadd 	DEVMETHOD(bhnd_bus_read_region_1,	bhnd_read_region_1),
10390e141e3cSAdrian Chadd 	DEVMETHOD(bhnd_bus_read_region_2,	bhnd_read_region_2),
10400e141e3cSAdrian Chadd 	DEVMETHOD(bhnd_bus_read_region_4,	bhnd_read_region_4),
10410e141e3cSAdrian Chadd 	DEVMETHOD(bhnd_bus_write_region_1,	bhnd_write_region_1),
10420e141e3cSAdrian Chadd 	DEVMETHOD(bhnd_bus_write_region_2,	bhnd_write_region_2),
10430e141e3cSAdrian Chadd 	DEVMETHOD(bhnd_bus_write_region_4,	bhnd_write_region_4),
10440e141e3cSAdrian Chadd 
10450e141e3cSAdrian Chadd 	DEVMETHOD(bhnd_bus_read_region_stream_1,bhnd_read_region_stream_1),
10460e141e3cSAdrian Chadd 	DEVMETHOD(bhnd_bus_read_region_stream_2,bhnd_read_region_stream_2),
10470e141e3cSAdrian Chadd 	DEVMETHOD(bhnd_bus_read_region_stream_4,bhnd_read_region_stream_4),
10480e141e3cSAdrian Chadd 	DEVMETHOD(bhnd_bus_write_region_stream_1, bhnd_write_region_stream_1),
10490e141e3cSAdrian Chadd 	DEVMETHOD(bhnd_bus_write_region_stream_2, bhnd_write_region_stream_2),
10500e141e3cSAdrian Chadd 	DEVMETHOD(bhnd_bus_write_region_stream_4, bhnd_write_region_stream_4),
10510e141e3cSAdrian Chadd 
10524ad7e9b0SAdrian Chadd 	DEVMETHOD(bhnd_bus_barrier,			bhnd_barrier),
10534ad7e9b0SAdrian Chadd 
10544ad7e9b0SAdrian Chadd 	DEVMETHOD_END
10554ad7e9b0SAdrian Chadd };
10564ad7e9b0SAdrian Chadd 
10574ad7e9b0SAdrian Chadd devclass_t bhnd_devclass;	/**< bhnd bus. */
10584ad7e9b0SAdrian Chadd devclass_t bhnd_hostb_devclass;	/**< bhnd bus host bridge. */
10594ad7e9b0SAdrian Chadd devclass_t bhnd_nvram_devclass;	/**< bhnd NVRAM device */
10604ad7e9b0SAdrian Chadd 
10614ad7e9b0SAdrian Chadd DEFINE_CLASS_0(bhnd, bhnd_driver, bhnd_methods, sizeof(struct bhnd_softc));
10624ad7e9b0SAdrian Chadd MODULE_VERSION(bhnd, 1);
1063