]> git.kernelconcepts.de Git - meta-kc-bsp.git/blob - recipes-kernel/linux/linux-karo-4.9.11/reset_ethernet_phy_whenever_the_enet_out_clock_is_being_enabled.patch
fix machine definition substitution
[meta-kc-bsp.git] / recipes-kernel / linux / linux-karo-4.9.11 / reset_ethernet_phy_whenever_the_enet_out_clock_is_being_enabled.patch
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
5  re-enabled
6
7 ---
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(-)
11
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 {
17  
18         int     dev_id;
19  
20 +       int     reset_gpio;
21 +       int     phy_reset_duration;
22 +       int     phy_post_delay;
23 +       int     reset_active_high;
24 +
25         /* Phylib and MDIO interface */
26         struct  mii_bus *mii_bus;
27         int     mii_timeout;
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,
33         return ret;
34  }
35  
36 +static void fec_reset_phy(struct fec_enet_private *fep);
37 +
38  static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
39  {
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)
42                 if (ret)
43                         return ret;
44  
45 -               ret = clk_prepare_enable(fep->clk_enet_out);
46 -               if (ret)
47 -                       goto failed_clk_enet_out;
48 +               if (fep->clk_enet_out) {
49 +                       ret = clk_prepare_enable(fep->clk_enet_out);
50 +                       if (ret)
51 +                               goto failed_clk_enet_out;
52 +
53 +                       fec_reset_phy(fep);
54 +               }
55  
56                 if (fep->clk_ptp) {
57                         mutex_lock(&fep->ptp_clk_mutex);
58 @@ -3213,67 +3219,90 @@ static int fec_enet_init(struct net_device *ndev)
59  }
60  
61  #ifdef CONFIG_OF
62 -static int fec_reset_phy(struct platform_device *pdev)
63 +static void fec_reset_phy(struct fec_enet_private *fep)
64  {
65 -       int err, phy_reset;
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))
70 +               return;
71  
72 -       if (!np)
73 -               return 0;
74 +       gpio_set_value_cansleep(fep->reset_gpio, fep->reset_active_high);
75  
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)
79 -               msec = 1;
80 +       if (fep->phy_reset_duration > 20)
81 +               msleep(fep->phy_reset_duration);
82 +       else
83 +               usleep_range(fep->phy_reset_duration * 1000,
84 +                            fep->phy_reset_duration * 1000 + 1000);
85  
86 -       phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0);
87 -       if (phy_reset == -EPROBE_DEFER)
88 -               return phy_reset;
89 -       else if (!gpio_is_valid(phy_reset))
90 -               return 0;
91 +       gpio_set_value_cansleep(fep->reset_gpio, !fep->reset_active_high);
92  
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)
96 -               return -EINVAL;
97 +       if (!fep->phy_post_delay)
98 +               return;
99 +       if (fep->phy_post_delay > 20)
100 +               msleep(fep->phy_post_delay);
101 +       else
102 +               usleep_range(fep->phy_post_delay * 1000,
103 +                            fep->phy_post_delay * 1000 + 1000);
104 +}
105 +
106 +static int fec_get_reset_gpio(struct platform_device *pdev)
107 +{
108 +       int err;
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);
112  
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
117 +        * signal polarity.
118 +        */
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))
123 +               return 0;
124 +
125 +       fep->reset_active_high = of_property_read_bool(np,
126 +                                                      "phy-reset-active-high");
127  
128 -       err = devm_gpio_request_one(&pdev->dev, phy_reset,
129 -                       active_high ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
130 -                       "phy-reset");
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,
134 +                                   "phy-reset");
135         if (err) {
136                 dev_err(&pdev->dev, "failed to get phy-reset-gpios: %d\n", err);
137                 return err;
138         }
139  
140 -       if (msec > 20)
141 -               msleep(msec);
142 -       else
143 -               usleep_range(msec * 1000, msec * 1000 + 1000);
144 -
145 -       gpio_set_value_cansleep(phy_reset, !active_high);
146 -
147 -       if (!phy_post_delay)
148 -               return 0;
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;
154  
155 -       if (phy_post_delay > 20)
156 -               msleep(phy_post_delay);
157 -       else
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 */
163 +       if (err)
164 +               fep->phy_post_delay = 0;
165 +       else if (fep->phy_post_delay > 1000)
166 +               return -EINVAL;
167  
168         return 0;
169  }
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
173 + * by machine code.
174 + */
175 +static inline void fec_reset_phy(struct fec_enet_private *fep)
176  {
177 -       /*
178 -        * In case of platform probe, the reset has been done
179 -        * by machine code.
180 -        */
181 +}
182 +
183 +static int fec_get_reset_gpio(struct platform_device *pdev)
184 +{
185 +       struct net_device *ndev = platform_get_drvdata(pdev);
186 +       struct fec_enet_private *fep = netdev_priv(ndev);
187 +
188 +       fep->reset_gpio = -EINVAL;
189         return 0;
190  }
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);
195  
196 -       ret = fec_reset_phy(pdev);
197 +       ret = fec_get_reset_gpio(pdev);
198         if (ret)
199                 goto failed_reset;
200 +       fec_reset_phy(fep);
201  
202         if (fep->bufdesc_ex)
203                 fec_ptp_init(pdev);