12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 20cdfcc0fSMark Brown /* 30cdfcc0fSMark Brown * devres.c -- Voltage/Current Regulator framework devres implementation. 40cdfcc0fSMark Brown * 50cdfcc0fSMark Brown * Copyright 2013 Linaro Ltd 60cdfcc0fSMark Brown */ 70cdfcc0fSMark Brown 80cdfcc0fSMark Brown #include <linux/kernel.h> 90cdfcc0fSMark Brown #include <linux/err.h> 100cdfcc0fSMark Brown #include <linux/regmap.h> 110cdfcc0fSMark Brown #include <linux/regulator/consumer.h> 120cdfcc0fSMark Brown #include <linux/regulator/driver.h> 130cdfcc0fSMark Brown #include <linux/module.h> 140cdfcc0fSMark Brown 150cdfcc0fSMark Brown #include "internal.h" 160cdfcc0fSMark Brown 170cdfcc0fSMark Brown static void devm_regulator_release(struct device *dev, void *res) 180cdfcc0fSMark Brown { 190cdfcc0fSMark Brown regulator_put(*(struct regulator **)res); 200cdfcc0fSMark Brown } 210cdfcc0fSMark Brown 220cdfcc0fSMark Brown static struct regulator *_devm_regulator_get(struct device *dev, const char *id, 230cdfcc0fSMark Brown int get_type) 240cdfcc0fSMark Brown { 250cdfcc0fSMark Brown struct regulator **ptr, *regulator; 260cdfcc0fSMark Brown 270cdfcc0fSMark Brown ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL); 280cdfcc0fSMark Brown if (!ptr) 290cdfcc0fSMark Brown return ERR_PTR(-ENOMEM); 300cdfcc0fSMark Brown 31a8bd42a9SDmitry Torokhov regulator = _regulator_get(dev, id, get_type); 320cdfcc0fSMark Brown if (!IS_ERR(regulator)) { 330cdfcc0fSMark Brown *ptr = regulator; 340cdfcc0fSMark Brown devres_add(dev, ptr); 350cdfcc0fSMark Brown } else { 360cdfcc0fSMark Brown devres_free(ptr); 370cdfcc0fSMark Brown } 380cdfcc0fSMark Brown 390cdfcc0fSMark Brown return regulator; 400cdfcc0fSMark Brown } 410cdfcc0fSMark Brown 420cdfcc0fSMark Brown /** 430cdfcc0fSMark Brown * devm_regulator_get - Resource managed regulator_get() 44a7c15187SLee Jones * @dev: device to supply 45a7c15187SLee Jones * @id: supply name or regulator ID. 460cdfcc0fSMark Brown * 470cdfcc0fSMark Brown * Managed regulator_get(). Regulators returned from this function are 480cdfcc0fSMark Brown * automatically regulator_put() on driver detach. See regulator_get() for more 490cdfcc0fSMark Brown * information. 500cdfcc0fSMark Brown */ 510cdfcc0fSMark Brown struct regulator *devm_regulator_get(struct device *dev, const char *id) 520cdfcc0fSMark Brown { 530cdfcc0fSMark Brown return _devm_regulator_get(dev, id, NORMAL_GET); 540cdfcc0fSMark Brown } 550cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_get); 560cdfcc0fSMark Brown 570cdfcc0fSMark Brown /** 580cdfcc0fSMark Brown * devm_regulator_get_exclusive - Resource managed regulator_get_exclusive() 59a7c15187SLee Jones * @dev: device to supply 60a7c15187SLee Jones * @id: supply name or regulator ID. 610cdfcc0fSMark Brown * 620cdfcc0fSMark Brown * Managed regulator_get_exclusive(). Regulators returned from this function 630cdfcc0fSMark Brown * are automatically regulator_put() on driver detach. See regulator_get() for 640cdfcc0fSMark Brown * more information. 650cdfcc0fSMark Brown */ 660cdfcc0fSMark Brown struct regulator *devm_regulator_get_exclusive(struct device *dev, 670cdfcc0fSMark Brown const char *id) 680cdfcc0fSMark Brown { 690cdfcc0fSMark Brown return _devm_regulator_get(dev, id, EXCLUSIVE_GET); 700cdfcc0fSMark Brown } 710cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_get_exclusive); 720cdfcc0fSMark Brown 730cdfcc0fSMark Brown /** 740cdfcc0fSMark Brown * devm_regulator_get_optional - Resource managed regulator_get_optional() 75a7c15187SLee Jones * @dev: device to supply 76a7c15187SLee Jones * @id: supply name or regulator ID. 770cdfcc0fSMark Brown * 780cdfcc0fSMark Brown * Managed regulator_get_optional(). Regulators returned from this 790cdfcc0fSMark Brown * function are automatically regulator_put() on driver detach. See 800cdfcc0fSMark Brown * regulator_get_optional() for more information. 810cdfcc0fSMark Brown */ 820cdfcc0fSMark Brown struct regulator *devm_regulator_get_optional(struct device *dev, 830cdfcc0fSMark Brown const char *id) 840cdfcc0fSMark Brown { 850cdfcc0fSMark Brown return _devm_regulator_get(dev, id, OPTIONAL_GET); 860cdfcc0fSMark Brown } 870cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_get_optional); 880cdfcc0fSMark Brown 890cdfcc0fSMark Brown static int devm_regulator_match(struct device *dev, void *res, void *data) 900cdfcc0fSMark Brown { 910cdfcc0fSMark Brown struct regulator **r = res; 920cdfcc0fSMark Brown if (!r || !*r) { 930cdfcc0fSMark Brown WARN_ON(!r || !*r); 940cdfcc0fSMark Brown return 0; 950cdfcc0fSMark Brown } 960cdfcc0fSMark Brown return *r == data; 970cdfcc0fSMark Brown } 980cdfcc0fSMark Brown 990cdfcc0fSMark Brown /** 1000cdfcc0fSMark Brown * devm_regulator_put - Resource managed regulator_put() 1010cdfcc0fSMark Brown * @regulator: regulator to free 1020cdfcc0fSMark Brown * 1030cdfcc0fSMark Brown * Deallocate a regulator allocated with devm_regulator_get(). Normally 1040cdfcc0fSMark Brown * this function will not need to be called and the resource management 1050cdfcc0fSMark Brown * code will ensure that the resource is freed. 1060cdfcc0fSMark Brown */ 1070cdfcc0fSMark Brown void devm_regulator_put(struct regulator *regulator) 1080cdfcc0fSMark Brown { 1090cdfcc0fSMark Brown int rc; 1100cdfcc0fSMark Brown 1110cdfcc0fSMark Brown rc = devres_release(regulator->dev, devm_regulator_release, 1120cdfcc0fSMark Brown devm_regulator_match, regulator); 1130cdfcc0fSMark Brown if (rc != 0) 1140cdfcc0fSMark Brown WARN_ON(rc); 1150cdfcc0fSMark Brown } 1160cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_put); 1170cdfcc0fSMark Brown 1183eaeb475SDmitry Torokhov struct regulator_bulk_devres { 1193eaeb475SDmitry Torokhov struct regulator_bulk_data *consumers; 1203eaeb475SDmitry Torokhov int num_consumers; 1213eaeb475SDmitry Torokhov }; 1223eaeb475SDmitry Torokhov 1233eaeb475SDmitry Torokhov static void devm_regulator_bulk_release(struct device *dev, void *res) 1243eaeb475SDmitry Torokhov { 1253eaeb475SDmitry Torokhov struct regulator_bulk_devres *devres = res; 1263eaeb475SDmitry Torokhov 1273eaeb475SDmitry Torokhov regulator_bulk_free(devres->num_consumers, devres->consumers); 1283eaeb475SDmitry Torokhov } 1293eaeb475SDmitry Torokhov 1300cdfcc0fSMark Brown /** 1310cdfcc0fSMark Brown * devm_regulator_bulk_get - managed get multiple regulator consumers 1320cdfcc0fSMark Brown * 133a7c15187SLee Jones * @dev: device to supply 134a7c15187SLee Jones * @num_consumers: number of consumers to register 135a7c15187SLee Jones * @consumers: configuration of consumers; clients are stored here. 1360cdfcc0fSMark Brown * 1370cdfcc0fSMark Brown * @return 0 on success, an errno on failure. 1380cdfcc0fSMark Brown * 1390cdfcc0fSMark Brown * This helper function allows drivers to get several regulator 1400cdfcc0fSMark Brown * consumers in one operation with management, the regulators will 1410cdfcc0fSMark Brown * automatically be freed when the device is unbound. If any of the 1420cdfcc0fSMark Brown * regulators cannot be acquired then any regulators that were 1430cdfcc0fSMark Brown * allocated will be freed before returning to the caller. 1440cdfcc0fSMark Brown */ 1450cdfcc0fSMark Brown int devm_regulator_bulk_get(struct device *dev, int num_consumers, 1460cdfcc0fSMark Brown struct regulator_bulk_data *consumers) 1470cdfcc0fSMark Brown { 1483eaeb475SDmitry Torokhov struct regulator_bulk_devres *devres; 1490cdfcc0fSMark Brown int ret; 1500cdfcc0fSMark Brown 1513eaeb475SDmitry Torokhov devres = devres_alloc(devm_regulator_bulk_release, 1523eaeb475SDmitry Torokhov sizeof(*devres), GFP_KERNEL); 1533eaeb475SDmitry Torokhov if (!devres) 1543eaeb475SDmitry Torokhov return -ENOMEM; 1550cdfcc0fSMark Brown 1563eaeb475SDmitry Torokhov ret = regulator_bulk_get(dev, num_consumers, consumers); 1573eaeb475SDmitry Torokhov if (!ret) { 1583eaeb475SDmitry Torokhov devres->consumers = consumers; 1593eaeb475SDmitry Torokhov devres->num_consumers = num_consumers; 1603eaeb475SDmitry Torokhov devres_add(dev, devres); 1613eaeb475SDmitry Torokhov } else { 1623eaeb475SDmitry Torokhov devres_free(devres); 1630cdfcc0fSMark Brown } 1640cdfcc0fSMark Brown 1650cdfcc0fSMark Brown return ret; 1660cdfcc0fSMark Brown } 1670cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_bulk_get); 1680cdfcc0fSMark Brown 1690cdfcc0fSMark Brown static void devm_rdev_release(struct device *dev, void *res) 1700cdfcc0fSMark Brown { 1710cdfcc0fSMark Brown regulator_unregister(*(struct regulator_dev **)res); 1720cdfcc0fSMark Brown } 1730cdfcc0fSMark Brown 1740cdfcc0fSMark Brown /** 1750cdfcc0fSMark Brown * devm_regulator_register - Resource managed regulator_register() 1769565cccdSLee Jones * @dev: device to supply 1770cdfcc0fSMark Brown * @regulator_desc: regulator to register 1780cdfcc0fSMark Brown * @config: runtime configuration for regulator 1790cdfcc0fSMark Brown * 1800cdfcc0fSMark Brown * Called by regulator drivers to register a regulator. Returns a 1810cdfcc0fSMark Brown * valid pointer to struct regulator_dev on success or an ERR_PTR() on 1820cdfcc0fSMark Brown * error. The regulator will automatically be released when the device 1830cdfcc0fSMark Brown * is unbound. 1840cdfcc0fSMark Brown */ 1850cdfcc0fSMark Brown struct regulator_dev *devm_regulator_register(struct device *dev, 1860cdfcc0fSMark Brown const struct regulator_desc *regulator_desc, 1870cdfcc0fSMark Brown const struct regulator_config *config) 1880cdfcc0fSMark Brown { 1890cdfcc0fSMark Brown struct regulator_dev **ptr, *rdev; 1900cdfcc0fSMark Brown 1910cdfcc0fSMark Brown ptr = devres_alloc(devm_rdev_release, sizeof(*ptr), 1920cdfcc0fSMark Brown GFP_KERNEL); 1930cdfcc0fSMark Brown if (!ptr) 1940cdfcc0fSMark Brown return ERR_PTR(-ENOMEM); 1950cdfcc0fSMark Brown 1960cdfcc0fSMark Brown rdev = regulator_register(regulator_desc, config); 1970cdfcc0fSMark Brown if (!IS_ERR(rdev)) { 1980cdfcc0fSMark Brown *ptr = rdev; 1990cdfcc0fSMark Brown devres_add(dev, ptr); 2000cdfcc0fSMark Brown } else { 2010cdfcc0fSMark Brown devres_free(ptr); 2020cdfcc0fSMark Brown } 2030cdfcc0fSMark Brown 2040cdfcc0fSMark Brown return rdev; 2050cdfcc0fSMark Brown } 2060cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_register); 2070cdfcc0fSMark Brown 2080cdfcc0fSMark Brown static int devm_rdev_match(struct device *dev, void *res, void *data) 2090cdfcc0fSMark Brown { 2100cdfcc0fSMark Brown struct regulator_dev **r = res; 2110cdfcc0fSMark Brown if (!r || !*r) { 2120cdfcc0fSMark Brown WARN_ON(!r || !*r); 2130cdfcc0fSMark Brown return 0; 2140cdfcc0fSMark Brown } 2150cdfcc0fSMark Brown return *r == data; 2160cdfcc0fSMark Brown } 2170cdfcc0fSMark Brown 2180cdfcc0fSMark Brown /** 2190cdfcc0fSMark Brown * devm_regulator_unregister - Resource managed regulator_unregister() 2209565cccdSLee Jones * @dev: device to supply 2219565cccdSLee Jones * @rdev: regulator to free 2220cdfcc0fSMark Brown * 2230cdfcc0fSMark Brown * Unregister a regulator registered with devm_regulator_register(). 2240cdfcc0fSMark Brown * Normally this function will not need to be called and the resource 2250cdfcc0fSMark Brown * management code will ensure that the resource is freed. 2260cdfcc0fSMark Brown */ 2270cdfcc0fSMark Brown void devm_regulator_unregister(struct device *dev, struct regulator_dev *rdev) 2280cdfcc0fSMark Brown { 2290cdfcc0fSMark Brown int rc; 2300cdfcc0fSMark Brown 2310cdfcc0fSMark Brown rc = devres_release(dev, devm_rdev_release, devm_rdev_match, rdev); 2320cdfcc0fSMark Brown if (rc != 0) 2330cdfcc0fSMark Brown WARN_ON(rc); 2340cdfcc0fSMark Brown } 2350cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_unregister); 236a06ccd9cSCharles Keepax 237a06ccd9cSCharles Keepax struct regulator_supply_alias_match { 238a06ccd9cSCharles Keepax struct device *dev; 239a06ccd9cSCharles Keepax const char *id; 240a06ccd9cSCharles Keepax }; 241a06ccd9cSCharles Keepax 242a06ccd9cSCharles Keepax static int devm_regulator_match_supply_alias(struct device *dev, void *res, 243a06ccd9cSCharles Keepax void *data) 244a06ccd9cSCharles Keepax { 245a06ccd9cSCharles Keepax struct regulator_supply_alias_match *match = res; 246a06ccd9cSCharles Keepax struct regulator_supply_alias_match *target = data; 247a06ccd9cSCharles Keepax 248a06ccd9cSCharles Keepax return match->dev == target->dev && strcmp(match->id, target->id) == 0; 249a06ccd9cSCharles Keepax } 250a06ccd9cSCharles Keepax 251a06ccd9cSCharles Keepax static void devm_regulator_destroy_supply_alias(struct device *dev, void *res) 252a06ccd9cSCharles Keepax { 253a06ccd9cSCharles Keepax struct regulator_supply_alias_match *match = res; 254a06ccd9cSCharles Keepax 255a06ccd9cSCharles Keepax regulator_unregister_supply_alias(match->dev, match->id); 256a06ccd9cSCharles Keepax } 257a06ccd9cSCharles Keepax 258a06ccd9cSCharles Keepax /** 259a06ccd9cSCharles Keepax * devm_regulator_register_supply_alias - Resource managed 260a06ccd9cSCharles Keepax * regulator_register_supply_alias() 261a06ccd9cSCharles Keepax * 262a7c15187SLee Jones * @dev: device to supply 263a7c15187SLee Jones * @id: supply name or regulator ID 264a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 265a7c15187SLee Jones * @alias_id: supply name or regulator ID that should be used to lookup the 266a06ccd9cSCharles Keepax * supply 267a06ccd9cSCharles Keepax * 268a06ccd9cSCharles Keepax * The supply alias will automatically be unregistered when the source 269a06ccd9cSCharles Keepax * device is unbound. 270a06ccd9cSCharles Keepax */ 271a06ccd9cSCharles Keepax int devm_regulator_register_supply_alias(struct device *dev, const char *id, 272a06ccd9cSCharles Keepax struct device *alias_dev, 273a06ccd9cSCharles Keepax const char *alias_id) 274a06ccd9cSCharles Keepax { 275a06ccd9cSCharles Keepax struct regulator_supply_alias_match *match; 276a06ccd9cSCharles Keepax int ret; 277a06ccd9cSCharles Keepax 278a06ccd9cSCharles Keepax match = devres_alloc(devm_regulator_destroy_supply_alias, 279a06ccd9cSCharles Keepax sizeof(struct regulator_supply_alias_match), 280a06ccd9cSCharles Keepax GFP_KERNEL); 281a06ccd9cSCharles Keepax if (!match) 282a06ccd9cSCharles Keepax return -ENOMEM; 283a06ccd9cSCharles Keepax 284a06ccd9cSCharles Keepax match->dev = dev; 285a06ccd9cSCharles Keepax match->id = id; 286a06ccd9cSCharles Keepax 287a06ccd9cSCharles Keepax ret = regulator_register_supply_alias(dev, id, alias_dev, alias_id); 288a06ccd9cSCharles Keepax if (ret < 0) { 289a06ccd9cSCharles Keepax devres_free(match); 290a06ccd9cSCharles Keepax return ret; 291a06ccd9cSCharles Keepax } 292a06ccd9cSCharles Keepax 293a06ccd9cSCharles Keepax devres_add(dev, match); 294a06ccd9cSCharles Keepax 295a06ccd9cSCharles Keepax return 0; 296a06ccd9cSCharles Keepax } 297a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_register_supply_alias); 298a06ccd9cSCharles Keepax 299a06ccd9cSCharles Keepax /** 300a06ccd9cSCharles Keepax * devm_regulator_unregister_supply_alias - Resource managed 301a06ccd9cSCharles Keepax * regulator_unregister_supply_alias() 302a06ccd9cSCharles Keepax * 303a7c15187SLee Jones * @dev: device to supply 304a7c15187SLee Jones * @id: supply name or regulator ID 305a06ccd9cSCharles Keepax * 306a06ccd9cSCharles Keepax * Unregister an alias registered with 307a06ccd9cSCharles Keepax * devm_regulator_register_supply_alias(). Normally this function 308a06ccd9cSCharles Keepax * will not need to be called and the resource management code 309a06ccd9cSCharles Keepax * will ensure that the resource is freed. 310a06ccd9cSCharles Keepax */ 311a06ccd9cSCharles Keepax void devm_regulator_unregister_supply_alias(struct device *dev, const char *id) 312a06ccd9cSCharles Keepax { 313a06ccd9cSCharles Keepax struct regulator_supply_alias_match match; 314a06ccd9cSCharles Keepax int rc; 315a06ccd9cSCharles Keepax 316a06ccd9cSCharles Keepax match.dev = dev; 317a06ccd9cSCharles Keepax match.id = id; 318a06ccd9cSCharles Keepax 319a06ccd9cSCharles Keepax rc = devres_release(dev, devm_regulator_destroy_supply_alias, 320a06ccd9cSCharles Keepax devm_regulator_match_supply_alias, &match); 321a06ccd9cSCharles Keepax if (rc != 0) 322a06ccd9cSCharles Keepax WARN_ON(rc); 323a06ccd9cSCharles Keepax } 324a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_unregister_supply_alias); 325a06ccd9cSCharles Keepax 326a06ccd9cSCharles Keepax /** 327a06ccd9cSCharles Keepax * devm_regulator_bulk_register_supply_alias - Managed register 328a06ccd9cSCharles Keepax * multiple aliases 329a06ccd9cSCharles Keepax * 330a7c15187SLee Jones * @dev: device to supply 331a7c15187SLee Jones * @id: list of supply names or regulator IDs 332a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 333a7c15187SLee Jones * @alias_id: list of supply names or regulator IDs that should be used to 334a06ccd9cSCharles Keepax * lookup the supply 335a7c15187SLee Jones * @num_id: number of aliases to register 336a06ccd9cSCharles Keepax * 337a06ccd9cSCharles Keepax * @return 0 on success, an errno on failure. 338a06ccd9cSCharles Keepax * 339a06ccd9cSCharles Keepax * This helper function allows drivers to register several supply 340a06ccd9cSCharles Keepax * aliases in one operation, the aliases will be automatically 341a06ccd9cSCharles Keepax * unregisters when the source device is unbound. If any of the 342a06ccd9cSCharles Keepax * aliases cannot be registered any aliases that were registered 343a06ccd9cSCharles Keepax * will be removed before returning to the caller. 344a06ccd9cSCharles Keepax */ 345a06ccd9cSCharles Keepax int devm_regulator_bulk_register_supply_alias(struct device *dev, 3469f8c0fe9SLee Jones const char *const *id, 347a06ccd9cSCharles Keepax struct device *alias_dev, 3489f8c0fe9SLee Jones const char *const *alias_id, 349a06ccd9cSCharles Keepax int num_id) 350a06ccd9cSCharles Keepax { 351a06ccd9cSCharles Keepax int i; 352a06ccd9cSCharles Keepax int ret; 353a06ccd9cSCharles Keepax 354a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) { 355a06ccd9cSCharles Keepax ret = devm_regulator_register_supply_alias(dev, id[i], 356a06ccd9cSCharles Keepax alias_dev, 357a06ccd9cSCharles Keepax alias_id[i]); 358a06ccd9cSCharles Keepax if (ret < 0) 359a06ccd9cSCharles Keepax goto err; 360a06ccd9cSCharles Keepax } 361a06ccd9cSCharles Keepax 362a06ccd9cSCharles Keepax return 0; 363a06ccd9cSCharles Keepax 364a06ccd9cSCharles Keepax err: 365a06ccd9cSCharles Keepax dev_err(dev, 366a06ccd9cSCharles Keepax "Failed to create supply alias %s,%s -> %s,%s\n", 367a06ccd9cSCharles Keepax id[i], dev_name(dev), alias_id[i], dev_name(alias_dev)); 368a06ccd9cSCharles Keepax 369a06ccd9cSCharles Keepax while (--i >= 0) 370a06ccd9cSCharles Keepax devm_regulator_unregister_supply_alias(dev, id[i]); 371a06ccd9cSCharles Keepax 372a06ccd9cSCharles Keepax return ret; 373a06ccd9cSCharles Keepax } 374a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_bulk_register_supply_alias); 375a06ccd9cSCharles Keepax 376a06ccd9cSCharles Keepax /** 377a06ccd9cSCharles Keepax * devm_regulator_bulk_unregister_supply_alias - Managed unregister 378a06ccd9cSCharles Keepax * multiple aliases 379a06ccd9cSCharles Keepax * 380a7c15187SLee Jones * @dev: device to supply 381a7c15187SLee Jones * @id: list of supply names or regulator IDs 382a7c15187SLee Jones * @num_id: number of aliases to unregister 383a06ccd9cSCharles Keepax * 384a06ccd9cSCharles Keepax * Unregister aliases registered with 385a06ccd9cSCharles Keepax * devm_regulator_bulk_register_supply_alias(). Normally this function 386a06ccd9cSCharles Keepax * will not need to be called and the resource management code 387a06ccd9cSCharles Keepax * will ensure that the resource is freed. 388a06ccd9cSCharles Keepax */ 389a06ccd9cSCharles Keepax void devm_regulator_bulk_unregister_supply_alias(struct device *dev, 3909f8c0fe9SLee Jones const char *const *id, 391a06ccd9cSCharles Keepax int num_id) 392a06ccd9cSCharles Keepax { 393a06ccd9cSCharles Keepax int i; 394a06ccd9cSCharles Keepax 395a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) 396a06ccd9cSCharles Keepax devm_regulator_unregister_supply_alias(dev, id[i]); 397a06ccd9cSCharles Keepax } 398a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_bulk_unregister_supply_alias); 399046db763SCharles Keepax 400046db763SCharles Keepax struct regulator_notifier_match { 401046db763SCharles Keepax struct regulator *regulator; 402046db763SCharles Keepax struct notifier_block *nb; 403046db763SCharles Keepax }; 404046db763SCharles Keepax 405046db763SCharles Keepax static int devm_regulator_match_notifier(struct device *dev, void *res, 406046db763SCharles Keepax void *data) 407046db763SCharles Keepax { 408046db763SCharles Keepax struct regulator_notifier_match *match = res; 409046db763SCharles Keepax struct regulator_notifier_match *target = data; 410046db763SCharles Keepax 411046db763SCharles Keepax return match->regulator == target->regulator && match->nb == target->nb; 412046db763SCharles Keepax } 413046db763SCharles Keepax 414046db763SCharles Keepax static void devm_regulator_destroy_notifier(struct device *dev, void *res) 415046db763SCharles Keepax { 416046db763SCharles Keepax struct regulator_notifier_match *match = res; 417046db763SCharles Keepax 418046db763SCharles Keepax regulator_unregister_notifier(match->regulator, match->nb); 419046db763SCharles Keepax } 420046db763SCharles Keepax 421046db763SCharles Keepax /** 422046db763SCharles Keepax * devm_regulator_register_notifier - Resource managed 423046db763SCharles Keepax * regulator_register_notifier 424046db763SCharles Keepax * 425046db763SCharles Keepax * @regulator: regulator source 426046db763SCharles Keepax * @nb: notifier block 427046db763SCharles Keepax * 428046db763SCharles Keepax * The notifier will be registers under the consumer device and be 429046db763SCharles Keepax * automatically be unregistered when the source device is unbound. 430046db763SCharles Keepax */ 431046db763SCharles Keepax int devm_regulator_register_notifier(struct regulator *regulator, 432046db763SCharles Keepax struct notifier_block *nb) 433046db763SCharles Keepax { 434046db763SCharles Keepax struct regulator_notifier_match *match; 435046db763SCharles Keepax int ret; 436046db763SCharles Keepax 437046db763SCharles Keepax match = devres_alloc(devm_regulator_destroy_notifier, 438046db763SCharles Keepax sizeof(struct regulator_notifier_match), 439046db763SCharles Keepax GFP_KERNEL); 440046db763SCharles Keepax if (!match) 441046db763SCharles Keepax return -ENOMEM; 442046db763SCharles Keepax 443046db763SCharles Keepax match->regulator = regulator; 444046db763SCharles Keepax match->nb = nb; 445046db763SCharles Keepax 446046db763SCharles Keepax ret = regulator_register_notifier(regulator, nb); 447046db763SCharles Keepax if (ret < 0) { 448046db763SCharles Keepax devres_free(match); 449046db763SCharles Keepax return ret; 450046db763SCharles Keepax } 451046db763SCharles Keepax 452046db763SCharles Keepax devres_add(regulator->dev, match); 453046db763SCharles Keepax 454046db763SCharles Keepax return 0; 455046db763SCharles Keepax } 456046db763SCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_register_notifier); 457046db763SCharles Keepax 458046db763SCharles Keepax /** 459046db763SCharles Keepax * devm_regulator_unregister_notifier - Resource managed 460046db763SCharles Keepax * regulator_unregister_notifier() 461046db763SCharles Keepax * 462046db763SCharles Keepax * @regulator: regulator source 463046db763SCharles Keepax * @nb: notifier block 464046db763SCharles Keepax * 465046db763SCharles Keepax * Unregister a notifier registered with devm_regulator_register_notifier(). 466046db763SCharles Keepax * Normally this function will not need to be called and the resource 467046db763SCharles Keepax * management code will ensure that the resource is freed. 468046db763SCharles Keepax */ 469046db763SCharles Keepax void devm_regulator_unregister_notifier(struct regulator *regulator, 470046db763SCharles Keepax struct notifier_block *nb) 471046db763SCharles Keepax { 472046db763SCharles Keepax struct regulator_notifier_match match; 473046db763SCharles Keepax int rc; 474046db763SCharles Keepax 475046db763SCharles Keepax match.regulator = regulator; 476046db763SCharles Keepax match.nb = nb; 477046db763SCharles Keepax 478046db763SCharles Keepax rc = devres_release(regulator->dev, devm_regulator_destroy_notifier, 479046db763SCharles Keepax devm_regulator_match_notifier, &match); 480046db763SCharles Keepax if (rc != 0) 481046db763SCharles Keepax WARN_ON(rc); 482046db763SCharles Keepax } 483046db763SCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_unregister_notifier); 484