Message ID | 20230619034922.24019-1-venkatesh.abbarapu@amd.com |
---|---|
State | Accepted |
Commit | 22836f088d6027ee8e4bde17abbf71644a8388f5 |
Delegated to: | Michal Simek |
Headers | show |
Series | net: zynq_gem: Don't hardcode the MDC clock divisor | expand |
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@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
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);
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@amd.com> --- drivers/net/zynq_gem.c | 57 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 8 deletions(-)