aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/fdt/simplebus.c
diff options
context:
space:
mode:
authorIan Lepore <ian@FreeBSD.org>2015-03-27 23:10:15 +0000
committerIan Lepore <ian@FreeBSD.org>2015-03-27 23:10:15 +0000
commitecaecbc7d8bc212d8e854088106b3b21e631bb52 (patch)
treeb6b813988bcb1821b70172b1f43167e3d7533bfd /sys/dev/fdt/simplebus.c
parent8465cb40164fdd4113b78bbec6f67e4832e07f44 (diff)
downloadsrc-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.c143
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