64
64
#define RTL822X_VND1_SERDES_CTRL3_MODE_SGMII 0x02
65
65
#define RTL822X_VND1_SERDES_CTRL3_MODE_2500BASEX 0x16
66
66
67
+ /* RTL822X_VND2_XXXXX registers are only accessible when phydev->is_c45
68
+ * is set, they cannot be accessed by C45-over-C22.
69
+ */
70
+ #define RTL822X_VND2_GBCR 0xa412
71
+
72
+ #define RTL822X_VND2_GANLPAR 0xa414
73
+
67
74
#define RTL8366RB_POWER_SAVE 0x15
68
75
#define RTL8366RB_POWER_SAVE_ON BIT(12)
69
76
74
81
75
82
#define RTL_GENERIC_PHYID 0x001cc800
76
83
#define RTL_8211FVD_PHYID 0x001cc878
84
+ #define RTL_8221B_VB_CG 0x001cc849
85
+ #define RTL_8221B_VN_CG 0x001cc84a
86
+ #define RTL_8251B 0x001cc862
77
87
78
88
MODULE_DESCRIPTION ("Realtek PHY driver" );
79
89
MODULE_AUTHOR ("Johnson Leung" );
@@ -839,6 +849,67 @@ static int rtl822xb_read_status(struct phy_device *phydev)
839
849
return 0 ;
840
850
}
841
851
852
+ static int rtl822x_c45_config_aneg (struct phy_device * phydev )
853
+ {
854
+ bool changed = false;
855
+ int ret , val ;
856
+
857
+ if (phydev -> autoneg == AUTONEG_DISABLE )
858
+ return genphy_c45_pma_setup_forced (phydev );
859
+
860
+ ret = genphy_c45_an_config_aneg (phydev );
861
+ if (ret < 0 )
862
+ return ret ;
863
+ if (ret > 0 )
864
+ changed = true;
865
+
866
+ val = linkmode_adv_to_mii_ctrl1000_t (phydev -> advertising );
867
+
868
+ /* Vendor register as C45 has no standardized support for 1000BaseT */
869
+ ret = phy_modify_mmd_changed (phydev , MDIO_MMD_VEND2 , RTL822X_VND2_GBCR ,
870
+ ADVERTISE_1000FULL , val );
871
+ if (ret < 0 )
872
+ return ret ;
873
+ if (ret > 0 )
874
+ changed = true;
875
+
876
+ return genphy_c45_check_and_restart_aneg (phydev , changed );
877
+ }
878
+
879
+ static int rtl822x_c45_read_status (struct phy_device * phydev )
880
+ {
881
+ int ret , val ;
882
+
883
+ ret = genphy_c45_read_status (phydev );
884
+ if (ret < 0 )
885
+ return ret ;
886
+
887
+ /* Vendor register as C45 has no standardized support for 1000BaseT */
888
+ if (phydev -> autoneg == AUTONEG_ENABLE ) {
889
+ val = phy_read_mmd (phydev , MDIO_MMD_VEND2 ,
890
+ RTL822X_VND2_GANLPAR );
891
+ if (val < 0 )
892
+ return val ;
893
+
894
+ mii_stat1000_mod_linkmode_lpa_t (phydev -> lp_advertising , val );
895
+ }
896
+
897
+ return 0 ;
898
+ }
899
+
900
+ static int rtl822xb_c45_read_status (struct phy_device * phydev )
901
+ {
902
+ int ret ;
903
+
904
+ ret = rtl822x_c45_read_status (phydev );
905
+ if (ret < 0 )
906
+ return ret ;
907
+
908
+ rtl822xb_update_interface (phydev );
909
+
910
+ return 0 ;
911
+ }
912
+
842
913
static bool rtlgen_supports_2_5gbps (struct phy_device * phydev )
843
914
{
844
915
int val ;
@@ -862,6 +933,35 @@ static int rtl8226_match_phy_device(struct phy_device *phydev)
862
933
rtlgen_supports_2_5gbps (phydev );
863
934
}
864
935
936
+ static int rtlgen_is_c45_match (struct phy_device * phydev , unsigned int id ,
937
+ bool is_c45 )
938
+ {
939
+ if (phydev -> is_c45 )
940
+ return is_c45 && (id == phydev -> c45_ids .device_ids [1 ]);
941
+ else
942
+ return !is_c45 && (id == phydev -> phy_id );
943
+ }
944
+
945
+ static int rtl8221b_vb_cg_c22_match_phy_device (struct phy_device * phydev )
946
+ {
947
+ return rtlgen_is_c45_match (phydev , RTL_8221B_VB_CG , false);
948
+ }
949
+
950
+ static int rtl8221b_vb_cg_c45_match_phy_device (struct phy_device * phydev )
951
+ {
952
+ return rtlgen_is_c45_match (phydev , RTL_8221B_VB_CG , true);
953
+ }
954
+
955
+ static int rtl8221b_vn_cg_c22_match_phy_device (struct phy_device * phydev )
956
+ {
957
+ return rtlgen_is_c45_match (phydev , RTL_8221B_VN_CG , false);
958
+ }
959
+
960
+ static int rtl8221b_vn_cg_c45_match_phy_device (struct phy_device * phydev )
961
+ {
962
+ return rtlgen_is_c45_match (phydev , RTL_8221B_VN_CG , true);
963
+ }
964
+
865
965
static int rtlgen_resume (struct phy_device * phydev )
866
966
{
867
967
int ret = genphy_resume (phydev );
@@ -872,6 +972,15 @@ static int rtlgen_resume(struct phy_device *phydev)
872
972
return ret ;
873
973
}
874
974
975
+ static int rtlgen_c45_resume (struct phy_device * phydev )
976
+ {
977
+ int ret = genphy_c45_pma_resume (phydev );
978
+
979
+ msleep (20 );
980
+
981
+ return ret ;
982
+ }
983
+
875
984
static int rtl9000a_config_init (struct phy_device * phydev )
876
985
{
877
986
phydev -> autoneg = AUTONEG_DISABLE ;
@@ -1143,8 +1252,8 @@ static struct phy_driver realtek_drvs[] = {
1143
1252
.read_page = rtl821x_read_page ,
1144
1253
.write_page = rtl821x_write_page ,
1145
1254
}, {
1146
- PHY_ID_MATCH_EXACT ( 0x001cc849 ) ,
1147
- .name = "RTL8221B-VB-CG 2.5Gbps PHY" ,
1255
+ . match_phy_device = rtl8221b_vb_cg_c22_match_phy_device ,
1256
+ .name = "RTL8221B-VB-CG 2.5Gbps PHY (C22) " ,
1148
1257
.get_features = rtl822x_get_features ,
1149
1258
.config_aneg = rtl822x_config_aneg ,
1150
1259
.config_init = rtl822xb_config_init ,
@@ -1155,8 +1264,17 @@ static struct phy_driver realtek_drvs[] = {
1155
1264
.read_page = rtl821x_read_page ,
1156
1265
.write_page = rtl821x_write_page ,
1157
1266
}, {
1158
- PHY_ID_MATCH_EXACT (0x001cc84a ),
1159
- .name = "RTL8221B-VM-CG 2.5Gbps PHY" ,
1267
+ .match_phy_device = rtl8221b_vb_cg_c45_match_phy_device ,
1268
+ .name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)" ,
1269
+ .config_init = rtl822xb_config_init ,
1270
+ .get_rate_matching = rtl822xb_get_rate_matching ,
1271
+ .config_aneg = rtl822x_c45_config_aneg ,
1272
+ .read_status = rtl822xb_c45_read_status ,
1273
+ .suspend = genphy_c45_pma_suspend ,
1274
+ .resume = rtlgen_c45_resume ,
1275
+ }, {
1276
+ .match_phy_device = rtl8221b_vn_cg_c22_match_phy_device ,
1277
+ .name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)" ,
1160
1278
.get_features = rtl822x_get_features ,
1161
1279
.config_aneg = rtl822x_config_aneg ,
1162
1280
.config_init = rtl822xb_config_init ,
@@ -1166,6 +1284,15 @@ static struct phy_driver realtek_drvs[] = {
1166
1284
.resume = rtlgen_resume ,
1167
1285
.read_page = rtl821x_read_page ,
1168
1286
.write_page = rtl821x_write_page ,
1287
+ }, {
1288
+ .match_phy_device = rtl8221b_vn_cg_c45_match_phy_device ,
1289
+ .name = "RTL8221B-VN-CG 2.5Gbps PHY (C45)" ,
1290
+ .config_init = rtl822xb_config_init ,
1291
+ .get_rate_matching = rtl822xb_get_rate_matching ,
1292
+ .config_aneg = rtl822x_c45_config_aneg ,
1293
+ .read_status = rtl822xb_c45_read_status ,
1294
+ .suspend = genphy_c45_pma_suspend ,
1295
+ .resume = rtlgen_c45_resume ,
1169
1296
}, {
1170
1297
PHY_ID_MATCH_EXACT (0x001cc862 ),
1171
1298
.name = "RTL8251B 5Gbps PHY" ,
0 commit comments