linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/3] net: ethernet: fec: fix refclk enable for SMSC LAN8710/20
@ 2017-11-20  8:34 Richard Leitner
  2017-11-20  8:34 ` [PATCH v2 1/3] net: ethernet: freescale: simplify fec_reset_phy Richard Leitner
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Richard Leitner @ 2017-11-20  8:34 UTC (permalink / raw)
  To: f.fainelli, fugang.duan, andrew; +Cc: netdev, linux-kernel, richard.leitner

From: Richard Leitner <richard.leitner@skidata.com>

This patch series fixes the use of the SMSC LAN8710/20 with a Freescale ETH
when the refclk is generated by the FSL.

Changes v2:
	- simplify and fix fec_reset_phy function to support multiple calls
	- include: linux: phy: harmonize phy_id{,_mask} type
	- reset the phy instead of not turning the clock on and off
	  (which would have caused a power consumption regression)

Richard Leitner (3):
  net: ethernet: freescale: simplify fec_reset_phy
  include: linux: phy: harmonize phy_id{,_mask} type
  net: ethernet: fec: fix refclk enable for SMSC LAN8710/20

 drivers/net/ethernet/freescale/fec.h      |   4 +
 drivers/net/ethernet/freescale/fec_main.c | 125 ++++++++++++++++++++----------
 include/linux/phy.h                       |   2 +-
 3 files changed, 88 insertions(+), 43 deletions(-)

-- 
2.11.0

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v2 1/3] net: ethernet: freescale: simplify fec_reset_phy
  2017-11-20  8:34 [PATCH v2 0/3] net: ethernet: fec: fix refclk enable for SMSC LAN8710/20 Richard Leitner
@ 2017-11-20  8:34 ` Richard Leitner
  2017-11-20  9:35   ` Andy Duan
  2017-11-20  8:34 ` [PATCH v2 2/3] include: linux: phy: harmonize phy_id{,_mask} type Richard Leitner
  2017-11-20  8:34 ` [PATCH v2 3/3] net: ethernet: fec: fix refclk enable for SMSC LAN8710/20 Richard Leitner
  2 siblings, 1 reply; 13+ messages in thread
From: Richard Leitner @ 2017-11-20  8:34 UTC (permalink / raw)
  To: f.fainelli, fugang.duan, andrew; +Cc: netdev, linux-kernel, richard.leitner

From: Richard Leitner <richard.leitner@skidata.com>

The fec_reset_phy function allowed only one execution during probeing.
To make it more usable move the dt parsing and gpio allocation to the
probe function. The parameters of the phy reset are added to the
fec_enet_private struct. As a result the fec_reset_phy function may be
called anytime after probe.

One checkpatch.pl warning (too long line) is ignored. This is due to the
fact a string (dt property name) otherwise needs to be split over
multiple lines, which is counterproductive for the readability.

Signed-off-by: Richard Leitner <richard.leitner@skidata.com>
---
 drivers/net/ethernet/freescale/fec.h      |  4 ++
 drivers/net/ethernet/freescale/fec_main.c | 88 ++++++++++++++++---------------
 2 files changed, 50 insertions(+), 42 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 5385074b3b7d..401c4eabf08a 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -539,6 +539,10 @@ struct fec_enet_private {
 	int	pause_flag;
 	int	wol_flag;
 	u32	quirks;
+	int	phy_reset;
+	int	phy_reset_duration;
+	int	phy_reset_post_delay;
+	bool	phy_reset_active_high;
 
 	struct	napi_struct napi;
 	int	csum_flags;
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 610573855213..06a7caca0cee 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -3212,62 +3212,36 @@ static int fec_enet_init(struct net_device *ndev)
 }
 
 #ifdef CONFIG_OF
-static int fec_reset_phy(struct platform_device *pdev)
+static int fec_reset_phy(struct net_device *ndev)
 {
-	int err, phy_reset;
-	bool active_high = false;
-	int msec = 1, phy_post_delay = 0;
-	struct device_node *np = pdev->dev.of_node;
-
-	if (!np)
-		return 0;
-
-	err = of_property_read_u32(np, "phy-reset-duration", &msec);
-	/* A sane reset duration should not be longer than 1s */
-	if (!err && msec > 1000)
-		msec = 1;
+	struct fec_enet_private *fep = netdev_priv(ndev);
 
-	phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0);
-	if (phy_reset == -EPROBE_DEFER)
-		return phy_reset;
-	else if (!gpio_is_valid(phy_reset))
+	if (!fep->phy_reset)
 		return 0;
 
-	err = of_property_read_u32(np, "phy-reset-post-delay", &phy_post_delay);
-	/* valid reset duration should be less than 1s */
-	if (!err && phy_post_delay > 1000)
-		return -EINVAL;
-
-	active_high = of_property_read_bool(np, "phy-reset-active-high");
+	gpio_set_value_cansleep(fep->phy_reset, fep->phy_reset_active_high);
 
-	err = devm_gpio_request_one(&pdev->dev, phy_reset,
-			active_high ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
-			"phy-reset");
-	if (err) {
-		dev_err(&pdev->dev, "failed to get phy-reset-gpios: %d\n", err);
-		return err;
-	}
-
-	if (msec > 20)
-		msleep(msec);
+	if (fep->phy_reset_duration > 20)
+		msleep(fep->phy_reset_duration);
 	else
-		usleep_range(msec * 1000, msec * 1000 + 1000);
+		usleep_range(fep->phy_reset_duration * 1000,
+			     fep->phy_reset_duration * 1000 + 1000);
 
-	gpio_set_value_cansleep(phy_reset, !active_high);
+	gpio_set_value_cansleep(fep->phy_reset, !fep->phy_reset_active_high);
 
-	if (!phy_post_delay)
+	if (!fep->phy_reset_post_delay)
 		return 0;
 
-	if (phy_post_delay > 20)
-		msleep(phy_post_delay);
+	if (fep->phy_reset_post_delay > 20)
+		msleep(fep->phy_reset_post_delay);
 	else
-		usleep_range(phy_post_delay * 1000,
-			     phy_post_delay * 1000 + 1000);
+		usleep_range(fep->phy_reset_post_delay * 1000,
+			     fep->phy_reset_post_delay * 1000 + 1000);
 
 	return 0;
 }
 #else /* CONFIG_OF */
-static int fec_reset_phy(struct platform_device *pdev)
+static int fec_reset_phy(struct net_device *ndev)
 {
 	/*
 	 * In case of platform probe, the reset has been done
@@ -3400,6 +3374,36 @@ fec_probe(struct platform_device *pdev)
 	}
 	fep->phy_node = phy_node;
 
+	fep->phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0);
+	if (gpio_is_valid(fep->phy_reset)) {
+		ret = of_property_read_u32(np, "phy-reset-duration",
+					   &fep->phy_reset_duration);
+		/* A sane reset duration should not be longer than 1s */
+		if (!ret && fep->phy_reset_post_delay > 1000)
+			fep->phy_reset_post_delay = 1;
+
+		ret = of_property_read_u32(np, "phy-reset-post-delay",
+					   &fep->phy_reset_post_delay);
+		/* valid post reset delay should be less than 1s */
+		if (!ret && fep->phy_reset_post_delay > 1000)
+			fep->phy_reset_post_delay = 1;
+
+		fep->phy_reset_active_high = of_property_read_bool(np, "phy-reset-active-high");
+
+		ret = devm_gpio_request_one(&pdev->dev, fep->phy_reset,
+					    fep->phy_reset_active_high ?
+					    GPIOF_OUT_INIT_HIGH :
+					    GPIOF_OUT_INIT_LOW,
+					    "phy-reset");
+		if (ret) {
+			dev_err(&pdev->dev, "failed to get reset-gpios: %d\n",
+				ret);
+			goto failed_phy;
+		}
+	} else {
+		fep->phy_reset = 0;
+	}
+
 	ret = of_get_phy_mode(pdev->dev.of_node);
 	if (ret < 0) {
 		pdata = dev_get_platdata(&pdev->dev);
@@ -3472,7 +3476,7 @@ fec_probe(struct platform_device *pdev)
 	pm_runtime_set_active(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
 
-	ret = fec_reset_phy(pdev);
+	ret = fec_reset_phy(ndev);
 	if (ret)
 		goto failed_reset;
 
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 2/3] include: linux: phy: harmonize phy_id{,_mask} type
  2017-11-20  8:34 [PATCH v2 0/3] net: ethernet: fec: fix refclk enable for SMSC LAN8710/20 Richard Leitner
  2017-11-20  8:34 ` [PATCH v2 1/3] net: ethernet: freescale: simplify fec_reset_phy Richard Leitner
@ 2017-11-20  8:34 ` Richard Leitner
  2017-11-20  8:34 ` [PATCH v2 3/3] net: ethernet: fec: fix refclk enable for SMSC LAN8710/20 Richard Leitner
  2 siblings, 0 replies; 13+ messages in thread
From: Richard Leitner @ 2017-11-20  8:34 UTC (permalink / raw)
  To: f.fainelli, fugang.duan, andrew; +Cc: netdev, linux-kernel, richard.leitner

From: Richard Leitner <richard.leitner@skidata.com>

Previously phy_id was u32 and phy_id_mask was unsigned int. As the
phy_id_mask defines the important bits of the phy_id (and is therefore the
same size) these two variables should be the same datatype.

Signed-off-by: Richard Leitner <richard.leitner@skidata.com>
---
 include/linux/phy.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/phy.h b/include/linux/phy.h
index dc82a07cb4fd..e00fd9ce3bce 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -509,7 +509,7 @@ struct phy_driver {
 	struct mdio_driver_common mdiodrv;
 	u32 phy_id;
 	char *name;
-	unsigned int phy_id_mask;
+	u32 phy_id_mask;
 	u32 features;
 	u32 flags;
 	const void *driver_data;
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 3/3] net: ethernet: fec: fix refclk enable for SMSC LAN8710/20
  2017-11-20  8:34 [PATCH v2 0/3] net: ethernet: fec: fix refclk enable for SMSC LAN8710/20 Richard Leitner
  2017-11-20  8:34 ` [PATCH v2 1/3] net: ethernet: freescale: simplify fec_reset_phy Richard Leitner
  2017-11-20  8:34 ` [PATCH v2 2/3] include: linux: phy: harmonize phy_id{,_mask} type Richard Leitner
@ 2017-11-20  8:34 ` Richard Leitner
  2017-11-20  9:47   ` Andy Duan
  2 siblings, 1 reply; 13+ messages in thread
From: Richard Leitner @ 2017-11-20  8:34 UTC (permalink / raw)
  To: f.fainelli, fugang.duan, andrew; +Cc: netdev, linux-kernel, richard.leitner

From: Richard Leitner <richard.leitner@skidata.com>

Some PHYs (for example the SMSC LAN8710/LAN8720) doesn't allow turning
the refclk on and off again during operation (according to their
datasheet). Nonetheless exactly this behaviour was introduced for power
saving reasons by commit e8fcfcd5684a ("net: fec: optimize the clock management to save power").
Therefore after enabling the refclk we detect if an affected PHY is
attached. If so reset and initialize it again.

For a better understanding here's a outline of the time response of the
clock and reset lines before and after this patch:

			  v--fec_probe()              v--fec_enet_open()
			  v                           v
	w/o patch eCLK: ___||||||||____________________|||||||||||||||||
	w/o patch nRST: ----__------------------------------------------
	w/o patch CONF: _______XX_______________________________________

	w/  patch eCLK: ___||||||||____________________|||||||||||||||||
	w/  patch nRST: ----__-----------------------------__-----------
	w/  patch CONF: _______XX_____________________________XX________
			  ^                           ^
			  ^--fec_probe()              ^--fec_enet_open()

Generally speaking this issue is only relevant if the ref clk for the
PHY is generated by the SoC. In our specific case (PCB) this problem
does occur at about every 10th to 50th POR of an LAN8710 connected to an
i.MX6DL SoC. The typical symptom of this problem is a "swinging"
ethernet link. Similar issues were reported by users of the NXP forum:
	https://community.nxp.com/thread/389902
	https://community.nxp.com/message/309354
With this patch applied the issue didn't occur for at least a few
hundret PORs of our board.

Fixes: e8fcfcd5684a ("net: fec: optimize the clock management to save power")
Signed-off-by: Richard Leitner <richard.leitner@skidata.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 37 +++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 06a7caca0cee..52ec9b29a70e 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -68,6 +68,7 @@
 
 static void set_multicast_list(struct net_device *ndev);
 static void fec_enet_itr_coal_init(struct net_device *ndev);
+static int fec_reset_phy(struct net_device *ndev);
 
 #define DRIVER_NAME	"fec"
 
@@ -1833,6 +1834,32 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
 	return ret;
 }
 
+static int fec_enet_clk_ref_enable_reset_phy_quirk(struct net_device *ndev)
+{
+	struct phy_device *phy_dev = ndev->phydev;
+	u32 real_phy_id;
+	int ret;
+
+	/* some PHYs need a reset after the refclk was enabled, so we
+	 * reset them here
+	 */
+	if (!phy_dev)
+		return 0;
+	if (!phy_dev->drv)
+		return 0;
+	real_phy_id = phy_dev->drv->phy_id & phy_dev->drv->phy_id_mask;
+	switch (real_phy_id) {
+	case 0x0007c0f0: /* SMSC LAN8710/LAN8720 */
+		ret = fec_reset_phy(ndev);
+		if (ret)
+			return ret;
+		ret = phy_init_hw(phy_dev);
+		if (ret)
+			return ret;
+	}
+	return 0;
+}
+
 static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
@@ -1862,6 +1889,10 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
 		ret = clk_prepare_enable(fep->clk_ref);
 		if (ret)
 			goto failed_clk_ref;
+
+		ret = fec_enet_clk_ref_enable_reset_phy_quirk(ndev);
+		if (ret)
+			netdev_warn(ndev, "Resetting PHY failed, connection may be unstable\n");
 	} else {
 		clk_disable_unprepare(fep->clk_ahb);
 		clk_disable_unprepare(fep->clk_enet_out);
@@ -2860,11 +2891,17 @@ fec_enet_open(struct net_device *ndev)
 	if (ret)
 		goto err_enet_mii_probe;
 
+	/* as the PHY is connected now, trigger the reset quirk again */
+	ret = fec_enet_clk_ref_enable_reset_phy_quirk(ndev);
+	if (ret)
+		netdev_warn(ndev, "Resetting PHY failed, connection may be unstable\n");
+
 	if (fep->quirks & FEC_QUIRK_ERR006687)
 		imx6q_cpuidle_fec_irqs_used();
 
 	napi_enable(&fep->napi);
 	phy_start(ndev->phydev);
+
 	netif_tx_start_all_queues(ndev);
 
 	device_set_wakeup_enable(&ndev->dev, fep->wol_flag &
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* RE: [PATCH v2 1/3] net: ethernet: freescale: simplify fec_reset_phy
  2017-11-20  8:34 ` [PATCH v2 1/3] net: ethernet: freescale: simplify fec_reset_phy Richard Leitner
@ 2017-11-20  9:35   ` Andy Duan
  0 siblings, 0 replies; 13+ messages in thread
From: Andy Duan @ 2017-11-20  9:35 UTC (permalink / raw)
  To: Richard Leitner, f.fainelli, andrew; +Cc: netdev, linux-kernel, richard.leitner

From: Richard Leitner <dev@g0hl1n.net> Sent: Monday, November 20, 2017 4:34 PM
>The fec_reset_phy function allowed only one execution during probeing.
>To make it more usable move the dt parsing and gpio allocation to the probe
>function. The parameters of the phy reset are added to the fec_enet_private
>struct. As a result the fec_reset_phy function may be called anytime after
>probe.
>
>One checkpatch.pl warning (too long line) is ignored. This is due to the fact a
>string (dt property name) otherwise needs to be split over multiple lines,
>which is counterproductive for the readability.
>
>Signed-off-by: Richard Leitner <richard.leitner@skidata.com>
>---

It is better to convert to gpio descriptor, and use dts gpio flag as the gpio polarity instead of extra phy_reset_active_high variable.

Regards,
Andy

> drivers/net/ethernet/freescale/fec.h      |  4 ++
> drivers/net/ethernet/freescale/fec_main.c | 88 ++++++++++++++++----------
>-----
> 2 files changed, 50 insertions(+), 42 deletions(-)
>
>diff --git a/drivers/net/ethernet/freescale/fec.h
>b/drivers/net/ethernet/freescale/fec.h
>index 5385074b3b7d..401c4eabf08a 100644
>--- a/drivers/net/ethernet/freescale/fec.h
>+++ b/drivers/net/ethernet/freescale/fec.h
>@@ -539,6 +539,10 @@ struct fec_enet_private {
> 	int	pause_flag;
> 	int	wol_flag;
> 	u32	quirks;
>+	int	phy_reset;
>+	int	phy_reset_duration;
>+	int	phy_reset_post_delay;
>+	bool	phy_reset_active_high;
>
> 	struct	napi_struct napi;
> 	int	csum_flags;
>diff --git a/drivers/net/ethernet/freescale/fec_main.c
>b/drivers/net/ethernet/freescale/fec_main.c
>index 610573855213..06a7caca0cee 100644
>--- a/drivers/net/ethernet/freescale/fec_main.c
>+++ b/drivers/net/ethernet/freescale/fec_main.c
>@@ -3212,62 +3212,36 @@ static int fec_enet_init(struct net_device *ndev)  }
>
> #ifdef CONFIG_OF
>-static int fec_reset_phy(struct platform_device *pdev)
>+static int fec_reset_phy(struct net_device *ndev)
> {
>-	int err, phy_reset;
>-	bool active_high = false;
>-	int msec = 1, phy_post_delay = 0;
>-	struct device_node *np = pdev->dev.of_node;
>-
>-	if (!np)
>-		return 0;
>-
>-	err = of_property_read_u32(np, "phy-reset-duration", &msec);
>-	/* A sane reset duration should not be longer than 1s */
>-	if (!err && msec > 1000)
>-		msec = 1;
>+	struct fec_enet_private *fep = netdev_priv(ndev);
>
>-	phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0);
>-	if (phy_reset == -EPROBE_DEFER)
>-		return phy_reset;
>-	else if (!gpio_is_valid(phy_reset))
>+	if (!fep->phy_reset)
> 		return 0;
>
>-	err = of_property_read_u32(np, "phy-reset-post-delay",
>&phy_post_delay);
>-	/* valid reset duration should be less than 1s */
>-	if (!err && phy_post_delay > 1000)
>-		return -EINVAL;
>-
>-	active_high = of_property_read_bool(np, "phy-reset-active-high");
>+	gpio_set_value_cansleep(fep->phy_reset, fep-
>>phy_reset_active_high);
>
>-	err = devm_gpio_request_one(&pdev->dev, phy_reset,
>-			active_high ? GPIOF_OUT_INIT_HIGH :
>GPIOF_OUT_INIT_LOW,
>-			"phy-reset");
>-	if (err) {
>-		dev_err(&pdev->dev, "failed to get phy-reset-gpios: %d\n",
>err);
>-		return err;
>-	}
>-
>-	if (msec > 20)
>-		msleep(msec);
>+	if (fep->phy_reset_duration > 20)
>+		msleep(fep->phy_reset_duration);
> 	else
>-		usleep_range(msec * 1000, msec * 1000 + 1000);
>+		usleep_range(fep->phy_reset_duration * 1000,
>+			     fep->phy_reset_duration * 1000 + 1000);
>
>-	gpio_set_value_cansleep(phy_reset, !active_high);
>+	gpio_set_value_cansleep(fep->phy_reset, !fep-
>>phy_reset_active_high);
>
>-	if (!phy_post_delay)
>+	if (!fep->phy_reset_post_delay)
> 		return 0;
>
>-	if (phy_post_delay > 20)
>-		msleep(phy_post_delay);
>+	if (fep->phy_reset_post_delay > 20)
>+		msleep(fep->phy_reset_post_delay);
> 	else
>-		usleep_range(phy_post_delay * 1000,
>-			     phy_post_delay * 1000 + 1000);
>+		usleep_range(fep->phy_reset_post_delay * 1000,
>+			     fep->phy_reset_post_delay * 1000 + 1000);
>
> 	return 0;
> }
> #else /* CONFIG_OF */
>-static int fec_reset_phy(struct platform_device *pdev)
>+static int fec_reset_phy(struct net_device *ndev)
> {
> 	/*
> 	 * In case of platform probe, the reset has been done @@ -3400,6
>+3374,36 @@ fec_probe(struct platform_device *pdev)
> 	}
> 	fep->phy_node = phy_node;
>
>+	fep->phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0);
>+	if (gpio_is_valid(fep->phy_reset)) {
>+		ret = of_property_read_u32(np, "phy-reset-duration",
>+					   &fep->phy_reset_duration);
>+		/* A sane reset duration should not be longer than 1s */
>+		if (!ret && fep->phy_reset_post_delay > 1000)
>+			fep->phy_reset_post_delay = 1;
>+
>+		ret = of_property_read_u32(np, "phy-reset-post-delay",
>+					   &fep->phy_reset_post_delay);
>+		/* valid post reset delay should be less than 1s */
>+		if (!ret && fep->phy_reset_post_delay > 1000)
>+			fep->phy_reset_post_delay = 1;
>+
>+		fep->phy_reset_active_high = of_property_read_bool(np,
>+"phy-reset-active-high");
>+
>+		ret = devm_gpio_request_one(&pdev->dev, fep->phy_reset,
>+					    fep->phy_reset_active_high ?
>+					    GPIOF_OUT_INIT_HIGH :
>+					    GPIOF_OUT_INIT_LOW,
>+					    "phy-reset");
>+		if (ret) {
>+			dev_err(&pdev->dev, "failed to get reset-
>gpios: %d\n",
>+				ret);
>+			goto failed_phy;
>+		}
>+	} else {
>+		fep->phy_reset = 0;
>+	}
>+
> 	ret = of_get_phy_mode(pdev->dev.of_node);
> 	if (ret < 0) {
> 		pdata = dev_get_platdata(&pdev->dev); @@ -3472,7 +3476,7
>@@ fec_probe(struct platform_device *pdev)
> 	pm_runtime_set_active(&pdev->dev);
> 	pm_runtime_enable(&pdev->dev);
>
>-	ret = fec_reset_phy(pdev);
>+	ret = fec_reset_phy(ndev);
> 	if (ret)
> 		goto failed_reset;
>
>--
>2.11.0

^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: [PATCH v2 3/3] net: ethernet: fec: fix refclk enable for SMSC LAN8710/20
  2017-11-20  8:34 ` [PATCH v2 3/3] net: ethernet: fec: fix refclk enable for SMSC LAN8710/20 Richard Leitner
@ 2017-11-20  9:47   ` Andy Duan
  2017-11-20  9:57     ` Richard Leitner
  0 siblings, 1 reply; 13+ messages in thread
From: Andy Duan @ 2017-11-20  9:47 UTC (permalink / raw)
  To: Richard Leitner, f.fainelli, andrew; +Cc: netdev, linux-kernel, richard.leitner

From: Richard Leitner <dev@g0hl1n.net> Sent: Monday, November 20, 2017 4:34 PM
>To: f.fainelli@gmail.com; Andy Duan <fugang.duan@nxp.com>;
>andrew@lunn.ch
>Cc: netdev@vger.kernel.org; linux-kernel@vger.kernel.org;
>richard.leitner@skidata.com
>Subject: [PATCH v2 3/3] net: ethernet: fec: fix refclk enable for SMSC
>LAN8710/20
>
>From: Richard Leitner <richard.leitner@skidata.com>
>
>Some PHYs (for example the SMSC LAN8710/LAN8720) doesn't allow turning
>the refclk on and off again during operation (according to their datasheet).
>Nonetheless exactly this behaviour was introduced for power saving reasons
>by commit e8fcfcd5684a ("net: fec: optimize the clock management to save
>power").
>Therefore after enabling the refclk we detect if an affected PHY is attached. If
>so reset and initialize it again.
>
>For a better understanding here's a outline of the time response of the clock
>and reset lines before and after this patch:
>
>			  v--fec_probe()              v--fec_enet_open()
>			  v                           v
>	w/o patch eCLK:
>___||||||||____________________|||||||||||||||||
>	w/o patch nRST: ----__------------------------------------------
>	w/o patch CONF:
>_______XX_______________________________________
>
>	w/  patch eCLK:
>___||||||||____________________|||||||||||||||||
>	w/  patch nRST: ----__-----------------------------__-----------
>	w/  patch CONF:
>_______XX_____________________________XX________
>			  ^                           ^
>			  ^--fec_probe()              ^--fec_enet_open()
>
>Generally speaking this issue is only relevant if the ref clk for the PHY is
>generated by the SoC. In our specific case (PCB) this problem does occur at
>about every 10th to 50th POR of an LAN8710 connected to an i.MX6DL SoC.
>The typical symptom of this problem is a "swinging"
>ethernet link. Similar issues were reported by users of the NXP forum:
>	https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F
>%2Fcommunity.nxp.com%2Fthread%2F389902&data=02%7C01%7Cfugang.du
>an%40nxp.com%7C507c7aafbd4744f81ebf08d52ff1acff%7C686ea1d3bc2b4c6f
>a92cd99c5c301635%7C0%7C0%7C636467637399145483&sdata=RNXVGpPrlrcyL
>0SoQl8%2BI0k8Oc8BM0Iwykd1O%2Bjmvcc%3D&reserved=0
>	https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F
>%2Fcommunity.nxp.com%2Fmessage%2F309354&data=02%7C01%7Cfugang.d
>uan%40nxp.com%7C507c7aafbd4744f81ebf08d52ff1acff%7C686ea1d3bc2b4c6
>fa92cd99c5c301635%7C0%7C0%7C636467637399145483&sdata=pjeJEZGuBpb9
>uCMKGr70qa%2FmsNoak6v3nCID2vbNAeg%3D&reserved=0
>With this patch applied the issue didn't occur for at least a few hundret PORs
>of our board.
>
>Fixes: e8fcfcd5684a ("net: fec: optimize the clock management to save
>power")
>Signed-off-by: Richard Leitner <richard.leitner@skidata.com>
>---
> drivers/net/ethernet/freescale/fec_main.c | 37
>+++++++++++++++++++++++++++++++
> 1 file changed, 37 insertions(+)
>
>diff --git a/drivers/net/ethernet/freescale/fec_main.c
>b/drivers/net/ethernet/freescale/fec_main.c
>index 06a7caca0cee..52ec9b29a70e 100644
>--- a/drivers/net/ethernet/freescale/fec_main.c
>+++ b/drivers/net/ethernet/freescale/fec_main.c
>@@ -68,6 +68,7 @@
>
> static void set_multicast_list(struct net_device *ndev);  static void
>fec_enet_itr_coal_init(struct net_device *ndev);
>+static int fec_reset_phy(struct net_device *ndev);
>
> #define DRIVER_NAME	"fec"
>
>@@ -1833,6 +1834,32 @@ static int fec_enet_mdio_write(struct mii_bus *bus,
>int mii_id, int regnum,
> 	return ret;
> }
>
>+static int fec_enet_clk_ref_enable_reset_phy_quirk(struct net_device
>+*ndev) {
>+	struct phy_device *phy_dev = ndev->phydev;
>+	u32 real_phy_id;
>+	int ret;
>+
>+	/* some PHYs need a reset after the refclk was enabled, so we
>+	 * reset them here
>+	 */
>+	if (!phy_dev)
>+		return 0;
>+	if (!phy_dev->drv)
>+		return 0;
>+	real_phy_id = phy_dev->drv->phy_id & phy_dev->drv->phy_id_mask;
>+	switch (real_phy_id) {
>+	case 0x0007c0f0: /* SMSC LAN8710/LAN8720 */

Don't hard code here...
I believe there have many other phys also do such operation, hardcode is unacceptable...

And these code can be put into phy_device.c as common interface.

>+		ret = fec_reset_phy(ndev);
>+		if (ret)
>+			return ret;
>+		ret = phy_init_hw(phy_dev);
>+		if (ret)
>+			return ret;
>+	}
>+	return 0;
>+}
>+
> static int fec_enet_clk_enable(struct net_device *ndev, bool enable)  {
> 	struct fec_enet_private *fep = netdev_priv(ndev); @@ -1862,6
>+1889,10 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool
>enable)
> 		ret = clk_prepare_enable(fep->clk_ref);
> 		if (ret)
> 			goto failed_clk_ref;
>+
>+		ret = fec_enet_clk_ref_enable_reset_phy_quirk(ndev);
>+		if (ret)
>+			netdev_warn(ndev, "Resetting PHY failed, connection
>may be
>+unstable\n");
> 	} else {
> 		clk_disable_unprepare(fep->clk_ahb);
> 		clk_disable_unprepare(fep->clk_enet_out);
>@@ -2860,11 +2891,17 @@ fec_enet_open(struct net_device *ndev)
> 	if (ret)
> 		goto err_enet_mii_probe;
>
>+	/* as the PHY is connected now, trigger the reset quirk again */
>+	ret = fec_enet_clk_ref_enable_reset_phy_quirk(ndev);
>+	if (ret)
>+		netdev_warn(ndev, "Resetting PHY failed, connection may be
>+unstable\n");
>+
> 	if (fep->quirks & FEC_QUIRK_ERR006687)
> 		imx6q_cpuidle_fec_irqs_used();
>
> 	napi_enable(&fep->napi);
> 	phy_start(ndev->phydev);
>+

No need blank line here...
> 	netif_tx_start_all_queues(ndev);
>
> 	device_set_wakeup_enable(&ndev->dev, fep->wol_flag &
>--
>2.11.0

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 3/3] net: ethernet: fec: fix refclk enable for SMSC LAN8710/20
  2017-11-20  9:47   ` Andy Duan
@ 2017-11-20  9:57     ` Richard Leitner
  2017-11-20 10:35       ` Andy Duan
  0 siblings, 1 reply; 13+ messages in thread
From: Richard Leitner @ 2017-11-20  9:57 UTC (permalink / raw)
  To: Andy Duan, f.fainelli, andrew; +Cc: Richard Leitner, netdev, linux-kernel


On 11/20/2017 10:47 AM, Andy Duan wrote:
> From: Richard Leitner <dev@g0hl1n.net> Sent: Monday, November 20, 2017 4:34 PM
>> To: f.fainelli@gmail.com; Andy Duan <fugang.duan@nxp.com>;
>> andrew@lunn.ch
>> Cc: netdev@vger.kernel.org; linux-kernel@vger.kernel.org;
>> richard.leitner@skidata.com
>> Subject: [PATCH v2 3/3] net: ethernet: fec: fix refclk enable for SMSC
>> LAN8710/20
>>
>> From: Richard Leitner <richard.leitner@skidata.com>
>>
>> Some PHYs (for example the SMSC LAN8710/LAN8720) doesn't allow turning
>> the refclk on and off again during operation (according to their datasheet).
>> Nonetheless exactly this behaviour was introduced for power saving reasons
>> by commit e8fcfcd5684a ("net: fec: optimize the clock management to save
>> power").
>> Therefore after enabling the refclk we detect if an affected PHY is attached. If
>> so reset and initialize it again.

...

>> +static int fec_enet_clk_ref_enable_reset_phy_quirk(struct net_device
>> +*ndev) {
>> +	struct phy_device *phy_dev = ndev->phydev;
>> +	u32 real_phy_id;
>> +	int ret;
>> +
>> +	/* some PHYs need a reset after the refclk was enabled, so we
>> +	 * reset them here
>> +	 */
>> +	if (!phy_dev)
>> +		return 0;
>> +	if (!phy_dev->drv)
>> +		return 0;
>> +	real_phy_id = phy_dev->drv->phy_id & phy_dev->drv->phy_id_mask;
>> +	switch (real_phy_id) {
>> +	case 0x0007c0f0: /* SMSC LAN8710/LAN8720 */
> 
> Don't hard code here...
> I believe there have many other phys also do such operation, hardcode is unacceptable...
> 
> And these code can be put into phy_device.c as common interface.

Ok. Thank you for the feedback.
So it would be fine to hardcode the affected phy_id's in a common
function in phy_device.c?


Another possible solution that came to my mind is to add a flag called
something like "PHY_RST_AFTER_CLK_EN" to the flags variable in struct
phy_driver. This flag could then be set in the smsc PHY driver for
affected PHYs.

Then instead of comparing the phy_id in the MAC driver this flag could
be checked:

if (phydev->drv->flags & PHY_RST_AFTER_CLK_EN) {
    ret = fec_reset_phy(ndev);
    ...
}

Would checking the flag be OK in fec_main.c?

What would be the "better" approach?

> 
>> +		ret = fec_reset_phy(ndev);
>> +		if (ret)
>> +			return ret;
>> +		ret = phy_init_hw(phy_dev);
>> +		if (ret)
>> +			return ret;
>> +	}
>> +	return 0;
>> +}
>> +
>> static int fec_enet_clk_enable(struct net_device *ndev, bool enable)  {
>> 	struct fec_enet_private *fep = netdev_priv(ndev); @@ -1862,6
>> +1889,10 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool
>> enable)
>> 		ret = clk_prepare_enable(fep->clk_ref);
>> 		if (ret)
>> 			goto failed_clk_ref;
>> +
>> +		ret = fec_enet_clk_ref_enable_reset_phy_quirk(ndev);
>> +		if (ret)
>> +			netdev_warn(ndev, "Resetting PHY failed, connection
>> may be
>> +unstable\n");
>> 	} else {
>> 		clk_disable_unprepare(fep->clk_ahb);
>> 		clk_disable_unprepare(fep->clk_enet_out);
>> @@ -2860,11 +2891,17 @@ fec_enet_open(struct net_device *ndev)
>> 	if (ret)
>> 		goto err_enet_mii_probe;
>>
>> +	/* as the PHY is connected now, trigger the reset quirk again */
>> +	ret = fec_enet_clk_ref_enable_reset_phy_quirk(ndev);
>> +	if (ret)
>> +		netdev_warn(ndev, "Resetting PHY failed, connection may be
>> +unstable\n");
>> +
>> 	if (fep->quirks & FEC_QUIRK_ERR006687)
>> 		imx6q_cpuidle_fec_irqs_used();
>>
>> 	napi_enable(&fep->napi);
>> 	phy_start(ndev->phydev);
>> +
> 
> No need blank line here...
>> 	netif_tx_start_all_queues(ndev);
>>
>> 	device_set_wakeup_enable(&ndev->dev, fep->wol_flag &
>> --
>> 2.11.0

^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: [PATCH v2 3/3] net: ethernet: fec: fix refclk enable for SMSC LAN8710/20
  2017-11-20  9:57     ` Richard Leitner
@ 2017-11-20 10:35       ` Andy Duan
  2017-11-20 12:55         ` Richard Leitner
  0 siblings, 1 reply; 13+ messages in thread
From: Andy Duan @ 2017-11-20 10:35 UTC (permalink / raw)
  To: Richard Leitner, f.fainelli, andrew; +Cc: Richard Leitner, netdev, linux-kernel

From: Richard Leitner <richard.leitner@skidata.com> Sent: Monday, November 20, 2017 5:57 PM
>To: Andy Duan <fugang.duan@nxp.com>; f.fainelli@gmail.com;
>andrew@lunn.ch
>Cc: Richard Leitner <dev@g0hl1n.net>; netdev@vger.kernel.org; linux-
>kernel@vger.kernel.org
>Subject: Re: [PATCH v2 3/3] net: ethernet: fec: fix refclk enable for SMSC
>LAN8710/20
>
>
>On 11/20/2017 10:47 AM, Andy Duan wrote:
>> From: Richard Leitner <dev@g0hl1n.net> Sent: Monday, November 20, 2017
>> 4:34 PM
>>> To: f.fainelli@gmail.com; Andy Duan <fugang.duan@nxp.com>;
>>> andrew@lunn.ch
>>> Cc: netdev@vger.kernel.org; linux-kernel@vger.kernel.org;
>>> richard.leitner@skidata.com
>>> Subject: [PATCH v2 3/3] net: ethernet: fec: fix refclk enable for
>>> SMSC
>>> LAN8710/20
>>>
>>> From: Richard Leitner <richard.leitner@skidata.com>
>>>
>>> Some PHYs (for example the SMSC LAN8710/LAN8720) doesn't allow
>>> turning the refclk on and off again during operation (according to their
>datasheet).
>>> Nonetheless exactly this behaviour was introduced for power saving
>>> reasons by commit e8fcfcd5684a ("net: fec: optimize the clock
>>> management to save power").
>>> Therefore after enabling the refclk we detect if an affected PHY is
>>> attached. If so reset and initialize it again.
>
>...
>
>>> +static int fec_enet_clk_ref_enable_reset_phy_quirk(struct net_device
>>> +*ndev) {
>>> +	struct phy_device *phy_dev = ndev->phydev;
>>> +	u32 real_phy_id;
>>> +	int ret;
>>> +
>>> +	/* some PHYs need a reset after the refclk was enabled, so we
>>> +	 * reset them here
>>> +	 */
>>> +	if (!phy_dev)
>>> +		return 0;
>>> +	if (!phy_dev->drv)
>>> +		return 0;
>>> +	real_phy_id = phy_dev->drv->phy_id & phy_dev->drv->phy_id_mask;
>>> +	switch (real_phy_id) {
>>> +	case 0x0007c0f0: /* SMSC LAN8710/LAN8720 */
>>
>> Don't hard code here...
>> I believe there have many other phys also do such operation, hardcode is
>unacceptable...
>>
>> And these code can be put into phy_device.c as common interface.
>
>Ok. Thank you for the feedback.
>So it would be fine to hardcode the affected phy_id's in a common function in
>phy_device.c?
>
>
>Another possible solution that came to my mind is to add a flag called
>something like "PHY_RST_AFTER_CLK_EN" to the flags variable in struct
>phy_driver. This flag could then be set in the smsc PHY driver for affected
>PHYs.
>
>Then instead of comparing the phy_id in the MAC driver this flag could be
>checked:
>
>if (phydev->drv->flags & PHY_RST_AFTER_CLK_EN) {
>    ret = fec_reset_phy(ndev);
>    ...
>}
>
>Would checking the flag be OK in fec_main.c?

Yes, it is better than previous solution.
But add new common API in phy_device.c is much better like: 
1. add a flag called "PHY_RST_AFTER_CLK_EN" to the flags variable in struct phy_driver,  all phy driver that need reset can set the flag.
2. add new common api interface phy_reset_after_clk_enable() in phy_device.c driver
3. add reset gpio descriptor for common phy device driver. 
4. then any mac driver can directly call the common interface .phy_reset_after_clk_enable().

That is only my suggestion, maybe there have better idea.
Thanks.

>
>What would be the "better" approach?
>
>>
>>> +		ret = fec_reset_phy(ndev);
>>> +		if (ret)
>>> +			return ret;
>>> +		ret = phy_init_hw(phy_dev);
>>> +		if (ret)
>>> +			return ret;
>>> +	}
>>> +	return 0;
>>> +}
>>> +
>>> static int fec_enet_clk_enable(struct net_device *ndev, bool enable)  {
>>> 	struct fec_enet_private *fep = netdev_priv(ndev); @@ -1862,6
>>> +1889,10 @@ static int fec_enet_clk_enable(struct net_device *ndev,
>>> +bool
>>> enable)
>>> 		ret = clk_prepare_enable(fep->clk_ref);
>>> 		if (ret)
>>> 			goto failed_clk_ref;
>>> +
>>> +		ret = fec_enet_clk_ref_enable_reset_phy_quirk(ndev);
>>> +		if (ret)
>>> +			netdev_warn(ndev, "Resetting PHY failed, connection
>>> may be
>>> +unstable\n");
>>> 	} else {
>>> 		clk_disable_unprepare(fep->clk_ahb);
>>> 		clk_disable_unprepare(fep->clk_enet_out);
>>> @@ -2860,11 +2891,17 @@ fec_enet_open(struct net_device *ndev)
>>> 	if (ret)
>>> 		goto err_enet_mii_probe;
>>>
>>> +	/* as the PHY is connected now, trigger the reset quirk again */
>>> +	ret = fec_enet_clk_ref_enable_reset_phy_quirk(ndev);
>>> +	if (ret)
>>> +		netdev_warn(ndev, "Resetting PHY failed, connection may be
>>> +unstable\n");
>>> +
>>> 	if (fep->quirks & FEC_QUIRK_ERR006687)
>>> 		imx6q_cpuidle_fec_irqs_used();
>>>
>>> 	napi_enable(&fep->napi);
>>> 	phy_start(ndev->phydev);
>>> +
>>
>> No need blank line here...
>>> 	netif_tx_start_all_queues(ndev);
>>>
>>> 	device_set_wakeup_enable(&ndev->dev, fep->wol_flag &
>>> --
>>> 2.11.0

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 3/3] net: ethernet: fec: fix refclk enable for SMSC LAN8710/20
  2017-11-20 10:35       ` Andy Duan
@ 2017-11-20 12:55         ` Richard Leitner
  2017-11-20 13:13           ` Geert Uytterhoeven
  2017-11-20 13:43           ` Andy Duan
  0 siblings, 2 replies; 13+ messages in thread
From: Richard Leitner @ 2017-11-20 12:55 UTC (permalink / raw)
  To: Andy Duan, f.fainelli, andrew
  Cc: Richard Leitner, netdev, linux-kernel, Sergei Shtylyov,
	Geert Uytterhoeven

On 11/20/2017 11:35 AM, Andy Duan wrote:
> From: Richard Leitner <richard.leitner@skidata.com> Sent: Monday, November 20, 2017 5:57 PM
>> To: Andy Duan <fugang.duan@nxp.com>; f.fainelli@gmail.com;
>> andrew@lunn.ch
>> Cc: Richard Leitner <dev@g0hl1n.net>; netdev@vger.kernel.org; linux-
>> kernel@vger.kernel.org
>> Subject: Re: [PATCH v2 3/3] net: ethernet: fec: fix refclk enable for SMSC
>> LAN8710/20
>>
>>
>> On 11/20/2017 10:47 AM, Andy Duan wrote:
>>> From: Richard Leitner <dev@g0hl1n.net> Sent: Monday, November 20, 2017
>>> 4:34 PM
>>>> To: f.fainelli@gmail.com; Andy Duan <fugang.duan@nxp.com>;
>>>> andrew@lunn.ch
>>>> Cc: netdev@vger.kernel.org; linux-kernel@vger.kernel.org;
>>>> richard.leitner@skidata.com
>>>> Subject: [PATCH v2 3/3] net: ethernet: fec: fix refclk enable for
>>>> SMSC
>>>> LAN8710/20
>>>>
>>>> From: Richard Leitner <richard.leitner@skidata.com>
>>>>
>>>> Some PHYs (for example the SMSC LAN8710/LAN8720) doesn't allow
>>>> turning the refclk on and off again during operation (according to their
>> datasheet).
>>>> Nonetheless exactly this behaviour was introduced for power saving
>>>> reasons by commit e8fcfcd5684a ("net: fec: optimize the clock
>>>> management to save power").
>>>> Therefore after enabling the refclk we detect if an affected PHY is
>>>> attached. If so reset and initialize it again.
>> ...
>>
>>>> +static int fec_enet_clk_ref_enable_reset_phy_quirk(struct net_device
>>>> +*ndev) {
>>>> +	struct phy_device *phy_dev = ndev->phydev;
>>>> +	u32 real_phy_id;
>>>> +	int ret;
>>>> +
>>>> +	/* some PHYs need a reset after the refclk was enabled, so we
>>>> +	 * reset them here
>>>> +	 */
>>>> +	if (!phy_dev)
>>>> +		return 0;
>>>> +	if (!phy_dev->drv)
>>>> +		return 0;
>>>> +	real_phy_id = phy_dev->drv->phy_id & phy_dev->drv->phy_id_mask;
>>>> +	switch (real_phy_id) {
>>>> +	case 0x0007c0f0: /* SMSC LAN8710/LAN8720 */
>>> Don't hard code here...
>>> I believe there have many other phys also do such operation, hardcode is
>> unacceptable...
>>> And these code can be put into phy_device.c as common interface.
>> Ok. Thank you for the feedback.
>> So it would be fine to hardcode the affected phy_id's in a common function in
>> phy_device.c?
>>
>>
>> Another possible solution that came to my mind is to add a flag called
>> something like "PHY_RST_AFTER_CLK_EN" to the flags variable in struct
>> phy_driver. This flag could then be set in the smsc PHY driver for affected
>> PHYs.
>>
>> Then instead of comparing the phy_id in the MAC driver this flag could be
>> checked:
>>
>> if (phydev->drv->flags & PHY_RST_AFTER_CLK_EN) {
>>    ret = fec_reset_phy(ndev);
>>    ...
>> }
>>
>> Would checking the flag be OK in fec_main.c?
> Yes, it is better than previous solution.
> But add new common API in phy_device.c is much better like: 
> 1. add a flag called "PHY_RST_AFTER_CLK_EN" to the flags variable in struct phy_driver,  all phy driver that need reset can set the flag.

OK.

> 2. add new common api interface phy_reset_after_clk_enable() in phy_device.c driver

OK. But see below...

> 3. add reset gpio descriptor for common phy device driver. 

... if I understood it correctly the patch called "Teach phylib
hard-resetting devices" by Geert and Sergei is exactly doing this:
	https://patchwork.ozlabs.org/cover/828503/
	https://lkml.org/lkml/2017/10/20/166

So I'll implement the phy_reset_after_clk_enable function atop of this
patch-set and add a note that my patch-series depends on it. Would that
be OK?

> 4. then any mac driver can directly call the common interface .phy_reset_after_clk_enable().

Sounds reasonable :-)

> 
> That is only my suggestion, maybe there have better idea.
> Thanks.
> 

Thanks for your quick feedback.

regards
Richard.L

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 3/3] net: ethernet: fec: fix refclk enable for SMSC LAN8710/20
  2017-11-20 12:55         ` Richard Leitner
@ 2017-11-20 13:13           ` Geert Uytterhoeven
  2017-11-20 13:21             ` Richard Leitner
  2017-11-20 13:43           ` Andy Duan
  1 sibling, 1 reply; 13+ messages in thread
From: Geert Uytterhoeven @ 2017-11-20 13:13 UTC (permalink / raw)
  To: Richard Leitner
  Cc: Andy Duan, f.fainelli, andrew, Richard Leitner, netdev,
	linux-kernel, Sergei Shtylyov, Geert Uytterhoeven

Hi Richard,

On Mon, Nov 20, 2017 at 1:55 PM, Richard Leitner
<richard.leitner@skidata.com> wrote:
> On 11/20/2017 11:35 AM, Andy Duan wrote:
>> 3. add reset gpio descriptor for common phy device driver.
>
> ... if I understood it correctly the patch called "Teach phylib
> hard-resetting devices" by Geert and Sergei is exactly doing this:
>         https://patchwork.ozlabs.org/cover/828503/
>         https://lkml.org/lkml/2017/10/20/166
>
> So I'll implement the phy_reset_after_clk_enable function atop of this
> patch-set and add a note that my patch-series depends on it. Would that
> be OK?

I will update and respin that patch series after the merge window has closed.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 3/3] net: ethernet: fec: fix refclk enable for SMSC LAN8710/20
  2017-11-20 13:13           ` Geert Uytterhoeven
@ 2017-11-20 13:21             ` Richard Leitner
  2017-11-20 13:40               ` Geert Uytterhoeven
  0 siblings, 1 reply; 13+ messages in thread
From: Richard Leitner @ 2017-11-20 13:21 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Andy Duan, f.fainelli, andrew, Richard Leitner, netdev,
	linux-kernel, Sergei Shtylyov, Geert Uytterhoeven


On 11/20/2017 02:13 PM, Geert Uytterhoeven wrote:
> Hi Richard,
> 
> On Mon, Nov 20, 2017 at 1:55 PM, Richard Leitner
> <richard.leitner@skidata.com> wrote:
>> On 11/20/2017 11:35 AM, Andy Duan wrote:
>>> 3. add reset gpio descriptor for common phy device driver.
>>
>> ... if I understood it correctly the patch called "Teach phylib
>> hard-resetting devices" by Geert and Sergei is exactly doing this:
>>         https://patchwork.ozlabs.org/cover/828503/
>>         https://lkml.org/lkml/2017/10/20/166
>>
>> So I'll implement the phy_reset_after_clk_enable function atop of this
>> patch-set and add a note that my patch-series depends on it. Would that
>> be OK?
> 
> I will update and respin that patch series after the merge window has closed.

Ok. Thank you for the quick response an this information.

For the Freescale Fast Ethernet Controller (FEC) there are currently (in
addition to the reset gpio) two additional optional dt properties for
the reset:
 - phy-reset-duration : Reset duration in milliseconds.
 - phy-reset-post-delay : Post reset delay in milliseconds.

IMHO it would make sense to include them also in the phylib
implementation. What do you think about it? Should I include it in my
patch-series?

kind regards;
Richard.L

> 
> Gr{oetje,eeting}s,
> 
>                         Geert
> 
> --
> Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
> 
> In personal conversations with technical people, I call myself a hacker. But
> when I'm talking to journalists I just say "programmer" or something like that.
>                                 -- Linus Torvalds
> 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 3/3] net: ethernet: fec: fix refclk enable for SMSC LAN8710/20
  2017-11-20 13:21             ` Richard Leitner
@ 2017-11-20 13:40               ` Geert Uytterhoeven
  0 siblings, 0 replies; 13+ messages in thread
From: Geert Uytterhoeven @ 2017-11-20 13:40 UTC (permalink / raw)
  To: Richard Leitner
  Cc: Andy Duan, f.fainelli, andrew, Richard Leitner, netdev,
	linux-kernel, Sergei Shtylyov, Geert Uytterhoeven

Hi Richard,

On Mon, Nov 20, 2017 at 2:21 PM, Richard Leitner
<richard.leitner@skidata.com> wrote:
> On 11/20/2017 02:13 PM, Geert Uytterhoeven wrote:
>> On Mon, Nov 20, 2017 at 1:55 PM, Richard Leitner
>> <richard.leitner@skidata.com> wrote:
>>> On 11/20/2017 11:35 AM, Andy Duan wrote:
>>>> 3. add reset gpio descriptor for common phy device driver.
>>>
>>> ... if I understood it correctly the patch called "Teach phylib
>>> hard-resetting devices" by Geert and Sergei is exactly doing this:
>>>         https://patchwork.ozlabs.org/cover/828503/
>>>         https://lkml.org/lkml/2017/10/20/166
>>>
>>> So I'll implement the phy_reset_after_clk_enable function atop of this
>>> patch-set and add a note that my patch-series depends on it. Would that
>>> be OK?
>>
>> I will update and respin that patch series after the merge window has closed.
>
> Ok. Thank you for the quick response an this information.
>
> For the Freescale Fast Ethernet Controller (FEC) there are currently (in
> addition to the reset gpio) two additional optional dt properties for
> the reset:
>  - phy-reset-duration : Reset duration in milliseconds.
>  - phy-reset-post-delay : Post reset delay in milliseconds.
>
> IMHO it would make sense to include them also in the phylib
> implementation. What do you think about it? Should I include it in my
> patch-series?

Sure, you can always extend phylib, building on top of our simple reset
implementation.

BTW, I think phy-reset-{duration,post-delay} should be moved to the
phy node as well, dropping the "phy-" prefix in the process.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: [PATCH v2 3/3] net: ethernet: fec: fix refclk enable for SMSC LAN8710/20
  2017-11-20 12:55         ` Richard Leitner
  2017-11-20 13:13           ` Geert Uytterhoeven
@ 2017-11-20 13:43           ` Andy Duan
  1 sibling, 0 replies; 13+ messages in thread
From: Andy Duan @ 2017-11-20 13:43 UTC (permalink / raw)
  To: Richard Leitner, f.fainelli, andrew
  Cc: Richard Leitner, netdev, linux-kernel, Sergei Shtylyov,
	Geert Uytterhoeven

From: Richard Leitner <richard.leitner@skidata.com> Sent: Monday, November 20, 2017 8:55 PM
>On 11/20/2017 11:35 AM, Andy Duan wrote:
>> From: Richard Leitner <richard.leitner@skidata.com> Sent: Monday,
>> November 20, 2017 5:57 PM
>>> To: Andy Duan <fugang.duan@nxp.com>; f.fainelli@gmail.com;
>>> andrew@lunn.ch
>>> Cc: Richard Leitner <dev@g0hl1n.net>; netdev@vger.kernel.org; linux-
>>> kernel@vger.kernel.org
>>> Subject: Re: [PATCH v2 3/3] net: ethernet: fec: fix refclk enable for
>>> SMSC
>>> LAN8710/20
>>>
>>>
>>> On 11/20/2017 10:47 AM, Andy Duan wrote:
>>>> From: Richard Leitner <dev@g0hl1n.net> Sent: Monday, November 20,
>>>> 2017
>>>> 4:34 PM
>>>>> To: f.fainelli@gmail.com; Andy Duan <fugang.duan@nxp.com>;
>>>>> andrew@lunn.ch
>>>>> Cc: netdev@vger.kernel.org; linux-kernel@vger.kernel.org;
>>>>> richard.leitner@skidata.com
>>>>> Subject: [PATCH v2 3/3] net: ethernet: fec: fix refclk enable for
>>>>> SMSC
>>>>> LAN8710/20
>>>>>
>>>>> From: Richard Leitner <richard.leitner@skidata.com>
>>>>>
>>>>> Some PHYs (for example the SMSC LAN8710/LAN8720) doesn't allow
>>>>> turning the refclk on and off again during operation (according to
>>>>> their
>>> datasheet).
>>>>> Nonetheless exactly this behaviour was introduced for power saving
>>>>> reasons by commit e8fcfcd5684a ("net: fec: optimize the clock
>>>>> management to save power").
>>>>> Therefore after enabling the refclk we detect if an affected PHY is
>>>>> attached. If so reset and initialize it again.
>>> ...
>>>
>>>>> +static int fec_enet_clk_ref_enable_reset_phy_quirk(struct
>>>>> +net_device
>>>>> +*ndev) {
>>>>> +	struct phy_device *phy_dev = ndev->phydev;
>>>>> +	u32 real_phy_id;
>>>>> +	int ret;
>>>>> +
>>>>> +	/* some PHYs need a reset after the refclk was enabled, so we
>>>>> +	 * reset them here
>>>>> +	 */
>>>>> +	if (!phy_dev)
>>>>> +		return 0;
>>>>> +	if (!phy_dev->drv)
>>>>> +		return 0;
>>>>> +	real_phy_id = phy_dev->drv->phy_id & phy_dev->drv->phy_id_mask;
>>>>> +	switch (real_phy_id) {
>>>>> +	case 0x0007c0f0: /* SMSC LAN8710/LAN8720 */
>>>> Don't hard code here...
>>>> I believe there have many other phys also do such operation,
>>>> hardcode is
>>> unacceptable...
>>>> And these code can be put into phy_device.c as common interface.
>>> Ok. Thank you for the feedback.
>>> So it would be fine to hardcode the affected phy_id's in a common
>>> function in phy_device.c?
>>>
>>>
>>> Another possible solution that came to my mind is to add a flag
>>> called something like "PHY_RST_AFTER_CLK_EN" to the flags variable in
>>> struct phy_driver. This flag could then be set in the smsc PHY driver
>>> for affected PHYs.
>>>
>>> Then instead of comparing the phy_id in the MAC driver this flag
>>> could be
>>> checked:
>>>
>>> if (phydev->drv->flags & PHY_RST_AFTER_CLK_EN) {
>>>    ret = fec_reset_phy(ndev);
>>>    ...
>>> }
>>>
>>> Would checking the flag be OK in fec_main.c?
>> Yes, it is better than previous solution.
>> But add new common API in phy_device.c is much better like:
>> 1. add a flag called "PHY_RST_AFTER_CLK_EN" to the flags variable in struct
>phy_driver,  all phy driver that need reset can set the flag.
>
>OK.
>
>> 2. add new common api interface phy_reset_after_clk_enable() in
>> phy_device.c driver
>
>OK. But see below...
>
>> 3. add reset gpio descriptor for common phy device driver.
>
>... if I understood it correctly the patch called "Teach phylib hard-resetting
>devices" by Geert and Sergei is exactly doing this:
>	https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F
>%2Fpatchwork.ozlabs.org%2Fcover%2F828503%2F&data=02%7C01%7Cfugang
>.duan%40nxp.com%7C087010d8b4784e3c88c608d53015f2ad%7C686ea1d3bc2
>b4c6fa92cd99c5c301635%7C0%7C0%7C636467793180108636&sdata=yY9thX8Q
>CCVteoF5vvUoAYYxGH0gg4wOUq7TQKtkiok%3D&reserved=0
>	https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F
>%2Flkml.org%2Flkml%2F2017%2F10%2F20%2F166&data=02%7C01%7Cfugang.
>duan%40nxp.com%7C087010d8b4784e3c88c608d53015f2ad%7C686ea1d3bc2b
>4c6fa92cd99c5c301635%7C0%7C0%7C636467793180108636&sdata=rxV12dum1
>VmbWLWvSACDuZevFSFbUoWr9AiUtVSsV6w%3D&reserved=0
>
>So I'll implement the phy_reset_after_clk_enable function atop of this patch-
>set and add a note that my patch-series depends on it. Would that be OK?
>
Yes, it is the best solution.

>> 4. then any mac driver can directly call the common
>interface .phy_reset_after_clk_enable().
>
>Sounds reasonable :-)
>
>>
>> That is only my suggestion, maybe there have better idea.
>> Thanks.
>>
>
>Thanks for your quick feedback.
>
>regards
>Richard.L

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2017-11-20 13:44 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-20  8:34 [PATCH v2 0/3] net: ethernet: fec: fix refclk enable for SMSC LAN8710/20 Richard Leitner
2017-11-20  8:34 ` [PATCH v2 1/3] net: ethernet: freescale: simplify fec_reset_phy Richard Leitner
2017-11-20  9:35   ` Andy Duan
2017-11-20  8:34 ` [PATCH v2 2/3] include: linux: phy: harmonize phy_id{,_mask} type Richard Leitner
2017-11-20  8:34 ` [PATCH v2 3/3] net: ethernet: fec: fix refclk enable for SMSC LAN8710/20 Richard Leitner
2017-11-20  9:47   ` Andy Duan
2017-11-20  9:57     ` Richard Leitner
2017-11-20 10:35       ` Andy Duan
2017-11-20 12:55         ` Richard Leitner
2017-11-20 13:13           ` Geert Uytterhoeven
2017-11-20 13:21             ` Richard Leitner
2017-11-20 13:40               ` Geert Uytterhoeven
2017-11-20 13:43           ` Andy Duan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).