[PATCH net-next 16/16] net: stmmac: Add externally detected DW XPCS support

Serge Semin
2023-12-05T10:37:44Z

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@gmail.com>
---
.../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