diff options
| -rw-r--r-- | Documentation/driver-api/driver-model/devres.rst | 1 | ||||
| -rw-r--r-- | drivers/regulator/devres.c | 59 | ||||
| -rw-r--r-- | include/linux/regulator/consumer.h | 7 | 
3 files changed, 67 insertions, 0 deletions
| diff --git a/Documentation/driver-api/driver-model/devres.rst b/Documentation/driver-api/driver-model/devres.rst index 7be8b8dd5f00..18caebad7376 100644 --- a/Documentation/driver-api/driver-model/devres.rst +++ b/Documentation/driver-api/driver-model/devres.rst @@ -433,6 +433,7 @@ REGULATOR    devm_regulator_bulk_put()    devm_regulator_get()    devm_regulator_get_enable() +  devm_regulator_get_enable_read_voltage()    devm_regulator_get_enable_optional()    devm_regulator_get_exclusive()    devm_regulator_get_optional() diff --git a/drivers/regulator/devres.c b/drivers/regulator/devres.c index 90bb0d178885..4f290b9b559b 100644 --- a/drivers/regulator/devres.c +++ b/drivers/regulator/devres.c @@ -145,6 +145,65 @@ struct regulator *devm_regulator_get_optional(struct device *dev,  }  EXPORT_SYMBOL_GPL(devm_regulator_get_optional); +/** + * devm_regulator_get_enable_read_voltage - Resource managed regulator get and + *                                          enable that returns the voltage + * @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(), regulator_enable(), and + * regulator_get_voltage() for more information. + * + * This is a convenience function for supplies that provide a reference voltage + * where the consumer driver just needs to know the voltage and keep the + * regulator enabled. + * + * In cases where the supply is not strictly required, callers can check for + * -ENODEV error and handle it accordingly. + * + * Returns: voltage in microvolts on success, or an error code on failure. + */ +int devm_regulator_get_enable_read_voltage(struct device *dev, const char *id) +{ +	struct regulator *r; +	int ret; + +	/* +	 * Since we need a real voltage, we use devm_regulator_get_optional() +	 * rather than getting a dummy regulator with devm_regulator_get() and +	 * then letting regulator_get_voltage() fail with -EINVAL. This way, the +	 * caller can handle the -ENODEV error code if needed instead of the +	 * ambiguous -EINVAL. +	 */ +	r = devm_regulator_get_optional(dev, id); +	if (IS_ERR(r)) +		return PTR_ERR(r); + +	ret = regulator_enable(r); +	if (ret) +		goto err_regulator_put; + +	ret = devm_add_action_or_reset(dev, regulator_action_disable, r); +	if (ret) +		goto err_regulator_put; + +	ret = regulator_get_voltage(r); +	if (ret < 0) +		goto err_release_action; + +	return 0; + +err_release_action: +	devm_release_action(dev, regulator_action_disable, r); +err_regulator_put: +	devm_regulator_put(r); + +	return ret; +} +EXPORT_SYMBOL_GPL(devm_regulator_get_enable_read_voltage); +  static int devm_regulator_match(struct device *dev, void *res, void *data)  {  	struct regulator **r = res; diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index 4660582a3302..6f41a11c92e7 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -164,6 +164,7 @@ struct regulator *__must_check devm_regulator_get_optional(struct device *dev,  							   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); +int devm_regulator_get_enable_read_voltage(struct device *dev, const char *id);  void regulator_put(struct regulator *regulator);  void devm_regulator_put(struct regulator *regulator); @@ -329,6 +330,12 @@ static inline int devm_regulator_get_enable_optional(struct device *dev,  	return -ENODEV;  } +static inline int devm_regulator_get_enable_read_voltage(struct device *dev, +							 const char *id) +{ +	return -ENODEV; +} +  static inline struct regulator *__must_check  regulator_get_optional(struct device *dev, const char *id)  { | 
