* [PATCH v9 0/4] ohci-platform and ehci-plaform patches rebased on 3.14-rc1
@ 2014-02-07 15:36 Hans de Goede
[not found] ` <1391787403-20961-1-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
0 siblings, 1 reply; 12+ messages in thread
From: Hans de Goede @ 2014-02-07 15:36 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Alan Stern, Tony Prisk, linux-usb, Maxime Ripard,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree
Hi Greg,
Here is v9 of my ohci-platform and ehci-platform patchset, It is just a
rebase (with some manual conflict resolution), to make it easier for you
to throw this into usb-next, there are no other changes.
Thanks & Regards,
Hans
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v9 1/4] ohci-platform: Add support for devicetree instantiation
[not found] ` <1391787403-20961-1-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2014-02-07 15:36 ` Hans de Goede
2014-02-07 15:36 ` [PATCH v9 2/4] ehci-platform: Add support for clks and phy passed through devicetree Hans de Goede
` (3 subsequent siblings)
4 siblings, 0 replies; 12+ messages in thread
From: Hans de Goede @ 2014-02-07 15:36 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Alan Stern, Tony Prisk, linux-usb, Maxime Ripard,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree,
Hans de Goede
Add support for ohci-platform instantiation from devicetree, including
optionally getting clks and a phy from devicetree, and enabling / disabling
those on power_on / off.
This should allow using ohci-platform from devicetree in various cases.
Specifically after this commit it can be used for the ohci controller found
on Allwinner sunxi SoCs.
Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Acked-by: Alan Stern <stern-nwvwT67g6+6dFdvTe/nMLpVzexx5G7lz@public.gmane.org>
---
Documentation/devicetree/bindings/usb/usb-ohci.txt | 22 +++
drivers/usb/host/ohci-platform.c | 162 ++++++++++++++++++---
2 files changed, 162 insertions(+), 22 deletions(-)
create mode 100644 Documentation/devicetree/bindings/usb/usb-ohci.txt
diff --git a/Documentation/devicetree/bindings/usb/usb-ohci.txt b/Documentation/devicetree/bindings/usb/usb-ohci.txt
new file mode 100644
index 0000000..6ba38d9
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/usb-ohci.txt
@@ -0,0 +1,22 @@
+USB OHCI controllers
+
+Required properties:
+- compatible : "usb-ohci"
+- reg : ohci controller register range (address and length)
+- interrupts : ohci controller interrupt
+
+Optional properties:
+- clocks : a list of phandle + clock specifier pairs
+- phys : phandle + phy specifier pair
+- phy-names : "usb"
+
+Example:
+
+ ohci0: usb@01c14400 {
+ compatible = "allwinner,sun4i-a10-ohci", "usb-ohci";
+ reg = <0x01c14400 0x100>;
+ interrupts = <64>;
+ clocks = <&usb_clk 6>, <&ahb_gates 2>;
+ phys = <&usbphy 1>;
+ phy-names = "usb";
+ };
diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
index 68f674c..49304dd 100644
--- a/drivers/usb/host/ohci-platform.c
+++ b/drivers/usb/host/ohci-platform.c
@@ -3,6 +3,7 @@
*
* Copyright 2007 Michael Buesch <m@bues.ch>
* Copyright 2011-2012 Hauke Mehrtens <hauke-5/S+JYg5SzeELgA04lAiVw@public.gmane.org>
+ * Copyright 2014 Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
*
* Derived from the OCHI-SSB driver
* Derived from the OHCI-PCI driver
@@ -14,11 +15,14 @@
* Licensed under the GNU/GPL. See COPYING for details.
*/
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
#include <linux/hrtimer.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/err.h>
+#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/usb/ohci_pdriver.h>
#include <linux/usb.h>
@@ -27,6 +31,13 @@
#include "ohci.h"
#define DRIVER_DESC "OHCI generic platform driver"
+#define OHCI_MAX_CLKS 3
+#define hcd_to_ohci_priv(h) ((struct ohci_platform_priv *)hcd_to_ohci(h)->priv)
+
+struct ohci_platform_priv {
+ struct clk *clks[OHCI_MAX_CLKS];
+ struct phy *phy;
+};
static const char hcd_name[] = "ohci-platform";
@@ -48,11 +59,67 @@ static int ohci_platform_reset(struct usb_hcd *hcd)
return ohci_setup(hcd);
}
+static int ohci_platform_power_on(struct platform_device *dev)
+{
+ struct usb_hcd *hcd = platform_get_drvdata(dev);
+ struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd);
+ int clk, ret;
+
+ for (clk = 0; clk < OHCI_MAX_CLKS && priv->clks[clk]; clk++) {
+ ret = clk_prepare_enable(priv->clks[clk]);
+ if (ret)
+ goto err_disable_clks;
+ }
+
+ if (priv->phy) {
+ ret = phy_init(priv->phy);
+ if (ret)
+ goto err_disable_clks;
+
+ ret = phy_power_on(priv->phy);
+ if (ret)
+ goto err_exit_phy;
+ }
+
+ return 0;
+
+err_exit_phy:
+ phy_exit(priv->phy);
+err_disable_clks:
+ while (--clk >= 0)
+ clk_disable_unprepare(priv->clks[clk]);
+
+ return ret;
+}
+
+static void ohci_platform_power_off(struct platform_device *dev)
+{
+ struct usb_hcd *hcd = platform_get_drvdata(dev);
+ struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd);
+ int clk;
+
+ if (priv->phy) {
+ phy_power_off(priv->phy);
+ phy_exit(priv->phy);
+ }
+
+ for (clk = OHCI_MAX_CLKS - 1; clk >= 0; clk--)
+ if (priv->clks[clk])
+ clk_disable_unprepare(priv->clks[clk]);
+}
+
static struct hc_driver __read_mostly ohci_platform_hc_driver;
static const struct ohci_driver_overrides platform_overrides __initconst = {
- .product_desc = "Generic Platform OHCI controller",
- .reset = ohci_platform_reset,
+ .product_desc = "Generic Platform OHCI controller",
+ .reset = ohci_platform_reset,
+ .extra_priv_size = sizeof(struct ohci_platform_priv),
+};
+
+static struct usb_ohci_pdata ohci_platform_defaults = {
+ .power_on = ohci_platform_power_on,
+ .power_suspend = ohci_platform_power_off,
+ .power_off = ohci_platform_power_off,
};
static int ohci_platform_probe(struct platform_device *dev)
@@ -60,17 +127,23 @@ static int ohci_platform_probe(struct platform_device *dev)
struct usb_hcd *hcd;
struct resource *res_mem;
struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev);
- int irq;
- int err = -ENOMEM;
-
- if (!pdata) {
- WARN_ON(1);
- return -ENODEV;
- }
+ struct ohci_platform_priv *priv;
+ int err, irq, clk = 0;
if (usb_disabled())
return -ENODEV;
+ /*
+ * Use reasonable defaults so platforms don't have to provide these
+ * with DT probing on ARM.
+ */
+ if (!pdata)
+ pdata = &ohci_platform_defaults;
+
+ err = dma_coerce_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
+ if (err)
+ return err;
+
irq = platform_get_irq(dev, 0);
if (irq < 0) {
dev_err(&dev->dev, "no irq provided");
@@ -83,17 +156,40 @@ static int ohci_platform_probe(struct platform_device *dev)
return -ENXIO;
}
+ hcd = usb_create_hcd(&ohci_platform_hc_driver, &dev->dev,
+ dev_name(&dev->dev));
+ if (!hcd)
+ return -ENOMEM;
+
+ platform_set_drvdata(dev, hcd);
+ dev->dev.platform_data = pdata;
+ priv = hcd_to_ohci_priv(hcd);
+
+ if (pdata == &ohci_platform_defaults && dev->dev.of_node) {
+ priv->phy = devm_phy_get(&dev->dev, "usb");
+ if (IS_ERR(priv->phy)) {
+ err = PTR_ERR(priv->phy);
+ if (err == -EPROBE_DEFER)
+ goto err_put_hcd;
+ priv->phy = NULL;
+ }
+
+ for (clk = 0; clk < OHCI_MAX_CLKS; clk++) {
+ priv->clks[clk] = of_clk_get(dev->dev.of_node, clk);
+ if (IS_ERR(priv->clks[clk])) {
+ err = PTR_ERR(priv->clks[clk]);
+ if (err == -EPROBE_DEFER)
+ goto err_put_clks;
+ priv->clks[clk] = NULL;
+ break;
+ }
+ }
+ }
+
if (pdata->power_on) {
err = pdata->power_on(dev);
if (err < 0)
- return err;
- }
-
- hcd = usb_create_hcd(&ohci_platform_hc_driver, &dev->dev,
- dev_name(&dev->dev));
- if (!hcd) {
- err = -ENOMEM;
- goto err_power;
+ goto err_put_clks;
}
hcd->rsrc_start = res_mem->start;
@@ -102,11 +198,11 @@ static int ohci_platform_probe(struct platform_device *dev)
hcd->regs = devm_ioremap_resource(&dev->dev, res_mem);
if (IS_ERR(hcd->regs)) {
err = PTR_ERR(hcd->regs);
- goto err_put_hcd;
+ goto err_power;
}
err = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (err)
- goto err_put_hcd;
+ goto err_power;
device_wakeup_enable(hcd->self.controller);
@@ -114,11 +210,17 @@ static int ohci_platform_probe(struct platform_device *dev)
return err;
-err_put_hcd:
- usb_put_hcd(hcd);
err_power:
if (pdata->power_off)
pdata->power_off(dev);
+err_put_clks:
+ while (--clk >= 0)
+ clk_put(priv->clks[clk]);
+err_put_hcd:
+ if (pdata == &ohci_platform_defaults)
+ dev->dev.platform_data = NULL;
+
+ usb_put_hcd(hcd);
return err;
}
@@ -127,13 +229,22 @@ static int ohci_platform_remove(struct platform_device *dev)
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev);
+ struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd);
+ int clk;
usb_remove_hcd(hcd);
- usb_put_hcd(hcd);
if (pdata->power_off)
pdata->power_off(dev);
+ for (clk = 0; clk < OHCI_MAX_CLKS && priv->clks[clk]; clk++)
+ clk_put(priv->clks[clk]);
+
+ usb_put_hcd(hcd);
+
+ if (pdata == &ohci_platform_defaults)
+ dev->dev.platform_data = NULL;
+
return 0;
}
@@ -180,6 +291,12 @@ static int ohci_platform_resume(struct device *dev)
#define ohci_platform_resume NULL
#endif /* CONFIG_PM */
+static const struct of_device_id ohci_platform_ids[] = {
+ { .compatible = "usb-ohci", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ohci_platform_ids);
+
static const struct platform_device_id ohci_platform_table[] = {
{ "ohci-platform", 0 },
{ }
@@ -200,6 +317,7 @@ static struct platform_driver ohci_platform_driver = {
.owner = THIS_MODULE,
.name = "ohci-platform",
.pm = &ohci_platform_pm_ops,
+ .of_match_table = ohci_platform_ids,
}
};
--
1.8.4.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v9 2/4] ehci-platform: Add support for clks and phy passed through devicetree
[not found] ` <1391787403-20961-1-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2014-02-07 15:36 ` [PATCH v9 1/4] ohci-platform: Add support for devicetree instantiation Hans de Goede
@ 2014-02-07 15:36 ` Hans de Goede
[not found] ` <1391787403-20961-3-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2014-02-07 15:36 ` [PATCH v9 3/4] ohci-platform: Add support for controllers with big-endian regs / descriptors Hans de Goede
` (2 subsequent siblings)
4 siblings, 1 reply; 12+ messages in thread
From: Hans de Goede @ 2014-02-07 15:36 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Alan Stern, Tony Prisk, linux-usb, Maxime Ripard,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree,
Hans de Goede
Currently ehci-platform is only used in combination with devicetree when used
with some Via socs. By extending it to (optionally) get clks and a phy from
devicetree, and enabling / disabling those on power_on / off, it can be used
more generically. Specifically after this commit it can be used for the
ehci controller on Allwinner sunxi SoCs.
Since ehci-platform is intended to handle any generic enough non pci ehci
device, add a "usb-ehci" compatibility string.
There already is a usb-ehci device-tree bindings document, update this
with clks and phy bindings info.
Although actually quite generic so far the via,vt8500 compatibilty string
had its own bindings document. Somehow we even ended up with 2 of them. Since
these provide no extra information over the generic usb-ehci documentation,
this patch removes them.
The ehci-ppc-of.c driver also claims the usb-ehci compatibility string,
even though it mostly is ibm,usb-ehci-440epx specific. ehci-platform.c is
not needed on ppc platforms, so add a !PPC_OF dependency to it to avoid
2 drivers claiming the same compatibility string getting build on ppc.
Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Acked-by: Alan Stern <stern-nwvwT67g6+6dFdvTe/nMLpVzexx5G7lz@public.gmane.org>
---
Documentation/devicetree/bindings/usb/usb-ehci.txt | 25 +++-
.../devicetree/bindings/usb/via,vt8500-ehci.txt | 15 ---
.../devicetree/bindings/usb/vt8500-ehci.txt | 12 --
drivers/usb/host/Kconfig | 1 +
drivers/usb/host/ehci-platform.c | 147 +++++++++++++++++----
5 files changed, 142 insertions(+), 58 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt
delete mode 100644 Documentation/devicetree/bindings/usb/vt8500-ehci.txt
diff --git a/Documentation/devicetree/bindings/usb/usb-ehci.txt b/Documentation/devicetree/bindings/usb/usb-ehci.txt
index fa18612..2c1aeeb 100644
--- a/Documentation/devicetree/bindings/usb/usb-ehci.txt
+++ b/Documentation/devicetree/bindings/usb/usb-ehci.txt
@@ -7,13 +7,14 @@ Required properties:
(debug-port or other) can be also specified here, but only after
definition of standard EHCI registers.
- interrupts : one EHCI interrupt should be described here.
-If device registers are implemented in big endian mode, the device
-node should have "big-endian-regs" property.
-If controller implementation operates with big endian descriptors,
-"big-endian-desc" property should be specified.
-If both big endian registers and descriptors are used by the controller
-implementation, "big-endian" property can be specified instead of having
-both "big-endian-regs" and "big-endian-desc".
+
+Optional properties:
+ - big-endian-regs : boolean, set this for hcds with big-endian registers
+ - big-endian-desc : boolean, set this for hcds with big-endian descriptors
+ - big-endian : boolean, for hcds with big-endian-regs + big-endian-desc
+ - clocks : a list of phandle + clock specifier pairs
+ - phys : phandle + phy specifier pair
+ - phy-names : "usb"
Example (Sequoia 440EPx):
ehci@e0000300 {
@@ -23,3 +24,13 @@ Example (Sequoia 440EPx):
reg = <0 e0000300 90 0 e0000390 70>;
big-endian;
};
+
+Example (Allwinner sun4i A10 SoC):
+ ehci0: usb@01c14000 {
+ compatible = "allwinner,sun4i-a10-ehci", "usb-ehci";
+ reg = <0x01c14000 0x100>;
+ interrupts = <39>;
+ clocks = <&ahb_gates 1>;
+ phys = <&usbphy 1>;
+ phy-names = "usb";
+ };
diff --git a/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt b/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt
deleted file mode 100644
index 17b3ad1..0000000
--- a/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-VIA/Wondermedia VT8500 EHCI Controller
------------------------------------------------------
-
-Required properties:
-- compatible : "via,vt8500-ehci"
-- reg : Should contain 1 register ranges(address and length)
-- interrupts : ehci controller interrupt
-
-Example:
-
- ehci@d8007900 {
- compatible = "via,vt8500-ehci";
- reg = <0xd8007900 0x200>;
- interrupts = <43>;
- };
diff --git a/Documentation/devicetree/bindings/usb/vt8500-ehci.txt b/Documentation/devicetree/bindings/usb/vt8500-ehci.txt
deleted file mode 100644
index 5fb8fd6..0000000
--- a/Documentation/devicetree/bindings/usb/vt8500-ehci.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-VIA VT8500 and Wondermedia WM8xxx SoC USB controllers.
-
-Required properties:
- - compatible: Should be "via,vt8500-ehci" or "wm,prizm-ehci".
- - reg: Address range of the ehci registers. size should be 0x200
- - interrupts: Should contain the ehci interrupt.
-
-usb: ehci@D8007100 {
- compatible = "wm,prizm-ehci", "usb-ehci";
- reg = <0xD8007100 0x200>;
- interrupts = <1>;
-};
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index a9707da..e28cbe0 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -255,6 +255,7 @@ config USB_EHCI_ATH79
config USB_EHCI_HCD_PLATFORM
tristate "Generic EHCI driver for a platform device"
+ depends on !PPC_OF
default n
---help---
Adds an EHCI host driver for a generic platform device, which
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index 01536cf..5ebd0b7 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -3,6 +3,7 @@
*
* Copyright 2007 Steven Brown <sbrown-aLUkz7fEuXBWk0Htik3J/w@public.gmane.org>
* Copyright 2010-2012 Hauke Mehrtens <hauke-5/S+JYg5SzeELgA04lAiVw@public.gmane.org>
+ * Copyright 2014 Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
*
* Derived from the ohci-ssb driver
* Copyright 2007 Michael Buesch <m@bues.ch>
@@ -18,6 +19,7 @@
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
+#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/kernel.h>
@@ -25,6 +27,7 @@
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
@@ -33,6 +36,13 @@
#include "ehci.h"
#define DRIVER_DESC "EHCI generic platform driver"
+#define EHCI_MAX_CLKS 3
+#define hcd_to_ehci_priv(h) ((struct ehci_platform_priv *)hcd_to_ehci(h)->priv)
+
+struct ehci_platform_priv {
+ struct clk *clks[EHCI_MAX_CLKS];
+ struct phy *phy;
+};
static const char hcd_name[] = "ehci-platform";
@@ -64,38 +74,90 @@ static int ehci_platform_reset(struct usb_hcd *hcd)
return 0;
}
+static int ehci_platform_power_on(struct platform_device *dev)
+{
+ struct usb_hcd *hcd = platform_get_drvdata(dev);
+ struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
+ int clk, ret;
+
+ for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++) {
+ ret = clk_prepare_enable(priv->clks[clk]);
+ if (ret)
+ goto err_disable_clks;
+ }
+
+ if (priv->phy) {
+ ret = phy_init(priv->phy);
+ if (ret)
+ goto err_disable_clks;
+
+ ret = phy_power_on(priv->phy);
+ if (ret)
+ goto err_exit_phy;
+ }
+
+ return 0;
+
+err_exit_phy:
+ phy_exit(priv->phy);
+err_disable_clks:
+ while (--clk >= 0)
+ clk_disable_unprepare(priv->clks[clk]);
+
+ return ret;
+}
+
+static void ehci_platform_power_off(struct platform_device *dev)
+{
+ struct usb_hcd *hcd = platform_get_drvdata(dev);
+ struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
+ int clk;
+
+ if (priv->phy) {
+ phy_power_off(priv->phy);
+ phy_exit(priv->phy);
+ }
+
+ for (clk = EHCI_MAX_CLKS - 1; clk >= 0; clk--)
+ if (priv->clks[clk])
+ clk_disable_unprepare(priv->clks[clk]);
+}
+
static struct hc_driver __read_mostly ehci_platform_hc_driver;
static const struct ehci_driver_overrides platform_overrides __initconst = {
- .reset = ehci_platform_reset,
+ .reset = ehci_platform_reset,
+ .extra_priv_size = sizeof(struct ehci_platform_priv),
};
-static struct usb_ehci_pdata ehci_platform_defaults;
+static struct usb_ehci_pdata ehci_platform_defaults = {
+ .power_on = ehci_platform_power_on,
+ .power_suspend = ehci_platform_power_off,
+ .power_off = ehci_platform_power_off,
+};
static int ehci_platform_probe(struct platform_device *dev)
{
struct usb_hcd *hcd;
struct resource *res_mem;
- struct usb_ehci_pdata *pdata;
- int irq;
- int err;
+ struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev);
+ struct ehci_platform_priv *priv;
+ int err, irq, clk = 0;
if (usb_disabled())
return -ENODEV;
/*
- * use reasonable defaults so platforms don't have to provide these.
- * with DT probing on ARM, none of these are set.
+ * Use reasonable defaults so platforms don't have to provide these
+ * with DT probing on ARM.
*/
- if (!dev_get_platdata(&dev->dev))
- dev->dev.platform_data = &ehci_platform_defaults;
+ if (!pdata)
+ pdata = &ehci_platform_defaults;
err = dma_coerce_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
if (err)
return err;
- pdata = dev_get_platdata(&dev->dev);
-
irq = platform_get_irq(dev, 0);
if (irq < 0) {
dev_err(&dev->dev, "no irq provided");
@@ -107,17 +169,40 @@ static int ehci_platform_probe(struct platform_device *dev)
return -ENXIO;
}
+ hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev,
+ dev_name(&dev->dev));
+ if (!hcd)
+ return -ENOMEM;
+
+ platform_set_drvdata(dev, hcd);
+ dev->dev.platform_data = pdata;
+ priv = hcd_to_ehci_priv(hcd);
+
+ if (pdata == &ehci_platform_defaults && dev->dev.of_node) {
+ priv->phy = devm_phy_get(&dev->dev, "usb");
+ if (IS_ERR(priv->phy)) {
+ err = PTR_ERR(priv->phy);
+ if (err == -EPROBE_DEFER)
+ goto err_put_hcd;
+ priv->phy = NULL;
+ }
+
+ for (clk = 0; clk < EHCI_MAX_CLKS; clk++) {
+ priv->clks[clk] = of_clk_get(dev->dev.of_node, clk);
+ if (IS_ERR(priv->clks[clk])) {
+ err = PTR_ERR(priv->clks[clk]);
+ if (err == -EPROBE_DEFER)
+ goto err_put_clks;
+ priv->clks[clk] = NULL;
+ break;
+ }
+ }
+ }
+
if (pdata->power_on) {
err = pdata->power_on(dev);
if (err < 0)
- return err;
- }
-
- hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev,
- dev_name(&dev->dev));
- if (!hcd) {
- err = -ENOMEM;
- goto err_power;
+ goto err_put_clks;
}
hcd->rsrc_start = res_mem->start;
@@ -126,22 +211,28 @@ static int ehci_platform_probe(struct platform_device *dev)
hcd->regs = devm_ioremap_resource(&dev->dev, res_mem);
if (IS_ERR(hcd->regs)) {
err = PTR_ERR(hcd->regs);
- goto err_put_hcd;
+ goto err_power;
}
err = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (err)
- goto err_put_hcd;
+ goto err_power;
device_wakeup_enable(hcd->self.controller);
platform_set_drvdata(dev, hcd);
return err;
-err_put_hcd:
- usb_put_hcd(hcd);
err_power:
if (pdata->power_off)
pdata->power_off(dev);
+err_put_clks:
+ while (--clk >= 0)
+ clk_put(priv->clks[clk]);
+err_put_hcd:
+ if (pdata == &ehci_platform_defaults)
+ dev->dev.platform_data = NULL;
+
+ usb_put_hcd(hcd);
return err;
}
@@ -150,13 +241,19 @@ static int ehci_platform_remove(struct platform_device *dev)
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev);
+ struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
+ int clk;
usb_remove_hcd(hcd);
- usb_put_hcd(hcd);
if (pdata->power_off)
pdata->power_off(dev);
+ for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++)
+ clk_put(priv->clks[clk]);
+
+ usb_put_hcd(hcd);
+
if (pdata == &ehci_platform_defaults)
dev->dev.platform_data = NULL;
@@ -207,8 +304,10 @@ static int ehci_platform_resume(struct device *dev)
static const struct of_device_id vt8500_ehci_ids[] = {
{ .compatible = "via,vt8500-ehci", },
{ .compatible = "wm,prizm-ehci", },
+ { .compatible = "usb-ehci", },
{}
};
+MODULE_DEVICE_TABLE(of, vt8500_ehci_ids);
static const struct platform_device_id ehci_platform_table[] = {
{ "ehci-platform", 0 },
--
1.8.4.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v9 3/4] ohci-platform: Add support for controllers with big-endian regs / descriptors
[not found] ` <1391787403-20961-1-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2014-02-07 15:36 ` [PATCH v9 1/4] ohci-platform: Add support for devicetree instantiation Hans de Goede
2014-02-07 15:36 ` [PATCH v9 2/4] ehci-platform: Add support for clks and phy passed through devicetree Hans de Goede
@ 2014-02-07 15:36 ` Hans de Goede
2014-02-07 15:36 ` [PATCH v9 4/4] ehci-platform: " Hans de Goede
2014-02-07 22:31 ` [PATCH v9 0/4] ohci-platform and ehci-plaform patches rebased on 3.14-rc1 Greg Kroah-Hartman
4 siblings, 0 replies; 12+ messages in thread
From: Hans de Goede @ 2014-02-07 15:36 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Alan Stern, Tony Prisk, linux-usb, Maxime Ripard,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree,
Hans de Goede
Note this commit uses the same devicetree booleans for this as the ones
already existing in the usb-ehci bindings, see:
Documentation/devicetree/bindings/usb/usb-ehci.txt
Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
Documentation/devicetree/bindings/usb/usb-ohci.txt | 3 +++
drivers/usb/host/ohci-platform.c | 27 ++++++++++++++++++++++
2 files changed, 30 insertions(+)
diff --git a/Documentation/devicetree/bindings/usb/usb-ohci.txt b/Documentation/devicetree/bindings/usb/usb-ohci.txt
index 6ba38d9..6933b0c 100644
--- a/Documentation/devicetree/bindings/usb/usb-ohci.txt
+++ b/Documentation/devicetree/bindings/usb/usb-ohci.txt
@@ -6,6 +6,9 @@ Required properties:
- interrupts : ohci controller interrupt
Optional properties:
+- big-endian-regs : boolean, set this for hcds with big-endian registers
+- big-endian-desc : boolean, set this for hcds with big-endian descriptors
+- big-endian : boolean, for hcds with big-endian-regs + big-endian-desc
- clocks : a list of phandle + clock specifier pairs
- phys : phandle + phy specifier pair
- phy-names : "usb"
diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
index 49304dd..e2c28fd 100644
--- a/drivers/usb/host/ohci-platform.c
+++ b/drivers/usb/host/ohci-platform.c
@@ -128,6 +128,7 @@ static int ohci_platform_probe(struct platform_device *dev)
struct resource *res_mem;
struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev);
struct ohci_platform_priv *priv;
+ struct ohci_hcd *ohci;
int err, irq, clk = 0;
if (usb_disabled())
@@ -164,8 +165,34 @@ static int ohci_platform_probe(struct platform_device *dev)
platform_set_drvdata(dev, hcd);
dev->dev.platform_data = pdata;
priv = hcd_to_ohci_priv(hcd);
+ ohci = hcd_to_ohci(hcd);
if (pdata == &ohci_platform_defaults && dev->dev.of_node) {
+ if (of_property_read_bool(dev->dev.of_node, "big-endian-regs"))
+ ohci->flags |= OHCI_QUIRK_BE_MMIO;
+
+ if (of_property_read_bool(dev->dev.of_node, "big-endian-desc"))
+ ohci->flags |= OHCI_QUIRK_BE_DESC;
+
+ if (of_property_read_bool(dev->dev.of_node, "big-endian"))
+ ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC;
+
+#ifndef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO
+ if (ohci->flags & OHCI_QUIRK_BE_MMIO) {
+ dev_err(&dev->dev,
+ "Error big-endian-regs not compiled in\n");
+ err = -EINVAL;
+ goto err_put_hcd;
+ }
+#endif
+#ifndef CONFIG_USB_OHCI_BIG_ENDIAN_DESC
+ if (ohci->flags & OHCI_QUIRK_BE_DESC) {
+ dev_err(&dev->dev,
+ "Error big-endian-desc not compiled in\n");
+ err = -EINVAL;
+ goto err_put_hcd;
+ }
+#endif
priv->phy = devm_phy_get(&dev->dev, "usb");
if (IS_ERR(priv->phy)) {
err = PTR_ERR(priv->phy);
--
1.8.4.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v9 4/4] ehci-platform: Add support for controllers with big-endian regs / descriptors
[not found] ` <1391787403-20961-1-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
` (2 preceding siblings ...)
2014-02-07 15:36 ` [PATCH v9 3/4] ohci-platform: Add support for controllers with big-endian regs / descriptors Hans de Goede
@ 2014-02-07 15:36 ` Hans de Goede
2014-02-07 22:31 ` [PATCH v9 0/4] ohci-platform and ehci-plaform patches rebased on 3.14-rc1 Greg Kroah-Hartman
4 siblings, 0 replies; 12+ messages in thread
From: Hans de Goede @ 2014-02-07 15:36 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Alan Stern, Tony Prisk, linux-usb, Maxime Ripard,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree,
Hans de Goede
This uses the already documented devicetree booleans for this, see:
Documentation/devicetree/bindings/usb/usb-ehci.txt
Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
drivers/usb/host/ehci-platform.c | 33 +++++++++++++++++++++++++++++++--
1 file changed, 31 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index 5ebd0b7..8fde649 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -55,8 +55,10 @@ static int ehci_platform_reset(struct usb_hcd *hcd)
hcd->has_tt = pdata->has_tt;
ehci->has_synopsys_hc_bug = pdata->has_synopsys_hc_bug;
- ehci->big_endian_desc = pdata->big_endian_desc;
- ehci->big_endian_mmio = pdata->big_endian_mmio;
+ if (pdata->big_endian_desc)
+ ehci->big_endian_desc = 1;
+ if (pdata->big_endian_mmio)
+ ehci->big_endian_mmio = 1;
if (pdata->pre_setup) {
retval = pdata->pre_setup(hcd);
@@ -142,6 +144,7 @@ static int ehci_platform_probe(struct platform_device *dev)
struct resource *res_mem;
struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev);
struct ehci_platform_priv *priv;
+ struct ehci_hcd *ehci;
int err, irq, clk = 0;
if (usb_disabled())
@@ -177,8 +180,34 @@ static int ehci_platform_probe(struct platform_device *dev)
platform_set_drvdata(dev, hcd);
dev->dev.platform_data = pdata;
priv = hcd_to_ehci_priv(hcd);
+ ehci = hcd_to_ehci(hcd);
if (pdata == &ehci_platform_defaults && dev->dev.of_node) {
+ if (of_property_read_bool(dev->dev.of_node, "big-endian-regs"))
+ ehci->big_endian_mmio = 1;
+
+ if (of_property_read_bool(dev->dev.of_node, "big-endian-desc"))
+ ehci->big_endian_desc = 1;
+
+ if (of_property_read_bool(dev->dev.of_node, "big-endian"))
+ ehci->big_endian_mmio = ehci->big_endian_desc = 1;
+
+#ifndef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
+ if (ehci->big_endian_mmio) {
+ dev_err(&dev->dev,
+ "Error big-endian-regs not compiled in\n");
+ err = -EINVAL;
+ goto err_put_hcd;
+ }
+#endif
+#ifndef CONFIG_USB_EHCI_BIG_ENDIAN_DESC
+ if (ehci->big_endian_desc) {
+ dev_err(&dev->dev,
+ "Error big-endian-desc not compiled in\n");
+ err = -EINVAL;
+ goto err_put_hcd;
+ }
+#endif
priv->phy = devm_phy_get(&dev->dev, "usb");
if (IS_ERR(priv->phy)) {
err = PTR_ERR(priv->phy);
--
1.8.4.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v9 0/4] ohci-platform and ehci-plaform patches rebased on 3.14-rc1
[not found] ` <1391787403-20961-1-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
` (3 preceding siblings ...)
2014-02-07 15:36 ` [PATCH v9 4/4] ehci-platform: " Hans de Goede
@ 2014-02-07 22:31 ` Greg Kroah-Hartman
[not found] ` <20140207223101.GA21062-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org>
4 siblings, 1 reply; 12+ messages in thread
From: Greg Kroah-Hartman @ 2014-02-07 22:31 UTC (permalink / raw)
To: Hans de Goede
Cc: Alan Stern, Tony Prisk, linux-usb, Maxime Ripard,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree
On Fri, Feb 07, 2014 at 04:36:39PM +0100, Hans de Goede wrote:
> Hi Greg,
>
> Here is v9 of my ohci-platform and ehci-platform patchset, It is just a
> rebase (with some manual conflict resolution), to make it easier for you
> to throw this into usb-next, there are no other changes.
I've applied these, thanks. I saw a number of older series and
revisions, and I assumed this was the latest, right? If not, can you
resend anything that I might have missed?
thanks,
greg k-h
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v9 0/4] ohci-platform and ehci-plaform patches rebased on 3.14-rc1
[not found] ` <20140207223101.GA21062-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org>
@ 2014-02-07 23:05 ` Hans de Goede
0 siblings, 0 replies; 12+ messages in thread
From: Hans de Goede @ 2014-02-07 23:05 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Alan Stern, Tony Prisk, linux-usb, Maxime Ripard,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree
Hi,
On 02/07/2014 11:31 PM, Greg Kroah-Hartman wrote:
> On Fri, Feb 07, 2014 at 04:36:39PM +0100, Hans de Goede wrote:
>> Hi Greg,
>>
>> Here is v9 of my ohci-platform and ehci-platform patchset, It is just a
>> rebase (with some manual conflict resolution), to make it easier for you
>> to throw this into usb-next, there are no other changes.
>
> I've applied these, thanks. I saw a number of older series and
> revisions, and I assumed this was the latest, right?
Yes this was the latest.
Regards,
Hans
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v9 2/4] ehci-platform: Add support for clks and phy passed through devicetree
[not found] ` <1391787403-20961-3-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2014-02-11 9:12 ` Roger Quadros
[not found] ` <52F9E98B.90407-l0cyMroinI0@public.gmane.org>
0 siblings, 1 reply; 12+ messages in thread
From: Roger Quadros @ 2014-02-11 9:12 UTC (permalink / raw)
To: Hans de Goede, Greg Kroah-Hartman
Cc: Alan Stern, Tony Prisk, linux-usb, Maxime Ripard,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree,
Menon, Nishanth, Kevin Hilman
Hi Hans,
On 02/07/2014 05:36 PM, Hans de Goede wrote:
> Currently ehci-platform is only used in combination with devicetree when used
> with some Via socs. By extending it to (optionally) get clks and a phy from
> devicetree, and enabling / disabling those on power_on / off, it can be used
> more generically. Specifically after this commit it can be used for the
> ehci controller on Allwinner sunxi SoCs.
>
> Since ehci-platform is intended to handle any generic enough non pci ehci
> device, add a "usb-ehci" compatibility string.
>
> There already is a usb-ehci device-tree bindings document, update this
> with clks and phy bindings info.
>
> Although actually quite generic so far the via,vt8500 compatibilty string
> had its own bindings document. Somehow we even ended up with 2 of them. Since
> these provide no extra information over the generic usb-ehci documentation,
> this patch removes them.
>
> The ehci-ppc-of.c driver also claims the usb-ehci compatibility string,
> even though it mostly is ibm,usb-ehci-440epx specific. ehci-platform.c is
> not needed on ppc platforms, so add a !PPC_OF dependency to it to avoid
> 2 drivers claiming the same compatibility string getting build on ppc.
>
This breaks all OMAP platforms on linux-next for the exact same reason. see [1].
./arch/arm/boot/dts/omap4.dtsi: compatible = "ti,ehci-omap", "usb-ehci";
./arch/arm/boot/dts/omap3.dtsi: compatible = "ti,ehci-omap", "usb-ehci";
./arch/arm/boot/dts/omap5.dtsi: compatible = "ti,ehci-omap", "usb-ehci";
The other platforms that claim compatibility with "usb-ehci" are
ARM
./arch/arm/boot/dts/tegra30.dtsi: compatible = "nvidia,tegra30-ehci", "usb-ehci";
./arch/arm/boot/dts/tegra20.dtsi: compatible = "nvidia,tegra20-ehci", "usb-ehci";
./arch/arm/boot/dts/spear600.dtsi: compatible = "st,spear600-ehci", "usb-ehci";
./arch/arm/boot/dts/spear3xx.dtsi: compatible = "st,spear600-ehci", "usb-ehci";
./arch/arm/boot/dts/sama5d3.dtsi: compatible = "atmel,at91sam9g45-ehci", "usb-ehci";
./arch/arm/boot/dts/at91sam9g45.dtsi: compatible = "atmel,at91sam9g45-ehci", "usb-ehci";
./arch/arm/boot/dts/spear13xx.dtsi: compatible = "st,spear600-ehci", "usb-ehci";
./arch/arm/boot/dts/at91sam9x5.dtsi: compatible = "atmel,at91sam9g45-ehci", "usb-ehci";
./arch/arm/boot/dts/tegra114.dtsi: compatible = "nvidia,tegra30-ehci", "usb-ehci";
MIPS
./arch/mips/cavium-octeon/octeon_68xx.dts: compatible = "cavium,octeon-6335-ehci","usb-ehci";
./arch/mips/cavium-octeon/octeon_3xxx.dts: compatible = "cavium,octeon-6335-ehci","usb-ehci";
Do we know that we don't break these platforms as well?
cheers,
-roger
[1] - http://marc.info/?l=linux-usb&m=139204800102167&w=2
> Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> Acked-by: Alan Stern <stern-nwvwT67g6+6dFdvTe/nMLpVzexx5G7lz@public.gmane.org>
> ---
> Documentation/devicetree/bindings/usb/usb-ehci.txt | 25 +++-
> .../devicetree/bindings/usb/via,vt8500-ehci.txt | 15 ---
> .../devicetree/bindings/usb/vt8500-ehci.txt | 12 --
> drivers/usb/host/Kconfig | 1 +
> drivers/usb/host/ehci-platform.c | 147 +++++++++++++++++----
> 5 files changed, 142 insertions(+), 58 deletions(-)
> delete mode 100644 Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt
> delete mode 100644 Documentation/devicetree/bindings/usb/vt8500-ehci.txt
>
> diff --git a/Documentation/devicetree/bindings/usb/usb-ehci.txt b/Documentation/devicetree/bindings/usb/usb-ehci.txt
> index fa18612..2c1aeeb 100644
> --- a/Documentation/devicetree/bindings/usb/usb-ehci.txt
> +++ b/Documentation/devicetree/bindings/usb/usb-ehci.txt
> @@ -7,13 +7,14 @@ Required properties:
> (debug-port or other) can be also specified here, but only after
> definition of standard EHCI registers.
> - interrupts : one EHCI interrupt should be described here.
> -If device registers are implemented in big endian mode, the device
> -node should have "big-endian-regs" property.
> -If controller implementation operates with big endian descriptors,
> -"big-endian-desc" property should be specified.
> -If both big endian registers and descriptors are used by the controller
> -implementation, "big-endian" property can be specified instead of having
> -both "big-endian-regs" and "big-endian-desc".
> +
> +Optional properties:
> + - big-endian-regs : boolean, set this for hcds with big-endian registers
> + - big-endian-desc : boolean, set this for hcds with big-endian descriptors
> + - big-endian : boolean, for hcds with big-endian-regs + big-endian-desc
> + - clocks : a list of phandle + clock specifier pairs
> + - phys : phandle + phy specifier pair
> + - phy-names : "usb"
>
> Example (Sequoia 440EPx):
> ehci@e0000300 {
> @@ -23,3 +24,13 @@ Example (Sequoia 440EPx):
> reg = <0 e0000300 90 0 e0000390 70>;
> big-endian;
> };
> +
> +Example (Allwinner sun4i A10 SoC):
> + ehci0: usb@01c14000 {
> + compatible = "allwinner,sun4i-a10-ehci", "usb-ehci";
> + reg = <0x01c14000 0x100>;
> + interrupts = <39>;
> + clocks = <&ahb_gates 1>;
> + phys = <&usbphy 1>;
> + phy-names = "usb";
> + };
> diff --git a/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt b/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt
> deleted file mode 100644
> index 17b3ad1..0000000
> --- a/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt
> +++ /dev/null
> @@ -1,15 +0,0 @@
> -VIA/Wondermedia VT8500 EHCI Controller
> ------------------------------------------------------
> -
> -Required properties:
> -- compatible : "via,vt8500-ehci"
> -- reg : Should contain 1 register ranges(address and length)
> -- interrupts : ehci controller interrupt
> -
> -Example:
> -
> - ehci@d8007900 {
> - compatible = "via,vt8500-ehci";
> - reg = <0xd8007900 0x200>;
> - interrupts = <43>;
> - };
> diff --git a/Documentation/devicetree/bindings/usb/vt8500-ehci.txt b/Documentation/devicetree/bindings/usb/vt8500-ehci.txt
> deleted file mode 100644
> index 5fb8fd6..0000000
> --- a/Documentation/devicetree/bindings/usb/vt8500-ehci.txt
> +++ /dev/null
> @@ -1,12 +0,0 @@
> -VIA VT8500 and Wondermedia WM8xxx SoC USB controllers.
> -
> -Required properties:
> - - compatible: Should be "via,vt8500-ehci" or "wm,prizm-ehci".
> - - reg: Address range of the ehci registers. size should be 0x200
> - - interrupts: Should contain the ehci interrupt.
> -
> -usb: ehci@D8007100 {
> - compatible = "wm,prizm-ehci", "usb-ehci";
> - reg = <0xD8007100 0x200>;
> - interrupts = <1>;
> -};
> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
> index a9707da..e28cbe0 100644
> --- a/drivers/usb/host/Kconfig
> +++ b/drivers/usb/host/Kconfig
> @@ -255,6 +255,7 @@ config USB_EHCI_ATH79
>
> config USB_EHCI_HCD_PLATFORM
> tristate "Generic EHCI driver for a platform device"
> + depends on !PPC_OF
> default n
> ---help---
> Adds an EHCI host driver for a generic platform device, which
> diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
> index 01536cf..5ebd0b7 100644
> --- a/drivers/usb/host/ehci-platform.c
> +++ b/drivers/usb/host/ehci-platform.c
> @@ -3,6 +3,7 @@
> *
> * Copyright 2007 Steven Brown <sbrown-aLUkz7fEuXBWk0Htik3J/w@public.gmane.org>
> * Copyright 2010-2012 Hauke Mehrtens <hauke-5/S+JYg5SzeELgA04lAiVw@public.gmane.org>
> + * Copyright 2014 Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> *
> * Derived from the ohci-ssb driver
> * Copyright 2007 Michael Buesch <m@bues.ch>
> @@ -18,6 +19,7 @@
> *
> * Licensed under the GNU/GPL. See COPYING for details.
> */
> +#include <linux/clk.h>
> #include <linux/dma-mapping.h>
> #include <linux/err.h>
> #include <linux/kernel.h>
> @@ -25,6 +27,7 @@
> #include <linux/io.h>
> #include <linux/module.h>
> #include <linux/of.h>
> +#include <linux/phy/phy.h>
> #include <linux/platform_device.h>
> #include <linux/usb.h>
> #include <linux/usb/hcd.h>
> @@ -33,6 +36,13 @@
> #include "ehci.h"
>
> #define DRIVER_DESC "EHCI generic platform driver"
> +#define EHCI_MAX_CLKS 3
> +#define hcd_to_ehci_priv(h) ((struct ehci_platform_priv *)hcd_to_ehci(h)->priv)
> +
> +struct ehci_platform_priv {
> + struct clk *clks[EHCI_MAX_CLKS];
> + struct phy *phy;
> +};
>
> static const char hcd_name[] = "ehci-platform";
>
> @@ -64,38 +74,90 @@ static int ehci_platform_reset(struct usb_hcd *hcd)
> return 0;
> }
>
> +static int ehci_platform_power_on(struct platform_device *dev)
> +{
> + struct usb_hcd *hcd = platform_get_drvdata(dev);
> + struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
> + int clk, ret;
> +
> + for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++) {
> + ret = clk_prepare_enable(priv->clks[clk]);
> + if (ret)
> + goto err_disable_clks;
> + }
> +
> + if (priv->phy) {
> + ret = phy_init(priv->phy);
> + if (ret)
> + goto err_disable_clks;
> +
> + ret = phy_power_on(priv->phy);
> + if (ret)
> + goto err_exit_phy;
> + }
> +
> + return 0;
> +
> +err_exit_phy:
> + phy_exit(priv->phy);
> +err_disable_clks:
> + while (--clk >= 0)
> + clk_disable_unprepare(priv->clks[clk]);
> +
> + return ret;
> +}
> +
> +static void ehci_platform_power_off(struct platform_device *dev)
> +{
> + struct usb_hcd *hcd = platform_get_drvdata(dev);
> + struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
> + int clk;
> +
> + if (priv->phy) {
> + phy_power_off(priv->phy);
> + phy_exit(priv->phy);
> + }
> +
> + for (clk = EHCI_MAX_CLKS - 1; clk >= 0; clk--)
> + if (priv->clks[clk])
> + clk_disable_unprepare(priv->clks[clk]);
> +}
> +
> static struct hc_driver __read_mostly ehci_platform_hc_driver;
>
> static const struct ehci_driver_overrides platform_overrides __initconst = {
> - .reset = ehci_platform_reset,
> + .reset = ehci_platform_reset,
> + .extra_priv_size = sizeof(struct ehci_platform_priv),
> };
>
> -static struct usb_ehci_pdata ehci_platform_defaults;
> +static struct usb_ehci_pdata ehci_platform_defaults = {
> + .power_on = ehci_platform_power_on,
> + .power_suspend = ehci_platform_power_off,
> + .power_off = ehci_platform_power_off,
> +};
>
> static int ehci_platform_probe(struct platform_device *dev)
> {
> struct usb_hcd *hcd;
> struct resource *res_mem;
> - struct usb_ehci_pdata *pdata;
> - int irq;
> - int err;
> + struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev);
> + struct ehci_platform_priv *priv;
> + int err, irq, clk = 0;
>
> if (usb_disabled())
> return -ENODEV;
>
> /*
> - * use reasonable defaults so platforms don't have to provide these.
> - * with DT probing on ARM, none of these are set.
> + * Use reasonable defaults so platforms don't have to provide these
> + * with DT probing on ARM.
> */
> - if (!dev_get_platdata(&dev->dev))
> - dev->dev.platform_data = &ehci_platform_defaults;
> + if (!pdata)
> + pdata = &ehci_platform_defaults;
>
> err = dma_coerce_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
> if (err)
> return err;
>
> - pdata = dev_get_platdata(&dev->dev);
> -
> irq = platform_get_irq(dev, 0);
> if (irq < 0) {
> dev_err(&dev->dev, "no irq provided");
> @@ -107,17 +169,40 @@ static int ehci_platform_probe(struct platform_device *dev)
> return -ENXIO;
> }
>
> + hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev,
> + dev_name(&dev->dev));
> + if (!hcd)
> + return -ENOMEM;
> +
> + platform_set_drvdata(dev, hcd);
> + dev->dev.platform_data = pdata;
> + priv = hcd_to_ehci_priv(hcd);
> +
> + if (pdata == &ehci_platform_defaults && dev->dev.of_node) {
> + priv->phy = devm_phy_get(&dev->dev, "usb");
> + if (IS_ERR(priv->phy)) {
> + err = PTR_ERR(priv->phy);
> + if (err == -EPROBE_DEFER)
> + goto err_put_hcd;
> + priv->phy = NULL;
> + }
> +
> + for (clk = 0; clk < EHCI_MAX_CLKS; clk++) {
> + priv->clks[clk] = of_clk_get(dev->dev.of_node, clk);
> + if (IS_ERR(priv->clks[clk])) {
> + err = PTR_ERR(priv->clks[clk]);
> + if (err == -EPROBE_DEFER)
> + goto err_put_clks;
> + priv->clks[clk] = NULL;
> + break;
> + }
> + }
> + }
> +
> if (pdata->power_on) {
> err = pdata->power_on(dev);
> if (err < 0)
> - return err;
> - }
> -
> - hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev,
> - dev_name(&dev->dev));
> - if (!hcd) {
> - err = -ENOMEM;
> - goto err_power;
> + goto err_put_clks;
> }
>
> hcd->rsrc_start = res_mem->start;
> @@ -126,22 +211,28 @@ static int ehci_platform_probe(struct platform_device *dev)
> hcd->regs = devm_ioremap_resource(&dev->dev, res_mem);
> if (IS_ERR(hcd->regs)) {
> err = PTR_ERR(hcd->regs);
> - goto err_put_hcd;
> + goto err_power;
> }
> err = usb_add_hcd(hcd, irq, IRQF_SHARED);
> if (err)
> - goto err_put_hcd;
> + goto err_power;
>
> device_wakeup_enable(hcd->self.controller);
> platform_set_drvdata(dev, hcd);
>
> return err;
>
> -err_put_hcd:
> - usb_put_hcd(hcd);
> err_power:
> if (pdata->power_off)
> pdata->power_off(dev);
> +err_put_clks:
> + while (--clk >= 0)
> + clk_put(priv->clks[clk]);
> +err_put_hcd:
> + if (pdata == &ehci_platform_defaults)
> + dev->dev.platform_data = NULL;
> +
> + usb_put_hcd(hcd);
>
> return err;
> }
> @@ -150,13 +241,19 @@ static int ehci_platform_remove(struct platform_device *dev)
> {
> struct usb_hcd *hcd = platform_get_drvdata(dev);
> struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev);
> + struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
> + int clk;
>
> usb_remove_hcd(hcd);
> - usb_put_hcd(hcd);
>
> if (pdata->power_off)
> pdata->power_off(dev);
>
> + for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++)
> + clk_put(priv->clks[clk]);
> +
> + usb_put_hcd(hcd);
> +
> if (pdata == &ehci_platform_defaults)
> dev->dev.platform_data = NULL;
>
> @@ -207,8 +304,10 @@ static int ehci_platform_resume(struct device *dev)
> static const struct of_device_id vt8500_ehci_ids[] = {
> { .compatible = "via,vt8500-ehci", },
> { .compatible = "wm,prizm-ehci", },
> + { .compatible = "usb-ehci", },
> {}
> };
> +MODULE_DEVICE_TABLE(of, vt8500_ehci_ids);
>
> static const struct platform_device_id ehci_platform_table[] = {
> { "ehci-platform", 0 },
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v9 2/4] ehci-platform: Add support for clks and phy passed through devicetree
[not found] ` <52F9E98B.90407-l0cyMroinI0@public.gmane.org>
@ 2014-02-11 9:31 ` Hans de Goede
[not found] ` <52F9EE06.3070003-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
0 siblings, 1 reply; 12+ messages in thread
From: Hans de Goede @ 2014-02-11 9:31 UTC (permalink / raw)
To: Roger Quadros, Greg Kroah-Hartman
Cc: Alan Stern, Tony Prisk, linux-usb, Maxime Ripard,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree,
Menon, Nishanth, Kevin Hilman
Hi,
On 02/11/2014 10:12 AM, Roger Quadros wrote:
> Hi Hans,
>
> On 02/07/2014 05:36 PM, Hans de Goede wrote:
>> Currently ehci-platform is only used in combination with devicetree when used
>> with some Via socs. By extending it to (optionally) get clks and a phy from
>> devicetree, and enabling / disabling those on power_on / off, it can be used
>> more generically. Specifically after this commit it can be used for the
>> ehci controller on Allwinner sunxi SoCs.
>>
>> Since ehci-platform is intended to handle any generic enough non pci ehci
>> device, add a "usb-ehci" compatibility string.
>>
>> There already is a usb-ehci device-tree bindings document, update this
>> with clks and phy bindings info.
>>
>> Although actually quite generic so far the via,vt8500 compatibilty string
>> had its own bindings document. Somehow we even ended up with 2 of them. Since
>> these provide no extra information over the generic usb-ehci documentation,
>> this patch removes them.
>>
>> The ehci-ppc-of.c driver also claims the usb-ehci compatibility string,
>> even though it mostly is ibm,usb-ehci-440epx specific. ehci-platform.c is
>> not needed on ppc platforms, so add a !PPC_OF dependency to it to avoid
>> 2 drivers claiming the same compatibility string getting build on ppc.
>>
>
> This breaks all OMAP platforms on linux-next for the exact same reason. see [1].
>
> ./arch/arm/boot/dts/omap4.dtsi: compatible = "ti,ehci-omap", "usb-ehci";
> ./arch/arm/boot/dts/omap3.dtsi: compatible = "ti,ehci-omap", "usb-ehci";
> ./arch/arm/boot/dts/omap5.dtsi: compatible = "ti,ehci-omap", "usb-ehci";
That should not be the case, the driver core should try to find a driver matching
the compatibility string from left to right, or in other words from most specific
to least specific. This is part of the whole devicetree design.
So as long as the driver claiming "ti,ehci-omap" is available at probe time that
one should get used and things should work fine. Now if ehci-platform is built-in
and ehci-omap is a module, then I guess one could see the described breakage.
If the driver is built-in and things are not working, then we will need to do some
debugging as to why the left to right matching is not working as expected.
I must admit I'm not sure what happens if both are a module, the kernel direct
module load will likely fail due to lack of a rootfs at that point, and then
the module will later get loaded by udev I assume, at which point there are no
loading ordering guarantees.
The easiest solution to ensure that "ti,ehci-omap" is available at probe time
(if enabled) seems to be to change USB_EHCI_HCD_OMAP to a boolean.
Regards,
Hans
>
>
> The other platforms that claim compatibility with "usb-ehci" are
>
> ARM
> ./arch/arm/boot/dts/tegra30.dtsi: compatible = "nvidia,tegra30-ehci", "usb-ehci";
> ./arch/arm/boot/dts/tegra20.dtsi: compatible = "nvidia,tegra20-ehci", "usb-ehci";
> ./arch/arm/boot/dts/spear600.dtsi: compatible = "st,spear600-ehci", "usb-ehci";
>
> ./arch/arm/boot/dts/spear3xx.dtsi: compatible = "st,spear600-ehci", "usb-ehci";
> ./arch/arm/boot/dts/sama5d3.dtsi: compatible = "atmel,at91sam9g45-ehci", "usb-ehci";
> ./arch/arm/boot/dts/at91sam9g45.dtsi: compatible = "atmel,at91sam9g45-ehci", "usb-ehci";
> ./arch/arm/boot/dts/spear13xx.dtsi: compatible = "st,spear600-ehci", "usb-ehci";
> ./arch/arm/boot/dts/at91sam9x5.dtsi: compatible = "atmel,at91sam9g45-ehci", "usb-ehci";
> ./arch/arm/boot/dts/tegra114.dtsi: compatible = "nvidia,tegra30-ehci", "usb-ehci";
>
>
> MIPS
> ./arch/mips/cavium-octeon/octeon_68xx.dts: compatible = "cavium,octeon-6335-ehci","usb-ehci";
> ./arch/mips/cavium-octeon/octeon_3xxx.dts: compatible = "cavium,octeon-6335-ehci","usb-ehci";
>
> Do we know that we don't break these platforms as well?
>
> cheers,
> -roger
>
> [1] - http://marc.info/?l=linux-usb&m=139204800102167&w=2
>
>> Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
>> Acked-by: Alan Stern <stern-nwvwT67g6+6dFdvTe/nMLpVzexx5G7lz@public.gmane.org>
>> ---
>> Documentation/devicetree/bindings/usb/usb-ehci.txt | 25 +++-
>> .../devicetree/bindings/usb/via,vt8500-ehci.txt | 15 ---
>> .../devicetree/bindings/usb/vt8500-ehci.txt | 12 --
>> drivers/usb/host/Kconfig | 1 +
>> drivers/usb/host/ehci-platform.c | 147 +++++++++++++++++----
>> 5 files changed, 142 insertions(+), 58 deletions(-)
>> delete mode 100644 Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt
>> delete mode 100644 Documentation/devicetree/bindings/usb/vt8500-ehci.txt
>>
>> diff --git a/Documentation/devicetree/bindings/usb/usb-ehci.txt b/Documentation/devicetree/bindings/usb/usb-ehci.txt
>> index fa18612..2c1aeeb 100644
>> --- a/Documentation/devicetree/bindings/usb/usb-ehci.txt
>> +++ b/Documentation/devicetree/bindings/usb/usb-ehci.txt
>> @@ -7,13 +7,14 @@ Required properties:
>> (debug-port or other) can be also specified here, but only after
>> definition of standard EHCI registers.
>> - interrupts : one EHCI interrupt should be described here.
>> -If device registers are implemented in big endian mode, the device
>> -node should have "big-endian-regs" property.
>> -If controller implementation operates with big endian descriptors,
>> -"big-endian-desc" property should be specified.
>> -If both big endian registers and descriptors are used by the controller
>> -implementation, "big-endian" property can be specified instead of having
>> -both "big-endian-regs" and "big-endian-desc".
>> +
>> +Optional properties:
>> + - big-endian-regs : boolean, set this for hcds with big-endian registers
>> + - big-endian-desc : boolean, set this for hcds with big-endian descriptors
>> + - big-endian : boolean, for hcds with big-endian-regs + big-endian-desc
>> + - clocks : a list of phandle + clock specifier pairs
>> + - phys : phandle + phy specifier pair
>> + - phy-names : "usb"
>>
>> Example (Sequoia 440EPx):
>> ehci@e0000300 {
>> @@ -23,3 +24,13 @@ Example (Sequoia 440EPx):
>> reg = <0 e0000300 90 0 e0000390 70>;
>> big-endian;
>> };
>> +
>> +Example (Allwinner sun4i A10 SoC):
>> + ehci0: usb@01c14000 {
>> + compatible = "allwinner,sun4i-a10-ehci", "usb-ehci";
>> + reg = <0x01c14000 0x100>;
>> + interrupts = <39>;
>> + clocks = <&ahb_gates 1>;
>> + phys = <&usbphy 1>;
>> + phy-names = "usb";
>> + };
>> diff --git a/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt b/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt
>> deleted file mode 100644
>> index 17b3ad1..0000000
>> --- a/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt
>> +++ /dev/null
>> @@ -1,15 +0,0 @@
>> -VIA/Wondermedia VT8500 EHCI Controller
>> ------------------------------------------------------
>> -
>> -Required properties:
>> -- compatible : "via,vt8500-ehci"
>> -- reg : Should contain 1 register ranges(address and length)
>> -- interrupts : ehci controller interrupt
>> -
>> -Example:
>> -
>> - ehci@d8007900 {
>> - compatible = "via,vt8500-ehci";
>> - reg = <0xd8007900 0x200>;
>> - interrupts = <43>;
>> - };
>> diff --git a/Documentation/devicetree/bindings/usb/vt8500-ehci.txt b/Documentation/devicetree/bindings/usb/vt8500-ehci.txt
>> deleted file mode 100644
>> index 5fb8fd6..0000000
>> --- a/Documentation/devicetree/bindings/usb/vt8500-ehci.txt
>> +++ /dev/null
>> @@ -1,12 +0,0 @@
>> -VIA VT8500 and Wondermedia WM8xxx SoC USB controllers.
>> -
>> -Required properties:
>> - - compatible: Should be "via,vt8500-ehci" or "wm,prizm-ehci".
>> - - reg: Address range of the ehci registers. size should be 0x200
>> - - interrupts: Should contain the ehci interrupt.
>> -
>> -usb: ehci@D8007100 {
>> - compatible = "wm,prizm-ehci", "usb-ehci";
>> - reg = <0xD8007100 0x200>;
>> - interrupts = <1>;
>> -};
>> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
>> index a9707da..e28cbe0 100644
>> --- a/drivers/usb/host/Kconfig
>> +++ b/drivers/usb/host/Kconfig
>> @@ -255,6 +255,7 @@ config USB_EHCI_ATH79
>>
>> config USB_EHCI_HCD_PLATFORM
>> tristate "Generic EHCI driver for a platform device"
>> + depends on !PPC_OF
>> default n
>> ---help---
>> Adds an EHCI host driver for a generic platform device, which
>> diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
>> index 01536cf..5ebd0b7 100644
>> --- a/drivers/usb/host/ehci-platform.c
>> +++ b/drivers/usb/host/ehci-platform.c
>> @@ -3,6 +3,7 @@
>> *
>> * Copyright 2007 Steven Brown <sbrown-aLUkz7fEuXBWk0Htik3J/w@public.gmane.org>
>> * Copyright 2010-2012 Hauke Mehrtens <hauke-5/S+JYg5SzeELgA04lAiVw@public.gmane.org>
>> + * Copyright 2014 Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
>> *
>> * Derived from the ohci-ssb driver
>> * Copyright 2007 Michael Buesch <m@bues.ch>
>> @@ -18,6 +19,7 @@
>> *
>> * Licensed under the GNU/GPL. See COPYING for details.
>> */
>> +#include <linux/clk.h>
>> #include <linux/dma-mapping.h>
>> #include <linux/err.h>
>> #include <linux/kernel.h>
>> @@ -25,6 +27,7 @@
>> #include <linux/io.h>
>> #include <linux/module.h>
>> #include <linux/of.h>
>> +#include <linux/phy/phy.h>
>> #include <linux/platform_device.h>
>> #include <linux/usb.h>
>> #include <linux/usb/hcd.h>
>> @@ -33,6 +36,13 @@
>> #include "ehci.h"
>>
>> #define DRIVER_DESC "EHCI generic platform driver"
>> +#define EHCI_MAX_CLKS 3
>> +#define hcd_to_ehci_priv(h) ((struct ehci_platform_priv *)hcd_to_ehci(h)->priv)
>> +
>> +struct ehci_platform_priv {
>> + struct clk *clks[EHCI_MAX_CLKS];
>> + struct phy *phy;
>> +};
>>
>> static const char hcd_name[] = "ehci-platform";
>>
>> @@ -64,38 +74,90 @@ static int ehci_platform_reset(struct usb_hcd *hcd)
>> return 0;
>> }
>>
>> +static int ehci_platform_power_on(struct platform_device *dev)
>> +{
>> + struct usb_hcd *hcd = platform_get_drvdata(dev);
>> + struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
>> + int clk, ret;
>> +
>> + for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++) {
>> + ret = clk_prepare_enable(priv->clks[clk]);
>> + if (ret)
>> + goto err_disable_clks;
>> + }
>> +
>> + if (priv->phy) {
>> + ret = phy_init(priv->phy);
>> + if (ret)
>> + goto err_disable_clks;
>> +
>> + ret = phy_power_on(priv->phy);
>> + if (ret)
>> + goto err_exit_phy;
>> + }
>> +
>> + return 0;
>> +
>> +err_exit_phy:
>> + phy_exit(priv->phy);
>> +err_disable_clks:
>> + while (--clk >= 0)
>> + clk_disable_unprepare(priv->clks[clk]);
>> +
>> + return ret;
>> +}
>> +
>> +static void ehci_platform_power_off(struct platform_device *dev)
>> +{
>> + struct usb_hcd *hcd = platform_get_drvdata(dev);
>> + struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
>> + int clk;
>> +
>> + if (priv->phy) {
>> + phy_power_off(priv->phy);
>> + phy_exit(priv->phy);
>> + }
>> +
>> + for (clk = EHCI_MAX_CLKS - 1; clk >= 0; clk--)
>> + if (priv->clks[clk])
>> + clk_disable_unprepare(priv->clks[clk]);
>> +}
>> +
>> static struct hc_driver __read_mostly ehci_platform_hc_driver;
>>
>> static const struct ehci_driver_overrides platform_overrides __initconst = {
>> - .reset = ehci_platform_reset,
>> + .reset = ehci_platform_reset,
>> + .extra_priv_size = sizeof(struct ehci_platform_priv),
>> };
>>
>> -static struct usb_ehci_pdata ehci_platform_defaults;
>> +static struct usb_ehci_pdata ehci_platform_defaults = {
>> + .power_on = ehci_platform_power_on,
>> + .power_suspend = ehci_platform_power_off,
>> + .power_off = ehci_platform_power_off,
>> +};
>>
>> static int ehci_platform_probe(struct platform_device *dev)
>> {
>> struct usb_hcd *hcd;
>> struct resource *res_mem;
>> - struct usb_ehci_pdata *pdata;
>> - int irq;
>> - int err;
>> + struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev);
>> + struct ehci_platform_priv *priv;
>> + int err, irq, clk = 0;
>>
>> if (usb_disabled())
>> return -ENODEV;
>>
>> /*
>> - * use reasonable defaults so platforms don't have to provide these.
>> - * with DT probing on ARM, none of these are set.
>> + * Use reasonable defaults so platforms don't have to provide these
>> + * with DT probing on ARM.
>> */
>> - if (!dev_get_platdata(&dev->dev))
>> - dev->dev.platform_data = &ehci_platform_defaults;
>> + if (!pdata)
>> + pdata = &ehci_platform_defaults;
>>
>> err = dma_coerce_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
>> if (err)
>> return err;
>>
>> - pdata = dev_get_platdata(&dev->dev);
>> -
>> irq = platform_get_irq(dev, 0);
>> if (irq < 0) {
>> dev_err(&dev->dev, "no irq provided");
>> @@ -107,17 +169,40 @@ static int ehci_platform_probe(struct platform_device *dev)
>> return -ENXIO;
>> }
>>
>> + hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev,
>> + dev_name(&dev->dev));
>> + if (!hcd)
>> + return -ENOMEM;
>> +
>> + platform_set_drvdata(dev, hcd);
>> + dev->dev.platform_data = pdata;
>> + priv = hcd_to_ehci_priv(hcd);
>> +
>> + if (pdata == &ehci_platform_defaults && dev->dev.of_node) {
>> + priv->phy = devm_phy_get(&dev->dev, "usb");
>> + if (IS_ERR(priv->phy)) {
>> + err = PTR_ERR(priv->phy);
>> + if (err == -EPROBE_DEFER)
>> + goto err_put_hcd;
>> + priv->phy = NULL;
>> + }
>> +
>> + for (clk = 0; clk < EHCI_MAX_CLKS; clk++) {
>> + priv->clks[clk] = of_clk_get(dev->dev.of_node, clk);
>> + if (IS_ERR(priv->clks[clk])) {
>> + err = PTR_ERR(priv->clks[clk]);
>> + if (err == -EPROBE_DEFER)
>> + goto err_put_clks;
>> + priv->clks[clk] = NULL;
>> + break;
>> + }
>> + }
>> + }
>> +
>> if (pdata->power_on) {
>> err = pdata->power_on(dev);
>> if (err < 0)
>> - return err;
>> - }
>> -
>> - hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev,
>> - dev_name(&dev->dev));
>> - if (!hcd) {
>> - err = -ENOMEM;
>> - goto err_power;
>> + goto err_put_clks;
>> }
>>
>> hcd->rsrc_start = res_mem->start;
>> @@ -126,22 +211,28 @@ static int ehci_platform_probe(struct platform_device *dev)
>> hcd->regs = devm_ioremap_resource(&dev->dev, res_mem);
>> if (IS_ERR(hcd->regs)) {
>> err = PTR_ERR(hcd->regs);
>> - goto err_put_hcd;
>> + goto err_power;
>> }
>> err = usb_add_hcd(hcd, irq, IRQF_SHARED);
>> if (err)
>> - goto err_put_hcd;
>> + goto err_power;
>>
>> device_wakeup_enable(hcd->self.controller);
>> platform_set_drvdata(dev, hcd);
>>
>> return err;
>>
>> -err_put_hcd:
>> - usb_put_hcd(hcd);
>> err_power:
>> if (pdata->power_off)
>> pdata->power_off(dev);
>> +err_put_clks:
>> + while (--clk >= 0)
>> + clk_put(priv->clks[clk]);
>> +err_put_hcd:
>> + if (pdata == &ehci_platform_defaults)
>> + dev->dev.platform_data = NULL;
>> +
>> + usb_put_hcd(hcd);
>>
>> return err;
>> }
>> @@ -150,13 +241,19 @@ static int ehci_platform_remove(struct platform_device *dev)
>> {
>> struct usb_hcd *hcd = platform_get_drvdata(dev);
>> struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev);
>> + struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
>> + int clk;
>>
>> usb_remove_hcd(hcd);
>> - usb_put_hcd(hcd);
>>
>> if (pdata->power_off)
>> pdata->power_off(dev);
>>
>> + for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++)
>> + clk_put(priv->clks[clk]);
>> +
>> + usb_put_hcd(hcd);
>> +
>> if (pdata == &ehci_platform_defaults)
>> dev->dev.platform_data = NULL;
>>
>> @@ -207,8 +304,10 @@ static int ehci_platform_resume(struct device *dev)
>> static const struct of_device_id vt8500_ehci_ids[] = {
>> { .compatible = "via,vt8500-ehci", },
>> { .compatible = "wm,prizm-ehci", },
>> + { .compatible = "usb-ehci", },
>> {}
>> };
>> +MODULE_DEVICE_TABLE(of, vt8500_ehci_ids);
>>
>> static const struct platform_device_id ehci_platform_table[] = {
>> { "ehci-platform", 0 },
>>
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v9 2/4] ehci-platform: Add support for clks and phy passed through devicetree
[not found] ` <52F9EE06.3070003-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2014-02-11 10:00 ` Roger Quadros
[not found] ` <52F9F4C6.6080201-l0cyMroinI0@public.gmane.org>
0 siblings, 1 reply; 12+ messages in thread
From: Roger Quadros @ 2014-02-11 10:00 UTC (permalink / raw)
To: Hans de Goede, Greg Kroah-Hartman
Cc: Alan Stern, Tony Prisk, linux-usb, Maxime Ripard,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree,
Menon, Nishanth, Kevin Hilman
On 02/11/2014 11:31 AM, Hans de Goede wrote:
> Hi,
>
> On 02/11/2014 10:12 AM, Roger Quadros wrote:
>> Hi Hans,
>>
>> On 02/07/2014 05:36 PM, Hans de Goede wrote:
>>> Currently ehci-platform is only used in combination with devicetree when used
>>> with some Via socs. By extending it to (optionally) get clks and a phy from
>>> devicetree, and enabling / disabling those on power_on / off, it can be used
>>> more generically. Specifically after this commit it can be used for the
>>> ehci controller on Allwinner sunxi SoCs.
>>>
>>> Since ehci-platform is intended to handle any generic enough non pci ehci
>>> device, add a "usb-ehci" compatibility string.
>>>
>>> There already is a usb-ehci device-tree bindings document, update this
>>> with clks and phy bindings info.
>>>
>>> Although actually quite generic so far the via,vt8500 compatibilty string
>>> had its own bindings document. Somehow we even ended up with 2 of them. Since
>>> these provide no extra information over the generic usb-ehci documentation,
>>> this patch removes them.
>>>
>>> The ehci-ppc-of.c driver also claims the usb-ehci compatibility string,
>>> even though it mostly is ibm,usb-ehci-440epx specific. ehci-platform.c is
>>> not needed on ppc platforms, so add a !PPC_OF dependency to it to avoid
>>> 2 drivers claiming the same compatibility string getting build on ppc.
>>>
>>
>> This breaks all OMAP platforms on linux-next for the exact same reason. see [1].
>>
>> ./arch/arm/boot/dts/omap4.dtsi: compatible = "ti,ehci-omap", "usb-ehci";
>> ./arch/arm/boot/dts/omap3.dtsi: compatible = "ti,ehci-omap", "usb-ehci";
>> ./arch/arm/boot/dts/omap5.dtsi: compatible = "ti,ehci-omap", "usb-ehci";
>
> That should not be the case, the driver core should try to find a driver matching
> the compatibility string from left to right, or in other words from most specific
> to least specific. This is part of the whole devicetree design.
>
> So as long as the driver claiming "ti,ehci-omap" is available at probe time that
> one should get used and things should work fine. Now if ehci-platform is built-in
> and ehci-omap is a module, then I guess one could see the described breakage.
>
> If the driver is built-in and things are not working, then we will need to do some
> debugging as to why the left to right matching is not working as expected.
Both ehci_platform and ehci_omap were built-in and still the ehci_platform driver got
probe preference. So it looks like the left to right compatible list priority probing
feature doesn't work.
>
> I must admit I'm not sure what happens if both are a module, the kernel direct
> module load will likely fail due to lack of a rootfs at that point, and then
> the module will later get loaded by udev I assume, at which point there are no
> loading ordering guarantees.
>
> The easiest solution to ensure that "ti,ehci-omap" is available at probe time
> (if enabled) seems to be to change USB_EHCI_HCD_OMAP to a boolean.
That is a limitation I don't like to have for USB_EHCI_HCD_OMAP.
cheers,
-roger
>
>
>>
>>
>> The other platforms that claim compatibility with "usb-ehci" are
>>
>> ARM
>> ./arch/arm/boot/dts/tegra30.dtsi: compatible = "nvidia,tegra30-ehci", "usb-ehci";
>> ./arch/arm/boot/dts/tegra20.dtsi: compatible = "nvidia,tegra20-ehci", "usb-ehci";
>> ./arch/arm/boot/dts/spear600.dtsi: compatible = "st,spear600-ehci", "usb-ehci";
>>
>> ./arch/arm/boot/dts/spear3xx.dtsi: compatible = "st,spear600-ehci", "usb-ehci";
>> ./arch/arm/boot/dts/sama5d3.dtsi: compatible = "atmel,at91sam9g45-ehci", "usb-ehci";
>> ./arch/arm/boot/dts/at91sam9g45.dtsi: compatible = "atmel,at91sam9g45-ehci", "usb-ehci";
>> ./arch/arm/boot/dts/spear13xx.dtsi: compatible = "st,spear600-ehci", "usb-ehci";
>> ./arch/arm/boot/dts/at91sam9x5.dtsi: compatible = "atmel,at91sam9g45-ehci", "usb-ehci";
>> ./arch/arm/boot/dts/tegra114.dtsi: compatible = "nvidia,tegra30-ehci", "usb-ehci";
>>
>>
>> MIPS
>> ./arch/mips/cavium-octeon/octeon_68xx.dts: compatible = "cavium,octeon-6335-ehci","usb-ehci";
>> ./arch/mips/cavium-octeon/octeon_3xxx.dts: compatible = "cavium,octeon-6335-ehci","usb-ehci";
>>
>> Do we know that we don't break these platforms as well?
>>
>> cheers,
>> -roger
>>
>> [1] - http://marc.info/?l=linux-usb&m=139204800102167&w=2
>>
>>> Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
>>> Acked-by: Alan Stern <stern-nwvwT67g6+6dFdvTe/nMLpVzexx5G7lz@public.gmane.org>
>>> ---
>>> Documentation/devicetree/bindings/usb/usb-ehci.txt | 25 +++-
>>> .../devicetree/bindings/usb/via,vt8500-ehci.txt | 15 ---
>>> .../devicetree/bindings/usb/vt8500-ehci.txt | 12 --
>>> drivers/usb/host/Kconfig | 1 +
>>> drivers/usb/host/ehci-platform.c | 147 +++++++++++++++++----
>>> 5 files changed, 142 insertions(+), 58 deletions(-)
>>> delete mode 100644 Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt
>>> delete mode 100644 Documentation/devicetree/bindings/usb/vt8500-ehci.txt
>>>
>>> diff --git a/Documentation/devicetree/bindings/usb/usb-ehci.txt b/Documentation/devicetree/bindings/usb/usb-ehci.txt
>>> index fa18612..2c1aeeb 100644
>>> --- a/Documentation/devicetree/bindings/usb/usb-ehci.txt
>>> +++ b/Documentation/devicetree/bindings/usb/usb-ehci.txt
>>> @@ -7,13 +7,14 @@ Required properties:
>>> (debug-port or other) can be also specified here, but only after
>>> definition of standard EHCI registers.
>>> - interrupts : one EHCI interrupt should be described here.
>>> -If device registers are implemented in big endian mode, the device
>>> -node should have "big-endian-regs" property.
>>> -If controller implementation operates with big endian descriptors,
>>> -"big-endian-desc" property should be specified.
>>> -If both big endian registers and descriptors are used by the controller
>>> -implementation, "big-endian" property can be specified instead of having
>>> -both "big-endian-regs" and "big-endian-desc".
>>> +
>>> +Optional properties:
>>> + - big-endian-regs : boolean, set this for hcds with big-endian registers
>>> + - big-endian-desc : boolean, set this for hcds with big-endian descriptors
>>> + - big-endian : boolean, for hcds with big-endian-regs + big-endian-desc
>>> + - clocks : a list of phandle + clock specifier pairs
>>> + - phys : phandle + phy specifier pair
>>> + - phy-names : "usb"
>>>
>>> Example (Sequoia 440EPx):
>>> ehci@e0000300 {
>>> @@ -23,3 +24,13 @@ Example (Sequoia 440EPx):
>>> reg = <0 e0000300 90 0 e0000390 70>;
>>> big-endian;
>>> };
>>> +
>>> +Example (Allwinner sun4i A10 SoC):
>>> + ehci0: usb@01c14000 {
>>> + compatible = "allwinner,sun4i-a10-ehci", "usb-ehci";
>>> + reg = <0x01c14000 0x100>;
>>> + interrupts = <39>;
>>> + clocks = <&ahb_gates 1>;
>>> + phys = <&usbphy 1>;
>>> + phy-names = "usb";
>>> + };
>>> diff --git a/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt b/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt
>>> deleted file mode 100644
>>> index 17b3ad1..0000000
>>> --- a/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt
>>> +++ /dev/null
>>> @@ -1,15 +0,0 @@
>>> -VIA/Wondermedia VT8500 EHCI Controller
>>> ------------------------------------------------------
>>> -
>>> -Required properties:
>>> -- compatible : "via,vt8500-ehci"
>>> -- reg : Should contain 1 register ranges(address and length)
>>> -- interrupts : ehci controller interrupt
>>> -
>>> -Example:
>>> -
>>> - ehci@d8007900 {
>>> - compatible = "via,vt8500-ehci";
>>> - reg = <0xd8007900 0x200>;
>>> - interrupts = <43>;
>>> - };
>>> diff --git a/Documentation/devicetree/bindings/usb/vt8500-ehci.txt b/Documentation/devicetree/bindings/usb/vt8500-ehci.txt
>>> deleted file mode 100644
>>> index 5fb8fd6..0000000
>>> --- a/Documentation/devicetree/bindings/usb/vt8500-ehci.txt
>>> +++ /dev/null
>>> @@ -1,12 +0,0 @@
>>> -VIA VT8500 and Wondermedia WM8xxx SoC USB controllers.
>>> -
>>> -Required properties:
>>> - - compatible: Should be "via,vt8500-ehci" or "wm,prizm-ehci".
>>> - - reg: Address range of the ehci registers. size should be 0x200
>>> - - interrupts: Should contain the ehci interrupt.
>>> -
>>> -usb: ehci@D8007100 {
>>> - compatible = "wm,prizm-ehci", "usb-ehci";
>>> - reg = <0xD8007100 0x200>;
>>> - interrupts = <1>;
>>> -};
>>> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
>>> index a9707da..e28cbe0 100644
>>> --- a/drivers/usb/host/Kconfig
>>> +++ b/drivers/usb/host/Kconfig
>>> @@ -255,6 +255,7 @@ config USB_EHCI_ATH79
>>>
>>> config USB_EHCI_HCD_PLATFORM
>>> tristate "Generic EHCI driver for a platform device"
>>> + depends on !PPC_OF
>>> default n
>>> ---help---
>>> Adds an EHCI host driver for a generic platform device, which
>>> diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
>>> index 01536cf..5ebd0b7 100644
>>> --- a/drivers/usb/host/ehci-platform.c
>>> +++ b/drivers/usb/host/ehci-platform.c
>>> @@ -3,6 +3,7 @@
>>> *
>>> * Copyright 2007 Steven Brown <sbrown-aLUkz7fEuXBWk0Htik3J/w@public.gmane.org>
>>> * Copyright 2010-2012 Hauke Mehrtens <hauke-5/S+JYg5SzeELgA04lAiVw@public.gmane.org>
>>> + * Copyright 2014 Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
>>> *
>>> * Derived from the ohci-ssb driver
>>> * Copyright 2007 Michael Buesch <m@bues.ch>
>>> @@ -18,6 +19,7 @@
>>> *
>>> * Licensed under the GNU/GPL. See COPYING for details.
>>> */
>>> +#include <linux/clk.h>
>>> #include <linux/dma-mapping.h>
>>> #include <linux/err.h>
>>> #include <linux/kernel.h>
>>> @@ -25,6 +27,7 @@
>>> #include <linux/io.h>
>>> #include <linux/module.h>
>>> #include <linux/of.h>
>>> +#include <linux/phy/phy.h>
>>> #include <linux/platform_device.h>
>>> #include <linux/usb.h>
>>> #include <linux/usb/hcd.h>
>>> @@ -33,6 +36,13 @@
>>> #include "ehci.h"
>>>
>>> #define DRIVER_DESC "EHCI generic platform driver"
>>> +#define EHCI_MAX_CLKS 3
>>> +#define hcd_to_ehci_priv(h) ((struct ehci_platform_priv *)hcd_to_ehci(h)->priv)
>>> +
>>> +struct ehci_platform_priv {
>>> + struct clk *clks[EHCI_MAX_CLKS];
>>> + struct phy *phy;
>>> +};
>>>
>>> static const char hcd_name[] = "ehci-platform";
>>>
>>> @@ -64,38 +74,90 @@ static int ehci_platform_reset(struct usb_hcd *hcd)
>>> return 0;
>>> }
>>>
>>> +static int ehci_platform_power_on(struct platform_device *dev)
>>> +{
>>> + struct usb_hcd *hcd = platform_get_drvdata(dev);
>>> + struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
>>> + int clk, ret;
>>> +
>>> + for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++) {
>>> + ret = clk_prepare_enable(priv->clks[clk]);
>>> + if (ret)
>>> + goto err_disable_clks;
>>> + }
>>> +
>>> + if (priv->phy) {
>>> + ret = phy_init(priv->phy);
>>> + if (ret)
>>> + goto err_disable_clks;
>>> +
>>> + ret = phy_power_on(priv->phy);
>>> + if (ret)
>>> + goto err_exit_phy;
>>> + }
>>> +
>>> + return 0;
>>> +
>>> +err_exit_phy:
>>> + phy_exit(priv->phy);
>>> +err_disable_clks:
>>> + while (--clk >= 0)
>>> + clk_disable_unprepare(priv->clks[clk]);
>>> +
>>> + return ret;
>>> +}
>>> +
>>> +static void ehci_platform_power_off(struct platform_device *dev)
>>> +{
>>> + struct usb_hcd *hcd = platform_get_drvdata(dev);
>>> + struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
>>> + int clk;
>>> +
>>> + if (priv->phy) {
>>> + phy_power_off(priv->phy);
>>> + phy_exit(priv->phy);
>>> + }
>>> +
>>> + for (clk = EHCI_MAX_CLKS - 1; clk >= 0; clk--)
>>> + if (priv->clks[clk])
>>> + clk_disable_unprepare(priv->clks[clk]);
>>> +}
>>> +
>>> static struct hc_driver __read_mostly ehci_platform_hc_driver;
>>>
>>> static const struct ehci_driver_overrides platform_overrides __initconst = {
>>> - .reset = ehci_platform_reset,
>>> + .reset = ehci_platform_reset,
>>> + .extra_priv_size = sizeof(struct ehci_platform_priv),
>>> };
>>>
>>> -static struct usb_ehci_pdata ehci_platform_defaults;
>>> +static struct usb_ehci_pdata ehci_platform_defaults = {
>>> + .power_on = ehci_platform_power_on,
>>> + .power_suspend = ehci_platform_power_off,
>>> + .power_off = ehci_platform_power_off,
>>> +};
>>>
>>> static int ehci_platform_probe(struct platform_device *dev)
>>> {
>>> struct usb_hcd *hcd;
>>> struct resource *res_mem;
>>> - struct usb_ehci_pdata *pdata;
>>> - int irq;
>>> - int err;
>>> + struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev);
>>> + struct ehci_platform_priv *priv;
>>> + int err, irq, clk = 0;
>>>
>>> if (usb_disabled())
>>> return -ENODEV;
>>>
>>> /*
>>> - * use reasonable defaults so platforms don't have to provide these.
>>> - * with DT probing on ARM, none of these are set.
>>> + * Use reasonable defaults so platforms don't have to provide these
>>> + * with DT probing on ARM.
>>> */
>>> - if (!dev_get_platdata(&dev->dev))
>>> - dev->dev.platform_data = &ehci_platform_defaults;
>>> + if (!pdata)
>>> + pdata = &ehci_platform_defaults;
>>>
>>> err = dma_coerce_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
>>> if (err)
>>> return err;
>>>
>>> - pdata = dev_get_platdata(&dev->dev);
>>> -
>>> irq = platform_get_irq(dev, 0);
>>> if (irq < 0) {
>>> dev_err(&dev->dev, "no irq provided");
>>> @@ -107,17 +169,40 @@ static int ehci_platform_probe(struct platform_device *dev)
>>> return -ENXIO;
>>> }
>>>
>>> + hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev,
>>> + dev_name(&dev->dev));
>>> + if (!hcd)
>>> + return -ENOMEM;
>>> +
>>> + platform_set_drvdata(dev, hcd);
>>> + dev->dev.platform_data = pdata;
>>> + priv = hcd_to_ehci_priv(hcd);
>>> +
>>> + if (pdata == &ehci_platform_defaults && dev->dev.of_node) {
>>> + priv->phy = devm_phy_get(&dev->dev, "usb");
>>> + if (IS_ERR(priv->phy)) {
>>> + err = PTR_ERR(priv->phy);
>>> + if (err == -EPROBE_DEFER)
>>> + goto err_put_hcd;
>>> + priv->phy = NULL;
>>> + }
>>> +
>>> + for (clk = 0; clk < EHCI_MAX_CLKS; clk++) {
>>> + priv->clks[clk] = of_clk_get(dev->dev.of_node, clk);
>>> + if (IS_ERR(priv->clks[clk])) {
>>> + err = PTR_ERR(priv->clks[clk]);
>>> + if (err == -EPROBE_DEFER)
>>> + goto err_put_clks;
>>> + priv->clks[clk] = NULL;
>>> + break;
>>> + }
>>> + }
>>> + }
>>> +
>>> if (pdata->power_on) {
>>> err = pdata->power_on(dev);
>>> if (err < 0)
>>> - return err;
>>> - }
>>> -
>>> - hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev,
>>> - dev_name(&dev->dev));
>>> - if (!hcd) {
>>> - err = -ENOMEM;
>>> - goto err_power;
>>> + goto err_put_clks;
>>> }
>>>
>>> hcd->rsrc_start = res_mem->start;
>>> @@ -126,22 +211,28 @@ static int ehci_platform_probe(struct platform_device *dev)
>>> hcd->regs = devm_ioremap_resource(&dev->dev, res_mem);
>>> if (IS_ERR(hcd->regs)) {
>>> err = PTR_ERR(hcd->regs);
>>> - goto err_put_hcd;
>>> + goto err_power;
>>> }
>>> err = usb_add_hcd(hcd, irq, IRQF_SHARED);
>>> if (err)
>>> - goto err_put_hcd;
>>> + goto err_power;
>>>
>>> device_wakeup_enable(hcd->self.controller);
>>> platform_set_drvdata(dev, hcd);
>>>
>>> return err;
>>>
>>> -err_put_hcd:
>>> - usb_put_hcd(hcd);
>>> err_power:
>>> if (pdata->power_off)
>>> pdata->power_off(dev);
>>> +err_put_clks:
>>> + while (--clk >= 0)
>>> + clk_put(priv->clks[clk]);
>>> +err_put_hcd:
>>> + if (pdata == &ehci_platform_defaults)
>>> + dev->dev.platform_data = NULL;
>>> +
>>> + usb_put_hcd(hcd);
>>>
>>> return err;
>>> }
>>> @@ -150,13 +241,19 @@ static int ehci_platform_remove(struct platform_device *dev)
>>> {
>>> struct usb_hcd *hcd = platform_get_drvdata(dev);
>>> struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev);
>>> + struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
>>> + int clk;
>>>
>>> usb_remove_hcd(hcd);
>>> - usb_put_hcd(hcd);
>>>
>>> if (pdata->power_off)
>>> pdata->power_off(dev);
>>>
>>> + for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++)
>>> + clk_put(priv->clks[clk]);
>>> +
>>> + usb_put_hcd(hcd);
>>> +
>>> if (pdata == &ehci_platform_defaults)
>>> dev->dev.platform_data = NULL;
>>>
>>> @@ -207,8 +304,10 @@ static int ehci_platform_resume(struct device *dev)
>>> static const struct of_device_id vt8500_ehci_ids[] = {
>>> { .compatible = "via,vt8500-ehci", },
>>> { .compatible = "wm,prizm-ehci", },
>>> + { .compatible = "usb-ehci", },
>>> {}
>>> };
>>> +MODULE_DEVICE_TABLE(of, vt8500_ehci_ids);
>>>
>>> static const struct platform_device_id ehci_platform_table[] = {
>>> { "ehci-platform", 0 },
>>>
>>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v9 2/4] ehci-platform: Add support for clks and phy passed through devicetree
[not found] ` <52F9F4C6.6080201-l0cyMroinI0@public.gmane.org>
@ 2014-02-11 10:13 ` Hans de Goede
[not found] ` <52F9F7B3.6080802-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
0 siblings, 1 reply; 12+ messages in thread
From: Hans de Goede @ 2014-02-11 10:13 UTC (permalink / raw)
To: Roger Quadros, Greg Kroah-Hartman
Cc: Alan Stern, Tony Prisk, linux-usb, Maxime Ripard,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree,
Menon, Nishanth, Kevin Hilman
Hi,
On 02/11/2014 11:00 AM, Roger Quadros wrote:
> On 02/11/2014 11:31 AM, Hans de Goede wrote:
>> Hi,
>>
>> On 02/11/2014 10:12 AM, Roger Quadros wrote:
>>> Hi Hans,
>>>
>>> On 02/07/2014 05:36 PM, Hans de Goede wrote:
>>>> Currently ehci-platform is only used in combination with devicetree when used
>>>> with some Via socs. By extending it to (optionally) get clks and a phy from
>>>> devicetree, and enabling / disabling those on power_on / off, it can be used
>>>> more generically. Specifically after this commit it can be used for the
>>>> ehci controller on Allwinner sunxi SoCs.
>>>>
>>>> Since ehci-platform is intended to handle any generic enough non pci ehci
>>>> device, add a "usb-ehci" compatibility string.
>>>>
>>>> There already is a usb-ehci device-tree bindings document, update this
>>>> with clks and phy bindings info.
>>>>
>>>> Although actually quite generic so far the via,vt8500 compatibilty string
>>>> had its own bindings document. Somehow we even ended up with 2 of them. Since
>>>> these provide no extra information over the generic usb-ehci documentation,
>>>> this patch removes them.
>>>>
>>>> The ehci-ppc-of.c driver also claims the usb-ehci compatibility string,
>>>> even though it mostly is ibm,usb-ehci-440epx specific. ehci-platform.c is
>>>> not needed on ppc platforms, so add a !PPC_OF dependency to it to avoid
>>>> 2 drivers claiming the same compatibility string getting build on ppc.
>>>>
>>>
>>> This breaks all OMAP platforms on linux-next for the exact same reason. see [1].
>>>
>>> ./arch/arm/boot/dts/omap4.dtsi: compatible = "ti,ehci-omap", "usb-ehci";
>>> ./arch/arm/boot/dts/omap3.dtsi: compatible = "ti,ehci-omap", "usb-ehci";
>>> ./arch/arm/boot/dts/omap5.dtsi: compatible = "ti,ehci-omap", "usb-ehci";
>>
>> That should not be the case, the driver core should try to find a driver matching
>> the compatibility string from left to right, or in other words from most specific
>> to least specific. This is part of the whole devicetree design.
>>
>> So as long as the driver claiming "ti,ehci-omap" is available at probe time that
>> one should get used and things should work fine. Now if ehci-platform is built-in
>> and ehci-omap is a module, then I guess one could see the described breakage.
>>
>> If the driver is built-in and things are not working, then we will need to do some
>> debugging as to why the left to right matching is not working as expected.
>
> Both ehci_platform and ehci_omap were built-in and still the ehci_platform driver got
> probe preference. So it looks like the left to right compatible list priority probing
> feature doesn't work.
Oops, I guess nothing relies on it sofar. Well we could go and debug and fix this but...
>
>>
>> I must admit I'm not sure what happens if both are a module, the kernel direct
>> module load will likely fail due to lack of a rootfs at that point, and then
>> the module will later get loaded by udev I assume, at which point there are no
>> loading ordering guarantees.
>>
>> The easiest solution to ensure that "ti,ehci-omap" is available at probe time
>> (if enabled) seems to be to change USB_EHCI_HCD_OMAP to a boolean.
>
> That is a limitation I don't like to have for USB_EHCI_HCD_OMAP.
I completely understand, thinking more about this I'm simply going to change the
compatibility string for ohci- and ehci-platform to be "ohci-platform" resp.
"ehci-platform". I know there are some people who don't like the -platform
suffix, but though luck, as the above clearly shows using the generic "usb-ohci" /
"usb-ehci" they were advocating for leads to a ton of issues, and we already
have a precedent for ?hci-platform in the form of "xhci-platform".
Regards,
Hans
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v9 2/4] ehci-platform: Add support for clks and phy passed through devicetree
[not found] ` <52F9F7B3.6080802-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2014-02-11 13:42 ` Roger Quadros
0 siblings, 0 replies; 12+ messages in thread
From: Roger Quadros @ 2014-02-11 13:42 UTC (permalink / raw)
To: Hans de Goede, Greg Kroah-Hartman
Cc: Alan Stern, Tony Prisk, linux-usb, Maxime Ripard,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree,
Menon, Nishanth, Kevin Hilman
On 02/11/2014 12:13 PM, Hans de Goede wrote:
> Hi,
>
> On 02/11/2014 11:00 AM, Roger Quadros wrote:
>> On 02/11/2014 11:31 AM, Hans de Goede wrote:
>>> Hi,
>>>
>>> On 02/11/2014 10:12 AM, Roger Quadros wrote:
>>>> Hi Hans,
>>>>
>>>> On 02/07/2014 05:36 PM, Hans de Goede wrote:
>>>>> Currently ehci-platform is only used in combination with devicetree when used
>>>>> with some Via socs. By extending it to (optionally) get clks and a phy from
>>>>> devicetree, and enabling / disabling those on power_on / off, it can be used
>>>>> more generically. Specifically after this commit it can be used for the
>>>>> ehci controller on Allwinner sunxi SoCs.
>>>>>
>>>>> Since ehci-platform is intended to handle any generic enough non pci ehci
>>>>> device, add a "usb-ehci" compatibility string.
>>>>>
>>>>> There already is a usb-ehci device-tree bindings document, update this
>>>>> with clks and phy bindings info.
>>>>>
>>>>> Although actually quite generic so far the via,vt8500 compatibilty string
>>>>> had its own bindings document. Somehow we even ended up with 2 of them. Since
>>>>> these provide no extra information over the generic usb-ehci documentation,
>>>>> this patch removes them.
>>>>>
>>>>> The ehci-ppc-of.c driver also claims the usb-ehci compatibility string,
>>>>> even though it mostly is ibm,usb-ehci-440epx specific. ehci-platform.c is
>>>>> not needed on ppc platforms, so add a !PPC_OF dependency to it to avoid
>>>>> 2 drivers claiming the same compatibility string getting build on ppc.
>>>>>
>>>>
>>>> This breaks all OMAP platforms on linux-next for the exact same reason. see [1].
>>>>
>>>> ./arch/arm/boot/dts/omap4.dtsi: compatible = "ti,ehci-omap", "usb-ehci";
>>>> ./arch/arm/boot/dts/omap3.dtsi: compatible = "ti,ehci-omap", "usb-ehci";
>>>> ./arch/arm/boot/dts/omap5.dtsi: compatible = "ti,ehci-omap", "usb-ehci";
>>>
>>> That should not be the case, the driver core should try to find a driver matching
>>> the compatibility string from left to right, or in other words from most specific
>>> to least specific. This is part of the whole devicetree design.
>>>
>>> So as long as the driver claiming "ti,ehci-omap" is available at probe time that
>>> one should get used and things should work fine. Now if ehci-platform is built-in
>>> and ehci-omap is a module, then I guess one could see the described breakage.
>>>
>>> If the driver is built-in and things are not working, then we will need to do some
>>> debugging as to why the left to right matching is not working as expected.
>>
>> Both ehci_platform and ehci_omap were built-in and still the ehci_platform driver got
>> probe preference. So it looks like the left to right compatible list priority probing
>> feature doesn't work.
>
> Oops, I guess nothing relies on it sofar. Well we could go and debug and fix this but...
>
I think we have a misunderstanding. The compatible list priority probing is only for the
platform identification compatible. I don't think it is meant to work with driver core yet.
http://lxr.free-electrons.com/source/Documentation/devicetree/usage-model.txt#L116
>>
>>>
>>> I must admit I'm not sure what happens if both are a module, the kernel direct
>>> module load will likely fail due to lack of a rootfs at that point, and then
>>> the module will later get loaded by udev I assume, at which point there are no
>>> loading ordering guarantees.
>>>
>>> The easiest solution to ensure that "ti,ehci-omap" is available at probe time
>>> (if enabled) seems to be to change USB_EHCI_HCD_OMAP to a boolean.
>>
>> That is a limitation I don't like to have for USB_EHCI_HCD_OMAP.
>
> I completely understand, thinking more about this I'm simply going to change the
> compatibility string for ohci- and ehci-platform to be "ohci-platform" resp.
> "ehci-platform". I know there are some people who don't like the -platform
> suffix, but though luck, as the above clearly shows using the generic "usb-ohci" /
> "usb-ehci" they were advocating for leads to a ton of issues, and we already
> have a precedent for ?hci-platform in the form of "xhci-platform".
+1
cheers,
-roger
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2014-02-11 13:42 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-02-07 15:36 [PATCH v9 0/4] ohci-platform and ehci-plaform patches rebased on 3.14-rc1 Hans de Goede
[not found] ` <1391787403-20961-1-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2014-02-07 15:36 ` [PATCH v9 1/4] ohci-platform: Add support for devicetree instantiation Hans de Goede
2014-02-07 15:36 ` [PATCH v9 2/4] ehci-platform: Add support for clks and phy passed through devicetree Hans de Goede
[not found] ` <1391787403-20961-3-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2014-02-11 9:12 ` Roger Quadros
[not found] ` <52F9E98B.90407-l0cyMroinI0@public.gmane.org>
2014-02-11 9:31 ` Hans de Goede
[not found] ` <52F9EE06.3070003-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2014-02-11 10:00 ` Roger Quadros
[not found] ` <52F9F4C6.6080201-l0cyMroinI0@public.gmane.org>
2014-02-11 10:13 ` Hans de Goede
[not found] ` <52F9F7B3.6080802-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2014-02-11 13:42 ` Roger Quadros
2014-02-07 15:36 ` [PATCH v9 3/4] ohci-platform: Add support for controllers with big-endian regs / descriptors Hans de Goede
2014-02-07 15:36 ` [PATCH v9 4/4] ehci-platform: " Hans de Goede
2014-02-07 22:31 ` [PATCH v9 0/4] ohci-platform and ehci-plaform patches rebased on 3.14-rc1 Greg Kroah-Hartman
[not found] ` <20140207223101.GA21062-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org>
2014-02-07 23:05 ` Hans de Goede
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).