diff options
Diffstat (limited to 'target/linux/sunxi/patches-3.14/195-2-ehci-plat-changes.patch')
-rw-r--r-- | target/linux/sunxi/patches-3.14/195-2-ehci-plat-changes.patch | 414 |
1 files changed, 0 insertions, 414 deletions
diff --git a/target/linux/sunxi/patches-3.14/195-2-ehci-plat-changes.patch b/target/linux/sunxi/patches-3.14/195-2-ehci-plat-changes.patch deleted file mode 100644 index 425993c7bb..0000000000 --- a/target/linux/sunxi/patches-3.14/195-2-ehci-plat-changes.patch +++ /dev/null @@ -1,414 +0,0 @@ -From 738b350437abfca820dae226549ecf4fb100fa30 Mon Sep 17 00:00:00 2001 -From: Hans de Goede <hdegoede@redhat.com> -Date: Sun, 5 Jan 2014 00:04:02 +0100 -Subject: [PATCH] ehci-platform: Add support for clks and phy passed through - devicetree - -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@redhat.com> -Acked-by: Alan Stern <stern@rowland.harvard.edu> ---- - 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 - ---- a/Documentation/devicetree/bindings/usb/usb-ehci.txt -+++ b/Documentation/devicetree/bindings/usb/usb-ehci.txt -@@ -1,19 +1,20 @@ - USB EHCI controllers - - Required properties: -- - compatible : should be "usb-ehci". -+ - compatible : should be "generic-ehci". - - reg : should contain at least address and length of the standard EHCI - register set for the device. Optional platform-dependent registers - (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", "generic-ehci"; -+ reg = <0x01c14000 0x100>; -+ interrupts = <39>; -+ clocks = <&ahb_gates 1>; -+ phys = <&usbphy 1>; -+ phy-names = "usb"; -+ }; ---- 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>; -- }; ---- 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>; --}; ---- a/drivers/usb/host/ehci-platform.c -+++ b/drivers/usb/host/ehci-platform.c -@@ -3,6 +3,7 @@ - * - * Copyright 2007 Steven Brown <sbrown@cortland.com> - * Copyright 2010-2012 Hauke Mehrtens <hauke@hauke-m.de> -+ * Copyright 2014 Hans de Goede <hdegoede@redhat.com> - * - * 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"; - -@@ -45,8 +55,10 @@ static int ehci_platform_reset(struct us - - 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; - ehci->ignore_oc = pdata->ignore_oc; - - if (pdata->pre_setup) { -@@ -65,38 +77,91 @@ static int ehci_platform_reset(struct us - 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; -+ struct ehci_hcd *ehci; -+ 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"); -@@ -108,17 +173,66 @@ static int ehci_platform_probe(struct pl - 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); -+ 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); -+ 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; -@@ -127,22 +241,28 @@ static int ehci_platform_probe(struct pl - 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; - } -@@ -151,13 +271,19 @@ static int ehci_platform_remove(struct p - { - 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; - -@@ -208,8 +334,10 @@ static int ehci_platform_resume(struct d - static const struct of_device_id vt8500_ehci_ids[] = { - { .compatible = "via,vt8500-ehci", }, - { .compatible = "wm,prizm-ehci", }, -+ { .compatible = "generic-ehci", }, - {} - }; -+MODULE_DEVICE_TABLE(of, vt8500_ehci_ids); - - static const struct platform_device_id ehci_platform_table[] = { - { "ehci-platform", 0 }, |