summaryrefslogtreecommitdiff
path: root/drivers/net/phy/marvell.c
diff options
context:
space:
mode:
authorAndrew Lunn <andrew@lunn.ch>2020-05-27 00:21:41 +0200
committerDavid S. Miller <davem@davemloft.net>2020-05-26 23:22:21 -0700
commitf2bc8ad31a7f814237bc6301d59296d76505a688 (patch)
tree738fb4f9aa7157772793f5c7c5febbedb6d828f4 /drivers/net/phy/marvell.c
parent0c9bcc1d2394acef2c6e89e652d984cc845c7bea (diff)
net: ethtool: Allow PHY cable test TDR data to configured
Allow the user to configure where on the cable the TDR data should be retrieved, in terms of first and last sample, and the step between samples. Also add the ability to ask for TDR data for just one pair. If this configuration is not provided, it defaults to 1-150m at 1m intervals for all pairs. Signed-off-by: Andrew Lunn <andrew@lunn.ch> v3: Move the TDR configuration into a structure Add a range check on step Use NL_SET_ERR_MSG_ATTR() when appropriate Move TDR configuration into a nest Document attributes in the request Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/phy/marvell.c')
-rw-r--r--drivers/net/phy/marvell.c59
1 files changed, 42 insertions, 17 deletions
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index e597bee2e966..335e51d6f138 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -198,6 +198,7 @@
#define MII_VCT5_CTRL_PEEK_HYST_DEFAULT 3
#define MII_VCT5_SAMPLE_POINT_DISTANCE 0x18
+#define MII_VCT5_SAMPLE_POINT_DISTANCE_MAX 511
#define MII_VCT5_TX_PULSE_CTRL 0x1c
#define MII_VCT5_TX_PULSE_CTRL_DONT_WAIT_LINK_DOWN BIT(12)
#define MII_VCT5_TX_PULSE_CTRL_PULSE_WIDTH_128nS (0x0 << 10)
@@ -270,6 +271,10 @@ struct marvell_priv {
char *hwmon_name;
struct device *hwmon_dev;
bool cable_test_tdr;
+ u32 first;
+ u32 last;
+ u32 step;
+ s8 pair;
};
static int marvell_read_page(struct phy_device *phydev)
@@ -1787,12 +1792,18 @@ static u32 marvell_vct5_distance2cm(int distance)
return distance * 805 / 10;
}
+static u32 marvell_vct5_cm2distance(int cm)
+{
+ return cm * 10 / 805;
+}
+
static int marvell_vct5_amplitude_distance(struct phy_device *phydev,
- int distance)
+ int distance, int pair)
{
- int mV_pair0, mV_pair1, mV_pair2, mV_pair3;
u16 reg;
int err;
+ int mV;
+ int i;
err = phy_write_paged(phydev, MII_MARVELL_VCT5_PAGE,
MII_VCT5_SAMPLE_POINT_DISTANCE,
@@ -1814,21 +1825,20 @@ static int marvell_vct5_amplitude_distance(struct phy_device *phydev,
if (err)
return err;
- mV_pair0 = marvell_vct5_amplitude(phydev, 0);
- mV_pair1 = marvell_vct5_amplitude(phydev, 1);
- mV_pair2 = marvell_vct5_amplitude(phydev, 2);
- mV_pair3 = marvell_vct5_amplitude(phydev, 3);
+ for (i = 0; i < 4; i++) {
+ if (pair != PHY_PAIR_ALL && i != pair)
+ continue;
- ethnl_cable_test_amplitude(phydev, ETHTOOL_A_CABLE_PAIR_A, mV_pair0);
- ethnl_cable_test_amplitude(phydev, ETHTOOL_A_CABLE_PAIR_B, mV_pair1);
- ethnl_cable_test_amplitude(phydev, ETHTOOL_A_CABLE_PAIR_C, mV_pair2);
- ethnl_cable_test_amplitude(phydev, ETHTOOL_A_CABLE_PAIR_D, mV_pair3);
+ mV = marvell_vct5_amplitude(phydev, i);
+ ethnl_cable_test_amplitude(phydev, i, mV);
+ }
return 0;
}
static int marvell_vct5_amplitude_graph(struct phy_device *phydev)
{
+ struct marvell_priv *priv = phydev->priv;
int distance;
int err;
u16 reg;
@@ -1843,8 +1853,11 @@ static int marvell_vct5_amplitude_graph(struct phy_device *phydev)
if (err)
return err;
- for (distance = 0; distance <= 100; distance++) {
- err = marvell_vct5_amplitude_distance(phydev, distance);
+ for (distance = priv->first;
+ distance <= priv->last;
+ distance += priv->step) {
+ err = marvell_vct5_amplitude_distance(phydev, distance,
+ priv->pair);
if (err)
return err;
}
@@ -1918,11 +1931,24 @@ static int marvell_vct7_cable_test_start(struct phy_device *phydev)
MII_VCT7_CTRL_CENTIMETERS);
}
-static int marvell_vct5_cable_test_tdr_start(struct phy_device *phydev)
+static int marvell_vct5_cable_test_tdr_start(struct phy_device *phydev,
+ const struct phy_tdr_config *cfg)
{
struct marvell_priv *priv = phydev->priv;
int ret;
+ priv->cable_test_tdr = true;
+ priv->first = marvell_vct5_cm2distance(cfg->first);
+ priv->last = marvell_vct5_cm2distance(cfg->last);
+ priv->step = marvell_vct5_cm2distance(cfg->step);
+ priv->pair = cfg->pair;
+
+ if (priv->first > MII_VCT5_SAMPLE_POINT_DISTANCE_MAX)
+ return -EINVAL;
+
+ if (priv->last > MII_VCT5_SAMPLE_POINT_DISTANCE_MAX)
+ return -EINVAL;
+
/* Disable VCT7 */
ret = phy_write_paged(phydev, MII_MARVELL_VCT7_PAGE,
MII_VCT7_CTRL, 0);
@@ -1933,15 +1959,14 @@ static int marvell_vct5_cable_test_tdr_start(struct phy_device *phydev)
if (ret)
return ret;
- priv->cable_test_tdr = true;
ret = ethnl_cable_test_pulse(phydev, 1000);
if (ret)
return ret;
return ethnl_cable_test_step(phydev,
- marvell_vct5_distance2cm(0),
- marvell_vct5_distance2cm(100),
- marvell_vct5_distance2cm(1));
+ marvell_vct5_distance2cm(priv->first),
+ marvell_vct5_distance2cm(priv->last),
+ marvell_vct5_distance2cm(priv->step));
}
static int marvell_vct7_distance_to_length(int distance, bool meter)