diff --git a/drivers/net/phy/mscc/mscc.h b/drivers/net/phy/mscc/mscc.h index d1b8bbe8acca3c74fbf0ccad5c5cd823769d1b9e..25729302714c895ce91852fc4714b44d22be5e36 100644 --- a/drivers/net/phy/mscc/mscc.h +++ b/drivers/net/phy/mscc/mscc.h @@ -161,6 +161,20 @@ enum rgmii_rx_clock_delay { /* Extended Page 2 Registers */ #define MSCC_PHY_CU_PMD_TX_CNTL 16 +#define MSCC_PHY_RGMII_SETTINGS 18 +#define RGMII_SKEW_RX_POS 1 +#define RGMII_SKEW_TX_POS 4 + +/* RGMII skew values, in ns */ +#define VSC8584_RGMII_SKEW_0_2 0 +#define VSC8584_RGMII_SKEW_0_8 1 +#define VSC8584_RGMII_SKEW_1_1 2 +#define VSC8584_RGMII_SKEW_1_7 3 +#define VSC8584_RGMII_SKEW_2_0 4 +#define VSC8584_RGMII_SKEW_2_3 5 +#define VSC8584_RGMII_SKEW_2_6 6 +#define VSC8584_RGMII_SKEW_3_4 7 + #define MSCC_PHY_RGMII_CNTL 20 #define RGMII_RX_CLK_DELAY_MASK 0x0070 #define RGMII_RX_CLK_DELAY_POS 4 diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c index 86bb5c3c911adb9d926c6778cbd756aa4bb95ec9..5d78732de70208af149f22e102cfed7ade819ee7 100644 --- a/drivers/net/phy/mscc/mscc_main.c +++ b/drivers/net/phy/mscc/mscc_main.c @@ -1288,6 +1288,32 @@ static bool vsc8584_is_pkg_init(struct phy_device *phydev, bool reversed) return false; } +static void vsc8584_rgmii_set_skews(struct phy_device *phydev) +{ + u32 skew_rx, skew_tx; + + /* We first set the Rx and Tx skews to their default value in h/w + * (0.2 ns). + */ + skew_rx = VSC8584_RGMII_SKEW_0_2; + skew_tx = VSC8584_RGMII_SKEW_0_2; + + /* We then set the skews based on the interface mode. */ + if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || + phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) + skew_rx = VSC8584_RGMII_SKEW_2_0; + if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || + phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) + skew_tx = VSC8584_RGMII_SKEW_2_0; + + /* Finally we apply the skews configuration. */ + phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2, + MSCC_PHY_RGMII_SETTINGS, + (0x7 << RGMII_SKEW_RX_POS) | (0x7 << RGMII_SKEW_TX_POS), + (skew_rx << RGMII_SKEW_RX_POS) | + (skew_tx << RGMII_SKEW_TX_POS)); +} + static int vsc8584_config_init(struct phy_device *phydev) { struct vsc8531_private *vsc8531 = phydev->priv; @@ -1422,6 +1448,9 @@ static int vsc8584_config_init(struct phy_device *phydev) if (ret) return ret; + if (phy_interface_is_rgmii(phydev)) + vsc8584_rgmii_set_skews(phydev); + ret = genphy_soft_reset(phydev); if (ret) return ret;