diff options
| -rw-r--r-- | Documentation/driver-model/devres.txt | 5 | ||||
| -rw-r--r-- | drivers/regulator/core.c | 108 | ||||
| -rw-r--r-- | include/linux/regulator/consumer.h | 22 |
3 files changed, 135 insertions, 0 deletions
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index 41c0c5d1ba1..2a596a4fc23 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt | |||
| @@ -271,3 +271,8 @@ IOMAP | |||
| 271 | pcim_iounmap() | 271 | pcim_iounmap() |
| 272 | pcim_iomap_table() : array of mapped addresses indexed by BAR | 272 | pcim_iomap_table() : array of mapped addresses indexed by BAR |
| 273 | pcim_iomap_regions() : do request_region() and iomap() on multiple BARs | 273 | pcim_iomap_regions() : do request_region() and iomap() on multiple BARs |
| 274 | |||
| 275 | REGULATOR | ||
| 276 | devm_regulator_get() | ||
| 277 | devm_regulator_put() | ||
| 278 | devm_regulator_bulk_get() | ||
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 8f11d0eb59a..f4d31830f12 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c | |||
| @@ -1316,6 +1316,40 @@ struct regulator *regulator_get(struct device *dev, const char *id) | |||
| 1316 | } | 1316 | } |
| 1317 | EXPORT_SYMBOL_GPL(regulator_get); | 1317 | EXPORT_SYMBOL_GPL(regulator_get); |
| 1318 | 1318 | ||
| 1319 | static void devm_regulator_release(struct device *dev, void *res) | ||
| 1320 | { | ||
| 1321 | regulator_put(*(struct regulator **)res); | ||
| 1322 | } | ||
| 1323 | |||
| 1324 | /** | ||
| 1325 | * devm_regulator_get - Resource managed regulator_get() | ||
| 1326 | * @dev: device for regulator "consumer" | ||
| 1327 | * @id: Supply name or regulator ID. | ||
| 1328 | * | ||
| 1329 | * Managed regulator_get(). Regulators returned from this function are | ||
| 1330 | * automatically regulator_put() on driver detach. See regulator_get() for more | ||
| 1331 | * information. | ||
| 1332 | */ | ||
| 1333 | struct regulator *devm_regulator_get(struct device *dev, const char *id) | ||
| 1334 | { | ||
| 1335 | struct regulator **ptr, *regulator; | ||
| 1336 | |||
| 1337 | ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL); | ||
| 1338 | if (!ptr) | ||
| 1339 | return ERR_PTR(-ENOMEM); | ||
| 1340 | |||
| 1341 | regulator = regulator_get(dev, id); | ||
| 1342 | if (!IS_ERR(regulator)) { | ||
| 1343 | *ptr = regulator; | ||
| 1344 | devres_add(dev, ptr); | ||
| 1345 | } else { | ||
| 1346 | devres_free(ptr); | ||
| 1347 | } | ||
| 1348 | |||
| 1349 | return regulator; | ||
| 1350 | } | ||
| 1351 | EXPORT_SYMBOL_GPL(devm_regulator_get); | ||
| 1352 | |||
| 1319 | /** | 1353 | /** |
| 1320 | * regulator_get_exclusive - obtain exclusive access to a regulator. | 1354 | * regulator_get_exclusive - obtain exclusive access to a regulator. |
| 1321 | * @dev: device for regulator "consumer" | 1355 | * @dev: device for regulator "consumer" |
| @@ -1381,6 +1415,34 @@ void regulator_put(struct regulator *regulator) | |||
| 1381 | } | 1415 | } |
| 1382 | EXPORT_SYMBOL_GPL(regulator_put); | 1416 | EXPORT_SYMBOL_GPL(regulator_put); |
| 1383 | 1417 | ||
| 1418 | static int devm_regulator_match(struct device *dev, void *res, void *data) | ||
| 1419 | { | ||
| 1420 | struct regulator **r = res; | ||
| 1421 | if (!r || !*r) { | ||
| 1422 | WARN_ON(!r || !*r); | ||
| 1423 | return 0; | ||
| 1424 | } | ||
| 1425 | return *r == data; | ||
| 1426 | } | ||
| 1427 | |||
| 1428 | /** | ||
| 1429 | * devm_regulator_put - Resource managed regulator_put() | ||
| 1430 | * @regulator: regulator to free | ||
| 1431 | * | ||
| 1432 | * Deallocate a regulator allocated with devm_regulator_get(). Normally | ||
| 1433 | * this function will not need to be called and the resource management | ||
| 1434 | * code will ensure that the resource is freed. | ||
| 1435 | */ | ||
| 1436 | void devm_regulator_put(struct regulator *regulator) | ||
| 1437 | { | ||
| 1438 | int rc; | ||
| 1439 | |||
| 1440 | rc = devres_destroy(regulator->dev, devm_regulator_release, | ||
| 1441 | devm_regulator_match, regulator); | ||
| 1442 | WARN_ON(rc); | ||
| 1443 | } | ||
| 1444 | EXPORT_SYMBOL_GPL(devm_regulator_put); | ||
| 1445 | |||
| 1384 | static int _regulator_can_change_status(struct regulator_dev *rdev) | 1446 | static int _regulator_can_change_status(struct regulator_dev *rdev) |
| 1385 | { | 1447 | { |
| 1386 | if (!rdev->constraints) | 1448 | if (!rdev->constraints) |
| @@ -2399,6 +2461,52 @@ err: | |||
| 2399 | } | 2461 | } |
| 2400 | EXPORT_SYMBOL_GPL(regulator_bulk_get); | 2462 | EXPORT_SYMBOL_GPL(regulator_bulk_get); |
| 2401 | 2463 | ||
| 2464 | /** | ||
| 2465 | * devm_regulator_bulk_get - managed get multiple regulator consumers | ||
| 2466 | * | ||
| 2467 | * @dev: Device to supply | ||
| 2468 | * @num_consumers: Number of consumers to register | ||
| 2469 | * @consumers: Configuration of consumers; clients are stored here. | ||
| 2470 | * | ||
| 2471 | * @return 0 on success, an errno on failure. | ||
| 2472 | * | ||
| 2473 | * This helper function allows drivers to get several regulator | ||
| 2474 | * consumers in one operation with management, the regulators will | ||
| 2475 | * automatically be freed when the device is unbound. If any of the | ||
| 2476 | * regulators cannot be acquired then any regulators that were | ||
| 2477 | * allocated will be freed before returning to the caller. | ||
| 2478 | */ | ||
| 2479 | int devm_regulator_bulk_get(struct device *dev, int num_consumers, | ||
| 2480 | struct regulator_bulk_data *consumers) | ||
| 2481 | { | ||
| 2482 | int i; | ||
| 2483 | int ret; | ||
| 2484 | |||
| 2485 | for (i = 0; i < num_consumers; i++) | ||
| 2486 | consumers[i].consumer = NULL; | ||
| 2487 | |||
| 2488 | for (i = 0; i < num_consumers; i++) { | ||
| 2489 | consumers[i].consumer = devm_regulator_get(dev, | ||
| 2490 | consumers[i].supply); | ||
| 2491 | if (IS_ERR(consumers[i].consumer)) { | ||
| 2492 | ret = PTR_ERR(consumers[i].consumer); | ||
| 2493 | dev_err(dev, "Failed to get supply '%s': %d\n", | ||
| 2494 | consumers[i].supply, ret); | ||
| 2495 | consumers[i].consumer = NULL; | ||
| 2496 | goto err; | ||
| 2497 | } | ||
| 2498 | } | ||
| 2499 | |||
| 2500 | return 0; | ||
| 2501 | |||
| 2502 | err: | ||
| 2503 | for (i = 0; i < num_consumers && consumers[i].consumer; i++) | ||
| 2504 | devm_regulator_put(consumers[i].consumer); | ||
| 2505 | |||
| 2506 | return ret; | ||
| 2507 | } | ||
| 2508 | EXPORT_SYMBOL_GPL(devm_regulator_bulk_get); | ||
| 2509 | |||
| 2402 | static void regulator_bulk_enable_async(void *data, async_cookie_t cookie) | 2510 | static void regulator_bulk_enable_async(void *data, async_cookie_t cookie) |
| 2403 | { | 2511 | { |
| 2404 | struct regulator_bulk_data *bulk = data; | 2512 | struct regulator_bulk_data *bulk = data; |
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index f2698a0edfc..b6c8d717c7e 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h | |||
| @@ -132,9 +132,12 @@ struct regulator_bulk_data { | |||
| 132 | /* regulator get and put */ | 132 | /* regulator get and put */ |
| 133 | struct regulator *__must_check regulator_get(struct device *dev, | 133 | struct regulator *__must_check regulator_get(struct device *dev, |
| 134 | const char *id); | 134 | const char *id); |
| 135 | struct regulator *__must_check devm_regulator_get(struct device *dev, | ||
| 136 | const char *id); | ||
| 135 | struct regulator *__must_check regulator_get_exclusive(struct device *dev, | 137 | struct regulator *__must_check regulator_get_exclusive(struct device *dev, |
| 136 | const char *id); | 138 | const char *id); |
| 137 | void regulator_put(struct regulator *regulator); | 139 | void regulator_put(struct regulator *regulator); |
| 140 | void devm_regulator_put(struct regulator *regulator); | ||
| 138 | 141 | ||
| 139 | /* regulator output control and status */ | 142 | /* regulator output control and status */ |
| 140 | int regulator_enable(struct regulator *regulator); | 143 | int regulator_enable(struct regulator *regulator); |
| @@ -145,6 +148,8 @@ int regulator_disable_deferred(struct regulator *regulator, int ms); | |||
| 145 | 148 | ||
| 146 | int regulator_bulk_get(struct device *dev, int num_consumers, | 149 | int regulator_bulk_get(struct device *dev, int num_consumers, |
| 147 | struct regulator_bulk_data *consumers); | 150 | struct regulator_bulk_data *consumers); |
| 151 | int devm_regulator_bulk_get(struct device *dev, int num_consumers, | ||
| 152 | struct regulator_bulk_data *consumers); | ||
| 148 | int regulator_bulk_enable(int num_consumers, | 153 | int regulator_bulk_enable(int num_consumers, |
| 149 | struct regulator_bulk_data *consumers); | 154 | struct regulator_bulk_data *consumers); |
| 150 | int regulator_bulk_disable(int num_consumers, | 155 | int regulator_bulk_disable(int num_consumers, |
| @@ -200,10 +205,21 @@ static inline struct regulator *__must_check regulator_get(struct device *dev, | |||
| 200 | */ | 205 | */ |
| 201 | return NULL; | 206 | return NULL; |
| 202 | } | 207 | } |
| 208 | |||
| 209 | static inline struct regulator *__must_check | ||
| 210 | devm_regulator_get(struct device *dev, const char *id) | ||
| 211 | { | ||
| 212 | return NULL; | ||
| 213 | } | ||
| 214 | |||
| 203 | static inline void regulator_put(struct regulator *regulator) | 215 | static inline void regulator_put(struct regulator *regulator) |
| 204 | { | 216 | { |
| 205 | } | 217 | } |
| 206 | 218 | ||
| 219 | static inline void devm_regulator_put(struct regulator *regulator) | ||
| 220 | { | ||
| 221 | } | ||
| 222 | |||
| 207 | static inline int regulator_enable(struct regulator *regulator) | 223 | static inline int regulator_enable(struct regulator *regulator) |
| 208 | { | 224 | { |
| 209 | return 0; | 225 | return 0; |
| @@ -237,6 +253,12 @@ static inline int regulator_bulk_get(struct device *dev, | |||
| 237 | return 0; | 253 | return 0; |
| 238 | } | 254 | } |
| 239 | 255 | ||
| 256 | static inline int devm_regulator_bulk_get(struct device *dev, int num_consumers, | ||
| 257 | struct regulator_bulk_data *consumers) | ||
| 258 | { | ||
| 259 | return 0; | ||
| 260 | } | ||
| 261 | |||
| 240 | static inline int regulator_bulk_enable(int num_consumers, | 262 | static inline int regulator_bulk_enable(int num_consumers, |
| 241 | struct regulator_bulk_data *consumers) | 263 | struct regulator_bulk_data *consumers) |
| 242 | { | 264 | { |
