All of lore.kernel.org
 help / color / mirror / Atom feed
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

  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.