aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/regulator/devres.c
diff options
context:
space:
mode:
authorCharles Keepax <ckeepax@opensource.wolfsonmicro.com>2013-10-15 15:14:20 -0400
committerMark Brown <broonie@linaro.org>2013-10-17 19:56:05 -0400
commita06ccd9c3785fa5550917ae036944f4e080b5749 (patch)
tree9314ebad2316f4f1e016f53e8f10eb0fbf911190 /drivers/regulator/devres.c
parent0cdfcc0f9352a4c076fbb51299e2b12a35619a51 (diff)
regulator: core: Add ability to create a lookup alias for supply
These patches add the ability to create an alternative device on which a lookup for a certain supply should be conducted. A common use-case for this would be devices that are logically represented as a collection of drivers within Linux but are are presented as a single device from device tree. It this case it is necessary for each sub device to locate their supply data on the main device. Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'drivers/regulator/devres.c')
-rw-r--r--drivers/regulator/devres.c163
1 files changed, 163 insertions, 0 deletions
diff --git a/drivers/regulator/devres.c b/drivers/regulator/devres.c
index 2672a029fa25..f44818b838dc 100644
--- a/drivers/regulator/devres.c
+++ b/drivers/regulator/devres.c
@@ -250,3 +250,166 @@ void devm_regulator_unregister(struct device *dev, struct regulator_dev *rdev)
250 WARN_ON(rc); 250 WARN_ON(rc);
251} 251}
252EXPORT_SYMBOL_GPL(devm_regulator_unregister); 252EXPORT_SYMBOL_GPL(devm_regulator_unregister);
253
254struct regulator_supply_alias_match {
255 struct device *dev;
256 const char *id;
257};
258
259static 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
268static 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 */
288int 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}
314EXPORT_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 */
328void 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}
341EXPORT_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 */
362int devm_regulator_bulk_register_supply_alias(struct device *dev,
363 const char **id,
364 struct device *alias_dev,
365 const char **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
381err:
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}
391EXPORT_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 */
406void devm_regulator_bulk_unregister_supply_alias(struct device *dev,
407 const char **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}
415EXPORT_SYMBOL_GPL(devm_regulator_bulk_unregister_supply_alias);