Message ID | 20161010125704.1058-4-mugunthanvnm@ti.com |
---|---|
State | Superseded |
Delegated to: | Joe Hershberger |
Headers | show |
On Mon, Oct 10, 2016 at 2:57 PM, Mugunthan V N <mugunthanvnm@ti.com> wrote: > cpsw driver supports only selection of phy mode in control module > but control module has more setting like RGMII ID mode selection, > RMII clock source selection. So ported to cpsw-phy-sel driver > from kernel to u-boot. > > Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com> Acked-by: Joe Hershberger <joe.hershberger@ni.com>
On Monday 10 October 2016 06:27 PM, Mugunthan V N wrote: > cpsw driver supports only selection of phy mode in control module > but control module has more setting like RGMII ID mode selection, > RMII clock source selection. So ported to cpsw-phy-sel driver > from kernel to u-boot. > > Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com> > --- > drivers/net/cpsw.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++++----- > include/cpsw.h | 1 + > 2 files changed, 140 insertions(+), 14 deletions(-) > > diff --git a/drivers/net/cpsw.c b/drivers/net/cpsw.c > index d17505e..1441f44 100644 > --- a/drivers/net/cpsw.c > +++ b/drivers/net/cpsw.c > @@ -225,6 +225,18 @@ struct cpdma_chan { > void *hdp, *cp, *rxfree; > }; > > +/* AM33xx SoC specific definitions for the CONTROL port */ > +#define AM33XX_GMII_SEL_MODE_MII 0 > +#define AM33XX_GMII_SEL_MODE_RMII 1 > +#define AM33XX_GMII_SEL_MODE_RGMII 2 > + > +#define AM33XX_GMII_SEL_RGMII1_IDMODE BIT(4) > +#define AM33XX_GMII_SEL_RGMII2_IDMODE BIT(5) > +#define AM33XX_GMII_SEL_RMII1_IO_CLK_EN BIT(6) > +#define AM33XX_GMII_SEL_RMII2_IO_CLK_EN BIT(7) > + > +#define GMII_SEL_MODE_MASK 0x3 > + > #define desc_write(desc, fld, val) __raw_writel((u32)(val), &(desc)->fld) > #define desc_read(desc, fld) __raw_readl(&(desc)->fld) > #define desc_read_ptr(desc, fld) ((void *)__raw_readl(&(desc)->fld)) > @@ -1150,12 +1162,129 @@ static inline fdt_addr_t cpsw_get_addr_by_node(const void *fdt, int node) > false); > } > > +static void cpsw_gmii_sel_am3352(struct cpsw_priv *priv, > + phy_interface_t phy_mode) > +{ > + u32 reg; > + u32 mask; > + u32 mode = 0; > + bool rgmii_id = false; > + int slave = priv->data.active_slave; > + > + reg = readl(priv->data.gmii_sel); > + > + switch (phy_mode) { > + case PHY_INTERFACE_MODE_RMII: > + mode = AM33XX_GMII_SEL_MODE_RMII; > + break; > + > + case PHY_INTERFACE_MODE_RGMII: > + mode = AM33XX_GMII_SEL_MODE_RGMII; > + break; > + case PHY_INTERFACE_MODE_RGMII_ID: > + case PHY_INTERFACE_MODE_RGMII_RXID: > + case PHY_INTERFACE_MODE_RGMII_TXID: > + mode = AM33XX_GMII_SEL_MODE_RGMII; > + rgmii_id = true; > + break; > + > + case PHY_INTERFACE_MODE_MII: > + default: > + mode = AM33XX_GMII_SEL_MODE_MII; > + break; > + }; > + > + mask = GMII_SEL_MODE_MASK << (slave * 2) | BIT(slave + 6); > + mode <<= slave * 2; > + > + if (priv->data.rmii_clock_external) { I do not see any one updating value for priv->data.rmii_clock_external. I guess cpsw_eth_ofdata_to_platdata() should be populating this value based on DT. Thanks and regards, Lokesh
On Thursday 13 October 2016 09:39 AM, Lokesh Vutla wrote: > > > On Monday 10 October 2016 06:27 PM, Mugunthan V N wrote: >> cpsw driver supports only selection of phy mode in control module >> but control module has more setting like RGMII ID mode selection, >> RMII clock source selection. So ported to cpsw-phy-sel driver >> from kernel to u-boot. >> >> Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com> >> --- >> drivers/net/cpsw.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++++----- >> include/cpsw.h | 1 + >> 2 files changed, 140 insertions(+), 14 deletions(-) >> >> diff --git a/drivers/net/cpsw.c b/drivers/net/cpsw.c >> index d17505e..1441f44 100644 >> --- a/drivers/net/cpsw.c >> +++ b/drivers/net/cpsw.c >> @@ -225,6 +225,18 @@ struct cpdma_chan { >> void *hdp, *cp, *rxfree; >> }; >> >> +/* AM33xx SoC specific definitions for the CONTROL port */ >> +#define AM33XX_GMII_SEL_MODE_MII 0 >> +#define AM33XX_GMII_SEL_MODE_RMII 1 >> +#define AM33XX_GMII_SEL_MODE_RGMII 2 >> + >> +#define AM33XX_GMII_SEL_RGMII1_IDMODE BIT(4) >> +#define AM33XX_GMII_SEL_RGMII2_IDMODE BIT(5) >> +#define AM33XX_GMII_SEL_RMII1_IO_CLK_EN BIT(6) >> +#define AM33XX_GMII_SEL_RMII2_IO_CLK_EN BIT(7) >> + >> +#define GMII_SEL_MODE_MASK 0x3 >> + >> #define desc_write(desc, fld, val) __raw_writel((u32)(val), &(desc)->fld) >> #define desc_read(desc, fld) __raw_readl(&(desc)->fld) >> #define desc_read_ptr(desc, fld) ((void *)__raw_readl(&(desc)->fld)) >> @@ -1150,12 +1162,129 @@ static inline fdt_addr_t cpsw_get_addr_by_node(const void *fdt, int node) >> false); >> } >> >> +static void cpsw_gmii_sel_am3352(struct cpsw_priv *priv, >> + phy_interface_t phy_mode) >> +{ >> + u32 reg; >> + u32 mask; >> + u32 mode = 0; >> + bool rgmii_id = false; >> + int slave = priv->data.active_slave; >> + >> + reg = readl(priv->data.gmii_sel); >> + >> + switch (phy_mode) { >> + case PHY_INTERFACE_MODE_RMII: >> + mode = AM33XX_GMII_SEL_MODE_RMII; >> + break; >> + >> + case PHY_INTERFACE_MODE_RGMII: >> + mode = AM33XX_GMII_SEL_MODE_RGMII; >> + break; >> + case PHY_INTERFACE_MODE_RGMII_ID: >> + case PHY_INTERFACE_MODE_RGMII_RXID: >> + case PHY_INTERFACE_MODE_RGMII_TXID: >> + mode = AM33XX_GMII_SEL_MODE_RGMII; >> + rgmii_id = true; >> + break; >> + >> + case PHY_INTERFACE_MODE_MII: >> + default: >> + mode = AM33XX_GMII_SEL_MODE_MII; >> + break; >> + }; >> + >> + mask = GMII_SEL_MODE_MASK << (slave * 2) | BIT(slave + 6); >> + mode <<= slave * 2; >> + >> + if (priv->data.rmii_clock_external) { > > I do not see any one updating value for priv->data.rmii_clock_external. > I guess cpsw_eth_ofdata_to_platdata() should be populating this value > based on DT. > Oops, missed squashing fixup patches from TI repo. Will be careful next time. Thanks for pointing out early. Regards Mugunthan V N
diff --git a/drivers/net/cpsw.c b/drivers/net/cpsw.c index d17505e..1441f44 100644 --- a/drivers/net/cpsw.c +++ b/drivers/net/cpsw.c @@ -225,6 +225,18 @@ struct cpdma_chan { void *hdp, *cp, *rxfree; }; +/* AM33xx SoC specific definitions for the CONTROL port */ +#define AM33XX_GMII_SEL_MODE_MII 0 +#define AM33XX_GMII_SEL_MODE_RMII 1 +#define AM33XX_GMII_SEL_MODE_RGMII 2 + +#define AM33XX_GMII_SEL_RGMII1_IDMODE BIT(4) +#define AM33XX_GMII_SEL_RGMII2_IDMODE BIT(5) +#define AM33XX_GMII_SEL_RMII1_IO_CLK_EN BIT(6) +#define AM33XX_GMII_SEL_RMII2_IO_CLK_EN BIT(7) + +#define GMII_SEL_MODE_MASK 0x3 + #define desc_write(desc, fld, val) __raw_writel((u32)(val), &(desc)->fld) #define desc_read(desc, fld) __raw_readl(&(desc)->fld) #define desc_read_ptr(desc, fld) ((void *)__raw_readl(&(desc)->fld)) @@ -1150,12 +1162,129 @@ static inline fdt_addr_t cpsw_get_addr_by_node(const void *fdt, int node) false); } +static void cpsw_gmii_sel_am3352(struct cpsw_priv *priv, + phy_interface_t phy_mode) +{ + u32 reg; + u32 mask; + u32 mode = 0; + bool rgmii_id = false; + int slave = priv->data.active_slave; + + reg = readl(priv->data.gmii_sel); + + switch (phy_mode) { + case PHY_INTERFACE_MODE_RMII: + mode = AM33XX_GMII_SEL_MODE_RMII; + break; + + case PHY_INTERFACE_MODE_RGMII: + mode = AM33XX_GMII_SEL_MODE_RGMII; + break; + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: + mode = AM33XX_GMII_SEL_MODE_RGMII; + rgmii_id = true; + break; + + case PHY_INTERFACE_MODE_MII: + default: + mode = AM33XX_GMII_SEL_MODE_MII; + break; + }; + + mask = GMII_SEL_MODE_MASK << (slave * 2) | BIT(slave + 6); + mode <<= slave * 2; + + if (priv->data.rmii_clock_external) { + if (slave == 0) + mode |= AM33XX_GMII_SEL_RMII1_IO_CLK_EN; + else + mode |= AM33XX_GMII_SEL_RMII2_IO_CLK_EN; + } + + if (rgmii_id) { + if (slave == 0) + mode |= AM33XX_GMII_SEL_RGMII1_IDMODE; + else + mode |= AM33XX_GMII_SEL_RGMII2_IDMODE; + } + + reg &= ~mask; + reg |= mode; + + writel(reg, priv->data.gmii_sel); +} + +static void cpsw_gmii_sel_dra7xx(struct cpsw_priv *priv, + phy_interface_t phy_mode) +{ + u32 reg; + u32 mask; + u32 mode = 0; + int slave = priv->data.active_slave; + + reg = readl(priv->data.gmii_sel); + + switch (phy_mode) { + case PHY_INTERFACE_MODE_RMII: + mode = AM33XX_GMII_SEL_MODE_RMII; + break; + + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: + mode = AM33XX_GMII_SEL_MODE_RGMII; + break; + + case PHY_INTERFACE_MODE_MII: + default: + mode = AM33XX_GMII_SEL_MODE_MII; + break; + }; + + switch (slave) { + case 0: + mask = GMII_SEL_MODE_MASK; + break; + case 1: + mask = GMII_SEL_MODE_MASK << 4; + mode <<= 4; + break; + default: + dev_err(priv->dev, "invalid slave number...\n"); + return; + } + + if (priv->data.rmii_clock_external) + dev_err(priv->dev, "RMII External clock is not supported\n"); + + reg &= ~mask; + reg |= mode; + + writel(reg, priv->data.gmii_sel); +} + +static void cpsw_phy_sel(struct cpsw_priv *priv, const char *compat, + phy_interface_t phy_mode) +{ + if (!strcmp(compat, "ti,am3352-cpsw-phy-sel")) + cpsw_gmii_sel_am3352(priv, phy_mode); + if (!strcmp(compat, "ti,am43xx-cpsw-phy-sel")) + cpsw_gmii_sel_am3352(priv, phy_mode); + else if (!strcmp(compat, "ti,dra7xx-cpsw-phy-sel")) + cpsw_gmii_sel_dra7xx(priv, phy_mode); +} + static int cpsw_eth_ofdata_to_platdata(struct udevice *dev) { struct eth_pdata *pdata = dev_get_platdata(dev); struct cpsw_priv *priv = dev_get_priv(dev); struct gpio_desc *mode_gpios; const char *phy_mode; + const char *phy_sel_compat = NULL; const void *fdt = gd->fdt_blob; int node = dev->of_offset; int subnode; @@ -1271,6 +1400,13 @@ static int cpsw_eth_ofdata_to_platdata(struct udevice *dev) error("Not able to get gmii_sel reg address\n"); return -ENOENT; } + + phy_sel_compat = fdt_getprop(fdt, subnode, "compatible", + NULL); + if (!phy_sel_compat) { + error("Not able to get gmii_sel compatible\n"); + return -ENOENT; + } } } @@ -1293,20 +1429,9 @@ static int cpsw_eth_ofdata_to_platdata(struct udevice *dev) debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode); return -EINVAL; } - switch (pdata->phy_interface) { - case PHY_INTERFACE_MODE_MII: - writel(MII_MODE_ENABLE, priv->data.gmii_sel); - break; - case PHY_INTERFACE_MODE_RMII: - writel(RMII_MODE_ENABLE, priv->data.gmii_sel); - break; - case PHY_INTERFACE_MODE_RGMII: - case PHY_INTERFACE_MODE_RGMII_ID: - case PHY_INTERFACE_MODE_RGMII_RXID: - case PHY_INTERFACE_MODE_RGMII_TXID: - writel(RGMII_MODE_ENABLE, priv->data.gmii_sel); - break; - } + + /* Select phy interface in control module */ + cpsw_phy_sel(priv, phy_sel_compat, pdata->phy_interface); return 0; } diff --git a/include/cpsw.h b/include/cpsw.h index 257d12a..f135e7b 100644 --- a/include/cpsw.h +++ b/include/cpsw.h @@ -48,6 +48,7 @@ struct cpsw_platform_data { void (*control)(int enabled); u32 host_port_num; u32 active_slave; + bool rmii_clock_external; u8 version; };
cpsw driver supports only selection of phy mode in control module but control module has more setting like RGMII ID mode selection, RMII clock source selection. So ported to cpsw-phy-sel driver from kernel to u-boot. Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com> --- drivers/net/cpsw.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++++----- include/cpsw.h | 1 + 2 files changed, 140 insertions(+), 14 deletions(-)