All of lore.kernel.org
 help / color / mirror / Atom feed
* [patch 2.6.29-rc7-omap 0/5] mmc-twl4030 loses twl4030-dependency
@ 2009-03-11 12:18 David Brownell
  2009-03-11 12:20 ` [patch 2.6.29-rc7-omap 1/5] regulator: enumerate voltages David Brownell
                   ` (4 more replies)
  0 siblings, 5 replies; 19+ messages in thread
From: David Brownell @ 2009-03-11 12:18 UTC (permalink / raw)
  To: OMAP

The last dependency of that code on twl4030 specific behavior
was coupled to regulator usage ... and, hey, there's a regulator
framework to hide such details!

The first four of these patches are from the regulator-next tree:

 - regulator: enumerate voltages
 - regulator: twl4030 voltage enumeration
 - regulator: twl4030 voltage enumeration cleanups
 - MMC: regulator utilities

More precisely ... the first three are, but the wrong version of
the fourth got merged; that should get sorted out soonish.

The last patch does the magic:

 - mmc-twl4030 uses regulator framework

This works if the boards have hooked up their regulators to the
MMC devices.  Beagle does that; so does the 3430 SDP (which has
a second 1.8V SD/MMCplus slot).  I'll resend a patch doing that
for Overo.

So for example two of Adrian's patches from yesterday are now
subsumed by the regulator framework.  To have MMC2 hook up to
an eMMC chip that needs VccQ for interface level shifting, just
hook up the "aux" supply to that MMC device.  To have it use
the VAUX3 supply instead of VMMC2, just be sure to hook up the
right regulator.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [patch 2.6.29-rc7-omap 1/5] regulator: enumerate voltages
  2009-03-11 12:18 [patch 2.6.29-rc7-omap 0/5] mmc-twl4030 loses twl4030-dependency David Brownell
@ 2009-03-11 12:20 ` David Brownell
  2009-03-11 16:09   ` [APPLIED] regulator: enumerate voltages (v2) Tony Lindgren
  2009-03-11 12:21 ` [patch 2.6.29-rc7-omap 2/5] regulator: twl4030 voltage enumeration David Brownell
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 19+ messages in thread
From: David Brownell @ 2009-03-11 12:20 UTC (permalink / raw)
  To: OMAP

From: David Brownell <dbrownell@users.sourceforge.net>
Subject: regulator: enumerate voltages (v2)

Add a basic mechanism for regulators to report the discrete
voltages they support:  list_voltage() enumerates them using
selectors numbered from 0 to an upper bound.

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>
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
---
 drivers/regulator/core.c           |  113 +++++++++++++++++++++++++++++++++++
 include/linux/regulator/consumer.h |    2 
 include/linux/regulator/driver.h   |    9 ++
 3 files changed, 124 insertions(+)

--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -719,6 +719,69 @@ static int set_machine_constraints(struc
 	else
 		name = "regulator";
 
+	/* constrain machine-level voltage specs to fit
+	 * the actual range supported by this regulator.
+	 */
+	if (ops->list_voltage && rdev->desc->n_voltages) {
+		int	count = rdev->desc->n_voltages;
+		int	i;
+		int	min_uV = INT_MAX;
+		int	max_uV = INT_MIN;
+		int	cmin = constraints->min_uV;
+		int	cmax = constraints->max_uV;
+
+		/* it's safe to autoconfigure fixed-voltage supplies */
+		if (count == 1 && !cmin) {
+			cmin = INT_MIN;
+			cmax = INT_MAX;
+		}
+
+		/* else require explicit machine-level constraints */
+		else if (cmin <= 0 || cmax <= 0 || cmax < cmin) {
+			pr_err("%s: %s '%s' voltage constraints\n",
+				       __func__, "invalid", name);
+			ret = -EINVAL;
+			goto out;
+		}
+
+		/* 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: %s '%s' voltage constraints\n",
+				       __func__, "unsupportable", name);
+			ret = -EINVAL;
+			goto out;
+		}
+
+		/* use regulator's subset of machine constraints */
+		if (constraints->min_uV < min_uV) {
+			pr_debug("%s: override '%s' %s, %d -> %d\n",
+				       __func__, name, "min_uV",
+					constraints->min_uV, min_uV);
+			constraints->min_uV = min_uV;
+		}
+		if (constraints->max_uV > max_uV) {
+			pr_debug("%s: override '%s' %s, %d -> %d\n",
+				       __func__, name, "max_uV",
+					constraints->max_uV, max_uV);
+			constraints->max_uV = max_uV;
+		}
+	}
+
 	rdev->constraints = constraints;
 
 	/* do we need to apply the constraint voltage */
@@ -1245,6 +1308,56 @@ int regulator_is_enabled(struct regulato
 EXPORT_SYMBOL_GPL(regulator_is_enabled);
 
 /**
+ * regulator_count_voltages - count regulator_list_voltage() selectors
+ * @regulator: regulator source
+ *
+ * Returns number of selectors, or negative errno.  Selectors are
+ * numbered starting at zero, and typically correspond to bitfields
+ * in hardware registers.
+ */
+int regulator_count_voltages(struct regulator *regulator)
+{
+	struct regulator_dev	*rdev = regulator->rdev;
+
+	return rdev->desc->n_voltages ? : -EINVAL;
+}
+EXPORT_SYMBOL_GPL(regulator_count_voltages);
+
+/**
+ * regulator_list_voltage - enumerate supported voltages
+ * @regulator: regulator source
+ * @selector: identify voltage to list
+ * Context: can sleep
+ *
+ * Returns a voltage that can be passed to @regulator_set_voltage(),
+ * zero if this selector code can't be used on this sytem, or a
+ * negative errno.
+ */
+int regulator_list_voltage(struct regulator *regulator, unsigned selector)
+{
+	struct regulator_dev	*rdev = regulator->rdev;
+	struct regulator_ops	*ops = rdev->desc->ops;
+	int			ret;
+
+	if (!ops->list_voltage || selector >= rdev->desc->n_voltages)
+		return -EINVAL;
+
+	mutex_lock(&rdev->mutex);
+	ret = ops->list_voltage(rdev, selector);
+	mutex_unlock(&rdev->mutex);
+
+	if (ret > 0) {
+		if (ret < rdev->constraints->min_uV)
+			ret = 0;
+		else if (ret > rdev->constraints->max_uV)
+			ret = 0;
+	}
+
+	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 selector);
 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
@@ -45,6 +45,10 @@ 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.
+ * @list_voltage: Return one of the supported voltages, in microvolts; zero
+ *	if the selector indicates a voltage that is unusable on this system;
+ *	or negative errno.  Selectors range from zero to one less than
+ *	regulator_desc.n_voltages.  Voltages may be reported in any order.
  *
  * @set_current_limit: Configure a limit for a current-limited regulator.
  * @get_current_limit: Get the limit for a current-limited regulator.
@@ -65,6 +69,9 @@ enum regulator_status {
  */
 struct regulator_ops {
 
+	/* enumerate supported voltages */
+	int (*list_voltage) (struct regulator_dev *, unsigned selector);
+
 	/* get/set regulator voltage */
 	int (*set_voltage) (struct regulator_dev *, int min_uV, int max_uV);
 	int (*get_voltage) (struct regulator_dev *);
@@ -123,6 +130,7 @@ enum regulator_type {
  *
  * @name: Identifying name for the regulator.
  * @id: Numerical identifier for the regulator.
+ * @n_voltages: Number of selectors available for ops.list_voltage().
  * @ops: Regulator operations table.
  * @irq: Interrupt number for the regulator.
  * @type: Indicates if the regulator is a voltage or current regulator.
@@ -131,6 +139,7 @@ enum regulator_type {
 struct regulator_desc {
 	const char *name;
 	int id;
+	unsigned n_voltages;
 	struct regulator_ops *ops;
 	int irq;
 	enum regulator_type type;

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [patch 2.6.29-rc7-omap 2/5] regulator: twl4030 voltage enumeration
  2009-03-11 12:18 [patch 2.6.29-rc7-omap 0/5] mmc-twl4030 loses twl4030-dependency David Brownell
  2009-03-11 12:20 ` [patch 2.6.29-rc7-omap 1/5] regulator: enumerate voltages David Brownell
@ 2009-03-11 12:21 ` David Brownell
  2009-03-11 16:09   ` [APPLIED] regulator: twl4030 voltage enumeration (v2) Tony Lindgren
  2009-03-11 12:22 ` [patch 2.6.29-rc7-omap 3/5] regulator: twl4030 voltage enumeration cleanup David Brownell
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 19+ messages in thread
From: David Brownell @ 2009-03-11 12:21 UTC (permalink / raw)
  To: OMAP

From: David Brownell <dbrownell@users.sourceforge.net>
Subject: regulator: twl4030 voltage enumeration (v2)

Update previously-posted twl4030 regulator driver to export
supported voltages to upper layers using a new mechanism.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
---
 drivers/regulator/twl4030-regulator.c |   62 +++++++++++---------------------
 1 file changed, 23 insertions(+), 39 deletions(-)

--- a/drivers/regulator/twl4030-regulator.c
+++ b/drivers/regulator/twl4030-regulator.c
@@ -42,7 +42,6 @@ struct twlreg_info {
 
 	/* chip constraints on regulator behavior */
 	u16			min_mV;
-	u16			max_mV;
 
 	/* used by regulator core */
 	struct regulator_desc	desc;
@@ -262,6 +261,14 @@ static const u16 VDAC_VSEL_table[] = {
 };
 
 
+static int twl4030ldo_list_voltage(struct regulator_dev *rdev, unsigned index)
+{
+	struct twlreg_info	*info = rdev_get_drvdata(rdev);
+	int			mV = info->table[index];
+
+	return IS_UNSUP(mV) ? 0 : (LDO_MV(mV) * 1000);
+}
+
 static int
 twl4030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV)
 {
@@ -276,6 +283,8 @@ twl4030ldo_set_voltage(struct regulator_
 			continue;
 		uV = LDO_MV(mV) * 1000;
 
+		/* REVISIT for VAUX2, first match may not be best/lowest */
+
 		/* use the first in-range value */
 		if (min_uV <= uV && uV <= max_uV)
 			return twl4030reg_write(info, VREG_DEDICATED, vsel);
@@ -297,6 +306,8 @@ static int twl4030ldo_get_voltage(struct
 }
 
 static struct regulator_ops twl4030ldo_ops = {
+	.list_voltage	= twl4030ldo_list_voltage,
+
 	.set_voltage	= twl4030ldo_set_voltage,
 	.get_voltage	= twl4030ldo_get_voltage,
 
@@ -314,6 +325,13 @@ static struct regulator_ops twl4030ldo_o
 /*
  * Fixed voltage LDOs don't have a VSEL field to update.
  */
+static int twl4030fixed_list_voltage(struct regulator_dev *rdev, unsigned index)
+{
+	struct twlreg_info	*info = rdev_get_drvdata(rdev);
+
+	return info->min_mV * 1000;
+}
+
 static int twl4030fixed_get_voltage(struct regulator_dev *rdev)
 {
 	struct twlreg_info	*info = rdev_get_drvdata(rdev);
@@ -322,6 +340,8 @@ static int twl4030fixed_get_voltage(stru
 }
 
 static struct regulator_ops twl4030fixed_ops = {
+	.list_voltage	= twl4030fixed_list_voltage,
+
 	.get_voltage	= twl4030fixed_get_voltage,
 
 	.enable		= twl4030reg_enable,
@@ -343,6 +363,7 @@ static struct regulator_ops twl4030fixed
 	.desc = { \
 		.name = #label, \
 		.id = TWL4030_REG_##label, \
+		.n_voltages = ARRAY_SIZE(label##_VSEL_table), \
 		.ops = &twl4030ldo_ops, \
 		.type = REGULATOR_VOLTAGE, \
 		.owner = THIS_MODULE, \
@@ -353,10 +374,10 @@ static struct regulator_ops twl4030fixed
 	.base = offset, \
 	.id = num, \
 	.min_mV = mVolts, \
-	.max_mV = mVolts, \
 	.desc = { \
 		.name = #label, \
 		.id = TWL4030_REG_##label, \
+		.n_voltages = 1, \
 		.ops = &twl4030fixed_ops, \
 		.type = REGULATOR_VOLTAGE, \
 		.owner = THIS_MODULE, \
@@ -402,14 +423,11 @@ static int twl4030reg_probe(struct platf
 	struct regulator_init_data	*initdata;
 	struct regulation_constraints	*c;
 	struct regulator_dev		*rdev;
-	int				min_uV, max_uV;
 
 	for (i = 0, info = NULL; i < ARRAY_SIZE(twl4030_regs); i++) {
 		if (twl4030_regs[i].desc.id != pdev->id)
 			continue;
 		info = twl4030_regs + i;
-		min_uV = info->min_mV * 1000;
-		max_uV = info->max_mV * 1000;
 		break;
 	}
 	if (!info)
@@ -423,10 +441,6 @@ static int twl4030reg_probe(struct platf
 	 * this driver and the chip itself can actually do.
 	 */
 	c = &initdata->constraints;
-	if (!c->min_uV || c->min_uV < min_uV)
-		c->min_uV = min_uV;
-	if (!c->max_uV || c->max_uV > max_uV)
-		c->max_uV = max_uV;
 	c->valid_modes_mask &= REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY;
 	c->valid_ops_mask &= REGULATOR_CHANGE_VOLTAGE
 				| REGULATOR_CHANGE_MODE
@@ -471,36 +485,6 @@ static struct platform_driver twl4030reg
 
 static int __init twl4030reg_init(void)
 {
-	unsigned i, j;
-
-	/* determine min/max voltage constraints, taking into account
-	 * whether set_voltage() will use the "unsupported" settings
-	 */
-	for (i = 0; i < ARRAY_SIZE(twl4030_regs); i++) {
-		struct twlreg_info	*info = twl4030_regs + i;
-		const u16		*table;
-
-		/* fixed-voltage regulators */
-		if (!info->table_len)
-			continue;
-
-		/* LDO regulators: */
-		for (j = 0, table = info->table;
-				j < info->table_len;
-				j++, table++) {
-			u16		mV = *table;
-
-			if (IS_UNSUP(mV))
-				continue;
-			mV = LDO_MV(mV);
-
-			if (info->min_mV == 0 || info->min_mV > mV)
-				info->min_mV = mV;
-			if (info->max_mV < mV)
-				info->max_mV = mV;
-		}
-	}
-
 	return platform_driver_register(&twl4030reg_driver);
 }
 subsys_initcall(twl4030reg_init);

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [patch 2.6.29-rc7-omap 3/5] regulator: twl4030 voltage enumeration cleanup
  2009-03-11 12:18 [patch 2.6.29-rc7-omap 0/5] mmc-twl4030 loses twl4030-dependency David Brownell
  2009-03-11 12:20 ` [patch 2.6.29-rc7-omap 1/5] regulator: enumerate voltages David Brownell
  2009-03-11 12:21 ` [patch 2.6.29-rc7-omap 2/5] regulator: twl4030 voltage enumeration David Brownell
@ 2009-03-11 12:22 ` David Brownell
  2009-03-11 16:09   ` [APPLIED] regulator: twl4030 voltage enumeration (v2) cleanups Tony Lindgren
  2009-03-11 12:23 ` [patch 2.6.29-rc7-omap 4/5] MMC: regulator utilities David Brownell
  2009-03-11 12:24 ` [patch 2.6.29-rc7-omap 5/5] mmc-twl4030 uses regulator framework David Brownell
  4 siblings, 1 reply; 19+ messages in thread
From: David Brownell @ 2009-03-11 12:22 UTC (permalink / raw)
  To: OMAP

From: David Brownell <dbrownell@users.sourceforge.net>
Subject: regulator: twl4030 voltage enumeration (v2) cleanups

Minor cleanups to the twl403 regulator driver, mostly enabled
by other recent changes:  comments, shrink memory usage, add
definition for one bit.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
---
 drivers/regulator/twl4030-regulator.c |   16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

--- a/drivers/regulator/twl4030-regulator.c
+++ b/drivers/regulator/twl4030-regulator.c
@@ -36,13 +36,13 @@ struct twlreg_info {
 	/* twl4030 resource ID, for resource control state machine */
 	u8			id;
 
+	/* FIXED_LDO voltage */
+	u8			deciV;
+
 	/* voltage in mV = table[VSEL]; table_len must be a power-of-two */
 	u8			table_len;
 	const u16		*table;
 
-	/* chip constraints on regulator behavior */
-	u16			min_mV;
-
 	/* used by regulator core */
 	struct regulator_desc	desc;
 };
@@ -97,6 +97,7 @@ static int twl4030reg_grp(struct regulat
 #define P3_GRP		BIT(7)		/* "peripherals" */
 #define P2_GRP		BIT(6)		/* secondary processor, modem, etc */
 #define P1_GRP		BIT(5)		/* CPU/Linux */
+#define WARM_CFG	BIT(4)
 
 static int twl4030reg_is_enabled(struct regulator_dev *rdev)
 {
@@ -329,14 +330,14 @@ static int twl4030fixed_list_voltage(str
 {
 	struct twlreg_info	*info = rdev_get_drvdata(rdev);
 
-	return info->min_mV * 1000;
+	return info->deciV * 100 * 1000;
 }
 
 static int twl4030fixed_get_voltage(struct regulator_dev *rdev)
 {
 	struct twlreg_info	*info = rdev_get_drvdata(rdev);
 
-	return info->min_mV * 1000;
+	return info->deciV * 100 * 1000;
 }
 
 static struct regulator_ops twl4030fixed_ops = {
@@ -373,7 +374,7 @@ static struct regulator_ops twl4030fixed
 #define TWL_FIXED_LDO(label, offset, mVolts, num) { \
 	.base = offset, \
 	.id = num, \
-	.min_mV = mVolts, \
+	.deciV = mVolts / 100 , \
 	.desc = { \
 		.name = #label, \
 		.id = TWL4030_REG_##label, \
@@ -385,7 +386,7 @@ static struct regulator_ops twl4030fixed
 	}
 
 /*
- * We list regulators here if systems need some level of
+ * We expose regulators here if systems need some level of
  * software control over them after boot.
  */
 static struct twlreg_info twl4030_regs[] = {
@@ -439,6 +440,7 @@ static int twl4030reg_probe(struct platf
 
 	/* Constrain board-specific capabilities according to what
 	 * this driver and the chip itself can actually do.
+	 * (Regulator core now does this for voltage constraints.)
 	 */
 	c = &initdata->constraints;
 	c->valid_modes_mask &= REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY;

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [patch 2.6.29-rc7-omap 4/5] MMC: regulator utilities
  2009-03-11 12:18 [patch 2.6.29-rc7-omap 0/5] mmc-twl4030 loses twl4030-dependency David Brownell
                   ` (2 preceding siblings ...)
  2009-03-11 12:22 ` [patch 2.6.29-rc7-omap 3/5] regulator: twl4030 voltage enumeration cleanup David Brownell
@ 2009-03-11 12:23 ` David Brownell
  2009-03-11 16:09   ` [APPLIED] " Tony Lindgren
  2009-03-11 12:24 ` [patch 2.6.29-rc7-omap 5/5] mmc-twl4030 uses regulator framework David Brownell
  4 siblings, 1 reply; 19+ messages in thread
From: David Brownell @ 2009-03-11 12:23 UTC (permalink / raw)
  To: OMAP

From: David Brownell <dbrownell@users.sourceforge.net>
Subject: MMC: regulator utilities

Glue between MMC and regulator stacks ... verified with
some OMAP3 boards using adjustable and configured-as-fixed
regulators on several MMC controllers.

These calls are intended to be used by MMC host adapters
using at least one regulator per host.  Examples include
slots with regulators supporting multiple voltages and
ones using multiple voltage rails (e.g. DAT4..DAT7 using a
separate supply, or a split rail chip like certain SDIO
WLAN or eMMC solutions).

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Acked-by: Pierre Ossman <drzeus@drzeus.cx>
---
Changes since previous version:  simplified set_ocr() calling
convention, fixed an off-by-100mA error in that code, and don't
set voltage on regulators that don't need (and may disallow) it.

 drivers/mmc/core/core.c  |  100 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/mmc/host.h |    5 ++
 2 files changed, 105 insertions(+)

--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -21,6 +21,7 @@
 #include <linux/leds.h>
 #include <linux/scatterlist.h>
 #include <linux/log2.h>
+#include <linux/regulator/consumer.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
@@ -523,6 +524,105 @@ u32 mmc_vddrange_to_ocrmask(int vdd_min,
 }
 EXPORT_SYMBOL(mmc_vddrange_to_ocrmask);
 
+#ifdef CONFIG_REGULATOR
+
+/**
+ * mmc_regulator_get_ocrmask - return mask of supported voltages
+ * @supply: regulator to use
+ *
+ * This returns either a negative errno, or a mask of voltages that
+ * can be provided to MMC/SD/SDIO devices using the specified voltage
+ * regulator.  This would normally be called before registering the
+ * MMC host adapter.
+ */
+int mmc_regulator_get_ocrmask(struct regulator *supply)
+{
+	int			result = 0;
+	int			count;
+	int			i;
+
+	count = regulator_count_voltages(supply);
+	if (count < 0)
+		return count;
+
+	for (i = 0; i < count; i++) {
+		int		vdd_uV;
+		int		vdd_mV;
+
+		vdd_uV = regulator_list_voltage(supply, i);
+		if (vdd_uV <= 0)
+			continue;
+
+		vdd_mV = vdd_uV / 1000;
+		result |= mmc_vddrange_to_ocrmask(vdd_mV, vdd_mV);
+	}
+
+	return result;
+}
+EXPORT_SYMBOL(mmc_regulator_get_ocrmask);
+
+/**
+ * mmc_regulator_set_ocr - set regulator to match host->ios voltage
+ * @vdd_bit: zero for power off, else a bit number (host->ios.vdd)
+ * @supply: regulator to use
+ *
+ * Returns zero on success, else negative errno.
+ *
+ * MMC host drivers may use this to enable or disable a regulator using
+ * a particular supply voltage.  This would normally be called from the
+ * set_ios() method.
+ */
+int mmc_regulator_set_ocr(struct regulator *supply, unsigned short vdd_bit)
+{
+	int			result = 0;
+	int			min_uV, max_uV;
+	int			enabled;
+
+	enabled = regulator_is_enabled(supply);
+	if (enabled < 0)
+		return enabled;
+
+	if (vdd_bit) {
+		int		tmp;
+		int		voltage;
+
+		/* REVISIT mmc_vddrange_to_ocrmask() may have set some
+		 * bits this regulator doesn't quite support ... don't
+		 * be too picky, most cards and regulators are OK with
+		 * a 0.1V range goof (it's a small error percentage).
+		 */
+		tmp = vdd_bit - ilog2(MMC_VDD_165_195);
+		if (tmp == 0) {
+			min_uV = 1650 * 1000;
+			max_uV = 1950 * 1000;
+		} else {
+			min_uV = 1900 * 1000 + tmp * 100 * 1000;
+			max_uV = min_uV + 100 * 1000;
+		}
+
+		/* avoid needless changes to this voltage; the regulator
+		 * might not allow this operation
+		 */
+		voltage = regulator_get_voltage(supply);
+		if (voltage < 0)
+			result = voltage;
+		else if (voltage < min_uV || voltage > max_uV)
+			result = regulator_set_voltage(supply, min_uV, max_uV);
+		else
+			result = 0;
+
+		if (result == 0 && !enabled)
+			result = regulator_enable(supply);
+	} else if (enabled) {
+		result = regulator_disable(supply);
+	}
+
+	return result;
+}
+EXPORT_SYMBOL(mmc_regulator_set_ocr);
+
+#endif
+
 /*
  * Mask off any voltages we don't support and select
  * the lowest voltage
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -192,5 +192,10 @@ static inline void mmc_signal_sdio_irq(s
 	wake_up_process(host->sdio_irq_thread);
 }
 
+struct regulator;
+
+int mmc_regulator_get_ocrmask(struct regulator *supply);
+int mmc_regulator_set_ocr(struct regulator *supply, unsigned short vdd_bit);
+
 #endif
 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [patch 2.6.29-rc7-omap 5/5] mmc-twl4030 uses regulator framework
  2009-03-11 12:18 [patch 2.6.29-rc7-omap 0/5] mmc-twl4030 loses twl4030-dependency David Brownell
                   ` (3 preceding siblings ...)
  2009-03-11 12:23 ` [patch 2.6.29-rc7-omap 4/5] MMC: regulator utilities David Brownell
@ 2009-03-11 12:24 ` David Brownell
  2009-03-11 16:09   ` [APPLIED] " Tony Lindgren
  2009-03-12  8:57   ` [patch 2.6.29-rc7-omap 5/5] " Adrian Hunter
  4 siblings, 2 replies; 19+ messages in thread
From: David Brownell @ 2009-03-11 12:24 UTC (permalink / raw)
  To: OMAP

From: David Brownell <dbrownell@users.sourceforge.net>
Subject: mmc-twl4030 uses regulator framework

Finish decoupling the HSMMC glue from the twl4030 as the only
regulator provider, using the regulator framework instead.
This makes the glue's "mmc-twl4030" name become a complete
misnomer ... this code could probably all migrate into the
HSMMC driver now.

Tested on 3430SDP (SD and low-voltage MMC) and Beagle (SD),
plus some other boards (including Overo) after they were
converted to set up MMC regulators properly.

Eventually all boards should just associate a regulator with
each MMC controller they use.  In some cases (Overo MMC2 and
Pandora MMC3, at least) that would be a fixed-voltage regulator
with no real software control.  As a temporary hack (pending
regulator-next updates to make the "fixed.c" regulator become
usable) there's a new ocr_mask field for those boards.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
---
 arch/arm/mach-omap2/mmc-twl4030.c |  262 +++++++++++++-----------------------
 arch/arm/mach-omap2/mmc-twl4030.h |    3 
 drivers/mmc/host/omap_hsmmc.c     |    6 
 3 files changed, 100 insertions(+), 171 deletions(-)

--- a/arch/arm/mach-omap2/mmc-twl4030.c
+++ b/arch/arm/mach-omap2/mmc-twl4030.c
@@ -16,8 +16,8 @@
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/gpio.h>
-#include <linux/i2c/twl4030.h>
-#include <linux/regulator/machine.h>
+#include <linux/mmc/host.h>
+#include <linux/regulator/consumer.h>
 
 #include <mach/hardware.h>
 #include <mach/control.h>
@@ -26,31 +26,9 @@
 
 #include "mmc-twl4030.h"
 
-#if defined(CONFIG_TWL4030_CORE) && \
-	(defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE))
-
-#define LDO_CLR			0x00
-#define VSEL_S2_CLR		0x40
-
-#define VMMC1_DEV_GRP		0x27
-#define VMMC1_CLR		0x00
-#define VMMC1_315V		0x03
-#define VMMC1_300V		0x02
-#define VMMC1_285V		0x01
-#define VMMC1_185V		0x00
-#define VMMC1_DEDICATED		0x2A
 
-#define VMMC2_DEV_GRP		0x2B
-#define VMMC2_CLR		0x40
-#define VMMC2_315V		0x0c
-#define VMMC2_300V		0x0b
-#define VMMC2_285V		0x0a
-#define VMMC2_280V		0x09
-#define VMMC2_260V		0x08
-#define VMMC2_185V		0x06
-#define VMMC2_DEDICATED		0x2E
-
-#define VMMC_DEV_GRP_P1		0x20
+#if defined(CONFIG_REGULATOR) && \
+	(defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE))
 
 static u16 control_pbias_offset;
 static u16 control_devconf1_offset;
@@ -59,19 +37,16 @@ static u16 control_devconf1_offset;
 
 static struct twl_mmc_controller {
 	struct omap_mmc_platform_data	*mmc;
-	u8		twl_vmmc_dev_grp;
-	u8		twl_mmc_dedicated;
-	char		name[HSMMC_NAME_LEN + 1];
-} hsmmc[OMAP34XX_NR_MMC] = {
-	{
-		.twl_vmmc_dev_grp		= VMMC1_DEV_GRP,
-		.twl_mmc_dedicated		= VMMC1_DEDICATED,
-	},
-	{
-		.twl_vmmc_dev_grp		= VMMC2_DEV_GRP,
-		.twl_mmc_dedicated		= VMMC2_DEDICATED,
-	},
-};
+	/* Vcc == configured supply
+	 * Vcc_alt == optional
+	 *   -	MMC1, supply for DAT4..DAT7
+	 *   -	MMC2/MMC2, external level shifter voltage supply, for
+	 *	chip (SDIO, eMMC, etc) or transceiver (MMC2 only)
+	 */
+	struct regulator		*vcc;
+	struct regulator		*vcc_aux;
+	char				name[HSMMC_NAME_LEN + 1];
+} hsmmc[OMAP34XX_NR_MMC];
 
 static int twl_mmc_card_detect(int irq)
 {
@@ -117,16 +92,42 @@ static int twl_mmc_late_init(struct devi
 	int ret = 0;
 	int i;
 
-	ret = gpio_request(mmc->slots[0].switch_pin, "mmc_cd");
-	if (ret)
-		goto done;
-	ret = gpio_direction_input(mmc->slots[0].switch_pin);
-	if (ret)
-		goto err;
+	/* MMC/SD/SDIO doesn't require a card detect switch */
+	if (gpio_is_valid(mmc->slots[0].switch_pin)) {
+		ret = gpio_request(mmc->slots[0].switch_pin, "mmc_cd");
+		if (ret)
+			goto done;
+		ret = gpio_direction_input(mmc->slots[0].switch_pin);
+		if (ret)
+			goto err;
+	}
 
+	/* require at least main regulator */
 	for (i = 0; i < ARRAY_SIZE(hsmmc); i++) {
 		if (hsmmc[i].name == mmc->slots[0].name) {
+			struct regulator *reg;
+
 			hsmmc[i].mmc = mmc;
+
+			reg = regulator_get(dev, "vmmc");
+			if (IS_ERR(reg)) {
+				dev_dbg(dev, "vmmc regulator missing\n");
+				/* HACK: until fixed.c regulator is usable,
+				 * we don't require a main regulator
+				 * for MMC2 or MMC3
+				 */
+				if (i != 0)
+					break;
+				ret = PTR_ERR(reg);
+				goto err;
+			}
+			hsmmc[i].vcc = reg;
+			mmc->slots[0].ocr_mask = mmc_regulator_get_ocrmask(reg);
+
+			/* allow an aux regulator */
+			reg = regulator_get(dev, "vmmc_aux");
+			hsmmc[i].vcc_aux = IS_ERR(reg) ? NULL : reg;
+
 			break;
 		}
 	}
@@ -173,96 +174,6 @@ static int twl_mmc_resume(struct device 
 #define twl_mmc_resume	NULL
 #endif
 
-/*
- * Sets the MMC voltage in twl4030
- */
-
-#define MMC1_OCR	(MMC_VDD_165_195 \
-		|MMC_VDD_28_29|MMC_VDD_29_30|MMC_VDD_30_31|MMC_VDD_31_32)
-#define MMC2_OCR	(MMC_VDD_165_195 \
-		|MMC_VDD_25_26|MMC_VDD_26_27|MMC_VDD_27_28 \
-		|MMC_VDD_28_29|MMC_VDD_29_30|MMC_VDD_30_31|MMC_VDD_31_32)
-
-static int twl_mmc_set_voltage(struct twl_mmc_controller *c, int vdd)
-{
-	int ret;
-	u8 vmmc = 0, dev_grp_val;
-
-	if (!vdd)
-		goto doit;
-
-	if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP) {
-		/* VMMC1:  max 220 mA.  And for 8-bit mode,
-		 * VSIM:  max 50 mA
-		 */
-		switch (1 << vdd) {
-		case MMC_VDD_165_195:
-			vmmc = VMMC1_185V;
-			/* and VSIM_180V */
-			break;
-		case MMC_VDD_28_29:
-			vmmc = VMMC1_285V;
-			/* and VSIM_280V */
-			break;
-		case MMC_VDD_29_30:
-		case MMC_VDD_30_31:
-			vmmc = VMMC1_300V;
-			/* and VSIM_300V */
-			break;
-		case MMC_VDD_31_32:
-			vmmc = VMMC1_315V;
-			/* error if VSIM needed */
-			break;
-		default:
-			return -EINVAL;
-		}
-	} else if (c->twl_vmmc_dev_grp == VMMC2_DEV_GRP) {
-		/* VMMC2:  max 100 mA */
-		switch (1 << vdd) {
-		case MMC_VDD_165_195:
-			vmmc = VMMC2_185V;
-			break;
-		case MMC_VDD_25_26:
-		case MMC_VDD_26_27:
-			vmmc = VMMC2_260V;
-			break;
-		case MMC_VDD_27_28:
-			vmmc = VMMC2_280V;
-			break;
-		case MMC_VDD_28_29:
-			vmmc = VMMC2_285V;
-			break;
-		case MMC_VDD_29_30:
-		case MMC_VDD_30_31:
-			vmmc = VMMC2_300V;
-			break;
-		case MMC_VDD_31_32:
-			vmmc = VMMC2_315V;
-			break;
-		default:
-			return -EINVAL;
-		}
-	} else {
-		return -EINVAL;
-	}
-
-doit:
-	if (vdd)
-		dev_grp_val = VMMC_DEV_GRP_P1;	/* Power up */
-	else
-		dev_grp_val = LDO_CLR;		/* Power down */
-
-	ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
-					dev_grp_val, c->twl_vmmc_dev_grp);
-	if (ret || !vdd)
-		return ret;
-
-	ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
-					vmmc, c->twl_mmc_dedicated);
-
-	return ret;
-}
-
 static int twl_mmc1_set_power(struct device *dev, int slot, int power_on,
 				int vdd)
 {
@@ -273,11 +184,13 @@ static int twl_mmc1_set_power(struct dev
 
 	/*
 	 * Assume we power both OMAP VMMC1 (for CMD, CLK, DAT0..3) and the
-	 * card using the same TWL VMMC1 supply (hsmmc[0]); OMAP has both
+	 * card with Vcc regulator (from twl4030 or whatever).  OMAP has both
 	 * 1.8V and 3.0V modes, controlled by the PBIAS register.
 	 *
 	 * In 8-bit modes, OMAP VMMC1A (for DAT4..7) needs a supply, which
 	 * is most naturally TWL VSIM; those pins also use PBIAS.
+	 *
+	 * FIXME handle VMMC1A as needed ...
 	 */
 	if (power_on) {
 		if (cpu_is_omap2430()) {
@@ -300,7 +213,7 @@ static int twl_mmc1_set_power(struct dev
 		reg &= ~OMAP2_PBIASLITEPWRDNZ0;
 		omap_ctrl_writel(reg, control_pbias_offset);
 
-		ret = twl_mmc_set_voltage(c, vdd);
+		ret = mmc_regulator_set_ocr(c->vcc, vdd);
 
 		/* 100ms delay required for PBIAS configuration */
 		msleep(100);
@@ -316,7 +229,7 @@ static int twl_mmc1_set_power(struct dev
 		reg &= ~OMAP2_PBIASLITEPWRDNZ0;
 		omap_ctrl_writel(reg, control_pbias_offset);
 
-		ret = twl_mmc_set_voltage(c, 0);
+		ret = mmc_regulator_set_ocr(c->vcc, 0);
 
 		/* 100ms delay required for PBIAS configuration */
 		msleep(100);
@@ -329,19 +242,33 @@ static int twl_mmc1_set_power(struct dev
 	return ret;
 }
 
-static int twl_mmc2_set_power(struct device *dev, int slot, int power_on, int vdd)
+static int twl_mmc23_set_power(struct device *dev, int slot, int power_on, int vdd)
 {
-	int ret;
+	int ret = 0;
 	struct twl_mmc_controller *c = &hsmmc[1];
 	struct omap_mmc_platform_data *mmc = dev->platform_data;
 
+	/* If we don't see a Vcc regulator, assume it's a fixed
+	 * voltage always-on regulator.
+	 */
+	if (!c->vcc)
+		return 0;
+
 	/*
-	 * Assume TWL VMMC2 (hsmmc[1]) is used only to power the card ... OMAP
+	 * Assume Vcc regulator is used only to power the card ... OMAP
 	 * VDDS is used to power the pins, optionally with a transceiver to
 	 * support cards using voltages other than VDDS (1.8V nominal).  When a
 	 * transceiver is used, DAT3..7 are muxed as transceiver control pins.
+	 *
+	 * In some cases this regulator won't support enable/disable;
+	 * e.g. it's a fixed rail for a WLAN chip.
+	 *
+	 * In other cases vcc_aux switches interface power.  Example, for
+	 * eMMC cards it represents VccQ.  Sometimes transceivers or SDIO
+	 * chips/cards need an interface voltage rail too.
 	 */
 	if (power_on) {
+		/* only MMC2 supports a CLKIN */
 		if (mmc->slots[0].internal_clock) {
 			u32 reg;
 
@@ -349,24 +276,23 @@ static int twl_mmc2_set_power(struct dev
 			reg |= OMAP2_MMCSDIO2ADPCLKISEL;
 			omap_ctrl_writel(reg, control_devconf1_offset);
 		}
-		ret = twl_mmc_set_voltage(c, vdd);
+		ret = mmc_regulator_set_ocr(c->vcc, vdd);
+		/* enable interface voltage rail, if needed */
+		if (ret == 0 && c->vcc_aux) {
+			ret = regulator_enable(c->vcc_aux);
+			if (ret < 0)
+				ret = mmc_regulator_set_ocr(c->vcc, 0);
+		}
 	} else {
-		ret = twl_mmc_set_voltage(c, 0);
+		if (c->vcc_aux)
+			ret = regulator_enable(c->vcc_aux);
+		if (ret == 0)
+			ret = mmc_regulator_set_ocr(c->vcc, 0);
 	}
 
 	return ret;
 }
 
-static int twl_mmc3_set_power(struct device *dev, int slot, int power_on,
-		int vdd)
-{
-	/*
-	 * Assume MMC3 has self-powered device connected, for example on-board
-	 * chip with external power source.
-	 */
-	return 0;
-}
-
 static struct omap_mmc_platform_data *hsmmc_data[OMAP34XX_NR_MMC] __initdata;
 
 void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers)
@@ -411,10 +337,10 @@ void __init twl4030_mmc_init(struct twl4
 		mmc->slots[0].wires = c->wires;
 		mmc->slots[0].internal_clock = !c->ext_clock;
 		mmc->dma_mask = 0xffffffff;
+		mmc->init = twl_mmc_late_init;
 
-		/* note: twl4030 card detect GPIOs normally switch VMMCx ... */
+		/* note: twl4030 card detect GPIOs can disable VMMCx ... */
 		if (gpio_is_valid(c->gpio_cd)) {
-			mmc->init = twl_mmc_late_init;
 			mmc->cleanup = twl_mmc_cleanup;
 			mmc->suspend = twl_mmc_suspend;
 			mmc->resume = twl_mmc_resume;
@@ -438,26 +364,28 @@ void __init twl4030_mmc_init(struct twl4
 		} else
 			mmc->slots[0].gpio_wp = -EINVAL;
 
-		/* NOTE:  we assume OMAP's MMC1 and MMC2 use
-		 * the TWL4030's VMMC1 and VMMC2, respectively;
-		 * and that MMC3 device has it's own power source.
+		/* NOTE:  MMC slots should have a Vcc regulator set up.
+		 * This may be from a TWL4030-family chip, another
+		 * controllable regulator, or a fixed supply.
+		 *
+		 * temporary HACK: ocr_mask instead of fixed supply
 		 */
+		mmc->slots[0].ocr_mask = c->ocr_mask;
 
 		switch (c->mmc) {
 		case 1:
+			/* on-chip level shifting via PBIAS0/PBIAS1 */
 			mmc->slots[0].set_power = twl_mmc1_set_power;
-			mmc->slots[0].ocr_mask = MMC1_OCR;
 			break;
 		case 2:
-			mmc->slots[0].set_power = twl_mmc2_set_power;
-			if (c->transceiver)
-				mmc->slots[0].ocr_mask = MMC2_OCR;
-			else
-				mmc->slots[0].ocr_mask = MMC_VDD_165_195;
-			break;
+			if (c->ext_clock)
+				c->transceiver = 1;
+			if (c->transceiver && c->wires > 4)
+				c->wires = 4;
+			/* FALLTHROUGH */
 		case 3:
-			mmc->slots[0].set_power = twl_mmc3_set_power;
-			mmc->slots[0].ocr_mask = MMC_VDD_165_195;
+			/* off-chip level shifting, or none */
+			mmc->slots[0].set_power = twl_mmc23_set_power;
 			break;
 		default:
 			pr_err("MMC%d configuration not supported!\n", c->mmc);
--- a/arch/arm/mach-omap2/mmc-twl4030.h
+++ b/arch/arm/mach-omap2/mmc-twl4030.h
@@ -16,9 +16,10 @@ struct twl4030_hsmmc_info {
 	int	gpio_wp;	/* or -EINVAL */
 	char	*name;		/* or NULL for default */
 	struct device *dev;	/* returned: pointer to mmc adapter */
+	int	ocr_mask;	/* temporary HACK */
 };
 
-#if	defined(CONFIG_TWL4030_CORE) && \
+#if defined(CONFIG_REGULATOR) && \
 	(defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \
 	 defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE))
 
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -1005,7 +1005,6 @@ static int __init omap_mmc_probe(struct 
 	mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
 	mmc->max_seg_size = mmc->max_req_size;
 
-	mmc->ocr_avail = mmc_slot(host).ocr_mask;
 	mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
 
 	if (pdata->slots[host->slot_id].wires >= 4)
@@ -1042,13 +1041,14 @@ static int __init omap_mmc_probe(struct 
 		goto err_irq;
 	}
 
+	/* initialize power supplies, gpios, etc */
 	if (pdata->init != NULL) {
 		if (pdata->init(&pdev->dev) != 0) {
-			dev_dbg(mmc_dev(host->mmc),
-				"Unable to configure MMC IRQs\n");
+			dev_dbg(mmc_dev(host->mmc), "late init error\n");
 			goto err_irq_cd_init;
 		}
 	}
+	mmc->ocr_avail = mmc_slot(host).ocr_mask;
 
 	/* Request IRQ for card detect */
 	if ((mmc_slot(host).card_detect_irq) && (mmc_slot(host).card_detect)) {

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [APPLIED] regulator: enumerate voltages (v2)
  2009-03-11 12:20 ` [patch 2.6.29-rc7-omap 1/5] regulator: enumerate voltages David Brownell
@ 2009-03-11 16:09   ` Tony Lindgren
  0 siblings, 0 replies; 19+ messages in thread
From: Tony Lindgren @ 2009-03-11 16:09 UTC (permalink / raw)
  To: linux-omap

This patch has been applied to the linux-omap
by youw fwiendly patch wobot.

Commit: 278a2f75b0809c1242b65af61c9b1823e697a323

PatchWorks
http://patchwork.kernel.org/patch/11117/

Git
http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-2.6.git;a=commit;h=278a2f75b0809c1242b65af61c9b1823e697a323



^ permalink raw reply	[flat|nested] 19+ messages in thread

* [APPLIED] regulator: twl4030 voltage enumeration (v2)
  2009-03-11 12:21 ` [patch 2.6.29-rc7-omap 2/5] regulator: twl4030 voltage enumeration David Brownell
@ 2009-03-11 16:09   ` Tony Lindgren
  0 siblings, 0 replies; 19+ messages in thread
From: Tony Lindgren @ 2009-03-11 16:09 UTC (permalink / raw)
  To: linux-omap

This patch has been applied to the linux-omap
by youw fwiendly patch wobot.

Commit: 8b0f9499b13e61e3bd730f2f10d2cf20c693e36d

PatchWorks
http://patchwork.kernel.org/patch/11118/

Git
http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-2.6.git;a=commit;h=8b0f9499b13e61e3bd730f2f10d2cf20c693e36d



^ permalink raw reply	[flat|nested] 19+ messages in thread

* [APPLIED] regulator: twl4030 voltage enumeration (v2) cleanups
  2009-03-11 12:22 ` [patch 2.6.29-rc7-omap 3/5] regulator: twl4030 voltage enumeration cleanup David Brownell
@ 2009-03-11 16:09   ` Tony Lindgren
  0 siblings, 0 replies; 19+ messages in thread
From: Tony Lindgren @ 2009-03-11 16:09 UTC (permalink / raw)
  To: linux-omap

This patch has been applied to the linux-omap
by youw fwiendly patch wobot.

Commit: fd08b838200bb77a231468eb2fa1246525354c5c

PatchWorks
http://patchwork.kernel.org/patch/11119/

Git
http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-2.6.git;a=commit;h=fd08b838200bb77a231468eb2fa1246525354c5c



^ permalink raw reply	[flat|nested] 19+ messages in thread

* [APPLIED] MMC: regulator utilities
  2009-03-11 12:23 ` [patch 2.6.29-rc7-omap 4/5] MMC: regulator utilities David Brownell
@ 2009-03-11 16:09   ` Tony Lindgren
  0 siblings, 0 replies; 19+ messages in thread
From: Tony Lindgren @ 2009-03-11 16:09 UTC (permalink / raw)
  To: linux-omap

This patch has been applied to the linux-omap
by youw fwiendly patch wobot.

Commit: 4e1f2b829034be5383341dca9fa25062980c3b44

PatchWorks
http://patchwork.kernel.org/patch/11120/

Git
http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-2.6.git;a=commit;h=4e1f2b829034be5383341dca9fa25062980c3b44



^ permalink raw reply	[flat|nested] 19+ messages in thread

* [APPLIED] mmc-twl4030 uses regulator framework
  2009-03-11 12:24 ` [patch 2.6.29-rc7-omap 5/5] mmc-twl4030 uses regulator framework David Brownell
@ 2009-03-11 16:09   ` Tony Lindgren
  2009-03-12  8:57   ` [patch 2.6.29-rc7-omap 5/5] " Adrian Hunter
  1 sibling, 0 replies; 19+ messages in thread
From: Tony Lindgren @ 2009-03-11 16:09 UTC (permalink / raw)
  To: linux-omap

This patch has been applied to the linux-omap
by youw fwiendly patch wobot.

Commit: 3fe326511c66ab842ef0a09a1f4c564b1a8beecf

PatchWorks
http://patchwork.kernel.org/patch/11121/

Git
http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-2.6.git;a=commit;h=3fe326511c66ab842ef0a09a1f4c564b1a8beecf



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [patch 2.6.29-rc7-omap 5/5] mmc-twl4030 uses regulator framework
  2009-03-11 12:24 ` [patch 2.6.29-rc7-omap 5/5] mmc-twl4030 uses regulator framework David Brownell
  2009-03-11 16:09   ` [APPLIED] " Tony Lindgren
@ 2009-03-12  8:57   ` Adrian Hunter
  2009-03-12  9:22     ` David Brownell
  1 sibling, 1 reply; 19+ messages in thread
From: Adrian Hunter @ 2009-03-12  8:57 UTC (permalink / raw)
  To: David Brownell; +Cc: OMAP

David Brownell wrote:
> From: David Brownell <dbrownell@users.sourceforge.net>
> Subject: mmc-twl4030 uses regulator framework
> 
> Finish decoupling the HSMMC glue from the twl4030 as the only
> regulator provider, using the regulator framework instead.
> This makes the glue's "mmc-twl4030" name become a complete
> misnomer ... this code could probably all migrate into the
> HSMMC driver now.
> 
> Tested on 3430SDP (SD and low-voltage MMC) and Beagle (SD),
> plus some other boards (including Overo) after they were
> converted to set up MMC regulators properly.
> 
> Eventually all boards should just associate a regulator with
> each MMC controller they use.  In some cases (Overo MMC2 and
> Pandora MMC3, at least) that would be a fixed-voltage regulator
> with no real software control.  As a temporary hack (pending
> regulator-next updates to make the "fixed.c" regulator become
> usable) there's a new ocr_mask field for those boards.
> 
> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
> ---

snip

> @@ -349,24 +276,23 @@ static int twl_mmc2_set_power(struct dev
>                         reg |= OMAP2_MMCSDIO2ADPCLKISEL;
>                         omap_ctrl_writel(reg, control_devconf1_offset);
>                 }
> -               ret = twl_mmc_set_voltage(c, vdd);
> +               ret = mmc_regulator_set_ocr(c->vcc, vdd);
> +               /* enable interface voltage rail, if needed */
> +               if (ret == 0 && c->vcc_aux) {
> +                       ret = regulator_enable(c->vcc_aux);
> +                       if (ret < 0)
> +                               ret = mmc_regulator_set_ocr(c->vcc, 0);
> +               }
>         } else {
> -               ret = twl_mmc_set_voltage(c, 0);
> +               if (c->vcc_aux)
> +                       ret = regulator_enable(c->vcc_aux);

Sorry for slow reply.  Shouldn't that be regulator_disable() ?

> +               if (ret == 0)
> +                       ret = mmc_regulator_set_ocr(c->vcc, 0);
>         }
> 
>         return ret;
>  }
> 

snip

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [patch 2.6.29-rc7-omap 5/5] mmc-twl4030 uses regulator framework
  2009-03-12  8:57   ` [patch 2.6.29-rc7-omap 5/5] " Adrian Hunter
@ 2009-03-12  9:22     ` David Brownell
  2009-03-16 14:44       ` Adrian Hunter
  0 siblings, 1 reply; 19+ messages in thread
From: David Brownell @ 2009-03-12  9:22 UTC (permalink / raw)
  To: Adrian Hunter; +Cc: OMAP

On Thursday 12 March 2009, Adrian Hunter wrote:
> > +               }
> >         } else {
> > -               ret = twl_mmc_set_voltage(c, 0);
> > +               if (c->vcc_aux)
> > +                       ret = regulator_enable(c->vcc_aux);
> 
> Sorry for slow reply.  Shouldn't that be regulator_disable() ?

Indeed it should be.  In fact I think this probably explains
the failure I saw the other day, trying to go from 3.3V on one
chip down to 1.8V, where it failed (reasons unknown so far)
but the cleanup left vcc_aux active.  Got patch?  :)

I meant this one to be a patch/RFC ... so you could see how I
thought those issues should be addressed, vs the less general
patches you sent the other day.  Actually merging this one
runs into that annoying regulator framework isssue on most
systems.

- Dave


--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [patch 2.6.29-rc7-omap 5/5] mmc-twl4030 uses regulator framework
  2009-03-12  9:22     ` David Brownell
@ 2009-03-16 14:44       ` Adrian Hunter
  2009-03-16 19:33         ` David Brownell
  0 siblings, 1 reply; 19+ messages in thread
From: Adrian Hunter @ 2009-03-16 14:44 UTC (permalink / raw)
  To: David Brownell; +Cc: OMAP

ext David Brownell wrote:
> On Thursday 12 March 2009, Adrian Hunter wrote:
>>> +               }
>>>         } else {
>>> -               ret = twl_mmc_set_voltage(c, 0);
>>> +               if (c->vcc_aux)
>>> +                       ret = regulator_enable(c->vcc_aux);
>> Sorry for slow reply.  Shouldn't that be regulator_disable() ?
> 
> Indeed it should be.  In fact I think this probably explains
> the failure I saw the other day, trying to go from 3.3V on one
> chip down to 1.8V, where it failed (reasons unknown so far)
> but the cleanup left vcc_aux active.  Got patch?  :)
> 
> I meant this one to be a patch/RFC ... so you could see how I
> thought those issues should be addressed, vs the less general
> patches you sent the other day.  Actually merging this one
> runs into that annoying regulator framework isssue on most
> systems.
> 
> - Dave
> 
> 
> 


I have another problem:


arch/arm/mach-omap2/built-in.o: In function `twl_mmc23_set_power':
/home/ahunter/git/lo-on-rover/arch/arm/mach-omap2/mmc-twl4030.c:282: undefined reference to `mmc_regulator_set_ocr'
/home/ahunter/git/lo-on-rover/arch/arm/mach-omap2/mmc-twl4030.c:293: undefined reference to `mmc_regulator_set_ocr'
arch/arm/mach-omap2/built-in.o: In function `twl_mmc1_set_power':
/home/ahunter/git/lo-on-rover/arch/arm/mach-omap2/mmc-twl4030.c:219: undefined reference to `mmc_regulator_set_ocr'
/home/ahunter/git/lo-on-rover/arch/arm/mach-omap2/mmc-twl4030.c:235: undefined reference to `mmc_regulator_set_ocr'
arch/arm/mach-omap2/built-in.o: In function `twl_mmc_late_init':
/home/ahunter/git/lo-on-rover/arch/arm/mach-omap2/mmc-twl4030.c:128: undefined reference to `mmc_regulator_get_ocrmask'
make: *** [.tmp_vmlinux1] Error 1


The linker is not happy with built-in code trying to call functions in a module directly.


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [patch 2.6.29-rc7-omap 5/5] mmc-twl4030 uses regulator framework
  2009-03-16 14:44       ` Adrian Hunter
@ 2009-03-16 19:33         ` David Brownell
  2009-03-17  6:38           ` Adrian Hunter
  0 siblings, 1 reply; 19+ messages in thread
From: David Brownell @ 2009-03-16 19:33 UTC (permalink / raw)
  To: Adrian Hunter; +Cc: OMAP

On Monday 16 March 2009, Adrian Hunter wrote:
> The linker is not happy with built-in code trying to call functions in a module directly.

Hmm, I guess I mis-read something ... didn't know the MMC core
could be built as a module!

So the workaround is not to build it that way.  And the long-term
fix is to merge the mmc-twl4030 code into the hsmmc driver.

Any problem with using that workaround for a while?

- Dave


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [patch 2.6.29-rc7-omap 5/5] mmc-twl4030 uses regulator framework
  2009-03-16 19:33         ` David Brownell
@ 2009-03-17  6:38           ` Adrian Hunter
  2009-03-17  7:07             ` David Brownell
  0 siblings, 1 reply; 19+ messages in thread
From: Adrian Hunter @ 2009-03-17  6:38 UTC (permalink / raw)
  To: David Brownell; +Cc: OMAP

David Brownell wrote:
> On Monday 16 March 2009, Adrian Hunter wrote:
>> The linker is not happy with built-in code trying to call functions in a module directly.
> 
> Hmm, I guess I mis-read something ... didn't know the MMC core
> could be built as a module!
> 
> So the workaround is not to build it that way.  And the long-term
> fix is to merge the mmc-twl4030 code into the hsmmc driver.

Yes the code should be moved into omap_hsmmc.c

> 
> Any problem with using that workaround for a while?

No problem with that.

Also vsim (vmmc_aux) is not being found.


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [patch 2.6.29-rc7-omap 5/5] mmc-twl4030 uses regulator framework
  2009-03-17  6:38           ` Adrian Hunter
@ 2009-03-17  7:07             ` David Brownell
  2009-03-17  7:12               ` Adrian Hunter
  0 siblings, 1 reply; 19+ messages in thread
From: David Brownell @ 2009-03-17  7:07 UTC (permalink / raw)
  To: Adrian Hunter; +Cc: OMAP

On Monday 16 March 2009, Adrian Hunter wrote:
> Also vsim (vmmc_aux) is not being found.

Elaborate please?  The regulator framework complains
if it's not there, even when that's not a bug.



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [patch 2.6.29-rc7-omap 5/5] mmc-twl4030 uses regulator framework
  2009-03-17  7:07             ` David Brownell
@ 2009-03-17  7:12               ` Adrian Hunter
  2009-03-17 10:25                 ` David Brownell
  0 siblings, 1 reply; 19+ messages in thread
From: Adrian Hunter @ 2009-03-17  7:12 UTC (permalink / raw)
  To: David Brownell; +Cc: OMAP

David Brownell wrote:
> On Monday 16 March 2009, Adrian Hunter wrote:
>> Also vsim (vmmc_aux) is not being found.
> 
> Elaborate please?  The regulator framework complains
> if it's not there, even when that's not a bug.

Sorry, I am at home but I realise now that I did record the message:

regulator: Unable to get requested regulator: vmmc_aux

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [patch 2.6.29-rc7-omap 5/5] mmc-twl4030 uses regulator framework
  2009-03-17  7:12               ` Adrian Hunter
@ 2009-03-17 10:25                 ` David Brownell
  0 siblings, 0 replies; 19+ messages in thread
From: David Brownell @ 2009-03-17 10:25 UTC (permalink / raw)
  To: Adrian Hunter; +Cc: OMAP

On Tuesday 17 March 2009, Adrian Hunter wrote:
> > 
> > Elaborate please?  The regulator framework complains
> > if it's not there, even when that's not a bug.
> 
> Sorry, I am at home but I realise now that I did record the message:
> 
> regulator: Unable to get requested regulator: vmmc_aux

That's just the regulator framework being stupid.
In two ways:  (a) doesn't say which device didn't
have a "vmmc_aux" supply, (b) even if it did indicate
a bug, that would be the responsibility of the driver
to handle (when it gets an error from that lookup).


--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2009-03-17 10:25 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-03-11 12:18 [patch 2.6.29-rc7-omap 0/5] mmc-twl4030 loses twl4030-dependency David Brownell
2009-03-11 12:20 ` [patch 2.6.29-rc7-omap 1/5] regulator: enumerate voltages David Brownell
2009-03-11 16:09   ` [APPLIED] regulator: enumerate voltages (v2) Tony Lindgren
2009-03-11 12:21 ` [patch 2.6.29-rc7-omap 2/5] regulator: twl4030 voltage enumeration David Brownell
2009-03-11 16:09   ` [APPLIED] regulator: twl4030 voltage enumeration (v2) Tony Lindgren
2009-03-11 12:22 ` [patch 2.6.29-rc7-omap 3/5] regulator: twl4030 voltage enumeration cleanup David Brownell
2009-03-11 16:09   ` [APPLIED] regulator: twl4030 voltage enumeration (v2) cleanups Tony Lindgren
2009-03-11 12:23 ` [patch 2.6.29-rc7-omap 4/5] MMC: regulator utilities David Brownell
2009-03-11 16:09   ` [APPLIED] " Tony Lindgren
2009-03-11 12:24 ` [patch 2.6.29-rc7-omap 5/5] mmc-twl4030 uses regulator framework David Brownell
2009-03-11 16:09   ` [APPLIED] " Tony Lindgren
2009-03-12  8:57   ` [patch 2.6.29-rc7-omap 5/5] " Adrian Hunter
2009-03-12  9:22     ` David Brownell
2009-03-16 14:44       ` Adrian Hunter
2009-03-16 19:33         ` David Brownell
2009-03-17  6:38           ` Adrian Hunter
2009-03-17  7:07             ` David Brownell
2009-03-17  7:12               ` Adrian Hunter
2009-03-17 10:25                 ` David Brownell

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.