[PATCH] net: zynq_gem: Wait for SGMII PCS link in zynq_gem_init()

Sean Anderson sean.anderson at seco.com
Tue Jan 10 19:28:23 CET 2023


On 1/10/23 05:38, Stefan Roese wrote:
> In our system using ZynqMP with an external SGMII PHY it's necessary
> to wait for the PCS link and auto negotiation to finish before the xfer
> starts. Otherwise the first packet(s) might get dropped, resulting in a
> delay at the start of the ethernet transfers.
> 
> This patch adds the necessary code at the end of zynq_gem_init()
> including a minimal delay of 10ms which fixes problems of dropped
> first packages.
> 
> Signed-off-by: Stefan Roese <sr at denx.de>
> Cc: Michal Simek <michal.simek at amd.com>
> Cc: T Karthik Reddy <t.karthik.reddy at amd.com>
> Cc: Ramon Fried <rfried.dev at gmail.com>
> ---
>  drivers/net/zynq_gem.c | 32 +++++++++++++++++++++++++++++++-
>  1 file changed, 31 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c
> index 507b19b75975..625b0303d6e2 100644
> --- a/drivers/net/zynq_gem.c
> +++ b/drivers/net/zynq_gem.c
> @@ -125,6 +125,10 @@
>   */
>  #define PHY_DETECT_MASK 0x1808
>  
> +/* PCS (SGMII) Link Status */
> +#define ZYNQ_GEM_PCSSTATUS_LINK		BIT(2)
> +#define ZYNQ_GEM_PCSSTATUS_ANEG_COMPL	BIT(5)
> +
>  /* TX BD status masks */
>  #define ZYNQ_GEM_TXBUF_FRMLEN_MASK	0x000007ff
>  #define ZYNQ_GEM_TXBUF_EXHAUSTED	0x08000000
> @@ -164,7 +168,8 @@ struct zynq_gem_regs {
>  	u32 stat[STAT_SIZE]; /* 0x100 - Octects transmitted Low reg */
>  	u32 reserved9[20];
>  	u32 pcscntrl;
> -	u32 rserved12[36];
> +	u32 pcsstatus;
> +	u32 rserved12[35];
>  	u32 dcfg6; /* 0x294 Design config reg6 */
>  	u32 reserved7[106];
>  	u32 transmit_q1_ptr; /* 0x440 - Transmit priority queue 1 */
> @@ -522,6 +527,31 @@ static int zynq_gem_init(struct udevice *dev)
>  			return ret;
>  		}
>  	}
> +
> +	/* Wait for SGMII link */
> +	if (priv->interface == PHY_INTERFACE_MODE_SGMII && priv->int_pcs) {
> +		u32 pcsstatus;
> +
> +		if (priv->phydev->phy_id == PHY_FIXED_ID)
> +			pcsstatus = ZYNQ_GEM_PCSSTATUS_LINK;
> +		else
> +			pcsstatus = ZYNQ_GEM_PCSSTATUS_LINK |
> +				ZYNQ_GEM_PCSSTATUS_ANEG_COMPL;

Use BMSR_LSTATUS/BMSR_ANEGCOMPLETE.

> +
> +		ret = wait_for_bit_le32(&regs->pcsstatus, pcsstatus,
> +					true, 5000, true);
> +		if (ret) {
> +			dev_err(dev, "no PCS (SGMII) link detected\n");

This should be an info or lower, since this is normal behavior when there
is no link partner (e.g. when the cable is unplugged).

--Seam

> +			return ret;
> +		}
> +
> +		/*
> +		 * Some additional minimal delay seems to be needed so that
> +		 * the first packet will be sent correctly
> +		 */
> +		mdelay(10);
> +	}
> +
>  	setbits_le32(&regs->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK |
>  					ZYNQ_GEM_NWCTRL_TXEN_MASK);
>  



More information about the U-Boot mailing list