7070#define KSZ8081_LMD_SHORT_INDICATOR BIT(12)
7171#define KSZ8081_LMD_DELTA_TIME_MASK GENMASK(8, 0)
7272
73+ #define KSZ9x31_LMD 0x12
74+ #define KSZ9x31_LMD_VCT_EN BIT(15)
75+ #define KSZ9x31_LMD_VCT_DIS_TX BIT(14)
76+ #define KSZ9x31_LMD_VCT_PAIR (n ) (((n) & 0x3) << 12)
77+ #define KSZ9x31_LMD_VCT_SEL_RESULT 0
78+ #define KSZ9x31_LMD_VCT_SEL_THRES_HI BIT(10)
79+ #define KSZ9x31_LMD_VCT_SEL_THRES_LO BIT(11)
80+ #define KSZ9x31_LMD_VCT_SEL_MASK GENMASK(11, 10)
81+ #define KSZ9x31_LMD_VCT_ST_NORMAL 0
82+ #define KSZ9x31_LMD_VCT_ST_OPEN 1
83+ #define KSZ9x31_LMD_VCT_ST_SHORT 2
84+ #define KSZ9x31_LMD_VCT_ST_FAIL 3
85+ #define KSZ9x31_LMD_VCT_ST_MASK GENMASK(9, 8)
86+ #define KSZ9x31_LMD_VCT_DATA_REFLECTED_INVALID BIT(7)
87+ #define KSZ9x31_LMD_VCT_DATA_SIG_WAIT_TOO_LONG BIT(6)
88+ #define KSZ9x31_LMD_VCT_DATA_MASK100 BIT(5)
89+ #define KSZ9x31_LMD_VCT_DATA_NLP_FLP BIT(4)
90+ #define KSZ9x31_LMD_VCT_DATA_LO_PULSE_MASK GENMASK(3, 2)
91+ #define KSZ9x31_LMD_VCT_DATA_HI_PULSE_MASK GENMASK(1, 0)
92+ #define KSZ9x31_LMD_VCT_DATA_MASK GENMASK(7, 0)
93+
7394/* Lan8814 general Interrupt control/status reg in GPHY specific block. */
7495#define LAN8814_INTC 0x18
7596#define LAN8814_INTS 0x1B
@@ -280,6 +301,7 @@ struct kszphy_priv {
280301 struct kszphy_ptp_priv ptp_priv ;
281302 const struct kszphy_type * type ;
282303 int led_mode ;
304+ u16 vct_ctrl1000 ;
283305 bool rmii_ref_clk_sel ;
284306 bool rmii_ref_clk_sel_val ;
285307 u64 stats [ARRAY_SIZE (kszphy_hw_stats )];
@@ -1326,6 +1348,199 @@ static int ksz9031_read_status(struct phy_device *phydev)
13261348 return 0 ;
13271349}
13281350
1351+ static int ksz9x31_cable_test_start (struct phy_device * phydev )
1352+ {
1353+ struct kszphy_priv * priv = phydev -> priv ;
1354+ int ret ;
1355+
1356+ /* KSZ9131RNX, DS00002841B-page 38, 4.14 LinkMD (R) Cable Diagnostic
1357+ * Prior to running the cable diagnostics, Auto-negotiation should
1358+ * be disabled, full duplex set and the link speed set to 1000Mbps
1359+ * via the Basic Control Register.
1360+ */
1361+ ret = phy_modify (phydev , MII_BMCR ,
1362+ BMCR_SPEED1000 | BMCR_FULLDPLX |
1363+ BMCR_ANENABLE | BMCR_SPEED100 ,
1364+ BMCR_SPEED1000 | BMCR_FULLDPLX );
1365+ if (ret )
1366+ return ret ;
1367+
1368+ /* KSZ9131RNX, DS00002841B-page 38, 4.14 LinkMD (R) Cable Diagnostic
1369+ * The Master-Slave configuration should be set to Slave by writing
1370+ * a value of 0x1000 to the Auto-Negotiation Master Slave Control
1371+ * Register.
1372+ */
1373+ ret = phy_read (phydev , MII_CTRL1000 );
1374+ if (ret < 0 )
1375+ return ret ;
1376+
1377+ /* Cache these bits, they need to be restored once LinkMD finishes. */
1378+ priv -> vct_ctrl1000 = ret & (CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER );
1379+ ret &= ~(CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER );
1380+ ret |= CTL1000_ENABLE_MASTER ;
1381+
1382+ return phy_write (phydev , MII_CTRL1000 , ret );
1383+ }
1384+
1385+ static int ksz9x31_cable_test_result_trans (u16 status )
1386+ {
1387+ switch (FIELD_GET (KSZ9x31_LMD_VCT_ST_MASK , status )) {
1388+ case KSZ9x31_LMD_VCT_ST_NORMAL :
1389+ return ETHTOOL_A_CABLE_RESULT_CODE_OK ;
1390+ case KSZ9x31_LMD_VCT_ST_OPEN :
1391+ return ETHTOOL_A_CABLE_RESULT_CODE_OPEN ;
1392+ case KSZ9x31_LMD_VCT_ST_SHORT :
1393+ return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT ;
1394+ case KSZ9x31_LMD_VCT_ST_FAIL :
1395+ fallthrough ;
1396+ default :
1397+ return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC ;
1398+ }
1399+ }
1400+
1401+ static bool ksz9x31_cable_test_failed (u16 status )
1402+ {
1403+ int stat = FIELD_GET (KSZ9x31_LMD_VCT_ST_MASK , status );
1404+
1405+ return stat == KSZ9x31_LMD_VCT_ST_FAIL ;
1406+ }
1407+
1408+ static bool ksz9x31_cable_test_fault_length_valid (u16 status )
1409+ {
1410+ switch (FIELD_GET (KSZ9x31_LMD_VCT_ST_MASK , status )) {
1411+ case KSZ9x31_LMD_VCT_ST_OPEN :
1412+ fallthrough ;
1413+ case KSZ9x31_LMD_VCT_ST_SHORT :
1414+ return true;
1415+ }
1416+ return false;
1417+ }
1418+
1419+ static int ksz9x31_cable_test_fault_length (struct phy_device * phydev , u16 stat )
1420+ {
1421+ int dt = FIELD_GET (KSZ9x31_LMD_VCT_DATA_MASK , stat );
1422+
1423+ /* KSZ9131RNX, DS00002841B-page 38, 4.14 LinkMD (R) Cable Diagnostic
1424+ *
1425+ * distance to fault = (VCT_DATA - 22) * 4 / cable propagation velocity
1426+ */
1427+ if ((phydev -> phy_id & MICREL_PHY_ID_MASK ) == PHY_ID_KSZ9131 )
1428+ dt = clamp (dt - 22 , 0 , 255 );
1429+
1430+ return (dt * 400 ) / 10 ;
1431+ }
1432+
1433+ static int ksz9x31_cable_test_wait_for_completion (struct phy_device * phydev )
1434+ {
1435+ int val , ret ;
1436+
1437+ ret = phy_read_poll_timeout (phydev , KSZ9x31_LMD , val ,
1438+ !(val & KSZ9x31_LMD_VCT_EN ),
1439+ 30000 , 100000 , true);
1440+
1441+ return ret < 0 ? ret : 0 ;
1442+ }
1443+
1444+ static int ksz9x31_cable_test_get_pair (int pair )
1445+ {
1446+ static const int ethtool_pair [] = {
1447+ ETHTOOL_A_CABLE_PAIR_A ,
1448+ ETHTOOL_A_CABLE_PAIR_B ,
1449+ ETHTOOL_A_CABLE_PAIR_C ,
1450+ ETHTOOL_A_CABLE_PAIR_D ,
1451+ };
1452+
1453+ return ethtool_pair [pair ];
1454+ }
1455+
1456+ static int ksz9x31_cable_test_one_pair (struct phy_device * phydev , int pair )
1457+ {
1458+ int ret , val ;
1459+
1460+ /* KSZ9131RNX, DS00002841B-page 38, 4.14 LinkMD (R) Cable Diagnostic
1461+ * To test each individual cable pair, set the cable pair in the Cable
1462+ * Diagnostics Test Pair (VCT_PAIR[1:0]) field of the LinkMD Cable
1463+ * Diagnostic Register, along with setting the Cable Diagnostics Test
1464+ * Enable (VCT_EN) bit. The Cable Diagnostics Test Enable (VCT_EN) bit
1465+ * will self clear when the test is concluded.
1466+ */
1467+ ret = phy_write (phydev , KSZ9x31_LMD ,
1468+ KSZ9x31_LMD_VCT_EN | KSZ9x31_LMD_VCT_PAIR (pair ));
1469+ if (ret )
1470+ return ret ;
1471+
1472+ ret = ksz9x31_cable_test_wait_for_completion (phydev );
1473+ if (ret )
1474+ return ret ;
1475+
1476+ val = phy_read (phydev , KSZ9x31_LMD );
1477+ if (val < 0 )
1478+ return val ;
1479+
1480+ if (ksz9x31_cable_test_failed (val ))
1481+ return - EAGAIN ;
1482+
1483+ ret = ethnl_cable_test_result (phydev ,
1484+ ksz9x31_cable_test_get_pair (pair ),
1485+ ksz9x31_cable_test_result_trans (val ));
1486+ if (ret )
1487+ return ret ;
1488+
1489+ if (!ksz9x31_cable_test_fault_length_valid (val ))
1490+ return 0 ;
1491+
1492+ return ethnl_cable_test_fault_length (phydev ,
1493+ ksz9x31_cable_test_get_pair (pair ),
1494+ ksz9x31_cable_test_fault_length (phydev , val ));
1495+ }
1496+
1497+ static int ksz9x31_cable_test_get_status (struct phy_device * phydev ,
1498+ bool * finished )
1499+ {
1500+ struct kszphy_priv * priv = phydev -> priv ;
1501+ unsigned long pair_mask = 0xf ;
1502+ int retries = 20 ;
1503+ int pair , ret , rv ;
1504+
1505+ * finished = false;
1506+
1507+ /* Try harder if link partner is active */
1508+ while (pair_mask && retries -- ) {
1509+ for_each_set_bit (pair , & pair_mask , 4 ) {
1510+ ret = ksz9x31_cable_test_one_pair (phydev , pair );
1511+ if (ret == - EAGAIN )
1512+ continue ;
1513+ if (ret < 0 )
1514+ return ret ;
1515+ clear_bit (pair , & pair_mask );
1516+ }
1517+ /* If link partner is in autonegotiation mode it will send 2ms
1518+ * of FLPs with at least 6ms of silence.
1519+ * Add 2ms sleep to have better chances to hit this silence.
1520+ */
1521+ if (pair_mask )
1522+ usleep_range (2000 , 3000 );
1523+ }
1524+
1525+ /* Report remaining unfinished pair result as unknown. */
1526+ for_each_set_bit (pair , & pair_mask , 4 ) {
1527+ ret = ethnl_cable_test_result (phydev ,
1528+ ksz9x31_cable_test_get_pair (pair ),
1529+ ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC );
1530+ }
1531+
1532+ * finished = true;
1533+
1534+ /* Restore cached bits from before LinkMD got started. */
1535+ rv = phy_modify (phydev , MII_CTRL1000 ,
1536+ CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER ,
1537+ priv -> vct_ctrl1000 );
1538+ if (rv )
1539+ return rv ;
1540+
1541+ return ret ;
1542+ }
1543+
13291544static int ksz8873mll_config_aneg (struct phy_device * phydev )
13301545{
13311546 return 0 ;
@@ -2806,6 +3021,7 @@ static struct phy_driver ksphy_driver[] = {
28063021 .phy_id = PHY_ID_KSZ9031 ,
28073022 .phy_id_mask = MICREL_PHY_ID_MASK ,
28083023 .name = "Micrel KSZ9031 Gigabit PHY" ,
3024+ .flags = PHY_POLL_CABLE_TEST ,
28093025 .driver_data = & ksz9021_type ,
28103026 .probe = kszphy_probe ,
28113027 .get_features = ksz9031_get_features ,
@@ -2819,6 +3035,8 @@ static struct phy_driver ksphy_driver[] = {
28193035 .get_stats = kszphy_get_stats ,
28203036 .suspend = kszphy_suspend ,
28213037 .resume = kszphy_resume ,
3038+ .cable_test_start = ksz9x31_cable_test_start ,
3039+ .cable_test_get_status = ksz9x31_cable_test_get_status ,
28223040}, {
28233041 .phy_id = PHY_ID_LAN8814 ,
28243042 .phy_id_mask = MICREL_PHY_ID_MASK ,
@@ -2853,6 +3071,7 @@ static struct phy_driver ksphy_driver[] = {
28533071 .phy_id_mask = MICREL_PHY_ID_MASK ,
28543072 .name = "Microchip KSZ9131 Gigabit PHY" ,
28553073 /* PHY_GBIT_FEATURES */
3074+ .flags = PHY_POLL_CABLE_TEST ,
28563075 .driver_data = & ksz9021_type ,
28573076 .probe = kszphy_probe ,
28583077 .config_init = ksz9131_config_init ,
@@ -2863,6 +3082,8 @@ static struct phy_driver ksphy_driver[] = {
28633082 .get_stats = kszphy_get_stats ,
28643083 .suspend = kszphy_suspend ,
28653084 .resume = kszphy_resume ,
3085+ .cable_test_start = ksz9x31_cable_test_start ,
3086+ .cable_test_get_status = ksz9x31_cable_test_get_status ,
28663087}, {
28673088 .phy_id = PHY_ID_KSZ8873MLL ,
28683089 .phy_id_mask = MICREL_PHY_ID_MASK ,
0 commit comments