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 = of_node_get(dev->parent->of_node);
145 /* check for valid parent node */
147 if (!of_device_is_compatible(node, "xlnx,zynqmp-dwc3"))
148 node = of_get_next_parent(node);
154 struct platform_device *pdev_parent;
155 struct dwc3_of_simple *simple;
157 pdev_parent = of_find_device_by_node(node);
158 simple = platform_get_drvdata(pdev_parent);
160 /* Set wakeup capable as true or false */
161 simple->wakeup_capable = wakeup;
164 EXPORT_SYMBOL(dwc3_simple_wakeup_capable);
166 static int dwc3_of_simple_clk_init(struct dwc3_of_simple *simple, int count)
168 struct device *dev = simple->dev;
169 struct device_node *np = dev->of_node;
172 simple->num_clocks = count;
177 simple->clks = devm_kcalloc(dev, simple->num_clocks,
178 sizeof(struct clk *), GFP_KERNEL);
182 for (i = 0; i < simple->num_clocks; i++) {
186 clk = of_clk_get(np, i);
189 clk_put(simple->clks[i]);
193 ret = clk_prepare_enable(clk);
196 clk_disable_unprepare(simple->clks[i]);
197 clk_put(simple->clks[i]);
204 simple->clks[i] = clk;
210 static int dwc3_of_simple_probe(struct platform_device *pdev)
212 struct dwc3_of_simple *simple;
213 struct device *dev = &pdev->dev;
214 struct device_node *np = dev->of_node;
219 simple = devm_kzalloc(dev, sizeof(*simple), GFP_KERNEL);
223 platform_set_drvdata(pdev, simple);
226 if (of_device_is_compatible(pdev->dev.of_node,
227 "xlnx,zynqmp-dwc3")) {
230 struct resource *res;
233 res = platform_get_resource(pdev,
236 regs = devm_ioremap_resource(&pdev->dev, res);
238 return PTR_ERR(regs);
240 /* Store the usb control regs into simple for further usage */
243 /* read Silicon version using nvmem driver */
244 soc_rev = zynqmp_nvmem_get_silicon_version(&pdev->dev,
247 if (PTR_ERR(soc_rev) == -EPROBE_DEFER) {
248 /* Do a deferred probe */
249 return -EPROBE_DEFER;
251 } else if (!IS_ERR(soc_rev) &&
252 (*soc_rev < ZYNQMP_SILICON_V4)) {
253 /* Add snps,dis_u3_susphy_quirk
254 * for SOC revison less than v4
256 simple->dis_u3_susphy_quirk = true;
259 /* Clean soc_rev if got a valid pointer from nvmem driver
260 * else we may end up in kernel panic
262 if (!IS_ERR(soc_rev))
266 ret = dwc3_of_simple_clk_init(simple, of_clk_get_parent_count(np));
270 ret = of_platform_populate(np, NULL, NULL, dev);
272 for (i = 0; i < simple->num_clocks; i++) {
273 clk_disable_unprepare(simple->clks[i]);
274 clk_put(simple->clks[i]);
280 platform_set_drvdata(pdev, simple);
282 pm_runtime_set_active(dev);
283 pm_runtime_enable(dev);
284 pm_runtime_get_sync(dev);
289 static int dwc3_of_simple_remove(struct platform_device *pdev)
291 struct dwc3_of_simple *simple = platform_get_drvdata(pdev);
292 struct device *dev = &pdev->dev;
295 of_platform_depopulate(dev);
297 for (i = 0; i < simple->num_clocks; i++) {
298 clk_disable_unprepare(simple->clks[i]);
299 clk_put(simple->clks[i]);
302 pm_runtime_put_sync(dev);
303 pm_runtime_disable(dev);
310 static void dwc3_simple_vbus(struct dwc3 *dwc, bool vbus_off)
316 addr = ULPI_OTG_CTRL_CLEAR;
318 addr = ULPI_OTG_CTRL_SET;
320 val = (1 << OTG_CTRL_DRVVBUS_OFFSET);
322 reg = DWC3_GUSB2PHYACC_NEWREGREQ | DWC3_GUSB2PHYACC_ADDR(addr);
323 reg |= DWC3_GUSB2PHYACC_WRITE | val;
325 addr = DWC3_OF_ADDRESS(DWC3_GUSB2PHYACC(0));
326 writel(reg, dwc->regs + addr);
329 static int dwc3_of_simple_suspend(struct device *dev)
331 struct dwc3_of_simple *simple = dev_get_drvdata(dev);
334 if (!simple->wakeup_capable) {
335 /* Ask ULPI to turn OFF Vbus */
336 dwc3_simple_vbus(simple->dwc, true);
338 /* Disable the clocks */
339 for (i = 0; i < simple->num_clocks; i++)
340 clk_disable(simple->clks[i]);
346 static int dwc3_of_simple_resume(struct device *dev)
348 struct dwc3_of_simple *simple = dev_get_drvdata(dev);
352 if (simple->wakeup_capable)
355 for (i = 0; i < simple->num_clocks; i++) {
356 ret = clk_enable(simple->clks[i]);
359 clk_disable(simple->clks[i]);
363 /* Ask ULPI to turn ON Vbus */
364 dwc3_simple_vbus(simple->dwc, false);
370 static int dwc3_of_simple_runtime_suspend(struct device *dev)
372 struct dwc3_of_simple *simple = dev_get_drvdata(dev);
375 for (i = 0; i < simple->num_clocks; i++)
376 clk_disable(simple->clks[i]);
381 static int dwc3_of_simple_runtime_resume(struct device *dev)
383 struct dwc3_of_simple *simple = dev_get_drvdata(dev);
387 for (i = 0; i < simple->num_clocks; i++) {
388 ret = clk_enable(simple->clks[i]);
391 clk_disable(simple->clks[i]);
400 static const struct dev_pm_ops dwc3_of_simple_dev_pm_ops = {
401 SET_SYSTEM_SLEEP_PM_OPS(dwc3_of_simple_suspend,
402 dwc3_of_simple_resume)
403 SET_RUNTIME_PM_OPS(dwc3_of_simple_runtime_suspend,
404 dwc3_of_simple_runtime_resume, NULL)
407 static const struct of_device_id of_dwc3_simple_match[] = {
408 { .compatible = "qcom,dwc3" },
409 { .compatible = "rockchip,rk3399-dwc3" },
410 { .compatible = "xlnx,zynqmp-dwc3" },
411 { .compatible = "cavium,octeon-7130-usb-uctl" },
414 MODULE_DEVICE_TABLE(of, of_dwc3_simple_match);
416 static struct platform_driver dwc3_of_simple_driver = {
417 .probe = dwc3_of_simple_probe,
418 .remove = dwc3_of_simple_remove,
420 .name = "dwc3-of-simple",
421 .of_match_table = of_dwc3_simple_match,
422 .pm = &dwc3_of_simple_dev_pm_ops,
426 module_platform_driver(dwc3_of_simple_driver);
427 MODULE_LICENSE("GPL v2");
428 MODULE_DESCRIPTION("DesignWare USB3 OF Simple Glue Layer");
429 MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");