From: David Brownell <david-b@pacbell.net>
To: Mark Brown <broonie@sirena.org.uk>
Cc: Liam Girdwood <lrg@slimlogic.co.uk>,
lkml <linux-kernel@vger.kernel.org>,
OMAP <linux-omap@vger.kernel.org>,
Pierre Ossman <drzeus-mmc@drzeus.cx>
Subject: Re: [patch 2.6.29-rc3-git 1/2] regulator: twl4030 regulators
Date: Mon, 23 Feb 2009 23:25:10 -0800 [thread overview]
Message-ID: <200902232325.10447.david-b@pacbell.net> (raw)
In-Reply-To: <200902231822.27422.david-b@pacbell.net>
On Monday 23 February 2009, David Brownell wrote:
> > There's also fun and games to be had with accuracy once you
> > start looking too closely at the discrete voltages.
>
> Yes; the patch I sent is explicitly making those available.
>
> But I ignored issues like "+/- 3% accurate output" for LDOs
> (or switchers) ... if anyone really needs to address them,
> patches will be needed. For now I only care that a 3.1 Volt
> output can match both MMC_VDD_30_31 and MMC_VDD_31_32! ;)
And -- for kicks -- here's one notion of what it might look
like to have the MMC stack support the regulator framework.
- Dave
=================
Prototype glue between MMC and regulator stacks ... compiles,
and mmc_regulator_get_ocrmask() passed sanity testing.
NOTES:
- The MMC core does't call mmc_regulator_set_ocr() because hosts
may need to do that in conjunction with updating I/O voltage.
Case in point, MMC1 on omap_hsmmc ... where the host driver
must update MMC1_HCTL.SDVS and PBIAS registers in addition to
the regulator, supporting 1.8V or 3.0V voltage ranges. (MMC2
and MMC3 use external level shifting for Vdd != 1.8V.)
Likewise, using eMMC "managed NAND" solutions, powerup includes
not both Vcc ("vdd" to Linux, e.g. 3.0V) and an I/O interface
rail VccQ (e.g. 1.8V). The JEDEC spec for eMMC requires VccQ
powerup after Vcc, and powerdown before it.
- The "vdd" supply name isn't fixed, since platforms may need
to use more than one I/O supply.
Case in point, MMC1 on omap_hsmmc (again) ... where a second
supply is needed to kick in 8-bit I/O using DAT4..DAT7 signals.
That would not be handled quite like VccQ, since it's only
used for 8-bit I/O widths (MMCplus cards, some eMMC, etc).
---
drivers/mmc/core/Kconfig | 8 +++
drivers/mmc/core/core.c | 98 +++++++++++++++++++++++++++++++++++++++++++++
include/linux/mmc/host.h | 3 +
3 files changed, 109 insertions(+)
--- a/drivers/mmc/core/Kconfig
+++ b/drivers/mmc/core/Kconfig
@@ -14,3 +14,11 @@ config MMC_UNSAFE_RESUME
This option is usually just for embedded systems which use
a MMC/SD card for rootfs. Most people should say N here.
+config MMC_REGULATOR
+ bool
+ depends on REGULATOR
+ default y
+ help
+ Select this to provide some helper utilities to access the
+ "vdd" (card) voltage supply associated with an MMC/SD slot.
+
--- 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,103 @@ u32 mmc_vddrange_to_ocrmask(int vdd_min,
}
EXPORT_SYMBOL(mmc_vddrange_to_ocrmask);
+#ifdef CONFIG_MMC_REGULATOR
+
+/**
+ * mmc_regulator_get_ocrmask - return mask of supported voltages
+ * @host: mmc host whose supply will be consulted
+ * @supply: supply voltage to use; "vdd" if NULL
+ *
+ * This returns either a negative errno, or a mask of voltages
+ * that can be provided to MMC/SD/SDIO devices using the specified
+ * host's "vdd" supply.
+ */
+int mmc_regulator_get_ocrmask(struct mmc_host *host, const char *supply)
+{
+ int result = 0;
+ struct regulator *reg;
+ int count;
+ int i;
+
+ reg = regulator_get(host->parent, supply ? : "vdd");
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
+
+ count = regulator_count_voltages(reg);
+ if (count < 0) {
+ result = count;
+ goto done;
+ }
+
+ for (i = 0; i < count; i++) {
+ int vdd_uV;
+ int vdd_mV;
+
+ vdd_uV = regulator_list_voltage(reg, i);
+ if (vdd_uV <= 0)
+ continue;
+
+ vdd_mV = vdd_uV / 1000;
+ result |= mmc_vddrange_to_ocrmask(vdd_mV, vdd_mV);
+ }
+
+done:
+ regulator_put(reg);
+ return result;
+}
+EXPORT_SYMBOL(mmc_regulator_get_ocrmask);
+
+/**
+ * mmc_regulator_set_ocr - set regulator to match host->ios voltage
+ * @host: mmc host whose supply voltage will be changed
+ * @supply: supply voltage to use; "vdd" if NULL
+ *
+ * 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, possibly as part of updating
+ * digital interfaces to support that voltage.
+ */
+int mmc_regulator_set_ocr(struct mmc_host *host, const char *supply)
+{
+ int result = 0;
+ struct regulator *reg;
+ int min_mV, max_mV;
+ int enabled;
+
+ reg = regulator_get(host->parent, supply ? : "vdd");
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
+ enabled = regulator_is_enabled(reg);
+ if (WARN(enabled < 0, "%s: regulator_is_enabled --> %d\n",
+ mmc_hostname(host), enabled))
+ enabled = !host->ios.vdd;
+
+ if (host->ios.vdd) {
+ int tmp;
+
+ tmp = host->ios.vdd - ilog2(MMC_VDD_165_195);
+ if (tmp == 0) {
+ min_mV = 1650;
+ max_mV = 1950;
+ } else {
+ min_mV = 2000 + tmp * 100;
+ max_mV = min_mV + 100;
+ }
+
+ result = regulator_set_voltage(reg, min_mV * 1000, max_mV * 1000);
+ if (result == 0 && !enabled)
+ result = regulator_enable(reg);
+ } else if (enabled) {
+ result = regulator_disable(reg);
+ }
+
+ regulator_put(reg);
+ 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,8 @@ static inline void mmc_signal_sdio_irq(s
wake_up_process(host->sdio_irq_thread);
}
+int mmc_regulator_get_ocrmask(struct mmc_host *host, const char *supply);
+int mmc_regulator_set_ocr(struct mmc_host *host, const char *supply);
+
#endif
WARNING: multiple messages have this Message-ID (diff)
From: David Brownell <david-b@pacbell.net>
To: Mark Brown <broonie@sirena.org.uk>
Cc: Liam Girdwood <lrg@slimlogic.co.uk>,
lkml <linux-kernel@vger.kernel.org>,
OMAP <linux-omap@vger.kernel.org>,
Pierre Ossman <drzeus-mmc@drzeus.cx>
Subject: Re: [patch 2.6.29-rc3-git 1/2] regulator: twl4030 regulators
Date: Mon, 23 Feb 2009 23:25:10 -0800 [thread overview]
Message-ID: <200902232325.10447.david-b@pacbell.net> (raw)
In-Reply-To: <200902231822.27422.david-b@pacbell.net>
On Monday 23 February 2009, David Brownell wrote:
> > There's also fun and games to be had with accuracy once you
> > start looking too closely at the discrete voltages.
>
> Yes; the patch I sent is explicitly making those available.
>
> But I ignored issues like "+/- 3% accurate output" for LDOs
> (or switchers) ... if anyone really needs to address them,
> patches will be needed. For now I only care that a 3.1 Volt
> output can match both MMC_VDD_30_31 and MMC_VDD_31_32! ;)
And -- for kicks -- here's one notion of what it might look
like to have the MMC stack support the regulator framework.
- Dave
=================
Prototype glue between MMC and regulator stacks ... compiles,
and mmc_regulator_get_ocrmask() passed sanity testing.
NOTES:
- The MMC core does't call mmc_regulator_set_ocr() because hosts
may need to do that in conjunction with updating I/O voltage.
Case in point, MMC1 on omap_hsmmc ... where the host driver
must update MMC1_HCTL.SDVS and PBIAS registers in addition to
the regulator, supporting 1.8V or 3.0V voltage ranges. (MMC2
and MMC3 use external level shifting for Vdd != 1.8V.)
Likewise, using eMMC "managed NAND" solutions, powerup includes
not both Vcc ("vdd" to Linux, e.g. 3.0V) and an I/O interface
rail VccQ (e.g. 1.8V). The JEDEC spec for eMMC requires VccQ
powerup after Vcc, and powerdown before it.
- The "vdd" supply name isn't fixed, since platforms may need
to use more than one I/O supply.
Case in point, MMC1 on omap_hsmmc (again) ... where a second
supply is needed to kick in 8-bit I/O using DAT4..DAT7 signals.
That would not be handled quite like VccQ, since it's only
used for 8-bit I/O widths (MMCplus cards, some eMMC, etc).
---
drivers/mmc/core/Kconfig | 8 +++
drivers/mmc/core/core.c | 98 +++++++++++++++++++++++++++++++++++++++++++++
include/linux/mmc/host.h | 3 +
3 files changed, 109 insertions(+)
--- a/drivers/mmc/core/Kconfig
+++ b/drivers/mmc/core/Kconfig
@@ -14,3 +14,11 @@ config MMC_UNSAFE_RESUME
This option is usually just for embedded systems which use
a MMC/SD card for rootfs. Most people should say N here.
+config MMC_REGULATOR
+ bool
+ depends on REGULATOR
+ default y
+ help
+ Select this to provide some helper utilities to access the
+ "vdd" (card) voltage supply associated with an MMC/SD slot.
+
--- 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,103 @@ u32 mmc_vddrange_to_ocrmask(int vdd_min,
}
EXPORT_SYMBOL(mmc_vddrange_to_ocrmask);
+#ifdef CONFIG_MMC_REGULATOR
+
+/**
+ * mmc_regulator_get_ocrmask - return mask of supported voltages
+ * @host: mmc host whose supply will be consulted
+ * @supply: supply voltage to use; "vdd" if NULL
+ *
+ * This returns either a negative errno, or a mask of voltages
+ * that can be provided to MMC/SD/SDIO devices using the specified
+ * host's "vdd" supply.
+ */
+int mmc_regulator_get_ocrmask(struct mmc_host *host, const char *supply)
+{
+ int result = 0;
+ struct regulator *reg;
+ int count;
+ int i;
+
+ reg = regulator_get(host->parent, supply ? : "vdd");
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
+
+ count = regulator_count_voltages(reg);
+ if (count < 0) {
+ result = count;
+ goto done;
+ }
+
+ for (i = 0; i < count; i++) {
+ int vdd_uV;
+ int vdd_mV;
+
+ vdd_uV = regulator_list_voltage(reg, i);
+ if (vdd_uV <= 0)
+ continue;
+
+ vdd_mV = vdd_uV / 1000;
+ result |= mmc_vddrange_to_ocrmask(vdd_mV, vdd_mV);
+ }
+
+done:
+ regulator_put(reg);
+ return result;
+}
+EXPORT_SYMBOL(mmc_regulator_get_ocrmask);
+
+/**
+ * mmc_regulator_set_ocr - set regulator to match host->ios voltage
+ * @host: mmc host whose supply voltage will be changed
+ * @supply: supply voltage to use; "vdd" if NULL
+ *
+ * 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, possibly as part of updating
+ * digital interfaces to support that voltage.
+ */
+int mmc_regulator_set_ocr(struct mmc_host *host, const char *supply)
+{
+ int result = 0;
+ struct regulator *reg;
+ int min_mV, max_mV;
+ int enabled;
+
+ reg = regulator_get(host->parent, supply ? : "vdd");
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
+ enabled = regulator_is_enabled(reg);
+ if (WARN(enabled < 0, "%s: regulator_is_enabled --> %d\n",
+ mmc_hostname(host), enabled))
+ enabled = !host->ios.vdd;
+
+ if (host->ios.vdd) {
+ int tmp;
+
+ tmp = host->ios.vdd - ilog2(MMC_VDD_165_195);
+ if (tmp == 0) {
+ min_mV = 1650;
+ max_mV = 1950;
+ } else {
+ min_mV = 2000 + tmp * 100;
+ max_mV = min_mV + 100;
+ }
+
+ result = regulator_set_voltage(reg, min_mV * 1000, max_mV * 1000);
+ if (result == 0 && !enabled)
+ result = regulator_enable(reg);
+ } else if (enabled) {
+ result = regulator_disable(reg);
+ }
+
+ regulator_put(reg);
+ 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,8 @@ static inline void mmc_signal_sdio_irq(s
wake_up_process(host->sdio_irq_thread);
}
+int mmc_regulator_get_ocrmask(struct mmc_host *host, const char *supply);
+int mmc_regulator_set_ocr(struct mmc_host *host, const char *supply);
+
#endif
--
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
next prev parent reply other threads:[~2009-02-24 7:25 UTC|newest]
Thread overview: 66+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-02-08 18:37 [patch 2.6.29-rc3-git 1/2] regulator: twl4030 regulators David Brownell
2009-02-08 23:29 ` Mark Brown
2009-02-09 0:04 ` David Brownell
2009-02-09 0:04 ` David Brownell
2009-02-09 17:27 ` Mark Brown
2009-02-10 0:24 ` David Brownell
2009-02-10 22:48 ` Mark Brown
2009-02-23 20:45 ` David Brownell
2009-02-23 20:52 ` [patch/rfc 2.6.29-rc6 1/2] regulator: enumerate voltages David Brownell
2009-02-24 22:23 ` Mark Brown
2009-02-25 0:17 ` David Brownell
2009-02-25 15:17 ` Mark Brown
2009-02-25 22:12 ` David Brownell
2009-02-25 23:01 ` Mark Brown
2009-02-25 23:47 ` David Brownell
2009-02-25 23:47 ` David Brownell
2009-02-26 11:05 ` Mark Brown
2009-02-26 1:02 ` David Brownell
2009-02-26 1:02 ` David Brownell
2009-02-26 10:46 ` Mark Brown
2009-02-26 18:56 ` David Brownell
2009-02-26 19:05 ` Mark Brown
2009-02-26 19:38 ` David Brownell
2009-02-26 20:02 ` Liam Girdwood
2009-02-26 20:59 ` David Brownell
2009-02-26 20:59 ` David Brownell
2009-02-26 19:48 ` [patch 2.6.29-rc6 1/2] regulator: enumerate voltages (v2) David Brownell
2009-02-26 20:20 ` Mark Brown
2009-02-26 21:12 ` David Brownell
2009-02-26 21:48 ` [patch 2.6.29-rc6+misc] MMC: regulator utilities David Brownell
2009-03-02 20:59 ` Pierre Ossman
2009-03-02 21:27 ` David Brownell
2009-03-02 21:40 ` Pierre Ossman
2009-03-02 22:00 ` David Brownell
2009-03-04 3:18 ` David Brownell
2009-03-08 13:59 ` Pierre Ossman
2009-03-08 20:34 ` David Brownell
2009-03-08 21:49 ` Pierre Ossman
2009-03-09 11:52 ` Liam Girdwood
2009-03-11 11:30 ` David Brownell
2009-03-11 14:34 ` Liam Girdwood
2009-02-26 20:53 ` [patch 2.6.29-rc6 1/2] regulator: enumerate voltages (v2) Liam Girdwood
2009-02-26 21:28 ` David Brownell
2009-02-26 21:58 ` Liam Girdwood
2009-02-27 0:10 ` David Brownell
2009-02-23 20:54 ` [patch/rfc 2.6.29-rc6 2/2] regulator: twl4030 voltage enumeration David Brownell
2009-02-26 19:50 ` [patch/rfc 2.6.29-rc6 2/2] regulator: twl4030 voltage enumeration (v2) David Brownell
2009-02-26 20:25 ` Mark Brown
2009-02-26 22:16 ` Liam Girdwood
2009-02-27 0:02 ` David Brownell
2009-02-27 0:02 ` David Brownell
2009-02-27 12:32 ` Liam Girdwood
2009-02-27 20:39 ` David Brownell
2009-02-27 21:26 ` Liam Girdwood
2009-03-03 22:59 ` David Brownell
2009-03-04 11:47 ` Liam Girdwood
2009-02-23 22:04 ` [patch 2.6.29-rc3-git 1/2] regulator: twl4030 regulators Mark Brown
2009-02-23 22:43 ` David Brownell
2009-02-24 0:55 ` Mark Brown
2009-02-24 2:03 ` David Brownell
2009-02-24 12:41 ` Mark Brown
2009-02-24 2:22 ` David Brownell
2009-02-24 2:22 ` David Brownell
2009-02-24 7:25 ` David Brownell [this message]
2009-02-24 7:25 ` David Brownell
2009-02-26 22:15 ` Liam Girdwood
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200902232325.10447.david-b@pacbell.net \
--to=david-b@pacbell.net \
--cc=broonie@sirena.org.uk \
--cc=drzeus-mmc@drzeus.cx \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-omap@vger.kernel.org \
--cc=lrg@slimlogic.co.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.