It's possible to have the DW XPCS device accessible over an external bus (external MDIO or DW XPCS management interface). Thus it will be futile to try to detect the device on the local SMA interface. Besides such platform setup isn't supported by the STMMAC driver anyway since the stmmac_mdio_bus_data instance might not be created and even if it is there is no code path which would set the stmmac_mdio_bus_data.has_xpcs flag thus activating the XPCS device setup. So in order to solve the denoted problem a pretty much standard approach is implemented: DT "pcs-handle" property is used to get the phandle referencing the DT-node describing the DW XPCS device; device node will be parsed by the xpcs_create_bynode() method implemented in the DW XPCS driver in a way as it's done for PHY-node; the node is used to find the MDIO-device instance, which in its turn will be used to create the XPCS descriptor. Note as a nice side effect of the provided change the conditional stmmac_xpcs_setup() method execution can be converted to the conditional statements implemented in the function itself. Thus the stmmac_open() will turn to look a bit simpler meanwhile stmmac_xpcs_setup() will provide the optional XPCS device semantic. Signed-off-by: Serge Semin <fancer.lancer@xxxxxxxxx> --- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 8 ++--- .../net/ethernet/stmicro/stmmac/stmmac_mdio.c | 34 ++++++++++++------- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 379552240ac9..a33ba00d091d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -7604,11 +7604,9 @@ int stmmac_dvr_probe(struct device *device, if (priv->plat->speed_mode_2500) priv->plat->speed_mode_2500(ndev, priv->plat->bsp_priv); - if (priv->plat->mdio_bus_data && priv->plat->mdio_bus_data->has_xpcs) { - ret = stmmac_xpcs_setup(ndev); - if (ret) - goto error_xpcs_setup; - } + ret = stmmac_xpcs_setup(ndev); + if (ret) + goto error_xpcs_setup; ret = stmmac_phy_setup(priv); if (ret) { diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index 101fa50c3c96..b906be363b61 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -499,25 +499,33 @@ int stmmac_xpcs_setup(struct net_device *ndev) { struct stmmac_priv *priv; struct dw_xpcs *xpcs; - int mode, addr; + int ret, mode, addr; priv = netdev_priv(ndev); mode = priv->plat->phy_interface; - /* Try to probe the XPCS by scanning all addresses. */ - for (addr = 0; addr < PHY_MAX_ADDR; addr++) { - xpcs = xpcs_create_byaddr(priv->mii, addr, mode); - if (IS_ERR(xpcs)) - continue; - - priv->hw->xpcs = xpcs; - break; + /* If PCS-node is specified use it to create the XPCS descriptor */ + if (fwnode_property_present(priv->plat->port_node, "pcs-handle")) { + xpcs = xpcs_create_bynode(priv->plat->port_node, mode); + ret = PTR_ERR_OR_ZERO(xpcs); + } else if (priv->plat->mdio_bus_data && priv->plat->mdio_bus_data->has_xpcs) { + /* Try to probe the XPCS by scanning all addresses */ + for (ret = -ENODEV, addr = 0; addr < PHY_MAX_ADDR; addr++) { + xpcs = xpcs_create_byaddr(priv->mii, addr, mode); + if (IS_ERR(xpcs)) + continue; + + ret = 0; + break; + } + } else { + return 0; } - if (!priv->hw->xpcs) { - dev_warn(priv->device, "No xPCS found\n"); - return -ENODEV; - } + if (ret) + return dev_err_probe(priv->device, ret, "No xPCS found\n"); + + priv->hw->xpcs = xpcs; return 0; } -- 2.42.1