Skip to content

Commit d133ef1

Browse files
CHKDSK88davem330
authored andcommitted
net: phy: marvell: implement cable test for 88E1111
The same implementation is also valid for 88E1145. VCT in 88E1111 is similar to the 88E609x family. The main difference lies in register organization and required workarounds. It utilizes the same fields in registers but requires a simpler implementation. Signed-off-by: Pawel Dembicki <[email protected]> Reviewed-by: Andrew Lunn <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 8e69b34 commit d133ef1

File tree

1 file changed

+93
-0
lines changed

1 file changed

+93
-0
lines changed

drivers/net/phy/marvell.c

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@
281281

282282
#define MII_VCT_TXPINS 0x1A
283283
#define MII_VCT_RXPINS 0x1B
284+
#define MII_VCT_SR 0x1C
284285
#define MII_VCT_TXPINS_ENVCT BIT(15)
285286
#define MII_VCT_TXRXPINS_VCTTST GENMASK(14, 13)
286287
#define MII_VCT_TXRXPINS_VCTTST_SHIFT 13
@@ -2623,6 +2624,92 @@ static int m88e3082_vct_cable_test_get_status(struct phy_device *phydev,
26232624
return 0;
26242625
}
26252626

2627+
static int m88e1111_vct_cable_test_start(struct phy_device *phydev)
2628+
{
2629+
int ret;
2630+
2631+
ret = marvell_cable_test_start_common(phydev);
2632+
if (ret)
2633+
return ret;
2634+
2635+
/* It needs some magic workarounds described in VCT manual for this PHY.
2636+
*/
2637+
ret = phy_write(phydev, 29, 0x0018);
2638+
if (ret < 0)
2639+
return ret;
2640+
2641+
ret = phy_write(phydev, 30, 0x00c2);
2642+
if (ret < 0)
2643+
return ret;
2644+
2645+
ret = phy_write(phydev, 30, 0x00ca);
2646+
if (ret < 0)
2647+
return ret;
2648+
2649+
ret = phy_write(phydev, 30, 0x00c2);
2650+
if (ret < 0)
2651+
return ret;
2652+
2653+
ret = phy_write_paged(phydev, MII_MARVELL_COPPER_PAGE, MII_VCT_SR,
2654+
MII_VCT_TXPINS_ENVCT);
2655+
if (ret < 0)
2656+
return ret;
2657+
2658+
ret = phy_write(phydev, 29, 0x0018);
2659+
if (ret < 0)
2660+
return ret;
2661+
2662+
ret = phy_write(phydev, 30, 0x0042);
2663+
if (ret < 0)
2664+
return ret;
2665+
2666+
return 0;
2667+
}
2668+
2669+
static u32 m88e1111_vct_distrfln_2_cm(u8 distrfln)
2670+
{
2671+
if (distrfln < 36)
2672+
return 0;
2673+
2674+
/* Original function for meters: y = 0.8018x - 28.751 */
2675+
return (8018 * distrfln - 287510) / 100;
2676+
}
2677+
2678+
static int m88e1111_vct_cable_test_get_status(struct phy_device *phydev,
2679+
bool *finished)
2680+
{
2681+
u8 vcttst_res, distrfln;
2682+
int ret, result;
2683+
2684+
*finished = false;
2685+
2686+
/* Each pair use one page: A-0, B-1, C-2, D-3 */
2687+
for (u8 i = 0; i < 4; i++) {
2688+
ret = phy_read_paged(phydev, i, MII_VCT_SR);
2689+
if (ret < 0)
2690+
return ret;
2691+
else if (i == 0 && ret & MII_VCT_TXPINS_ENVCT)
2692+
return 0;
2693+
2694+
distrfln = ret & MII_VCT_TXRXPINS_DISTRFLN;
2695+
vcttst_res = (ret & MII_VCT_TXRXPINS_VCTTST) >>
2696+
MII_VCT_TXRXPINS_VCTTST_SHIFT;
2697+
2698+
result = m88e3082_vct_cable_test_report_trans(vcttst_res,
2699+
distrfln);
2700+
ethnl_cable_test_result(phydev, i, result);
2701+
2702+
if (distrfln < MII_VCT_TXRXPINS_DISTRFLN_MAX) {
2703+
u32 cm = m88e1111_vct_distrfln_2_cm(distrfln);
2704+
2705+
ethnl_cable_test_fault_length(phydev, i, cm);
2706+
}
2707+
}
2708+
2709+
*finished = true;
2710+
return 0;
2711+
}
2712+
26262713
#ifdef CONFIG_HWMON
26272714
struct marvell_hwmon_ops {
26282715
int (*config)(struct phy_device *phydev);
@@ -3534,6 +3621,7 @@ static struct phy_driver marvell_drivers[] = {
35343621
.phy_id_mask = MARVELL_PHY_ID_MASK,
35353622
.name = "Marvell 88E1111",
35363623
/* PHY_GBIT_FEATURES */
3624+
.flags = PHY_POLL_CABLE_TEST,
35373625
.probe = marvell_probe,
35383626
.config_init = m88e1111gbe_config_init,
35393627
.config_aneg = m88e1111_config_aneg,
@@ -3549,6 +3637,8 @@ static struct phy_driver marvell_drivers[] = {
35493637
.get_stats = marvell_get_stats,
35503638
.get_tunable = m88e1111_get_tunable,
35513639
.set_tunable = m88e1111_set_tunable,
3640+
.cable_test_start = m88e1111_vct_cable_test_start,
3641+
.cable_test_get_status = m88e1111_vct_cable_test_get_status,
35523642
},
35533643
{
35543644
.phy_id = MARVELL_PHY_ID_88E1111_FINISAR,
@@ -3642,6 +3732,7 @@ static struct phy_driver marvell_drivers[] = {
36423732
.phy_id_mask = MARVELL_PHY_ID_MASK,
36433733
.name = "Marvell 88E1145",
36443734
/* PHY_GBIT_FEATURES */
3735+
.flags = PHY_POLL_CABLE_TEST,
36453736
.probe = marvell_probe,
36463737
.config_init = m88e1145_config_init,
36473738
.config_aneg = m88e1101_config_aneg,
@@ -3656,6 +3747,8 @@ static struct phy_driver marvell_drivers[] = {
36563747
.get_stats = marvell_get_stats,
36573748
.get_tunable = m88e1111_get_tunable,
36583749
.set_tunable = m88e1111_set_tunable,
3750+
.cable_test_start = m88e1111_vct_cable_test_start,
3751+
.cable_test_get_status = m88e1111_vct_cable_test_get_status,
36593752
},
36603753
{
36613754
.phy_id = MARVELL_PHY_ID_88E1149R,

0 commit comments

Comments
 (0)