]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
net: ethernet: ti: am65-cpsw: fix up PHY mode for fixed RGMII TX delay
authorMatthias Schiffer <matthias.schiffer@ew.tq-group.com>
Tue, 30 Sep 2025 08:05:11 +0000 (10:05 +0200)
committerTom Rini <trini@konsulko.com>
Fri, 10 Oct 2025 17:07:44 +0000 (11:07 -0600)
The am65-cpsw driver currently sets the SEL_RGMII_IDMODE flag in a MAC's
mode register to enable or disable the TX delay. While this was supported
for earlier generations of the CPSW controller, the datasheets of all
modern TI SoCs using the am65-cpsw MAC state that the TX delay is fixed,
and the SEL_RGMII_IDMODE bit is documented as reserved in most of them.
Furthermore, while it was found that this bit does in fact disable the TX
delay, [1] states that this setting is truly unsupported by TI and not
just undocumented.

Following the clarification of the rgmii* phy-mode values in the Linux
DT bindings in [2], the Linux am65-cpsw driver was changed in [3] to
account for the fixed TX delay by fixing up the mode passed to the PHY
driver; a similar fixup already existed in the TI icssg-prueth driver.
[4] followed up on this by explicitly clearing the SEL_RGMII_IDMODE flag
to handle the case where it is set by the bootloader or other firmware
before Linux.

With the above changes, Device Trees that set the recommended "rgmii-id"
mode are now appearing in Linux 6.17+. Avoid setting the unsupported
SEL_RGMII_IDMODE flag for such Device Trees, and instead fix up the PHY
interface mode, thus aligning the U-Boot driver with the Linux kernel.

[1] https://www.spinics.net/lists/netdev/msg1112647.html
[2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c360eb0c3ccb95306704fd221442283ee82f1f58
[3] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ca13b249f291f4920466638d1adbfb3f9c8db6e9
[4] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a22d3b0d49d411e64ed07e30c2095035ecb30ed2

Signed-off-by: Matthias Schiffer <matthias.schiffer@ew.tq-group.com>
drivers/net/ti/am65-cpsw-nuss.c

index 2aa7e5e3a30daa087fb8c1622c164220429f8454..7a88f76fd0992d72c9c5a1945295f3e9c8f19789 100644 (file)
@@ -234,14 +234,11 @@ out:
 #define AM65_GMII_SEL_MODE_RGMII       2
 #define AM65_GMII_SEL_MODE_SGMII       3
 
-#define AM65_GMII_SEL_RGMII_IDMODE     BIT(4)
-
 static int am65_cpsw_gmii_sel_k3(struct am65_cpsw_priv *priv,
                                 phy_interface_t phy_mode)
 {
        struct udevice *dev = priv->dev;
        u32 offset, reg, phandle;
-       bool rgmii_id = false;
        fdt_addr_t gmii_sel;
        u32 mode = 0;
        ofnode node;
@@ -278,12 +275,6 @@ static int am65_cpsw_gmii_sel_k3(struct am65_cpsw_priv *priv,
                mode = AM65_GMII_SEL_MODE_RGMII;
                break;
 
-       case PHY_INTERFACE_MODE_RGMII_ID:
-       case PHY_INTERFACE_MODE_RGMII_TXID:
-               mode = AM65_GMII_SEL_MODE_RGMII;
-               rgmii_id = true;
-               break;
-
        case PHY_INTERFACE_MODE_SGMII:
                mode = AM65_GMII_SEL_MODE_SGMII;
                break;
@@ -298,9 +289,6 @@ static int am65_cpsw_gmii_sel_k3(struct am65_cpsw_priv *priv,
                break;
        };
 
-       if (rgmii_id)
-               mode |= AM65_GMII_SEL_RGMII_IDMODE;
-
        reg = mode;
        dev_dbg(dev, "gmii_sel PHY mode: %u, new gmii_sel: %08x\n",
                phy_mode, reg);
@@ -630,7 +618,7 @@ static int am65_cpsw_phy_init(struct udevice *dev)
        u32 supported = PHY_GBIT_FEATURES;
        int ret = 0;
 
-       phydev = dm_eth_phy_connect(dev);
+       phydev = dm_eth_phy_connect_interface(dev, pdata->phy_interface);
        if (!phydev) {
                dev_err(dev, "phy_connect() failed\n");
                return -ENODEV;
@@ -657,9 +645,28 @@ static int am65_cpsw_ofdata_parse_phy(struct udevice *dev)
        dev_read_u32(dev, "reg", &priv->port_id);
 
        pdata->phy_interface = dev_read_phy_mode(dev);
-       if (pdata->phy_interface == PHY_INTERFACE_MODE_NA) {
+
+       /* CPSW controllers supported by this driver have a fixed internal TX
+        * delay in RGMII mode. Fix up PHY mode to account for this and warn
+        * about Device Trees that claim to have a TX delay on the PCB.
+        */
+       switch (pdata->phy_interface) {
+       case PHY_INTERFACE_MODE_RGMII_ID:
+               pdata->phy_interface = PHY_INTERFACE_MODE_RGMII_RXID;
+               break;
+       case PHY_INTERFACE_MODE_RGMII_TXID:
+               pdata->phy_interface = PHY_INTERFACE_MODE_RGMII;
+               break;
+       case PHY_INTERFACE_MODE_RGMII:
+       case PHY_INTERFACE_MODE_RGMII_RXID:
+               dev_warn(dev,
+                        "RGMII mode without internal TX delay unsupported; please fix your Device Tree\n");
+               break;
+       case PHY_INTERFACE_MODE_NA:
                dev_err(dev, "Invalid PHY mode, port %u\n", priv->port_id);
                return -EINVAL;
+       default:
+               break;
        }
 
        dev_read_u32(dev, "max-speed", (u32 *)&pdata->max_speed);