diff mbox series

[2/2] net: phy: mscc: sync rx/tx delay settings with Linux on vsc85xx

Message ID 20200609133740.1421966-2-heiko@sntech.de
State New
Headers show
Series [1/2] net: phy: mscc: make clock-output configurable on vsc85xx | expand

Commit Message

Heiko Stuebner June 9, 2020, 1:37 p.m. UTC
From: Heiko Stuebner <heiko.stuebner at theobroma-systems.com>

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 at theobroma-systems.com>
---
 drivers/net/phy/mscc.c | 70 +++++++++++++++++++++++++++---------------
 1 file changed, 46 insertions(+), 24 deletions(-)

Comments

Philipp Tomsich June 9, 2020, 1:39 p.m. UTC | #1
> On 09.06.2020, at 15:37, Heiko Stuebner <heiko at sntech.de> wrote:
> 
> From: Heiko Stuebner <heiko.stuebner at theobroma-systems.com>
> 
> 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 at theobroma-systems.com>

Reviewed-by: Philipp Tomsich <philipp.tomsich at theobroma-systems.com>
Tom Rini Oct. 1, 2020, 2:09 p.m. UTC | #2
On Tue, Jun 09, 2020 at 03:37:40PM +0200, Heiko Stuebner wrote:

> From: Heiko Stuebner <heiko.stuebner@theobroma-systems.com>

> 

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


Applied to u-boot/next, thanks!

-- 
Tom
diff mbox series

Patch

diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c
index 64e9093827..d1a643cf5a 100644
--- a/drivers/net/phy/mscc.c
+++ b/drivers/net/phy/mscc.c
@@ -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,