diff options
Diffstat (limited to 'target/linux/sunxi/patches-3.14/195-1-ohci-plat-changes.patch')
-rw-r--r-- | target/linux/sunxi/patches-3.14/195-1-ohci-plat-changes.patch | 344 |
1 files changed, 0 insertions, 344 deletions
diff --git a/target/linux/sunxi/patches-3.14/195-1-ohci-plat-changes.patch b/target/linux/sunxi/patches-3.14/195-1-ohci-plat-changes.patch deleted file mode 100644 index fb4c87e..0000000 --- a/target/linux/sunxi/patches-3.14/195-1-ohci-plat-changes.patch +++ /dev/null @@ -1,344 +0,0 @@ -From 49ff47db168655cac5213cf5dd1844b08fb9823c Mon Sep 17 00:00:00 2001 -From: Hans de Goede <hdegoede@redhat.com> -Date: Sun, 5 Jan 2014 14:42:39 +0100 -Subject: [PATCH] ohci-platform: Add support for devicetree instantiation - -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@redhat.com> -Acked-by: Alan Stern <stern@rowland.harvard.edu> ---- - 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 - ---- /dev/null -+++ b/Documentation/devicetree/bindings/usb/usb-ohci.txt -@@ -0,0 +1,25 @@ -+USB OHCI controllers -+ -+Required properties: -+- compatible : "generic-ohci" -+- reg : ohci controller register range (address and length) -+- 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" -+ -+Example: -+ -+ ohci0: usb@01c14400 { -+ compatible = "allwinner,sun4i-a10-ohci", "generic-ohci"; -+ reg = <0x01c14400 0x100>; -+ interrupts = <64>; -+ clocks = <&usb_clk 6>, <&ahb_gates 2>; -+ phys = <&usbphy 1>; -+ phy-names = "usb"; -+ }; ---- 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@hauke-m.de> -+ * Copyright 2014 Hans de Goede <hdegoede@redhat.com> - * - * 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 us - 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,24 @@ static int ohci_platform_probe(struct pl - 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; -+ struct ohci_hcd *ohci; -+ 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 +157,66 @@ static int ohci_platform_probe(struct pl - 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); -+ 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); -+ 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 +225,11 @@ static int ohci_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); - -@@ -114,11 +237,17 @@ static int ohci_platform_probe(struct pl - - 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 +256,22 @@ static int ohci_platform_remove(struct p - { - 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 +318,12 @@ static int ohci_platform_resume(struct d - #define ohci_platform_resume NULL - #endif /* CONFIG_PM */ - -+static const struct of_device_id ohci_platform_ids[] = { -+ { .compatible = "generic-ohci", }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, ohci_platform_ids); -+ - static const struct platform_device_id ohci_platform_table[] = { - { "ohci-platform", 0 }, - { } -@@ -200,6 +344,7 @@ static struct platform_driver ohci_platf - .owner = THIS_MODULE, - .name = "ohci-platform", - .pm = &ohci_platform_pm_ops, -+ .of_match_table = ohci_platform_ids, - } - }; - |