• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * devres.c  --  Voltage/Current Regulator framework devres implementation.
3  *
4  * Copyright 2013 Linaro Ltd
5  *
6  *  This program is free software; you can redistribute  it and/or modify it
7  *  under  the terms of  the GNU General  Public License as published by the
8  *  Free Software Foundation;  either version 2 of the  License, or (at your
9  *  option) any later version.
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 
22 enum {
23 	NORMAL_GET,
24 	EXCLUSIVE_GET,
25 	OPTIONAL_GET,
26 };
27 
devm_regulator_release(struct device * dev,void * res)28 static void devm_regulator_release(struct device *dev, void *res)
29 {
30 	regulator_put(*(struct regulator **)res);
31 }
32 
_devm_regulator_get(struct device * dev,const char * id,int get_type)33 static 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  * devm_regulator_get - Resource managed regulator_get()
68  * @dev: device for regulator "consumer"
69  * @id: Supply name or regulator ID.
70  *
71  * Managed regulator_get(). Regulators returned from this function are
72  * automatically regulator_put() on driver detach. See regulator_get() for more
73  * information.
74  */
devm_regulator_get(struct device * dev,const char * id)75 struct regulator *devm_regulator_get(struct device *dev, const char *id)
76 {
77 	return _devm_regulator_get(dev, id, NORMAL_GET);
78 }
79 EXPORT_SYMBOL_GPL(devm_regulator_get);
80 
81 /**
82  * devm_regulator_get_exclusive - Resource managed regulator_get_exclusive()
83  * @dev: device for regulator "consumer"
84  * @id: Supply name or regulator ID.
85  *
86  * Managed regulator_get_exclusive(). Regulators returned from this function
87  * are automatically regulator_put() on driver detach. See regulator_get() for
88  * more information.
89  */
devm_regulator_get_exclusive(struct device * dev,const char * id)90 struct regulator *devm_regulator_get_exclusive(struct device *dev,
91 					       const char *id)
92 {
93 	return _devm_regulator_get(dev, id, EXCLUSIVE_GET);
94 }
95 EXPORT_SYMBOL_GPL(devm_regulator_get_exclusive);
96 
97 /**
98  * devm_regulator_get_optional - Resource managed regulator_get_optional()
99  * @dev: device for regulator "consumer"
100  * @id: Supply name or regulator ID.
101  *
102  * Managed regulator_get_optional(). Regulators returned from this
103  * function are automatically regulator_put() on driver detach. See
104  * regulator_get_optional() for more information.
105  */
devm_regulator_get_optional(struct device * dev,const char * id)106 struct regulator *devm_regulator_get_optional(struct device *dev,
107 					      const char *id)
108 {
109 	return _devm_regulator_get(dev, id, OPTIONAL_GET);
110 }
111 EXPORT_SYMBOL_GPL(devm_regulator_get_optional);
112 
devm_regulator_match(struct device * dev,void * res,void * data)113 static 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  * devm_regulator_put - Resource managed regulator_put()
125  * @regulator: regulator to free
126  *
127  * Deallocate a regulator allocated with devm_regulator_get(). Normally
128  * this function will not need to be called and the resource management
129  * code will ensure that the resource is freed.
130  */
devm_regulator_put(struct regulator * regulator)131 void 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 }
140 EXPORT_SYMBOL_GPL(devm_regulator_put);
141 
142 /**
143  * devm_regulator_bulk_get - managed get multiple regulator consumers
144  *
145  * @dev:           Device to supply
146  * @num_consumers: Number of consumers to register
147  * @consumers:     Configuration of consumers; clients are stored here.
148  *
149  * @return 0 on success, an errno on failure.
150  *
151  * This helper function allows drivers to get several regulator
152  * consumers in one operation with management, the regulators will
153  * automatically be freed when the device is unbound.  If any of the
154  * regulators cannot be acquired then any regulators that were
155  * allocated will be freed before returning to the caller.
156  */
devm_regulator_bulk_get(struct device * dev,int num_consumers,struct regulator_bulk_data * consumers)157 int 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 		if (IS_ERR(consumers[i].consumer)) {
170 			ret = PTR_ERR(consumers[i].consumer);
171 			dev_err(dev, "Failed to get supply '%s': %d\n",
172 				consumers[i].supply, ret);
173 			consumers[i].consumer = NULL;
174 			goto err;
175 		}
176 	}
177 
178 	return 0;
179 
180 err:
181 	for (i = 0; i < num_consumers && consumers[i].consumer; i++)
182 		devm_regulator_put(consumers[i].consumer);
183 
184 	return ret;
185 }
186 EXPORT_SYMBOL_GPL(devm_regulator_bulk_get);
187 
devm_rdev_release(struct device * dev,void * res)188 static void devm_rdev_release(struct device *dev, void *res)
189 {
190 	regulator_unregister(*(struct regulator_dev **)res);
191 }
192 
193 /**
194  * devm_regulator_register - Resource managed regulator_register()
195  * @regulator_desc: regulator to register
196  * @config: runtime configuration for regulator
197  *
198  * Called by regulator drivers to register a regulator.  Returns a
199  * valid pointer to struct regulator_dev on success or an ERR_PTR() on
200  * error.  The regulator will automatically be released when the device
201  * is unbound.
202  */
devm_regulator_register(struct device * dev,const struct regulator_desc * regulator_desc,const struct regulator_config * config)203 struct regulator_dev *devm_regulator_register(struct device *dev,
204 				  const struct regulator_desc *regulator_desc,
205 				  const struct regulator_config *config)
206 {
207 	struct regulator_dev **ptr, *rdev;
208 
209 	ptr = devres_alloc(devm_rdev_release, sizeof(*ptr),
210 			   GFP_KERNEL);
211 	if (!ptr)
212 		return ERR_PTR(-ENOMEM);
213 
214 	rdev = regulator_register(regulator_desc, config);
215 	if (!IS_ERR(rdev)) {
216 		*ptr = rdev;
217 		devres_add(dev, ptr);
218 	} else {
219 		devres_free(ptr);
220 	}
221 
222 	return rdev;
223 }
224 EXPORT_SYMBOL_GPL(devm_regulator_register);
225 
devm_rdev_match(struct device * dev,void * res,void * data)226 static int devm_rdev_match(struct device *dev, void *res, void *data)
227 {
228 	struct regulator_dev **r = res;
229 	if (!r || !*r) {
230 		WARN_ON(!r || !*r);
231 		return 0;
232 	}
233 	return *r == data;
234 }
235 
236 /**
237  * devm_regulator_unregister - Resource managed regulator_unregister()
238  * @regulator: regulator to free
239  *
240  * Unregister a regulator registered with devm_regulator_register().
241  * Normally this function will not need to be called and the resource
242  * management code will ensure that the resource is freed.
243  */
devm_regulator_unregister(struct device * dev,struct regulator_dev * rdev)244 void devm_regulator_unregister(struct device *dev, struct regulator_dev *rdev)
245 {
246 	int rc;
247 
248 	rc = devres_release(dev, devm_rdev_release, devm_rdev_match, rdev);
249 	if (rc != 0)
250 		WARN_ON(rc);
251 }
252 EXPORT_SYMBOL_GPL(devm_regulator_unregister);
253 
254 struct regulator_supply_alias_match {
255 	struct device *dev;
256 	const char *id;
257 };
258 
devm_regulator_match_supply_alias(struct device * dev,void * res,void * data)259 static int devm_regulator_match_supply_alias(struct device *dev, void *res,
260 					     void *data)
261 {
262 	struct regulator_supply_alias_match *match = res;
263 	struct regulator_supply_alias_match *target = data;
264 
265 	return match->dev == target->dev && strcmp(match->id, target->id) == 0;
266 }
267 
devm_regulator_destroy_supply_alias(struct device * dev,void * res)268 static void devm_regulator_destroy_supply_alias(struct device *dev, void *res)
269 {
270 	struct regulator_supply_alias_match *match = res;
271 
272 	regulator_unregister_supply_alias(match->dev, match->id);
273 }
274 
275 /**
276  * devm_regulator_register_supply_alias - Resource managed
277  * regulator_register_supply_alias()
278  *
279  * @dev: device that will be given as the regulator "consumer"
280  * @id: Supply name or regulator ID
281  * @alias_dev: device that should be used to lookup the supply
282  * @alias_id: Supply name or regulator ID that should be used to lookup the
283  * supply
284  *
285  * The supply alias will automatically be unregistered when the source
286  * device is unbound.
287  */
devm_regulator_register_supply_alias(struct device * dev,const char * id,struct device * alias_dev,const char * alias_id)288 int devm_regulator_register_supply_alias(struct device *dev, const char *id,
289 					 struct device *alias_dev,
290 					 const char *alias_id)
291 {
292 	struct regulator_supply_alias_match *match;
293 	int ret;
294 
295 	match = devres_alloc(devm_regulator_destroy_supply_alias,
296 			   sizeof(struct regulator_supply_alias_match),
297 			   GFP_KERNEL);
298 	if (!match)
299 		return -ENOMEM;
300 
301 	match->dev = dev;
302 	match->id = id;
303 
304 	ret = regulator_register_supply_alias(dev, id, alias_dev, alias_id);
305 	if (ret < 0) {
306 		devres_free(match);
307 		return ret;
308 	}
309 
310 	devres_add(dev, match);
311 
312 	return 0;
313 }
314 EXPORT_SYMBOL_GPL(devm_regulator_register_supply_alias);
315 
316 /**
317  * devm_regulator_unregister_supply_alias - Resource managed
318  * regulator_unregister_supply_alias()
319  *
320  * @dev: device that will be given as the regulator "consumer"
321  * @id: Supply name or regulator ID
322  *
323  * Unregister an alias registered with
324  * devm_regulator_register_supply_alias(). Normally this function
325  * will not need to be called and the resource management code
326  * will ensure that the resource is freed.
327  */
devm_regulator_unregister_supply_alias(struct device * dev,const char * id)328 void devm_regulator_unregister_supply_alias(struct device *dev, const char *id)
329 {
330 	struct regulator_supply_alias_match match;
331 	int rc;
332 
333 	match.dev = dev;
334 	match.id = id;
335 
336 	rc = devres_release(dev, devm_regulator_destroy_supply_alias,
337 			    devm_regulator_match_supply_alias, &match);
338 	if (rc != 0)
339 		WARN_ON(rc);
340 }
341 EXPORT_SYMBOL_GPL(devm_regulator_unregister_supply_alias);
342 
343 /**
344  * devm_regulator_bulk_register_supply_alias - Managed register
345  * multiple aliases
346  *
347  * @dev: device that will be given as the regulator "consumer"
348  * @id: List of supply names or regulator IDs
349  * @alias_dev: device that should be used to lookup the supply
350  * @alias_id: List of supply names or regulator IDs that should be used to
351  * lookup the supply
352  * @num_id: Number of aliases to register
353  *
354  * @return 0 on success, an errno on failure.
355  *
356  * This helper function allows drivers to register several supply
357  * aliases in one operation, the aliases will be automatically
358  * unregisters when the source device is unbound.  If any of the
359  * aliases cannot be registered any aliases that were registered
360  * will be removed before returning to the caller.
361  */
devm_regulator_bulk_register_supply_alias(struct device * dev,const char * const * id,struct device * alias_dev,const char * const * alias_id,int num_id)362 int devm_regulator_bulk_register_supply_alias(struct device *dev,
363 					      const char *const *id,
364 					      struct device *alias_dev,
365 					      const char *const *alias_id,
366 					      int num_id)
367 {
368 	int i;
369 	int ret;
370 
371 	for (i = 0; i < num_id; ++i) {
372 		ret = devm_regulator_register_supply_alias(dev, id[i],
373 							   alias_dev,
374 							   alias_id[i]);
375 		if (ret < 0)
376 			goto err;
377 	}
378 
379 	return 0;
380 
381 err:
382 	dev_err(dev,
383 		"Failed to create supply alias %s,%s -> %s,%s\n",
384 		id[i], dev_name(dev), alias_id[i], dev_name(alias_dev));
385 
386 	while (--i >= 0)
387 		devm_regulator_unregister_supply_alias(dev, id[i]);
388 
389 	return ret;
390 }
391 EXPORT_SYMBOL_GPL(devm_regulator_bulk_register_supply_alias);
392 
393 /**
394  * devm_regulator_bulk_unregister_supply_alias - Managed unregister
395  * multiple aliases
396  *
397  * @dev: device that will be given as the regulator "consumer"
398  * @id: List of supply names or regulator IDs
399  * @num_id: Number of aliases to unregister
400  *
401  * Unregister aliases registered with
402  * devm_regulator_bulk_register_supply_alias(). Normally this function
403  * will not need to be called and the resource management code
404  * will ensure that the resource is freed.
405  */
devm_regulator_bulk_unregister_supply_alias(struct device * dev,const char * const * id,int num_id)406 void devm_regulator_bulk_unregister_supply_alias(struct device *dev,
407 						 const char *const *id,
408 						 int num_id)
409 {
410 	int i;
411 
412 	for (i = 0; i < num_id; ++i)
413 		devm_regulator_unregister_supply_alias(dev, id[i]);
414 }
415 EXPORT_SYMBOL_GPL(devm_regulator_bulk_unregister_supply_alias);
416 
417 struct regulator_notifier_match {
418 	struct regulator *regulator;
419 	struct notifier_block *nb;
420 };
421 
devm_regulator_match_notifier(struct device * dev,void * res,void * data)422 static int devm_regulator_match_notifier(struct device *dev, void *res,
423 					 void *data)
424 {
425 	struct regulator_notifier_match *match = res;
426 	struct regulator_notifier_match *target = data;
427 
428 	return match->regulator == target->regulator && match->nb == target->nb;
429 }
430 
devm_regulator_destroy_notifier(struct device * dev,void * res)431 static void devm_regulator_destroy_notifier(struct device *dev, void *res)
432 {
433 	struct regulator_notifier_match *match = res;
434 
435 	regulator_unregister_notifier(match->regulator, match->nb);
436 }
437 
438 /**
439  * devm_regulator_register_notifier - Resource managed
440  * regulator_register_notifier
441  *
442  * @regulator: regulator source
443  * @nb: notifier block
444  *
445  * The notifier will be registers under the consumer device and be
446  * automatically be unregistered when the source device is unbound.
447  */
devm_regulator_register_notifier(struct regulator * regulator,struct notifier_block * nb)448 int devm_regulator_register_notifier(struct regulator *regulator,
449 				     struct notifier_block *nb)
450 {
451 	struct regulator_notifier_match *match;
452 	int ret;
453 
454 	match = devres_alloc(devm_regulator_destroy_notifier,
455 			     sizeof(struct regulator_notifier_match),
456 			     GFP_KERNEL);
457 	if (!match)
458 		return -ENOMEM;
459 
460 	match->regulator = regulator;
461 	match->nb = nb;
462 
463 	ret = regulator_register_notifier(regulator, nb);
464 	if (ret < 0) {
465 		devres_free(match);
466 		return ret;
467 	}
468 
469 	devres_add(regulator->dev, match);
470 
471 	return 0;
472 }
473 EXPORT_SYMBOL_GPL(devm_regulator_register_notifier);
474 
475 /**
476  * devm_regulator_unregister_notifier - Resource managed
477  * regulator_unregister_notifier()
478  *
479  * @regulator: regulator source
480  * @nb: notifier block
481  *
482  * Unregister a notifier registered with devm_regulator_register_notifier().
483  * Normally this function will not need to be called and the resource
484  * management code will ensure that the resource is freed.
485  */
devm_regulator_unregister_notifier(struct regulator * regulator,struct notifier_block * nb)486 void devm_regulator_unregister_notifier(struct regulator *regulator,
487 					struct notifier_block *nb)
488 {
489 	struct regulator_notifier_match match;
490 	int rc;
491 
492 	match.regulator = regulator;
493 	match.nb = nb;
494 
495 	rc = devres_release(regulator->dev, devm_regulator_destroy_notifier,
496 			    devm_regulator_match_notifier, &match);
497 	if (rc != 0)
498 		WARN_ON(rc);
499 }
500 EXPORT_SYMBOL_GPL(devm_regulator_unregister_notifier);
501