ofwbus.c revision 261513
1139825Simp/*-
294755Sbenno * Copyright 1998 Massachusetts Institute of Technology
3256901Snwhitehorn * Copyright 2001 by Thomas Moestl <tmm@FreeBSD.org>.
4256901Snwhitehorn * Copyright 2006 by Marius Strobl <marius@FreeBSD.org>.
5256901Snwhitehorn * All rights reserved.
694755Sbenno *
794755Sbenno * Permission to use, copy, modify, and distribute this software and
894755Sbenno * its documentation for any purpose and without fee is hereby
994755Sbenno * granted, provided that both the above copyright notice and this
1094755Sbenno * permission notice appear in all copies, that both the above
1194755Sbenno * copyright notice and this permission notice appear in all
1294755Sbenno * supporting documentation, and that the name of M.I.T. not be used
1394755Sbenno * in advertising or publicity pertaining to distribution of the
1494755Sbenno * software without specific, written prior permission.  M.I.T. makes
1594755Sbenno * no representations about the suitability of this software for any
1694755Sbenno * purpose.  It is provided "as is" without express or implied
1794755Sbenno * warranty.
18125702Sgrehan *
1994755Sbenno * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
2094755Sbenno * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
2194755Sbenno * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
2294755Sbenno * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
2394755Sbenno * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2494755Sbenno * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2594755Sbenno * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
2694755Sbenno * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
2794755Sbenno * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2894755Sbenno * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
2994755Sbenno * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3094755Sbenno * SUCH DAMAGE.
3194755Sbenno *
3294755Sbenno * 	from: FreeBSD: src/sys/i386/i386/nexus.c,v 1.43 2001/02/09
3394755Sbenno */
3494755Sbenno
35227843Smarius#include <sys/cdefs.h>
36227843Smarius__FBSDID("$FreeBSD: head/sys/dev/ofw/ofwbus.c 261513 2014-02-05 14:44:22Z nwhitehorn $");
37227843Smarius
3894755Sbenno#include <sys/param.h>
3994755Sbenno#include <sys/systm.h>
4094755Sbenno#include <sys/bus.h>
4194755Sbenno#include <sys/kernel.h>
4294755Sbenno#include <sys/malloc.h>
43256901Snwhitehorn#include <sys/module.h>
44256901Snwhitehorn#include <sys/pcpu.h>
45256901Snwhitehorn#include <sys/rman.h>
4694755Sbenno
47256901Snwhitehorn#include <vm/vm.h>
48256901Snwhitehorn#include <vm/pmap.h>
49256901Snwhitehorn
50256855Snwhitehorn#include <dev/ofw/ofw_bus.h>
51212239Smav#include <dev/ofw/ofw_bus_subr.h>
5294755Sbenno#include <dev/ofw/openfirm.h>
5394755Sbenno
5494755Sbenno#include <machine/bus.h>
5594755Sbenno#include <machine/resource.h>
5694755Sbenno
5794755Sbenno/*
58261513Snwhitehorn * The ofwbus (which is a pseudo-bus actually) iterates over the nodes that
59256901Snwhitehorn * hang from the Open Firmware root node and adds them as devices to this bus
60256901Snwhitehorn * (except some special nodes which are excluded) so that drivers can be
61256901Snwhitehorn * attached to them.
6294755Sbenno *
6394755Sbenno */
6494755Sbenno
65261513Snwhitehornstruct ofwbus_devinfo {
66256901Snwhitehorn	struct ofw_bus_devinfo	ndi_obdinfo;
67256901Snwhitehorn	struct resource_list	ndi_rl;
6894755Sbenno};
6994755Sbenno
70261513Snwhitehornstruct ofwbus_softc {
71261513Snwhitehorn	uint32_t	acells, scells;
72261513Snwhitehorn	struct rman	sc_intr_rman;
73261513Snwhitehorn	struct rman	sc_mem_rman;
74261513Snwhitehorn};
7599652Sbenno
76261513Snwhitehornstatic device_identify_t ofwbus_identify;
77261513Snwhitehornstatic device_probe_t ofwbus_probe;
78261513Snwhitehornstatic device_attach_t ofwbus_attach;
79261513Snwhitehornstatic bus_print_child_t ofwbus_print_child;
80261513Snwhitehornstatic bus_add_child_t ofwbus_add_child;
81261513Snwhitehornstatic bus_probe_nomatch_t ofwbus_probe_nomatch;
82261513Snwhitehornstatic bus_alloc_resource_t ofwbus_alloc_resource;
83261513Snwhitehornstatic bus_adjust_resource_t ofwbus_adjust_resource;
84261513Snwhitehornstatic bus_release_resource_t ofwbus_release_resource;
85261513Snwhitehornstatic bus_get_resource_list_t ofwbus_get_resource_list;
86261513Snwhitehornstatic ofw_bus_get_devinfo_t ofwbus_get_devinfo;
8799652Sbenno
88261513Snwhitehornstatic int ofwbus_inlist(const char *, const char *const *);
89261513Snwhitehornstatic struct ofwbus_devinfo * ofwbus_setup_dinfo(device_t, phandle_t);
90261513Snwhitehornstatic void ofwbus_destroy_dinfo(struct ofwbus_devinfo *);
91261513Snwhitehornstatic int ofwbus_print_res(struct ofwbus_devinfo *);
92261513Snwhitehorn
93261513Snwhitehornstatic device_method_t ofwbus_methods[] = {
9494755Sbenno	/* Device interface */
95261513Snwhitehorn	DEVMETHOD(device_identify,	ofwbus_identify),
96261513Snwhitehorn	DEVMETHOD(device_probe,		ofwbus_probe),
97261513Snwhitehorn	DEVMETHOD(device_attach,	ofwbus_attach),
9894755Sbenno	DEVMETHOD(device_detach,	bus_generic_detach),
9994755Sbenno	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
10094755Sbenno	DEVMETHOD(device_suspend,	bus_generic_suspend),
10194755Sbenno	DEVMETHOD(device_resume,	bus_generic_resume),
10294755Sbenno
103256901Snwhitehorn	/* Bus interface */
104261513Snwhitehorn	DEVMETHOD(bus_print_child,	ofwbus_print_child),
105261513Snwhitehorn	DEVMETHOD(bus_probe_nomatch,	ofwbus_probe_nomatch),
106256901Snwhitehorn	DEVMETHOD(bus_read_ivar,	bus_generic_read_ivar),
107256901Snwhitehorn	DEVMETHOD(bus_write_ivar,	bus_generic_write_ivar),
108261513Snwhitehorn	DEVMETHOD(bus_add_child,	ofwbus_add_child),
109212239Smav	DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
110261513Snwhitehorn	DEVMETHOD(bus_alloc_resource,	ofwbus_alloc_resource),
111261513Snwhitehorn	DEVMETHOD(bus_adjust_resource,	ofwbus_adjust_resource),
112261513Snwhitehorn	DEVMETHOD(bus_release_resource,	ofwbus_release_resource),
113256901Snwhitehorn	DEVMETHOD(bus_set_resource,	bus_generic_rl_set_resource),
114256901Snwhitehorn	DEVMETHOD(bus_get_resource,	bus_generic_rl_get_resource),
115261513Snwhitehorn	DEVMETHOD(bus_get_resource_list, ofwbus_get_resource_list),
116261513Snwhitehorn	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
117261513Snwhitehorn	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
118261513Snwhitehorn	DEVMETHOD(bus_config_intr,	bus_generic_config_intr),
119261513Snwhitehorn	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
120261513Snwhitehorn	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
12194755Sbenno
122256901Snwhitehorn	/* ofw_bus interface */
123261513Snwhitehorn	DEVMETHOD(ofw_bus_get_devinfo,	ofwbus_get_devinfo),
124256855Snwhitehorn	DEVMETHOD(ofw_bus_get_compat,	ofw_bus_gen_get_compat),
125256855Snwhitehorn	DEVMETHOD(ofw_bus_get_model,	ofw_bus_gen_get_model),
126256855Snwhitehorn	DEVMETHOD(ofw_bus_get_name,	ofw_bus_gen_get_name),
127256855Snwhitehorn	DEVMETHOD(ofw_bus_get_node,	ofw_bus_gen_get_node),
128256855Snwhitehorn	DEVMETHOD(ofw_bus_get_type,	ofw_bus_gen_get_type),
129168885Sgrehan
130227843Smarius	DEVMETHOD_END
13194755Sbenno};
13294755Sbenno
133261513Snwhitehornstatic driver_t ofwbus_driver = {
134261513Snwhitehorn	"ofwbus",
135261513Snwhitehorn	ofwbus_methods,
136261513Snwhitehorn	sizeof(struct ofwbus_softc)
137261513Snwhitehorn};
138261513Snwhitehornstatic devclass_t ofwbus_devclass;
139261513SnwhitehornDRIVER_MODULE(ofwbus, nexus, ofwbus_driver, ofwbus_devclass, 0, 0);
140261513SnwhitehornMODULE_VERSION(ofwbus, 1);
14194755Sbenno
142261513Snwhitehornstatic const char *const ofwbus_excl_name[] = {
143256901Snwhitehorn	"FJSV,system",
144256901Snwhitehorn	"aliases",
145256901Snwhitehorn	"associations",
146256901Snwhitehorn	"chosen",
147256901Snwhitehorn	"cmp",
148256901Snwhitehorn	"counter-timer",	/* No separate device; handled by psycho/sbus */
149256901Snwhitehorn	"failsafe",
150256901Snwhitehorn	"memory",
151256901Snwhitehorn	"openprom",
152256901Snwhitehorn	"options",
153256901Snwhitehorn	"packages",
154256901Snwhitehorn	"physical-memory",
155256901Snwhitehorn	"rsc",
156256901Snwhitehorn	"sgcn",
157256901Snwhitehorn	"todsg",
158256901Snwhitehorn	"virtual-memory",
159256901Snwhitehorn	NULL
160256901Snwhitehorn};
161256901Snwhitehorn
162261513Snwhitehornstatic const char *const ofwbus_excl_type[] = {
163256901Snwhitehorn	"core",
164256901Snwhitehorn	"cpu",
165256901Snwhitehorn	NULL
166256901Snwhitehorn};
167256901Snwhitehorn
16894755Sbennostatic int
169261513Snwhitehornofwbus_inlist(const char *name, const char *const *list)
170256901Snwhitehorn{
171256901Snwhitehorn	int i;
172256901Snwhitehorn
173256901Snwhitehorn	if (name == NULL)
174256901Snwhitehorn		return (0);
175256901Snwhitehorn	for (i = 0; list[i] != NULL; i++)
176256901Snwhitehorn		if (strcmp(name, list[i]) == 0)
177256901Snwhitehorn			return (1);
178256901Snwhitehorn	return (0);
179256901Snwhitehorn}
180256901Snwhitehorn
181261513Snwhitehorn#define	OFWBUS_EXCLUDED(name, type)					\
182261513Snwhitehorn	(ofwbus_inlist((name), ofwbus_excl_name) ||			\
183261513Snwhitehorn	((type) != NULL && ofwbus_inlist((type), ofwbus_excl_type)))
184256901Snwhitehorn
185261513Snwhitehornstatic void
186261513Snwhitehornofwbus_identify(driver_t *driver, device_t parent)
187261513Snwhitehorn{
188261513Snwhitehorn
189261513Snwhitehorn	/* Check if Open Firmware has been instantiated */
190261513Snwhitehorn	if (OF_peer(0) == -1)
191261513Snwhitehorn		return;
192261513Snwhitehorn
193261513Snwhitehorn	if (device_find_child(parent, "ofwbus", -1) == NULL)
194261513Snwhitehorn		BUS_ADD_CHILD(parent, 0, "ofwbus", -1);
195261513Snwhitehorn}
196261513Snwhitehorn
197256901Snwhitehornstatic int
198261513Snwhitehornofwbus_probe(device_t dev)
19994755Sbenno{
200256901Snwhitehorn
201261513Snwhitehorn	device_set_desc(dev, "Open Firmware Device Tree");
202261513Snwhitehorn	return (BUS_PROBE_NOWILDCARD);
203178367Smarcel}
204178367Smarcel
205178367Smarcelstatic int
206261513Snwhitehornofwbus_attach(device_t dev)
207178367Smarcel{
208261513Snwhitehorn	struct ofwbus_devinfo *ndi;
209261513Snwhitehorn	struct ofwbus_softc *sc;
210256901Snwhitehorn	device_t cdev;
211256901Snwhitehorn	phandle_t node;
21294755Sbenno
21399652Sbenno	sc = device_get_softc(dev);
21499652Sbenno
215257075Snwhitehorn	node = OF_peer(0);
216171805Smarcel
217261513Snwhitehorn	/*
218261513Snwhitehorn	 * If no Open Firmware, bail early
219261513Snwhitehorn	 */
220261513Snwhitehorn	if (node == -1)
221261513Snwhitehorn		return (ENXIO);
222261513Snwhitehorn
223257075Snwhitehorn	sc->sc_intr_rman.rm_type = RMAN_ARRAY;
224257075Snwhitehorn	sc->sc_intr_rman.rm_descr = "Interrupts";
225257075Snwhitehorn	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
226257075Snwhitehorn	sc->sc_mem_rman.rm_descr = "Device Memory";
227257075Snwhitehorn	if (rman_init(&sc->sc_intr_rman) != 0 ||
228257075Snwhitehorn	    rman_init(&sc->sc_mem_rman) != 0 ||
229257075Snwhitehorn	    rman_manage_region(&sc->sc_intr_rman, 0, ~0) != 0 ||
230257075Snwhitehorn	    rman_manage_region(&sc->sc_mem_rman, 0, BUS_SPACE_MAXADDR) != 0)
231257075Snwhitehorn		panic("%s: failed to set up rmans.", __func__);
232171805Smarcel
233256901Snwhitehorn	/*
234256901Snwhitehorn	 * Allow devices to identify.
235256901Snwhitehorn	 */
236256901Snwhitehorn	bus_generic_probe(dev);
237256901Snwhitehorn
238256901Snwhitehorn	/*
239256901Snwhitehorn	 * Some important numbers
240124468Sgrehan	 */
241256901Snwhitehorn	sc->acells = 2;
242256969Snwhitehorn	OF_getencprop(node, "#address-cells", &sc->acells, sizeof(sc->acells));
243256901Snwhitehorn	sc->scells = 1;
244256969Snwhitehorn	OF_getencprop(node, "#size-cells", &sc->scells, sizeof(sc->scells));
24599652Sbenno
246256901Snwhitehorn	/*
247256901Snwhitehorn	 * Now walk the OFW tree and attach top-level devices.
248256901Snwhitehorn	 */
249256901Snwhitehorn	for (node = OF_child(node); node > 0; node = OF_peer(node)) {
250261513Snwhitehorn		if ((ndi = ofwbus_setup_dinfo(dev, node)) == NULL)
251256901Snwhitehorn			continue;
252256901Snwhitehorn		cdev = device_add_child(dev, NULL, -1);
253256901Snwhitehorn		if (cdev == NULL) {
254256901Snwhitehorn			device_printf(dev, "<%s>: device_add_child failed\n",
255256901Snwhitehorn			    ndi->ndi_obdinfo.obd_name);
256261513Snwhitehorn			ofwbus_destroy_dinfo(ndi);
257256901Snwhitehorn			continue;
258256901Snwhitehorn		}
259256901Snwhitehorn		device_set_ivars(cdev, ndi);
26094755Sbenno	}
261178367Smarcel	return (bus_generic_attach(dev));
26294755Sbenno}
26394755Sbenno
264256901Snwhitehornstatic device_t
265261513Snwhitehornofwbus_add_child(device_t dev, u_int order, const char *name, int unit)
26694755Sbenno{
267256901Snwhitehorn	device_t cdev;
268261513Snwhitehorn	struct ofwbus_devinfo *ndi;
26994755Sbenno
270256901Snwhitehorn	cdev = device_add_child_ordered(dev, order, name, unit);
271256901Snwhitehorn	if (cdev == NULL)
272256901Snwhitehorn		return (NULL);
27394755Sbenno
274256901Snwhitehorn	ndi = malloc(sizeof(*ndi), M_DEVBUF, M_WAITOK | M_ZERO);
275256901Snwhitehorn	ndi->ndi_obdinfo.obd_node = -1;
276256901Snwhitehorn	resource_list_init(&ndi->ndi_rl);
277256901Snwhitehorn	device_set_ivars(cdev, ndi);
278124468Sgrehan
279256901Snwhitehorn	return (cdev);
28094755Sbenno}
28194755Sbenno
282256901Snwhitehornstatic int
283261513Snwhitehornofwbus_print_child(device_t bus, device_t child)
284124468Sgrehan{
285256901Snwhitehorn	int rv;
286124468Sgrehan
287256901Snwhitehorn	rv = bus_print_child_header(bus, child);
288261513Snwhitehorn	rv += ofwbus_print_res(device_get_ivars(child));
289256901Snwhitehorn	rv += bus_print_child_footer(bus, child);
290256901Snwhitehorn	return (rv);
291256901Snwhitehorn}
292125702Sgrehan
293256901Snwhitehornstatic void
294261513Snwhitehornofwbus_probe_nomatch(device_t bus, device_t child)
295256901Snwhitehorn{
296256901Snwhitehorn	const char *name, *type;
297124468Sgrehan
298256901Snwhitehorn	if (!bootverbose)
299256901Snwhitehorn		return;
300256855Snwhitehorn
301256901Snwhitehorn	name = ofw_bus_get_name(child);
302256901Snwhitehorn	type = ofw_bus_get_type(child);
303125702Sgrehan
304256901Snwhitehorn	device_printf(bus, "<%s>",
305256901Snwhitehorn	    name != NULL ? name : "unknown");
306261513Snwhitehorn	ofwbus_print_res(device_get_ivars(child));
307256901Snwhitehorn	printf(" type %s (no driver attached)\n",
308256901Snwhitehorn	    type != NULL ? type : "unknown");
309124468Sgrehan}
310124468Sgrehan
31199652Sbennostatic struct resource *
312261513Snwhitehornofwbus_alloc_resource(device_t bus, device_t child, int type, int *rid,
31399652Sbenno    u_long start, u_long end, u_long count, u_int flags)
31499652Sbenno{
315261513Snwhitehorn	struct ofwbus_softc *sc;
316256901Snwhitehorn	struct rman *rm;
317171805Smarcel	struct resource *rv;
318256901Snwhitehorn	struct resource_list_entry *rle;
319256901Snwhitehorn	int isdefault, passthrough;
32099652Sbenno
321256901Snwhitehorn	isdefault = (start == 0UL && end == ~0UL);
322256901Snwhitehorn	passthrough = (device_get_parent(child) != bus);
323257075Snwhitehorn	sc = device_get_softc(bus);
324256901Snwhitehorn	rle = NULL;
325256901Snwhitehorn
326256901Snwhitehorn	if (!passthrough && isdefault) {
327256901Snwhitehorn		rle = resource_list_find(BUS_GET_RESOURCE_LIST(bus, child),
328256901Snwhitehorn		    type, *rid);
329256901Snwhitehorn		if (rle == NULL)
330256901Snwhitehorn			return (NULL);
331256901Snwhitehorn		if (rle->res != NULL)
332256901Snwhitehorn			panic("%s: resource entry is busy", __func__);
333256901Snwhitehorn		start = rle->start;
334256901Snwhitehorn		count = ulmax(count, rle->count);
335256901Snwhitehorn		end = ulmax(rle->end, start + count - 1);
336256901Snwhitehorn	}
337256901Snwhitehorn
338256901Snwhitehorn	switch (type) {
339256901Snwhitehorn	case SYS_RES_IRQ:
340256901Snwhitehorn		rm = &sc->sc_intr_rman;
341256901Snwhitehorn		break;
342256901Snwhitehorn	case SYS_RES_MEMORY:
343256901Snwhitehorn		rm = &sc->sc_mem_rman;
344256901Snwhitehorn		break;
345256901Snwhitehorn	default:
34699652Sbenno		return (NULL);
34799652Sbenno	}
34899652Sbenno
349256901Snwhitehorn	rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE,
350256901Snwhitehorn	    child);
351256901Snwhitehorn	if (rv == NULL)
352171805Smarcel		return (NULL);
353256901Snwhitehorn	rman_set_rid(rv, *rid);
354256901Snwhitehorn
355256901Snwhitehorn	if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(child, type,
356256901Snwhitehorn	    *rid, rv) != 0) {
357256901Snwhitehorn		rman_release_resource(rv);
358256901Snwhitehorn		return (NULL);
359171805Smarcel	}
36099652Sbenno
361256901Snwhitehorn	if (!passthrough && rle != NULL) {
362256901Snwhitehorn		rle->res = rv;
363256901Snwhitehorn		rle->start = rman_get_start(rv);
364256901Snwhitehorn		rle->end = rman_get_end(rv);
365256901Snwhitehorn		rle->count = rle->end - rle->start + 1;
366256901Snwhitehorn	}
36799652Sbenno
36899652Sbenno	return (rv);
36999652Sbenno}
37099652Sbenno
37199652Sbennostatic int
372261513Snwhitehornofwbus_adjust_resource(device_t bus, device_t child __unused, int type,
373256901Snwhitehorn    struct resource *r, u_long start, u_long end)
37499652Sbenno{
375261513Snwhitehorn	struct ofwbus_softc *sc;
376256901Snwhitehorn	struct rman *rm;
377261513Snwhitehorn	device_t ofwbus;
37899652Sbenno
379261513Snwhitehorn	ofwbus = bus;
380261513Snwhitehorn	while (strcmp(device_get_name(device_get_parent(ofwbus)), "root") != 0)
381261513Snwhitehorn		ofwbus = device_get_parent(ofwbus);
382261513Snwhitehorn	sc = device_get_softc(ofwbus);
383256901Snwhitehorn	switch (type) {
384256901Snwhitehorn	case SYS_RES_IRQ:
385256901Snwhitehorn		rm = &sc->sc_intr_rman;
386256901Snwhitehorn		break;
387256901Snwhitehorn	case SYS_RES_MEMORY:
388256901Snwhitehorn		rm = &sc->sc_mem_rman;
389256901Snwhitehorn		break;
390256901Snwhitehorn	default:
391124468Sgrehan		return (EINVAL);
39299652Sbenno	}
393256901Snwhitehorn	if (rm == NULL)
394256901Snwhitehorn		return (ENXIO);
395256901Snwhitehorn	if (rman_is_region_manager(r, rm) == 0)
396256901Snwhitehorn		return (EINVAL);
397256901Snwhitehorn	return (rman_adjust_resource(r, start, end));
39899652Sbenno}
39999652Sbenno
400256901Snwhitehornstatic int
401261513Snwhitehornofwbus_release_resource(device_t bus __unused, device_t child, int type,
402256901Snwhitehorn    int rid, struct resource *r)
40399652Sbenno{
404256901Snwhitehorn	int error;
40599652Sbenno
406256901Snwhitehorn	if ((rman_get_flags(r) & RF_ACTIVE) != 0) {
407256901Snwhitehorn		error = bus_deactivate_resource(child, type, rid, r);
408256901Snwhitehorn		if (error)
409256901Snwhitehorn			return (error);
410256855Snwhitehorn	}
411256901Snwhitehorn	return (rman_release_resource(r));
412256901Snwhitehorn}
41399652Sbenno
414256901Snwhitehornstatic struct resource_list *
415261513Snwhitehornofwbus_get_resource_list(device_t bus __unused, device_t child)
416256901Snwhitehorn{
417261513Snwhitehorn	struct ofwbus_devinfo *ndi;
418256901Snwhitehorn
419256901Snwhitehorn	ndi = device_get_ivars(child);
420256901Snwhitehorn	return (&ndi->ndi_rl);
42199652Sbenno}
422124468Sgrehan
423256855Snwhitehornstatic const struct ofw_bus_devinfo *
424261513Snwhitehornofwbus_get_devinfo(device_t bus __unused, device_t child)
425168885Sgrehan{
426261513Snwhitehorn	struct ofwbus_devinfo *ndi;
427168885Sgrehan
428256901Snwhitehorn	ndi = device_get_ivars(child);
429256901Snwhitehorn	return (&ndi->ndi_obdinfo);
430168885Sgrehan}
431168885Sgrehan
432261513Snwhitehornstatic struct ofwbus_devinfo *
433261513Snwhitehornofwbus_setup_dinfo(device_t dev, phandle_t node)
434256901Snwhitehorn{
435261513Snwhitehorn	struct ofwbus_softc *sc;
436261513Snwhitehorn	struct ofwbus_devinfo *ndi;
437256901Snwhitehorn	uint32_t *reg, *intr, icells;
438256901Snwhitehorn	uint64_t phys, size;
439256901Snwhitehorn	phandle_t iparent;
440256901Snwhitehorn	int i, j;
441256901Snwhitehorn	int nintr;
442256901Snwhitehorn	int nreg;
443256901Snwhitehorn
444256901Snwhitehorn	sc = device_get_softc(dev);
445256901Snwhitehorn
446256901Snwhitehorn	ndi = malloc(sizeof(*ndi), M_DEVBUF, M_WAITOK | M_ZERO);
447256901Snwhitehorn	if (ofw_bus_gen_setup_devinfo(&ndi->ndi_obdinfo, node) != 0) {
448256901Snwhitehorn		free(ndi, M_DEVBUF);
449256901Snwhitehorn		return (NULL);
450256901Snwhitehorn	}
451261513Snwhitehorn	if (OFWBUS_EXCLUDED(ndi->ndi_obdinfo.obd_name,
452256901Snwhitehorn	    ndi->ndi_obdinfo.obd_type)) {
453256901Snwhitehorn		ofw_bus_gen_destroy_devinfo(&ndi->ndi_obdinfo);
454256901Snwhitehorn		free(ndi, M_DEVBUF);
455256901Snwhitehorn		return (NULL);
456256901Snwhitehorn	}
457256901Snwhitehorn
458256901Snwhitehorn	resource_list_init(&ndi->ndi_rl);
459256969Snwhitehorn	nreg = OF_getencprop_alloc(node, "reg", sizeof(*reg), (void **)&reg);
460256901Snwhitehorn	if (nreg == -1)
461256901Snwhitehorn		nreg = 0;
462256914Snwhitehorn	if (nreg % (sc->acells + sc->scells) != 0) {
463256914Snwhitehorn		if (bootverbose)
464256914Snwhitehorn			device_printf(dev, "Malformed reg property on <%s>\n",
465256914Snwhitehorn			    ndi->ndi_obdinfo.obd_name);
466256914Snwhitehorn		nreg = 0;
467256914Snwhitehorn	}
468256901Snwhitehorn
469256901Snwhitehorn	for (i = 0; i < nreg; i += sc->acells + sc->scells) {
470256901Snwhitehorn		phys = size = 0;
471256901Snwhitehorn		for (j = 0; j < sc->acells; j++) {
472256901Snwhitehorn			phys <<= 32;
473256901Snwhitehorn			phys |= reg[i + j];
474256901Snwhitehorn		}
475256901Snwhitehorn		for (j = 0; j < sc->scells; j++) {
476256901Snwhitehorn			size <<= 32;
477256901Snwhitehorn			size |= reg[i + sc->acells + j];
478256901Snwhitehorn		}
479256901Snwhitehorn		/* Skip the dummy reg property of glue devices like ssm(4). */
480256901Snwhitehorn		if (size != 0)
481256901Snwhitehorn			resource_list_add(&ndi->ndi_rl, SYS_RES_MEMORY, i,
482256901Snwhitehorn			    phys, phys + size - 1, size);
483256901Snwhitehorn	}
484256901Snwhitehorn	free(reg, M_OFWPROP);
485256901Snwhitehorn
486256969Snwhitehorn	nintr = OF_getencprop_alloc(node, "interrupts",  sizeof(*intr),
487256901Snwhitehorn	    (void **)&intr);
488256901Snwhitehorn	if (nintr > 0) {
489256901Snwhitehorn		iparent = 0;
490257055Snwhitehorn		OF_searchencprop(node, "interrupt-parent", &iparent,
491256901Snwhitehorn		    sizeof(iparent));
492257118Snwhitehorn		OF_searchencprop(OF_xref_phandle(iparent), "#interrupt-cells",
493257118Snwhitehorn		    &icells, sizeof(icells));
494256901Snwhitehorn		for (i = 0; i < nintr; i+= icells) {
495261351Snwhitehorn			intr[i] = ofw_bus_map_intr(dev, iparent, icells,
496261351Snwhitehorn			    &intr[i]);
497256901Snwhitehorn			resource_list_add(&ndi->ndi_rl, SYS_RES_IRQ, i, intr[i],
498256901Snwhitehorn			    intr[i], 1);
499256901Snwhitehorn		}
500256901Snwhitehorn		free(intr, M_OFWPROP);
501256901Snwhitehorn	}
502256901Snwhitehorn
503256901Snwhitehorn	return (ndi);
504256901Snwhitehorn}
505256901Snwhitehorn
506256901Snwhitehornstatic void
507261513Snwhitehornofwbus_destroy_dinfo(struct ofwbus_devinfo *ndi)
508256901Snwhitehorn{
509256901Snwhitehorn
510256901Snwhitehorn	resource_list_free(&ndi->ndi_rl);
511256901Snwhitehorn	ofw_bus_gen_destroy_devinfo(&ndi->ndi_obdinfo);
512256901Snwhitehorn	free(ndi, M_DEVBUF);
513256901Snwhitehorn}
514256901Snwhitehorn
515256901Snwhitehornstatic int
516261513Snwhitehornofwbus_print_res(struct ofwbus_devinfo *ndi)
517256901Snwhitehorn{
518256901Snwhitehorn	int rv;
519256901Snwhitehorn
520256901Snwhitehorn	rv = 0;
521256901Snwhitehorn	rv += resource_list_print_type(&ndi->ndi_rl, "mem", SYS_RES_MEMORY,
522256901Snwhitehorn	    "%#lx");
523256901Snwhitehorn	rv += resource_list_print_type(&ndi->ndi_rl, "irq", SYS_RES_IRQ,
524256901Snwhitehorn	    "%ld");
525256901Snwhitehorn	return (rv);
526256901Snwhitehorn}
527256901Snwhitehorn
528