git: f0a6f99b2a3a - stable/13 - miibus: Add support for mapping OFW nodes to PHY devices
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 29 Mar 2022 23:00:00 UTC
The branch stable/13 has been updated by mw: URL: https://cgit.FreeBSD.org/src/commit/?id=f0a6f99b2a3a449caab404dc5888ceb8ae716c98 commit f0a6f99b2a3a449caab404dc5888ceb8ae716c98 Author: Kornel Duleba <mindal@semihalf.com> AuthorDate: 2021-11-15 08:55:33 +0000 Commit: Marcin Wojtas <mw@FreeBSD.org> CommitDate: 2022-03-29 22:24:28 +0000 miibus: Add support for mapping OFW nodes to PHY devices Create a new miibus OFW specific layer leveraging miibus_fdt.c code. PHY drivers can than read the properties using device_get_property(9) API. Resource(interrupt) allocation is also supported. In order to enable this each NIC/switch driver will have to be modified, because of how miibus is attached to the parent driver. Obtained from: Semihalf Sponsored by: Alstom Group Differential revision: https://reviews.freebsd.org/D32812 (cherry picked from commit 9174eab4142c5ed199b1599c1a3eefd5f0573ab7) --- sys/dev/mii/mii.c | 10 +--- sys/dev/mii/mii_fdt.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++ sys/dev/mii/miivar.h | 23 ++++++++- 3 files changed, 155 insertions(+), 9 deletions(-) diff --git a/sys/dev/mii/mii.c b/sys/dev/mii/mii.c index 57294f4c096c..aaae2ec4e5d6 100644 --- a/sys/dev/mii/mii.c +++ b/sys/dev/mii/mii.c @@ -59,7 +59,6 @@ MODULE_VERSION(miibus, 1); #include "miibus_if.h" -static device_attach_t miibus_attach; static bus_child_detached_t miibus_child_detached; static bus_child_location_str_t miibus_child_location_str; static bus_child_pnpinfo_str_t miibus_child_pnpinfo_str; @@ -102,12 +101,7 @@ static device_method_t miibus_methods[] = { }; devclass_t miibus_devclass; - -driver_t miibus_driver = { - "miibus", - miibus_methods, - sizeof(struct mii_data) -}; +DEFINE_CLASS_0(miibus, miibus_driver, miibus_methods, sizeof(struct mii_data)); struct miibus_ivars { if_t ifp; @@ -126,7 +120,7 @@ miibus_probe(device_t dev) return (BUS_PROBE_SPECIFIC); } -static int +int miibus_attach(device_t dev) { struct miibus_ivars *ivars; 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); diff --git a/sys/dev/mii/miivar.h b/sys/dev/mii/miivar.h index 4658394797e9..0f928dce6efc 100644 --- a/sys/dev/mii/miivar.h +++ b/sys/dev/mii/miivar.h @@ -40,6 +40,14 @@ #include <sys/queue.h> #include <net/if_var.h> /* XXX driver API temporary */ +#include "opt_platform.h" + +#ifdef FDT +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> +#endif + /* * Media Independent Interface data structure defintions */ @@ -205,6 +213,11 @@ struct mii_attach_args { uint32_t mii_id1; /* PHY ID register 1 */ uint32_t mii_id2; /* PHY ID register 2 */ u_int mii_capmask; /* capability mask for BMSR */ +#ifdef FDT + struct ofw_bus_devinfo obd; + struct resource_list rl; +#endif + }; typedef struct mii_attach_args mii_attach_args_t; @@ -250,7 +263,13 @@ enum miibus_device_ivars { MIIBUS_ACCESSOR(flags, FLAGS, u_int) extern devclass_t miibus_devclass; -extern driver_t miibus_driver; +DECLARE_CLASS(miibus_driver); + +#ifdef FDT +extern devclass_t miibus_fdt_devclass; +DECLARE_CLASS(miibus_fdt_driver); +#endif + int mii_attach(device_t, device_t *, if_t, ifm_change_cb_t, ifm_stat_cb_t, int, int, int, int); @@ -279,6 +298,8 @@ int mii_phy_dev_probe(device_t dev, const struct mii_phydesc *mpd, int mrv); void mii_phy_dev_attach(device_t dev, u_int flags, const struct mii_phy_funcs *mpf, int add_media); +device_attach_t miibus_attach; + void ukphy_status(struct mii_softc *); u_int mii_oui(u_int, u_int);