forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-04 1543e317f1da31b75942316931e8f491a8920811
kernel/drivers/usb/dwc3/dwc3-exynos.c
....@@ -1,6 +1,6 @@
11 // SPDX-License-Identifier: GPL-2.0
22 /**
3
- * dwc3-exynos.c - Samsung EXYNOS DWC3 Specific Glue layer
3
+ * dwc3-exynos.c - Samsung Exynos DWC3 Specific Glue layer
44 *
55 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
66 * http://www.samsung.com
....@@ -13,134 +13,70 @@
1313 #include <linux/slab.h>
1414 #include <linux/platform_device.h>
1515 #include <linux/clk.h>
16
-#include <linux/usb/otg.h>
17
-#include <linux/usb/usb_phy_generic.h>
1816 #include <linux/of.h>
1917 #include <linux/of_platform.h>
2018 #include <linux/regulator/consumer.h>
2119
20
+#define DWC3_EXYNOS_MAX_CLOCKS 4
21
+
22
+struct dwc3_exynos_driverdata {
23
+ const char *clk_names[DWC3_EXYNOS_MAX_CLOCKS];
24
+ int num_clks;
25
+ int suspend_clk_idx;
26
+};
27
+
2228 struct dwc3_exynos {
23
- struct platform_device *usb2_phy;
24
- struct platform_device *usb3_phy;
2529 struct device *dev;
2630
27
- struct clk *clk;
28
- struct clk *susp_clk;
29
- struct clk *axius_clk;
31
+ const char **clk_names;
32
+ struct clk *clks[DWC3_EXYNOS_MAX_CLOCKS];
33
+ int num_clks;
34
+ int suspend_clk_idx;
3035
3136 struct regulator *vdd33;
3237 struct regulator *vdd10;
3338 };
34
-
35
-static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
36
-{
37
- struct usb_phy_generic_platform_data pdata;
38
- struct platform_device *pdev;
39
- int ret;
40
-
41
- memset(&pdata, 0x00, sizeof(pdata));
42
-
43
- pdev = platform_device_alloc("usb_phy_generic", PLATFORM_DEVID_AUTO);
44
- if (!pdev)
45
- return -ENOMEM;
46
-
47
- exynos->usb2_phy = pdev;
48
- pdata.type = USB_PHY_TYPE_USB2;
49
- pdata.gpio_reset = -1;
50
-
51
- ret = platform_device_add_data(exynos->usb2_phy, &pdata, sizeof(pdata));
52
- if (ret)
53
- goto err1;
54
-
55
- pdev = platform_device_alloc("usb_phy_generic", PLATFORM_DEVID_AUTO);
56
- if (!pdev) {
57
- ret = -ENOMEM;
58
- goto err1;
59
- }
60
-
61
- exynos->usb3_phy = pdev;
62
- pdata.type = USB_PHY_TYPE_USB3;
63
-
64
- ret = platform_device_add_data(exynos->usb3_phy, &pdata, sizeof(pdata));
65
- if (ret)
66
- goto err2;
67
-
68
- ret = platform_device_add(exynos->usb2_phy);
69
- if (ret)
70
- goto err2;
71
-
72
- ret = platform_device_add(exynos->usb3_phy);
73
- if (ret)
74
- goto err3;
75
-
76
- return 0;
77
-
78
-err3:
79
- platform_device_del(exynos->usb2_phy);
80
-
81
-err2:
82
- platform_device_put(exynos->usb3_phy);
83
-
84
-err1:
85
- platform_device_put(exynos->usb2_phy);
86
-
87
- return ret;
88
-}
89
-
90
-static int dwc3_exynos_remove_child(struct device *dev, void *unused)
91
-{
92
- struct platform_device *pdev = to_platform_device(dev);
93
-
94
- platform_device_unregister(pdev);
95
-
96
- return 0;
97
-}
9839
9940 static int dwc3_exynos_probe(struct platform_device *pdev)
10041 {
10142 struct dwc3_exynos *exynos;
10243 struct device *dev = &pdev->dev;
10344 struct device_node *node = dev->of_node;
104
-
105
- int ret;
45
+ const struct dwc3_exynos_driverdata *driver_data;
46
+ int i, ret;
10647
10748 exynos = devm_kzalloc(dev, sizeof(*exynos), GFP_KERNEL);
10849 if (!exynos)
10950 return -ENOMEM;
11051
52
+ driver_data = of_device_get_match_data(dev);
53
+ exynos->dev = dev;
54
+ exynos->num_clks = driver_data->num_clks;
55
+ exynos->clk_names = (const char **)driver_data->clk_names;
56
+ exynos->suspend_clk_idx = driver_data->suspend_clk_idx;
57
+
11158 platform_set_drvdata(pdev, exynos);
11259
113
- exynos->dev = dev;
114
-
115
- exynos->clk = devm_clk_get(dev, "usbdrd30");
116
- if (IS_ERR(exynos->clk)) {
117
- dev_err(dev, "couldn't get clock\n");
118
- return -EINVAL;
119
- }
120
- ret = clk_prepare_enable(exynos->clk);
121
- if (ret)
122
- return ret;
123
-
124
- exynos->susp_clk = devm_clk_get(dev, "usbdrd30_susp_clk");
125
- if (IS_ERR(exynos->susp_clk))
126
- exynos->susp_clk = NULL;
127
- ret = clk_prepare_enable(exynos->susp_clk);
128
- if (ret)
129
- goto susp_clk_err;
130
-
131
- if (of_device_is_compatible(node, "samsung,exynos7-dwusb3")) {
132
- exynos->axius_clk = devm_clk_get(dev, "usbdrd30_axius_clk");
133
- if (IS_ERR(exynos->axius_clk)) {
134
- dev_err(dev, "no AXI UpScaler clk specified\n");
135
- ret = -ENODEV;
136
- goto axius_clk_err;
60
+ for (i = 0; i < exynos->num_clks; i++) {
61
+ exynos->clks[i] = devm_clk_get(dev, exynos->clk_names[i]);
62
+ if (IS_ERR(exynos->clks[i])) {
63
+ dev_err(dev, "failed to get clock: %s\n",
64
+ exynos->clk_names[i]);
65
+ return PTR_ERR(exynos->clks[i]);
13766 }
138
- ret = clk_prepare_enable(exynos->axius_clk);
139
- if (ret)
140
- goto axius_clk_err;
141
- } else {
142
- exynos->axius_clk = NULL;
14367 }
68
+
69
+ for (i = 0; i < exynos->num_clks; i++) {
70
+ ret = clk_prepare_enable(exynos->clks[i]);
71
+ if (ret) {
72
+ while (i-- > 0)
73
+ clk_disable_unprepare(exynos->clks[i]);
74
+ return ret;
75
+ }
76
+ }
77
+
78
+ if (exynos->suspend_clk_idx >= 0)
79
+ clk_prepare_enable(exynos->clks[exynos->suspend_clk_idx]);
14480
14581 exynos->vdd33 = devm_regulator_get(dev, "vdd33");
14682 if (IS_ERR(exynos->vdd33)) {
....@@ -164,12 +100,6 @@
164100 goto vdd10_err;
165101 }
166102
167
- ret = dwc3_exynos_register_phys(exynos);
168
- if (ret) {
169
- dev_err(dev, "couldn't register PHYs\n");
170
- goto phys_err;
171
- }
172
-
173103 if (node) {
174104 ret = of_platform_populate(node, NULL, NULL, dev);
175105 if (ret) {
....@@ -185,32 +115,31 @@
185115 return 0;
186116
187117 populate_err:
188
- platform_device_unregister(exynos->usb2_phy);
189
- platform_device_unregister(exynos->usb3_phy);
190
-phys_err:
191118 regulator_disable(exynos->vdd10);
192119 vdd10_err:
193120 regulator_disable(exynos->vdd33);
194121 vdd33_err:
195
- clk_disable_unprepare(exynos->axius_clk);
196
-axius_clk_err:
197
- clk_disable_unprepare(exynos->susp_clk);
198
-susp_clk_err:
199
- clk_disable_unprepare(exynos->clk);
122
+ for (i = exynos->num_clks - 1; i >= 0; i--)
123
+ clk_disable_unprepare(exynos->clks[i]);
124
+
125
+ if (exynos->suspend_clk_idx >= 0)
126
+ clk_disable_unprepare(exynos->clks[exynos->suspend_clk_idx]);
127
+
200128 return ret;
201129 }
202130
203131 static int dwc3_exynos_remove(struct platform_device *pdev)
204132 {
205133 struct dwc3_exynos *exynos = platform_get_drvdata(pdev);
134
+ int i;
206135
207
- device_for_each_child(&pdev->dev, NULL, dwc3_exynos_remove_child);
208
- platform_device_unregister(exynos->usb2_phy);
209
- platform_device_unregister(exynos->usb3_phy);
136
+ of_platform_depopulate(&pdev->dev);
210137
211
- clk_disable_unprepare(exynos->axius_clk);
212
- clk_disable_unprepare(exynos->susp_clk);
213
- clk_disable_unprepare(exynos->clk);
138
+ for (i = exynos->num_clks - 1; i >= 0; i--)
139
+ clk_disable_unprepare(exynos->clks[i]);
140
+
141
+ if (exynos->suspend_clk_idx >= 0)
142
+ clk_disable_unprepare(exynos->clks[exynos->suspend_clk_idx]);
214143
215144 regulator_disable(exynos->vdd33);
216145 regulator_disable(exynos->vdd10);
....@@ -218,10 +147,36 @@
218147 return 0;
219148 }
220149
150
+static const struct dwc3_exynos_driverdata exynos5250_drvdata = {
151
+ .clk_names = { "usbdrd30" },
152
+ .num_clks = 1,
153
+ .suspend_clk_idx = -1,
154
+};
155
+
156
+static const struct dwc3_exynos_driverdata exynos5433_drvdata = {
157
+ .clk_names = { "aclk", "susp_clk", "pipe_pclk", "phyclk" },
158
+ .num_clks = 4,
159
+ .suspend_clk_idx = 1,
160
+};
161
+
162
+static const struct dwc3_exynos_driverdata exynos7_drvdata = {
163
+ .clk_names = { "usbdrd30", "usbdrd30_susp_clk", "usbdrd30_axius_clk" },
164
+ .num_clks = 3,
165
+ .suspend_clk_idx = 1,
166
+};
167
+
221168 static const struct of_device_id exynos_dwc3_match[] = {
222
- { .compatible = "samsung,exynos5250-dwusb3" },
223
- { .compatible = "samsung,exynos7-dwusb3" },
224
- {},
169
+ {
170
+ .compatible = "samsung,exynos5250-dwusb3",
171
+ .data = &exynos5250_drvdata,
172
+ }, {
173
+ .compatible = "samsung,exynos5433-dwusb3",
174
+ .data = &exynos5433_drvdata,
175
+ }, {
176
+ .compatible = "samsung,exynos7-dwusb3",
177
+ .data = &exynos7_drvdata,
178
+ }, {
179
+ }
225180 };
226181 MODULE_DEVICE_TABLE(of, exynos_dwc3_match);
227182
....@@ -229,9 +184,10 @@
229184 static int dwc3_exynos_suspend(struct device *dev)
230185 {
231186 struct dwc3_exynos *exynos = dev_get_drvdata(dev);
187
+ int i;
232188
233
- clk_disable(exynos->axius_clk);
234
- clk_disable(exynos->clk);
189
+ for (i = exynos->num_clks - 1; i >= 0; i--)
190
+ clk_disable_unprepare(exynos->clks[i]);
235191
236192 regulator_disable(exynos->vdd33);
237193 regulator_disable(exynos->vdd10);
....@@ -242,7 +198,7 @@
242198 static int dwc3_exynos_resume(struct device *dev)
243199 {
244200 struct dwc3_exynos *exynos = dev_get_drvdata(dev);
245
- int ret;
201
+ int i, ret;
246202
247203 ret = regulator_enable(exynos->vdd33);
248204 if (ret) {
....@@ -255,13 +211,14 @@
255211 return ret;
256212 }
257213
258
- clk_enable(exynos->clk);
259
- clk_enable(exynos->axius_clk);
260
-
261
- /* runtime set active to reflect active state. */
262
- pm_runtime_disable(dev);
263
- pm_runtime_set_active(dev);
264
- pm_runtime_enable(dev);
214
+ for (i = 0; i < exynos->num_clks; i++) {
215
+ ret = clk_prepare_enable(exynos->clks[i]);
216
+ if (ret) {
217
+ while (i-- > 0)
218
+ clk_disable_unprepare(exynos->clks[i]);
219
+ return ret;
220
+ }
221
+ }
265222
266223 return 0;
267224 }
....@@ -289,4 +246,4 @@
289246
290247 MODULE_AUTHOR("Anton Tikhomirov <av.tikhomirov@samsung.com>");
291248 MODULE_LICENSE("GPL v2");
292
-MODULE_DESCRIPTION("DesignWare USB3 EXYNOS Glue Layer");
249
+MODULE_DESCRIPTION("DesignWare USB3 Exynos Glue Layer");