diff options
author | Ian Lepore <ian@FreeBSD.org> | 2015-03-27 23:10:15 +0000 |
---|---|---|
committer | Ian Lepore <ian@FreeBSD.org> | 2015-03-27 23:10:15 +0000 |
commit | ecaecbc7d8bc212d8e854088106b3b21e631bb52 (patch) | |
tree | b6b813988bcb1821b70172b1f43167e3d7533bfd /sys/dev/fdt/simplebus.c | |
parent | 8465cb40164fdd4113b78bbec6f67e4832e07f44 (diff) | |
download | src-ecaecbc7d8bc212d8e854088106b3b21e631bb52.tar.gz src-ecaecbc7d8bc212d8e854088106b3b21e631bb52.zip |
Make simplebus a base class of ofwbus. This allows the elimination of
duplicated code in the two classes, and also allows devices in FDT-based
systems to declare simplebus as their parent and still work correctly
when the FDT data describes the device at the root of the tree rather
than as a child of a simplebus (which is common for interrupt, clock,
and power controllers).
Differential Revision: https://reviews.freebsd.org/D1990
Submitted by: Michal Meloun
Notes
Notes:
svn path=/head/; revision=280772
Diffstat (limited to 'sys/dev/fdt/simplebus.c')
-rw-r--r-- | sys/dev/fdt/simplebus.c | 143 |
1 files changed, 101 insertions, 42 deletions
diff --git a/sys/dev/fdt/simplebus.c b/sys/dev/fdt/simplebus.c index 41b87e4785f7..585f5bf8e991 100644 --- a/sys/dev/fdt/simplebus.c +++ b/sys/dev/fdt/simplebus.c @@ -49,7 +49,10 @@ static struct resource *simplebus_alloc_resource(device_t, device_t, int, int *, u_long, u_long, u_long, u_int); static void simplebus_probe_nomatch(device_t bus, device_t child); static int simplebus_print_child(device_t bus, device_t child); - +static device_t simplebus_add_child(device_t dev, u_int order, + const char *name, int unit); +static struct resource_list *simplebus_get_resource_list(device_t bus, + device_t child); /* * ofw_bus interface */ @@ -62,8 +65,6 @@ static const struct ofw_bus_devinfo *simplebus_get_devinfo(device_t bus, static int simplebus_fill_ranges(phandle_t node, struct simplebus_softc *sc); -static struct simplebus_devinfo *simplebus_setup_dinfo(device_t dev, - phandle_t node); /* * Driver methods. @@ -72,10 +73,17 @@ static device_method_t simplebus_methods[] = { /* Device interface */ DEVMETHOD(device_probe, simplebus_probe), DEVMETHOD(device_attach, simplebus_attach), + DEVMETHOD(device_detach, bus_generic_detach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), /* Bus interface */ + DEVMETHOD(bus_add_child, simplebus_add_child), DEVMETHOD(bus_print_child, simplebus_print_child), DEVMETHOD(bus_probe_nomatch, simplebus_probe_nomatch), + DEVMETHOD(bus_read_ivar, bus_generic_read_ivar), + DEVMETHOD(bus_write_ivar, bus_generic_write_ivar), DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), DEVMETHOD(bus_alloc_resource, simplebus_alloc_resource), @@ -83,7 +91,10 @@ static device_method_t simplebus_methods[] = { DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource), + DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource), + DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str), + DEVMETHOD(bus_get_resource_list, simplebus_get_resource_list), /* ofw_bus interface */ DEVMETHOD(ofw_bus_get_devinfo, simplebus_get_devinfo), @@ -132,13 +143,33 @@ static int simplebus_attach(device_t dev) { struct simplebus_softc *sc; - struct simplebus_devinfo *di; phandle_t node; - device_t cdev; - node = ofw_bus_get_node(dev); sc = device_get_softc(dev); + simplebus_init(dev, 0); + if (simplebus_fill_ranges(sc->node, sc) < 0) { + device_printf(dev, "could not get ranges\n"); + return (ENXIO); + } + + /* + * In principle, simplebus could have an interrupt map, but ignore that + * for now + */ + + for (node = OF_child(sc->node); node > 0; node = OF_peer(node)) + simplebus_add_device(dev, node, 0, NULL, -1, NULL); + return (bus_generic_attach(dev)); +} + +void +simplebus_init(device_t dev, phandle_t node) +{ + struct simplebus_softc *sc; + sc = device_get_softc(dev); + if (node == 0) + node = ofw_bus_get_node(dev); sc->dev = dev; sc->node = node; @@ -149,33 +180,6 @@ simplebus_attach(device_t dev) OF_getencprop(node, "#address-cells", &sc->acells, sizeof(sc->acells)); sc->scells = 1; OF_getencprop(node, "#size-cells", &sc->scells, sizeof(sc->scells)); - - if (simplebus_fill_ranges(node, sc) < 0) { - device_printf(dev, "could not get ranges\n"); - return (ENXIO); - } - - /* - * In principle, simplebus could have an interrupt map, but ignore that - * for now - */ - - for (node = OF_child(node); node > 0; node = OF_peer(node)) { - if ((di = simplebus_setup_dinfo(dev, node)) == NULL) - continue; - cdev = device_add_child(dev, NULL, -1); - if (cdev == NULL) { - device_printf(dev, "<%s>: device_add_child failed\n", - di->obdinfo.obd_name); - resource_list_free(&di->rl); - ofw_bus_gen_destroy_devinfo(&di->obdinfo); - free(di, M_DEVBUF); - continue; - } - device_set_ivars(cdev, di); - } - - return (bus_generic_attach(dev)); } static int @@ -227,17 +231,21 @@ simplebus_fill_ranges(phandle_t node, struct simplebus_softc *sc) return (sc->nranges); } -static struct simplebus_devinfo * -simplebus_setup_dinfo(device_t dev, phandle_t node) +struct simplebus_devinfo * +simplebus_setup_dinfo(device_t dev, phandle_t node, + struct simplebus_devinfo *di) { struct simplebus_softc *sc; struct simplebus_devinfo *ndi; sc = device_get_softc(dev); - - ndi = malloc(sizeof(*ndi), M_DEVBUF, M_WAITOK | M_ZERO); + if (di == NULL) + ndi = malloc(sizeof(*ndi), M_DEVBUF, M_WAITOK | M_ZERO); + else + ndi = di; if (ofw_bus_gen_setup_devinfo(&ndi->obdinfo, node) != 0) { - free(ndi, M_DEVBUF); + if (di == NULL) + free(ndi, M_DEVBUF); return (NULL); } @@ -248,6 +256,48 @@ simplebus_setup_dinfo(device_t dev, phandle_t node) return (ndi); } +device_t +simplebus_add_device(device_t dev, phandle_t node, u_int order, + const char *name, int unit, struct simplebus_devinfo *di) +{ + struct simplebus_devinfo *ndi; + device_t cdev; + + if ((ndi = simplebus_setup_dinfo(dev, node, di)) == NULL) + return (NULL); + cdev = device_add_child_ordered(dev, order, name, unit); + if (cdev == NULL) { + device_printf(dev, "<%s>: device_add_child failed\n", + ndi->obdinfo.obd_name); + resource_list_free(&ndi->rl); + ofw_bus_gen_destroy_devinfo(&ndi->obdinfo); + if (di == NULL) + free(ndi, M_DEVBUF); + return (NULL); + } + device_set_ivars(cdev, ndi); + + return(cdev); +} + +static device_t +simplebus_add_child(device_t dev, u_int order, const char *name, int unit) +{ + device_t cdev; + struct simplebus_devinfo *ndi; + + cdev = device_add_child_ordered(dev, order, name, unit); + if (cdev == NULL) + return (NULL); + + ndi = malloc(sizeof(*ndi), M_DEVBUF, M_WAITOK | M_ZERO); + ndi->obdinfo.obd_node = -1; + resource_list_init(&ndi->rl); + device_set_ivars(cdev, ndi); + + return (cdev); +} + static const struct ofw_bus_devinfo * simplebus_get_devinfo(device_t bus __unused, device_t child) { @@ -257,6 +307,15 @@ simplebus_get_devinfo(device_t bus __unused, device_t child) return (&ndi->obdinfo); } +static struct resource_list * +simplebus_get_resource_list(device_t bus __unused, device_t child) +{ + struct simplebus_devinfo *ndi; + + ndi = device_get_ivars(child); + return (&ndi->rl); +} + static struct resource * simplebus_alloc_resource(device_t bus, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) @@ -335,9 +394,11 @@ simplebus_probe_nomatch(device_t bus, device_t child) if (!bootverbose) return; + compat = ofw_bus_get_compat(child); + if (compat == NULL) + return; name = ofw_bus_get_name(child); type = ofw_bus_get_type(child); - compat = ofw_bus_get_compat(child); device_printf(bus, "<%s>", name != NULL ? name : "unknown"); simplebus_print_res(device_get_ivars(child)); @@ -345,9 +406,7 @@ simplebus_probe_nomatch(device_t bus, device_t child) printf(" disabled"); if (type) printf(" type %s", type); - if (compat) - printf(" compat %s", compat); - printf(" (no driver attached)\n"); + printf(" compat %s (no driver attached)\n", compat); } static int |