RollBall SFPs contain Marvell 88X3310 PHY, but they have configuration
pins strapped so that MACTYPE is configured in XFI with Rate Matching
mode.

When these SFPs are inserted into a device which only supports lower
speeds on host interface, we need to configure the MACTYPE to a mode
in which the H unit changes SerDes speed according to speed on the
copper interface. I chose to use the
10GBASE-R/5GBASE-R/2500BASE-X/SGMII with AN mode.

Signed-off-by: Marek Behún <marek.be...@nic.cz>
---
 drivers/net/phy/marvell10g.c | 32 ++++++++++++++++++++++++++++----
 1 file changed, 28 insertions(+), 4 deletions(-)

diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
index 29575442b25b2..13a588fa69e77 100644
--- a/drivers/net/phy/marvell10g.c
+++ b/drivers/net/phy/marvell10g.c
@@ -81,6 +81,7 @@ enum {
        MV_V2_PORT_CTRL_SWRST   = BIT(15),
        MV_V2_PORT_CTRL_PWRDOWN = BIT(11),
        MV_V2_PORT_MAC_TYPE_MASK = 0x7,
+       MV_V2_PORT_MAC_TYPE_10GBR_SGMII_AN = 0x4,
        MV_V2_PORT_MAC_TYPE_RATE_MATCH = 0x6,
        /* Temperature control/read registers (88X3310 only) */
        MV_V2_TEMP_CTRL         = 0xf08a,
@@ -258,17 +259,40 @@ static int mv3310_power_down(struct phy_device *phydev)
 static int mv3310_power_up(struct phy_device *phydev)
 {
        struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
+       u16 val, mask;
        int ret;
 
        ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
                                 MV_V2_PORT_CTRL_PWRDOWN);
 
-       if (phydev->drv->phy_id != MARVELL_PHY_ID_88X3310 ||
-           priv->firmware_ver < 0x00030000)
+       if (ret < 0)
                return ret;
 
-       return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
-                               MV_V2_PORT_CTRL_SWRST);
+       /* TODO: add support for changing MACTYPE on 88E2110 via register 
1.C0A4.2:0 */
+       if (phydev->drv->phy_id != MARVELL_PHY_ID_88X3310)
+               return 0;
+
+       val = mask = MV_V2_PORT_CTRL_SWRST;
+
+       switch (phydev->interface) {
+       case PHY_INTERFACE_MODE_SGMII:
+       case PHY_INTERFACE_MODE_2500BASEX:
+               val |= MV_V2_PORT_MAC_TYPE_10GBR_SGMII_AN;
+               mask |= MV_V2_PORT_MAC_TYPE_MASK;
+               break;
+
+       default:
+               /* Otherwise we assume that the MACTYPE is set correctly by 
strapping pins.
+                * Feel free to add support for changing MACTYPE for other modes
+                * (XAUI/RXAUI/USXGMII).
+                */
+
+               /* reset is not needed for firmware version < 0.3.0.0 when not 
changing MACTYPE */
+               if (priv->firmware_ver < 0x00030000)
+                       return 0;
+       }
+
+       return phy_modify_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL, mask, 
val);
 }
 
 static int mv3310_reset(struct phy_device *phydev, u32 unit)
-- 
2.26.2

Reply via email to