5353
5454#define MII_M1011_PHY_SCR 0x10
5555#define MII_M1011_PHY_SCR_DOWNSHIFT_EN BIT(11)
56- #define MII_M1011_PHY_SCR_DOWNSHIFT_SHIFT 12
57- #define MII_M1011_PHY_SRC_DOWNSHIFT_MASK 0x7800
56+ #define MII_M1011_PHY_SRC_DOWNSHIFT_MASK GENMASK(14, 12)
57+ #define MII_M1011_PHY_SCR_DOWNSHIFT_MAX 8
5858#define MII_M1011_PHY_SCR_MDI (0x0 << 5)
5959#define MII_M1011_PHY_SCR_MDI_X (0x1 << 5)
6060#define MII_M1011_PHY_SCR_AUTO_CROSS (0x3 << 5)
6161
62+ #define MII_M1011_PHY_SSR 0x11
63+ #define MII_M1011_PHY_SSR_DOWNSHIFT BIT(5)
64+
6265#define MII_M1111_PHY_LED_CONTROL 0x18
6366#define MII_M1111_PHY_LED_DIRECT 0x4100
6467#define MII_M1111_PHY_LED_COMBINE 0x411c
@@ -273,23 +276,6 @@ static int marvell_set_polarity(struct phy_device *phydev, int polarity)
273276 return val != reg ;
274277}
275278
276- static int marvell_set_downshift (struct phy_device * phydev , bool enable ,
277- u8 retries )
278- {
279- int reg ;
280-
281- reg = phy_read (phydev , MII_M1011_PHY_SCR );
282- if (reg < 0 )
283- return reg ;
284-
285- reg &= MII_M1011_PHY_SRC_DOWNSHIFT_MASK ;
286- reg |= ((retries - 1 ) << MII_M1011_PHY_SCR_DOWNSHIFT_SHIFT );
287- if (enable )
288- reg |= MII_M1011_PHY_SCR_DOWNSHIFT_EN ;
289-
290- return phy_write (phydev , MII_M1011_PHY_SCR , reg );
291- }
292-
293279static int marvell_config_aneg (struct phy_device * phydev )
294280{
295281 int changed = 0 ;
@@ -658,41 +644,6 @@ static int marvell_config_init(struct phy_device *phydev)
658644 return marvell_of_reg_init (phydev );
659645}
660646
661- static int m88e1116r_config_init (struct phy_device * phydev )
662- {
663- int err ;
664-
665- err = genphy_soft_reset (phydev );
666- if (err < 0 )
667- return err ;
668-
669- msleep (500 );
670-
671- err = marvell_set_page (phydev , MII_MARVELL_COPPER_PAGE );
672- if (err < 0 )
673- return err ;
674-
675- err = marvell_set_polarity (phydev , phydev -> mdix_ctrl );
676- if (err < 0 )
677- return err ;
678-
679- err = marvell_set_downshift (phydev , true, 8 );
680- if (err < 0 )
681- return err ;
682-
683- if (phy_interface_is_rgmii (phydev )) {
684- err = m88e1121_config_aneg_rgmii_delays (phydev );
685- if (err < 0 )
686- return err ;
687- }
688-
689- err = genphy_soft_reset (phydev );
690- if (err < 0 )
691- return err ;
692-
693- return marvell_config_init (phydev );
694- }
695-
696647static int m88e3016_config_init (struct phy_device * phydev )
697648{
698649 int ret ;
@@ -833,6 +784,114 @@ static int m88e1111_config_init(struct phy_device *phydev)
833784 return genphy_soft_reset (phydev );
834785}
835786
787+ static int m88e1111_get_downshift (struct phy_device * phydev , u8 * data )
788+ {
789+ int val , cnt , enable ;
790+
791+ val = phy_read (phydev , MII_M1011_PHY_SCR );
792+ if (val < 0 )
793+ return val ;
794+
795+ enable = FIELD_GET (MII_M1011_PHY_SCR_DOWNSHIFT_EN , val );
796+ cnt = FIELD_GET (MII_M1011_PHY_SRC_DOWNSHIFT_MASK , val ) + 1 ;
797+
798+ * data = enable ? cnt : DOWNSHIFT_DEV_DISABLE ;
799+
800+ return 0 ;
801+ }
802+
803+ static int m88e1111_set_downshift (struct phy_device * phydev , u8 cnt )
804+ {
805+ int val ;
806+
807+ if (cnt > MII_M1011_PHY_SCR_DOWNSHIFT_MAX )
808+ return - E2BIG ;
809+
810+ if (!cnt )
811+ return phy_clear_bits (phydev , MII_M1011_PHY_SCR ,
812+ MII_M1011_PHY_SCR_DOWNSHIFT_EN );
813+
814+ val = MII_M1011_PHY_SCR_DOWNSHIFT_EN ;
815+ val |= FIELD_PREP (MII_M1011_PHY_SRC_DOWNSHIFT_MASK , cnt - 1 );
816+
817+ return phy_modify (phydev , MII_M1011_PHY_SCR ,
818+ MII_M1011_PHY_SCR_DOWNSHIFT_EN |
819+ MII_M1011_PHY_SRC_DOWNSHIFT_MASK ,
820+ val );
821+ }
822+
823+ static int m88e1111_get_tunable (struct phy_device * phydev ,
824+ struct ethtool_tunable * tuna , void * data )
825+ {
826+ switch (tuna -> id ) {
827+ case ETHTOOL_PHY_DOWNSHIFT :
828+ return m88e1111_get_downshift (phydev , data );
829+ default :
830+ return - EOPNOTSUPP ;
831+ }
832+ }
833+
834+ static int m88e1111_set_tunable (struct phy_device * phydev ,
835+ struct ethtool_tunable * tuna , const void * data )
836+ {
837+ switch (tuna -> id ) {
838+ case ETHTOOL_PHY_DOWNSHIFT :
839+ return m88e1111_set_downshift (phydev , * (const u8 * )data );
840+ default :
841+ return - EOPNOTSUPP ;
842+ }
843+ }
844+
845+ static void m88e1111_link_change_notify (struct phy_device * phydev )
846+ {
847+ int status ;
848+
849+ if (phydev -> state != PHY_RUNNING )
850+ return ;
851+
852+ /* we may be on fiber page currently */
853+ status = phy_read_paged (phydev , MII_MARVELL_COPPER_PAGE ,
854+ MII_M1011_PHY_SSR );
855+
856+ if (status > 0 && status & MII_M1011_PHY_SSR_DOWNSHIFT )
857+ phydev_warn (phydev , "Downshift occurred! Cabling may be defective.\n" );
858+ }
859+
860+ static int m88e1116r_config_init (struct phy_device * phydev )
861+ {
862+ int err ;
863+
864+ err = genphy_soft_reset (phydev );
865+ if (err < 0 )
866+ return err ;
867+
868+ msleep (500 );
869+
870+ err = marvell_set_page (phydev , MII_MARVELL_COPPER_PAGE );
871+ if (err < 0 )
872+ return err ;
873+
874+ err = marvell_set_polarity (phydev , phydev -> mdix_ctrl );
875+ if (err < 0 )
876+ return err ;
877+
878+ err = m88e1111_set_downshift (phydev , 8 );
879+ if (err < 0 )
880+ return err ;
881+
882+ if (phy_interface_is_rgmii (phydev )) {
883+ err = m88e1121_config_aneg_rgmii_delays (phydev );
884+ if (err < 0 )
885+ return err ;
886+ }
887+
888+ err = genphy_soft_reset (phydev );
889+ if (err < 0 )
890+ return err ;
891+
892+ return marvell_config_init (phydev );
893+ }
894+
836895static int m88e1318_config_init (struct phy_device * phydev )
837896{
838897 if (phy_interrupt_is_valid (phydev )) {
@@ -1117,6 +1176,8 @@ static int m88e1540_get_tunable(struct phy_device *phydev,
11171176 switch (tuna -> id ) {
11181177 case ETHTOOL_PHY_FAST_LINK_DOWN :
11191178 return m88e1540_get_fld (phydev , data );
1179+ case ETHTOOL_PHY_DOWNSHIFT :
1180+ return m88e1111_get_downshift (phydev , data );
11201181 default :
11211182 return - EOPNOTSUPP ;
11221183 }
@@ -1128,6 +1189,8 @@ static int m88e1540_set_tunable(struct phy_device *phydev,
11281189 switch (tuna -> id ) {
11291190 case ETHTOOL_PHY_FAST_LINK_DOWN :
11301191 return m88e1540_set_fld (phydev , data );
1192+ case ETHTOOL_PHY_DOWNSHIFT :
1193+ return m88e1111_set_downshift (phydev , * (const u8 * )data );
11311194 default :
11321195 return - EOPNOTSUPP ;
11331196 }
@@ -2220,6 +2283,9 @@ static struct phy_driver marvell_drivers[] = {
22202283 .get_sset_count = marvell_get_sset_count ,
22212284 .get_strings = marvell_get_strings ,
22222285 .get_stats = marvell_get_stats ,
2286+ .get_tunable = m88e1111_get_tunable ,
2287+ .set_tunable = m88e1111_set_tunable ,
2288+ .link_change_notify = m88e1111_link_change_notify ,
22232289 },
22242290 {
22252291 .phy_id = MARVELL_PHY_ID_88E1318S ,
@@ -2359,6 +2425,7 @@ static struct phy_driver marvell_drivers[] = {
23592425 .get_stats = marvell_get_stats ,
23602426 .get_tunable = m88e1540_get_tunable ,
23612427 .set_tunable = m88e1540_set_tunable ,
2428+ .link_change_notify = m88e1111_link_change_notify ,
23622429 },
23632430 {
23642431 .phy_id = MARVELL_PHY_ID_88E1545 ,
@@ -2421,6 +2488,7 @@ static struct phy_driver marvell_drivers[] = {
24212488 .get_stats = marvell_get_stats ,
24222489 .get_tunable = m88e1540_get_tunable ,
24232490 .set_tunable = m88e1540_set_tunable ,
2491+ .link_change_notify = m88e1111_link_change_notify ,
24242492 },
24252493};
24262494
0 commit comments