Skip to content

Commit cf740e3

Browse files
CHKDSK88kuba-moo
authored andcommitted
net: phy: vitesse: implement MDI-X configuration in vsc73xx
This commit introduces MDI-X configuration support in vsc73xx phys. Vsc73xx supports only auto mode or forced MDI. Vsc73xx have auto MDI-X disabled by default in forced speed mode. This commit enables it. Signed-off-by: Pawel Dembicki <[email protected]> Reviewed-by: Andrew Lunn <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent ec4d817 commit cf740e3

File tree

1 file changed

+93
-0
lines changed

1 file changed

+93
-0
lines changed

drivers/net/phy/vitesse.c

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,19 @@
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

224240
static 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

Comments
 (0)