net: phy: dp83822: Fix RGMII TX delay configuration
authorTim Pambor <tp@osasysteme.de>
Tue, 5 Mar 2024 11:06:08 +0000 (12:06 +0100)
committerJakub Kicinski <kuba@kernel.org>
Sat, 9 Mar 2024 04:33:44 +0000 (20:33 -0800)
The logic for enabling the TX clock shift is inverse of enabling the RX
clock shift. The TX clock shift is disabled when DP83822_TX_CLK_SHIFT is
set. Correct the current behavior and always write the delay configuration
to ensure consistent delay settings regardless of bootloader configuration.

Reference: https://www.ti.com/lit/ds/symlink/dp83822i.pdf p. 69

Fixes: 8095295292b5 ("net: phy: DP83822: Add setting the fixed internal delay")
Signed-off-by: Tim Pambor <tp@osasysteme.de>
Link: https://lore.kernel.org/r/20240305110608.104072-1-tp@osasysteme.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/phy/dp83822.c

index b7cb71817780ce8c2c25b05f231f5b24ba1d612c..29e1cbea6dc0c3180cf465b2f2ce11d077e1a344 100644 (file)
@@ -380,7 +380,7 @@ static int dp83822_config_init(struct phy_device *phydev)
 {
        struct dp83822_private *dp83822 = phydev->priv;
        struct device *dev = &phydev->mdio.dev;
-       int rgmii_delay;
+       int rgmii_delay = 0;
        s32 rx_int_delay;
        s32 tx_int_delay;
        int err = 0;
@@ -390,30 +390,33 @@ static int dp83822_config_init(struct phy_device *phydev)
                rx_int_delay = phy_get_internal_delay(phydev, dev, NULL, 0,
                                                      true);
 
-               if (rx_int_delay <= 0)
-                       rgmii_delay = 0;
-               else
-                       rgmii_delay = DP83822_RX_CLK_SHIFT;
+               /* Set DP83822_RX_CLK_SHIFT to enable rx clk internal delay */
+               if (rx_int_delay > 0)
+                       rgmii_delay |= DP83822_RX_CLK_SHIFT;
 
                tx_int_delay = phy_get_internal_delay(phydev, dev, NULL, 0,
                                                      false);
+
+               /* Set DP83822_TX_CLK_SHIFT to disable tx clk internal delay */
                if (tx_int_delay <= 0)
-                       rgmii_delay &= ~DP83822_TX_CLK_SHIFT;
-               else
                        rgmii_delay |= DP83822_TX_CLK_SHIFT;
 
-               if (rgmii_delay) {
-                       err = phy_set_bits_mmd(phydev, DP83822_DEVADDR,
-                                              MII_DP83822_RCSR, rgmii_delay);
-                       if (err)
-                               return err;
-               }
+               err = phy_modify_mmd(phydev, DP83822_DEVADDR, MII_DP83822_RCSR,
+                                    DP83822_RX_CLK_SHIFT | DP83822_TX_CLK_SHIFT, rgmii_delay);
+               if (err)
+                       return err;
+
+               err = phy_set_bits_mmd(phydev, DP83822_DEVADDR,
+                                      MII_DP83822_RCSR, DP83822_RGMII_MODE_EN);
 
-               phy_set_bits_mmd(phydev, DP83822_DEVADDR,
-                                       MII_DP83822_RCSR, DP83822_RGMII_MODE_EN);
+               if (err)
+                       return err;
        } else {
-               phy_clear_bits_mmd(phydev, DP83822_DEVADDR,
-                                       MII_DP83822_RCSR, DP83822_RGMII_MODE_EN);
+               err = phy_clear_bits_mmd(phydev, DP83822_DEVADDR,
+                                        MII_DP83822_RCSR, DP83822_RGMII_MODE_EN);
+
+               if (err)
+                       return err;
        }
 
        if (dp83822->fx_enabled) {