From c3dd3b1e76e0ff20ce97e99bc8d1f3152eb177b9 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Fri, 27 Mar 2026 08:43:28 +0000 Subject: [PATCH 01/15] net: stmmac: qcom-ethqos: remove ethqos_configure() ethqos_configure() does nothing more than indirect via ethqos->configure_func, and is only called from ethqos_fix_mac_speed() just below. Move the indirect call into ethqos_fix_mac_speed(). Signed-off-by: Russell King (Oracle) Tested-by: Mohd Ayaan Anwar Link: https://patch.msgid.link/E1w62mu-0000000E3Bq-15wa@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index 3ccf20fdf52a..502f2b184a87 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -623,18 +623,12 @@ static void ethqos_configure_sgmii(struct qcom_ethqos *ethqos, ethqos_pcs_set_inband(priv, interface == PHY_INTERFACE_MODE_SGMII); } -static void ethqos_configure(struct qcom_ethqos *ethqos, - phy_interface_t interface, int speed) -{ - return ethqos->configure_func(ethqos, interface, speed); -} - static void ethqos_fix_mac_speed(void *priv, phy_interface_t interface, int speed, unsigned int mode) { struct qcom_ethqos *ethqos = priv; - ethqos_configure(ethqos, interface, speed); + ethqos->configure_func(ethqos, interface, speed); } static int qcom_ethqos_serdes_powerup(struct net_device *ndev, void *priv) From 673416fb5b410b536f45e738ac34e482efd94e81 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Fri, 27 Mar 2026 08:43:33 +0000 Subject: [PATCH 02/15] net: stmmac: qcom-ethqos: pass ethqos to ethqos_pcs_set_inband() Rather than getting the stmmac_priv pointer in ethqos_configure_sgmii(), move it into ethqos_pcs_set_inband() and pass the struct qcom_ethqos pointer instead. Signed-off-by: Russell King (Oracle) Tested-by: Mohd Ayaan Anwar Link: https://patch.msgid.link/E1w62mz-0000000E3Bx-1Xd8@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- .../net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index 502f2b184a87..b9cfcf32cebc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -590,8 +590,11 @@ static void ethqos_configure_rgmii(struct qcom_ethqos *ethqos, ethqos_rgmii_macro_init(ethqos, speed); } -static void ethqos_pcs_set_inband(struct stmmac_priv *priv, bool enable) +static void ethqos_pcs_set_inband(struct qcom_ethqos *ethqos, bool enable) { + struct net_device *dev = platform_get_drvdata(ethqos->pdev); + struct stmmac_priv *priv = netdev_priv(dev); + stmmac_pcs_ctrl_ane(priv, enable, 0); } @@ -601,9 +604,6 @@ static void ethqos_pcs_set_inband(struct stmmac_priv *priv, bool enable) static void ethqos_configure_sgmii(struct qcom_ethqos *ethqos, phy_interface_t interface, int speed) { - struct net_device *dev = platform_get_drvdata(ethqos->pdev); - struct stmmac_priv *priv = netdev_priv(dev); - switch (speed) { case SPEED_2500: case SPEED_1000: @@ -620,7 +620,7 @@ static void ethqos_configure_sgmii(struct qcom_ethqos *ethqos, break; } - ethqos_pcs_set_inband(priv, interface == PHY_INTERFACE_MODE_SGMII); + ethqos_pcs_set_inband(ethqos, interface == PHY_INTERFACE_MODE_SGMII); } static void ethqos_fix_mac_speed(void *priv, phy_interface_t interface, From e9ed46a0b129d743f6ca008101b055fdd2e5ea2e Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Fri, 27 Mar 2026 08:43:38 +0000 Subject: [PATCH 03/15] net: stmmac: qcom-ethqos: eliminate configure_func Since ethqos_fix_mac_speed() is called via a function pointer, and only indirects via the configure_func function pointer, eliminate this unnecessary indirection. Signed-off-by: Russell King (Oracle) Tested-by: Mohd Ayaan Anwar Link: https://patch.msgid.link/E1w62n4-0000000E3C3-251S@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- .../stmicro/stmmac/dwmac-qcom-ethqos.c | 35 ++++++++----------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index b9cfcf32cebc..f7e3a2b8803f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -100,9 +100,6 @@ struct ethqos_emac_driver_data { struct qcom_ethqos { struct platform_device *pdev; void __iomem *rgmii_base; - void (*configure_func)(struct qcom_ethqos *ethqos, - phy_interface_t interface, int speed); - struct clk *link_clk; struct phy *serdes_phy; phy_interface_t phy_mode; @@ -521,13 +518,17 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) return 0; } -static void ethqos_configure_rgmii(struct qcom_ethqos *ethqos, - phy_interface_t interface, int speed) +static void ethqos_fix_mac_speed_rgmii(void *bsp_priv, + phy_interface_t interface, int speed, + unsigned int mode) { - struct device *dev = ðqos->pdev->dev; + struct qcom_ethqos *ethqos = bsp_priv; + struct device *dev; unsigned int i; u32 val; + dev = ðqos->pdev->dev; + /* Reset to POR values and enable clk */ for (i = 0; i < ethqos->num_rgmii_por; i++) rgmii_writel(ethqos, ethqos->rgmii_por[i].value, @@ -601,9 +602,12 @@ static void ethqos_pcs_set_inband(struct qcom_ethqos *ethqos, bool enable) /* On interface toggle MAC registers gets reset. * Configure MAC block for SGMII on ethernet phy link up */ -static void ethqos_configure_sgmii(struct qcom_ethqos *ethqos, - phy_interface_t interface, int speed) +static void ethqos_fix_mac_speed_sgmii(void *bsp_priv, + phy_interface_t interface, int speed, + unsigned int mode) { + struct qcom_ethqos *ethqos = bsp_priv; + switch (speed) { case SPEED_2500: case SPEED_1000: @@ -623,14 +627,6 @@ static void ethqos_configure_sgmii(struct qcom_ethqos *ethqos, ethqos_pcs_set_inband(ethqos, interface == PHY_INTERFACE_MODE_SGMII); } -static void ethqos_fix_mac_speed(void *priv, phy_interface_t interface, - int speed, unsigned int mode) -{ - struct qcom_ethqos *ethqos = priv; - - ethqos->configure_func(ethqos, interface, speed); -} - static int qcom_ethqos_serdes_powerup(struct net_device *ndev, void *priv) { struct qcom_ethqos *ethqos = priv; @@ -687,7 +683,7 @@ static int ethqos_clks_config(void *priv, bool enabled) /* Enable functional clock to prevent DMA reset to timeout due * to lacking PHY clock after the hardware block has been power * cycled. The actual configuration will be adjusted once - * ethqos_fix_mac_speed() is invoked. + * ethqos' fix_mac_speed() method is invoked. */ qcom_ethqos_set_sgmii_loopback(ethqos, true); ethqos_set_func_clk_en(ethqos); @@ -753,11 +749,11 @@ static int qcom_ethqos_probe(struct platform_device *pdev) case PHY_INTERFACE_MODE_RGMII_ID: case PHY_INTERFACE_MODE_RGMII_RXID: case PHY_INTERFACE_MODE_RGMII_TXID: - ethqos->configure_func = ethqos_configure_rgmii; + plat_dat->fix_mac_speed = ethqos_fix_mac_speed_rgmii; break; case PHY_INTERFACE_MODE_2500BASEX: case PHY_INTERFACE_MODE_SGMII: - ethqos->configure_func = ethqos_configure_sgmii; + plat_dat->fix_mac_speed = ethqos_fix_mac_speed_sgmii; plat_dat->mac_finish = ethqos_mac_finish_serdes; break; default: @@ -805,7 +801,6 @@ static int qcom_ethqos_probe(struct platform_device *pdev) plat_dat->bsp_priv = ethqos; plat_dat->set_clk_tx_rate = ethqos_set_clk_tx_rate; - plat_dat->fix_mac_speed = ethqos_fix_mac_speed; plat_dat->dump_debug_regs = rgmii_dump; plat_dat->ptp_clk_freq_config = ethqos_ptp_clk_freq_config; plat_dat->core_type = DWMAC_CORE_GMAC4; From 426ce4677e8101996d1ff230464ea696eba2d853 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Fri, 27 Mar 2026 08:43:43 +0000 Subject: [PATCH 04/15] net: stmmac: qcom-ethqos: move detection of invalid RGMII speed Move detection of invalid RGMII speeds (which will never be triggered) before the switch() to allow register modifications that are common to all speeds to be moved out of the switch. Signed-off-by: Russell King (Oracle) Tested-by: Mohd Ayaan Anwar Link: https://patch.msgid.link/E1w62n9-0000000E3C9-2Zkr@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index f7e3a2b8803f..d19331067459 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -397,6 +397,11 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) /* Select RGMII, write 0 to interface select */ rgmii_clrmask(ethqos, RGMII_CONFIG_INTF_SEL, RGMII_IO_MACRO_CONFIG); + if (speed != SPEED_1000 && speed != SPEED_100 && speed != SPEED_10) { + dev_err(dev, "Invalid speed %d\n", speed); + return -EINVAL; + } + switch (speed) { case SPEED_1000: rgmii_setmask(ethqos, RGMII_CONFIG_DDR_MODE, @@ -510,9 +515,6 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, loopback, RGMII_IO_MACRO_CONFIG); break; - default: - dev_err(dev, "Invalid speed %d\n", speed); - return -EINVAL; } return 0; From 6be23c4c636acc08c691e2b7371f341b13de23f7 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Fri, 27 Mar 2026 08:43:48 +0000 Subject: [PATCH 05/15] net: stmmac: qcom-ethqos: move RGMII_CONFIG_DDR_MODE RGMII_CONFIG_DDR_MODE is always set irrespective of the speed. Move this out of the switch. Signed-off-by: Russell King (Oracle) Tested-by: Mohd Ayaan Anwar Link: https://patch.msgid.link/E1w62nE-0000000E3CF-331r@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index d19331067459..34d9a6b2d023 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -402,10 +402,10 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) return -EINVAL; } + rgmii_setmask(ethqos, RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG); + switch (speed) { case SPEED_1000: - rgmii_setmask(ethqos, RGMII_CONFIG_DDR_MODE, - RGMII_IO_MACRO_CONFIG); rgmii_clrmask(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN, RGMII_IO_MACRO_CONFIG); rgmii_setmask(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL, @@ -443,8 +443,6 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) break; case SPEED_100: - rgmii_setmask(ethqos, RGMII_CONFIG_DDR_MODE, - RGMII_IO_MACRO_CONFIG); rgmii_setmask(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN, RGMII_IO_MACRO_CONFIG); rgmii_clrmask(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL, @@ -481,8 +479,6 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) break; case SPEED_10: - rgmii_setmask(ethqos, RGMII_CONFIG_DDR_MODE, - RGMII_IO_MACRO_CONFIG); rgmii_setmask(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN, RGMII_IO_MACRO_CONFIG); rgmii_clrmask(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL, From 82d5fdc82a33bea93baec4795e835b016d2dc87e Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Fri, 27 Mar 2026 08:43:53 +0000 Subject: [PATCH 06/15] net: stmmac: qcom-ethqos: move 1G vs 100M/10M RGMII settings Move RGMII_CONFIG_BYPASS_TX_ID_EN, RGMII_CONFIG_POS_NEG_DATA_SEL and RGMII_CONFIG_PROG_SWAP. There are two states for these: one group for 1G, and the logical inversion for 100M and 10M. Move this out of the switch into an if-else clause. Signed-off-by: Russell King (Oracle) Tested-by: Mohd Ayaan Anwar Link: https://patch.msgid.link/E1w62nJ-0000000E3CL-3YSr@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- .../stmicro/stmmac/dwmac-qcom-ethqos.c | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index 34d9a6b2d023..e9d8c8a7146a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -404,14 +404,24 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) rgmii_setmask(ethqos, RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG); - switch (speed) { - case SPEED_1000: + if (speed == SPEED_1000) { rgmii_clrmask(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN, RGMII_IO_MACRO_CONFIG); rgmii_setmask(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL, RGMII_IO_MACRO_CONFIG); rgmii_setmask(ethqos, RGMII_CONFIG_PROG_SWAP, RGMII_IO_MACRO_CONFIG); + } else { + rgmii_setmask(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN, + RGMII_IO_MACRO_CONFIG); + rgmii_clrmask(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL, + RGMII_IO_MACRO_CONFIG); + rgmii_clrmask(ethqos, RGMII_CONFIG_PROG_SWAP, + RGMII_IO_MACRO_CONFIG); + } + + switch (speed) { + case SPEED_1000: rgmii_clrmask(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, RGMII_IO_MACRO_CONFIG2); @@ -443,12 +453,6 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) break; case SPEED_100: - rgmii_setmask(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN, - RGMII_IO_MACRO_CONFIG); - rgmii_clrmask(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL, - RGMII_IO_MACRO_CONFIG); - rgmii_clrmask(ethqos, RGMII_CONFIG_PROG_SWAP, - RGMII_IO_MACRO_CONFIG); rgmii_clrmask(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, RGMII_IO_MACRO_CONFIG2); rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, @@ -479,12 +483,6 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) break; case SPEED_10: - rgmii_setmask(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN, - RGMII_IO_MACRO_CONFIG); - rgmii_clrmask(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL, - RGMII_IO_MACRO_CONFIG); - rgmii_clrmask(ethqos, RGMII_CONFIG_PROG_SWAP, - RGMII_IO_MACRO_CONFIG); rgmii_clrmask(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, RGMII_IO_MACRO_CONFIG2); rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, From dd07f2f9149a885ea2d8d19f95439227ec558106 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Fri, 27 Mar 2026 08:43:58 +0000 Subject: [PATCH 07/15] net: stmmac: qcom-ethqos: move two more RGMII_IO_MACRO_CONFIG2 out RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL is always cleared, and RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN is always updated with the phase shift in each path through the switch, so these are independent of the speed. Move them out. Signed-off-by: Russell King (Oracle) Tested-by: Mohd Ayaan Anwar Link: https://patch.msgid.link/E1w62nO-0000000E3CR-445p@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- .../stmicro/stmmac/dwmac-qcom-ethqos.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index e9d8c8a7146a..ab6554f58214 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -420,13 +420,13 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) RGMII_IO_MACRO_CONFIG); } + rgmii_clrmask(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, + RGMII_IO_MACRO_CONFIG2); + rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, phase_shift, + RGMII_IO_MACRO_CONFIG2); + switch (speed) { case SPEED_1000: - rgmii_clrmask(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, - RGMII_IO_MACRO_CONFIG2); - - rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, - phase_shift, RGMII_IO_MACRO_CONFIG2); rgmii_clrmask(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, RGMII_IO_MACRO_CONFIG2); rgmii_setmask(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, @@ -453,10 +453,6 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) break; case SPEED_100: - rgmii_clrmask(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, - RGMII_IO_MACRO_CONFIG2); - rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, - phase_shift, RGMII_IO_MACRO_CONFIG2); rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_2, FIELD_PREP(RGMII_CONFIG_MAX_SPD_PRG_2, 1), RGMII_IO_MACRO_CONFIG); @@ -483,10 +479,6 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) break; case SPEED_10: - rgmii_clrmask(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, - RGMII_IO_MACRO_CONFIG2); - rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, - phase_shift, RGMII_IO_MACRO_CONFIG2); rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_9, FIELD_PREP(RGMII_CONFIG_MAX_SPD_PRG_9, 19), RGMII_IO_MACRO_CONFIG); From 8b19a91844203db70584a2e56ad97d117e2c0277 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Fri, 27 Mar 2026 08:44:04 +0000 Subject: [PATCH 08/15] net: stmmac: qcom-ethqos: move 100M/10M speed programming Move the speed programming for 100M and 10M out of the switch. There is no programming done for 1G speed. It looks like there are two fields, 7:6 which are programemd to '1' to select a /2 divisor for 100M, and bits 16:8 which are programmed to '19' to select a /20 divisor. Signed-off-by: Russell King (Oracle) Tested-by: Mohd Ayaan Anwar Link: https://patch.msgid.link/E1w62nU-0000000E3CX-0KF9@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- .../ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index ab6554f58214..2751def922df 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -425,6 +425,15 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, phase_shift, RGMII_IO_MACRO_CONFIG2); + if (speed == SPEED_100) + rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_2, + FIELD_PREP(RGMII_CONFIG_MAX_SPD_PRG_2, 1), + RGMII_IO_MACRO_CONFIG); + else if (speed == SPEED_10) + rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_9, + FIELD_PREP(RGMII_CONFIG_MAX_SPD_PRG_9, 19), + RGMII_IO_MACRO_CONFIG); + switch (speed) { case SPEED_1000: rgmii_clrmask(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, @@ -453,9 +462,6 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) break; case SPEED_100: - rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_2, - FIELD_PREP(RGMII_CONFIG_MAX_SPD_PRG_2, 1), - RGMII_IO_MACRO_CONFIG); rgmii_clrmask(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, RGMII_IO_MACRO_CONFIG2); @@ -479,9 +485,6 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) break; case SPEED_10: - rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_9, - FIELD_PREP(RGMII_CONFIG_MAX_SPD_PRG_9, 19), - RGMII_IO_MACRO_CONFIG); rgmii_clrmask(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, RGMII_IO_MACRO_CONFIG2); if (ethqos->has_emac_ge_3) From dae1de3df3e17b98fe78c4b1ba26322b03cd9f46 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Fri, 27 Mar 2026 08:44:09 +0000 Subject: [PATCH 09/15] net: stmmac: qcom-ethqos: move RGMII_CONFIG2_RSVD_CONFIG15 out All paths through the switch clear the RGMII_CONFIG2_RSVD_CONFIG15 field. move it out of the switch statement. Signed-off-by: Russell King (Oracle) Tested-by: Mohd Ayaan Anwar Link: https://patch.msgid.link/E1w62nZ-0000000E3Ce-0lyP@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- .../net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index 2751def922df..13f4df0a90d7 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -434,10 +434,11 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) FIELD_PREP(RGMII_CONFIG_MAX_SPD_PRG_9, 19), RGMII_IO_MACRO_CONFIG); + rgmii_clrmask(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, + RGMII_IO_MACRO_CONFIG2); + switch (speed) { case SPEED_1000: - rgmii_clrmask(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, - RGMII_IO_MACRO_CONFIG2); rgmii_setmask(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, RGMII_IO_MACRO_CONFIG2); @@ -462,9 +463,6 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) break; case SPEED_100: - rgmii_clrmask(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, - RGMII_IO_MACRO_CONFIG2); - if (ethqos->has_emac_ge_3) rgmii_setmask(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, RGMII_IO_MACRO_CONFIG2); @@ -485,8 +483,6 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) break; case SPEED_10: - rgmii_clrmask(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, - RGMII_IO_MACRO_CONFIG2); if (ethqos->has_emac_ge_3) rgmii_setmask(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, RGMII_IO_MACRO_CONFIG2); From 432c8a9f5528e362cc42de46901f25373a3a9928 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Fri, 27 Mar 2026 08:44:14 +0000 Subject: [PATCH 10/15] net: stmmac: qcom-ethqos: move RGMII_CONFIG2_RX_PROG_SWAP Move RGMII_CONFIG2_RX_PROG_SWAP out of the switch. 1G speed always sets this field. 100M and 10M sets it for has_emac_ge_3 devices, otherwise it is cleared. Signed-off-by: Russell King (Oracle) Tested-by: Mohd Ayaan Anwar Link: https://patch.msgid.link/E1w62ne-0000000E3Ck-1Haf@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- .../stmicro/stmmac/dwmac-qcom-ethqos.c | 21 ++++++------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index 13f4df0a90d7..b4c61cb24e1d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -437,11 +437,15 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) rgmii_clrmask(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, RGMII_IO_MACRO_CONFIG2); - switch (speed) { - case SPEED_1000: + if (speed == SPEED_1000 || ethqos->has_emac_ge_3) rgmii_setmask(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, RGMII_IO_MACRO_CONFIG2); + else + rgmii_clrmask(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, + RGMII_IO_MACRO_CONFIG2); + switch (speed) { + case SPEED_1000: /* PRG_RCLK_DLY = TCXO period * TCXO_CYCLES_CNT / 2 * RX delay ns, * in practice this becomes PRG_RCLK_DLY = 52 * 4 / 2 * RX delay ns */ @@ -463,13 +467,6 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) break; case SPEED_100: - if (ethqos->has_emac_ge_3) - rgmii_setmask(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, - RGMII_IO_MACRO_CONFIG2); - else - rgmii_clrmask(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, - RGMII_IO_MACRO_CONFIG2); - /* Write 0x5 to PRG_RCLK_DLY_CODE */ rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE, FIELD_PREP(SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE, @@ -483,12 +480,6 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) break; case SPEED_10: - if (ethqos->has_emac_ge_3) - rgmii_setmask(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, - RGMII_IO_MACRO_CONFIG2); - else - rgmii_clrmask(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, - RGMII_IO_MACRO_CONFIG2); /* Write 0x5 to PRG_RCLK_DLY_CODE */ rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE, FIELD_PREP(SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE, From 439a27f21ecc1c7c59d6e00c7c6b9be380f66a64 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Fri, 27 Mar 2026 08:44:19 +0000 Subject: [PATCH 11/15] net: stmmac: qcom-ethqos: finally eliminate the switch Move the RCLK delay configuration out of the switch, which just leaves the RGMII_CONFIG_LOOPBACK_EN setting in all three paths. This makes it trivial to eliminate the switch. Signed-off-by: Russell King (Oracle) Tested-by: Mohd Ayaan Anwar Link: https://patch.msgid.link/E1w62nj-0000000E3Cq-1lPL@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- .../stmicro/stmmac/dwmac-qcom-ethqos.c | 47 +++++++------------ 1 file changed, 16 insertions(+), 31 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index b4c61cb24e1d..7690ae0bb008 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -444,8 +444,18 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) rgmii_clrmask(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, RGMII_IO_MACRO_CONFIG2); - switch (speed) { - case SPEED_1000: + if (speed != SPEED_1000) { + /* Write 0x5 to PRG_RCLK_DLY_CODE */ + rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE, + FIELD_PREP(SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE, + 5), SDCC_HC_REG_DDR_CONFIG); + + rgmii_setmask(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY, + SDCC_HC_REG_DDR_CONFIG); + + rgmii_setmask(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN, + SDCC_HC_REG_DDR_CONFIG); + } else { /* PRG_RCLK_DLY = TCXO period * TCXO_CYCLES_CNT / 2 * RX delay ns, * in practice this becomes PRG_RCLK_DLY = 52 * 4 / 2 * RX delay ns */ @@ -460,39 +470,14 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) FIELD_PREP(SDCC_DDR_CONFIG_PRG_RCLK_DLY, 57), SDCC_HC_REG_DDR_CONFIG); } + rgmii_setmask(ethqos, SDCC_DDR_CONFIG_PRG_DLY_EN, SDCC_HC_REG_DDR_CONFIG); - rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, - loopback, RGMII_IO_MACRO_CONFIG); - break; - - case SPEED_100: - /* Write 0x5 to PRG_RCLK_DLY_CODE */ - rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE, - FIELD_PREP(SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE, - 5), SDCC_HC_REG_DDR_CONFIG); - rgmii_setmask(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY, - SDCC_HC_REG_DDR_CONFIG); - rgmii_setmask(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN, - SDCC_HC_REG_DDR_CONFIG); - rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, - loopback, RGMII_IO_MACRO_CONFIG); - break; - - case SPEED_10: - /* Write 0x5 to PRG_RCLK_DLY_CODE */ - rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE, - FIELD_PREP(SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE, - 5), SDCC_HC_REG_DDR_CONFIG); - rgmii_setmask(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY, - SDCC_HC_REG_DDR_CONFIG); - rgmii_setmask(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN, - SDCC_HC_REG_DDR_CONFIG); - rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, - loopback, RGMII_IO_MACRO_CONFIG); - break; } + rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, loopback, + RGMII_IO_MACRO_CONFIG); + return 0; } From 3df0e86f8f8d708a820f7844f1a5830839f78efd Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Fri, 27 Mar 2026 08:44:24 +0000 Subject: [PATCH 12/15] net: stmmac: qcom-ethqos: simplify prg_rclk_dly programming Rather than coding the entire register update twice with different values, use a local variable to specify the value and have one register update statement that uses this local variable. This results in neater code. Signed-off-by: Russell King (Oracle) Tested-by: Mohd Ayaan Anwar Link: https://patch.msgid.link/E1w62no-0000000E3Cw-2EmH@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- .../net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index 7690ae0bb008..580deec1dc30 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -374,6 +374,7 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos) static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) { struct device *dev = ðqos->pdev->dev; + unsigned int prg_rclk_dly; int phase_shift; int loopback; @@ -461,16 +462,16 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) */ if (ethqos->has_emac_ge_3) { /* 0.9 ns */ - rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY, - FIELD_PREP(SDCC_DDR_CONFIG_PRG_RCLK_DLY, - 115), SDCC_HC_REG_DDR_CONFIG); + prg_rclk_dly = 115; } else { /* 1.8 ns */ - rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY, - FIELD_PREP(SDCC_DDR_CONFIG_PRG_RCLK_DLY, - 57), SDCC_HC_REG_DDR_CONFIG); + prg_rclk_dly = 57; } + rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY, + FIELD_PREP(SDCC_DDR_CONFIG_PRG_RCLK_DLY, + prg_rclk_dly), SDCC_HC_REG_DDR_CONFIG); + rgmii_setmask(ethqos, SDCC_DDR_CONFIG_PRG_DLY_EN, SDCC_HC_REG_DDR_CONFIG); } From 67343aa24e595ac2522d9f7e2daba7ec29f32926 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Fri, 27 Mar 2026 08:44:29 +0000 Subject: [PATCH 13/15] net: stmmac: qcom-ethqos: move loopback decision next to reg update Move the loopback decision next to the register update, and make the local variable unsigned. As a result, there is now no need for the comment referring to the programming being later. Signed-off-by: Russell King (Oracle) Tested-by: Mohd Ayaan Anwar Link: https://patch.msgid.link/E1w62nt-0000000E3D2-2fWk@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- .../ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index 580deec1dc30..9dae40c27903 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -374,9 +374,8 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos) static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) { struct device *dev = ðqos->pdev->dev; - unsigned int prg_rclk_dly; + unsigned int prg_rclk_dly, loopback; int phase_shift; - int loopback; /* Determine if the PHY adds a 2 ns TX delay or the MAC handles it */ if (ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_ID || @@ -389,12 +388,6 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) rgmii_clrmask(ethqos, RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG2); - /* Determine if this platform wants loopback enabled after programming */ - if (ethqos->rgmii_config_loopback_en) - loopback = RGMII_CONFIG_LOOPBACK_EN; - else - loopback = 0; - /* Select RGMII, write 0 to interface select */ rgmii_clrmask(ethqos, RGMII_CONFIG_INTF_SEL, RGMII_IO_MACRO_CONFIG); @@ -476,6 +469,11 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) SDCC_HC_REG_DDR_CONFIG); } + if (ethqos->rgmii_config_loopback_en) + loopback = RGMII_CONFIG_LOOPBACK_EN; + else + loopback = 0; + rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, loopback, RGMII_IO_MACRO_CONFIG); From 2d350a892aad3b3dfdcfc170e7681f4095808a0c Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Fri, 27 Mar 2026 08:44:34 +0000 Subject: [PATCH 14/15] net: stmmac: qcom-ethqos: correct prg_rclk_dly comment The comment for calculating the prg_rclk_dly value is incorrect as it omits the brackets around the divisor. Add the brackets to allow the reader to correctly evaluate the value. Validated with the values given in the driver. Signed-off-by: Russell King (Oracle) Tested-by: Mohd Ayaan Anwar Link: https://patch.msgid.link/E1w62ny-0000000E3D8-38Yp@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index 9dae40c27903..667676c29a95 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -450,8 +450,10 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) rgmii_setmask(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN, SDCC_HC_REG_DDR_CONFIG); } else { - /* PRG_RCLK_DLY = TCXO period * TCXO_CYCLES_CNT / 2 * RX delay ns, - * in practice this becomes PRG_RCLK_DLY = 52 * 4 / 2 * RX delay ns + /* PRG_RCLK_DLY = TCXO period * TCXO_CYCLES_CNT / + * (2 * RX delay ns), + * in practice this becomes PRG_RCLK_DLY = 52 * 4 / + * (2 * RX delay ns) */ if (ethqos->has_emac_ge_3) { /* 0.9 ns */ From 7f9f301660051353282e579affcd40e7075ab223 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Fri, 27 Mar 2026 08:44:39 +0000 Subject: [PATCH 15/15] net: stmmac: qcom-ethqos: move phase_shift to register update site Move the determination of the phase shift enable alongside the register update, and make "phase_shift" unsigned. Signed-off-by: Russell King (Oracle) Tested-by: Mohd Ayaan Anwar Link: https://patch.msgid.link/E1w62o3-0000000E3DE-3Vf8@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- .../ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index 667676c29a95..ad3a983d2a08 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -375,14 +375,7 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) { struct device *dev = ðqos->pdev->dev; unsigned int prg_rclk_dly, loopback; - int phase_shift; - - /* Determine if the PHY adds a 2 ns TX delay or the MAC handles it */ - if (ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_ID || - ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_TXID) - phase_shift = 0; - else - phase_shift = RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN; + unsigned int phase_shift; /* Disable loopback mode */ rgmii_clrmask(ethqos, RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN, @@ -416,6 +409,14 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) rgmii_clrmask(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, RGMII_IO_MACRO_CONFIG2); + + /* Determine if the PHY adds a 2 ns TX delay or the MAC handles it */ + if (ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_ID || + ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_TXID) + phase_shift = 0; + else + phase_shift = RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN; + rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, phase_shift, RGMII_IO_MACRO_CONFIG2);