xref: /freebsd/sys/dev/fdt/simplebus.c (revision 1f40dbc85461b76d8aa691cd5bdf39ec9c2115cc)
158158742SRafal Jaworowski /*-
258158742SRafal Jaworowski  * Copyright (c) 2009-2010 The FreeBSD Foundation
358158742SRafal Jaworowski  * All rights reserved.
458158742SRafal Jaworowski  *
558158742SRafal Jaworowski  * This software was developed by Semihalf under sponsorship from
658158742SRafal Jaworowski  * the FreeBSD Foundation.
758158742SRafal Jaworowski  *
858158742SRafal Jaworowski  * Redistribution and use in source and binary forms, with or without
958158742SRafal Jaworowski  * modification, are permitted provided that the following conditions
1058158742SRafal Jaworowski  * are met:
1158158742SRafal Jaworowski  * 1. Redistributions of source code must retain the above copyright
1258158742SRafal Jaworowski  *    notice, this list of conditions and the following disclaimer.
1358158742SRafal Jaworowski  * 2. Redistributions in binary form must reproduce the above copyright
1458158742SRafal Jaworowski  *    notice, this list of conditions and the following disclaimer in the
1558158742SRafal Jaworowski  *    documentation and/or other materials provided with the distribution.
1658158742SRafal Jaworowski  *
1758158742SRafal Jaworowski  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1858158742SRafal Jaworowski  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1958158742SRafal Jaworowski  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2058158742SRafal Jaworowski  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2158158742SRafal Jaworowski  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2258158742SRafal Jaworowski  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2358158742SRafal Jaworowski  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2458158742SRafal Jaworowski  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2558158742SRafal Jaworowski  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2658158742SRafal Jaworowski  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2758158742SRafal Jaworowski  * SUCH DAMAGE.
2858158742SRafal Jaworowski  */
2958158742SRafal Jaworowski 
3058158742SRafal Jaworowski #include <sys/cdefs.h>
3158158742SRafal Jaworowski __FBSDID("$FreeBSD$");
3258158742SRafal Jaworowski 
3358158742SRafal Jaworowski #include "opt_platform.h"
3458158742SRafal Jaworowski #include <sys/param.h>
3558158742SRafal Jaworowski #include <sys/systm.h>
3658158742SRafal Jaworowski #include <sys/ktr.h>
3758158742SRafal Jaworowski #include <sys/kernel.h>
3858158742SRafal Jaworowski #include <sys/module.h>
3958158742SRafal Jaworowski #include <sys/bus.h>
4058158742SRafal Jaworowski #include <sys/rman.h>
4158158742SRafal Jaworowski #include <sys/malloc.h>
4258158742SRafal Jaworowski 
4358158742SRafal Jaworowski #include <machine/fdt.h>
4458158742SRafal Jaworowski 
4558158742SRafal Jaworowski #include <dev/ofw/ofw_bus.h>
4658158742SRafal Jaworowski #include <dev/ofw/ofw_bus_subr.h>
4758158742SRafal Jaworowski #include <dev/ofw/openfirm.h>
4858158742SRafal Jaworowski 
4958158742SRafal Jaworowski #include "fdt_common.h"
50*1f40dbc8SBrooks Davis #include "fdt_ic_if.h"
5158158742SRafal Jaworowski #include "ofw_bus_if.h"
5258158742SRafal Jaworowski 
5358158742SRafal Jaworowski #ifdef DEBUG
5458158742SRafal Jaworowski #define debugf(fmt, args...) do { printf("%s(): ", __func__);	\
5558158742SRafal Jaworowski     printf(fmt,##args); } while (0)
5658158742SRafal Jaworowski #else
5758158742SRafal Jaworowski #define debugf(fmt, args...)
5858158742SRafal Jaworowski #endif
5958158742SRafal Jaworowski 
6058158742SRafal Jaworowski static MALLOC_DEFINE(M_SIMPLEBUS, "simplebus", "simplebus devices information");
6158158742SRafal Jaworowski 
6258158742SRafal Jaworowski struct simplebus_softc {
6358158742SRafal Jaworowski 	int	sc_addr_cells;
6458158742SRafal Jaworowski 	int	sc_size_cells;
6558158742SRafal Jaworowski };
6658158742SRafal Jaworowski 
6758158742SRafal Jaworowski struct simplebus_devinfo {
6858158742SRafal Jaworowski 	struct ofw_bus_devinfo	di_ofw;
6958158742SRafal Jaworowski 	struct resource_list	di_res;
7058158742SRafal Jaworowski 
7158158742SRafal Jaworowski 	/* Interrupts sense-level info for this device */
7258158742SRafal Jaworowski 	struct fdt_sense_level	di_intr_sl[DI_MAX_INTR_NUM];
7358158742SRafal Jaworowski };
7458158742SRafal Jaworowski 
7558158742SRafal Jaworowski /*
7658158742SRafal Jaworowski  * Prototypes.
7758158742SRafal Jaworowski  */
7858158742SRafal Jaworowski static int simplebus_probe(device_t);
7958158742SRafal Jaworowski static int simplebus_attach(device_t);
8058158742SRafal Jaworowski 
8158158742SRafal Jaworowski static int simplebus_print_child(device_t, device_t);
8258158742SRafal Jaworowski static int simplebus_setup_intr(device_t, device_t, struct resource *, int,
8358158742SRafal Jaworowski     driver_filter_t *, driver_intr_t *, void *, void **);
84*1f40dbc8SBrooks Davis static int simplebus_teardown_intr(device_t, device_t, struct resource *,
85*1f40dbc8SBrooks Davis     void *);
8658158742SRafal Jaworowski 
87*1f40dbc8SBrooks Davis static int simplebus_activate_resource(device_t, device_t, int, int,
88*1f40dbc8SBrooks Davis     struct resource *);
8958158742SRafal Jaworowski static struct resource *simplebus_alloc_resource(device_t, device_t, int,
9058158742SRafal Jaworowski     int *, u_long, u_long, u_long, u_int);
91*1f40dbc8SBrooks Davis static int simplebus_deactivate_resource(device_t, device_t, int, int,
92*1f40dbc8SBrooks Davis     struct resource *);
93*1f40dbc8SBrooks Davis static int simplebus_release_resource(device_t, device_t, int, int,
94*1f40dbc8SBrooks Davis     struct resource *);
95*1f40dbc8SBrooks Davis static device_t simplebus_get_interrupt_parent(device_t);
9658158742SRafal Jaworowski static struct resource_list *simplebus_get_resource_list(device_t, device_t);
9758158742SRafal Jaworowski 
9858158742SRafal Jaworowski static ofw_bus_get_devinfo_t simplebus_get_devinfo;
9958158742SRafal Jaworowski 
10058158742SRafal Jaworowski /*
10158158742SRafal Jaworowski  * Bus interface definition.
10258158742SRafal Jaworowski  */
10358158742SRafal Jaworowski static device_method_t simplebus_methods[] = {
10458158742SRafal Jaworowski 	/* Device interface */
10558158742SRafal Jaworowski 	DEVMETHOD(device_probe,		simplebus_probe),
10658158742SRafal Jaworowski 	DEVMETHOD(device_attach,	simplebus_attach),
10758158742SRafal Jaworowski 	DEVMETHOD(device_detach,	bus_generic_detach),
10858158742SRafal Jaworowski 	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
10958158742SRafal Jaworowski 	DEVMETHOD(device_suspend,	bus_generic_suspend),
11058158742SRafal Jaworowski 	DEVMETHOD(device_resume,	bus_generic_resume),
11158158742SRafal Jaworowski 
11258158742SRafal Jaworowski 	/* Bus interface */
11358158742SRafal Jaworowski 	DEVMETHOD(bus_print_child,	simplebus_print_child),
11458158742SRafal Jaworowski 	DEVMETHOD(bus_alloc_resource,	simplebus_alloc_resource),
115*1f40dbc8SBrooks Davis 	DEVMETHOD(bus_release_resource,	simplebus_release_resource),
116*1f40dbc8SBrooks Davis 	DEVMETHOD(bus_activate_resource, simplebus_activate_resource),
117*1f40dbc8SBrooks Davis 	DEVMETHOD(bus_deactivate_resource, simplebus_deactivate_resource),
11858158742SRafal Jaworowski 	DEVMETHOD(bus_setup_intr,	simplebus_setup_intr),
119*1f40dbc8SBrooks Davis 	DEVMETHOD(bus_teardown_intr,	simplebus_teardown_intr),
12058158742SRafal Jaworowski 	DEVMETHOD(bus_get_resource_list, simplebus_get_resource_list),
12158158742SRafal Jaworowski 
12258158742SRafal Jaworowski 	/* OFW bus interface */
12358158742SRafal Jaworowski 	DEVMETHOD(ofw_bus_get_devinfo,	simplebus_get_devinfo),
12458158742SRafal Jaworowski 	DEVMETHOD(ofw_bus_get_compat,	ofw_bus_gen_get_compat),
12558158742SRafal Jaworowski 	DEVMETHOD(ofw_bus_get_model,	ofw_bus_gen_get_model),
12658158742SRafal Jaworowski 	DEVMETHOD(ofw_bus_get_name,	ofw_bus_gen_get_name),
12758158742SRafal Jaworowski 	DEVMETHOD(ofw_bus_get_node,	ofw_bus_gen_get_node),
12858158742SRafal Jaworowski 	DEVMETHOD(ofw_bus_get_type,	ofw_bus_gen_get_type),
12958158742SRafal Jaworowski 
13058158742SRafal Jaworowski 	{ 0, 0 }
13158158742SRafal Jaworowski };
13258158742SRafal Jaworowski 
13358158742SRafal Jaworowski static driver_t simplebus_driver = {
13458158742SRafal Jaworowski 	"simplebus",
13558158742SRafal Jaworowski 	simplebus_methods,
13658158742SRafal Jaworowski 	sizeof(struct simplebus_softc)
13758158742SRafal Jaworowski };
13858158742SRafal Jaworowski 
13958158742SRafal Jaworowski devclass_t simplebus_devclass;
14058158742SRafal Jaworowski 
14158158742SRafal Jaworowski DRIVER_MODULE(simplebus, fdtbus, simplebus_driver, simplebus_devclass, 0, 0);
142bf9d6206SAleksandr Rybalko DRIVER_MODULE(simplebus, simplebus, simplebus_driver, simplebus_devclass, 0,
143bf9d6206SAleksandr Rybalko     0);
14458158742SRafal Jaworowski 
14558158742SRafal Jaworowski static int
14658158742SRafal Jaworowski simplebus_probe(device_t dev)
14758158742SRafal Jaworowski {
14858158742SRafal Jaworowski 
1492737a5a9SAleksandr Rybalko 	if (!ofw_bus_is_compatible(dev, "simple-bus"))
15058158742SRafal Jaworowski 		return (ENXIO);
15158158742SRafal Jaworowski 
15258158742SRafal Jaworowski 	device_set_desc(dev, "Flattened device tree simple bus");
15358158742SRafal Jaworowski 
1542737a5a9SAleksandr Rybalko 	return (BUS_PROBE_GENERIC);
15558158742SRafal Jaworowski }
15658158742SRafal Jaworowski 
15758158742SRafal Jaworowski static int
15858158742SRafal Jaworowski simplebus_attach(device_t dev)
15958158742SRafal Jaworowski {
16058158742SRafal Jaworowski 	device_t dev_child;
16158158742SRafal Jaworowski 	struct simplebus_devinfo *di;
16258158742SRafal Jaworowski 	struct simplebus_softc *sc;
16358158742SRafal Jaworowski 	phandle_t dt_node, dt_child;
16458158742SRafal Jaworowski 
16558158742SRafal Jaworowski 	sc = device_get_softc(dev);
16658158742SRafal Jaworowski 
16758158742SRafal Jaworowski 	/*
16858158742SRafal Jaworowski 	 * Walk simple-bus and add direct subordinates as our children.
16958158742SRafal Jaworowski 	 */
17058158742SRafal Jaworowski 	dt_node = ofw_bus_get_node(dev);
17158158742SRafal Jaworowski 	for (dt_child = OF_child(dt_node); dt_child != 0;
17258158742SRafal Jaworowski 	    dt_child = OF_peer(dt_child)) {
17358158742SRafal Jaworowski 
17458158742SRafal Jaworowski 		/* Check and process 'status' property. */
17558158742SRafal Jaworowski 		if (!(fdt_is_enabled(dt_child)))
17658158742SRafal Jaworowski 			continue;
17758158742SRafal Jaworowski 
17858158742SRafal Jaworowski 		if (!(fdt_pm_is_enabled(dt_child)))
17958158742SRafal Jaworowski 			continue;
18058158742SRafal Jaworowski 
18158158742SRafal Jaworowski 		di = malloc(sizeof(*di), M_SIMPLEBUS, M_WAITOK | M_ZERO);
18258158742SRafal Jaworowski 
18358158742SRafal Jaworowski 		if (ofw_bus_gen_setup_devinfo(&di->di_ofw, dt_child) != 0) {
18458158742SRafal Jaworowski 			free(di, M_SIMPLEBUS);
18558158742SRafal Jaworowski 			device_printf(dev, "could not set up devinfo\n");
18658158742SRafal Jaworowski 			continue;
18758158742SRafal Jaworowski 		}
18858158742SRafal Jaworowski 
18958158742SRafal Jaworowski 		resource_list_init(&di->di_res);
1908bb93637SOleksandr Tymoshenko 		if (fdt_reg_to_rl(dt_child, &di->di_res)) {
1918bb93637SOleksandr Tymoshenko 			device_printf(dev,
1928bb93637SOleksandr Tymoshenko 			    "%s: could not process 'reg' "
193a22cd1e6SRafal Jaworowski 			    "property\n", di->di_ofw.obd_name);
19458158742SRafal Jaworowski 			ofw_bus_gen_destroy_devinfo(&di->di_ofw);
19558158742SRafal Jaworowski 			free(di, M_SIMPLEBUS);
19658158742SRafal Jaworowski 			continue;
19758158742SRafal Jaworowski 		}
19858158742SRafal Jaworowski 
19958158742SRafal Jaworowski 		if (fdt_intr_to_rl(dt_child, &di->di_res, di->di_intr_sl)) {
200a22cd1e6SRafal Jaworowski 			device_printf(dev, "%s: could not process "
201a22cd1e6SRafal Jaworowski 			    "'interrupts' property\n", di->di_ofw.obd_name);
20258158742SRafal Jaworowski 			resource_list_free(&di->di_res);
20358158742SRafal Jaworowski 			ofw_bus_gen_destroy_devinfo(&di->di_ofw);
20458158742SRafal Jaworowski 			free(di, M_SIMPLEBUS);
20558158742SRafal Jaworowski 			continue;
20658158742SRafal Jaworowski 		}
20758158742SRafal Jaworowski 
20858158742SRafal Jaworowski 		/* Add newbus device for this FDT node */
20958158742SRafal Jaworowski 		dev_child = device_add_child(dev, NULL, -1);
21058158742SRafal Jaworowski 		if (dev_child == NULL) {
21158158742SRafal Jaworowski 			device_printf(dev, "could not add child: %s\n",
21258158742SRafal Jaworowski 			    di->di_ofw.obd_name);
21358158742SRafal Jaworowski 			resource_list_free(&di->di_res);
21458158742SRafal Jaworowski 			ofw_bus_gen_destroy_devinfo(&di->di_ofw);
21558158742SRafal Jaworowski 			free(di, M_SIMPLEBUS);
21658158742SRafal Jaworowski 			continue;
21758158742SRafal Jaworowski 		}
218a22cd1e6SRafal Jaworowski #ifdef DEBUG
219a22cd1e6SRafal Jaworowski 		device_printf(dev, "added child: %s\n\n", di->di_ofw.obd_name);
220a22cd1e6SRafal Jaworowski #endif
22158158742SRafal Jaworowski 		device_set_ivars(dev_child, di);
22258158742SRafal Jaworowski 	}
22358158742SRafal Jaworowski 
22458158742SRafal Jaworowski 	return (bus_generic_attach(dev));
22558158742SRafal Jaworowski }
22658158742SRafal Jaworowski 
22758158742SRafal Jaworowski static int
22858158742SRafal Jaworowski simplebus_print_child(device_t dev, device_t child)
22958158742SRafal Jaworowski {
230*1f40dbc8SBrooks Davis 	device_t ip;
23158158742SRafal Jaworowski 	struct simplebus_devinfo *di;
23258158742SRafal Jaworowski 	struct resource_list *rl;
23358158742SRafal Jaworowski 	int rv;
23458158742SRafal Jaworowski 
23558158742SRafal Jaworowski 	di = device_get_ivars(child);
23658158742SRafal Jaworowski 	rl = &di->di_res;
23758158742SRafal Jaworowski 
23858158742SRafal Jaworowski 	rv = 0;
23958158742SRafal Jaworowski 	rv += bus_print_child_header(dev, child);
24058158742SRafal Jaworowski 	rv += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
24158158742SRafal Jaworowski 	rv += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
242*1f40dbc8SBrooks Davis 	if ((ip = simplebus_get_interrupt_parent(child)) != NULL)
243*1f40dbc8SBrooks Davis 		rv += printf(" (%s)", device_get_nameunit(ip));
24458158742SRafal Jaworowski 	rv += bus_print_child_footer(dev, child);
24558158742SRafal Jaworowski 
24658158742SRafal Jaworowski 	return (rv);
24758158742SRafal Jaworowski }
24858158742SRafal Jaworowski 
24958158742SRafal Jaworowski static struct resource *
25058158742SRafal Jaworowski simplebus_alloc_resource(device_t bus, device_t child, int type, int *rid,
25158158742SRafal Jaworowski     u_long start, u_long end, u_long count, u_int flags)
25258158742SRafal Jaworowski {
253*1f40dbc8SBrooks Davis 	device_t ic;
25458158742SRafal Jaworowski 	struct simplebus_devinfo *di;
25558158742SRafal Jaworowski 	struct resource_list_entry *rle;
25658158742SRafal Jaworowski 
25758158742SRafal Jaworowski 	/*
25858158742SRafal Jaworowski 	 * Request for the default allocation with a given rid: use resource
25958158742SRafal Jaworowski 	 * list stored in the local device info.
26058158742SRafal Jaworowski 	 */
26158158742SRafal Jaworowski 	if ((start == 0UL) && (end == ~0UL)) {
26258158742SRafal Jaworowski 		if ((di = device_get_ivars(child)) == NULL)
26358158742SRafal Jaworowski 			return (NULL);
26458158742SRafal Jaworowski 
26558158742SRafal Jaworowski 		if (type == SYS_RES_IOPORT)
26658158742SRafal Jaworowski 			type = SYS_RES_MEMORY;
26758158742SRafal Jaworowski 
26858158742SRafal Jaworowski 		rle = resource_list_find(&di->di_res, type, *rid);
26958158742SRafal Jaworowski 		if (rle == NULL) {
270089dfb09SAleksandr Rybalko 			if (bootverbose)
27158158742SRafal Jaworowski 				device_printf(bus, "no default resources for "
27258158742SRafal Jaworowski 				    "rid = %d, type = %d\n", *rid, type);
27358158742SRafal Jaworowski 			return (NULL);
27458158742SRafal Jaworowski 		}
27558158742SRafal Jaworowski 		start = rle->start;
27658158742SRafal Jaworowski 		end = rle->end;
27758158742SRafal Jaworowski 		count = rle->count;
27858158742SRafal Jaworowski 	}
27958158742SRafal Jaworowski 
280*1f40dbc8SBrooks Davis 	if (type == SYS_RES_IRQ &&
281*1f40dbc8SBrooks Davis 	    (ic = simplebus_get_interrupt_parent(child)) != NULL)
282*1f40dbc8SBrooks Davis 		return(FDT_IC_ALLOC_INTR(ic, child, rid, start, flags));
283*1f40dbc8SBrooks Davis 
28458158742SRafal Jaworowski 	return (bus_generic_alloc_resource(bus, child, type, rid, start, end,
28558158742SRafal Jaworowski 	    count, flags));
28658158742SRafal Jaworowski }
28758158742SRafal Jaworowski 
288*1f40dbc8SBrooks Davis static int
289*1f40dbc8SBrooks Davis simplebus_activate_resource(device_t dev, device_t child, int type, int rid,
290*1f40dbc8SBrooks Davis     struct resource *r)
291*1f40dbc8SBrooks Davis {
292*1f40dbc8SBrooks Davis 	device_t ic;
293*1f40dbc8SBrooks Davis 
294*1f40dbc8SBrooks Davis 	if (type == SYS_RES_IRQ &&
295*1f40dbc8SBrooks Davis 	    (ic = simplebus_get_interrupt_parent(child)) != NULL)
296*1f40dbc8SBrooks Davis 		return (FDT_IC_ACTIVATE_INTR(ic, r));
297*1f40dbc8SBrooks Davis 
298*1f40dbc8SBrooks Davis 	return (bus_generic_activate_resource(dev, child, type, rid, r));
299*1f40dbc8SBrooks Davis }
300*1f40dbc8SBrooks Davis 
301*1f40dbc8SBrooks Davis static int
302*1f40dbc8SBrooks Davis simplebus_deactivate_resource(device_t dev, device_t child, int type, int rid,
303*1f40dbc8SBrooks Davis     struct resource *r)
304*1f40dbc8SBrooks Davis {
305*1f40dbc8SBrooks Davis 	device_t ic;
306*1f40dbc8SBrooks Davis 
307*1f40dbc8SBrooks Davis 	if (type == SYS_RES_IRQ &&
308*1f40dbc8SBrooks Davis 	    (ic = simplebus_get_interrupt_parent(child)) != NULL)
309*1f40dbc8SBrooks Davis 		return (FDT_IC_DEACTIVATE_INTR(ic, r));
310*1f40dbc8SBrooks Davis 
311*1f40dbc8SBrooks Davis 	return (bus_generic_deactivate_resource(dev, child, type, rid, r));
312*1f40dbc8SBrooks Davis }
313*1f40dbc8SBrooks Davis 
314*1f40dbc8SBrooks Davis static int
315*1f40dbc8SBrooks Davis simplebus_release_resource(device_t dev, device_t child, int type, int rid,
316*1f40dbc8SBrooks Davis     struct resource *r)
317*1f40dbc8SBrooks Davis {
318*1f40dbc8SBrooks Davis 	device_t ic;
319*1f40dbc8SBrooks Davis 
320*1f40dbc8SBrooks Davis 	if (type == SYS_RES_IRQ &&
321*1f40dbc8SBrooks Davis 	    (ic = simplebus_get_interrupt_parent(child)) != NULL)
322*1f40dbc8SBrooks Davis 		return (FDT_IC_RELEASE_INTR(ic, r));
323*1f40dbc8SBrooks Davis 
324*1f40dbc8SBrooks Davis 	return (bus_generic_release_resource(dev, child, type, rid, r));
325*1f40dbc8SBrooks Davis }
326*1f40dbc8SBrooks Davis 
32758158742SRafal Jaworowski static struct resource_list *
32858158742SRafal Jaworowski simplebus_get_resource_list(device_t bus, device_t child)
32958158742SRafal Jaworowski {
33058158742SRafal Jaworowski 	struct simplebus_devinfo *di;
33158158742SRafal Jaworowski 
33258158742SRafal Jaworowski 	di = device_get_ivars(child);
33358158742SRafal Jaworowski 	return (&di->di_res);
33458158742SRafal Jaworowski }
33558158742SRafal Jaworowski 
336*1f40dbc8SBrooks Davis static device_t
337*1f40dbc8SBrooks Davis simplebus_get_interrupt_parent(device_t dev)
338*1f40dbc8SBrooks Davis {
339*1f40dbc8SBrooks Davis 	struct simplebus_devinfo *di;
340*1f40dbc8SBrooks Davis 	struct fdt_ic *ic;
341*1f40dbc8SBrooks Davis 	device_t ip;
342*1f40dbc8SBrooks Davis 	ihandle_t iph;
343*1f40dbc8SBrooks Davis 	phandle_t ph;
344*1f40dbc8SBrooks Davis 
345*1f40dbc8SBrooks Davis 	ip = NULL;
346*1f40dbc8SBrooks Davis 
347*1f40dbc8SBrooks Davis 	di = device_get_ivars(dev);
348*1f40dbc8SBrooks Davis 	if (di == NULL)
349*1f40dbc8SBrooks Davis 		return (NULL);
350*1f40dbc8SBrooks Davis 
351*1f40dbc8SBrooks Davis 	if (OF_getprop(di->di_ofw.obd_node, "interrupt-parent", &iph,
352*1f40dbc8SBrooks Davis 	    sizeof(iph)) > 0) {
353*1f40dbc8SBrooks Davis 		iph = fdt32_to_cpu(iph);
354*1f40dbc8SBrooks Davis 		ph = OF_instance_to_package(iph);
355*1f40dbc8SBrooks Davis 		SLIST_FOREACH(ic, &fdt_ic_list_head, fdt_ics) {
356*1f40dbc8SBrooks Davis 			if (ic->iph == ph) {
357*1f40dbc8SBrooks Davis 				ip = ic->dev;
358*1f40dbc8SBrooks Davis 				break;
359*1f40dbc8SBrooks Davis 			}
360*1f40dbc8SBrooks Davis 		}
361*1f40dbc8SBrooks Davis 	}
362*1f40dbc8SBrooks Davis 	return (ip);
363*1f40dbc8SBrooks Davis }
364*1f40dbc8SBrooks Davis 
36558158742SRafal Jaworowski static int
36658158742SRafal Jaworowski simplebus_setup_intr(device_t bus, device_t child, struct resource *res,
36758158742SRafal Jaworowski     int flags, driver_filter_t *filter, driver_intr_t *ihand, void *arg,
36858158742SRafal Jaworowski     void **cookiep)
36958158742SRafal Jaworowski {
37058158742SRafal Jaworowski 	struct simplebus_devinfo *di;
371*1f40dbc8SBrooks Davis 	device_t ic;
37258158742SRafal Jaworowski 	enum intr_trigger trig;
37358158742SRafal Jaworowski 	enum intr_polarity pol;
374*1f40dbc8SBrooks Davis 	int error, irq, rid;
375120c7e2eSMarcel Moolenaar 
376120c7e2eSMarcel Moolenaar 	di = device_get_ivars(child);
377120c7e2eSMarcel Moolenaar 	if (di == NULL)
378120c7e2eSMarcel Moolenaar 		return (ENXIO);
37958158742SRafal Jaworowski 
38058158742SRafal Jaworowski 	if (res == NULL)
381120c7e2eSMarcel Moolenaar 		return (EINVAL);
38258158742SRafal Jaworowski 
38358158742SRafal Jaworowski 	rid = rman_get_rid(res);
384120c7e2eSMarcel Moolenaar 	if (rid >= DI_MAX_INTR_NUM)
385120c7e2eSMarcel Moolenaar 		return (ENOENT);
38658158742SRafal Jaworowski 
387*1f40dbc8SBrooks Davis 	ic = simplebus_get_interrupt_parent(child);
388*1f40dbc8SBrooks Davis 
38958158742SRafal Jaworowski 	trig = di->di_intr_sl[rid].trig;
39058158742SRafal Jaworowski 	pol = di->di_intr_sl[rid].pol;
391120c7e2eSMarcel Moolenaar 	if (trig != INTR_TRIGGER_CONFORM || pol != INTR_POLARITY_CONFORM) {
392*1f40dbc8SBrooks Davis 		irq = rman_get_start(res);
393*1f40dbc8SBrooks Davis 		if (ic != NULL)
394*1f40dbc8SBrooks Davis 			error = FDT_IC_CONFIG_INTR(ic, irq, trig, pol);
395*1f40dbc8SBrooks Davis 		else
396*1f40dbc8SBrooks Davis 			error = bus_generic_config_intr(bus, irq, trig, pol);
397120c7e2eSMarcel Moolenaar 		if (error)
398120c7e2eSMarcel Moolenaar 			return (error);
399120c7e2eSMarcel Moolenaar 	}
40058158742SRafal Jaworowski 
401*1f40dbc8SBrooks Davis 	if (ic != NULL)
402*1f40dbc8SBrooks Davis 		error = FDT_IC_SETUP_INTR(ic, child, res, flags, filter,
403*1f40dbc8SBrooks Davis 		    ihand, arg, cookiep);
404*1f40dbc8SBrooks Davis 	else
405*1f40dbc8SBrooks Davis 		error = bus_generic_setup_intr(bus, child, res, flags, filter,
406*1f40dbc8SBrooks Davis 		    ihand, arg, cookiep);
407120c7e2eSMarcel Moolenaar 	return (error);
40858158742SRafal Jaworowski }
40958158742SRafal Jaworowski 
410*1f40dbc8SBrooks Davis static int
411*1f40dbc8SBrooks Davis simplebus_teardown_intr(device_t bus, device_t child, struct resource *res,
412*1f40dbc8SBrooks Davis     void *cookie)
413*1f40dbc8SBrooks Davis {
414*1f40dbc8SBrooks Davis 	device_t ic;
415*1f40dbc8SBrooks Davis 
416*1f40dbc8SBrooks Davis 	if ((ic = simplebus_get_interrupt_parent(child)) != NULL)
417*1f40dbc8SBrooks Davis 		return (FDT_IC_TEARDOWN_INTR(ic, child, res, cookie));
418*1f40dbc8SBrooks Davis 
419*1f40dbc8SBrooks Davis 	return (bus_generic_teardown_intr(bus, child, res, cookie));
420*1f40dbc8SBrooks Davis }
421*1f40dbc8SBrooks Davis 
42258158742SRafal Jaworowski static const struct ofw_bus_devinfo *
42358158742SRafal Jaworowski simplebus_get_devinfo(device_t bus, device_t child)
42458158742SRafal Jaworowski {
42558158742SRafal Jaworowski 	struct simplebus_devinfo *di;
42658158742SRafal Jaworowski 
42758158742SRafal Jaworowski 	di = device_get_ivars(child);
42858158742SRafal Jaworowski 	return (&di->di_ofw);
42958158742SRafal Jaworowski }
430