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
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.
13 Since ehci-platform is intended to handle any generic enough non pci ehci
14 device, add a "usb-ehci" compatibility string.
16 There already is a usb-ehci device-tree bindings document, update this
17 with clks and phy bindings info.
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.
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.
29 Signed-off-by: Hans de Goede <hdegoede@redhat.com>
30 Acked-by: Alan Stern <stern@rowland.harvard.edu>
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
41 diff --git a/Documentation/devicetree/bindings/usb/usb-ehci.txt b/Documentation/devicetree/bindings/usb/usb-ehci.txt
42 index fa18612..2c1aeeb 100644
43 --- a/Documentation/devicetree/bindings/usb/usb-ehci.txt
44 +++ b/Documentation/devicetree/bindings/usb/usb-ehci.txt
45 @@ -7,13 +7,14 @@ Required properties:
46 (debug-port or other) can be also specified here, but only after
47 definition of standard EHCI registers.
48 - interrupts : one EHCI interrupt should be described here.
49 -If device registers are implemented in big endian mode, the device
50 -node should have "big-endian-regs" property.
51 -If controller implementation operates with big endian descriptors,
52 -"big-endian-desc" property should be specified.
53 -If both big endian registers and descriptors are used by the controller
54 -implementation, "big-endian" property can be specified instead of having
55 -both "big-endian-regs" and "big-endian-desc".
58 + - big-endian-regs : boolean, set this for hcds with big-endian registers
59 + - big-endian-desc : boolean, set this for hcds with big-endian descriptors
60 + - big-endian : boolean, for hcds with big-endian-regs + big-endian-desc
61 + - clocks : a list of phandle + clock specifier pairs
62 + - phys : phandle + phy specifier pair
65 Example (Sequoia 440EPx):
67 @@ -23,3 +24,13 @@ Example (Sequoia 440EPx):
68 reg = <0 e0000300 90 0 e0000390 70>;
72 +Example (Allwinner sun4i A10 SoC):
73 + ehci0: usb@01c14000 {
74 + compatible = "allwinner,sun4i-a10-ehci", "usb-ehci";
75 + reg = <0x01c14000 0x100>;
77 + clocks = <&ahb_gates 1>;
81 diff --git a/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt b/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt
82 deleted file mode 100644
83 index 17b3ad1..0000000
84 --- a/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt
87 -VIA/Wondermedia VT8500 EHCI Controller
88 ------------------------------------------------------
91 -- compatible : "via,vt8500-ehci"
92 -- reg : Should contain 1 register ranges(address and length)
93 -- interrupts : ehci controller interrupt
98 - compatible = "via,vt8500-ehci";
99 - reg = <0xd8007900 0x200>;
102 diff --git a/Documentation/devicetree/bindings/usb/vt8500-ehci.txt b/Documentation/devicetree/bindings/usb/vt8500-ehci.txt
103 deleted file mode 100644
104 index 5fb8fd6..0000000
105 --- a/Documentation/devicetree/bindings/usb/vt8500-ehci.txt
108 -VIA VT8500 and Wondermedia WM8xxx SoC USB controllers.
110 -Required properties:
111 - - compatible: Should be "via,vt8500-ehci" or "wm,prizm-ehci".
112 - - reg: Address range of the ehci registers. size should be 0x200
113 - - interrupts: Should contain the ehci interrupt.
115 -usb: ehci@D8007100 {
116 - compatible = "wm,prizm-ehci", "usb-ehci";
117 - reg = <0xD8007100 0x200>;
120 diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
121 index a9707da..e28cbe0 100644
122 --- a/drivers/usb/host/Kconfig
123 +++ b/drivers/usb/host/Kconfig
124 @@ -255,6 +255,7 @@ config USB_EHCI_ATH79
126 config USB_EHCI_HCD_PLATFORM
127 tristate "Generic EHCI driver for a platform device"
131 Adds an EHCI host driver for a generic platform device, which
132 diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
133 index 01536cf..5ebd0b7 100644
134 --- a/drivers/usb/host/ehci-platform.c
135 +++ b/drivers/usb/host/ehci-platform.c
138 * Copyright 2007 Steven Brown <sbrown@cortland.com>
139 * Copyright 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
140 + * Copyright 2014 Hans de Goede <hdegoede@redhat.com>
142 * Derived from the ohci-ssb driver
143 * Copyright 2007 Michael Buesch <m@bues.ch>
146 * Licensed under the GNU/GPL. See COPYING for details.
148 +#include <linux/clk.h>
149 #include <linux/dma-mapping.h>
150 #include <linux/err.h>
151 #include <linux/kernel.h>
153 #include <linux/io.h>
154 #include <linux/module.h>
155 #include <linux/of.h>
156 +#include <linux/phy/phy.h>
157 #include <linux/platform_device.h>
158 #include <linux/usb.h>
159 #include <linux/usb/hcd.h>
163 #define DRIVER_DESC "EHCI generic platform driver"
164 +#define EHCI_MAX_CLKS 3
165 +#define hcd_to_ehci_priv(h) ((struct ehci_platform_priv *)hcd_to_ehci(h)->priv)
167 +struct ehci_platform_priv {
168 + struct clk *clks[EHCI_MAX_CLKS];
172 static const char hcd_name[] = "ehci-platform";
174 @@ -64,38 +74,90 @@ static int ehci_platform_reset(struct usb_hcd *hcd)
178 +static int ehci_platform_power_on(struct platform_device *dev)
180 + struct usb_hcd *hcd = platform_get_drvdata(dev);
181 + struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
184 + for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++) {
185 + ret = clk_prepare_enable(priv->clks[clk]);
187 + goto err_disable_clks;
191 + ret = phy_init(priv->phy);
193 + goto err_disable_clks;
195 + ret = phy_power_on(priv->phy);
203 + phy_exit(priv->phy);
206 + clk_disable_unprepare(priv->clks[clk]);
211 +static void ehci_platform_power_off(struct platform_device *dev)
213 + struct usb_hcd *hcd = platform_get_drvdata(dev);
214 + struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
218 + phy_power_off(priv->phy);
219 + phy_exit(priv->phy);
222 + for (clk = EHCI_MAX_CLKS - 1; clk >= 0; clk--)
223 + if (priv->clks[clk])
224 + clk_disable_unprepare(priv->clks[clk]);
227 static struct hc_driver __read_mostly ehci_platform_hc_driver;
229 static const struct ehci_driver_overrides platform_overrides __initconst = {
230 - .reset = ehci_platform_reset,
231 + .reset = ehci_platform_reset,
232 + .extra_priv_size = sizeof(struct ehci_platform_priv),
235 -static struct usb_ehci_pdata ehci_platform_defaults;
236 +static struct usb_ehci_pdata ehci_platform_defaults = {
237 + .power_on = ehci_platform_power_on,
238 + .power_suspend = ehci_platform_power_off,
239 + .power_off = ehci_platform_power_off,
242 static int ehci_platform_probe(struct platform_device *dev)
245 struct resource *res_mem;
246 - struct usb_ehci_pdata *pdata;
249 + struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev);
250 + struct ehci_platform_priv *priv;
251 + int err, irq, clk = 0;
257 - * use reasonable defaults so platforms don't have to provide these.
258 - * with DT probing on ARM, none of these are set.
259 + * Use reasonable defaults so platforms don't have to provide these
260 + * with DT probing on ARM.
262 - if (!dev_get_platdata(&dev->dev))
263 - dev->dev.platform_data = &ehci_platform_defaults;
265 + pdata = &ehci_platform_defaults;
267 err = dma_coerce_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
271 - pdata = dev_get_platdata(&dev->dev);
273 irq = platform_get_irq(dev, 0);
275 dev_err(&dev->dev, "no irq provided");
276 @@ -107,17 +169,40 @@ static int ehci_platform_probe(struct platform_device *dev)
280 + hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev,
281 + dev_name(&dev->dev));
285 + platform_set_drvdata(dev, hcd);
286 + dev->dev.platform_data = pdata;
287 + priv = hcd_to_ehci_priv(hcd);
289 + if (pdata == &ehci_platform_defaults && dev->dev.of_node) {
290 + priv->phy = devm_phy_get(&dev->dev, "usb");
291 + if (IS_ERR(priv->phy)) {
292 + err = PTR_ERR(priv->phy);
293 + if (err == -EPROBE_DEFER)
298 + for (clk = 0; clk < EHCI_MAX_CLKS; clk++) {
299 + priv->clks[clk] = of_clk_get(dev->dev.of_node, clk);
300 + if (IS_ERR(priv->clks[clk])) {
301 + err = PTR_ERR(priv->clks[clk]);
302 + if (err == -EPROBE_DEFER)
304 + priv->clks[clk] = NULL;
310 if (pdata->power_on) {
311 err = pdata->power_on(dev);
316 - hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev,
317 - dev_name(&dev->dev));
324 hcd->rsrc_start = res_mem->start;
325 @@ -126,22 +211,28 @@ static int ehci_platform_probe(struct platform_device *dev)
326 hcd->regs = devm_ioremap_resource(&dev->dev, res_mem);
327 if (IS_ERR(hcd->regs)) {
328 err = PTR_ERR(hcd->regs);
332 err = usb_add_hcd(hcd, irq, IRQF_SHARED);
337 device_wakeup_enable(hcd->self.controller);
338 platform_set_drvdata(dev, hcd);
345 if (pdata->power_off)
346 pdata->power_off(dev);
349 + clk_put(priv->clks[clk]);
351 + if (pdata == &ehci_platform_defaults)
352 + dev->dev.platform_data = NULL;
358 @@ -150,13 +241,19 @@ static int ehci_platform_remove(struct platform_device *dev)
360 struct usb_hcd *hcd = platform_get_drvdata(dev);
361 struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev);
362 + struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
368 if (pdata->power_off)
369 pdata->power_off(dev);
371 + for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++)
372 + clk_put(priv->clks[clk]);
376 if (pdata == &ehci_platform_defaults)
377 dev->dev.platform_data = NULL;
379 @@ -207,8 +304,10 @@ static int ehci_platform_resume(struct device *dev)
380 static const struct of_device_id vt8500_ehci_ids[] = {
381 { .compatible = "via,vt8500-ehci", },
382 { .compatible = "wm,prizm-ehci", },
383 + { .compatible = "usb-ehci", },
386 +MODULE_DEVICE_TABLE(of, vt8500_ehci_ids);
388 static const struct platform_device_id ehci_platform_table[] = {
389 { "ehci-platform", 0 },
393 From 91fc5f6e5e90d412a6778efbe05e5306a1df5032 Mon Sep 17 00:00:00 2001
394 From: Hans de Goede <hdegoede@redhat.com>
395 Date: Tue, 21 Jan 2014 16:20:53 +0100
396 Subject: [PATCH] ehci-platform: Add support for controllers with big-endian
399 This uses the already documented devicetree booleans for this, see:
400 Documentation/devicetree/bindings/usb/usb-ehci.txt
402 Signed-off-by: Hans de Goede <hdegoede@redhat.com>
404 drivers/usb/host/ehci-platform.c | 33 +++++++++++++++++++++++++++++++--
405 1 file changed, 31 insertions(+), 2 deletions(-)
407 diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
408 index 5ebd0b7..8fde649 100644
409 --- a/drivers/usb/host/ehci-platform.c
410 +++ b/drivers/usb/host/ehci-platform.c
411 @@ -55,8 +55,10 @@ static int ehci_platform_reset(struct usb_hcd *hcd)
413 hcd->has_tt = pdata->has_tt;
414 ehci->has_synopsys_hc_bug = pdata->has_synopsys_hc_bug;
415 - ehci->big_endian_desc = pdata->big_endian_desc;
416 - ehci->big_endian_mmio = pdata->big_endian_mmio;
417 + if (pdata->big_endian_desc)
418 + ehci->big_endian_desc = 1;
419 + if (pdata->big_endian_mmio)
420 + ehci->big_endian_mmio = 1;
421 ehci->ignore_oc = pdata->ignore_oc;
423 if (pdata->pre_setup) {
424 @@ -142,6 +144,7 @@ static int ehci_platform_probe(struct platform_device *dev)
425 struct resource *res_mem;
426 struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev);
427 struct ehci_platform_priv *priv;
428 + struct ehci_hcd *ehci;
429 int err, irq, clk = 0;
432 @@ -177,8 +180,34 @@ static int ehci_platform_probe(struct platform_device *dev)
433 platform_set_drvdata(dev, hcd);
434 dev->dev.platform_data = pdata;
435 priv = hcd_to_ehci_priv(hcd);
436 + ehci = hcd_to_ehci(hcd);
438 if (pdata == &ehci_platform_defaults && dev->dev.of_node) {
439 + if (of_property_read_bool(dev->dev.of_node, "big-endian-regs"))
440 + ehci->big_endian_mmio = 1;
442 + if (of_property_read_bool(dev->dev.of_node, "big-endian-desc"))
443 + ehci->big_endian_desc = 1;
445 + if (of_property_read_bool(dev->dev.of_node, "big-endian"))
446 + ehci->big_endian_mmio = ehci->big_endian_desc = 1;
448 +#ifndef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
449 + if (ehci->big_endian_mmio) {
451 + "Error big-endian-regs not compiled in\n");
456 +#ifndef CONFIG_USB_EHCI_BIG_ENDIAN_DESC
457 + if (ehci->big_endian_desc) {
459 + "Error big-endian-desc not compiled in\n");
464 priv->phy = devm_phy_get(&dev->dev, "usb");
465 if (IS_ERR(priv->phy)) {
466 err = PTR_ERR(priv->phy);
470 From 4a1ce69fa8c4595483493cd7df21c66dbcca1307 Mon Sep 17 00:00:00 2001
471 From: Hans de Goede <hdegoede@redhat.com>
472 Date: Tue, 11 Feb 2014 11:46:13 +0100
473 Subject: [PATCH] ehci-platform: Change compatible string from usb-ehci to
476 The initial versions of the devicetree enablement patches for ehci-platform
477 used "ehci-platform" as compatible string. However this was disliked by various
478 reviewers because the platform bus is a Linux invention and devicetree is
479 supposed to be OS agnostic. After much discussion I gave up, added a:
480 "depends on !PPC_OF" to Kconfig to avoid a known conflict with PPC-OF platforms
481 and went with the generic usb-ehci as requested.
483 In retro-spect I should have chosen something different, the dts files for many
484 existing boards already claim to be compatible with "usb-ehci", ie they have:
486 compatible = "ti,ehci-omap", "usb-ehci";
488 In theory this should not be a problem since the "ti,ehci-omap" entry takes
489 presedence, but in practice using a conflicting compatible string is an issue,
490 because it makes which driver gets used depend on driver registration order.
492 This patch changes the compatible string claimed by ehci-platform to
493 "generic-ehci", avoiding the driver registration / module loading ordering
494 problems, and removes the "depends on !PPC_OF" workaround.
496 Signed-off-by: Hans de Goede <hdegoede@redhat.com>
498 Documentation/devicetree/bindings/usb/usb-ehci.txt | 4 ++--
499 drivers/usb/host/Kconfig | 1 -
500 drivers/usb/host/ehci-platform.c | 2 +-
501 3 files changed, 3 insertions(+), 4 deletions(-)
503 diff --git a/Documentation/devicetree/bindings/usb/usb-ehci.txt b/Documentation/devicetree/bindings/usb/usb-ehci.txt
504 index 2c1aeeb..ff151ec 100644
505 --- a/Documentation/devicetree/bindings/usb/usb-ehci.txt
506 +++ b/Documentation/devicetree/bindings/usb/usb-ehci.txt
511 - - compatible : should be "usb-ehci".
512 + - compatible : should be "generic-ehci".
513 - reg : should contain at least address and length of the standard EHCI
514 register set for the device. Optional platform-dependent registers
515 (debug-port or other) can be also specified here, but only after
516 @@ -27,7 +27,7 @@ Example (Sequoia 440EPx):
518 Example (Allwinner sun4i A10 SoC):
519 ehci0: usb@01c14000 {
520 - compatible = "allwinner,sun4i-a10-ehci", "usb-ehci";
521 + compatible = "allwinner,sun4i-a10-ehci", "generic-ehci";
522 reg = <0x01c14000 0x100>;
524 clocks = <&ahb_gates 1>;
525 diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
526 index e28cbe0..a9707da 100644
527 --- a/drivers/usb/host/Kconfig
528 +++ b/drivers/usb/host/Kconfig
529 @@ -255,7 +255,6 @@ config USB_EHCI_ATH79
531 config USB_EHCI_HCD_PLATFORM
532 tristate "Generic EHCI driver for a platform device"
536 Adds an EHCI host driver for a generic platform device, which
537 diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
538 index 8fde649..1178730 100644
539 --- a/drivers/usb/host/ehci-platform.c
540 +++ b/drivers/usb/host/ehci-platform.c
541 @@ -333,7 +333,7 @@ static int ehci_platform_resume(struct device *dev)
542 static const struct of_device_id vt8500_ehci_ids[] = {
543 { .compatible = "via,vt8500-ehci", },
544 { .compatible = "wm,prizm-ehci", },
545 - { .compatible = "usb-ehci", },
546 + { .compatible = "generic-ehci", },
549 MODULE_DEVICE_TABLE(of, vt8500_ehci_ids);