10cdfcc0fSMark Brown /* 20cdfcc0fSMark Brown * devres.c -- Voltage/Current Regulator framework devres implementation. 30cdfcc0fSMark Brown * 40cdfcc0fSMark Brown * Copyright 2013 Linaro Ltd 50cdfcc0fSMark Brown * 60cdfcc0fSMark Brown * This program is free software; you can redistribute it and/or modify it 70cdfcc0fSMark Brown * under the terms of the GNU General Public License as published by the 80cdfcc0fSMark Brown * Free Software Foundation; either version 2 of the License, or (at your 90cdfcc0fSMark Brown * option) any later version. 100cdfcc0fSMark Brown * 110cdfcc0fSMark Brown */ 120cdfcc0fSMark Brown 130cdfcc0fSMark Brown #include <linux/kernel.h> 140cdfcc0fSMark Brown #include <linux/err.h> 150cdfcc0fSMark Brown #include <linux/regmap.h> 160cdfcc0fSMark Brown #include <linux/regulator/consumer.h> 170cdfcc0fSMark Brown #include <linux/regulator/driver.h> 180cdfcc0fSMark Brown #include <linux/module.h> 190cdfcc0fSMark Brown 200cdfcc0fSMark Brown #include "internal.h" 210cdfcc0fSMark Brown 220cdfcc0fSMark Brown enum { 230cdfcc0fSMark Brown NORMAL_GET, 240cdfcc0fSMark Brown EXCLUSIVE_GET, 250cdfcc0fSMark Brown OPTIONAL_GET, 260cdfcc0fSMark Brown }; 270cdfcc0fSMark Brown 280cdfcc0fSMark Brown static void devm_regulator_release(struct device *dev, void *res) 290cdfcc0fSMark Brown { 300cdfcc0fSMark Brown regulator_put(*(struct regulator **)res); 310cdfcc0fSMark Brown } 320cdfcc0fSMark Brown 330cdfcc0fSMark Brown static struct regulator *_devm_regulator_get(struct device *dev, const char *id, 340cdfcc0fSMark Brown int get_type) 350cdfcc0fSMark Brown { 360cdfcc0fSMark Brown struct regulator **ptr, *regulator; 370cdfcc0fSMark Brown 380cdfcc0fSMark Brown ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL); 390cdfcc0fSMark Brown if (!ptr) 400cdfcc0fSMark Brown return ERR_PTR(-ENOMEM); 410cdfcc0fSMark Brown 420cdfcc0fSMark Brown switch (get_type) { 430cdfcc0fSMark Brown case NORMAL_GET: 440cdfcc0fSMark Brown regulator = regulator_get(dev, id); 450cdfcc0fSMark Brown break; 460cdfcc0fSMark Brown case EXCLUSIVE_GET: 470cdfcc0fSMark Brown regulator = regulator_get_exclusive(dev, id); 480cdfcc0fSMark Brown break; 490cdfcc0fSMark Brown case OPTIONAL_GET: 500cdfcc0fSMark Brown regulator = regulator_get_optional(dev, id); 510cdfcc0fSMark Brown break; 520cdfcc0fSMark Brown default: 530cdfcc0fSMark Brown regulator = ERR_PTR(-EINVAL); 540cdfcc0fSMark Brown } 550cdfcc0fSMark Brown 560cdfcc0fSMark Brown if (!IS_ERR(regulator)) { 570cdfcc0fSMark Brown *ptr = regulator; 580cdfcc0fSMark Brown devres_add(dev, ptr); 590cdfcc0fSMark Brown } else { 600cdfcc0fSMark Brown devres_free(ptr); 610cdfcc0fSMark Brown } 620cdfcc0fSMark Brown 630cdfcc0fSMark Brown return regulator; 640cdfcc0fSMark Brown } 650cdfcc0fSMark Brown 660cdfcc0fSMark Brown /** 670cdfcc0fSMark Brown * devm_regulator_get - Resource managed regulator_get() 680cdfcc0fSMark Brown * @dev: device for regulator "consumer" 690cdfcc0fSMark Brown * @id: Supply name or regulator ID. 700cdfcc0fSMark Brown * 710cdfcc0fSMark Brown * Managed regulator_get(). Regulators returned from this function are 720cdfcc0fSMark Brown * automatically regulator_put() on driver detach. See regulator_get() for more 730cdfcc0fSMark Brown * information. 740cdfcc0fSMark Brown */ 750cdfcc0fSMark Brown struct regulator *devm_regulator_get(struct device *dev, const char *id) 760cdfcc0fSMark Brown { 770cdfcc0fSMark Brown return _devm_regulator_get(dev, id, NORMAL_GET); 780cdfcc0fSMark Brown } 790cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_get); 800cdfcc0fSMark Brown 810cdfcc0fSMark Brown /** 820cdfcc0fSMark Brown * devm_regulator_get_exclusive - Resource managed regulator_get_exclusive() 830cdfcc0fSMark Brown * @dev: device for regulator "consumer" 840cdfcc0fSMark Brown * @id: Supply name or regulator ID. 850cdfcc0fSMark Brown * 860cdfcc0fSMark Brown * Managed regulator_get_exclusive(). Regulators returned from this function 870cdfcc0fSMark Brown * are automatically regulator_put() on driver detach. See regulator_get() for 880cdfcc0fSMark Brown * more information. 890cdfcc0fSMark Brown */ 900cdfcc0fSMark Brown struct regulator *devm_regulator_get_exclusive(struct device *dev, 910cdfcc0fSMark Brown const char *id) 920cdfcc0fSMark Brown { 930cdfcc0fSMark Brown return _devm_regulator_get(dev, id, EXCLUSIVE_GET); 940cdfcc0fSMark Brown } 950cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_get_exclusive); 960cdfcc0fSMark Brown 970cdfcc0fSMark Brown /** 980cdfcc0fSMark Brown * devm_regulator_get_optional - Resource managed regulator_get_optional() 990cdfcc0fSMark Brown * @dev: device for regulator "consumer" 1000cdfcc0fSMark Brown * @id: Supply name or regulator ID. 1010cdfcc0fSMark Brown * 1020cdfcc0fSMark Brown * Managed regulator_get_optional(). Regulators returned from this 1030cdfcc0fSMark Brown * function are automatically regulator_put() on driver detach. See 1040cdfcc0fSMark Brown * regulator_get_optional() for more information. 1050cdfcc0fSMark Brown */ 1060cdfcc0fSMark Brown struct regulator *devm_regulator_get_optional(struct device *dev, 1070cdfcc0fSMark Brown const char *id) 1080cdfcc0fSMark Brown { 1090cdfcc0fSMark Brown return _devm_regulator_get(dev, id, OPTIONAL_GET); 1100cdfcc0fSMark Brown } 1110cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_get_optional); 1120cdfcc0fSMark Brown 1130cdfcc0fSMark Brown static int devm_regulator_match(struct device *dev, void *res, void *data) 1140cdfcc0fSMark Brown { 1150cdfcc0fSMark Brown struct regulator **r = res; 1160cdfcc0fSMark Brown if (!r || !*r) { 1170cdfcc0fSMark Brown WARN_ON(!r || !*r); 1180cdfcc0fSMark Brown return 0; 1190cdfcc0fSMark Brown } 1200cdfcc0fSMark Brown return *r == data; 1210cdfcc0fSMark Brown } 1220cdfcc0fSMark Brown 1230cdfcc0fSMark Brown /** 1240cdfcc0fSMark Brown * devm_regulator_put - Resource managed regulator_put() 1250cdfcc0fSMark Brown * @regulator: regulator to free 1260cdfcc0fSMark Brown * 1270cdfcc0fSMark Brown * Deallocate a regulator allocated with devm_regulator_get(). Normally 1280cdfcc0fSMark Brown * this function will not need to be called and the resource management 1290cdfcc0fSMark Brown * code will ensure that the resource is freed. 1300cdfcc0fSMark Brown */ 1310cdfcc0fSMark Brown void devm_regulator_put(struct regulator *regulator) 1320cdfcc0fSMark Brown { 1330cdfcc0fSMark Brown int rc; 1340cdfcc0fSMark Brown 1350cdfcc0fSMark Brown rc = devres_release(regulator->dev, devm_regulator_release, 1360cdfcc0fSMark Brown devm_regulator_match, regulator); 1370cdfcc0fSMark Brown if (rc != 0) 1380cdfcc0fSMark Brown WARN_ON(rc); 1390cdfcc0fSMark Brown } 1400cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_put); 1410cdfcc0fSMark Brown 1420cdfcc0fSMark Brown /** 1430cdfcc0fSMark Brown * devm_regulator_bulk_get - managed get multiple regulator consumers 1440cdfcc0fSMark Brown * 1450cdfcc0fSMark Brown * @dev: Device to supply 1460cdfcc0fSMark Brown * @num_consumers: Number of consumers to register 1470cdfcc0fSMark Brown * @consumers: Configuration of consumers; clients are stored here. 1480cdfcc0fSMark Brown * 1490cdfcc0fSMark Brown * @return 0 on success, an errno on failure. 1500cdfcc0fSMark Brown * 1510cdfcc0fSMark Brown * This helper function allows drivers to get several regulator 1520cdfcc0fSMark Brown * consumers in one operation with management, the regulators will 1530cdfcc0fSMark Brown * automatically be freed when the device is unbound. If any of the 1540cdfcc0fSMark Brown * regulators cannot be acquired then any regulators that were 1550cdfcc0fSMark Brown * allocated will be freed before returning to the caller. 1560cdfcc0fSMark Brown */ 1570cdfcc0fSMark Brown int devm_regulator_bulk_get(struct device *dev, int num_consumers, 1580cdfcc0fSMark Brown struct regulator_bulk_data *consumers) 1590cdfcc0fSMark Brown { 1600cdfcc0fSMark Brown int i; 1610cdfcc0fSMark Brown int ret; 1620cdfcc0fSMark Brown 1630cdfcc0fSMark Brown for (i = 0; i < num_consumers; i++) 1640cdfcc0fSMark Brown consumers[i].consumer = NULL; 1650cdfcc0fSMark Brown 1660cdfcc0fSMark Brown for (i = 0; i < num_consumers; i++) { 1670cdfcc0fSMark Brown consumers[i].consumer = devm_regulator_get(dev, 1680cdfcc0fSMark Brown consumers[i].supply); 1690cdfcc0fSMark Brown if (IS_ERR(consumers[i].consumer)) { 1700cdfcc0fSMark Brown ret = PTR_ERR(consumers[i].consumer); 1710cdfcc0fSMark Brown dev_err(dev, "Failed to get supply '%s': %d\n", 1720cdfcc0fSMark Brown consumers[i].supply, ret); 1730cdfcc0fSMark Brown consumers[i].consumer = NULL; 1740cdfcc0fSMark Brown goto err; 1750cdfcc0fSMark Brown } 1760cdfcc0fSMark Brown } 1770cdfcc0fSMark Brown 1780cdfcc0fSMark Brown return 0; 1790cdfcc0fSMark Brown 1800cdfcc0fSMark Brown err: 1810cdfcc0fSMark Brown for (i = 0; i < num_consumers && consumers[i].consumer; i++) 1820cdfcc0fSMark Brown devm_regulator_put(consumers[i].consumer); 1830cdfcc0fSMark Brown 1840cdfcc0fSMark Brown return ret; 1850cdfcc0fSMark Brown } 1860cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_bulk_get); 1870cdfcc0fSMark Brown 1880cdfcc0fSMark Brown static void devm_rdev_release(struct device *dev, void *res) 1890cdfcc0fSMark Brown { 1900cdfcc0fSMark Brown regulator_unregister(*(struct regulator_dev **)res); 1910cdfcc0fSMark Brown } 1920cdfcc0fSMark Brown 1930cdfcc0fSMark Brown /** 1940cdfcc0fSMark Brown * devm_regulator_register - Resource managed regulator_register() 1950cdfcc0fSMark Brown * @regulator_desc: regulator to register 1960cdfcc0fSMark Brown * @config: runtime configuration for regulator 1970cdfcc0fSMark Brown * 1980cdfcc0fSMark Brown * Called by regulator drivers to register a regulator. Returns a 1990cdfcc0fSMark Brown * valid pointer to struct regulator_dev on success or an ERR_PTR() on 2000cdfcc0fSMark Brown * error. The regulator will automatically be released when the device 2010cdfcc0fSMark Brown * is unbound. 2020cdfcc0fSMark Brown */ 2030cdfcc0fSMark Brown struct regulator_dev *devm_regulator_register(struct device *dev, 2040cdfcc0fSMark Brown const struct regulator_desc *regulator_desc, 2050cdfcc0fSMark Brown const struct regulator_config *config) 2060cdfcc0fSMark Brown { 2070cdfcc0fSMark Brown struct regulator_dev **ptr, *rdev; 2080cdfcc0fSMark Brown 2090cdfcc0fSMark Brown ptr = devres_alloc(devm_rdev_release, sizeof(*ptr), 2100cdfcc0fSMark Brown GFP_KERNEL); 2110cdfcc0fSMark Brown if (!ptr) 2120cdfcc0fSMark Brown return ERR_PTR(-ENOMEM); 2130cdfcc0fSMark Brown 2140cdfcc0fSMark Brown rdev = regulator_register(regulator_desc, config); 2150cdfcc0fSMark Brown if (!IS_ERR(rdev)) { 2160cdfcc0fSMark Brown *ptr = rdev; 2170cdfcc0fSMark Brown devres_add(dev, ptr); 2180cdfcc0fSMark Brown } else { 2190cdfcc0fSMark Brown devres_free(ptr); 2200cdfcc0fSMark Brown } 2210cdfcc0fSMark Brown 2220cdfcc0fSMark Brown return rdev; 2230cdfcc0fSMark Brown } 2240cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_register); 2250cdfcc0fSMark Brown 2260cdfcc0fSMark Brown static int devm_rdev_match(struct device *dev, void *res, void *data) 2270cdfcc0fSMark Brown { 2280cdfcc0fSMark Brown struct regulator_dev **r = res; 2290cdfcc0fSMark Brown if (!r || !*r) { 2300cdfcc0fSMark Brown WARN_ON(!r || !*r); 2310cdfcc0fSMark Brown return 0; 2320cdfcc0fSMark Brown } 2330cdfcc0fSMark Brown return *r == data; 2340cdfcc0fSMark Brown } 2350cdfcc0fSMark Brown 2360cdfcc0fSMark Brown /** 2370cdfcc0fSMark Brown * devm_regulator_unregister - Resource managed regulator_unregister() 2380cdfcc0fSMark Brown * @regulator: regulator to free 2390cdfcc0fSMark Brown * 2400cdfcc0fSMark Brown * Unregister a regulator registered with devm_regulator_register(). 2410cdfcc0fSMark Brown * Normally this function will not need to be called and the resource 2420cdfcc0fSMark Brown * management code will ensure that the resource is freed. 2430cdfcc0fSMark Brown */ 2440cdfcc0fSMark Brown void devm_regulator_unregister(struct device *dev, struct regulator_dev *rdev) 2450cdfcc0fSMark Brown { 2460cdfcc0fSMark Brown int rc; 2470cdfcc0fSMark Brown 2480cdfcc0fSMark Brown rc = devres_release(dev, devm_rdev_release, devm_rdev_match, rdev); 2490cdfcc0fSMark Brown if (rc != 0) 2500cdfcc0fSMark Brown WARN_ON(rc); 2510cdfcc0fSMark Brown } 2520cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_unregister); 253a06ccd9cSCharles Keepax 254a06ccd9cSCharles Keepax struct regulator_supply_alias_match { 255a06ccd9cSCharles Keepax struct device *dev; 256a06ccd9cSCharles Keepax const char *id; 257a06ccd9cSCharles Keepax }; 258a06ccd9cSCharles Keepax 259a06ccd9cSCharles Keepax static int devm_regulator_match_supply_alias(struct device *dev, void *res, 260a06ccd9cSCharles Keepax void *data) 261a06ccd9cSCharles Keepax { 262a06ccd9cSCharles Keepax struct regulator_supply_alias_match *match = res; 263a06ccd9cSCharles Keepax struct regulator_supply_alias_match *target = data; 264a06ccd9cSCharles Keepax 265a06ccd9cSCharles Keepax return match->dev == target->dev && strcmp(match->id, target->id) == 0; 266a06ccd9cSCharles Keepax } 267a06ccd9cSCharles Keepax 268a06ccd9cSCharles Keepax static void devm_regulator_destroy_supply_alias(struct device *dev, void *res) 269a06ccd9cSCharles Keepax { 270a06ccd9cSCharles Keepax struct regulator_supply_alias_match *match = res; 271a06ccd9cSCharles Keepax 272a06ccd9cSCharles Keepax regulator_unregister_supply_alias(match->dev, match->id); 273a06ccd9cSCharles Keepax } 274a06ccd9cSCharles Keepax 275a06ccd9cSCharles Keepax /** 276a06ccd9cSCharles Keepax * devm_regulator_register_supply_alias - Resource managed 277a06ccd9cSCharles Keepax * regulator_register_supply_alias() 278a06ccd9cSCharles Keepax * 279a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 280a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 281a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 282a06ccd9cSCharles Keepax * @alias_id: Supply name or regulator ID that should be used to lookup the 283a06ccd9cSCharles Keepax * supply 284a06ccd9cSCharles Keepax * 285a06ccd9cSCharles Keepax * The supply alias will automatically be unregistered when the source 286a06ccd9cSCharles Keepax * device is unbound. 287a06ccd9cSCharles Keepax */ 288a06ccd9cSCharles Keepax int devm_regulator_register_supply_alias(struct device *dev, const char *id, 289a06ccd9cSCharles Keepax struct device *alias_dev, 290a06ccd9cSCharles Keepax const char *alias_id) 291a06ccd9cSCharles Keepax { 292a06ccd9cSCharles Keepax struct regulator_supply_alias_match *match; 293a06ccd9cSCharles Keepax int ret; 294a06ccd9cSCharles Keepax 295a06ccd9cSCharles Keepax match = devres_alloc(devm_regulator_destroy_supply_alias, 296a06ccd9cSCharles Keepax sizeof(struct regulator_supply_alias_match), 297a06ccd9cSCharles Keepax GFP_KERNEL); 298a06ccd9cSCharles Keepax if (!match) 299a06ccd9cSCharles Keepax return -ENOMEM; 300a06ccd9cSCharles Keepax 301a06ccd9cSCharles Keepax match->dev = dev; 302a06ccd9cSCharles Keepax match->id = id; 303a06ccd9cSCharles Keepax 304a06ccd9cSCharles Keepax ret = regulator_register_supply_alias(dev, id, alias_dev, alias_id); 305a06ccd9cSCharles Keepax if (ret < 0) { 306a06ccd9cSCharles Keepax devres_free(match); 307a06ccd9cSCharles Keepax return ret; 308a06ccd9cSCharles Keepax } 309a06ccd9cSCharles Keepax 310a06ccd9cSCharles Keepax devres_add(dev, match); 311a06ccd9cSCharles Keepax 312a06ccd9cSCharles Keepax return 0; 313a06ccd9cSCharles Keepax } 314a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_register_supply_alias); 315a06ccd9cSCharles Keepax 316a06ccd9cSCharles Keepax /** 317a06ccd9cSCharles Keepax * devm_regulator_unregister_supply_alias - Resource managed 318a06ccd9cSCharles Keepax * regulator_unregister_supply_alias() 319a06ccd9cSCharles Keepax * 320a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 321a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 322a06ccd9cSCharles Keepax * 323a06ccd9cSCharles Keepax * Unregister an alias registered with 324a06ccd9cSCharles Keepax * devm_regulator_register_supply_alias(). Normally this function 325a06ccd9cSCharles Keepax * will not need to be called and the resource management code 326a06ccd9cSCharles Keepax * will ensure that the resource is freed. 327a06ccd9cSCharles Keepax */ 328a06ccd9cSCharles Keepax void devm_regulator_unregister_supply_alias(struct device *dev, const char *id) 329a06ccd9cSCharles Keepax { 330a06ccd9cSCharles Keepax struct regulator_supply_alias_match match; 331a06ccd9cSCharles Keepax int rc; 332a06ccd9cSCharles Keepax 333a06ccd9cSCharles Keepax match.dev = dev; 334a06ccd9cSCharles Keepax match.id = id; 335a06ccd9cSCharles Keepax 336a06ccd9cSCharles Keepax rc = devres_release(dev, devm_regulator_destroy_supply_alias, 337a06ccd9cSCharles Keepax devm_regulator_match_supply_alias, &match); 338a06ccd9cSCharles Keepax if (rc != 0) 339a06ccd9cSCharles Keepax WARN_ON(rc); 340a06ccd9cSCharles Keepax } 341a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_unregister_supply_alias); 342a06ccd9cSCharles Keepax 343a06ccd9cSCharles Keepax /** 344a06ccd9cSCharles Keepax * devm_regulator_bulk_register_supply_alias - Managed register 345a06ccd9cSCharles Keepax * multiple aliases 346a06ccd9cSCharles Keepax * 347a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 348a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 349a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 350a06ccd9cSCharles Keepax * @alias_id: List of supply names or regulator IDs that should be used to 351a06ccd9cSCharles Keepax * lookup the supply 352a06ccd9cSCharles Keepax * @num_id: Number of aliases to register 353a06ccd9cSCharles Keepax * 354a06ccd9cSCharles Keepax * @return 0 on success, an errno on failure. 355a06ccd9cSCharles Keepax * 356a06ccd9cSCharles Keepax * This helper function allows drivers to register several supply 357a06ccd9cSCharles Keepax * aliases in one operation, the aliases will be automatically 358a06ccd9cSCharles Keepax * unregisters when the source device is unbound. If any of the 359a06ccd9cSCharles Keepax * aliases cannot be registered any aliases that were registered 360a06ccd9cSCharles Keepax * will be removed before returning to the caller. 361a06ccd9cSCharles Keepax */ 362a06ccd9cSCharles Keepax int devm_regulator_bulk_register_supply_alias(struct device *dev, 3639f8c0fe9SLee Jones const char *const *id, 364a06ccd9cSCharles Keepax struct device *alias_dev, 3659f8c0fe9SLee Jones const char *const *alias_id, 366a06ccd9cSCharles Keepax int num_id) 367a06ccd9cSCharles Keepax { 368a06ccd9cSCharles Keepax int i; 369a06ccd9cSCharles Keepax int ret; 370a06ccd9cSCharles Keepax 371a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) { 372a06ccd9cSCharles Keepax ret = devm_regulator_register_supply_alias(dev, id[i], 373a06ccd9cSCharles Keepax alias_dev, 374a06ccd9cSCharles Keepax alias_id[i]); 375a06ccd9cSCharles Keepax if (ret < 0) 376a06ccd9cSCharles Keepax goto err; 377a06ccd9cSCharles Keepax } 378a06ccd9cSCharles Keepax 379a06ccd9cSCharles Keepax return 0; 380a06ccd9cSCharles Keepax 381a06ccd9cSCharles Keepax err: 382a06ccd9cSCharles Keepax dev_err(dev, 383a06ccd9cSCharles Keepax "Failed to create supply alias %s,%s -> %s,%s\n", 384a06ccd9cSCharles Keepax id[i], dev_name(dev), alias_id[i], dev_name(alias_dev)); 385a06ccd9cSCharles Keepax 386a06ccd9cSCharles Keepax while (--i >= 0) 387a06ccd9cSCharles Keepax devm_regulator_unregister_supply_alias(dev, id[i]); 388a06ccd9cSCharles Keepax 389a06ccd9cSCharles Keepax return ret; 390a06ccd9cSCharles Keepax } 391a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_bulk_register_supply_alias); 392a06ccd9cSCharles Keepax 393a06ccd9cSCharles Keepax /** 394a06ccd9cSCharles Keepax * devm_regulator_bulk_unregister_supply_alias - Managed unregister 395a06ccd9cSCharles Keepax * multiple aliases 396a06ccd9cSCharles Keepax * 397a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 398a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 399a06ccd9cSCharles Keepax * @num_id: Number of aliases to unregister 400a06ccd9cSCharles Keepax * 401a06ccd9cSCharles Keepax * Unregister aliases registered with 402a06ccd9cSCharles Keepax * devm_regulator_bulk_register_supply_alias(). Normally this function 403a06ccd9cSCharles Keepax * will not need to be called and the resource management code 404a06ccd9cSCharles Keepax * will ensure that the resource is freed. 405a06ccd9cSCharles Keepax */ 406a06ccd9cSCharles Keepax void devm_regulator_bulk_unregister_supply_alias(struct device *dev, 4079f8c0fe9SLee Jones const char *const *id, 408a06ccd9cSCharles Keepax int num_id) 409a06ccd9cSCharles Keepax { 410a06ccd9cSCharles Keepax int i; 411a06ccd9cSCharles Keepax 412a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) 413a06ccd9cSCharles Keepax devm_regulator_unregister_supply_alias(dev, id[i]); 414a06ccd9cSCharles Keepax } 415a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_bulk_unregister_supply_alias); 416046db763SCharles Keepax 417046db763SCharles Keepax struct regulator_notifier_match { 418046db763SCharles Keepax struct regulator *regulator; 419046db763SCharles Keepax struct notifier_block *nb; 420046db763SCharles Keepax }; 421046db763SCharles Keepax 422046db763SCharles Keepax static int devm_regulator_match_notifier(struct device *dev, void *res, 423046db763SCharles Keepax void *data) 424046db763SCharles Keepax { 425046db763SCharles Keepax struct regulator_notifier_match *match = res; 426046db763SCharles Keepax struct regulator_notifier_match *target = data; 427046db763SCharles Keepax 428046db763SCharles Keepax return match->regulator == target->regulator && match->nb == target->nb; 429046db763SCharles Keepax } 430046db763SCharles Keepax 431046db763SCharles Keepax static void devm_regulator_destroy_notifier(struct device *dev, void *res) 432046db763SCharles Keepax { 433046db763SCharles Keepax struct regulator_notifier_match *match = res; 434046db763SCharles Keepax 435046db763SCharles Keepax regulator_unregister_notifier(match->regulator, match->nb); 436046db763SCharles Keepax } 437046db763SCharles Keepax 438046db763SCharles Keepax /** 439046db763SCharles Keepax * devm_regulator_register_notifier - Resource managed 440046db763SCharles Keepax * regulator_register_notifier 441046db763SCharles Keepax * 442046db763SCharles Keepax * @regulator: regulator source 443046db763SCharles Keepax * @nb: notifier block 444046db763SCharles Keepax * 445046db763SCharles Keepax * The notifier will be registers under the consumer device and be 446046db763SCharles Keepax * automatically be unregistered when the source device is unbound. 447046db763SCharles Keepax */ 448046db763SCharles Keepax int devm_regulator_register_notifier(struct regulator *regulator, 449046db763SCharles Keepax struct notifier_block *nb) 450046db763SCharles Keepax { 451046db763SCharles Keepax struct regulator_notifier_match *match; 452046db763SCharles Keepax int ret; 453046db763SCharles Keepax 454046db763SCharles Keepax match = devres_alloc(devm_regulator_destroy_notifier, 455046db763SCharles Keepax sizeof(struct regulator_notifier_match), 456046db763SCharles Keepax GFP_KERNEL); 457046db763SCharles Keepax if (!match) 458046db763SCharles Keepax return -ENOMEM; 459046db763SCharles Keepax 460046db763SCharles Keepax match->regulator = regulator; 461046db763SCharles Keepax match->nb = nb; 462046db763SCharles Keepax 463046db763SCharles Keepax ret = regulator_register_notifier(regulator, nb); 464046db763SCharles Keepax if (ret < 0) { 465046db763SCharles Keepax devres_free(match); 466046db763SCharles Keepax return ret; 467046db763SCharles Keepax } 468046db763SCharles Keepax 469046db763SCharles Keepax devres_add(regulator->dev, match); 470046db763SCharles Keepax 471046db763SCharles Keepax return 0; 472046db763SCharles Keepax } 473046db763SCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_register_notifier); 474046db763SCharles Keepax 475046db763SCharles Keepax /** 476046db763SCharles Keepax * devm_regulator_unregister_notifier - Resource managed 477046db763SCharles Keepax * regulator_unregister_notifier() 478046db763SCharles Keepax * 479046db763SCharles Keepax * @regulator: regulator source 480046db763SCharles Keepax * @nb: notifier block 481046db763SCharles Keepax * 482046db763SCharles Keepax * Unregister a notifier registered with devm_regulator_register_notifier(). 483046db763SCharles Keepax * Normally this function will not need to be called and the resource 484046db763SCharles Keepax * management code will ensure that the resource is freed. 485046db763SCharles Keepax */ 486046db763SCharles Keepax void devm_regulator_unregister_notifier(struct regulator *regulator, 487046db763SCharles Keepax struct notifier_block *nb) 488046db763SCharles Keepax { 489046db763SCharles Keepax struct regulator_notifier_match match; 490046db763SCharles Keepax int rc; 491046db763SCharles Keepax 492046db763SCharles Keepax match.regulator = regulator; 493046db763SCharles Keepax match.nb = nb; 494046db763SCharles Keepax 495046db763SCharles Keepax rc = devres_release(regulator->dev, devm_regulator_destroy_notifier, 496046db763SCharles Keepax devm_regulator_match_notifier, &match); 497046db763SCharles Keepax if (rc != 0) 498046db763SCharles Keepax WARN_ON(rc); 499046db763SCharles Keepax } 500046db763SCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_unregister_notifier); 501