Unverified Commit b250c20b authored by David Lechner's avatar David Lechner Committed by Mark Brown
Browse files

regulator: devres: add API for reference voltage supplies



A common use case for regulators is to supply a reference voltage to an
analog input or output device. This adds a new devres API to get,
enable, and get the voltage in a single call. This allows eliminating
boilerplate code in drivers that use reference supplies in this way.

Signed-off-by: default avatarDavid Lechner <dlechner@baylibre.com>
Link: https://lore.kernel.org/r/20240429-regulator-get-enable-get-votlage-v2-1-b1f11ab766c1@baylibre.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent fec50db7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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()
+59 −0
Original line number Diff line number Diff line
@@ -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;
+7 −0
Original line number Diff line number Diff line
@@ -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)
{