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 41c0c5d1ba14..2a596a4fc23e 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 8f11d0eb59a5..f4d31830f12b 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 f2698a0edfc4..b6c8d717c7ec 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 | { |