]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
net: phy: mscc: sync rx/tx delay settings with Linux on vsc85xx
authorHeiko Stuebner <heiko.stuebner@theobroma-systems.com>
Tue, 9 Jun 2020 13:37:40 +0000 (15:37 +0200)
committerTom Rini <trini@konsulko.com>
Wed, 30 Sep 2020 20:48:18 +0000 (16:48 -0400)
The Linux kernel does set the clock delays to
- 0.2 ns (their default, and lowest, hardware value) if delays should
  not be enabled
- 2.0 ns (which causes the data to be sampled at exactly half way between
  clock transitions at 1000 Mbps) if delays should be enabled
depending on the interface mode

See https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/net/phy/mscc/mscc_main.c#n523

So instead of using arbitrary delay values like now, mimic this behaviour.

The behaviour is the same for all of vsc8530/8531/8540/8541 so move that
to a shared function while at it.

Signed-off-by: Heiko Stuebner <heiko.stuebner@theobroma-systems.com>
Reviewed-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
drivers/net/phy/mscc.c

index 64e9093827a5816249d3d2d66baad5bc781f5f2f..d1a643cf5a0ced833458b12f4be96e5bcf1e328b 100644 (file)
@@ -1176,6 +1176,9 @@ static int vsc8531_vsc8541_mac_config(struct phy_device *phydev)
                rx_clk_out = RX_CLK_OUT_NORMAL;
                break;
 
+       case PHY_INTERFACE_MODE_RGMII_TXID:
+       case PHY_INTERFACE_MODE_RGMII_RXID:
+       case PHY_INTERFACE_MODE_RGMII_ID:
        case PHY_INTERFACE_MODE_RGMII:
                /* Set Reg23.12:11=2 */
                mac_if = MAC_IF_SELECTION_RGMII;
@@ -1259,13 +1262,43 @@ static int vsc8531_vsc8541_clkout_config(struct phy_device *phydev)
        return 0;
 }
 
+static int vsc8531_vsc8541_clk_skew_config(struct phy_device *phydev)
+{
+       enum vsc_phy_rgmii_skew rx_clk_skew = VSC_PHY_RGMII_DELAY_200_PS;
+       enum vsc_phy_rgmii_skew tx_clk_skew = VSC_PHY_RGMII_DELAY_200_PS;
+       u16 reg_val;
+
+       if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID ||
+           phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
+               rx_clk_skew = VSC_PHY_RGMII_DELAY_2000_PS;
+
+       if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID ||
+           phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
+               tx_clk_skew = VSC_PHY_RGMII_DELAY_2000_PS;
+
+       phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+                 MSCC_PHY_PAGE_EXT2);
+       reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG);
+
+       /* Reg20E2 - Update RGMII RX_Clk Skews. */
+       reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS,
+                                  RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew);
+       /* Reg20E2 - Update RGMII TX_Clk Skews. */
+       reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS,
+                                  RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew);
+
+       phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val);
+       phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+                 MSCC_PHY_PAGE_STD);
+
+       return 0;
+}
+
 static int vsc8531_config(struct phy_device *phydev)
 {
        int  retval = -EINVAL;
        u16  reg_val;
        u16  rmii_clk_out;
-       enum vsc_phy_rgmii_skew  rx_clk_skew = VSC_PHY_RGMII_DELAY_1700_PS;
-       enum vsc_phy_rgmii_skew  tx_clk_skew = VSC_PHY_RGMII_DELAY_800_PS;
        enum vsc_phy_clk_slew    edge_rate = VSC_PHY_CLK_SLEW_RATE_4;
 
        /* For VSC8530/31 and VSC8540/41 the init scripts are the same */
@@ -1275,6 +1308,9 @@ static int vsc8531_config(struct phy_device *phydev)
        switch (phydev->interface) {
        case PHY_INTERFACE_MODE_RMII:
        case PHY_INTERFACE_MODE_RGMII:
+       case PHY_INTERFACE_MODE_RGMII_TXID:
+       case PHY_INTERFACE_MODE_RGMII_RXID:
+       case PHY_INTERFACE_MODE_RGMII_ID:
                retval = vsc8531_vsc8541_mac_config(phydev);
                if (retval != 0)
                        return retval;
@@ -1291,19 +1327,12 @@ static int vsc8531_config(struct phy_device *phydev)
        /* Default RMII Clk Output to 0=OFF/1=ON  */
        rmii_clk_out = 0;
 
+       retval = vsc8531_vsc8541_clk_skew_config(phydev);
+       if (retval != 0)
+               return retval;
+
        phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
                  MSCC_PHY_PAGE_EXT2);
-       reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG);
-
-       /* Reg20E2 - Update RGMII RX_Clk Skews. */
-       reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS,
-                                  RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew);
-       /* Reg20E2 - Update RGMII TX_Clk Skews. */
-       reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS,
-                                  RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew);
-
-       phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val);
-
        reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL);
        /* Reg27E2 - Update Clk Slew Rate. */
        reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS,
@@ -1329,8 +1358,6 @@ static int vsc8541_config(struct phy_device *phydev)
        int  retval = -EINVAL;
        u16  reg_val;
        u16  rmii_clk_out;
-       enum vsc_phy_rgmii_skew  rx_clk_skew = VSC_PHY_RGMII_DELAY_1700_PS;
-       enum vsc_phy_rgmii_skew  tx_clk_skew = VSC_PHY_RGMII_DELAY_800_PS;
        enum vsc_phy_clk_slew    edge_rate = VSC_PHY_CLK_SLEW_RATE_4;
 
        /* For VSC8530/31 and VSC8540/41 the init scripts are the same */
@@ -1358,17 +1385,12 @@ static int vsc8541_config(struct phy_device *phydev)
        /* Default RMII Clk Output to 0=OFF/1=ON  */
        rmii_clk_out = 0;
 
+       retval = vsc8531_vsc8541_clk_skew_config(phydev);
+       if (retval != 0)
+               return retval;
+
        phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
                  MSCC_PHY_PAGE_EXT2);
-       reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG);
-       /* Reg20E2 - Update RGMII RX_Clk Skews. */
-       reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS,
-                                  RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew);
-       /* Reg20E2 - Update RGMII TX_Clk Skews. */
-       reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS,
-                                  RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew);
-       phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val);
-
        reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL);
        /* Reg27E2 - Update Clk Slew Rate. */
        reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS,