1 From fac8dc6a300ced21494cba76af18cb4197c699c6 Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Lothar=20Wa=C3=9Fmann?= <LW@KARO-electronics.de>
3 Date: Tue, 10 Oct 2017 14:05:36 +0200
4 Subject: [PATCH] net: fec: reset PHY whenever enet out clock has been
8 drivers/net/ethernet/freescale/fec.h | 5 ++
9 drivers/net/ethernet/freescale/fec_main.c | 124 +++++++++++++++++++-----------
10 2 files changed, 82 insertions(+), 47 deletions(-)
12 diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
13 index 38c7b21e5d63..4c2de04fe0aa 100644
14 --- a/drivers/net/ethernet/freescale/fec.h
15 +++ b/drivers/net/ethernet/freescale/fec.h
16 @@ -523,6 +523,11 @@ struct fec_enet_private {
21 + int phy_reset_duration;
23 + int reset_active_high;
25 /* Phylib and MDIO interface */
26 struct mii_bus *mii_bus;
28 diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
29 index c1160ae22f94..3c2cff867704 100644
30 --- a/drivers/net/ethernet/freescale/fec_main.c
31 +++ b/drivers/net/ethernet/freescale/fec_main.c
32 @@ -1836,6 +1836,8 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
36 +static void fec_reset_phy(struct fec_enet_private *fep);
38 static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
40 struct fec_enet_private *fep = netdev_priv(ndev);
41 @@ -1846,9 +1848,13 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
45 - ret = clk_prepare_enable(fep->clk_enet_out);
47 - goto failed_clk_enet_out;
48 + if (fep->clk_enet_out) {
49 + ret = clk_prepare_enable(fep->clk_enet_out);
51 + goto failed_clk_enet_out;
57 mutex_lock(&fep->ptp_clk_mutex);
58 @@ -3213,67 +3219,90 @@ static int fec_enet_init(struct net_device *ndev)
62 -static int fec_reset_phy(struct platform_device *pdev)
63 +static void fec_reset_phy(struct fec_enet_private *fep)
66 - bool active_high = false;
67 - int msec = 1, phy_post_delay = 0;
68 - struct device_node *np = pdev->dev.of_node;
69 + if (!gpio_is_valid(fep->reset_gpio))
74 + gpio_set_value_cansleep(fep->reset_gpio, fep->reset_active_high);
76 - err = of_property_read_u32(np, "phy-reset-duration", &msec);
77 - /* A sane reset duration should not be longer than 1s */
78 - if (!err && msec > 1000)
80 + if (fep->phy_reset_duration > 20)
81 + msleep(fep->phy_reset_duration);
83 + usleep_range(fep->phy_reset_duration * 1000,
84 + fep->phy_reset_duration * 1000 + 1000);
86 - phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0);
87 - if (phy_reset == -EPROBE_DEFER)
89 - else if (!gpio_is_valid(phy_reset))
91 + gpio_set_value_cansleep(fep->reset_gpio, !fep->reset_active_high);
93 - err = of_property_read_u32(np, "phy-reset-post-delay", &phy_post_delay);
94 - /* valid reset duration should be less than 1s */
95 - if (!err && phy_post_delay > 1000)
97 + if (!fep->phy_post_delay)
99 + if (fep->phy_post_delay > 20)
100 + msleep(fep->phy_post_delay);
102 + usleep_range(fep->phy_post_delay * 1000,
103 + fep->phy_post_delay * 1000 + 1000);
106 +static int fec_get_reset_gpio(struct platform_device *pdev)
109 + struct device_node *np = pdev->dev.of_node;
110 + struct net_device *ndev = platform_get_drvdata(pdev);
111 + struct fec_enet_private *fep = netdev_priv(ndev);
113 - active_high = of_property_read_bool(np, "phy-reset-active-high");
114 + /* Most DT files do not specify the correct polarity
115 + * of the phy-reset GPIO.
116 + * So use this special property to signal the actual
119 + fep->reset_gpio = of_get_named_gpio(np, "phy-reset-gpios", 0);
120 + if (fep->reset_gpio == -EPROBE_DEFER)
121 + return -EPROBE_DEFER;
122 + if (!gpio_is_valid(fep->reset_gpio))
125 + fep->reset_active_high = of_property_read_bool(np,
126 + "phy-reset-active-high");
128 - err = devm_gpio_request_one(&pdev->dev, phy_reset,
129 - active_high ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
131 + err = devm_gpio_request_one(&pdev->dev, fep->reset_gpio,
132 + fep->reset_active_high ?
133 + GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH,
136 dev_err(&pdev->dev, "failed to get phy-reset-gpios: %d\n", err);
143 - usleep_range(msec * 1000, msec * 1000 + 1000);
145 - gpio_set_value_cansleep(phy_reset, !active_high);
147 - if (!phy_post_delay)
149 + err = of_property_read_u32(np, "phy-reset-duration",
150 + &fep->phy_reset_duration);
151 + /* A sane reset duration should not be longer than 1s */
152 + if (err || fep->phy_reset_duration > 1000)
153 + fep->phy_reset_duration = 1;
155 - if (phy_post_delay > 20)
156 - msleep(phy_post_delay);
158 - usleep_range(phy_post_delay * 1000,
159 - phy_post_delay * 1000 + 1000);
160 + err = of_property_read_u32(np, "phy-reset-post-delay",
161 + &fep->phy_post_delay);
162 + /* valid post reset delay should be less than 1s */
164 + fep->phy_post_delay = 0;
165 + else if (fep->phy_post_delay > 1000)
170 #else /* CONFIG_OF */
171 -static int fec_reset_phy(struct platform_device *pdev)
172 +/* In case of platform probe, the reset has been done
175 +static inline void fec_reset_phy(struct fec_enet_private *fep)
178 - * In case of platform probe, the reset has been done
183 +static int fec_get_reset_gpio(struct platform_device *pdev)
185 + struct net_device *ndev = platform_get_drvdata(pdev);
186 + struct fec_enet_private *fep = netdev_priv(ndev);
188 + fep->reset_gpio = -EINVAL;
191 #endif /* CONFIG_OF */
192 @@ -3455,9 +3484,10 @@ fec_probe(struct platform_device *pdev)
193 pm_runtime_set_active(&pdev->dev);
194 pm_runtime_enable(&pdev->dev);
196 - ret = fec_reset_phy(pdev);
197 + ret = fec_get_reset_gpio(pdev);
200 + fec_reset_phy(fep);