281
281
282
282
#define MII_VCT_TXPINS 0x1A
283
283
#define MII_VCT_RXPINS 0x1B
284
+ #define MII_VCT_SR 0x1C
284
285
#define MII_VCT_TXPINS_ENVCT BIT(15)
285
286
#define MII_VCT_TXRXPINS_VCTTST GENMASK(14, 13)
286
287
#define MII_VCT_TXRXPINS_VCTTST_SHIFT 13
@@ -2623,6 +2624,92 @@ static int m88e3082_vct_cable_test_get_status(struct phy_device *phydev,
2623
2624
return 0 ;
2624
2625
}
2625
2626
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
+
2626
2713
#ifdef CONFIG_HWMON
2627
2714
struct marvell_hwmon_ops {
2628
2715
int (* config )(struct phy_device * phydev );
@@ -3534,6 +3621,7 @@ static struct phy_driver marvell_drivers[] = {
3534
3621
.phy_id_mask = MARVELL_PHY_ID_MASK ,
3535
3622
.name = "Marvell 88E1111" ,
3536
3623
/* PHY_GBIT_FEATURES */
3624
+ .flags = PHY_POLL_CABLE_TEST ,
3537
3625
.probe = marvell_probe ,
3538
3626
.config_init = m88e1111gbe_config_init ,
3539
3627
.config_aneg = m88e1111_config_aneg ,
@@ -3549,6 +3637,8 @@ static struct phy_driver marvell_drivers[] = {
3549
3637
.get_stats = marvell_get_stats ,
3550
3638
.get_tunable = m88e1111_get_tunable ,
3551
3639
.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 ,
3552
3642
},
3553
3643
{
3554
3644
.phy_id = MARVELL_PHY_ID_88E1111_FINISAR ,
@@ -3642,6 +3732,7 @@ static struct phy_driver marvell_drivers[] = {
3642
3732
.phy_id_mask = MARVELL_PHY_ID_MASK ,
3643
3733
.name = "Marvell 88E1145" ,
3644
3734
/* PHY_GBIT_FEATURES */
3735
+ .flags = PHY_POLL_CABLE_TEST ,
3645
3736
.probe = marvell_probe ,
3646
3737
.config_init = m88e1145_config_init ,
3647
3738
.config_aneg = m88e1101_config_aneg ,
@@ -3656,6 +3747,8 @@ static struct phy_driver marvell_drivers[] = {
3656
3747
.get_stats = marvell_get_stats ,
3657
3748
.get_tunable = m88e1111_get_tunable ,
3658
3749
.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 ,
3659
3752
},
3660
3753
{
3661
3754
.phy_id = MARVELL_PHY_ID_88E1149R ,
0 commit comments