097-1-usb-dwc3-add-generic-OF-glue-layer.patch 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. From 41c2b5280cd2fa3e198c422cdf223ba6e48f857a Mon Sep 17 00:00:00 2001
  2. From: Felipe Balbi <balbi@ti.com>
  3. Date: Wed, 18 Nov 2015 13:15:20 -0600
  4. Subject: [PATCH] usb: dwc3: add generic OF glue layer
  5. For simple platforms which merely enable some clocks
  6. and populate its children, we can use this generic
  7. glue layer to avoid boilerplate code duplication.
  8. For now this supports Qcom and Xilinx, but if we
  9. find a way to add generic handling of regulators and
  10. optional PHYs, we can absorb exynos as well.
  11. Tested-by: Subbaraya Sundeep Bhatta <subbaraya.sundeep.bhatta@xilinx.com>
  12. Signed-off-by: Felipe Balbi <balbi@ti.com>
  13. (cherry picked from commit 16adc674d0d68a50dfc725574738d7ae11cf5d7e)
  14. Change-Id: I6fd260442997b198dc12ca726814b7a9518e6353
  15. Signed-off-by: Nitheesh Sekar <nsekar@codeaurora.org>
  16. ---
  17. drivers/usb/dwc3/Kconfig | 9 ++
  18. drivers/usb/dwc3/Makefile | 1 +
  19. drivers/usb/dwc3/dwc3-of-simple.c | 178 ++++++++++++++++++++++++++++++++++++++
  20. 3 files changed, 188 insertions(+)
  21. create mode 100644 drivers/usb/dwc3/dwc3-of-simple.c
  22. --- a/drivers/usb/dwc3/Kconfig
  23. +++ b/drivers/usb/dwc3/Kconfig
  24. @@ -87,6 +87,15 @@ config USB_DWC3_KEYSTONE
  25. Support of USB2/3 functionality in TI Keystone2 platforms.
  26. Say 'Y' or 'M' here if you have one such device
  27. +config USB_DWC3_OF_SIMPLE
  28. + tristate "Generic OF Simple Glue Layer"
  29. + depends on OF && COMMON_CLK
  30. + default USB_DWC3
  31. + help
  32. + Support USB2/3 functionality in simple SoC integrations.
  33. + Currently supports Xilinx and Qualcomm DWC USB3 IP.
  34. + Say 'Y' or 'M' if you have one such device.
  35. +
  36. config USB_DWC3_ST
  37. tristate "STMicroelectronics Platforms"
  38. depends on ARCH_STI && OF
  39. --- a/drivers/usb/dwc3/Makefile
  40. +++ b/drivers/usb/dwc3/Makefile
  41. @@ -37,5 +37,6 @@ obj-$(CONFIG_USB_DWC3_OMAP) += dwc3-oma
  42. obj-$(CONFIG_USB_DWC3_EXYNOS) += dwc3-exynos.o
  43. obj-$(CONFIG_USB_DWC3_PCI) += dwc3-pci.o
  44. obj-$(CONFIG_USB_DWC3_KEYSTONE) += dwc3-keystone.o
  45. +obj-$(CONFIG_USB_DWC3_OF_SIMPLE) += dwc3-of-simple.o
  46. obj-$(CONFIG_USB_DWC3_QCOM) += dwc3-qcom.o
  47. obj-$(CONFIG_USB_DWC3_ST) += dwc3-st.o
  48. --- /dev/null
  49. +++ b/drivers/usb/dwc3/dwc3-of-simple.c
  50. @@ -0,0 +1,178 @@
  51. +/**
  52. + * dwc3-of-simple.c - OF glue layer for simple integrations
  53. + *
  54. + * Copyright (c) 2015 Texas Instruments Incorporated - http://www.ti.com
  55. + *
  56. + * Author: Felipe Balbi <balbi@ti.com>
  57. + *
  58. + * This program is free software: you can redistribute it and/or modify
  59. + * it under the terms of the GNU General Public License version 2 of
  60. + * the License as published by the Free Software Foundation.
  61. + *
  62. + * This program is distributed in the hope that it will be useful,
  63. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  64. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  65. + * GNU General Public License for more details.
  66. + *
  67. + * This is a combination of the old dwc3-qcom.c by Ivan T. Ivanov
  68. + * <iivanov@mm-sol.com> and the original patch adding support for Xilinx' SoC
  69. + * by Subbaraya Sundeep Bhatta <subbaraya.sundeep.bhatta@xilinx.com>
  70. + */
  71. +
  72. +#include <linux/module.h>
  73. +#include <linux/kernel.h>
  74. +#include <linux/slab.h>
  75. +#include <linux/platform_device.h>
  76. +#include <linux/dma-mapping.h>
  77. +#include <linux/clk.h>
  78. +#include <linux/clk-provider.h>
  79. +#include <linux/of.h>
  80. +#include <linux/of_platform.h>
  81. +#include <linux/pm_runtime.h>
  82. +
  83. +struct dwc3_of_simple {
  84. + struct device *dev;
  85. + struct clk **clks;
  86. + int num_clocks;
  87. +};
  88. +
  89. +static int dwc3_of_simple_probe(struct platform_device *pdev)
  90. +{
  91. + struct dwc3_of_simple *simple;
  92. + struct device *dev = &pdev->dev;
  93. + struct device_node *np = dev->of_node;
  94. +
  95. + int ret;
  96. + int i;
  97. +
  98. + simple = devm_kzalloc(dev, sizeof(*simple), GFP_KERNEL);
  99. + if (!simple)
  100. + return -ENOMEM;
  101. +
  102. + ret = of_clk_get_parent_count(np);
  103. + if (ret < 0)
  104. + return ret;
  105. +
  106. + simple->num_clocks = ret;
  107. +
  108. + simple->clks = devm_kcalloc(dev, simple->num_clocks,
  109. + sizeof(struct clk *), GFP_KERNEL);
  110. + if (!simple->clks)
  111. + return -ENOMEM;
  112. +
  113. + simple->dev = dev;
  114. +
  115. + for (i = 0; i < simple->num_clocks; i++) {
  116. + struct clk *clk;
  117. +
  118. + clk = of_clk_get(np, i);
  119. + if (IS_ERR(clk)) {
  120. + while (--i >= 0)
  121. + clk_put(simple->clks[i]);
  122. + return PTR_ERR(clk);
  123. + }
  124. +
  125. + ret = clk_prepare_enable(clk);
  126. + if (ret < 0) {
  127. + while (--i >= 0) {
  128. + clk_disable_unprepare(simple->clks[i]);
  129. + clk_put(simple->clks[i]);
  130. + }
  131. + clk_put(clk);
  132. +
  133. + return ret;
  134. + }
  135. +
  136. + simple->clks[i] = clk;
  137. + }
  138. +
  139. + ret = of_platform_populate(np, NULL, NULL, dev);
  140. + if (ret) {
  141. + for (i = 0; i < simple->num_clocks; i++) {
  142. + clk_disable_unprepare(simple->clks[i]);
  143. + clk_put(simple->clks[i]);
  144. + }
  145. +
  146. + return ret;
  147. + }
  148. +
  149. + pm_runtime_set_active(dev);
  150. + pm_runtime_enable(dev);
  151. + pm_runtime_get_sync(dev);
  152. +
  153. + return 0;
  154. +}
  155. +
  156. +static int dwc3_of_simple_remove(struct platform_device *pdev)
  157. +{
  158. + struct dwc3_of_simple *simple = platform_get_drvdata(pdev);
  159. + struct device *dev = &pdev->dev;
  160. + int i;
  161. +
  162. + for (i = 0; i < simple->num_clocks; i++) {
  163. + clk_unprepare(simple->clks[i]);
  164. + clk_put(simple->clks[i]);
  165. + }
  166. +
  167. + of_platform_depopulate(dev);
  168. +
  169. + pm_runtime_put_sync(dev);
  170. + pm_runtime_disable(dev);
  171. +
  172. + return 0;
  173. +}
  174. +
  175. +static int dwc3_of_simple_runtime_suspend(struct device *dev)
  176. +{
  177. + struct dwc3_of_simple *simple = dev_get_drvdata(dev);
  178. + int i;
  179. +
  180. + for (i = 0; i < simple->num_clocks; i++)
  181. + clk_disable(simple->clks[i]);
  182. +
  183. + return 0;
  184. +}
  185. +
  186. +static int dwc3_of_simple_runtime_resume(struct device *dev)
  187. +{
  188. + struct dwc3_of_simple *simple = dev_get_drvdata(dev);
  189. + int ret;
  190. + int i;
  191. +
  192. + for (i = 0; i < simple->num_clocks; i++) {
  193. + ret = clk_enable(simple->clks[i]);
  194. + if (ret < 0) {
  195. + while (--i >= 0)
  196. + clk_disable(simple->clks[i]);
  197. + return ret;
  198. + }
  199. + }
  200. +
  201. + return 0;
  202. +}
  203. +
  204. +static const struct dev_pm_ops dwc3_of_simple_dev_pm_ops = {
  205. + SET_RUNTIME_PM_OPS(dwc3_of_simple_runtime_suspend,
  206. + dwc3_of_simple_runtime_resume, NULL)
  207. +};
  208. +
  209. +static const struct of_device_id of_dwc3_simple_match[] = {
  210. + { .compatible = "qcom,dwc3" },
  211. + { .compatible = "xlnx,zynqmp-dwc3" },
  212. + { /* Sentinel */ }
  213. +};
  214. +MODULE_DEVICE_TABLE(of, of_dwc3_simple_match);
  215. +
  216. +static struct platform_driver dwc3_of_simple_driver = {
  217. + .probe = dwc3_of_simple_probe,
  218. + .remove = dwc3_of_simple_remove,
  219. + .driver = {
  220. + .name = "dwc3-of-simple",
  221. + .of_match_table = of_dwc3_simple_match,
  222. + },
  223. +};
  224. +
  225. +module_platform_driver(dwc3_of_simple_driver);
  226. +MODULE_LICENSE("GPL v2");
  227. +MODULE_DESCRIPTION("DesignWare USB3 OF Simple Glue Layer");
  228. +MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");