All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Brownell <david-b@pacbell.net>
To: Mark Brown <broonie@sirena.org.uk>, Liam Girdwood <lrg@slimlogic.co.uk>
Cc: lkml <linux-kernel@vger.kernel.org>, OMAP <linux-omap@vger.kernel.org>
Subject: [patch/rfc 2.6.29-rc6 1/2] regulator: enumerate voltages
Date: Mon, 23 Feb 2009 12:52:01 -0800	[thread overview]
Message-ID: <200902231252.01980.david-b@pacbell.net> (raw)
In-Reply-To: <200902231245.44360.david-b@pacbell.net>

From: David Brownell <dbrownell@users.sourceforge.net>

Add a basic mechanism for regulators to report the discrete
voltages they support:  one method to count how many voltages
are available, and another to enumerate them.

Use those methods to force machine-level constraints into bounds.
(Example:  regulator supports 1.8V, 2.4V, 2.6V, 3.3V, and board
constraints for that rail are 2.0V to 3.6V ... so the range of
voltages is then 2.4V to 3.3V on this board.)

Export those voltages to the regulator consumer interface, so for
example regulator hooked up to an MMC/SD/SDIO slot can report the
actual voltage options available to cards connected there.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
---
I'm not particularly pleased with these names; suggestions?
This could also be done with one fewer method by designating a
special list_voltage() return value, but I like this better.

 drivers/regulator/core.c           |  107 +++++++++++++++++++++++++++++++++++
 include/linux/regulator/consumer.h |    2 
 include/linux/regulator/driver.h   |   10 +++
 3 files changed, 119 insertions(+)

--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -719,6 +719,44 @@ static int set_machine_constraints(struc
 	else
 		name = "regulator";
 
+	/* maybe force machine-wide voltage constraints to match the
+	 * voltages supported by this regulator.  use the regulator's
+	 * entire range for boards with no particular constraints.
+	 */
+	if (ops->list_voltage) {
+		int	count = ops->count_voltages(rdev);
+		int	i;
+		int	min_uV = INT_MAX;
+		int	max_uV = INT_MIN;
+		int	cmin = constraints->min_uV ? : INT_MIN;
+		int	cmax = constraints->max_uV ? : INT_MAX;
+
+		/* initial: [cmin..cmax] valid, [min_uV..max_uV] not */
+		for (i = 0; i < count; i++) {
+			int	value;
+
+			value = ops->list_voltage(rdev, i);
+			if (value <= 0)
+				continue;
+
+			/* maybe adjust [min_uV..max_uV] */
+			if (value >= cmin && value < min_uV)
+				min_uV = value;
+			if (value <= cmax && value > max_uV)
+				max_uV = value;
+		}
+
+		/* final: [min_uV..max_uV] valid iff constraints valid */
+		if (max_uV < min_uV) {
+			pr_err("%s: bad '%s' voltage constraints\n",
+				       __func__, name);
+			ret = -EINVAL;
+			goto out;
+		}
+		constraints->min_uV = min_uV;
+		constraints->max_uV = max_uV;
+	}
+
 	rdev->constraints = constraints;
 
 	/* do we need to apply the constraint voltage */
@@ -1245,6 +1283,75 @@ int regulator_is_enabled(struct regulato
 EXPORT_SYMBOL_GPL(regulator_is_enabled);
 
 /**
+ * regulator_count_voltages - count regulator_list_voltage() indices
+ * @regulator: regulator source
+ *
+ * Returns number of indices, or negative errno.
+ */
+int regulator_count_voltages(struct regulator *regulator)
+{
+	struct regulator_dev	*rdev = regulator->rdev;
+	struct regulator_ops	*ops;
+	int			ret = -EINVAL;
+
+	mutex_lock(&rdev->mutex);
+
+	ops = rdev->desc->ops;
+	if (ops->count_voltages)
+		ret = ops->count_voltages(rdev);
+
+	mutex_unlock(&rdev->mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(regulator_count_voltages);
+
+/**
+ * regulator_list_voltage - enumerate supported voltages
+ * @regulator: regulator source
+ * @index: identify voltage to list
+ *
+ * Returns a voltage that can be passed to @regulator_set_voltage(),
+ * or negative fault code.
+ *
+ * Faults include passing in invalid index, and using an index
+ * corresponding to a voltage that can't be used on this system.
+ */
+int regulator_list_voltage(struct regulator *regulator, unsigned index)
+{
+	struct regulator_dev	*rdev = regulator->rdev;
+	struct regulator_ops	*ops;
+	int			ret = -EINVAL;
+
+	mutex_lock(&rdev->mutex);
+
+	ops = rdev->desc->ops;
+	if (ops->count_voltages && ops->list_voltage)
+		ret = ops->count_voltages(rdev);
+
+	if (ret == 0)
+		ret = -EIO;
+	else if (ret > 0) {
+		if (index >= ret)
+			ret = -EDOM;
+		else
+			ret = ops->list_voltage(rdev, index);
+	}
+
+	if (ret >= 0) {
+		if (ret < rdev->constraints->min_uV)
+			ret = -ERANGE;
+		else if (ret > rdev->constraints->max_uV)
+			ret = -ERANGE;
+	}
+
+	mutex_unlock(&rdev->mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(regulator_list_voltage);
+
+/**
  * regulator_set_voltage - set regulator output voltage
  * @regulator: regulator source
  * @min_uV: Minimum required voltage in uV
--- a/include/linux/regulator/consumer.h
+++ b/include/linux/regulator/consumer.h
@@ -140,6 +140,8 @@ int regulator_bulk_disable(int num_consu
 void regulator_bulk_free(int num_consumers,
 			 struct regulator_bulk_data *consumers);
 
+int regulator_count_voltages(struct regulator *regulator);
+int regulator_list_voltage(struct regulator *regulator, unsigned index);
 int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV);
 int regulator_get_voltage(struct regulator *regulator);
 int regulator_set_current_limit(struct regulator *regulator,
--- a/include/linux/regulator/driver.h
+++ b/include/linux/regulator/driver.h
@@ -40,6 +40,12 @@ enum regulator_status {
  * @set_voltage: Set the voltage for the regulator within the range specified.
  *               The driver should select the voltage closest to min_uV.
  * @get_voltage: Return the currently configured voltage for the regulator.
+ * @count_voltages: Return the number of supported voltage indices which
+ *	may be passed to @list_voltage().  Some indices may correspond to
+ *	voltages that are not usable on this system.
+ * @list_voltage: Return one of the supported voltages, in microvolts;
+ *	or negative errno.  Indices range from zero to one less than
+ *	@count_voltages().  Voltages may be reported in any order.
  * @set_current_limit: Configure a limit for a current-limited regulator.
  * @get_current_limit: Get the configured limit for a current-limited regulator.
  * @set_mode: Set the operating mode for the regulator.
@@ -62,6 +68,10 @@ enum regulator_status {
  */
 struct regulator_ops {
 
+	/* enumerate supported voltages */
+	int (*count_voltages) (struct regulator_dev *);
+	int (*list_voltage) (struct regulator_dev *, unsigned index);
+
 	/* get/set regulator voltage */
 	int (*set_voltage) (struct regulator_dev *, int min_uV, int max_uV);
 	int (*get_voltage) (struct regulator_dev *);

  reply	other threads:[~2009-02-23 21:00 UTC|newest]

Thread overview: 66+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-02-08 18:37 [patch 2.6.29-rc3-git 1/2] regulator: twl4030 regulators David Brownell
2009-02-08 23:29 ` Mark Brown
2009-02-09  0:04   ` David Brownell
2009-02-09 17:27     ` Mark Brown
2009-02-10  0:24       ` David Brownell
2009-02-10 22:48         ` Mark Brown
2009-02-23 20:45           ` David Brownell
2009-02-23 20:52             ` David Brownell [this message]
2009-02-24 22:23               ` [patch/rfc 2.6.29-rc6 1/2] regulator: enumerate voltages Mark Brown
2009-02-25  0:17                 ` David Brownell
2009-02-25 15:17                   ` Mark Brown
2009-02-25 22:12                     ` David Brownell
2009-02-25 23:01                       ` Mark Brown
2009-02-25 23:47                         ` David Brownell
2009-02-26 11:05                           ` Mark Brown
2009-02-26  1:02                     ` David Brownell
2009-02-26 10:46                       ` Mark Brown
2009-02-26 18:56                         ` David Brownell
2009-02-26 19:05                           ` Mark Brown
2009-02-26 19:38                             ` David Brownell
2009-02-26 20:02                               ` Liam Girdwood
2009-02-26 20:59                                 ` David Brownell
2009-02-26 19:48               ` [patch 2.6.29-rc6 1/2] regulator: enumerate voltages (v2) David Brownell
2009-02-26 20:20                 ` Mark Brown
2009-02-26 21:12                   ` David Brownell
2009-02-26 21:48                     ` [patch 2.6.29-rc6+misc] MMC: regulator utilities David Brownell
2009-03-02 20:59                       ` Pierre Ossman
2009-03-02 21:27                         ` David Brownell
2009-03-02 21:40                           ` Pierre Ossman
2009-03-02 22:00                             ` David Brownell
2009-03-04  3:18                               ` David Brownell
2009-03-08 13:59                                 ` Pierre Ossman
2009-03-08 20:34                                   ` David Brownell
2009-03-08 21:49                                     ` Pierre Ossman
2009-03-09 11:52                                       ` Liam Girdwood
2009-03-11 11:30                                         ` David Brownell
2009-03-11 14:34                                           ` Liam Girdwood
2009-02-26 20:53                 ` [patch 2.6.29-rc6 1/2] regulator: enumerate voltages (v2) Liam Girdwood
2009-02-26 21:28                   ` David Brownell
2009-02-26 21:58                     ` Liam Girdwood
2009-02-27  0:10                       ` David Brownell
2009-02-23 20:54             ` [patch/rfc 2.6.29-rc6 2/2] regulator: twl4030 voltage enumeration David Brownell
2009-02-26 19:50               ` [patch/rfc 2.6.29-rc6 2/2] regulator: twl4030 voltage enumeration (v2) David Brownell
2009-02-26 20:25                 ` Mark Brown
2009-02-26 22:16                 ` Liam Girdwood
2009-02-27  0:02                   ` David Brownell
2009-02-27 12:32                     ` Liam Girdwood
2009-02-27 20:39                       ` David Brownell
2009-02-27 21:26                         ` Liam Girdwood
2009-03-03 22:59                       ` David Brownell
2009-03-04 11:47                         ` Liam Girdwood
2009-02-23 22:04             ` [patch 2.6.29-rc3-git 1/2] regulator: twl4030 regulators Mark Brown
2009-02-23 22:43               ` David Brownell
2009-02-24  0:55                 ` Mark Brown
2009-02-24  2:03                   ` David Brownell
2009-02-24 12:41                     ` Mark Brown
2009-02-24  2:22                   ` David Brownell
2009-02-24  7:25                     ` David Brownell
2009-02-26 22:15 ` Liam Girdwood

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200902231252.01980.david-b@pacbell.net \
    --to=david-b@pacbell.net \
    --cc=broonie@sirena.org.uk \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-omap@vger.kernel.org \
    --cc=lrg@slimlogic.co.uk \
    --subject='Re: [patch/rfc 2.6.29-rc6 1/2] regulator: enumerate voltages' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.