net: phy: marvell-88x2222: Support SFP through phy_port interface

The 88x2222 PHY from Marvell only supports serialised modes as its
line-facing interfaces. Convert that driver to the generic phylib SFP
handling.

Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Tested-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Link: https://patch.msgid.link/20260108080041.553250-9-maxime.chevallier@bootlin.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Maxime Chevallier
2026-01-08 09:00:33 +01:00
committed by Jakub Kicinski
parent d7c6082f7e
commit ea317f077a

View File

@@ -13,7 +13,7 @@
#include <linux/mdio.h>
#include <linux/marvell_phy.h>
#include <linux/of.h>
#include <linux/sfp.h>
#include <linux/phy_port.h>
#include <linux/netdevice.h>
/* Port PCS Configuration */
@@ -473,89 +473,70 @@ static int mv2222_config_init(struct phy_device *phydev)
return 0;
}
static int mv2222_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
static int mv2222_configure_serdes(struct phy_port *port, bool enable,
phy_interface_t interface)
{
struct phy_device *phydev = upstream;
const struct sfp_module_caps *caps;
phy_interface_t sfp_interface;
struct phy_device *phydev = port_phydev(port);
struct mv2222_data *priv;
struct device *dev;
int ret;
int ret = 0;
priv = phydev->priv;
dev = &phydev->mdio.dev;
priv->line_interface = interface;
caps = sfp_get_module_caps(phydev->sfp_bus);
if (enable) {
linkmode_and(priv->supported, phydev->supported, port->supported);
phydev->port = caps->port;
sfp_interface = sfp_select_interface(phydev->sfp_bus, caps->link_modes);
ret = mv2222_config_line(phydev);
if (ret < 0)
return ret;
dev_info(dev, "%s SFP module inserted\n", phy_modes(sfp_interface));
if (mutex_trylock(&phydev->lock)) {
ret = mv2222_config_aneg(phydev);
mutex_unlock(&phydev->lock);
}
if (sfp_interface != PHY_INTERFACE_MODE_10GBASER &&
sfp_interface != PHY_INTERFACE_MODE_1000BASEX &&
sfp_interface != PHY_INTERFACE_MODE_SGMII) {
dev_err(dev, "Incompatible SFP module inserted\n");
return -EINVAL;
}
priv->line_interface = sfp_interface;
linkmode_and(priv->supported, phydev->supported, caps->link_modes);
ret = mv2222_config_line(phydev);
if (ret < 0)
return ret;
if (mutex_trylock(&phydev->lock)) {
ret = mv2222_config_aneg(phydev);
mutex_unlock(&phydev->lock);
} else {
linkmode_zero(priv->supported);
}
return ret;
}
static void mv2222_sfp_remove(void *upstream)
static void mv2222_port_link_up(struct phy_port *port)
{
struct phy_device *phydev = upstream;
struct mv2222_data *priv;
priv = phydev->priv;
priv->line_interface = PHY_INTERFACE_MODE_NA;
linkmode_zero(priv->supported);
phydev->port = PORT_NONE;
}
static void mv2222_sfp_link_up(void *upstream)
{
struct phy_device *phydev = upstream;
struct phy_device *phydev = port_phydev(port);
struct mv2222_data *priv;
priv = phydev->priv;
priv->sfp_link = true;
}
static void mv2222_sfp_link_down(void *upstream)
static void mv2222_port_link_down(struct phy_port *port)
{
struct phy_device *phydev = upstream;
struct phy_device *phydev = port_phydev(port);
struct mv2222_data *priv;
priv = phydev->priv;
priv->sfp_link = false;
}
static const struct sfp_upstream_ops sfp_phy_ops = {
.module_insert = mv2222_sfp_insert,
.module_remove = mv2222_sfp_remove,
.link_up = mv2222_sfp_link_up,
.link_down = mv2222_sfp_link_down,
.attach = phy_sfp_attach,
.detach = phy_sfp_detach,
.connect_phy = phy_sfp_connect_phy,
.disconnect_phy = phy_sfp_disconnect_phy,
static const struct phy_port_ops mv2222_port_ops = {
.link_up = mv2222_port_link_up,
.link_down = mv2222_port_link_down,
.configure_mii = mv2222_configure_serdes,
};
static int mv2222_attach_mii_port(struct phy_device *phydev, struct phy_port *port)
{
port->ops = &mv2222_port_ops;
__set_bit(PHY_INTERFACE_MODE_10GBASER, port->interfaces);
__set_bit(PHY_INTERFACE_MODE_1000BASEX, port->interfaces);
__set_bit(PHY_INTERFACE_MODE_SGMII, port->interfaces);
return 0;
}
static int mv2222_probe(struct phy_device *phydev)
{
struct device *dev = &phydev->mdio.dev;
@@ -591,7 +572,7 @@ static int mv2222_probe(struct phy_device *phydev)
priv->line_interface = PHY_INTERFACE_MODE_NA;
phydev->priv = priv;
return phy_sfp_probe(phydev, &sfp_phy_ops);
return 0;
}
static struct phy_driver mv2222_drivers[] = {
@@ -608,6 +589,7 @@ static struct phy_driver mv2222_drivers[] = {
.suspend = mv2222_suspend,
.resume = mv2222_resume,
.read_status = mv2222_read_status,
.attach_mii_port = mv2222_attach_mii_port,
},
};
module_phy_driver(mv2222_drivers);