[PATCH] net: ti: am65-cpsw-nuss: allow skipping phy_config() for speed

Nora Schiffer nora.schiffer at ew.tq-group.com
Thu Jun 11 14:37:18 CEST 2026


On Thu, 2026-06-11 at 17:36 +0530, Siddharth Vadapalli wrote:
> Currently, phy_config() is invoked every time during am65_cpsw_start()
> which guarantees robustness and also allows recovering from link
> failures by resetting the Ethernet PHY. While this is beneficial for
> system stability, for use-cases where speed is prioritized over
> robustness, the existing implementation is insufficient.

Hi Siddharth,

I wonder if making this configurable is actually the best approach, and if we
can't find a way to make phy_config a no-op when there is already a valid link.
Is phy_config() actually needed to recover at all? I would expect regular
Ethernet PHYs to reestablish the link by themselves - I guess 1000BASE-T1
Single-Pair Ethernet might need this?

Some background:

In our vendor branch of U-Boot, we have reverted commit 05dc050059d2 ("net: ti:
am65-cpsw-nuss: invoke phy_config() in driver's .start callback") because it
made PXE boot with U-Boot's default config path selection pretty much unusable:
U-Boot would try a long list of TFTP paths based on different identifiers like
IP addresses, each time using a new TFTP context, thus resetting the PHY and
reestablishing the link dozens of times before arriving at the correct path.

Another solution for the PXE problem might be to refactor the code not to
shutdown and startup the Ethernet for each attempt, but that would not help
scripts that use separate tftp commands or similar for a sequence of file
transfers.

Best,
Nora


> 
> To support use-cases prioritizing speed while continuing to retain the
> existing behavior for robustness, sample the environment variable named
> "am65_cpsw_phy_config_once" to determine whether phy_config() should
> continue to be invoked once per invocation of am65_cpsw_start(), OR, it
> should only be invoked across invocations. Since the environment variable
> is not set by default, robustness is prioritized over speed. Use-cases
> which require speed can set "am65_cpsw_phy_config_once" to any of:
> '1', 'y', 'Y', 't' and 'T'
> based on the implementation of the env_get_yesno() helper function.
> 
> Signed-off-by: Siddharth Vadapalli <s-vadapalli at ti.com>
> ---
> 
> Hello,
> 
> This patch is based on commit
> 3cdce049f90 erge tag 'u-boot-rockchip-20260610' of https://source.denx.de/u-boot/custodians/u-boot-rockchip
> of the master branch of U-Boot.
> 
> Patch has been tested on J784S4 EVM which uses MCU CPSW2G for Ethernet
> functionality. The following test logs demonstrate the default behavior
> being retained in the absence of 'am65_cpsw_phy_config_once' environment
> variable being set to a logical true, followed by setting the environment
> variable to a logical true ('y') and observing the PHY Autonegotiation
> process being skipped, followed by setting the environment variable to a
> logical false ('n' but could be anything that isn't logically true based
> on the env_get_yesno() helper function) and verifying that we go back to
> the default behavior of performing PHY Autonegotiation again:
> https://gist.github.com/Siddharth-Vadapalli-at-TI/6229b5a3b7d80cd0c2037a6364406bbe
> 
> Regards,
> Siddharth.
> 
>  drivers/net/ti/am65-cpsw-nuss.c | 32 +++++++++++++++++++++++++++-----
>  1 file changed, 27 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/ti/am65-cpsw-nuss.c b/drivers/net/ti/am65-cpsw-nuss.c
> index 84a3e44ecbc..a5cca52f674 100644
> --- a/drivers/net/ti/am65-cpsw-nuss.c
> +++ b/drivers/net/ti/am65-cpsw-nuss.c
> @@ -18,6 +18,7 @@
>  #include <dm/pinctrl.h>
>  #include <dma-uclass.h>
>  #include <dm/of_access.h>
> +#include <env.h>
>  #include <miiphy.h>
>  #include <net.h>
>  #include <phy.h>
> @@ -104,6 +105,7 @@ struct am65_cpsw_port {
>  	fdt_addr_t	macsl_base;
>  	bool		disabled;
>  	u32		mac_control;
> +	bool            phy_configured;
>  };
>  
>  struct am65_cpsw_common {
> @@ -313,7 +315,7 @@ static int am65_cpsw_start(struct udevice *dev)
>  	struct am65_cpsw_port *port = &common->ports[priv->port_id];
>  	struct am65_cpsw_port *port0 = &common->ports[0];
>  	struct ti_udma_drv_chan_cfg_data *dma_rx_cfg_data;
> -	int ret, i;
> +	int ret, i, skip_phy_config_env;
>  
>  	if (common->started)
>  		return 0;
> @@ -426,10 +428,30 @@ static int am65_cpsw_start(struct udevice *dev)
>  		       port->port_sgmii_base + AM65_CPSW_SGMII_CONTROL_REG);
>  	}
>  
> -	ret = phy_config(priv->phydev);
> -	if (ret < 0) {
> -		dev_err(dev, "phy_config failed: %d", ret);
> -		goto err_dis_rx;
> +	/*
> +	 * Invoking phy_config() every time that am65_cpsw_start() is executed will
> +	 * make the link robust. However, it delays every networking command such as
> +	 * 'dhcp' and 'tftp'. For use-cases that prioritize speed over robustness,
> +	 * phy_config() should be invoked only once. To support both use-cases,
> +	 * sample the environment variable 'am65_cpsw_phy_config_once' to switch
> +	 * between:
> +	 * a) Invoke phy_config() every time - Default behavior for robustness
> +	 * b) Invoke phy_config() once per driver probe - User configurable behavior
> +	 *    for speed.
> +	 */
> +	skip_phy_config_env = env_get_yesno("am65_cpsw_phy_config_once");
> +
> +	/* If environment variable is not defined, assume it to be false. */
> +	if (skip_phy_config_env == -1)
> +		skip_phy_config_env = 0;
> +
> +	if (!port->phy_configured || !skip_phy_config_env) {
> +		ret = phy_config(priv->phydev);
> +		if (ret < 0) {
> +			dev_err(dev, "phy_config failed: %d", ret);
> +			goto err_dis_rx;
> +		}
> +		port->phy_configured = true;
>  	}
>  
>  	ret = phy_startup(priv->phydev);

-- 
TQ-Systems GmbH | Mühlstraße 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht München, HRB 105018
Geschäftsführer: Detlef Schneider, Rüdiger Stahl, Stefan Schneider
https://www.tq-group.com/


More information about the U-Boot mailing list