mirror of
https://github.com/nxp-imx/linux-imx.git
synced 2025-07-12 20:35:23 +02:00
regulator: Add devm helpers for get and enable
A few regulator consumer drivers seem to be just getting a regulator, enabling it and registering a devm-action to disable the regulator at the driver detach and then forget about it. We can simplify this a bit by adding a devm-helper for this pattern. Add devm_regulator_get_enable() and devm_regulator_get_enable_optional() Signed-off-by: Matti Vaittinen <mazziesaccount@gmail.com> Link: https://lore.kernel.org/r/ed7b8841193bb9749d426f3cb3b199c9460794cd.1660292316.git.mazziesaccount@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
568035b01c
commit
da279e6965
|
@ -70,6 +70,65 @@ struct regulator *devm_regulator_get_exclusive(struct device *dev,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(devm_regulator_get_exclusive);
|
EXPORT_SYMBOL_GPL(devm_regulator_get_exclusive);
|
||||||
|
|
||||||
|
static void regulator_action_disable(void *d)
|
||||||
|
{
|
||||||
|
struct regulator *r = (struct regulator *)d;
|
||||||
|
|
||||||
|
regulator_disable(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _devm_regulator_get_enable(struct device *dev, const char *id,
|
||||||
|
int get_type)
|
||||||
|
{
|
||||||
|
struct regulator *r;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
r = _devm_regulator_get(dev, id, get_type);
|
||||||
|
if (IS_ERR(r))
|
||||||
|
return PTR_ERR(r);
|
||||||
|
|
||||||
|
ret = regulator_enable(r);
|
||||||
|
if (!ret)
|
||||||
|
ret = devm_add_action_or_reset(dev, ®ulator_action_disable, r);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
devm_regulator_put(r);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* devm_regulator_get_enable_optional - Resource managed regulator get and enable
|
||||||
|
* @dev: device to supply
|
||||||
|
* @id: supply name or regulator ID.
|
||||||
|
*
|
||||||
|
* Get and enable regulator for duration of the device life-time.
|
||||||
|
* regulator_disable() and regulator_put() are automatically called on driver
|
||||||
|
* detach. See regulator_get_optional() and regulator_enable() for more
|
||||||
|
* information.
|
||||||
|
*/
|
||||||
|
int devm_regulator_get_enable_optional(struct device *dev, const char *id)
|
||||||
|
{
|
||||||
|
return _devm_regulator_get_enable(dev, id, OPTIONAL_GET);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(devm_regulator_get_enable_optional);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* devm_regulator_get_enable - Resource managed regulator get and enable
|
||||||
|
* @dev: device to supply
|
||||||
|
* @id: supply name or regulator ID.
|
||||||
|
*
|
||||||
|
* Get and enable regulator for duration of the device life-time.
|
||||||
|
* regulator_disable() and regulator_put() are automatically called on driver
|
||||||
|
* detach. See regulator_get() and regulator_enable() for more
|
||||||
|
* information.
|
||||||
|
*/
|
||||||
|
int devm_regulator_get_enable(struct device *dev, const char *id)
|
||||||
|
{
|
||||||
|
return _devm_regulator_get_enable(dev, id, NORMAL_GET);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(devm_regulator_get_enable);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* devm_regulator_get_optional - Resource managed regulator_get_optional()
|
* devm_regulator_get_optional - Resource managed regulator_get_optional()
|
||||||
* @dev: device to supply
|
* @dev: device to supply
|
||||||
|
@ -194,6 +253,111 @@ int devm_regulator_bulk_get_const(struct device *dev, int num_consumers,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(devm_regulator_bulk_get_const);
|
EXPORT_SYMBOL_GPL(devm_regulator_bulk_get_const);
|
||||||
|
|
||||||
|
static int devm_regulator_bulk_match(struct device *dev, void *res,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
struct regulator_bulk_devres *match = res;
|
||||||
|
struct regulator_bulk_data *target = data;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We check the put uses same consumer list as the get did.
|
||||||
|
* We _could_ scan all entries in consumer array and check the
|
||||||
|
* regulators match but ATM I don't see the need. We can change this
|
||||||
|
* later if needed.
|
||||||
|
*/
|
||||||
|
return match->consumers == target;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* devm_regulator_bulk_put - Resource managed regulator_bulk_put()
|
||||||
|
* @consumers: consumers to free
|
||||||
|
*
|
||||||
|
* Deallocate regulators allocated with devm_regulator_bulk_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_bulk_put(struct regulator_bulk_data *consumers)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
struct regulator *regulator = consumers[0].consumer;
|
||||||
|
|
||||||
|
rc = devres_release(regulator->dev, devm_regulator_bulk_release,
|
||||||
|
devm_regulator_bulk_match, consumers);
|
||||||
|
if (rc != 0)
|
||||||
|
WARN_ON(rc);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(devm_regulator_bulk_put);
|
||||||
|
|
||||||
|
static void devm_regulator_bulk_disable(void *res)
|
||||||
|
{
|
||||||
|
struct regulator_bulk_devres *devres = res;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < devres->num_consumers; i++)
|
||||||
|
regulator_disable(devres->consumers[i].consumer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* devm_regulator_bulk_get_enable - managed get'n enable multiple regulators
|
||||||
|
*
|
||||||
|
* @dev: device to supply
|
||||||
|
* @num_consumers: number of consumers to register
|
||||||
|
* @id: list of supply names or regulator IDs
|
||||||
|
*
|
||||||
|
* @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_enable(struct device *dev, int num_consumers,
|
||||||
|
const char * const *id)
|
||||||
|
{
|
||||||
|
struct regulator_bulk_devres *devres;
|
||||||
|
struct regulator_bulk_data *consumers;
|
||||||
|
int i, ret;
|
||||||
|
|
||||||
|
devres = devm_kmalloc(dev, sizeof(*devres), GFP_KERNEL);
|
||||||
|
if (!devres)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
devres->consumers = devm_kcalloc(dev, num_consumers, sizeof(*consumers),
|
||||||
|
GFP_KERNEL);
|
||||||
|
consumers = devres->consumers;
|
||||||
|
if (!consumers)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
devres->num_consumers = num_consumers;
|
||||||
|
|
||||||
|
for (i = 0; i < num_consumers; i++)
|
||||||
|
consumers[i].supply = id[i];
|
||||||
|
|
||||||
|
ret = devm_regulator_bulk_get(dev, num_consumers, consumers);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
for (i = 0; i < num_consumers; i++) {
|
||||||
|
ret = regulator_enable(consumers[i].consumer);
|
||||||
|
if (ret)
|
||||||
|
goto unwind;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = devm_add_action(dev, devm_regulator_bulk_disable, devres);
|
||||||
|
if (!ret)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
unwind:
|
||||||
|
while (--i >= 0)
|
||||||
|
regulator_disable(consumers[i].consumer);
|
||||||
|
|
||||||
|
devm_regulator_bulk_put(consumers);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(devm_regulator_bulk_get_enable);
|
||||||
|
|
||||||
static void devm_rdev_release(struct device *dev, void *res)
|
static void devm_rdev_release(struct device *dev, void *res)
|
||||||
{
|
{
|
||||||
regulator_unregister(*(struct regulator_dev **)res);
|
regulator_unregister(*(struct regulator_dev **)res);
|
||||||
|
|
|
@ -207,6 +207,8 @@ struct regulator *__must_check regulator_get_optional(struct device *dev,
|
||||||
const char *id);
|
const char *id);
|
||||||
struct regulator *__must_check devm_regulator_get_optional(struct device *dev,
|
struct regulator *__must_check devm_regulator_get_optional(struct device *dev,
|
||||||
const char *id);
|
const char *id);
|
||||||
|
int devm_regulator_get_enable(struct device *dev, const char *id);
|
||||||
|
int devm_regulator_get_enable_optional(struct device *dev, const char *id);
|
||||||
void regulator_put(struct regulator *regulator);
|
void regulator_put(struct regulator *regulator);
|
||||||
void devm_regulator_put(struct regulator *regulator);
|
void devm_regulator_put(struct regulator *regulator);
|
||||||
|
|
||||||
|
@ -244,12 +246,15 @@ int __must_check regulator_bulk_get(struct device *dev, int num_consumers,
|
||||||
struct regulator_bulk_data *consumers);
|
struct regulator_bulk_data *consumers);
|
||||||
int __must_check devm_regulator_bulk_get(struct device *dev, int num_consumers,
|
int __must_check devm_regulator_bulk_get(struct device *dev, int num_consumers,
|
||||||
struct regulator_bulk_data *consumers);
|
struct regulator_bulk_data *consumers);
|
||||||
|
void devm_regulator_bulk_put(struct regulator_bulk_data *consumers);
|
||||||
int __must_check devm_regulator_bulk_get_const(
|
int __must_check devm_regulator_bulk_get_const(
|
||||||
struct device *dev, int num_consumers,
|
struct device *dev, int num_consumers,
|
||||||
const struct regulator_bulk_data *in_consumers,
|
const struct regulator_bulk_data *in_consumers,
|
||||||
struct regulator_bulk_data **out_consumers);
|
struct regulator_bulk_data **out_consumers);
|
||||||
int __must_check regulator_bulk_enable(int num_consumers,
|
int __must_check regulator_bulk_enable(int num_consumers,
|
||||||
struct regulator_bulk_data *consumers);
|
struct regulator_bulk_data *consumers);
|
||||||
|
int devm_regulator_bulk_get_enable(struct device *dev, int num_consumers,
|
||||||
|
const char * const *id);
|
||||||
int regulator_bulk_disable(int num_consumers,
|
int regulator_bulk_disable(int num_consumers,
|
||||||
struct regulator_bulk_data *consumers);
|
struct regulator_bulk_data *consumers);
|
||||||
int regulator_bulk_force_disable(int num_consumers,
|
int regulator_bulk_force_disable(int num_consumers,
|
||||||
|
@ -354,6 +359,17 @@ devm_regulator_get_exclusive(struct device *dev, const char *id)
|
||||||
return ERR_PTR(-ENODEV);
|
return ERR_PTR(-ENODEV);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int devm_regulator_get_enable(struct device *dev, const char *id)
|
||||||
|
{
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int devm_regulator_get_enable_optional(struct device *dev,
|
||||||
|
const char *id)
|
||||||
|
{
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
static inline struct regulator *__must_check
|
static inline struct regulator *__must_check
|
||||||
regulator_get_optional(struct device *dev, const char *id)
|
regulator_get_optional(struct device *dev, const char *id)
|
||||||
{
|
{
|
||||||
|
@ -375,6 +391,10 @@ static inline void devm_regulator_put(struct regulator *regulator)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void devm_regulator_bulk_put(struct regulator_bulk_data *consumers)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static inline int regulator_register_supply_alias(struct device *dev,
|
static inline int regulator_register_supply_alias(struct device *dev,
|
||||||
const char *id,
|
const char *id,
|
||||||
struct device *alias_dev,
|
struct device *alias_dev,
|
||||||
|
@ -465,6 +485,13 @@ static inline int regulator_bulk_enable(int num_consumers,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int devm_regulator_bulk_get_enable(struct device *dev,
|
||||||
|
int num_consumers,
|
||||||
|
const char * const *id)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int regulator_bulk_disable(int num_consumers,
|
static inline int regulator_bulk_disable(int num_consumers,
|
||||||
struct regulator_bulk_data *consumers)
|
struct regulator_bulk_data *consumers)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue
Block a user