Index: sys/arm/broadcom/bcm2835/bcm2835_firmware.c =================================================================== --- sys/arm/broadcom/bcm2835/bcm2835_firmware.c +++ sys/arm/broadcom/bcm2835/bcm2835_firmware.c @@ -71,6 +71,31 @@ return (BUS_PROBE_DEFAULT); } +static device_t +bcm2835_firmware_add_device(device_t dev, phandle_t node, u_int order, + const char *name, int unit) +{ + struct ofw_bus_devinfo *di; + device_t cdev; + + di = malloc(sizeof(*di), M_DEVBUF, M_WAITOK | M_ZERO); + if (ofw_bus_gen_setup_devinfo(di, node) != 0) { + free(di, M_DEVBUF); + return (NULL); + } + cdev = device_add_child_ordered(dev, order, name, unit); + if (cdev == NULL) { + device_printf(dev, "<%s>: device_add_child failed\n", + di->obd_name); + ofw_bus_gen_destroy_devinfo(di); + free(di, M_DEVBUF); + return (NULL); + } + device_set_ivars(cdev, di); + + return(cdev); +} + static int bcm2835_firmware_attach(device_t dev) { @@ -101,9 +126,76 @@ CTLTYPE_UINT | CTLFLAG_RD, sc, sizeof(*sc), sysctl_bcm2835_firmware_get_revision, "IU", "Firmware revision"); - return (0); + + for (node = OF_child(node); node > 0; node = OF_peer(node)) + bcm2835_firmware_add_device(dev, node, 0, NULL, -1); + return (bus_generic_attach(dev)); } +static device_t +bcm2835_firmware_add_child(device_t dev, u_int order, const char *name, + int unit) +{ + device_t cdev; + struct ofw_bus_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->obd_node = -1; + device_set_ivars(cdev, ndi); + + return (cdev); +} + +static void +bcm2835_firmware_probe_nomatch(device_t bus, device_t child) +{ + const char *name, *type, *compat; + + 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); + + device_printf(bus, "<%s>", name != NULL ? name : "unknown"); + if (!ofw_bus_status_okay(child)) + printf(" disabled"); + if (type) + printf(" type %s", type); + printf(" compat %s (no driver attached)\n", compat); +} + +static int +bcm2835_firmware_print_child(device_t bus, device_t child) +{ + int rv; + + rv = bus_print_child_header(bus, child); + if (!ofw_bus_status_okay(child)) + rv += printf(" disabled"); + rv += bus_print_child_footer(bus, child); + return (rv); +} + +static const struct ofw_bus_devinfo * +bcm2835_firmware_get_devinfo(device_t bus __unused, device_t child) +{ + struct ofw_bus_devinfo *ndi; + + ndi = device_get_ivars(child); + if (ndi == NULL) + return (NULL); + return (ndi); +} + + int bcm2835_firmware_property(device_t dev, uint32_t prop, void *data, size_t len) { @@ -167,6 +259,22 @@ DEVMETHOD(device_probe, bcm2835_firmware_probe), DEVMETHOD(device_attach, bcm2835_firmware_attach), + /* Bus interface */ + DEVMETHOD(bus_add_child, bcm2835_firmware_add_child), + DEVMETHOD(bus_print_child, bcm2835_firmware_print_child), + DEVMETHOD(bus_probe_nomatch, bcm2835_firmware_probe_nomatch), + DEVMETHOD(bus_read_ivar, bus_generic_read_ivar), + DEVMETHOD(bus_write_ivar, bus_generic_write_ivar), + DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str), + + /* ofw_bus interface */ + DEVMETHOD(ofw_bus_get_devinfo, bcm2835_firmware_get_devinfo), + DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), + DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), + DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), + DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), + DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), + DEVMETHOD_END };