Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 4 additions & 24 deletions drivers/net/phy/marvell10g.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,11 +154,6 @@ 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;
};

Expand Down Expand Up @@ -198,7 +193,6 @@ struct mv3310_ptp_priv *mv3310_ptp_probe(struct phy_device *phydev);
int mv3310_ptp_power_up(struct mv3310_ptp_priv *priv);
int mv3310_ptp_power_down(struct mv3310_ptp_priv *priv);
int mv3310_ptp_start(struct mv3310_ptp_priv *priv);
int mv3310_ptp_update(struct mv3310_ptp_priv *priv);
int mv3310_ptp_get_sset_count(struct mv3310_ptp_priv *priv);
void mv3310_ptp_get_strings(u8 *data);
void mv3310_ptp_get_stats(struct mv3310_ptp_priv *priv,
Expand All @@ -221,10 +215,6 @@ static inline int mv3310_ptp_start(struct mv3310_ptp_priv *priv)
{
return 0;
}
static inline int mv3310_ptp_update(struct mv3310_ptp_priv *priv)
{
return 0;
}
static inline int mv3310_ptp_get_sset_count(struct mv3310_ptp_priv *priv)
{
return 0;
Expand Down Expand Up @@ -962,7 +952,6 @@ 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] = {
Expand Down Expand Up @@ -997,7 +986,6 @@ 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] = {
Expand All @@ -1016,7 +1004,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 || mactype->copper_multispeed) {
if (!mactype->fixed_interface) {
__set_bit(PHY_INTERFACE_MODE_5GBASER, possible);
__set_bit(PHY_INTERFACE_MODE_2500BASEX, possible);
__set_bit(PHY_INTERFACE_MODE_SGMII, possible);
Expand Down Expand Up @@ -1054,15 +1042,10 @@ 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.
/* 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.
*/
/* Force XFI/SGMII/Auto-neg mode regardless of strap configuration */
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_RATE_MATCH);
MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER);
if (err)
return err;

Expand Down Expand Up @@ -1362,11 +1345,8 @@ static int mv3310_read_status(struct phy_device *phydev)
if (err < 0)
return err;

if (phydev->link) {
struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
if (phydev->link)
mv3310_update_interface(phydev);
mv3310_ptp_update(priv->ptp_priv);
}

return 0;
}
Expand Down
92 changes: 31 additions & 61 deletions drivers/net/phy/marvell10g_ptp.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,17 @@ enum {
MV_V2_LINK_RESET_CFG_DEF_VAL = 0x3900,
MV_V2_LINK_RESET_CFG_LINK_DOWN = BIT(0),

/*
* Maximum receive unit (MRU) control registers. 1G/2.5G mode and XG
* mode have separate register groups; both are programmed for jumbo
* frames at power-up so no runtime reconfiguration is needed.
*/
MV_V2_SMC_1G_MRU_CTRL_REG = 0x8c00,
MV_V2_WMC_1G_MRU_CTRL_REG = 0x8e00,
MV_V2_SMC_XG_MRU_CTRL_REG = 0x8c02,
MV_V2_WMC_XG_MRU_CTRL_REG = 0x8e02,
MV_V2_MRU_MAX = 0x1fff, /* 16382 bytes, XG group: bits [12:0] */
MV_V2_MRU_1G_MAX = (0x1fff << 2), /* 16382 bytes, 1G/2.5G group: bits [15:2] */

MV_V2_MODE_CFG = 0xf000,
MV_V2_MODE_CFG_M_UNIT_PWRUP = BIT(12),
Expand Down Expand Up @@ -103,7 +110,6 @@ struct mv3310_ptp_priv {
struct ptp_clock *clock;
struct mutex lock; /* Protects against concurrent MDIO register access */
struct mii_timestamper mii_ts;
int old_speed; /* Last speed used to set MRU */
bool extts_enabled;
};

Expand Down Expand Up @@ -141,16 +147,12 @@ struct mv3310_ptp_priv *mv3310_ptp_probe(struct phy_device *phydev);
int mv3310_ptp_power_up(struct mv3310_ptp_priv *priv);
int mv3310_ptp_power_down(struct mv3310_ptp_priv *priv);
int mv3310_ptp_start(struct mv3310_ptp_priv *priv);
int mv3310_ptp_update(struct mv3310_ptp_priv *priv);
/* Get statistics from the PHY using ethtool */
int mv3310_ptp_get_sset_count(struct mv3310_ptp_priv *priv);
void mv3310_ptp_get_strings(u8 *data);
void mv3310_ptp_get_stats(struct mv3310_ptp_priv *priv,
struct ethtool_stats *stats, u64 *data);

/* General configuration functions */
static int mv3310_set_mac_mru(struct mv3310_ptp_priv *priv, int speed);

/* Helper functions */
static int mv3310_read_ptp_reg(struct phy_device *phydev, u32 regnum,
u32 *regval);
Expand Down Expand Up @@ -237,7 +239,6 @@ struct mv3310_ptp_priv *mv3310_ptp_probe(struct phy_device *phydev)

priv->phydev = phydev;
mutex_init(&priv->lock);
priv->old_speed = SPEED_UNKNOWN;
priv->extts_enabled = false;

/* Setup timestamping */
Expand Down Expand Up @@ -285,7 +286,7 @@ int mv3310_ptp_power_up(struct mv3310_ptp_priv *priv)

if (!priv)
return 0;

phydev = priv->phydev;

mutex_lock(&priv->lock);
Expand All @@ -307,15 +308,12 @@ int mv3310_ptp_power_up(struct mv3310_ptp_priv *priv)
MV_V2_SLC_CFG_GEN_SMC_ADD_CRC |
MV_V2_SLC_CFG_GEN_WMC_STRIP_CRC |
MV_V2_SLC_CFG_GEN_SMC_STRIP_CRC);

/* Increase the MRU for the default mode (XG) */
ret |= mv3310_set_mac_mru(priv, SPEED_10000);

/* Disable store-and-forward mode for egress drop FIFO. Without this
setting there are time error spikes of up to 1200ns when performing
1588TC accuracy measurements. */
ret |= mv3310_clear_ptp_reg_bits(phydev, MV_V2_SLC_CFG_GEN,
MV_V2_SLC_CFG_GEN_EGR_SF_EN);

unlock_out:
mutex_unlock(&priv->lock);
return ret;
Expand Down Expand Up @@ -364,58 +362,30 @@ int mv3310_ptp_start(struct mv3310_ptp_priv *priv)
if (ret < 0)
dev_err(&phydev->mdio.dev, "failed to enable PTP core: %d\n",
ret);
mutex_unlock(&priv->lock);

return ret;
}

int mv3310_ptp_update(struct mv3310_ptp_priv *priv)
{
int ret;

if (!priv)
return 0;

mutex_lock(&priv->lock);
ret = mv3310_set_mac_mru(priv, priv->phydev->speed);
mutex_unlock(&priv->lock);
return ret;
}

static int mv3310_set_mac_mru(struct mv3310_ptp_priv *priv, int speed)
{
const u32 MAX_MRU = 0x1fff; /* 16382 bytes */
int ret = 0;
struct phy_device *phydev = priv->phydev;

if ((priv->old_speed != SPEED_UNKNOWN) &&
((speed < SPEED_5000 && priv->old_speed < SPEED_5000) ||
(speed >= SPEED_5000 && priv->old_speed >= SPEED_5000))) {
/* No need to change the MRU if the new speed is in the same speed class */
priv->old_speed = speed;
return 0;
}

if (speed < SPEED_5000) {
/* Configuration registers for 1/2.5G mode */
ret |= mv3310_set_ptp_reg_bits(
phydev, MV_V2_SMC_1G_MRU_CTRL_REG, MAX_MRU << 2U);
ret |= mv3310_set_ptp_reg_bits(
phydev, MV_V2_WMC_1G_MRU_CTRL_REG, MAX_MRU << 2U);
} else {
/* Configuration registers for XG mode */
ret |= mv3310_write_ptp_reg(phydev, MV_V2_SMC_XG_MRU_CTRL_REG,
MAX_MRU);
ret |= mv3310_write_ptp_reg(phydev, MV_V2_WMC_XG_MRU_CTRL_REG,
MAX_MRU);
}

/*
* Configure maximum MRU for both speed-class register groups so that
* jumbo frames are supported at any copper speed. Done here (after
* SWRST has completed in mv3310_power_up) rather than in ptp_power_up
* because writing PTP registers before SWRST corrupts PHY host SerDes
* state on the subsequent link-up cycle.
*
* XG group (0x8c02/0x8e02): use write_ptp_reg (direct 32-bit write).
* 1G/2.5G group (0x8c00/0x8e00): use set_ptp_reg_bits (read-modify-
* write) to set only the MRU field in bits[15:2] without zeroing the
* adjacent control word at 0x8c01/0x8e01, which write_ptp_reg would do.
*/
ret |= mv3310_write_ptp_reg(phydev, MV_V2_SMC_XG_MRU_CTRL_REG,
MV_V2_MRU_MAX);
ret |= mv3310_write_ptp_reg(phydev, MV_V2_WMC_XG_MRU_CTRL_REG,
MV_V2_MRU_MAX);
ret |= mv3310_set_ptp_reg_bits(phydev, MV_V2_SMC_1G_MRU_CTRL_REG,
MV_V2_MRU_1G_MAX);
ret |= mv3310_set_ptp_reg_bits(phydev, MV_V2_WMC_1G_MRU_CTRL_REG,
MV_V2_MRU_1G_MAX);
if (ret < 0)
dev_err_ratelimited(&phydev->mdio.dev,
"failed to set MRU for speed=%d (%d)\n",
speed, ret);
else
priv->old_speed = speed;
dev_err(&phydev->mdio.dev, "failed to set MRU: %d\n", ret);
Comment on lines 386 to +387
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can just reset ret after PTP before MRU

mutex_unlock(&priv->lock);

return ret;
}
Expand Down
Loading