Commit ea317f07 authored by Maxime Chevallier's avatar Maxime Chevallier Committed by Jakub Kicinski
Browse files

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: default avatarChristophe Leroy <christophe.leroy@csgroup.eu>
Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Tested-by: default avatarChristophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: default avatarMaxime Chevallier <maxime.chevallier@bootlin.com>
Link: https://patch.msgid.link/20260108080041.553250-9-maxime.chevallier@bootlin.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent d7c6082f
Loading
Loading
Loading
Loading
+38 −56
Original line number Diff line number Diff line
@@ -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,35 +473,18 @@ 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;

	caps = sfp_get_module_caps(phydev->sfp_bus);

	phydev->port = caps->port;
	sfp_interface = sfp_select_interface(phydev->sfp_bus, caps->link_modes);

	dev_info(dev, "%s SFP module inserted\n", phy_modes(sfp_interface));
	priv->line_interface = interface;

	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);
	if (enable) {
		linkmode_and(priv->supported, phydev->supported, port->supported);

		ret = mv2222_config_line(phydev);
		if (ret < 0)
@@ -512,50 +495,48 @@ static int mv2222_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
			mutex_unlock(&phydev->lock);
		}

	return ret;
	} else {
		linkmode_zero(priv->supported);
	}

static void mv2222_sfp_remove(void *upstream)
{
	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;
	return ret;
}

static void mv2222_sfp_link_up(void *upstream)
static void mv2222_port_link_up(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 = 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);