diff mbox

[v3,1/2] mmc: sdio add regulator vsdio

Message ID 1314253575-2602-2-git-send-email-zhangfei.gao@marvell.com (mailing list archive)
State New, archived
Headers show

Commit Message

Zhangfei Gao Aug. 25, 2011, 6:26 a.m. UTC
sdio client may be required power on/off dynamically.
With regulator vsdio, sdio client power on/off could be executed by mmc_power_up/down

CC: Ohad Ben-Cohen <ohad@wizery.com>
Signed-off-by: Zhangfei Gao <zhangfei.gao@marvell.com>
---
 drivers/mmc/host/sdhci.c  |   22 ++++++++++++++++++++++
 include/linux/mmc/sdhci.h |    2 ++
 2 files changed, 24 insertions(+), 0 deletions(-)

Comments

Eric Miao Aug. 31, 2011, 2:06 p.m. UTC | #1
Zhangfei,

My understanding is that the card in the slot would be either MMC _or_
SDIO and why do we need another regulator for the power on/off?

On Thu, Aug 25, 2011 at 2:26 PM, Zhangfei Gao <zhangfei.gao@marvell.com> wrote:
> sdio client may be required power on/off dynamically.
> With regulator vsdio, sdio client power on/off could be executed by mmc_power_up/down
>
> CC: Ohad Ben-Cohen <ohad@wizery.com>
> Signed-off-by: Zhangfei Gao <zhangfei.gao@marvell.com>
> ---
>  drivers/mmc/host/sdhci.c  |   22 , >  include/linux/mmc/sdhci.h |    2 ++
>  2 files changed, 24 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 0e02cc1..e0ef7d3 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -1424,6 +1424,18 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>  out:
>        mmiowb();
>        spin_unlock_irqrestore(&host->lock, flags);
> +
> +       if (host->vsdio) {
> +               if (ios->power_mode != host->power_mode_old) {
> +                       if (ios->power_mode == MMC_POWER_OFF)
> +                               regulator_disable(host->vsdio);
> +
> +                       if (ios->power_mode == MMC_POWER_UP)
> +                               regulator_enable(host->vsdio);
> +               }
> +
> +               host->power_mode_old = ios->power_mode;
> +       }
>  }
>
>  static int check_ro(struct sdhci_host *host)
> @@ -2748,6 +2760,13 @@ int sdhci_add_host(struct sdhci_host *host)
>                regulator_enable(host->vmmc);
>        }
>
> +       host->vsdio = regulator_get(mmc_dev(mmc), "vsdio");
> +       if (IS_ERR(host->vsdio))
> +               host->vsdio = NULL;
> +       else
> +               printk(KERN_INFO "%s: vsdio regulator found\n",
> +                       mmc_hostname(mmc));
> +
>        sdhci_init(host, 0);
>
>  #ifdef CONFIG_MMC_DEBUG
> @@ -2839,6 +2858,9 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
>                regulator_put(host->vmmc);
>        }
>
> +       if (host->vsdio)
> +               regulator_put(host->vsdio);
> +
>        kfree(host->adma_desc);
>        kfree(host->align_buffer);
>
> diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
> index 5666f3a..201207a 100644
> --- a/include/linux/mmc/sdhci.h
> +++ b/include/linux/mmc/sdhci.h
> @@ -94,6 +94,8 @@ struct sdhci_host {
>        const struct sdhci_ops *ops;    /* Low level hw interface */
>
>        struct regulator *vmmc; /* Power regulator */
> +       struct regulator *vsdio;        /* sdio Power regulator */
> +       unsigned char power_mode_old;   /* power supply mode */
>
>        /* Internal data */
>        struct mmc_host *mmc;   /* MMC structure */
> --
> 1.7.0.4
>
>
Zhangfei Gao Sept. 1, 2011, 1:37 a.m. UTC | #2
On Wed, Aug 31, 2011 at 10:06 PM, Eric Miao <eric.y.miao@gmail.com> wrote:
> Zhangfei,
>
> My understanding is that the card in the slot would be either MMC _or_
> SDIO and why do we need another regulator for the power on/off?
>
Hi, Eric

vsdio is used for dynamically power control to sdio, for example
application dynamically disable/enable wifi.
Then mmc_start/stop_host and mmc_power_up/down could directly power
on/off sdio via mmc_set_ios.
This also workable with runtime PM, which already introduced into mmc by Ohad.

vmmc is used to statically provided power to sd or vmmc.

Daniel once suggested reusing vmmc, however we found CD pin requires
vmmc to be alwayes on.
If vmmc is dynamically power off, CD pin will be low, which indicating
card is inserted by mistake.
For example when no card inserted, CD pin will high -> host fail to
detect sd card -> vmmc disabled in set_ios -> host thought card
inserted -> irq happen -> host redetect card ->

If there is concern of vsdio in sdhci.c, how about moving vsdio to
specific driver via call back.

Thanks
diff mbox

Patch

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 0e02cc1..e0ef7d3 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1424,6 +1424,18 @@  static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 out:
 	mmiowb();
 	spin_unlock_irqrestore(&host->lock, flags);
+
+	if (host->vsdio) {
+		if (ios->power_mode != host->power_mode_old) {
+			if (ios->power_mode == MMC_POWER_OFF)
+				regulator_disable(host->vsdio);
+
+			if (ios->power_mode == MMC_POWER_UP)
+				regulator_enable(host->vsdio);
+		}
+
+		host->power_mode_old = ios->power_mode;
+	}
 }
 
 static int check_ro(struct sdhci_host *host)
@@ -2748,6 +2760,13 @@  int sdhci_add_host(struct sdhci_host *host)
 		regulator_enable(host->vmmc);
 	}
 
+	host->vsdio = regulator_get(mmc_dev(mmc), "vsdio");
+	if (IS_ERR(host->vsdio))
+		host->vsdio = NULL;
+	else
+		printk(KERN_INFO "%s: vsdio regulator found\n",
+			mmc_hostname(mmc));
+
 	sdhci_init(host, 0);
 
 #ifdef CONFIG_MMC_DEBUG
@@ -2839,6 +2858,9 @@  void sdhci_remove_host(struct sdhci_host *host, int dead)
 		regulator_put(host->vmmc);
 	}
 
+	if (host->vsdio)
+		regulator_put(host->vsdio);
+
 	kfree(host->adma_desc);
 	kfree(host->align_buffer);
 
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
index 5666f3a..201207a 100644
--- a/include/linux/mmc/sdhci.h
+++ b/include/linux/mmc/sdhci.h
@@ -94,6 +94,8 @@  struct sdhci_host {
 	const struct sdhci_ops *ops;	/* Low level hw interface */
 
 	struct regulator *vmmc;	/* Power regulator */
+	struct regulator *vsdio;	/* sdio Power regulator */
+	unsigned char power_mode_old;	/* power supply mode */
 
 	/* Internal data */
 	struct mmc_host *mmc;	/* MMC structure */