diff options
Diffstat (limited to 'target/linux/ipq806x/patches-4.4/097-1-usb-dwc3-add-generic-OF-glue-layer.patch')
-rw-r--r-- | target/linux/ipq806x/patches-4.4/097-1-usb-dwc3-add-generic-OF-glue-layer.patch | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/target/linux/ipq806x/patches-4.4/097-1-usb-dwc3-add-generic-OF-glue-layer.patch b/target/linux/ipq806x/patches-4.4/097-1-usb-dwc3-add-generic-OF-glue-layer.patch new file mode 100644 index 0000000000..214bedc95a --- /dev/null +++ b/target/linux/ipq806x/patches-4.4/097-1-usb-dwc3-add-generic-OF-glue-layer.patch @@ -0,0 +1,234 @@ +From 41c2b5280cd2fa3e198c422cdf223ba6e48f857a Mon Sep 17 00:00:00 2001 +From: Felipe Balbi <balbi@ti.com> +Date: Wed, 18 Nov 2015 13:15:20 -0600 +Subject: [PATCH] usb: dwc3: add generic OF glue layer + +For simple platforms which merely enable some clocks +and populate its children, we can use this generic +glue layer to avoid boilerplate code duplication. + +For now this supports Qcom and Xilinx, but if we +find a way to add generic handling of regulators and +optional PHYs, we can absorb exynos as well. + +Tested-by: Subbaraya Sundeep Bhatta <subbaraya.sundeep.bhatta@xilinx.com> +Signed-off-by: Felipe Balbi <balbi@ti.com> +(cherry picked from commit 16adc674d0d68a50dfc725574738d7ae11cf5d7e) + +Change-Id: I6fd260442997b198dc12ca726814b7a9518e6353 +Signed-off-by: Nitheesh Sekar <nsekar@codeaurora.org> +--- + drivers/usb/dwc3/Kconfig | 9 ++ + drivers/usb/dwc3/Makefile | 1 + + drivers/usb/dwc3/dwc3-of-simple.c | 178 ++++++++++++++++++++++++++++++++++++++ + 3 files changed, 188 insertions(+) + create mode 100644 drivers/usb/dwc3/dwc3-of-simple.c + +--- a/drivers/usb/dwc3/Kconfig ++++ b/drivers/usb/dwc3/Kconfig +@@ -87,6 +87,15 @@ config USB_DWC3_KEYSTONE + Support of USB2/3 functionality in TI Keystone2 platforms. + Say 'Y' or 'M' here if you have one such device + ++config USB_DWC3_OF_SIMPLE ++ tristate "Generic OF Simple Glue Layer" ++ depends on OF && COMMON_CLK ++ default USB_DWC3 ++ help ++ Support USB2/3 functionality in simple SoC integrations. ++ Currently supports Xilinx and Qualcomm DWC USB3 IP. ++ Say 'Y' or 'M' if you have one such device. ++ + config USB_DWC3_ST + tristate "STMicroelectronics Platforms" + depends on ARCH_STI && OF +--- a/drivers/usb/dwc3/Makefile ++++ b/drivers/usb/dwc3/Makefile +@@ -37,5 +37,6 @@ obj-$(CONFIG_USB_DWC3_OMAP) += dwc3-oma + obj-$(CONFIG_USB_DWC3_EXYNOS) += dwc3-exynos.o + obj-$(CONFIG_USB_DWC3_PCI) += dwc3-pci.o + obj-$(CONFIG_USB_DWC3_KEYSTONE) += dwc3-keystone.o ++obj-$(CONFIG_USB_DWC3_OF_SIMPLE) += dwc3-of-simple.o + obj-$(CONFIG_USB_DWC3_QCOM) += dwc3-qcom.o + obj-$(CONFIG_USB_DWC3_ST) += dwc3-st.o +--- /dev/null ++++ b/drivers/usb/dwc3/dwc3-of-simple.c +@@ -0,0 +1,178 @@ ++/** ++ * dwc3-of-simple.c - OF glue layer for simple integrations ++ * ++ * Copyright (c) 2015 Texas Instruments Incorporated - http://www.ti.com ++ * ++ * Author: Felipe Balbi <balbi@ti.com> ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 of ++ * the License as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * This is a combination of the old dwc3-qcom.c by Ivan T. Ivanov ++ * <iivanov@mm-sol.com> and the original patch adding support for Xilinx' SoC ++ * by Subbaraya Sundeep Bhatta <subbaraya.sundeep.bhatta@xilinx.com> ++ */ ++ ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/slab.h> ++#include <linux/platform_device.h> ++#include <linux/dma-mapping.h> ++#include <linux/clk.h> ++#include <linux/clk-provider.h> ++#include <linux/of.h> ++#include <linux/of_platform.h> ++#include <linux/pm_runtime.h> ++ ++struct dwc3_of_simple { ++ struct device *dev; ++ struct clk **clks; ++ int num_clocks; ++}; ++ ++static int dwc3_of_simple_probe(struct platform_device *pdev) ++{ ++ struct dwc3_of_simple *simple; ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ ++ int ret; ++ int i; ++ ++ simple = devm_kzalloc(dev, sizeof(*simple), GFP_KERNEL); ++ if (!simple) ++ return -ENOMEM; ++ ++ ret = of_clk_get_parent_count(np); ++ if (ret < 0) ++ return ret; ++ ++ simple->num_clocks = ret; ++ ++ simple->clks = devm_kcalloc(dev, simple->num_clocks, ++ sizeof(struct clk *), GFP_KERNEL); ++ if (!simple->clks) ++ return -ENOMEM; ++ ++ simple->dev = dev; ++ ++ for (i = 0; i < simple->num_clocks; i++) { ++ struct clk *clk; ++ ++ clk = of_clk_get(np, i); ++ if (IS_ERR(clk)) { ++ while (--i >= 0) ++ clk_put(simple->clks[i]); ++ return PTR_ERR(clk); ++ } ++ ++ ret = clk_prepare_enable(clk); ++ if (ret < 0) { ++ while (--i >= 0) { ++ clk_disable_unprepare(simple->clks[i]); ++ clk_put(simple->clks[i]); ++ } ++ clk_put(clk); ++ ++ return ret; ++ } ++ ++ simple->clks[i] = clk; ++ } ++ ++ ret = of_platform_populate(np, NULL, NULL, dev); ++ if (ret) { ++ for (i = 0; i < simple->num_clocks; i++) { ++ clk_disable_unprepare(simple->clks[i]); ++ clk_put(simple->clks[i]); ++ } ++ ++ return ret; ++ } ++ ++ pm_runtime_set_active(dev); ++ pm_runtime_enable(dev); ++ pm_runtime_get_sync(dev); ++ ++ return 0; ++} ++ ++static int dwc3_of_simple_remove(struct platform_device *pdev) ++{ ++ struct dwc3_of_simple *simple = platform_get_drvdata(pdev); ++ struct device *dev = &pdev->dev; ++ int i; ++ ++ for (i = 0; i < simple->num_clocks; i++) { ++ clk_unprepare(simple->clks[i]); ++ clk_put(simple->clks[i]); ++ } ++ ++ of_platform_depopulate(dev); ++ ++ pm_runtime_put_sync(dev); ++ pm_runtime_disable(dev); ++ ++ return 0; ++} ++ ++static int dwc3_of_simple_runtime_suspend(struct device *dev) ++{ ++ struct dwc3_of_simple *simple = dev_get_drvdata(dev); ++ int i; ++ ++ for (i = 0; i < simple->num_clocks; i++) ++ clk_disable(simple->clks[i]); ++ ++ return 0; ++} ++ ++static int dwc3_of_simple_runtime_resume(struct device *dev) ++{ ++ struct dwc3_of_simple *simple = dev_get_drvdata(dev); ++ int ret; ++ int i; ++ ++ for (i = 0; i < simple->num_clocks; i++) { ++ ret = clk_enable(simple->clks[i]); ++ if (ret < 0) { ++ while (--i >= 0) ++ clk_disable(simple->clks[i]); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops dwc3_of_simple_dev_pm_ops = { ++ SET_RUNTIME_PM_OPS(dwc3_of_simple_runtime_suspend, ++ dwc3_of_simple_runtime_resume, NULL) ++}; ++ ++static const struct of_device_id of_dwc3_simple_match[] = { ++ { .compatible = "qcom,dwc3" }, ++ { .compatible = "xlnx,zynqmp-dwc3" }, ++ { /* Sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, of_dwc3_simple_match); ++ ++static struct platform_driver dwc3_of_simple_driver = { ++ .probe = dwc3_of_simple_probe, ++ .remove = dwc3_of_simple_remove, ++ .driver = { ++ .name = "dwc3-of-simple", ++ .of_match_table = of_dwc3_simple_match, ++ }, ++}; ++ ++module_platform_driver(dwc3_of_simple_driver); ++MODULE_LICENSE("GPL v2"); ++MODULE_DESCRIPTION("DesignWare USB3 OF Simple Glue Layer"); ++MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); |