7171#define MII_VSC73XX_DOWNSHIFT_MAX 5
7272#define MII_VSC73XX_DOWNSHIFT_INVAL 1
7373
74+ /* VSC73XX PHY_BYPASS_CTRL register*/
75+ #define MII_VSC73XX_PHY_BYPASS_CTRL MII_DCOUNTER
76+ #define MII_VSC73XX_PBC_TX_DIS BIT(15)
77+ #define MII_VSC73XX_PBC_FOR_SPD_AUTO_MDIX_DIS BIT(7)
78+ #define MII_VSC73XX_PBC_PAIR_SWAP_DIS BIT(5)
79+ #define MII_VSC73XX_PBC_POL_INV_DIS BIT(4)
80+ #define MII_VSC73XX_PBC_PARALLEL_DET_DIS BIT(3)
81+ #define MII_VSC73XX_PBC_AUTO_NP_EXCHANGE_DIS BIT(1)
82+
83+ /* VSC73XX PHY_AUX_CTRL_STAT register */
84+ #define MII_VSC73XX_PHY_AUX_CTRL_STAT MII_NCONFIG
85+ #define MII_VSC73XX_PACS_NO_MDI_X_IND BIT(13)
86+
7487/* Vitesse VSC8601 Extended PHY Control Register 1 */
7588#define MII_VSC8601_EPHY_CTL 0x17
7689#define MII_VSC8601_EPHY_CTL_RGMII_SKEW (1 << 8)
@@ -219,6 +232,9 @@ static void vsc73xx_config_init(struct phy_device *phydev)
219232
220233 /* Enable downshift by default */
221234 vsc73xx_set_downshift (phydev , MII_VSC73XX_DOWNSHIFT_MAX );
235+
236+ /* Set Auto MDI-X by default */
237+ phydev -> mdix_ctrl = ETH_TP_MDI_AUTO ;
222238}
223239
224240static int vsc738x_config_init (struct phy_device * phydev )
@@ -319,6 +335,75 @@ static int vsc739x_config_init(struct phy_device *phydev)
319335 return 0 ;
320336}
321337
338+ static int vsc73xx_mdix_set (struct phy_device * phydev , u8 mdix )
339+ {
340+ int ret ;
341+ u16 val ;
342+
343+ val = phy_read (phydev , MII_VSC73XX_PHY_BYPASS_CTRL );
344+
345+ switch (mdix ) {
346+ case ETH_TP_MDI :
347+ val |= MII_VSC73XX_PBC_FOR_SPD_AUTO_MDIX_DIS |
348+ MII_VSC73XX_PBC_PAIR_SWAP_DIS |
349+ MII_VSC73XX_PBC_POL_INV_DIS ;
350+ break ;
351+ case ETH_TP_MDI_X :
352+ /* When MDI-X auto configuration is disabled, is possible
353+ * to force only MDI mode. Let's use autoconfig for forced
354+ * MDIX mode.
355+ */
356+ case ETH_TP_MDI_AUTO :
357+ val &= ~(MII_VSC73XX_PBC_FOR_SPD_AUTO_MDIX_DIS |
358+ MII_VSC73XX_PBC_PAIR_SWAP_DIS |
359+ MII_VSC73XX_PBC_POL_INV_DIS );
360+ break ;
361+ default :
362+ return - EINVAL ;
363+ }
364+
365+ ret = phy_write (phydev , MII_VSC73XX_PHY_BYPASS_CTRL , val );
366+ if (ret )
367+ return ret ;
368+
369+ return genphy_restart_aneg (phydev );
370+ }
371+
372+ static int vsc73xx_config_aneg (struct phy_device * phydev )
373+ {
374+ int ret ;
375+
376+ ret = vsc73xx_mdix_set (phydev , phydev -> mdix_ctrl );
377+ if (ret )
378+ return ret ;
379+
380+ return genphy_config_aneg (phydev );
381+ }
382+
383+ static int vsc73xx_mdix_get (struct phy_device * phydev , u8 * mdix )
384+ {
385+ u16 reg_val ;
386+
387+ reg_val = phy_read (phydev , MII_VSC73XX_PHY_AUX_CTRL_STAT );
388+ if (reg_val & MII_VSC73XX_PACS_NO_MDI_X_IND )
389+ * mdix = ETH_TP_MDI ;
390+ else
391+ * mdix = ETH_TP_MDI_X ;
392+
393+ return 0 ;
394+ }
395+
396+ static int vsc73xx_read_status (struct phy_device * phydev )
397+ {
398+ int ret ;
399+
400+ ret = vsc73xx_mdix_get (phydev , & phydev -> mdix );
401+ if (ret < 0 )
402+ return ret ;
403+
404+ return genphy_read_status (phydev );
405+ }
406+
322407/* This adds a skew for both TX and RX clocks, so the skew should only be
323408 * applied to "rgmii-id" interfaces. It may not work as expected
324409 * on "rgmii-txid", "rgmii-rxid" or "rgmii" interfaces.
@@ -516,6 +601,8 @@ static struct phy_driver vsc82xx_driver[] = {
516601 .phy_id_mask = 0x000ffff0 ,
517602 /* PHY_GBIT_FEATURES */
518603 .config_init = vsc738x_config_init ,
604+ .config_aneg = vsc73xx_config_aneg ,
605+ .read_status = vsc73xx_read_status ,
519606 .read_page = vsc73xx_read_page ,
520607 .write_page = vsc73xx_write_page ,
521608 .get_tunable = vsc73xx_get_tunable ,
@@ -526,6 +613,8 @@ static struct phy_driver vsc82xx_driver[] = {
526613 .phy_id_mask = 0x000ffff0 ,
527614 /* PHY_GBIT_FEATURES */
528615 .config_init = vsc738x_config_init ,
616+ .config_aneg = vsc73xx_config_aneg ,
617+ .read_status = vsc73xx_read_status ,
529618 .read_page = vsc73xx_read_page ,
530619 .write_page = vsc73xx_write_page ,
531620 .get_tunable = vsc73xx_get_tunable ,
@@ -536,6 +625,8 @@ static struct phy_driver vsc82xx_driver[] = {
536625 .phy_id_mask = 0x000ffff0 ,
537626 /* PHY_GBIT_FEATURES */
538627 .config_init = vsc739x_config_init ,
628+ .config_aneg = vsc73xx_config_aneg ,
629+ .read_status = vsc73xx_read_status ,
539630 .read_page = vsc73xx_read_page ,
540631 .write_page = vsc73xx_write_page ,
541632 .get_tunable = vsc73xx_get_tunable ,
@@ -546,6 +637,8 @@ static struct phy_driver vsc82xx_driver[] = {
546637 .phy_id_mask = 0x000ffff0 ,
547638 /* PHY_GBIT_FEATURES */
548639 .config_init = vsc739x_config_init ,
640+ .config_aneg = vsc73xx_config_aneg ,
641+ .read_status = vsc73xx_read_status ,
549642 .read_page = vsc73xx_read_page ,
550643 .write_page = vsc73xx_write_page ,
551644 .get_tunable = vsc73xx_get_tunable ,
0 commit comments