diff options
author | Oleksij Rempel <o.rempel@pengutronix.de> | 2022-06-20 13:56:01 +0200 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2022-06-21 22:01:14 -0700 |
commit | a80d8fb70cc7864fd09e5e177627ee38d3a8fbdd (patch) | |
tree | d2f58f62cd7c3618496d188d6af8c0b9d878f1f4 | |
parent | b1f01b4bd7ad7f642d896cb9d6f82ec34043b612 (diff) |
net: phy: dp83td510: add SQI support
Convert MSE (mean-square error) values to SNR and split it SQI (Signal Quality
Indicator) ranges. The used ranges are taken from "OPEN ALLIANCE - Advanced
diagnostic features for 100BASE-T1 automotive Ethernet PHYs"
specification.
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://lore.kernel.org/r/20220620115601.2035452-1-o.rempel@pengutronix.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r-- | drivers/net/phy/dp83td510.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/drivers/net/phy/dp83td510.c b/drivers/net/phy/dp83td510.c index 1ae792b0daaa..3cd9a77f9532 100644 --- a/drivers/net/phy/dp83td510.c +++ b/drivers/net/phy/dp83td510.c @@ -27,6 +27,27 @@ #define DP83TD510E_AN_STAT_1 0x60c #define DP83TD510E_MASTER_SLAVE_RESOL_FAIL BIT(15) +#define DP83TD510E_MSE_DETECT 0xa85 + +#define DP83TD510_SQI_MAX 7 + +/* Register values are converted to SNR(dB) as suggested by + * "Application Report - DP83TD510E Cable Diagnostics Toolkit": + * SNR(dB) = -10 * log10 (VAL/2^17) - 1.76 dB. + * SQI ranges are implemented according to "OPEN ALLIANCE - Advanced diagnostic + * features for 100BASE-T1 automotive Ethernet PHYs" + */ +static const u16 dp83td510_mse_sqi_map[] = { + 0x0569, /* < 18dB */ + 0x044c, /* 18dB =< SNR < 19dB */ + 0x0369, /* 19dB =< SNR < 20dB */ + 0x02b6, /* 20dB =< SNR < 21dB */ + 0x0227, /* 21dB =< SNR < 22dB */ + 0x01b6, /* 22dB =< SNR < 23dB */ + 0x015b, /* 23dB =< SNR < 24dB */ + 0x0000 /* 24dB =< SNR */ +}; + static int dp83td510_config_intr(struct phy_device *phydev) { int ret; @@ -164,6 +185,32 @@ static int dp83td510_config_aneg(struct phy_device *phydev) return genphy_c45_check_and_restart_aneg(phydev, changed); } +static int dp83td510_get_sqi(struct phy_device *phydev) +{ + int sqi, ret; + u16 mse_val; + + if (!phydev->link) + return 0; + + ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TD510E_MSE_DETECT); + if (ret < 0) + return ret; + + mse_val = 0xFFFF & ret; + for (sqi = 0; sqi < ARRAY_SIZE(dp83td510_mse_sqi_map); sqi++) { + if (mse_val >= dp83td510_mse_sqi_map[sqi]) + return sqi; + } + + return -EINVAL; +} + +static int dp83td510_get_sqi_max(struct phy_device *phydev) +{ + return DP83TD510_SQI_MAX; +} + static int dp83td510_get_features(struct phy_device *phydev) { /* This PHY can't respond on MDIO bus if no RMII clock is enabled. @@ -192,6 +239,8 @@ static struct phy_driver dp83td510_driver[] = { .get_features = dp83td510_get_features, .config_intr = dp83td510_config_intr, .handle_interrupt = dp83td510_handle_interrupt, + .get_sqi = dp83td510_get_sqi, + .get_sqi_max = dp83td510_get_sqi_max, .suspend = genphy_suspend, .resume = genphy_resume, |