[PATCH net-next 2/2] net: phy: at803x: Support downstream SFP cage
From: Robert Hancock <hidden>
Date: 2021-06-30 18:25:42
Subsystem:
ethernet phy library, networking drivers, the rest · Maintainers:
Andrew Lunn, Heiner Kallweit, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
Add support for downstream SFP cages for AR8031 and AR8033. This is primarily intended for fiber modules or direct-attach cables, however copper modules which work in 1000Base-X mode may also function. Such modules are allowed with a warning. Signed-off-by: Robert Hancock <redacted> --- drivers/net/phy/at803x.c | 53 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+)
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index 65f546eca5f4..b613e26b6b16 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c@@ -19,6 +19,8 @@ #include <linux/regulator/of_regulator.h> #include <linux/regulator/driver.h> #include <linux/regulator/consumer.h> +#include <linux/phylink.h> +#include <linux/sfp.h> #include <dt-bindings/net/qca-ar803x.h> #define AT803X_SPECIFIC_FUNCTION_CONTROL 0x10
@@ -552,6 +554,51 @@ static bool at803x_match_phy_id(struct phy_device *phydev, u32 phy_id) == (phy_id & phydev->drv->phy_id_mask); } +static int at803x_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) +{ + struct phy_device *phydev = upstream; + __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_support); + __ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_support); + phy_interface_t iface; + + linkmode_zero(phy_support); + phylink_set(phy_support, 1000baseX_Full); + phylink_set(phy_support, 1000baseT_Full); + phylink_set(phy_support, Autoneg); + phylink_set(phy_support, Pause); + phylink_set(phy_support, Asym_Pause); + + linkmode_zero(sfp_support); + sfp_parse_support(phydev->sfp_bus, id, sfp_support); + /* Some modules support 10G modes as well as others we support. + * Mask out non-supported modes so the correct interface is picked. + */ + linkmode_and(sfp_support, phy_support, sfp_support); + + iface = sfp_select_interface(phydev->sfp_bus, sfp_support); + + /* Only 1000Base-X is supported by AR8031/8033 as the downstream SerDes + * interface for use with SFP modules. + * However, some copper modules detected as having a preferred SGMII + * interface do default to and function in 1000Base-X mode, so just + * print a warning and allow such modules, as they may have some chance + * of working. + */ + if (iface == PHY_INTERFACE_MODE_SGMII) { + dev_warn(&phydev->mdio.dev, "module may not function if 1000Base-X not supported\n"); + } else if (iface != PHY_INTERFACE_MODE_1000BASEX) { + dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n"); + return -EINVAL; + } + return 0; +} + +static const struct sfp_upstream_ops at803x_sfp_ops = { + .attach = phy_sfp_attach, + .detach = phy_sfp_detach, + .module_insert = at803x_sfp_insert, +}; + static int at803x_parse_dt(struct phy_device *phydev) { struct device_node *node = phydev->mdio.dev.of_node;
@@ -716,6 +763,12 @@ static int at803x_probe(struct phy_device *phydev) phy_unlock_mdio_bus(phydev); if (ret) goto err; + + if (priv->is_1000basex) { + ret = phy_sfp_probe(phydev, &at803x_sfp_ops); + if (ret < 0) + goto err; + } } return 0;
--
2.27.0