kernel: refresh patches
[openwrt.git] / target / linux / sunxi / patches-3.14 / 195-2-ehci-plat-changes.patch
1 From 738b350437abfca820dae226549ecf4fb100fa30 Mon Sep 17 00:00:00 2001
2 From: Hans de Goede <hdegoede@redhat.com>
3 Date: Sun, 5 Jan 2014 00:04:02 +0100
4 Subject: [PATCH] ehci-platform: Add support for clks and phy passed through
5  devicetree
6
7 Currently ehci-platform is only used in combination with devicetree when used
8 with some Via socs. By extending it to (optionally) get clks and a phy from
9 devicetree, and enabling / disabling those on power_on / off, it can be used
10 more generically. Specifically after this commit it can be used for the
11 ehci controller on Allwinner sunxi SoCs.
12
13 Since ehci-platform is intended to handle any generic enough non pci ehci
14 device, add a "usb-ehci" compatibility string.
15
16 There already is a usb-ehci device-tree bindings document, update this
17 with clks and phy bindings info.
18
19 Although actually quite generic so far the via,vt8500 compatibilty string
20 had its own bindings document. Somehow we even ended up with 2 of them. Since
21 these provide no extra information over the generic usb-ehci documentation,
22 this patch removes them.
23
24 The ehci-ppc-of.c driver also claims the usb-ehci compatibility string,
25 even though it mostly is ibm,usb-ehci-440epx specific. ehci-platform.c is
26 not needed on ppc platforms, so add a !PPC_OF dependency to it to avoid
27 2 drivers claiming the same compatibility string getting build on ppc.
28
29 Signed-off-by: Hans de Goede <hdegoede@redhat.com>
30 Acked-by: Alan Stern <stern@rowland.harvard.edu>
31 ---
32  Documentation/devicetree/bindings/usb/usb-ehci.txt |  25 +++-
33  .../devicetree/bindings/usb/via,vt8500-ehci.txt    |  15 ---
34  .../devicetree/bindings/usb/vt8500-ehci.txt        |  12 --
35  drivers/usb/host/Kconfig                           |   1 +
36  drivers/usb/host/ehci-platform.c                   | 147 +++++++++++++++++----
37  5 files changed, 142 insertions(+), 58 deletions(-)
38  delete mode 100644 Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt
39  delete mode 100644 Documentation/devicetree/bindings/usb/vt8500-ehci.txt
40
41 --- a/Documentation/devicetree/bindings/usb/usb-ehci.txt
42 +++ b/Documentation/devicetree/bindings/usb/usb-ehci.txt
43 @@ -1,19 +1,20 @@
44  USB EHCI controllers
45  
46  Required properties:
47 -  - compatible : should be "usb-ehci".
48 +  - compatible : should be "generic-ehci".
49    - reg : should contain at least address and length of the standard EHCI
50      register set for the device. Optional platform-dependent registers
51      (debug-port or other) can be also specified here, but only after
52      definition of standard EHCI registers.
53    - interrupts : one EHCI interrupt should be described here.
54 -If device registers are implemented in big endian mode, the device
55 -node should have "big-endian-regs" property.
56 -If controller implementation operates with big endian descriptors,
57 -"big-endian-desc" property should be specified.
58 -If both big endian registers and descriptors are used by the controller
59 -implementation, "big-endian" property can be specified instead of having
60 -both "big-endian-regs" and "big-endian-desc".
61 +
62 +Optional properties:
63 + - big-endian-regs : boolean, set this for hcds with big-endian registers
64 + - big-endian-desc : boolean, set this for hcds with big-endian descriptors
65 + - big-endian : boolean, for hcds with big-endian-regs + big-endian-desc
66 + - clocks : a list of phandle + clock specifier pairs
67 + - phys : phandle + phy specifier pair
68 + - phy-names : "usb"
69  
70  Example (Sequoia 440EPx):
71      ehci@e0000300 {
72 @@ -23,3 +24,13 @@ Example (Sequoia 440EPx):
73            reg = <0 e0000300 90 0 e0000390 70>;
74            big-endian;
75     };
76 +
77 +Example (Allwinner sun4i A10 SoC):
78 +   ehci0: usb@01c14000 {
79 +          compatible = "allwinner,sun4i-a10-ehci", "generic-ehci";
80 +          reg = <0x01c14000 0x100>;
81 +          interrupts = <39>;
82 +          clocks = <&ahb_gates 1>;
83 +          phys = <&usbphy 1>;
84 +          phy-names = "usb";
85 +   };
86 --- a/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt
87 +++ /dev/null
88 @@ -1,15 +0,0 @@
89 -VIA/Wondermedia VT8500 EHCI Controller
90 ------------------------------------------------------
91 -
92 -Required properties:
93 -- compatible : "via,vt8500-ehci"
94 -- reg : Should contain 1 register ranges(address and length)
95 -- interrupts : ehci controller interrupt
96 -
97 -Example:
98 -
99 -       ehci@d8007900 {
100 -               compatible = "via,vt8500-ehci";
101 -               reg = <0xd8007900 0x200>;
102 -               interrupts = <43>;
103 -       };
104 --- a/Documentation/devicetree/bindings/usb/vt8500-ehci.txt
105 +++ /dev/null
106 @@ -1,12 +0,0 @@
107 -VIA VT8500 and Wondermedia WM8xxx SoC USB controllers.
108 -
109 -Required properties:
110 - - compatible: Should be "via,vt8500-ehci" or "wm,prizm-ehci".
111 - - reg: Address range of the ehci registers. size should be 0x200
112 - - interrupts: Should contain the ehci interrupt.
113 -
114 -usb: ehci@D8007100 {
115 -       compatible = "wm,prizm-ehci", "usb-ehci";
116 -       reg = <0xD8007100 0x200>;
117 -       interrupts = <1>;
118 -};
119 --- a/drivers/usb/host/ehci-platform.c
120 +++ b/drivers/usb/host/ehci-platform.c
121 @@ -3,6 +3,7 @@
122   *
123   * Copyright 2007 Steven Brown <sbrown@cortland.com>
124   * Copyright 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
125 + * Copyright 2014 Hans de Goede <hdegoede@redhat.com>
126   *
127   * Derived from the ohci-ssb driver
128   * Copyright 2007 Michael Buesch <m@bues.ch>
129 @@ -18,6 +19,7 @@
130   *
131   * Licensed under the GNU/GPL. See COPYING for details.
132   */
133 +#include <linux/clk.h>
134  #include <linux/dma-mapping.h>
135  #include <linux/err.h>
136  #include <linux/kernel.h>
137 @@ -25,6 +27,7 @@
138  #include <linux/io.h>
139  #include <linux/module.h>
140  #include <linux/of.h>
141 +#include <linux/phy/phy.h>
142  #include <linux/platform_device.h>
143  #include <linux/usb.h>
144  #include <linux/usb/hcd.h>
145 @@ -33,6 +36,13 @@
146  #include "ehci.h"
147  
148  #define DRIVER_DESC "EHCI generic platform driver"
149 +#define EHCI_MAX_CLKS 3
150 +#define hcd_to_ehci_priv(h) ((struct ehci_platform_priv *)hcd_to_ehci(h)->priv)
151 +
152 +struct ehci_platform_priv {
153 +       struct clk *clks[EHCI_MAX_CLKS];
154 +       struct phy *phy;
155 +};
156  
157  static const char hcd_name[] = "ehci-platform";
158  
159 @@ -45,8 +55,10 @@ static int ehci_platform_reset(struct us
160  
161         hcd->has_tt = pdata->has_tt;
162         ehci->has_synopsys_hc_bug = pdata->has_synopsys_hc_bug;
163 -       ehci->big_endian_desc = pdata->big_endian_desc;
164 -       ehci->big_endian_mmio = pdata->big_endian_mmio;
165 +       if (pdata->big_endian_desc)
166 +               ehci->big_endian_desc = 1;
167 +       if (pdata->big_endian_mmio)
168 +               ehci->big_endian_mmio = 1;
169         ehci->ignore_oc = pdata->ignore_oc;
170  
171         if (pdata->pre_setup) {
172 @@ -65,38 +77,91 @@ static int ehci_platform_reset(struct us
173         return 0;
174  }
175  
176 +static int ehci_platform_power_on(struct platform_device *dev)
177 +{
178 +       struct usb_hcd *hcd = platform_get_drvdata(dev);
179 +       struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
180 +       int clk, ret;
181 +
182 +       for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++) {
183 +               ret = clk_prepare_enable(priv->clks[clk]);
184 +               if (ret)
185 +                       goto err_disable_clks;
186 +       }
187 +
188 +       if (priv->phy) {
189 +               ret = phy_init(priv->phy);
190 +               if (ret)
191 +                       goto err_disable_clks;
192 +
193 +               ret = phy_power_on(priv->phy);
194 +               if (ret)
195 +                       goto err_exit_phy;
196 +       }
197 +
198 +       return 0;
199 +
200 +err_exit_phy:
201 +       phy_exit(priv->phy);
202 +err_disable_clks:
203 +       while (--clk >= 0)
204 +               clk_disable_unprepare(priv->clks[clk]);
205 +
206 +       return ret;
207 +}
208 +
209 +static void ehci_platform_power_off(struct platform_device *dev)
210 +{
211 +       struct usb_hcd *hcd = platform_get_drvdata(dev);
212 +       struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
213 +       int clk;
214 +
215 +       if (priv->phy) {
216 +               phy_power_off(priv->phy);
217 +               phy_exit(priv->phy);
218 +       }
219 +
220 +       for (clk = EHCI_MAX_CLKS - 1; clk >= 0; clk--)
221 +               if (priv->clks[clk])
222 +                       clk_disable_unprepare(priv->clks[clk]);
223 +}
224 +
225  static struct hc_driver __read_mostly ehci_platform_hc_driver;
226  
227  static const struct ehci_driver_overrides platform_overrides __initconst = {
228 -       .reset =        ehci_platform_reset,
229 +       .reset =                ehci_platform_reset,
230 +       .extra_priv_size =      sizeof(struct ehci_platform_priv),
231  };
232  
233 -static struct usb_ehci_pdata ehci_platform_defaults;
234 +static struct usb_ehci_pdata ehci_platform_defaults = {
235 +       .power_on =             ehci_platform_power_on,
236 +       .power_suspend =        ehci_platform_power_off,
237 +       .power_off =            ehci_platform_power_off,
238 +};
239  
240  static int ehci_platform_probe(struct platform_device *dev)
241  {
242         struct usb_hcd *hcd;
243         struct resource *res_mem;
244 -       struct usb_ehci_pdata *pdata;
245 -       int irq;
246 -       int err;
247 +       struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev);
248 +       struct ehci_platform_priv *priv;
249 +       struct ehci_hcd *ehci;
250 +       int err, irq, clk = 0;
251  
252         if (usb_disabled())
253                 return -ENODEV;
254  
255         /*
256 -        * use reasonable defaults so platforms don't have to provide these.
257 -        * with DT probing on ARM, none of these are set.
258 +        * Use reasonable defaults so platforms don't have to provide these
259 +        * with DT probing on ARM.
260          */
261 -       if (!dev_get_platdata(&dev->dev))
262 -               dev->dev.platform_data = &ehci_platform_defaults;
263 +       if (!pdata)
264 +               pdata = &ehci_platform_defaults;
265  
266         err = dma_coerce_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
267         if (err)
268                 return err;
269  
270 -       pdata = dev_get_platdata(&dev->dev);
271 -
272         irq = platform_get_irq(dev, 0);
273         if (irq < 0) {
274                 dev_err(&dev->dev, "no irq provided");
275 @@ -108,17 +173,66 @@ static int ehci_platform_probe(struct pl
276                 return -ENXIO;
277         }
278  
279 +       hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev,
280 +                            dev_name(&dev->dev));
281 +       if (!hcd)
282 +               return -ENOMEM;
283 +
284 +       platform_set_drvdata(dev, hcd);
285 +       dev->dev.platform_data = pdata;
286 +       priv = hcd_to_ehci_priv(hcd);
287 +       ehci = hcd_to_ehci(hcd);
288 +
289 +       if (pdata == &ehci_platform_defaults && dev->dev.of_node) {
290 +               if (of_property_read_bool(dev->dev.of_node, "big-endian-regs"))
291 +                       ehci->big_endian_mmio = 1;
292 +
293 +               if (of_property_read_bool(dev->dev.of_node, "big-endian-desc"))
294 +                       ehci->big_endian_desc = 1;
295 +
296 +               if (of_property_read_bool(dev->dev.of_node, "big-endian"))
297 +                       ehci->big_endian_mmio = ehci->big_endian_desc = 1;
298 +
299 +#ifndef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
300 +               if (ehci->big_endian_mmio) {
301 +                       dev_err(&dev->dev,
302 +                               "Error big-endian-regs not compiled in\n");
303 +                       err = -EINVAL;
304 +                       goto err_put_hcd;
305 +               }
306 +#endif
307 +#ifndef CONFIG_USB_EHCI_BIG_ENDIAN_DESC
308 +               if (ehci->big_endian_desc) {
309 +                       dev_err(&dev->dev,
310 +                               "Error big-endian-desc not compiled in\n");
311 +                       err = -EINVAL;
312 +                       goto err_put_hcd;
313 +               }
314 +#endif
315 +               priv->phy = devm_phy_get(&dev->dev, "usb");
316 +               if (IS_ERR(priv->phy)) {
317 +                       err = PTR_ERR(priv->phy);
318 +                       if (err == -EPROBE_DEFER)
319 +                               goto err_put_hcd;
320 +                       priv->phy = NULL;
321 +               }
322 +
323 +               for (clk = 0; clk < EHCI_MAX_CLKS; clk++) {
324 +                       priv->clks[clk] = of_clk_get(dev->dev.of_node, clk);
325 +                       if (IS_ERR(priv->clks[clk])) {
326 +                               err = PTR_ERR(priv->clks[clk]);
327 +                               if (err == -EPROBE_DEFER)
328 +                                       goto err_put_clks;
329 +                               priv->clks[clk] = NULL;
330 +                               break;
331 +                       }
332 +               }
333 +       }
334 +
335         if (pdata->power_on) {
336                 err = pdata->power_on(dev);
337                 if (err < 0)
338 -                       return err;
339 -       }
340 -
341 -       hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev,
342 -                            dev_name(&dev->dev));
343 -       if (!hcd) {
344 -               err = -ENOMEM;
345 -               goto err_power;
346 +                       goto err_put_clks;
347         }
348  
349         hcd->rsrc_start = res_mem->start;
350 @@ -127,22 +241,28 @@ static int ehci_platform_probe(struct pl
351         hcd->regs = devm_ioremap_resource(&dev->dev, res_mem);
352         if (IS_ERR(hcd->regs)) {
353                 err = PTR_ERR(hcd->regs);
354 -               goto err_put_hcd;
355 +               goto err_power;
356         }
357         err = usb_add_hcd(hcd, irq, IRQF_SHARED);
358         if (err)
359 -               goto err_put_hcd;
360 +               goto err_power;
361  
362         device_wakeup_enable(hcd->self.controller);
363         platform_set_drvdata(dev, hcd);
364  
365         return err;
366  
367 -err_put_hcd:
368 -       usb_put_hcd(hcd);
369  err_power:
370         if (pdata->power_off)
371                 pdata->power_off(dev);
372 +err_put_clks:
373 +       while (--clk >= 0)
374 +               clk_put(priv->clks[clk]);
375 +err_put_hcd:
376 +       if (pdata == &ehci_platform_defaults)
377 +               dev->dev.platform_data = NULL;
378 +
379 +       usb_put_hcd(hcd);
380  
381         return err;
382  }
383 @@ -151,13 +271,19 @@ static int ehci_platform_remove(struct p
384  {
385         struct usb_hcd *hcd = platform_get_drvdata(dev);
386         struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev);
387 +       struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
388 +       int clk;
389  
390         usb_remove_hcd(hcd);
391 -       usb_put_hcd(hcd);
392  
393         if (pdata->power_off)
394                 pdata->power_off(dev);
395  
396 +       for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++)
397 +               clk_put(priv->clks[clk]);
398 +
399 +       usb_put_hcd(hcd);
400 +
401         if (pdata == &ehci_platform_defaults)
402                 dev->dev.platform_data = NULL;
403  
404 @@ -208,8 +334,10 @@ static int ehci_platform_resume(struct d
405  static const struct of_device_id vt8500_ehci_ids[] = {
406         { .compatible = "via,vt8500-ehci", },
407         { .compatible = "wm,prizm-ehci", },
408 +       { .compatible = "generic-ehci", },
409         {}
410  };
411 +MODULE_DEVICE_TABLE(of, vt8500_ehci_ids);
412  
413  static const struct platform_device_id ehci_platform_table[] = {
414         { "ehci-platform", 0 },