1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/clk.h>
3 #include <linux/device.h>
4 #include <linux/export.h>
5 #include <linux/gfp.h>
6
7 struct devm_clk_state {
8 struct clk *clk;
9 void (*exit)(struct clk *clk);
10 };
11
devm_clk_release(struct device * dev,void * res)12 static void devm_clk_release(struct device *dev, void *res)
13 {
14 struct devm_clk_state *state = res;
15
16 if (state->exit)
17 state->exit(state->clk);
18
19 clk_put(state->clk);
20 }
21
__devm_clk_get(struct device * dev,const char * id,struct clk * (* get)(struct device * dev,const char * id),int (* init)(struct clk * clk),void (* exit)(struct clk * clk))22 static struct clk *__devm_clk_get(struct device *dev, const char *id,
23 struct clk *(*get)(struct device *dev, const char *id),
24 int (*init)(struct clk *clk),
25 void (*exit)(struct clk *clk))
26 {
27 struct devm_clk_state *state;
28 struct clk *clk;
29 int ret;
30
31 state = devres_alloc(devm_clk_release, sizeof(*state), GFP_KERNEL);
32 if (!state)
33 return ERR_PTR(-ENOMEM);
34
35 clk = get(dev, id);
36 if (IS_ERR(clk)) {
37 ret = PTR_ERR(clk);
38 goto err_clk_get;
39 }
40
41 if (init) {
42 ret = init(clk);
43 if (ret)
44 goto err_clk_init;
45 }
46
47 state->clk = clk;
48 state->exit = exit;
49
50 devres_add(dev, state);
51
52 return clk;
53
54 err_clk_init:
55
56 clk_put(clk);
57 err_clk_get:
58
59 devres_free(state);
60 return ERR_PTR(ret);
61 }
62
devm_clk_get(struct device * dev,const char * id)63 struct clk *devm_clk_get(struct device *dev, const char *id)
64 {
65 return __devm_clk_get(dev, id, clk_get, NULL, NULL);
66 }
67 EXPORT_SYMBOL(devm_clk_get);
68
devm_clk_get_prepared(struct device * dev,const char * id)69 struct clk *devm_clk_get_prepared(struct device *dev, const char *id)
70 {
71 return __devm_clk_get(dev, id, clk_get, clk_prepare, clk_unprepare);
72 }
73 EXPORT_SYMBOL_GPL(devm_clk_get_prepared);
74
devm_clk_get_enabled(struct device * dev,const char * id)75 struct clk *devm_clk_get_enabled(struct device *dev, const char *id)
76 {
77 return __devm_clk_get(dev, id, clk_get,
78 clk_prepare_enable, clk_disable_unprepare);
79 }
80 EXPORT_SYMBOL_GPL(devm_clk_get_enabled);
81
devm_clk_get_optional(struct device * dev,const char * id)82 struct clk *devm_clk_get_optional(struct device *dev, const char *id)
83 {
84 return __devm_clk_get(dev, id, clk_get_optional, NULL, NULL);
85 }
86 EXPORT_SYMBOL(devm_clk_get_optional);
87
devm_clk_get_optional_prepared(struct device * dev,const char * id)88 struct clk *devm_clk_get_optional_prepared(struct device *dev, const char *id)
89 {
90 return __devm_clk_get(dev, id, clk_get_optional,
91 clk_prepare, clk_unprepare);
92 }
93 EXPORT_SYMBOL_GPL(devm_clk_get_optional_prepared);
94
devm_clk_get_optional_enabled(struct device * dev,const char * id)95 struct clk *devm_clk_get_optional_enabled(struct device *dev, const char *id)
96 {
97 return __devm_clk_get(dev, id, clk_get_optional,
98 clk_prepare_enable, clk_disable_unprepare);
99 }
100 EXPORT_SYMBOL_GPL(devm_clk_get_optional_enabled);
101
devm_clk_disable_unprepare(void * data)102 static void devm_clk_disable_unprepare(void *data)
103 {
104 clk_disable_unprepare(data);
105 }
106
devm_clk_get_optional_enabled_with_rate(struct device * dev,const char * id,unsigned long rate)107 struct clk *devm_clk_get_optional_enabled_with_rate(struct device *dev,
108 const char *id,
109 unsigned long rate)
110 {
111 struct clk *clk;
112 int ret;
113
114 clk = devm_clk_get_optional(dev, id);
115 if (IS_ERR(clk))
116 return ERR_CAST(clk);
117
118 ret = clk_set_rate(clk, rate);
119 if (ret)
120 goto out_put_clk;
121
122 ret = clk_prepare_enable(clk);
123 if (ret)
124 goto out_put_clk;
125
126 ret = devm_add_action_or_reset(dev, devm_clk_disable_unprepare, clk);
127 if (ret)
128 goto out_put_clk;
129
130 return clk;
131
132 out_put_clk:
133 devm_clk_put(dev, clk);
134 return ERR_PTR(ret);
135 }
136 EXPORT_SYMBOL_GPL(devm_clk_get_optional_enabled_with_rate);
137
138 struct clk_bulk_devres {
139 struct clk_bulk_data *clks;
140 int num_clks;
141 };
142
devm_clk_bulk_release(struct device * dev,void * res)143 static void devm_clk_bulk_release(struct device *dev, void *res)
144 {
145 struct clk_bulk_devres *devres = res;
146
147 clk_bulk_put(devres->num_clks, devres->clks);
148 }
149
__devm_clk_bulk_get(struct device * dev,int num_clks,struct clk_bulk_data * clks,bool optional)150 static int __devm_clk_bulk_get(struct device *dev, int num_clks,
151 struct clk_bulk_data *clks, bool optional)
152 {
153 struct clk_bulk_devres *devres;
154 int ret;
155
156 devres = devres_alloc(devm_clk_bulk_release,
157 sizeof(*devres), GFP_KERNEL);
158 if (!devres)
159 return -ENOMEM;
160
161 if (optional)
162 ret = clk_bulk_get_optional(dev, num_clks, clks);
163 else
164 ret = clk_bulk_get(dev, num_clks, clks);
165 if (!ret) {
166 devres->clks = clks;
167 devres->num_clks = num_clks;
168 devres_add(dev, devres);
169 } else {
170 devres_free(devres);
171 }
172
173 return ret;
174 }
175
devm_clk_bulk_get(struct device * dev,int num_clks,struct clk_bulk_data * clks)176 int __must_check devm_clk_bulk_get(struct device *dev, int num_clks,
177 struct clk_bulk_data *clks)
178 {
179 return __devm_clk_bulk_get(dev, num_clks, clks, false);
180 }
181 EXPORT_SYMBOL_GPL(devm_clk_bulk_get);
182
devm_clk_bulk_get_optional(struct device * dev,int num_clks,struct clk_bulk_data * clks)183 int __must_check devm_clk_bulk_get_optional(struct device *dev, int num_clks,
184 struct clk_bulk_data *clks)
185 {
186 return __devm_clk_bulk_get(dev, num_clks, clks, true);
187 }
188 EXPORT_SYMBOL_GPL(devm_clk_bulk_get_optional);
189
devm_clk_bulk_release_enable(struct device * dev,void * res)190 static void devm_clk_bulk_release_enable(struct device *dev, void *res)
191 {
192 struct clk_bulk_devres *devres = res;
193
194 clk_bulk_disable_unprepare(devres->num_clks, devres->clks);
195 clk_bulk_put(devres->num_clks, devres->clks);
196 }
197
__devm_clk_bulk_get_enable(struct device * dev,int num_clks,struct clk_bulk_data * clks,bool optional)198 static int __devm_clk_bulk_get_enable(struct device *dev, int num_clks,
199 struct clk_bulk_data *clks, bool optional)
200 {
201 struct clk_bulk_devres *devres;
202 int ret;
203
204 devres = devres_alloc(devm_clk_bulk_release_enable,
205 sizeof(*devres), GFP_KERNEL);
206 if (!devres)
207 return -ENOMEM;
208
209 if (optional)
210 ret = clk_bulk_get_optional(dev, num_clks, clks);
211 else
212 ret = clk_bulk_get(dev, num_clks, clks);
213 if (ret)
214 goto err_clk_get;
215
216 ret = clk_bulk_prepare_enable(num_clks, clks);
217 if (ret)
218 goto err_clk_prepare;
219
220 devres->clks = clks;
221 devres->num_clks = num_clks;
222 devres_add(dev, devres);
223
224 return 0;
225
226 err_clk_prepare:
227 clk_bulk_put(num_clks, clks);
228 err_clk_get:
229 devres_free(devres);
230 return ret;
231 }
232
devm_clk_bulk_get_enable(struct device * dev,int num_clks,struct clk_bulk_data * clks)233 int __must_check devm_clk_bulk_get_enable(struct device *dev, int num_clks,
234 struct clk_bulk_data *clks)
235 {
236 return __devm_clk_bulk_get_enable(dev, num_clks, clks, false);
237 }
238 EXPORT_SYMBOL_GPL(devm_clk_bulk_get_enable);
239
devm_clk_bulk_get_optional_enable(struct device * dev,int num_clks,struct clk_bulk_data * clks)240 int __must_check devm_clk_bulk_get_optional_enable(struct device *dev, int num_clks,
241 struct clk_bulk_data *clks)
242 {
243 return __devm_clk_bulk_get_enable(dev, num_clks, clks, true);
244 }
245 EXPORT_SYMBOL_GPL(devm_clk_bulk_get_optional_enable);
246
devm_clk_bulk_release_all(struct device * dev,void * res)247 static void devm_clk_bulk_release_all(struct device *dev, void *res)
248 {
249 struct clk_bulk_devres *devres = res;
250
251 clk_bulk_put_all(devres->num_clks, devres->clks);
252 }
253
devm_clk_bulk_get_all(struct device * dev,struct clk_bulk_data ** clks)254 int __must_check devm_clk_bulk_get_all(struct device *dev,
255 struct clk_bulk_data **clks)
256 {
257 struct clk_bulk_devres *devres;
258 int ret;
259
260 devres = devres_alloc(devm_clk_bulk_release_all,
261 sizeof(*devres), GFP_KERNEL);
262 if (!devres)
263 return -ENOMEM;
264
265 ret = clk_bulk_get_all(dev, &devres->clks);
266 if (ret > 0) {
267 *clks = devres->clks;
268 devres->num_clks = ret;
269 devres_add(dev, devres);
270 } else {
271 devres_free(devres);
272 }
273
274 return ret;
275 }
276 EXPORT_SYMBOL_GPL(devm_clk_bulk_get_all);
277
devm_clk_bulk_release_all_enable(struct device * dev,void * res)278 static void devm_clk_bulk_release_all_enable(struct device *dev, void *res)
279 {
280 struct clk_bulk_devres *devres = res;
281
282 clk_bulk_disable_unprepare(devres->num_clks, devres->clks);
283 clk_bulk_put_all(devres->num_clks, devres->clks);
284 }
285
devm_clk_bulk_get_all_enabled(struct device * dev,struct clk_bulk_data ** clks)286 int __must_check devm_clk_bulk_get_all_enabled(struct device *dev,
287 struct clk_bulk_data **clks)
288 {
289 struct clk_bulk_devres *devres;
290 int ret;
291
292 devres = devres_alloc(devm_clk_bulk_release_all_enable,
293 sizeof(*devres), GFP_KERNEL);
294 if (!devres)
295 return -ENOMEM;
296
297 ret = clk_bulk_get_all(dev, &devres->clks);
298 if (ret > 0) {
299 *clks = devres->clks;
300 devres->num_clks = ret;
301 } else {
302 devres_free(devres);
303 return ret;
304 }
305
306 ret = clk_bulk_prepare_enable(devres->num_clks, *clks);
307 if (!ret) {
308 devres_add(dev, devres);
309 } else {
310 clk_bulk_put_all(devres->num_clks, devres->clks);
311 devres_free(devres);
312 return ret;
313 }
314
315 return devres->num_clks;
316 }
317 EXPORT_SYMBOL_GPL(devm_clk_bulk_get_all_enabled);
318
devm_clk_match(struct device * dev,void * res,void * data)319 static int devm_clk_match(struct device *dev, void *res, void *data)
320 {
321 struct clk **c = res;
322 if (!c || !*c) {
323 WARN_ON(!c || !*c);
324 return 0;
325 }
326 return *c == data;
327 }
328
devm_clk_put(struct device * dev,struct clk * clk)329 void devm_clk_put(struct device *dev, struct clk *clk)
330 {
331 int ret;
332
333 ret = devres_release(dev, devm_clk_release, devm_clk_match, clk);
334
335 WARN_ON(ret);
336 }
337 EXPORT_SYMBOL(devm_clk_put);
338
devm_get_clk_from_child(struct device * dev,struct device_node * np,const char * con_id)339 struct clk *devm_get_clk_from_child(struct device *dev,
340 struct device_node *np, const char *con_id)
341 {
342 struct devm_clk_state *state;
343 struct clk *clk;
344
345 state = devres_alloc(devm_clk_release, sizeof(*state), GFP_KERNEL);
346 if (!state)
347 return ERR_PTR(-ENOMEM);
348
349 clk = of_clk_get_by_name(np, con_id);
350 if (!IS_ERR(clk)) {
351 state->clk = clk;
352 devres_add(dev, state);
353 } else {
354 devres_free(state);
355 }
356
357 return clk;
358 }
359 EXPORT_SYMBOL(devm_get_clk_from_child);
360