* [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] 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