1
2
3
4
5
6
7
8
9
10
11
12
13#include <linux/kernel.h>
14#include <linux/err.h>
15#include <linux/regmap.h>
16#include <linux/regulator/consumer.h>
17#include <linux/regulator/driver.h>
18#include <linux/module.h>
19
20#include "internal.h"
21
22enum {
23 NORMAL_GET,
24 EXCLUSIVE_GET,
25 OPTIONAL_GET,
26};
27
28static void devm_regulator_release(struct device *dev, void *res)
29{
30 regulator_put(*(struct regulator **)res);
31}
32
33static struct regulator *_devm_regulator_get(struct device *dev, const char *id,
34 int get_type)
35{
36 struct regulator **ptr, *regulator;
37
38 ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
39 if (!ptr)
40 return ERR_PTR(-ENOMEM);
41
42 switch (get_type) {
43 case NORMAL_GET:
44 regulator = regulator_get(dev, id);
45 break;
46 case EXCLUSIVE_GET:
47 regulator = regulator_get_exclusive(dev, id);
48 break;
49 case OPTIONAL_GET:
50 regulator = regulator_get_optional(dev, id);
51 break;
52 default:
53 regulator = ERR_PTR(-EINVAL);
54 }
55
56 if (!IS_ERR(regulator)) {
57 *ptr = regulator;
58 devres_add(dev, ptr);
59 } else {
60 devres_free(ptr);
61 }
62
63 return regulator;
64}
65
66
67
68
69
70
71
72
73
74
75struct regulator *devm_regulator_get(struct device *dev, const char *id)
76{
77 return _devm_regulator_get(dev, id, NORMAL_GET);
78}
79EXPORT_SYMBOL_GPL(devm_regulator_get);
80
81
82
83
84
85
86
87
88
89
90struct regulator *devm_regulator_get_exclusive(struct device *dev,
91 const char *id)
92{
93 return _devm_regulator_get(dev, id, EXCLUSIVE_GET);
94}
95EXPORT_SYMBOL_GPL(devm_regulator_get_exclusive);
96
97
98
99
100
101
102
103
104
105
106struct regulator *devm_regulator_get_optional(struct device *dev,
107 const char *id)
108{
109 return _devm_regulator_get(dev, id, OPTIONAL_GET);
110}
111EXPORT_SYMBOL_GPL(devm_regulator_get_optional);
112
113static int devm_regulator_match(struct device *dev, void *res, void *data)
114{
115 struct regulator **r = res;
116 if (!r || !*r) {
117 WARN_ON(!r || !*r);
118 return 0;
119 }
120 return *r == data;
121}
122
123
124
125
126
127
128
129
130
131void devm_regulator_put(struct regulator *regulator)
132{
133 int rc;
134
135 rc = devres_release(regulator->dev, devm_regulator_release,
136 devm_regulator_match, regulator);
137 if (rc != 0)
138 WARN_ON(rc);
139}
140EXPORT_SYMBOL_GPL(devm_regulator_put);
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157int devm_regulator_bulk_get(struct device *dev, int num_consumers,
158 struct regulator_bulk_data *consumers)
159{
160 int i;
161 int ret;
162
163 for (i = 0; i < num_consumers; i++)
164 consumers[i].consumer = NULL;
165
166 for (i = 0; i < num_consumers; i++) {
167 consumers[i].consumer = _devm_regulator_get(dev,
168 consumers[i].supply,
169 consumers[i].optional ?
170 OPTIONAL_GET :
171 NORMAL_GET);
172 if (IS_ERR(consumers[i].consumer)) {
173 ret = PTR_ERR(consumers[i].consumer);
174 dev_err(dev, "Failed to get supply '%s': %d\n",
175 consumers[i].supply, ret);
176 consumers[i].consumer = NULL;
177 goto err;
178 }
179 }
180
181 return 0;
182
183err:
184 for (i = 0; i < num_consumers && consumers[i].consumer; i++)
185 devm_regulator_put(consumers[i].consumer);
186
187 return ret;
188}
189EXPORT_SYMBOL_GPL(devm_regulator_bulk_get);
190
191static void devm_rdev_release(struct device *dev, void *res)
192{
193 regulator_unregister(*(struct regulator_dev **)res);
194}
195
196
197
198
199
200
201
202
203
204
205
206struct regulator_dev *devm_regulator_register(struct device *dev,
207 const struct regulator_desc *regulator_desc,
208 const struct regulator_config *config)
209{
210 struct regulator_dev **ptr, *rdev;
211
212 ptr = devres_alloc(devm_rdev_release, sizeof(*ptr),
213 GFP_KERNEL);
214 if (!ptr)
215 return ERR_PTR(-ENOMEM);
216
217 rdev = regulator_register(regulator_desc, config);
218 if (!IS_ERR(rdev)) {
219 *ptr = rdev;
220 devres_add(dev, ptr);
221 } else {
222 devres_free(ptr);
223 }
224
225 return rdev;
226}
227EXPORT_SYMBOL_GPL(devm_regulator_register);
228
229static int devm_rdev_match(struct device *dev, void *res, void *data)
230{
231 struct regulator_dev **r = res;
232 if (!r || !*r) {
233 WARN_ON(!r || !*r);
234 return 0;
235 }
236 return *r == data;
237}
238
239
240
241
242
243
244
245
246
247void devm_regulator_unregister(struct device *dev, struct regulator_dev *rdev)
248{
249 int rc;
250
251 rc = devres_release(dev, devm_rdev_release, devm_rdev_match, rdev);
252 if (rc != 0)
253 WARN_ON(rc);
254}
255EXPORT_SYMBOL_GPL(devm_regulator_unregister);
256
257struct regulator_supply_alias_match {
258 struct device *dev;
259 const char *id;
260};
261
262static int devm_regulator_match_supply_alias(struct device *dev, void *res,
263 void *data)
264{
265 struct regulator_supply_alias_match *match = res;
266 struct regulator_supply_alias_match *target = data;
267
268 return match->dev == target->dev && strcmp(match->id, target->id) == 0;
269}
270
271static void devm_regulator_destroy_supply_alias(struct device *dev, void *res)
272{
273 struct regulator_supply_alias_match *match = res;
274
275 regulator_unregister_supply_alias(match->dev, match->id);
276}
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291int devm_regulator_register_supply_alias(struct device *dev, const char *id,
292 struct device *alias_dev,
293 const char *alias_id)
294{
295 struct regulator_supply_alias_match *match;
296 int ret;
297
298 match = devres_alloc(devm_regulator_destroy_supply_alias,
299 sizeof(struct regulator_supply_alias_match),
300 GFP_KERNEL);
301 if (!match)
302 return -ENOMEM;
303
304 match->dev = dev;
305 match->id = id;
306
307 ret = regulator_register_supply_alias(dev, id, alias_dev, alias_id);
308 if (ret < 0) {
309 devres_free(match);
310 return ret;
311 }
312
313 devres_add(dev, match);
314
315 return 0;
316}
317EXPORT_SYMBOL_GPL(devm_regulator_register_supply_alias);
318
319
320
321
322
323
324
325
326
327
328
329
330
331void devm_regulator_unregister_supply_alias(struct device *dev, const char *id)
332{
333 struct regulator_supply_alias_match match;
334 int rc;
335
336 match.dev = dev;
337 match.id = id;
338
339 rc = devres_release(dev, devm_regulator_destroy_supply_alias,
340 devm_regulator_match_supply_alias, &match);
341 if (rc != 0)
342 WARN_ON(rc);
343}
344EXPORT_SYMBOL_GPL(devm_regulator_unregister_supply_alias);
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365int devm_regulator_bulk_register_supply_alias(struct device *dev,
366 const char *const *id,
367 struct device *alias_dev,
368 const char *const *alias_id,
369 int num_id)
370{
371 int i;
372 int ret;
373
374 for (i = 0; i < num_id; ++i) {
375 ret = devm_regulator_register_supply_alias(dev, id[i],
376 alias_dev,
377 alias_id[i]);
378 if (ret < 0)
379 goto err;
380 }
381
382 return 0;
383
384err:
385 dev_err(dev,
386 "Failed to create supply alias %s,%s -> %s,%s\n",
387 id[i], dev_name(dev), alias_id[i], dev_name(alias_dev));
388
389 while (--i >= 0)
390 devm_regulator_unregister_supply_alias(dev, id[i]);
391
392 return ret;
393}
394EXPORT_SYMBOL_GPL(devm_regulator_bulk_register_supply_alias);
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409void devm_regulator_bulk_unregister_supply_alias(struct device *dev,
410 const char *const *id,
411 int num_id)
412{
413 int i;
414
415 for (i = 0; i < num_id; ++i)
416 devm_regulator_unregister_supply_alias(dev, id[i]);
417}
418EXPORT_SYMBOL_GPL(devm_regulator_bulk_unregister_supply_alias);
419
420struct regulator_notifier_match {
421 struct regulator *regulator;
422 struct notifier_block *nb;
423};
424
425static int devm_regulator_match_notifier(struct device *dev, void *res,
426 void *data)
427{
428 struct regulator_notifier_match *match = res;
429 struct regulator_notifier_match *target = data;
430
431 return match->regulator == target->regulator && match->nb == target->nb;
432}
433
434static void devm_regulator_destroy_notifier(struct device *dev, void *res)
435{
436 struct regulator_notifier_match *match = res;
437
438 regulator_unregister_notifier(match->regulator, match->nb);
439}
440
441
442
443
444
445
446
447
448
449
450
451int devm_regulator_register_notifier(struct regulator *regulator,
452 struct notifier_block *nb)
453{
454 struct regulator_notifier_match *match;
455 int ret;
456
457 match = devres_alloc(devm_regulator_destroy_notifier,
458 sizeof(struct regulator_notifier_match),
459 GFP_KERNEL);
460 if (!match)
461 return -ENOMEM;
462
463 match->regulator = regulator;
464 match->nb = nb;
465
466 ret = regulator_register_notifier(regulator, nb);
467 if (ret < 0) {
468 devres_free(match);
469 return ret;
470 }
471
472 devres_add(regulator->dev, match);
473
474 return 0;
475}
476EXPORT_SYMBOL_GPL(devm_regulator_register_notifier);
477
478
479
480
481
482
483
484
485
486
487
488
489void devm_regulator_unregister_notifier(struct regulator *regulator,
490 struct notifier_block *nb)
491{
492 struct regulator_notifier_match match;
493 int rc;
494
495 match.regulator = regulator;
496 match.nb = nb;
497
498 rc = devres_release(regulator->dev, devm_regulator_destroy_notifier,
499 devm_regulator_match_notifier, &match);
500 if (rc != 0)
501 WARN_ON(rc);
502}
503EXPORT_SYMBOL_GPL(devm_regulator_unregister_notifier);
504