Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

net: phy: marvell: Support SFP through phy_port interface

Convert the Marvell driver (especially the 88e1512 driver) to use the
phy_port interface to handle SFPs. This means registering a
.attach_port() handler to detect when a serdes line interface is used
(most likely, and SFP module).

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-10-maxime.chevallier@bootlin.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Maxime Chevallier and committed by
Jakub Kicinski
1384e138 ea317f07

+32 -60
+32 -60
drivers/net/phy/marvell.c
··· 29 29 #include <linux/ethtool.h> 30 30 #include <linux/ethtool_netlink.h> 31 31 #include <linux/phy.h> 32 + #include <linux/phy_port.h> 32 33 #include <linux/marvell_phy.h> 33 34 #include <linux/bitfield.h> 34 35 #include <linux/of.h> 35 - #include <linux/sfp.h> 36 36 37 37 #include <linux/io.h> 38 38 #include <asm/irq.h> ··· 3598 3598 return marvell_hwmon_probe(phydev); 3599 3599 } 3600 3600 3601 - static int m88e1510_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) 3601 + static int m88e1510_port_configure_serdes(struct phy_port *port, bool enable, 3602 + phy_interface_t interface) 3602 3603 { 3603 - struct phy_device *phydev = upstream; 3604 - const struct sfp_module_caps *caps; 3605 - phy_interface_t interface; 3604 + struct phy_device *phydev = port_phydev(port); 3606 3605 struct device *dev; 3607 3606 int oldpage; 3608 3607 int ret = 0; ··· 3609 3610 3610 3611 dev = &phydev->mdio.dev; 3611 3612 3612 - caps = sfp_get_module_caps(phydev->sfp_bus); 3613 - interface = sfp_select_interface(phydev->sfp_bus, caps->link_modes); 3613 + if (enable) { 3614 + switch (interface) { 3615 + case PHY_INTERFACE_MODE_1000BASEX: 3616 + mode = MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_1000X; 3614 3617 3615 - dev_info(dev, "%s SFP module inserted\n", phy_modes(interface)); 3618 + break; 3619 + case PHY_INTERFACE_MODE_100BASEX: 3620 + mode = MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_100FX; 3616 3621 3617 - switch (interface) { 3618 - case PHY_INTERFACE_MODE_1000BASEX: 3619 - mode = MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_1000X; 3622 + break; 3623 + case PHY_INTERFACE_MODE_SGMII: 3624 + mode = MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_SGMII; 3620 3625 3621 - break; 3622 - case PHY_INTERFACE_MODE_100BASEX: 3623 - mode = MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_100FX; 3626 + break; 3627 + default: 3628 + dev_err(dev, "Incompatible SFP module inserted\n"); 3624 3629 3625 - break; 3626 - case PHY_INTERFACE_MODE_SGMII: 3627 - mode = MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_SGMII; 3628 - 3629 - break; 3630 - default: 3631 - dev_err(dev, "Incompatible SFP module inserted\n"); 3632 - 3633 - return -EINVAL; 3630 + return -EINVAL; 3631 + } 3632 + } else { 3633 + mode = MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII; 3634 3634 } 3635 3635 3636 3636 oldpage = phy_select_page(phydev, MII_MARVELL_MODE_PAGE); ··· 3648 3650 return phy_restore_page(phydev, oldpage, ret); 3649 3651 } 3650 3652 3651 - static void m88e1510_sfp_remove(void *upstream) 3652 - { 3653 - struct phy_device *phydev = upstream; 3654 - int oldpage; 3655 - int ret = 0; 3656 - 3657 - oldpage = phy_select_page(phydev, MII_MARVELL_MODE_PAGE); 3658 - if (oldpage < 0) 3659 - goto error; 3660 - 3661 - ret = __phy_modify(phydev, MII_88E1510_GEN_CTRL_REG_1, 3662 - MII_88E1510_GEN_CTRL_REG_1_MODE_MASK, 3663 - MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII); 3664 - if (ret < 0) 3665 - goto error; 3666 - 3667 - ret = __phy_set_bits(phydev, MII_88E1510_GEN_CTRL_REG_1, 3668 - MII_88E1510_GEN_CTRL_REG_1_RESET); 3669 - 3670 - error: 3671 - phy_restore_page(phydev, oldpage, ret); 3672 - } 3673 - 3674 - static const struct sfp_upstream_ops m88e1510_sfp_ops = { 3675 - .module_insert = m88e1510_sfp_insert, 3676 - .module_remove = m88e1510_sfp_remove, 3677 - .attach = phy_sfp_attach, 3678 - .detach = phy_sfp_detach, 3679 - .connect_phy = phy_sfp_connect_phy, 3680 - .disconnect_phy = phy_sfp_disconnect_phy, 3653 + static const struct phy_port_ops m88e1510_serdes_port_ops = { 3654 + .configure_mii = m88e1510_port_configure_serdes, 3681 3655 }; 3682 3656 3683 - static int m88e1510_probe(struct phy_device *phydev) 3657 + static int m88e1510_attach_mii_port(struct phy_device *phy_device, 3658 + struct phy_port *port) 3684 3659 { 3685 - int err; 3660 + port->ops = &m88e1510_serdes_port_ops; 3686 3661 3687 - err = marvell_probe(phydev); 3688 - if (err) 3689 - return err; 3662 + __set_bit(PHY_INTERFACE_MODE_SGMII, port->interfaces); 3663 + __set_bit(PHY_INTERFACE_MODE_1000BASEX, port->interfaces); 3664 + __set_bit(PHY_INTERFACE_MODE_100BASEX, port->interfaces); 3690 3665 3691 - return phy_sfp_probe(phydev, &m88e1510_sfp_ops); 3666 + return 0; 3692 3667 } 3693 3668 3694 3669 static struct phy_driver marvell_drivers[] = { ··· 3921 3950 .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops), 3922 3951 .features = PHY_GBIT_FIBRE_FEATURES, 3923 3952 .flags = PHY_POLL_CABLE_TEST, 3924 - .probe = m88e1510_probe, 3953 + .probe = marvell_probe, 3925 3954 .config_init = m88e1510_config_init, 3926 3955 .config_aneg = m88e1510_config_aneg, 3927 3956 .read_status = marvell_read_status, ··· 3947 3976 .led_hw_is_supported = m88e1318_led_hw_is_supported, 3948 3977 .led_hw_control_set = m88e1318_led_hw_control_set, 3949 3978 .led_hw_control_get = m88e1318_led_hw_control_get, 3979 + .attach_mii_port = m88e1510_attach_mii_port, 3950 3980 }, 3951 3981 { 3952 3982 .phy_id = MARVELL_PHY_ID_88E1540,