2 * dwc3-of-simple.c - OF glue layer for simple integrations
4 * Copyright (c) 2015 Texas Instruments Incorporated - http://www.ti.com
6 * Author: Felipe Balbi <balbi@ti.com>
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 of
10 * the License as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * This is a combination of the old dwc3-qcom.c by Ivan T. Ivanov
18 * <iivanov@mm-sol.com> and the original patch adding support for Xilinx' SoC
19 * by Subbaraya Sundeep Bhatta <subbaraya.sundeep.bhatta@xilinx.com>
22 #include <linux/module.h>
23 #include <linux/kernel.h>
24 #include <linux/slab.h>
25 #include <linux/platform_device.h>
26 #include <linux/dma-mapping.h>
27 #include <linux/clk.h>
28 #include <linux/clk-provider.h>
30 #include <linux/of_platform.h>
31 #include <linux/pm_runtime.h>
32 #include <linux/soc/xilinx/zynqmp/fw.h>
33 #include <linux/slab.h>
35 #include <linux/phy/phy-zynqmp.h>
36 #include <linux/of_address.h>
40 /* Xilinx USB 3.0 IP Register */
41 #define XLNX_USB_COHERENCY 0x005C
42 #define XLNX_USB_COHERENCY_ENABLE 0x1
44 /* ULPI control registers */
45 #define ULPI_OTG_CTRL_SET 0xB
46 #define ULPI_OTG_CTRL_CLEAR 0XC
47 #define OTG_CTRL_DRVVBUS_OFFSET 5
49 #define DWC3_OF_ADDRESS(ADDR) ((ADDR) - DWC3_GLOBALS_REGS_START)
51 struct dwc3_of_simple {
58 bool dis_u3_susphy_quirk;
61 void dwc3_set_phydata(struct device *dev, struct phy *phy)
63 struct device_node *node = of_get_parent(dev->of_node);
67 of_device_is_compatible(node, "xlnx,zynqmp-dwc3")) {
68 struct platform_device *pdev_parent;
69 struct dwc3_of_simple *simple;
71 pdev_parent = of_find_device_by_node(node);
72 simple = platform_get_drvdata(pdev_parent);
74 /* assign USB vendor regs to phy lane */
75 ret = xpsgtr_set_protregs(phy, simple->regs);
77 dev_err(&pdev_parent->dev,
78 "Not able to set PHY data\n");
82 EXPORT_SYMBOL(dwc3_set_phydata);
84 int dwc3_enable_hw_coherency(struct device *dev)
86 struct device_node *node = of_get_parent(dev->of_node);
88 if (of_device_is_compatible(node, "xlnx,zynqmp-dwc3")) {
89 struct platform_device *pdev_parent;
90 struct dwc3_of_simple *simple;
94 pdev_parent = of_find_device_by_node(node);
95 simple = platform_get_drvdata(pdev_parent);
98 reg = readl(regs + XLNX_USB_COHERENCY);
99 reg |= XLNX_USB_COHERENCY_ENABLE;
100 writel(reg, regs + XLNX_USB_COHERENCY);
105 EXPORT_SYMBOL(dwc3_enable_hw_coherency);
107 void dwc3_set_simple_data(struct dwc3 *dwc)
109 struct device_node *node = of_get_parent(dwc->dev->of_node);
111 if (node && of_device_is_compatible(node, "xlnx,zynqmp-dwc3")) {
112 struct platform_device *pdev_parent;
113 struct dwc3_of_simple *simple;
115 pdev_parent = of_find_device_by_node(node);
116 simple = platform_get_drvdata(pdev_parent);
118 /* Set (struct dwc3 *) to simple->dwc for future use */
122 EXPORT_SYMBOL(dwc3_set_simple_data);
124 void dwc3_simple_check_quirks(struct dwc3 *dwc)
126 struct device_node *node = of_get_parent(dwc->dev->of_node);
128 if (node && of_device_is_compatible(node, "xlnx,zynqmp-dwc3")) {
129 struct platform_device *pdev_parent;
130 struct dwc3_of_simple *simple;
132 pdev_parent = of_find_device_by_node(node);
133 simple = platform_get_drvdata(pdev_parent);
135 /* Add snps,dis_u3_susphy_quirk */
136 dwc->dis_u3_susphy_quirk = simple->dis_u3_susphy_quirk;
139 EXPORT_SYMBOL(dwc3_simple_check_quirks);
141 void dwc3_simple_wakeup_capable(struct device *dev, bool wakeup)
143 struct device_node *node =
144 of_find_compatible_node(dev->of_node, NULL, "xlnx,zynqmp-dwc3");
147 struct platform_device *pdev_parent;
148 struct dwc3_of_simple *simple;
150 pdev_parent = of_find_device_by_node(node);
151 simple = platform_get_drvdata(pdev_parent);
153 /* Set wakeup capable as true or false */
154 simple->wakeup_capable = wakeup;
157 EXPORT_SYMBOL(dwc3_simple_wakeup_capable);
159 static int dwc3_of_simple_clk_init(struct dwc3_of_simple *simple, int count)
161 struct device *dev = simple->dev;
162 struct device_node *np = dev->of_node;
165 simple->num_clocks = count;
170 simple->clks = devm_kcalloc(dev, simple->num_clocks,
171 sizeof(struct clk *), GFP_KERNEL);
175 for (i = 0; i < simple->num_clocks; i++) {
179 clk = of_clk_get(np, i);
182 clk_put(simple->clks[i]);
186 ret = clk_prepare_enable(clk);
189 clk_disable_unprepare(simple->clks[i]);
190 clk_put(simple->clks[i]);
197 simple->clks[i] = clk;
203 static int dwc3_of_simple_probe(struct platform_device *pdev)
205 struct dwc3_of_simple *simple;
206 struct device *dev = &pdev->dev;
207 struct device_node *np = dev->of_node;
212 simple = devm_kzalloc(dev, sizeof(*simple), GFP_KERNEL);
216 platform_set_drvdata(pdev, simple);
219 if (of_device_is_compatible(pdev->dev.of_node,
220 "xlnx,zynqmp-dwc3")) {
223 struct resource *res;
226 res = platform_get_resource(pdev,
229 regs = devm_ioremap_resource(&pdev->dev, res);
231 return PTR_ERR(regs);
233 /* Store the usb control regs into simple for further usage */
236 /* read Silicon version using nvmem driver */
237 soc_rev = zynqmp_nvmem_get_silicon_version(&pdev->dev,
240 if (PTR_ERR(soc_rev) == -EPROBE_DEFER) {
241 /* Do a deferred probe */
242 return -EPROBE_DEFER;
244 } else if (!IS_ERR(soc_rev) &&
245 (*soc_rev < ZYNQMP_SILICON_V4)) {
246 /* Add snps,dis_u3_susphy_quirk
247 * for SOC revison less than v4
249 simple->dis_u3_susphy_quirk = true;
252 /* Clean soc_rev if got a valid pointer from nvmem driver
253 * else we may end up in kernel panic
255 if (!IS_ERR(soc_rev))
259 ret = dwc3_of_simple_clk_init(simple, of_clk_get_parent_count(np));
263 ret = of_platform_populate(np, NULL, NULL, dev);
265 for (i = 0; i < simple->num_clocks; i++) {
266 clk_disable_unprepare(simple->clks[i]);
267 clk_put(simple->clks[i]);
273 platform_set_drvdata(pdev, simple);
275 pm_runtime_set_active(dev);
276 pm_runtime_enable(dev);
277 pm_runtime_get_sync(dev);
282 static int dwc3_of_simple_remove(struct platform_device *pdev)
284 struct dwc3_of_simple *simple = platform_get_drvdata(pdev);
285 struct device *dev = &pdev->dev;
288 of_platform_depopulate(dev);
290 for (i = 0; i < simple->num_clocks; i++) {
291 clk_disable_unprepare(simple->clks[i]);
292 clk_put(simple->clks[i]);
295 pm_runtime_put_sync(dev);
296 pm_runtime_disable(dev);
303 static void dwc3_simple_vbus(struct dwc3 *dwc, bool vbus_off)
309 addr = ULPI_OTG_CTRL_CLEAR;
311 addr = ULPI_OTG_CTRL_SET;
313 val = (1 << OTG_CTRL_DRVVBUS_OFFSET);
315 reg = DWC3_GUSB2PHYACC_NEWREGREQ | DWC3_GUSB2PHYACC_ADDR(addr);
316 reg |= DWC3_GUSB2PHYACC_WRITE | val;
318 addr = DWC3_OF_ADDRESS(DWC3_GUSB2PHYACC(0));
319 writel(reg, dwc->regs + addr);
322 static int dwc3_of_simple_suspend(struct device *dev)
324 struct dwc3_of_simple *simple = dev_get_drvdata(dev);
327 if (!simple->wakeup_capable) {
328 /* Ask ULPI to turn OFF Vbus */
329 dwc3_simple_vbus(simple->dwc, true);
331 /* Disable the clocks */
332 for (i = 0; i < simple->num_clocks; i++)
333 clk_disable(simple->clks[i]);
339 static int dwc3_of_simple_resume(struct device *dev)
341 struct dwc3_of_simple *simple = dev_get_drvdata(dev);
345 if (simple->wakeup_capable)
348 for (i = 0; i < simple->num_clocks; i++) {
349 ret = clk_enable(simple->clks[i]);
352 clk_disable(simple->clks[i]);
356 /* Ask ULPI to turn ON Vbus */
357 dwc3_simple_vbus(simple->dwc, false);
363 static int dwc3_of_simple_runtime_suspend(struct device *dev)
365 struct dwc3_of_simple *simple = dev_get_drvdata(dev);
368 for (i = 0; i < simple->num_clocks; i++)
369 clk_disable(simple->clks[i]);
374 static int dwc3_of_simple_runtime_resume(struct device *dev)
376 struct dwc3_of_simple *simple = dev_get_drvdata(dev);
380 for (i = 0; i < simple->num_clocks; i++) {
381 ret = clk_enable(simple->clks[i]);
384 clk_disable(simple->clks[i]);
393 static const struct dev_pm_ops dwc3_of_simple_dev_pm_ops = {
394 SET_SYSTEM_SLEEP_PM_OPS(dwc3_of_simple_suspend,
395 dwc3_of_simple_resume)
396 SET_RUNTIME_PM_OPS(dwc3_of_simple_runtime_suspend,
397 dwc3_of_simple_runtime_resume, NULL)
400 static const struct of_device_id of_dwc3_simple_match[] = {
401 { .compatible = "qcom,dwc3" },
402 { .compatible = "rockchip,rk3399-dwc3" },
403 { .compatible = "xlnx,zynqmp-dwc3" },
404 { .compatible = "cavium,octeon-7130-usb-uctl" },
407 MODULE_DEVICE_TABLE(of, of_dwc3_simple_match);
409 static struct platform_driver dwc3_of_simple_driver = {
410 .probe = dwc3_of_simple_probe,
411 .remove = dwc3_of_simple_remove,
413 .name = "dwc3-of-simple",
414 .of_match_table = of_dwc3_simple_match,
415 .pm = &dwc3_of_simple_dev_pm_ops,
419 module_platform_driver(dwc3_of_simple_driver);
420 MODULE_LICENSE("GPL v2");
421 MODULE_DESCRIPTION("DesignWare USB3 OF Simple Glue Layer");
422 MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");