[PATCH] net: zynq_gem: Don't hardcode the MDC clock divisor

Michal Simek michal.simek at amd.com
Fri Jun 23 14:55:47 CEST 2023



On 6/19/23 05:49, Venkatesh Yadav Abbarapu wrote:
> As per spec MDC must not exceed 2.5MHz, read the pclk clock
> from the device tree and update the MDC clock divisor.
> GEM devices support larger clock divisors and have a different
> range of divisors.  Program the MDIO clock divisors based on
> the clock rate of the pclk clock.
> 
> Signed-off-by: Venkatesh Yadav Abbarapu <venkatesh.abbarapu at amd.com>
> ---
>   drivers/net/zynq_gem.c | 57 ++++++++++++++++++++++++++++++++++++------
>   1 file changed, 49 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c
> index 211b2c6e55..f3cdfb0275 100644
> --- a/drivers/net/zynq_gem.c
> +++ b/drivers/net/zynq_gem.c
> @@ -30,6 +30,7 @@
>   #include <asm/arch/hardware.h>
>   #include <asm/arch/sys_proto.h>
>   #include <dm/device_compat.h>
> +#include <linux/bitfield.h>
>   #include <linux/bitops.h>
>   #include <linux/err.h>
>   #include <linux/errno.h>
> @@ -67,11 +68,6 @@
>   #define ZYNQ_GEM_NWCFG_FSREM		0x00020000 /* FCS removal */
>   #define ZYNQ_GEM_NWCFG_SGMII_ENBL	0x08000000 /* SGMII Enable */
>   #define ZYNQ_GEM_NWCFG_PCS_SEL		0x00000800 /* PCS select */
> -#ifdef CONFIG_ARM64
> -#define ZYNQ_GEM_NWCFG_MDCCLKDIV	0x00100000 /* Div pclk by 64, max 160MHz */
> -#else
> -#define ZYNQ_GEM_NWCFG_MDCCLKDIV	0x000c0000 /* Div pclk by 48, max 120MHz */
> -#endif
>   
>   #ifdef CONFIG_ARM64
>   # define ZYNQ_GEM_DBUS_WIDTH	(1 << 21) /* 64 bit bus */
> @@ -81,8 +77,7 @@
>   
>   #define ZYNQ_GEM_NWCFG_INIT		(ZYNQ_GEM_DBUS_WIDTH | \
>   					ZYNQ_GEM_NWCFG_FDEN | \
> -					ZYNQ_GEM_NWCFG_FSREM | \
> -					ZYNQ_GEM_NWCFG_MDCCLKDIV)
> +					ZYNQ_GEM_NWCFG_FSREM)
>   
>   #define ZYNQ_GEM_NWSR_MDIOIDLE_MASK	0x00000004 /* PHY management idle */
>   
> @@ -141,6 +136,18 @@
>   
>   #define RXCLK_EN		BIT(0)
>   
> +/* GEM specific constants for CLK. */
> +#define GEM_CLK_DIV8		0
> +#define GEM_CLK_DIV16		1
> +#define GEM_CLK_DIV32		2
> +#define GEM_CLK_DIV48		3
> +#define GEM_CLK_DIV64		4
> +#define GEM_CLK_DIV96		5
> +#define GEM_CLK_DIV128		6
> +#define GEM_CLK_DIV224		7
> +
> +#define GEM_MDC_SET(val)	FIELD_PREP(GENMASK(20, 18), val)
> +
>   /* Device registers */
>   struct zynq_gem_regs {
>   	u32 nwctrl; /* 0x0 - Network Control reg */
> @@ -220,6 +227,7 @@ struct zynq_gem_priv {
>   	struct mii_dev *bus;
>   	struct clk rx_clk;
>   	struct clk tx_clk;
> +	struct clk pclk;
>   	u32 max_speed;
>   	bool int_pcs;
>   	bool dma_64bit;
> @@ -352,6 +360,32 @@ static int zynq_phy_init(struct udevice *dev)
>   	return phy_config(priv->phydev);
>   }
>   
> +static u32 gem_mdc_clk_div(struct zynq_gem_priv *priv)
> +{
> +	u32 config;
> +	unsigned long pclk_hz;
> +
> +	pclk_hz = clk_get_rate(&priv->pclk);
> +	if (pclk_hz <= 20000000)
> +		config = GEM_MDC_SET(GEM_CLK_DIV8);
> +	else if (pclk_hz <= 40000000)
> +		config = GEM_MDC_SET(GEM_CLK_DIV16);
> +	else if (pclk_hz <= 80000000)
> +		config = GEM_MDC_SET(GEM_CLK_DIV32);
> +	else if (pclk_hz <= 120000000)
> +		config = GEM_MDC_SET(GEM_CLK_DIV48);
> +	else if (pclk_hz <= 160000000)
> +		config = GEM_MDC_SET(GEM_CLK_DIV64);
> +	else if (pclk_hz <= 240000000)
> +		config = GEM_MDC_SET(GEM_CLK_DIV96);
> +	else if (pclk_hz <= 320000000)
> +		config = GEM_MDC_SET(GEM_CLK_DIV128);
> +	else
> +		config = GEM_MDC_SET(GEM_CLK_DIV224);
> +
> +	return config;
> +}
> +
>   static int zynq_gem_init(struct udevice *dev)
>   {
>   	u32 i, nwconfig;
> @@ -460,7 +494,8 @@ static int zynq_gem_init(struct udevice *dev)
>   		return -1;
>   	}
>   
> -	nwconfig = ZYNQ_GEM_NWCFG_INIT;
> +	nwconfig = gem_mdc_clk_div(priv);
> +	nwconfig |= ZYNQ_GEM_NWCFG_INIT;
>   
>   	/*
>   	 * Set SGMII enable PCS selection only if internal PCS/PMA
> @@ -828,6 +863,12 @@ static int zynq_gem_probe(struct udevice *dev)
>   		}
>   	}
>   
> +	ret = clk_get_by_name(dev, "pclk", &priv->pclk);
> +	if (ret < 0) {
> +		dev_err(dev, "failed to get pclk clock\n");
> +		goto err2;
> +	}
> +
>   	if (IS_ENABLED(CONFIG_DM_ETH_PHY))
>   		priv->bus = eth_phy_get_mdio_bus(dev);
>   

Applied.
M


More information about the U-Boot mailing list