diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 94d31bb25b47e..8d0fd920289bc 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -154,6 +154,11 @@ enum { struct mv3310_mactype { bool valid; bool fixed_interface; + /* PHY copper autoneg supports multiple speeds (1G/2.5G/5G/10G) even + * though the host-side interface is fixed (rate matching). This allows + * phylink to validate and advertise all copper speeds. + */ + bool copper_multispeed; phy_interface_t interface_10g; }; @@ -405,6 +410,16 @@ static int mv3310_power_up(struct phy_device *phydev) priv->firmware_ver < 0x00030000) return ret; + /* Poll until SWRST reads 0 (PHY ready for a new reset) before issuing + * SWRST. Without this, the second and subsequent link-up sequences + * result in broken TX/RX. The datasheet specifies bit 15 = 1 means + * reset in progress, 0 means normal operation. + */ + if (phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL, + ret, !(ret & MV_V2_33X0_PORT_CTRL_SWRST), + 5000, 200000, true)) + phydev_warn(phydev, "SWRST timed out 200ms\n"); + ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL, MV_V2_33X0_PORT_CTRL_SWRST); msleep(100); @@ -947,6 +962,7 @@ static const struct mv3310_mactype mv3310_mactypes[] = { [MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH] = { .valid = true, .fixed_interface = true, + .copper_multispeed = true, .interface_10g = PHY_INTERFACE_MODE_10GBASER, }, [MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII] = { @@ -981,6 +997,7 @@ static const struct mv3310_mactype mv3340_mactypes[] = { [MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH] = { .valid = true, .fixed_interface = true, + .copper_multispeed = true, .interface_10g = PHY_INTERFACE_MODE_10GBASER, }, [MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII] = { @@ -999,7 +1016,7 @@ static void mv3310_fill_possible_interfaces(struct phy_device *phydev) if (mactype->interface_10g != PHY_INTERFACE_MODE_NA) __set_bit(priv->mactype->interface_10g, possible); - if (!mactype->fixed_interface) { + if (!mactype->fixed_interface || mactype->copper_multispeed) { __set_bit(PHY_INTERFACE_MODE_5GBASER, possible); __set_bit(PHY_INTERFACE_MODE_2500BASEX, possible); __set_bit(PHY_INTERFACE_MODE_SGMII, possible); @@ -1037,10 +1054,15 @@ static int mv3310_config_init(struct phy_device *phydev) mv3310_config_init_clear_power_down(phydev); - /* Force XFI/SGMII/Auto-neg mode regardless of strap configuration */ + /* Force XFI/SGMII/Auto-neg mode regardless of strap configuration. + /* Default to rate-match mode so the host serdes stays fixed at 10GBASE-R + * regardless of copper wire speed. This is correct for MACs (e.g. mvpp2) that + * configure their comphy for 10GBASE-R and cannot handle the PHY switching + * the host interface to SGMII on 1G link-up. + */ err = phy_modify_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL, MV_V2_33X0_PORT_CTRL_MACTYPE_MASK, - MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER); + MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH); if (err) return err;