Provide managed versions of regulator_get() and regulator_bulk_get(),
saving code in error handling and cleanup paths by ensuring that that the regulators will be automatically unregistered when the device is unregistered. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJPITWJAAoJEBus8iNuMP3defMP/0rHwUk/XEVZHj0OLdA6r33f mDATRNX40BAllDUinYyrEWBhEFDWSxJQ1lA6iustO529gkd66j0n24g702GdRnvQ Hh2tFS73lmU75JrdTKprVQVV1P0vwDPtm9BbWCbpKl1TJ77z396KrzrO+pHqEVdQ FkPweqqGhwBcA/FHy8k8nGiMWk/6pMIbOkaaWRtxCtMxhC05qKOpL90VOEwut2Hb 0SL5QQUgYCjYzuIqdcOWBrgYcxt7COAS3Z0etgEgSIISdBa38SygRqiLnRZ1AqgX gWb7/+v3ont+PEEbjo4wsmO9anGamIUaHY449KKTY6EJnJxbJt6Z4wB86dT9C35s l3BjwCfROa+hs0HOS08ake9/y51dpIqiv+T5+jiY+h5dyt+lPxBRAZiVKP2jUo09 5womi/gt9loy37iQRkMVCGK5ZBnyFet+KpCPYR0Bx3mjBt/O4sqGniZBN7FUx5KS ZDBzVFihKLxLFP5xCWi5+Z/sr+wiCGSLKelawznavYCUzo0WYfUo6UrBR2r8U2QI 2xSE5qzRBLqvdwi/2NQnj/5kbuzv2iiOPAR2PZhwgWPxc0yj1icWCu8d2voKILag 1I7qGAKaA0E/CXveaf/xlWEFMpuyE+THvXlE2q9s+giV9+DRcEXMbr3uX26xh4Vl vwPSfBApJLg7FerS6Lmj =Sj0B -----END PGP SIGNATURE----- Merge tag 'topic/devm' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator into HEAD Provide managed versions of regulator_get() and regulator_bulk_get(), saving code in error handling and cleanup paths by ensuring that that the regulators will be automatically unregistered when the device is unregistered.
This commit is contained in:
commit
e8f00041a6
@ -267,3 +267,6 @@ IOMAP
|
|||||||
pcim_iounmap()
|
pcim_iounmap()
|
||||||
pcim_iomap_table() : array of mapped addresses indexed by BAR
|
pcim_iomap_table() : array of mapped addresses indexed by BAR
|
||||||
pcim_iomap_regions() : do request_region() and iomap() on multiple BARs
|
pcim_iomap_regions() : do request_region() and iomap() on multiple BARs
|
||||||
|
|
||||||
|
REGULATOR
|
||||||
|
devm_regulator_get()
|
||||||
|
@ -1320,6 +1320,40 @@ struct regulator *regulator_get(struct device *dev, const char *id)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(regulator_get);
|
EXPORT_SYMBOL_GPL(regulator_get);
|
||||||
|
|
||||||
|
static void devm_regulator_release(struct device *dev, void *res)
|
||||||
|
{
|
||||||
|
regulator_put(*(struct regulator **)res);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* devm_regulator_get - Resource managed regulator_get()
|
||||||
|
* @dev: device for regulator "consumer"
|
||||||
|
* @id: Supply name or regulator ID.
|
||||||
|
*
|
||||||
|
* Managed regulator_get(). Regulators returned from this function are
|
||||||
|
* automatically regulator_put() on driver detach. See regulator_get() for more
|
||||||
|
* information.
|
||||||
|
*/
|
||||||
|
struct regulator *devm_regulator_get(struct device *dev, const char *id)
|
||||||
|
{
|
||||||
|
struct regulator **ptr, *regulator;
|
||||||
|
|
||||||
|
ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
|
||||||
|
if (!ptr)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
regulator = regulator_get(dev, id);
|
||||||
|
if (!IS_ERR(regulator)) {
|
||||||
|
*ptr = regulator;
|
||||||
|
devres_add(dev, ptr);
|
||||||
|
} else {
|
||||||
|
devres_free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return regulator;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(devm_regulator_get);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* regulator_get_exclusive - obtain exclusive access to a regulator.
|
* regulator_get_exclusive - obtain exclusive access to a regulator.
|
||||||
* @dev: device for regulator "consumer"
|
* @dev: device for regulator "consumer"
|
||||||
@ -1387,6 +1421,34 @@ void regulator_put(struct regulator *regulator)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(regulator_put);
|
EXPORT_SYMBOL_GPL(regulator_put);
|
||||||
|
|
||||||
|
static int devm_regulator_match(struct device *dev, void *res, void *data)
|
||||||
|
{
|
||||||
|
struct regulator **r = res;
|
||||||
|
if (!r || !*r) {
|
||||||
|
WARN_ON(!r || !*r);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return *r == data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* devm_regulator_put - Resource managed regulator_put()
|
||||||
|
* @regulator: regulator to free
|
||||||
|
*
|
||||||
|
* Deallocate a regulator allocated with devm_regulator_get(). Normally
|
||||||
|
* this function will not need to be called and the resource management
|
||||||
|
* code will ensure that the resource is freed.
|
||||||
|
*/
|
||||||
|
void devm_regulator_put(struct regulator *regulator)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = devres_destroy(regulator->dev, devm_regulator_release,
|
||||||
|
devm_regulator_match, regulator);
|
||||||
|
WARN_ON(rc);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(devm_regulator_put);
|
||||||
|
|
||||||
static int _regulator_can_change_status(struct regulator_dev *rdev)
|
static int _regulator_can_change_status(struct regulator_dev *rdev)
|
||||||
{
|
{
|
||||||
if (!rdev->constraints)
|
if (!rdev->constraints)
|
||||||
@ -2401,6 +2463,52 @@ err:
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(regulator_bulk_get);
|
EXPORT_SYMBOL_GPL(regulator_bulk_get);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* devm_regulator_bulk_get - managed get multiple regulator consumers
|
||||||
|
*
|
||||||
|
* @dev: Device to supply
|
||||||
|
* @num_consumers: Number of consumers to register
|
||||||
|
* @consumers: Configuration of consumers; clients are stored here.
|
||||||
|
*
|
||||||
|
* @return 0 on success, an errno on failure.
|
||||||
|
*
|
||||||
|
* This helper function allows drivers to get several regulator
|
||||||
|
* consumers in one operation with management, the regulators will
|
||||||
|
* automatically be freed when the device is unbound. If any of the
|
||||||
|
* regulators cannot be acquired then any regulators that were
|
||||||
|
* allocated will be freed before returning to the caller.
|
||||||
|
*/
|
||||||
|
int devm_regulator_bulk_get(struct device *dev, int num_consumers,
|
||||||
|
struct regulator_bulk_data *consumers)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
for (i = 0; i < num_consumers; i++)
|
||||||
|
consumers[i].consumer = NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < num_consumers; i++) {
|
||||||
|
consumers[i].consumer = devm_regulator_get(dev,
|
||||||
|
consumers[i].supply);
|
||||||
|
if (IS_ERR(consumers[i].consumer)) {
|
||||||
|
ret = PTR_ERR(consumers[i].consumer);
|
||||||
|
dev_err(dev, "Failed to get supply '%s': %d\n",
|
||||||
|
consumers[i].supply, ret);
|
||||||
|
consumers[i].consumer = NULL;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
for (i = 0; i < num_consumers && consumers[i].consumer; i++)
|
||||||
|
devm_regulator_put(consumers[i].consumer);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(devm_regulator_bulk_get);
|
||||||
|
|
||||||
static void regulator_bulk_enable_async(void *data, async_cookie_t cookie)
|
static void regulator_bulk_enable_async(void *data, async_cookie_t cookie)
|
||||||
{
|
{
|
||||||
struct regulator_bulk_data *bulk = data;
|
struct regulator_bulk_data *bulk = data;
|
||||||
|
@ -132,9 +132,12 @@ struct regulator_bulk_data {
|
|||||||
/* regulator get and put */
|
/* regulator get and put */
|
||||||
struct regulator *__must_check regulator_get(struct device *dev,
|
struct regulator *__must_check regulator_get(struct device *dev,
|
||||||
const char *id);
|
const char *id);
|
||||||
|
struct regulator *__must_check devm_regulator_get(struct device *dev,
|
||||||
|
const char *id);
|
||||||
struct regulator *__must_check regulator_get_exclusive(struct device *dev,
|
struct regulator *__must_check regulator_get_exclusive(struct device *dev,
|
||||||
const char *id);
|
const char *id);
|
||||||
void regulator_put(struct regulator *regulator);
|
void regulator_put(struct regulator *regulator);
|
||||||
|
void devm_regulator_free(struct regulator *regulator);
|
||||||
|
|
||||||
/* regulator output control and status */
|
/* regulator output control and status */
|
||||||
int regulator_enable(struct regulator *regulator);
|
int regulator_enable(struct regulator *regulator);
|
||||||
@ -145,6 +148,8 @@ int regulator_disable_deferred(struct regulator *regulator, int ms);
|
|||||||
|
|
||||||
int regulator_bulk_get(struct device *dev, int num_consumers,
|
int regulator_bulk_get(struct device *dev, int num_consumers,
|
||||||
struct regulator_bulk_data *consumers);
|
struct regulator_bulk_data *consumers);
|
||||||
|
int devm_regulator_bulk_get(struct device *dev, int num_consumers,
|
||||||
|
struct regulator_bulk_data *consumers);
|
||||||
int regulator_bulk_enable(int num_consumers,
|
int regulator_bulk_enable(int num_consumers,
|
||||||
struct regulator_bulk_data *consumers);
|
struct regulator_bulk_data *consumers);
|
||||||
int regulator_bulk_disable(int num_consumers,
|
int regulator_bulk_disable(int num_consumers,
|
||||||
@ -200,6 +205,13 @@ static inline struct regulator *__must_check regulator_get(struct device *dev,
|
|||||||
*/
|
*/
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline struct regulator *__must_check
|
||||||
|
devm_regulator_get(struct device *dev, const char *id)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void regulator_put(struct regulator *regulator)
|
static inline void regulator_put(struct regulator *regulator)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user