2015-03-27 6:37 GMT-07:00 Stas Sergeev <stsp@xxxxxxx>: > > The following API is added: > - of_phy_fixed_link_set_link() allows to set link state (up/down) > - of_phy_fixed_link_set_speed() allows to set link speed > - of_phy_fixed_link_set_duplex() allows to enable/disable duplex > > This API is needed when the MDIO-less link have some other means > of a status passing to MAC, for example with in-band data (SGMII). > MAC driver can then use that API to update the PHY status. I do not think any of these changes are required, if you look at drivers/net/dsa/bcm_sf2.c, there is a fixed_link_update callback to re-act to link up/down interrupts (but this could easily be extended to speed/duplex as well), by directly modifying a fixed_phy_status structure. Can you try that approach in mvneta? > > CC: Florian Fainelli <f.fainelli@xxxxxxxxx> > CC: Grant Likely <grant.likely@xxxxxxxxxx> > CC: Rob Herring <robh+dt@xxxxxxxxxx> > CC: netdev@xxxxxxxxxxxxxxx > CC: devicetree@xxxxxxxxxxxxxxx > CC: linux-kernel@xxxxxxxxxxxxxxx > > Signed-off-by: Stas Sergeev <stsp@xxxxxxxxxxxxxxxxxxxxx> > --- > drivers/of/of_mdio.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++ > include/linux/of_mdio.h | 17 +++++++++++ > 2 files changed, 89 insertions(+) > > diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c > index b3dc1e6..ade2426 100644 > --- a/drivers/of/of_mdio.c > +++ b/drivers/of/of_mdio.c > @@ -251,6 +251,69 @@ struct phy_device *of_phy_attach(struct net_device *dev, > EXPORT_SYMBOL(of_phy_attach); > > #if defined(CONFIG_FIXED_PHY) > +struct fixed_link_data { > + struct fixed_phy_status status; > + struct fixed_phy_status changed; > +}; > + > +static int of_phy_fixed_link_update(struct phy_device *phy, > + struct fixed_phy_status *status) > +{ > + struct fixed_link_data *priv = phy->priv; > + > + if (priv->changed.link) { > + status->link = priv->status.link; > + priv->changed.link = 0; > + } > + if (priv->changed.speed) { > + status->speed = priv->status.speed; > + priv->changed.speed = 0; > + } > + if (priv->changed.duplex) { > + status->duplex = priv->status.duplex; > + priv->changed.duplex = 0; > + } > + if (priv->changed.pause) { > + status->pause = priv->status.pause; > + priv->changed.pause = 0; > + } > + if (priv->changed.asym_pause) { > + status->asym_pause = priv->status.asym_pause; > + priv->changed.asym_pause = 0; > + } > + return 0; > +} > + > +int of_phy_fixed_link_set_link(struct phy_device *phy, int link) > +{ > + struct fixed_link_data *priv = phy->priv; > + > + priv->status.link = link; > + priv->changed.link = 1; > + return 0; > +} > +EXPORT_SYMBOL(of_phy_fixed_link_set_link); > + > +int of_phy_fixed_link_set_speed(struct phy_device *phy, int speed) > +{ > + struct fixed_link_data *priv = phy->priv; > + > + priv->status.speed = speed; > + priv->changed.speed = 1; > + return 0; > +} > +EXPORT_SYMBOL(of_phy_fixed_link_set_speed); > + > +int of_phy_fixed_link_set_duplex(struct phy_device *phy, int duplex) > +{ > + struct fixed_link_data *priv = phy->priv; > + > + priv->status.duplex = duplex; > + priv->changed.duplex = 1; > + return 0; > +} > +EXPORT_SYMBOL(of_phy_fixed_link_set_duplex); > + > /* > * of_phy_is_fixed_link() and of_phy_register_fixed_link() must > * support two DT bindings: > @@ -287,6 +350,7 @@ int of_phy_register_fixed_link(struct device_node *np) > const __be32 *fixed_link_prop; > int len; > struct phy_device *phy; > + struct fixed_link_data *priv; > > /* New binding */ > fixed_link_node = of_get_child_by_name(np, "fixed-link"); > @@ -320,6 +384,14 @@ int of_phy_register_fixed_link(struct device_node *np) > } > } > > + priv = kmalloc(sizeof(*priv), GFP_KERNEL); > + if (!priv) { > + fixed_phy_unregister(phy); > + return -ENOMEM; > + } > + memset(&priv->changed, 0, sizeof(priv->changed)); > + phy->priv = priv; > + fixed_phy_set_link_update(phy, of_phy_fixed_link_update); > return 0; > } > EXPORT_SYMBOL(of_phy_register_fixed_link); > diff --git a/include/linux/of_mdio.h b/include/linux/of_mdio.h > index d449018..677adac 100644 > --- a/include/linux/of_mdio.h > +++ b/include/linux/of_mdio.h > @@ -65,6 +65,9 @@ static inline struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np) > #if defined(CONFIG_OF) && defined(CONFIG_FIXED_PHY) > extern int of_phy_register_fixed_link(struct device_node *np); > extern bool of_phy_is_fixed_link(struct device_node *np); > +extern int of_phy_fixed_link_set_link(struct phy_device *phy, int link); > +extern int of_phy_fixed_link_set_speed(struct phy_device *phy, int speed); > +extern int of_phy_fixed_link_set_duplex(struct phy_device *phy, int duplex); > #else > static inline int of_phy_register_fixed_link(struct device_node *np) > { > @@ -74,6 +77,20 @@ static inline bool of_phy_is_fixed_link(struct device_node *np) > { > return false; > } > +static inline int of_phy_fixed_link_set_link(struct phy_device *phy, int link) > +{ > + return -ENOSYS; > +} > +static inline int of_phy_fixed_link_set_speed(struct phy_device *phy, > + int speed) > +{ > + return -ENOSYS; > +} > +static inline int of_phy_fixed_link_set_duplex(struct phy_device *phy, > + int duplex) > +{ > + return -ENOSYS; > +} > #endif > > > -- > 1.7.9.5 -- Florian -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html