diff mbox

[U-Boot,v8,14/17] net: fec_mxc: Add fec_phy_reset support

Message ID 1495546425-753-1-git-send-email-jteki@openedev.com
State Changes Requested
Delegated to: Stefano Babic
Headers show

Commit Message

Jagan Teki May 23, 2017, 1:33 p.m. UTC
From: Jagan Teki <jagan@openedev.com>

phy-reset-gpios and phy-reset-duration properties are
needed for adding mii_dev reset bus operation,
so the board code not take care of phy_reset anymore
if it use DM_ETH.

Cc: Joe Hershberger <joe.hershberger@ni.com>
Cc: Fabio Estevam <fabio.estevam@nxp.com>
Signed-off-by: Jagan Teki <jagan@openedev.com>
---
Changes for v8:
- Add 'phy-reset-duration' property support

 drivers/net/fec_mxc.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++-----
 drivers/net/fec_mxc.h |  9 ++++++
 include/netdev.h      |  5 ++++
 3 files changed, 89 insertions(+), 8 deletions(-)

Comments

Joe Hershberger May 30, 2017, 7:35 p.m. UTC | #1
On Tue, May 23, 2017 at 8:33 AM, Jagan Teki <jagannadh.teki@gmail.com> wrote:
> From: Jagan Teki <jagan@openedev.com>
>
> phy-reset-gpios and phy-reset-duration properties are
> needed for adding mii_dev reset bus operation,
> so the board code not take care of phy_reset anymore
> if it use DM_ETH.
>
> Cc: Joe Hershberger <joe.hershberger@ni.com>
> Cc: Fabio Estevam <fabio.estevam@nxp.com>
> Signed-off-by: Jagan Teki <jagan@openedev.com>
> ---
> Changes for v8:
> - Add 'phy-reset-duration' property support
>
>  drivers/net/fec_mxc.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++-----
>  drivers/net/fec_mxc.h |  9 ++++++
>  include/netdev.h      |  5 ++++
>  3 files changed, 89 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
> index 08bea8b..17fe27f 100644
> --- a/drivers/net/fec_mxc.c
> +++ b/drivers/net/fec_mxc.c
> @@ -180,13 +180,27 @@ static int fec_mdio_write(struct ethernet_regs *eth, uint8_t phyaddr,
>  static int fec_phy_read(struct mii_dev *bus, int phyaddr, int dev_addr,
>                         int regaddr)
>  {
> -       return fec_mdio_read(bus->priv, phyaddr, regaddr);
> +#ifdef CONFIG_DM_ETH
> +       struct fec_priv *priv = dev_get_priv((struct udevice *)bus->priv);
> +       struct ethernet_regs *eth = priv->eth;
> +#else
> +       struct ethernet_regs *eth = bus->priv;
> +#endif
> +
> +       return fec_mdio_read(eth, phyaddr, regaddr);
>  }
>
>  static int fec_phy_write(struct mii_dev *bus, int phyaddr, int dev_addr,
>                          int regaddr, u16 data)
>  {
> -       return fec_mdio_write(bus->priv, phyaddr, regaddr, data);
> +#ifdef CONFIG_DM_ETH
> +       struct fec_priv *priv = dev_get_priv((struct udevice *)bus->priv);
> +       struct ethernet_regs *eth = priv->eth;
> +#else
> +       struct ethernet_regs *eth = bus->priv;
> +#endif
> +
> +       return fec_mdio_write(eth, phyaddr, regaddr, data);
>  }
>
>  #ifndef CONFIG_PHYLIB
> @@ -985,9 +999,44 @@ static void fec_free_descs(struct fec_priv *fec)
>         free(fec->tbd_base);
>  }
>
> +#if defined(CONFIG_DM_ETH) && defined(CONFIG_DM_GPIO)
> +static int fec_phy_reset(struct mii_dev *bus)
> +{
> +       struct fec_priv *priv = dev_get_priv((struct udevice *)bus->priv);
> +       int ret;
> +
> +       if (!dm_gpio_is_valid(&priv->reset_gpio))
> +               return 0;
> +
> +       /* phy reset */
> +       ret = dm_gpio_set_value(&priv->reset_gpio, 0);
> +       if (ret)
> +               return ret;
> +
> +       mdelay(priv->reset_duration);
> +
> +       ret = dm_gpio_set_value(&priv->reset_gpio, 1);
> +       if (ret)
> +               return ret;
> +
> +       mdelay(priv->reset_duration);
> +
> +       return 0;
> +}
> +#endif
> +
> +#ifdef CONFIG_DM_ETH
> +struct mii_dev *fec_get_miibus(struct udevice *dev, int dev_id)
> +#else
>  struct mii_dev *fec_get_miibus(uint32_t base_addr, int dev_id)
> +#endif
>  {
> +#ifdef CONFIG_DM_ETH
> +       struct fec_priv *priv = dev_get_priv(dev);
> +       struct ethernet_regs *eth = priv->eth;
> +#else
>         struct ethernet_regs *eth = (struct ethernet_regs *)base_addr;
> +#endif
>         struct mii_dev *bus;
>         int ret;
>
> @@ -998,7 +1047,14 @@ struct mii_dev *fec_get_miibus(uint32_t base_addr, int dev_id)
>         }
>         bus->read = fec_phy_read;
>         bus->write = fec_phy_write;
> +#ifdef CONFIG_DM_ETH
> +       bus->priv = dev;
> +# ifdef CONFIG_DM_GPIO
> +       bus->reset = fec_phy_reset;
> +# endif
> +#else
>         bus->priv = eth;
> +#endif
>         fec_set_dev_name(bus->name, dev_id);
>
>         ret = mdio_register(bus);
> @@ -1223,7 +1279,7 @@ static int fecmxc_probe(struct udevice *dev)
>         if (ret)
>                 return ret;
>
> -       bus = fec_get_miibus((uint32_t)priv->eth, dev_id);
> +       bus = fec_get_miibus(dev, dev_id);
>         if (!bus)
>                 goto err_mii;
>
> @@ -1278,6 +1334,7 @@ static int fecmxc_ofdata_to_platdata(struct udevice *dev)
>         struct eth_pdata *pdata = dev_get_platdata(dev);
>         struct fec_priv *priv = dev_get_priv(dev);
>         const char *phy_mode;
> +       int ret = 0;
>
>         pdata->iobase = (phys_addr_t)dev_get_addr(dev);
>         priv->eth = (struct ethernet_regs *)pdata->iobase;
> @@ -1292,12 +1349,22 @@ static int fecmxc_ofdata_to_platdata(struct udevice *dev)
>                 return -EINVAL;
>         }
>
> -       /* TODO
> -        * Need to get the reset-gpio and related properties from DT
> -        * and implemet the enet reset code on .probe call
> -        */
> +#ifdef CONFIG_DM_GPIO
> +       /* phy reset gpio */
> +       ret = gpio_request_by_name(dev, "phy-reset-gpios", 0,
> +                                  &priv->reset_gpio, GPIOD_IS_OUT);
> +       if (ret == 0) {
> +               priv->reset_duration = fdtdec_get_int(gd->fdt_blob,
> +                                                     dev_of_offset(dev),
> +                                                     "phy-reset-duration", 1);

Seems like

> +               /* A sane reset duration should not be longer than 1s */
> +               if (priv->reset_duration > 1000)
> +                       priv->reset_duration = 1;

It seems odd to set it to 1 ms if the requested was too long. Maybe it
should just be priv->reset_duration = MIN(priv->reset_duration, 1000);
?

Also, should the member variable have "_ms" at the end to make the units clear?

> +               ret = 0;
> +       }
> +#endif
>
> -       return 0;
> +       return ret;
>  }
>
>  static const struct udevice_id fecmxc_ids[] = {
> diff --git a/drivers/net/fec_mxc.h b/drivers/net/fec_mxc.h
> index 43a7d7b..fd51d6d 100644
> --- a/drivers/net/fec_mxc.h
> +++ b/drivers/net/fec_mxc.h
> @@ -17,6 +17,10 @@
>  #ifndef __FEC_MXC_H
>  #define __FEC_MXC_H
>
> +#ifdef CONFIG_DM_GPIO
> +# include <asm-generic/gpio.h>
> +#endif
> +
>  /* Layout description of the FEC */
>  struct ethernet_regs {
>         /* [10:2]addr = 00 */
> @@ -254,6 +258,11 @@ struct fec_priv {
>
>  #ifdef CONFIG_DM_ETH
>         u32 interface;
> +
> +# ifdef CONFIG_DM_GPIO
> +       struct gpio_desc reset_gpio;
> +       u32 reset_duration;
> +# endif
>  #endif
>  };
>
> diff --git a/include/netdev.h b/include/netdev.h
> index 8eb8b46..e5668f4 100644
> --- a/include/netdev.h
> +++ b/include/netdev.h
> @@ -133,7 +133,12 @@ static inline int pci_eth_init(bd_t *bis)
>         return num;
>  }
>
> +#ifdef CONFIG_DM_ETH
> +struct mii_dev *fec_get_miibus(struct udevice *dev, int dev_id);
> +#else
>  struct mii_dev *fec_get_miibus(uint32_t base_addr, int dev_id);
> +#endif
> +
>  #ifdef CONFIG_PHYLIB
>  struct phy_device;
>  int fec_probe(bd_t *bd, int dev_id, uint32_t base_addr,
> --
> 2.7.4
>
> _______________________________________________
> U-Boot mailing list
> U-Boot@lists.denx.de
> https://lists.denx.de/listinfo/u-boot
diff mbox

Patch

diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index 08bea8b..17fe27f 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -180,13 +180,27 @@  static int fec_mdio_write(struct ethernet_regs *eth, uint8_t phyaddr,
 static int fec_phy_read(struct mii_dev *bus, int phyaddr, int dev_addr,
 			int regaddr)
 {
-	return fec_mdio_read(bus->priv, phyaddr, regaddr);
+#ifdef CONFIG_DM_ETH
+	struct fec_priv *priv = dev_get_priv((struct udevice *)bus->priv);
+	struct ethernet_regs *eth = priv->eth;
+#else
+	struct ethernet_regs *eth = bus->priv;
+#endif
+
+	return fec_mdio_read(eth, phyaddr, regaddr);
 }
 
 static int fec_phy_write(struct mii_dev *bus, int phyaddr, int dev_addr,
 			 int regaddr, u16 data)
 {
-	return fec_mdio_write(bus->priv, phyaddr, regaddr, data);
+#ifdef CONFIG_DM_ETH
+	struct fec_priv *priv = dev_get_priv((struct udevice *)bus->priv);
+	struct ethernet_regs *eth = priv->eth;
+#else
+	struct ethernet_regs *eth = bus->priv;
+#endif
+
+	return fec_mdio_write(eth, phyaddr, regaddr, data);
 }
 
 #ifndef CONFIG_PHYLIB
@@ -985,9 +999,44 @@  static void fec_free_descs(struct fec_priv *fec)
 	free(fec->tbd_base);
 }
 
+#if defined(CONFIG_DM_ETH) && defined(CONFIG_DM_GPIO)
+static int fec_phy_reset(struct mii_dev *bus)
+{
+	struct fec_priv *priv = dev_get_priv((struct udevice *)bus->priv);
+	int ret;
+
+	if (!dm_gpio_is_valid(&priv->reset_gpio))
+		return 0;
+
+	/* phy reset */
+	ret = dm_gpio_set_value(&priv->reset_gpio, 0);
+	if (ret)
+		return ret;
+
+	mdelay(priv->reset_duration);
+
+	ret = dm_gpio_set_value(&priv->reset_gpio, 1);
+	if (ret)
+		return ret;
+
+	mdelay(priv->reset_duration);
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_DM_ETH
+struct mii_dev *fec_get_miibus(struct udevice *dev, int dev_id)
+#else
 struct mii_dev *fec_get_miibus(uint32_t base_addr, int dev_id)
+#endif
 {
+#ifdef CONFIG_DM_ETH
+	struct fec_priv *priv = dev_get_priv(dev);
+	struct ethernet_regs *eth = priv->eth;
+#else
 	struct ethernet_regs *eth = (struct ethernet_regs *)base_addr;
+#endif
 	struct mii_dev *bus;
 	int ret;
 
@@ -998,7 +1047,14 @@  struct mii_dev *fec_get_miibus(uint32_t base_addr, int dev_id)
 	}
 	bus->read = fec_phy_read;
 	bus->write = fec_phy_write;
+#ifdef CONFIG_DM_ETH
+	bus->priv = dev;
+# ifdef CONFIG_DM_GPIO
+	bus->reset = fec_phy_reset;
+# endif
+#else
 	bus->priv = eth;
+#endif
 	fec_set_dev_name(bus->name, dev_id);
 
 	ret = mdio_register(bus);
@@ -1223,7 +1279,7 @@  static int fecmxc_probe(struct udevice *dev)
 	if (ret)
 		return ret;
 
-	bus = fec_get_miibus((uint32_t)priv->eth, dev_id);
+	bus = fec_get_miibus(dev, dev_id);
 	if (!bus)
 		goto err_mii;
 
@@ -1278,6 +1334,7 @@  static int fecmxc_ofdata_to_platdata(struct udevice *dev)
 	struct eth_pdata *pdata = dev_get_platdata(dev);
 	struct fec_priv *priv = dev_get_priv(dev);
 	const char *phy_mode;
+	int ret = 0;
 
 	pdata->iobase = (phys_addr_t)dev_get_addr(dev);
 	priv->eth = (struct ethernet_regs *)pdata->iobase;
@@ -1292,12 +1349,22 @@  static int fecmxc_ofdata_to_platdata(struct udevice *dev)
 		return -EINVAL;
 	}
 
-	/* TODO
-	 * Need to get the reset-gpio and related properties from DT
-	 * and implemet the enet reset code on .probe call
-	 */
+#ifdef CONFIG_DM_GPIO
+	/* phy reset gpio */
+	ret = gpio_request_by_name(dev, "phy-reset-gpios", 0,
+				   &priv->reset_gpio, GPIOD_IS_OUT);
+	if (ret == 0) {
+		priv->reset_duration = fdtdec_get_int(gd->fdt_blob,
+						      dev_of_offset(dev),
+						      "phy-reset-duration", 1);
+		/* A sane reset duration should not be longer than 1s */
+		if (priv->reset_duration > 1000)
+			priv->reset_duration = 1;
+		ret = 0;
+	}
+#endif
 
-	return 0;
+	return ret;
 }
 
 static const struct udevice_id fecmxc_ids[] = {
diff --git a/drivers/net/fec_mxc.h b/drivers/net/fec_mxc.h
index 43a7d7b..fd51d6d 100644
--- a/drivers/net/fec_mxc.h
+++ b/drivers/net/fec_mxc.h
@@ -17,6 +17,10 @@ 
 #ifndef __FEC_MXC_H
 #define __FEC_MXC_H
 
+#ifdef CONFIG_DM_GPIO
+# include <asm-generic/gpio.h>
+#endif
+
 /* Layout description of the FEC */
 struct ethernet_regs {
 	/* [10:2]addr = 00 */
@@ -254,6 +258,11 @@  struct fec_priv {
 
 #ifdef CONFIG_DM_ETH
 	u32 interface;
+
+# ifdef CONFIG_DM_GPIO
+	struct gpio_desc reset_gpio;
+	u32 reset_duration;
+# endif
 #endif
 };
 
diff --git a/include/netdev.h b/include/netdev.h
index 8eb8b46..e5668f4 100644
--- a/include/netdev.h
+++ b/include/netdev.h
@@ -133,7 +133,12 @@  static inline int pci_eth_init(bd_t *bis)
 	return num;
 }
 
+#ifdef CONFIG_DM_ETH
+struct mii_dev *fec_get_miibus(struct udevice *dev, int dev_id);
+#else
 struct mii_dev *fec_get_miibus(uint32_t base_addr, int dev_id);
+#endif
+
 #ifdef CONFIG_PHYLIB
 struct phy_device;
 int fec_probe(bd_t *bd, int dev_id, uint32_t base_addr,