diff mbox series

[1/9] net: eqos: Add PHY reset control for i.MX platform

Message ID 1613718467-88336-1-git-send-email-ye.li@nxp.com
State Changes Requested
Delegated to: Stefano Babic
Headers show
Series [1/9] net: eqos: Add PHY reset control for i.MX platform | expand

Commit Message

Ye Li Feb. 19, 2021, 7:07 a.m. UTC
Parse the "phy-reset-gpios", "phy-reset-post-delay" and
"phy-reset-duration" properties from eqos node to control the
ethernet PHY reset at driver probe.
Reset PHY once is enough that can reduce the time cost to
get IP after the first time.

Signed-off-by: Ye Li <ye.li@nxp.com>
---
 drivers/net/dwc_eth_qos.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)

Comments

Stefano Babic July 17, 2021, 12:54 p.m. UTC | #1
Hi Ye,

series was completely lost on my side, I tried to check it today but it 
is obsolete now and conflicts with Peng's series for MX8ULP. So I drop 
it, yorry, you should rebase and post it again.

Best regards,
Stefano Babic

On 19.02.21 08:07, Ye Li wrote:
> Parse the "phy-reset-gpios", "phy-reset-post-delay" and
> "phy-reset-duration" properties from eqos node to control the
> ethernet PHY reset at driver probe.
> Reset PHY once is enough that can reduce the time cost to
> get IP after the first time.
> 
> Signed-off-by: Ye Li <ye.li@nxp.com>
> ---
>   drivers/net/dwc_eth_qos.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 55 insertions(+)
> 
> diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
> index e8242ca..14aafc6 100644
> --- a/drivers/net/dwc_eth_qos.c
> +++ b/drivers/net/dwc_eth_qos.c
> @@ -303,6 +303,8 @@ struct eqos_priv {
>   	struct eqos_tegra186_regs *tegra186_regs;
>   	struct reset_ctl reset_ctl;
>   	struct gpio_desc phy_reset_gpio;
> +	uint32_t reset_delay;
> +	uint32_t reset_post_delay;
>   	struct clk clk_master_bus;
>   	struct clk clk_rx;
>   	struct clk clk_ptp_ref;
> @@ -1880,6 +1882,7 @@ static int eqos_probe_resources_imx(struct udevice *dev)
>   {
>   	struct eqos_priv *eqos = dev_get_priv(dev);
>   	phy_interface_t interface;
> +	int ret = 0;
>   
>   	debug("%s(dev=%p):\n", __func__, dev);
>   
> @@ -1890,8 +1893,52 @@ static int eqos_probe_resources_imx(struct udevice *dev)
>   		return -EINVAL;
>   	}
>   
> +	ret = gpio_request_by_name(dev, "phy-reset-gpios", 0,
> +				   &eqos->phy_reset_gpio,
> +				   GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
> +	if (ret) {
> +		pr_debug("gpio_request_by_name(phy reset) failed: %d", ret);
> +	}
> +
> +	if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) {
> +		eqos->reset_delay = dev_read_u32_default(dev, "phy-reset-duration", 1);
> +		if (eqos->reset_delay > 1000) {
> +			pr_err("phy reset duration should be <= 1000ms\n");
> +			/* property value wrong, use default value */
> +			eqos->reset_delay = 1;
> +		}
> +
> +		mdelay(eqos->reset_delay);
> +
> +		eqos->reset_post_delay = dev_read_u32_default(dev,
> +							      "phy-reset-post-delay",
> +							      0);
> +		if (eqos->reset_post_delay > 1000) {
> +			pr_err("phy reset post delay should be <= 1000ms\n");
> +			/* property value wrong, use default value */
> +			eqos->reset_post_delay = 0;
> +		}
> +
> +		ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0);
> +		if (ret < 0) {
> +			pr_err("dm_gpio_set_value(phy_reset, deassert) failed: %d", ret);
> +			goto err_free_gpio_phy_reset;
> +		}
> +
> +		if (eqos->reset_post_delay)
> +			mdelay(eqos->reset_post_delay);
> +	}
> +
>   	debug("%s: OK\n", __func__);
>   	return 0;
> +
> +err_free_gpio_phy_reset:
> +	if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) {
> +		dm_gpio_free(dev, &eqos->phy_reset_gpio);
> +	}
> +
> +	debug("%s: returns %d\n", __func__, ret);
> +	return ret;
>   }
>   
>   static phy_interface_t eqos_get_interface_imx(struct udevice *dev)
> @@ -1951,6 +1998,14 @@ static int eqos_remove_resources_stm32(struct udevice *dev)
>   
>   static int eqos_remove_resources_imx(struct udevice *dev)
>   {
> +	struct eqos_priv *eqos = dev_get_priv(dev);
> +
> +	debug("%s(dev=%p):\n", __func__, dev);
> +	if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) {
> +		dm_gpio_free(dev, &eqos->phy_reset_gpio);
> +	}
> +
> +	debug("%s: OK\n", __func__);
>   	return 0;
>   }
>   
>
Ye Li July 21, 2021, 2:37 a.m. UTC | #2
Hi Stefano,

  Ok. I will rebase the patches after the 8ULP is merged.

Best regards,
Ye Li
> -----Original Message-----
> From: Stefano Babic <sbabic@denx.de>
> Sent: Saturday, July 17, 2021 8:54 PM
> To: Ye Li <ye.li@nxp.com>; sbabic@denx.de; u-boot@lists.denx.de; Peng Fan
> <peng.fan@nxp.com>; marex@denx.de
> Cc: rfried.dev@gmail.com; dl-uboot-imx <uboot-imx@nxp.com>;
> s.arendt@sensopart.de
> Subject: [EXT] Re: [PATCH 1/9] net: eqos: Add PHY reset control for i.MX
> platform
> 
> Caution: EXT Email
> 
> Hi Ye,
> 
> series was completely lost on my side, I tried to check it today but it is obsolete
> now and conflicts with Peng's series for MX8ULP. So I drop it, yorry, you should
> rebase and post it again.
> 
> Best regards,
> Stefano Babic
> 
> On 19.02.21 08:07, Ye Li wrote:
> > Parse the "phy-reset-gpios", "phy-reset-post-delay" and
> > "phy-reset-duration" properties from eqos node to control the ethernet
> > PHY reset at driver probe.
> > Reset PHY once is enough that can reduce the time cost to get IP after
> > the first time.
> >
> > Signed-off-by: Ye Li <ye.li@nxp.com>
> > ---
> >   drivers/net/dwc_eth_qos.c | 55
> +++++++++++++++++++++++++++++++++++++++++++++++
> >   1 file changed, 55 insertions(+)
> >
> > diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
> > index e8242ca..14aafc6 100644
> > --- a/drivers/net/dwc_eth_qos.c
> > +++ b/drivers/net/dwc_eth_qos.c
> > @@ -303,6 +303,8 @@ struct eqos_priv {
> >       struct eqos_tegra186_regs *tegra186_regs;
> >       struct reset_ctl reset_ctl;
> >       struct gpio_desc phy_reset_gpio;
> > +     uint32_t reset_delay;
> > +     uint32_t reset_post_delay;
> >       struct clk clk_master_bus;
> >       struct clk clk_rx;
> >       struct clk clk_ptp_ref;
> > @@ -1880,6 +1882,7 @@ static int eqos_probe_resources_imx(struct
> udevice *dev)
> >   {
> >       struct eqos_priv *eqos = dev_get_priv(dev);
> >       phy_interface_t interface;
> > +     int ret = 0;
> >
> >       debug("%s(dev=%p):\n", __func__, dev);
> >
> > @@ -1890,8 +1893,52 @@ static int eqos_probe_resources_imx(struct
> udevice *dev)
> >               return -EINVAL;
> >       }
> >
> > +     ret = gpio_request_by_name(dev, "phy-reset-gpios", 0,
> > +                                &eqos->phy_reset_gpio,
> > +                                GPIOD_IS_OUT |
> GPIOD_IS_OUT_ACTIVE);
> > +     if (ret) {
> > +             pr_debug("gpio_request_by_name(phy reset) failed: %d",
> ret);
> > +     }
> > +
> > +     if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) {
> > +             eqos->reset_delay = dev_read_u32_default(dev,
> "phy-reset-duration", 1);
> > +             if (eqos->reset_delay > 1000) {
> > +                     pr_err("phy reset duration should be <=
> 1000ms\n");
> > +                     /* property value wrong, use default value */
> > +                     eqos->reset_delay = 1;
> > +             }
> > +
> > +             mdelay(eqos->reset_delay);
> > +
> > +             eqos->reset_post_delay = dev_read_u32_default(dev,
> > +
> "phy-reset-post-delay",
> > +                                                           0);
> > +             if (eqos->reset_post_delay > 1000) {
> > +                     pr_err("phy reset post delay should be <=
> 1000ms\n");
> > +                     /* property value wrong, use default value */
> > +                     eqos->reset_post_delay = 0;
> > +             }
> > +
> > +             ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0);
> > +             if (ret < 0) {
> > +                     pr_err("dm_gpio_set_value(phy_reset, deassert)
> failed: %d", ret);
> > +                     goto err_free_gpio_phy_reset;
> > +             }
> > +
> > +             if (eqos->reset_post_delay)
> > +                     mdelay(eqos->reset_post_delay);
> > +     }
> > +
> >       debug("%s: OK\n", __func__);
> >       return 0;
> > +
> > +err_free_gpio_phy_reset:
> > +     if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) {
> > +             dm_gpio_free(dev, &eqos->phy_reset_gpio);
> > +     }
> > +
> > +     debug("%s: returns %d\n", __func__, ret);
> > +     return ret;
> >   }
> >
> >   static phy_interface_t eqos_get_interface_imx(struct udevice *dev)
> > @@ -1951,6 +1998,14 @@ static int eqos_remove_resources_stm32(struct
> > udevice *dev)
> >
> >   static int eqos_remove_resources_imx(struct udevice *dev)
> >   {
> > +     struct eqos_priv *eqos = dev_get_priv(dev);
> > +
> > +     debug("%s(dev=%p):\n", __func__, dev);
> > +     if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) {
> > +             dm_gpio_free(dev, &eqos->phy_reset_gpio);
> > +     }
> > +
> > +     debug("%s: OK\n", __func__);
> >       return 0;
> >   }
> >
> >
> 
> --
> ================================================================
> =====
> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic@denx.de
> ================================================================
> =====
diff mbox series

Patch

diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
index e8242ca..14aafc6 100644
--- a/drivers/net/dwc_eth_qos.c
+++ b/drivers/net/dwc_eth_qos.c
@@ -303,6 +303,8 @@  struct eqos_priv {
 	struct eqos_tegra186_regs *tegra186_regs;
 	struct reset_ctl reset_ctl;
 	struct gpio_desc phy_reset_gpio;
+	uint32_t reset_delay;
+	uint32_t reset_post_delay;
 	struct clk clk_master_bus;
 	struct clk clk_rx;
 	struct clk clk_ptp_ref;
@@ -1880,6 +1882,7 @@  static int eqos_probe_resources_imx(struct udevice *dev)
 {
 	struct eqos_priv *eqos = dev_get_priv(dev);
 	phy_interface_t interface;
+	int ret = 0;
 
 	debug("%s(dev=%p):\n", __func__, dev);
 
@@ -1890,8 +1893,52 @@  static int eqos_probe_resources_imx(struct udevice *dev)
 		return -EINVAL;
 	}
 
+	ret = gpio_request_by_name(dev, "phy-reset-gpios", 0,
+				   &eqos->phy_reset_gpio,
+				   GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
+	if (ret) {
+		pr_debug("gpio_request_by_name(phy reset) failed: %d", ret);
+	}
+
+	if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) {
+		eqos->reset_delay = dev_read_u32_default(dev, "phy-reset-duration", 1);
+		if (eqos->reset_delay > 1000) {
+			pr_err("phy reset duration should be <= 1000ms\n");
+			/* property value wrong, use default value */
+			eqos->reset_delay = 1;
+		}
+
+		mdelay(eqos->reset_delay);
+
+		eqos->reset_post_delay = dev_read_u32_default(dev,
+							      "phy-reset-post-delay",
+							      0);
+		if (eqos->reset_post_delay > 1000) {
+			pr_err("phy reset post delay should be <= 1000ms\n");
+			/* property value wrong, use default value */
+			eqos->reset_post_delay = 0;
+		}
+
+		ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0);
+		if (ret < 0) {
+			pr_err("dm_gpio_set_value(phy_reset, deassert) failed: %d", ret);
+			goto err_free_gpio_phy_reset;
+		}
+
+		if (eqos->reset_post_delay)
+			mdelay(eqos->reset_post_delay);
+	}
+
 	debug("%s: OK\n", __func__);
 	return 0;
+
+err_free_gpio_phy_reset:
+	if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) {
+		dm_gpio_free(dev, &eqos->phy_reset_gpio);
+	}
+
+	debug("%s: returns %d\n", __func__, ret);
+	return ret;
 }
 
 static phy_interface_t eqos_get_interface_imx(struct udevice *dev)
@@ -1951,6 +1998,14 @@  static int eqos_remove_resources_stm32(struct udevice *dev)
 
 static int eqos_remove_resources_imx(struct udevice *dev)
 {
+	struct eqos_priv *eqos = dev_get_priv(dev);
+
+	debug("%s(dev=%p):\n", __func__, dev);
+	if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) {
+		dm_gpio_free(dev, &eqos->phy_reset_gpio);
+	}
+
+	debug("%s: OK\n", __func__);
 	return 0;
 }