diff options
Diffstat (limited to 'sys/dev/mii/mii_fdt.c')
-rw-r--r-- | sys/dev/mii/mii_fdt.c | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/sys/dev/mii/mii_fdt.c b/sys/dev/mii/mii_fdt.c index 18ed9c8e749c..387b02f69504 100644 --- a/sys/dev/mii/mii_fdt.c +++ b/sys/dev/mii/mii_fdt.c @@ -239,3 +239,134 @@ mii_fdt_get_config(device_t phydev) return (cfg); } + +static int +miibus_fdt_probe(device_t dev) +{ + device_t parent; + + parent = device_get_parent(dev); + if (ofw_bus_get_node(parent) == -1) + return (ENXIO); + + device_set_desc(dev, "OFW MII bus"); + return (BUS_PROBE_DEFAULT); +} + +static int +miibus_fdt_attach(device_t dev) +{ + struct mii_attach_args *ma; + struct mii_data *sc; + int i, error, nchildren; + device_t parent, *children; + phandle_t phy_node; + + parent = device_get_parent(dev); + sc = device_get_softc(dev); + + error = device_get_children(dev, &children, &nchildren); + if (error != 0 || nchildren == 0) + return (ENXIO); + + for (i = 0; i < nchildren; i++) { + ma = device_get_ivars(children[i]); + bzero(&ma->obd, sizeof(ma->obd)); + phy_node = mii_fdt_lookup_phy(ofw_bus_get_node(parent), + ma->mii_phyno); + if (phy_node == -1) { + device_printf(dev, + "Warning: failed to find OFW node for PHY%d\n", + ma->mii_phyno); + continue; + } + error = ofw_bus_gen_setup_devinfo(&ma->obd, phy_node); + if (error != 0) { + device_printf(dev, + "Warning: failed to setup OFW devinfo for PHY%d\n", + ma->mii_phyno); + continue; + } + /* + * Setup interrupt resources. + * Only a handful of PHYs support those, + * so it's fine if we fail here. + */ + resource_list_init(&ma->rl); + (void)ofw_bus_intr_to_rl(children[i], phy_node, &ma->rl, NULL); + } + + free(children, M_TEMP); + return (miibus_attach(dev)); +} + +static struct resource_list * +miibus_fdt_get_resource_list(device_t bus, device_t child) +{ + struct mii_attach_args *ma; + + ma = device_get_ivars(child); + + if (ma->obd.obd_node == 0) + return (NULL); + + return (&ma->rl); +} + +static const struct ofw_bus_devinfo* +miibus_fdt_get_devinfo(device_t bus, device_t child) +{ + struct mii_attach_args *ma; + + ma = device_get_ivars(child); + + if (ma->obd.obd_node == 0) + return (NULL); + + return (&ma->obd); +} + +static ssize_t +miibus_fdt_get_property(device_t bus, device_t child, const char *propname, + void *buf, size_t size) +{ + struct mii_attach_args *ma; + + ma = device_get_ivars(child); + + if (ma->obd.obd_node == 0) + return (-1); + + return (OF_getencprop(ma->obd.obd_node, propname, buf, size)); +} + +static device_method_t miibus_fdt_methods[] = { + DEVMETHOD(device_probe, miibus_fdt_probe), + DEVMETHOD(device_attach, miibus_fdt_attach), + + /* ofw_bus interface */ + DEVMETHOD(ofw_bus_get_devinfo, miibus_fdt_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(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), + 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_alloc_resource, bus_generic_rl_alloc_resource), + DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), + DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource), + DEVMETHOD(bus_get_resource_list, miibus_fdt_get_resource_list), + DEVMETHOD(bus_get_property, miibus_fdt_get_property), + + DEVMETHOD_END +}; + +devclass_t miibus_fdt_devclass; +DEFINE_CLASS_1(miibus, miibus_fdt_driver, miibus_fdt_methods, + sizeof(struct mii_data), miibus_driver); |