17
17
#include <linux/of_platform.h>
18
18
#include <linux/regulator/consumer.h>
19
19
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
+
20
28
struct dwc3_exynos {
21
29
struct device * dev ;
22
30
23
- struct clk * clk ;
24
- struct clk * susp_clk ;
25
- 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 ;
26
35
27
36
struct regulator * vdd33 ;
28
37
struct regulator * vdd10 ;
@@ -42,47 +51,42 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
42
51
struct dwc3_exynos * exynos ;
43
52
struct device * dev = & pdev -> dev ;
44
53
struct device_node * node = dev -> of_node ;
45
-
46
- int ret ;
54
+ const struct dwc3_exynos_driverdata * driver_data ;
55
+ int i , ret ;
47
56
48
57
exynos = devm_kzalloc (dev , sizeof (* exynos ), GFP_KERNEL );
49
58
if (!exynos )
50
59
return - ENOMEM ;
51
60
52
- platform_set_drvdata (pdev , exynos );
61
+ driver_data = of_device_get_match_data (dev );
62
+ exynos -> dev = dev ;
63
+ exynos -> num_clks = driver_data -> num_clks ;
64
+ exynos -> clk_names = (const char * * )driver_data -> clk_names ;
65
+ exynos -> suspend_clk_idx = driver_data -> suspend_clk_idx ;
53
66
54
- exynos -> dev = dev ;
67
+ platform_set_drvdata ( pdev , exynos ) ;
55
68
56
- exynos -> clk = devm_clk_get (dev , "usbdrd30" );
57
- if (IS_ERR (exynos -> clk )) {
58
- dev_err (dev , "couldn't get clock\n" );
59
- return - EINVAL ;
69
+ for (i = 0 ; i < exynos -> num_clks ; i ++ ) {
70
+ exynos -> clks [i ] = devm_clk_get (dev , exynos -> clk_names [i ]);
71
+ if (IS_ERR (exynos -> clks [i ])) {
72
+ dev_err (dev , "failed to get clock: %s\n" ,
73
+ exynos -> clk_names [i ]);
74
+ return PTR_ERR (exynos -> clks [i ]);
75
+ }
60
76
}
61
- ret = clk_prepare_enable (exynos -> clk );
62
- if (ret )
63
- return ret ;
64
77
65
- exynos -> susp_clk = devm_clk_get (dev , "usbdrd30_susp_clk" );
66
- if (IS_ERR (exynos -> susp_clk ))
67
- exynos -> susp_clk = NULL ;
68
- ret = clk_prepare_enable (exynos -> susp_clk );
69
- if (ret )
70
- goto susp_clk_err ;
71
-
72
- if (of_device_is_compatible (node , "samsung,exynos7-dwusb3" )) {
73
- exynos -> axius_clk = devm_clk_get (dev , "usbdrd30_axius_clk" );
74
- if (IS_ERR (exynos -> axius_clk )) {
75
- dev_err (dev , "no AXI UpScaler clk specified\n" );
76
- ret = - ENODEV ;
77
- goto axius_clk_err ;
78
+ for (i = 0 ; i < exynos -> num_clks ; i ++ ) {
79
+ ret = clk_prepare_enable (exynos -> clks [i ]);
80
+ if (ret ) {
81
+ while (-- i > 0 )
82
+ clk_disable_unprepare (exynos -> clks [i ]);
83
+ return ret ;
78
84
}
79
- ret = clk_prepare_enable (exynos -> axius_clk );
80
- if (ret )
81
- goto axius_clk_err ;
82
- } else {
83
- exynos -> axius_clk = NULL ;
84
85
}
85
86
87
+ if (exynos -> suspend_clk_idx >= 0 )
88
+ clk_prepare_enable (exynos -> clks [exynos -> suspend_clk_idx ]);
89
+
86
90
exynos -> vdd33 = devm_regulator_get (dev , "vdd33" );
87
91
if (IS_ERR (exynos -> vdd33 )) {
88
92
ret = PTR_ERR (exynos -> vdd33 );
@@ -124,44 +128,66 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
124
128
vdd10_err :
125
129
regulator_disable (exynos -> vdd33 );
126
130
vdd33_err :
127
- clk_disable_unprepare (exynos -> axius_clk );
128
- axius_clk_err :
129
- clk_disable_unprepare (exynos -> susp_clk );
130
- susp_clk_err :
131
- clk_disable_unprepare (exynos -> clk );
131
+ for (i = exynos -> num_clks - 1 ; i >= 0 ; i -- )
132
+ clk_disable_unprepare (exynos -> clks [i ]);
133
+
134
+ if (exynos -> suspend_clk_idx >= 0 )
135
+ clk_disable_unprepare (exynos -> clks [exynos -> suspend_clk_idx ]);
136
+
132
137
return ret ;
133
138
}
134
139
135
140
static int dwc3_exynos_remove (struct platform_device * pdev )
136
141
{
137
142
struct dwc3_exynos * exynos = platform_get_drvdata (pdev );
143
+ int i ;
138
144
139
145
device_for_each_child (& pdev -> dev , NULL , dwc3_exynos_remove_child );
140
146
141
- clk_disable_unprepare (exynos -> axius_clk );
142
- clk_disable_unprepare (exynos -> susp_clk );
143
- clk_disable_unprepare (exynos -> clk );
147
+ for (i = exynos -> num_clks - 1 ; i >= 0 ; i -- )
148
+ clk_disable_unprepare (exynos -> clks [i ]);
149
+
150
+ if (exynos -> suspend_clk_idx >= 0 )
151
+ clk_disable_unprepare (exynos -> clks [exynos -> suspend_clk_idx ]);
144
152
145
153
regulator_disable (exynos -> vdd33 );
146
154
regulator_disable (exynos -> vdd10 );
147
155
148
156
return 0 ;
149
157
}
150
158
159
+ static const struct dwc3_exynos_driverdata exynos5250_drvdata = {
160
+ .clk_names = { "usbdrd30" },
161
+ .num_clks = 1 ,
162
+ .suspend_clk_idx = -1 ,
163
+ };
164
+
165
+ static const struct dwc3_exynos_driverdata exynos7_drvdata = {
166
+ .clk_names = { "usbdrd30" , "usbdrd30_susp_clk" , "usbdrd30_axius_clk" },
167
+ .num_clks = 3 ,
168
+ .suspend_clk_idx = 1 ,
169
+ };
170
+
151
171
static const struct of_device_id exynos_dwc3_match [] = {
152
- { .compatible = "samsung,exynos5250-dwusb3" },
153
- { .compatible = "samsung,exynos7-dwusb3" },
154
- {},
172
+ {
173
+ .compatible = "samsung,exynos5250-dwusb3" ,
174
+ .data = & exynos5250_drvdata ,
175
+ }, {
176
+ .compatible = "samsung,exynos7-dwusb3" ,
177
+ .data = & exynos7_drvdata ,
178
+ }, {
179
+ }
155
180
};
156
181
MODULE_DEVICE_TABLE (of , exynos_dwc3_match );
157
182
158
183
#ifdef CONFIG_PM_SLEEP
159
184
static int dwc3_exynos_suspend (struct device * dev )
160
185
{
161
186
struct dwc3_exynos * exynos = dev_get_drvdata (dev );
187
+ int i ;
162
188
163
- clk_disable ( exynos -> axius_clk );
164
- clk_disable (exynos -> clk );
189
+ for ( i = exynos -> num_clks - 1 ; i >= 0 ; i -- )
190
+ clk_disable_unprepare (exynos -> clks [ i ] );
165
191
166
192
regulator_disable (exynos -> vdd33 );
167
193
regulator_disable (exynos -> vdd10 );
@@ -172,7 +198,7 @@ static int dwc3_exynos_suspend(struct device *dev)
172
198
static int dwc3_exynos_resume (struct device * dev )
173
199
{
174
200
struct dwc3_exynos * exynos = dev_get_drvdata (dev );
175
- int ret ;
201
+ int i , ret ;
176
202
177
203
ret = regulator_enable (exynos -> vdd33 );
178
204
if (ret ) {
@@ -185,8 +211,14 @@ static int dwc3_exynos_resume(struct device *dev)
185
211
return ret ;
186
212
}
187
213
188
- clk_enable (exynos -> clk );
189
- clk_enable (exynos -> axius_clk );
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
+ }
190
222
191
223
return 0 ;
192
224
}
0 commit comments