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>
33 struct dwc3_of_simple
{
39 static int dwc3_of_simple_clk_init(struct dwc3_of_simple
*simple
, int count
)
41 struct device
*dev
= simple
->dev
;
42 struct device_node
*np
= dev
->of_node
;
45 simple
->num_clocks
= count
;
50 simple
->clks
= devm_kcalloc(dev
, simple
->num_clocks
,
51 sizeof(struct clk
*), GFP_KERNEL
);
55 for (i
= 0; i
< simple
->num_clocks
; i
++) {
59 clk
= of_clk_get(np
, i
);
62 clk_put(simple
->clks
[i
]);
66 ret
= clk_prepare_enable(clk
);
69 clk_disable_unprepare(simple
->clks
[i
]);
70 clk_put(simple
->clks
[i
]);
77 simple
->clks
[i
] = clk
;
83 static int dwc3_of_simple_probe(struct platform_device
*pdev
)
85 struct dwc3_of_simple
*simple
;
86 struct device
*dev
= &pdev
->dev
;
87 struct device_node
*np
= dev
->of_node
;
92 simple
= devm_kzalloc(dev
, sizeof(*simple
), GFP_KERNEL
);
96 platform_set_drvdata(pdev
, simple
);
99 ret
= dwc3_of_simple_clk_init(simple
, of_clk_get_parent_count(np
));
103 ret
= of_platform_populate(np
, NULL
, NULL
, dev
);
105 for (i
= 0; i
< simple
->num_clocks
; i
++) {
106 clk_disable_unprepare(simple
->clks
[i
]);
107 clk_put(simple
->clks
[i
]);
113 pm_runtime_set_active(dev
);
114 pm_runtime_enable(dev
);
115 pm_runtime_get_sync(dev
);
120 static int dwc3_of_simple_remove(struct platform_device
*pdev
)
122 struct dwc3_of_simple
*simple
= platform_get_drvdata(pdev
);
123 struct device
*dev
= &pdev
->dev
;
126 for (i
= 0; i
< simple
->num_clocks
; i
++) {
127 clk_disable_unprepare(simple
->clks
[i
]);
128 clk_put(simple
->clks
[i
]);
131 of_platform_depopulate(dev
);
133 pm_runtime_put_sync(dev
);
134 pm_runtime_disable(dev
);
140 static int dwc3_of_simple_runtime_suspend(struct device
*dev
)
142 struct dwc3_of_simple
*simple
= dev_get_drvdata(dev
);
145 for (i
= 0; i
< simple
->num_clocks
; i
++)
146 clk_disable(simple
->clks
[i
]);
151 static int dwc3_of_simple_runtime_resume(struct device
*dev
)
153 struct dwc3_of_simple
*simple
= dev_get_drvdata(dev
);
157 for (i
= 0; i
< simple
->num_clocks
; i
++) {
158 ret
= clk_enable(simple
->clks
[i
]);
161 clk_disable(simple
->clks
[i
]);
170 static const struct dev_pm_ops dwc3_of_simple_dev_pm_ops
= {
171 SET_RUNTIME_PM_OPS(dwc3_of_simple_runtime_suspend
,
172 dwc3_of_simple_runtime_resume
, NULL
)
175 static const struct of_device_id of_dwc3_simple_match
[] = {
176 { .compatible
= "qcom,dwc3" },
177 { .compatible
= "rockchip,rk3399-dwc3" },
178 { .compatible
= "xlnx,zynqmp-dwc3" },
179 { .compatible
= "cavium,octeon-7130-usb-uctl" },
182 MODULE_DEVICE_TABLE(of
, of_dwc3_simple_match
);
184 static struct platform_driver dwc3_of_simple_driver
= {
185 .probe
= dwc3_of_simple_probe
,
186 .remove
= dwc3_of_simple_remove
,
188 .name
= "dwc3-of-simple",
189 .of_match_table
= of_dwc3_simple_match
,
193 module_platform_driver(dwc3_of_simple_driver
);
194 MODULE_LICENSE("GPL v2");
195 MODULE_DESCRIPTION("DesignWare USB3 OF Simple Glue Layer");
196 MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");