All of lore.kernel.org
 help / color / mirror / Atom feed
From: Adrian Hunter <adrian.hunter@nokia.com>
To: Daniel Mack <daniel@caiaq.de>
Cc: "linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	Mark Brown <broonie@opensource.wolfsonmicro.com>,
	Liam Girdwood <lrg@slimlogic.co.uk>,
	Pierre Ossman <pierre@ossman.eu>,
	Andrew Morton <akpm@linux-foundation.org>,
	Matt Fleming <matt@console-pimps.org>,
	David Brownell <dbrownell@users.sourceforge.net>,
	Russell King <rmk+kernel@arm.linux.org.uk>,
	Linus Walleij <linus.walleij@stericsson.com>,
	Eric Miao <eric.y.miao@gmail.com>,
	Robert Jarzmik <robert.jarzmik@free.fr>,
	Cliff Brake <cbrake@bec-systems.com>,
	"Lavinen Jarkko (Nokia-D/Helsinki)" <jarkko.lavinen@nokia.com>,
	"linux-mmc@vger.kernel.org" <linux-mmc@vger.kernel.org>,
	"linux-arm-kernel@lists.infradead.org"
	<linux-arm-kernel@lists.infradead.org>
Subject: Re: [PATCH] mmc: move regulator handling to core
Date: Thu, 03 Dec 2009 16:27:39 +0200	[thread overview]
Message-ID: <4B17CADB.1070406@nokia.com> (raw)
In-Reply-To: <1259844390-10541-1-git-send-email-daniel@caiaq.de>

gDaniel Mack wrote:
> At the moment, regulator operations are done from individual mmc host
> drivers. This is a problem because the regulators are not claimed
> exclusively but the mmc core enables and disables them according to the
> return value of regulator_is_enabled(). That can lead to a number of
> problems and warnings when regulators are shared among multiple
> consumers or if regulators are marked as 'always_on'.
> 
> Fix this by moving the some logic to the core, and put the regulator
> reference to the mmc_host struct and let it do its own supply state
> tracking so that the reference counting in the regulator won't get
> confused.
> 
> [Note that I could only compile-test the mmci.c change]
> 
> Signed-off-by: Daniel Mack <daniel@caiaq.de>
> Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Cc: Liam Girdwood <lrg@slimlogic.co.uk>
> Cc: Pierre Ossman <pierre@ossman.eu>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Cc: Matt Fleming <matt@console-pimps.org>
> Cc: Adrian Hunter <adrian.hunter@nokia.com>
> Cc: David Brownell <dbrownell@users.sourceforge.net>
> Cc: Russell King <rmk+kernel@arm.linux.org.uk>
> Cc: Linus Walleij <linus.walleij@stericsson.com>
> Cc: Eric Miao <eric.y.miao@gmail.com>
> Cc: Robert Jarzmik <robert.jarzmik@free.fr>
> Cc: Cliff Brake <cbrake@bec-systems.com>
> Cc: Jarkko Lavinen <jarkko.lavinen@nokia.com>
> Cc: linux-mmc@vger.kernel.org
> Cc: linux-arm-kernel@lists.infradead.org
> ---
>  drivers/mmc/core/core.c   |   36 ++++++++++++++++++++----------------
>  drivers/mmc/core/host.c   |    3 +++
>  drivers/mmc/host/mmci.c   |   28 ++++++++++++----------------
>  drivers/mmc/host/mmci.h   |    1 -
>  drivers/mmc/host/pxamci.c |   20 ++++++++------------
>  include/linux/mmc/host.h  |   10 ++++++----

What about arch/arm/mach-omap2/mmc-twl4030.c ?


>  6 files changed, 49 insertions(+), 49 deletions(-)
> 
> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
> index 7dab2e5..9acb655 100644
> --- a/drivers/mmc/core/core.c
> +++ b/drivers/mmc/core/core.c
> @@ -727,13 +727,13 @@ EXPORT_SYMBOL(mmc_vddrange_to_ocrmask);
>   * regulator.  This would normally be called before registering the
>   * MMC host adapter.
>   */
> -int mmc_regulator_get_ocrmask(struct regulator *supply)
> +int mmc_regulator_get_ocrmask(struct mmc_host *host)
>  {
>  	int			result = 0;
>  	int			count;
>  	int			i;
>  
> -	count = regulator_count_voltages(supply);
> +	count = regulator_count_voltages(host->vcc);
>  	if (count < 0)
>  		return count;
>  
> @@ -741,7 +741,7 @@ int mmc_regulator_get_ocrmask(struct regulator *supply)
>  		int		vdd_uV;
>  		int		vdd_mV;
>  
> -		vdd_uV = regulator_list_voltage(supply, i);
> +		vdd_uV = regulator_list_voltage(host->vcc, i);
>  		if (vdd_uV <= 0)
>  			continue;
>  
> @@ -755,24 +755,22 @@ EXPORT_SYMBOL(mmc_regulator_get_ocrmask);
>  
>  /**
>   * mmc_regulator_set_ocr - set regulator to match host->ios voltage
> + * @host: the mmc_host
>   * @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
> + * the registered 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 mmc_regulator_set_ocr(struct mmc_host *host, 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 (!host->vcc || IS_ERR(host->vcc))
> +		return -EINVAL;
>  
>  	if (vdd_bit) {
>  		int		tmp;
> @@ -795,18 +793,24 @@ int mmc_regulator_set_ocr(struct regulator *supply, unsigned short vdd_bit)
>  		/* avoid needless changes to this voltage; the regulator
>  		 * might not allow this operation
>  		 */
> -		voltage = regulator_get_voltage(supply);
> +		voltage = regulator_get_voltage(host->vcc);
>  		if (voltage < 0)
>  			result = voltage;
>  		else if (voltage < min_uV || voltage > max_uV)
> -			result = regulator_set_voltage(supply, min_uV, max_uV);
> +			result = regulator_set_voltage(host->vcc, min_uV, max_uV);
>  		else
>  			result = 0;
>  
> -		if (result == 0 && !enabled)
> -			result = regulator_enable(supply);
> -	} else if (enabled) {
> -		result = regulator_disable(supply);
> +		if (result == 0 && !host->vcc_enabled) {
> +			result = regulator_enable(host->vcc);
> +
> +			if (result == 0)
> +				host->vcc_enabled = 1;
> +		}
> +	} else if (host->vcc_enabled) {
> +		result = regulator_disable(host->vcc);
> +		if (result == 0)
> +			host->vcc_enabled = 0;
>  	}
>  
>  	return result;
> diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
> index a268d12..f422d1f 100644
> --- a/drivers/mmc/core/host.c
> +++ b/drivers/mmc/core/host.c
> @@ -18,6 +18,7 @@
>  #include <linux/leds.h>
>  
>  #include <linux/mmc/host.h>
> +#include <linux/regulator/consumer.h>
>  
>  #include "core.h"
>  #include "host.h"
> @@ -154,6 +155,8 @@ void mmc_remove_host(struct mmc_host *host)
>  	mmc_remove_host_debugfs(host);
>  #endif
>  
> +	regulator_put(host->vcc);
> +

If the core is doing a 'regulator_put()' shouldn't it also be doing
a 'regulator_get()'?  Why not leave it to the drivers?

>  	device_del(&host->class_dev);
>  
>  	led_trigger_unregister_simple(host->led);
> diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
> index 705a589..eea9cde 100644
> --- a/drivers/mmc/host/mmci.c
> +++ b/drivers/mmc/host/mmci.c
> @@ -455,15 +455,15 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>  
>  	switch (ios->power_mode) {
>  	case MMC_POWER_OFF:
> -		if(host->vcc &&
> -		   regulator_is_enabled(host->vcc))
> -			regulator_disable(host->vcc);
> +		if(mmc->vcc && mmc->vcc_enabled) {
> +			regulator_disable(mmc->vcc);
> +			mmc->vcc_enabled = 0;
> +		}
>  		break;
>  	case MMC_POWER_UP:
>  #ifdef CONFIG_REGULATOR
> -		if (host->vcc)
> -			/* This implicitly enables the regulator */
> -			mmc_regulator_set_ocr(host->vcc, ios->vdd);
> +		/* This implicitly enables the regulator */
> +		mmc_regulator_set_ocr(mmc, ios->vdd);
>  #endif
>  		/*
>  		 * The translate_vdd function is not used if you have
> @@ -473,7 +473,7 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>  		 * a regulator, we might have some other platform specific
>  		 * power control behind this translate function.
>  		 */
> -		if (!host->vcc && host->plat->translate_vdd)
> +		if (!mmc->vcc && host->plat->translate_vdd)
>  			pwr |= host->plat->translate_vdd(mmc_dev(mmc), ios->vdd);
>  		/* The ST version does not have this, fall through to POWER_ON */
>  		if (host->hw_designer != AMBA_VENDOR_ST) {
> @@ -621,11 +621,11 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
>  	mmc->f_max = min(host->mclk, fmax);
>  #ifdef CONFIG_REGULATOR
>  	/* If we're using the regulator framework, try to fetch a regulator */
> -	host->vcc = regulator_get(&dev->dev, "vmmc");
> -	if (IS_ERR(host->vcc))
> -		host->vcc = NULL;
> +	mmc->vcc = regulator_get(&dev->dev, "vmmc");
> +	if (IS_ERR(mmc->vcc))
> +		mmc->vcc = NULL;
>  	else {
> -		int mask = mmc_regulator_get_ocrmask(host->vcc);
> +		int mask = mmc_regulator_get_ocrmask(mmc);
>  
>  		if (mask < 0)
>  			dev_err(&dev->dev, "error getting OCR mask (%d)\n",
> @@ -640,7 +640,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
>  	}
>  #endif
>  	/* Fall back to platform data if no regulator is found */
> -	if (host->vcc == NULL)
> +	if (mmc->vcc == NULL)
>  		mmc->ocr_avail = plat->ocr_mask;
>  	mmc->caps = plat->capabilities;
>  
> @@ -777,10 +777,6 @@ static int __devexit mmci_remove(struct amba_device *dev)
>  		clk_disable(host->clk);
>  		clk_put(host->clk);
>  
> -		if (regulator_is_enabled(host->vcc))
> -			regulator_disable(host->vcc);
> -		regulator_put(host->vcc);
> -
>  		mmc_free_host(mmc);
>  
>  		amba_release_regions(dev);
> diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
> index 1ceb9a9..a7f9a51 100644
> --- a/drivers/mmc/host/mmci.h
> +++ b/drivers/mmc/host/mmci.h
> @@ -175,7 +175,6 @@ struct mmci_host {
>  	struct scatterlist	*sg_ptr;
>  	unsigned int		sg_off;
>  	unsigned int		size;
> -	struct regulator	*vcc;
>  };
>  
>  static inline void mmci_init_sg(struct mmci_host *host, struct mmc_data *data)
> diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
> index fb0978c..25d2367 100644
> --- a/drivers/mmc/host/pxamci.c
> +++ b/drivers/mmc/host/pxamci.c
> @@ -69,25 +69,23 @@ struct pxamci_host {
>  	unsigned int		dma_dir;
>  	unsigned int		dma_drcmrrx;
>  	unsigned int		dma_drcmrtx;
> -
> -	struct regulator	*vcc;
>  };
>  
>  static inline void pxamci_init_ocr(struct pxamci_host *host)
>  {
>  #ifdef CONFIG_REGULATOR
> -	host->vcc = regulator_get(mmc_dev(host->mmc), "vmmc");
> +	host->mmc->vcc = regulator_get(mmc_dev(host->mmc), "vmmc");
>  
> -	if (IS_ERR(host->vcc))
> -		host->vcc = NULL;
> +	if (IS_ERR(host->mmc->vcc))
> +		host->mmc->vcc = NULL;
>  	else {
> -		host->mmc->ocr_avail = mmc_regulator_get_ocrmask(host->vcc);
> +		host->mmc->ocr_avail = mmc_regulator_get_ocrmask(host->mmc);
>  		if (host->pdata && host->pdata->ocr_mask)
>  			dev_warn(mmc_dev(host->mmc),
>  				"given ocr_mask will not be used\n");
>  	}
>  #endif
> -	if (host->vcc == NULL) {
> +	if (host->mmc->vcc == NULL) {
>  		/* fall-back to platform data */
>  		host->mmc->ocr_avail = host->pdata ?
>  			host->pdata->ocr_mask :
> @@ -100,10 +98,10 @@ static inline void pxamci_set_power(struct pxamci_host *host, unsigned int vdd)
>  	int on;
>  
>  #ifdef CONFIG_REGULATOR
> -	if (host->vcc)
> -		mmc_regulator_set_ocr(host->vcc, vdd);
> +	if (host->mmc->vcc)
> +		mmc_regulator_set_ocr(host->mmc, vdd);
>  #endif
> -	if (!host->vcc && host->pdata &&
> +	if (!host->mmc->vcc && host->pdata &&
>  	    gpio_is_valid(host->pdata->gpio_power)) {
>  		on = ((1 << vdd) & host->pdata->ocr_mask);
>  		gpio_set_value(host->pdata->gpio_power,
> @@ -775,8 +773,6 @@ static int pxamci_remove(struct platform_device *pdev)
>  			gpio_free(gpio_ro);
>  		if (gpio_is_valid(gpio_power))
>  			gpio_free(gpio_power);
> -		if (host->vcc)
> -			regulator_put(host->vcc);
>  
>  		if (host->pdata && host->pdata->exit)
>  			host->pdata->exit(&pdev->dev, mmc);
> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
> index eaf3636..2c1b079 100644
> --- a/include/linux/mmc/host.h
> +++ b/include/linux/mmc/host.h
> @@ -111,6 +111,7 @@ struct mmc_host_ops {
>  
>  struct mmc_card;
>  struct device;
> +struct regulator;
>  
>  struct mmc_host {
>  	struct device		*parent;
> @@ -203,6 +204,9 @@ struct mmc_host {
>  
>  	struct dentry		*debugfs_root;
>  
> +	struct regulator	*vcc;
> +	unsigned int		 vcc_enabled:1;
> +
>  	unsigned long		private[0] ____cacheline_aligned;
>  };
>  
> @@ -237,10 +241,8 @@ static inline void mmc_signal_sdio_irq(struct mmc_host *host)
>  	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);
> +int mmc_regulator_get_ocrmask(struct mmc_host *host);
> +int mmc_regulator_set_ocr(struct mmc_host *host, unsigned short vdd_bit);
>  
>  int mmc_card_awake(struct mmc_host *host);
>  int mmc_card_sleep(struct mmc_host *host);


WARNING: multiple messages have this Message-ID (diff)
From: adrian.hunter@nokia.com (Adrian Hunter)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH] mmc: move regulator handling to core
Date: Thu, 03 Dec 2009 16:27:39 +0200	[thread overview]
Message-ID: <4B17CADB.1070406@nokia.com> (raw)
In-Reply-To: <1259844390-10541-1-git-send-email-daniel@caiaq.de>

gDaniel Mack wrote:
> At the moment, regulator operations are done from individual mmc host
> drivers. This is a problem because the regulators are not claimed
> exclusively but the mmc core enables and disables them according to the
> return value of regulator_is_enabled(). That can lead to a number of
> problems and warnings when regulators are shared among multiple
> consumers or if regulators are marked as 'always_on'.
> 
> Fix this by moving the some logic to the core, and put the regulator
> reference to the mmc_host struct and let it do its own supply state
> tracking so that the reference counting in the regulator won't get
> confused.
> 
> [Note that I could only compile-test the mmci.c change]
> 
> Signed-off-by: Daniel Mack <daniel@caiaq.de>
> Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Cc: Liam Girdwood <lrg@slimlogic.co.uk>
> Cc: Pierre Ossman <pierre@ossman.eu>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Cc: Matt Fleming <matt@console-pimps.org>
> Cc: Adrian Hunter <adrian.hunter@nokia.com>
> Cc: David Brownell <dbrownell@users.sourceforge.net>
> Cc: Russell King <rmk+kernel@arm.linux.org.uk>
> Cc: Linus Walleij <linus.walleij@stericsson.com>
> Cc: Eric Miao <eric.y.miao@gmail.com>
> Cc: Robert Jarzmik <robert.jarzmik@free.fr>
> Cc: Cliff Brake <cbrake@bec-systems.com>
> Cc: Jarkko Lavinen <jarkko.lavinen@nokia.com>
> Cc: linux-mmc at vger.kernel.org
> Cc: linux-arm-kernel at lists.infradead.org
> ---
>  drivers/mmc/core/core.c   |   36 ++++++++++++++++++++----------------
>  drivers/mmc/core/host.c   |    3 +++
>  drivers/mmc/host/mmci.c   |   28 ++++++++++++----------------
>  drivers/mmc/host/mmci.h   |    1 -
>  drivers/mmc/host/pxamci.c |   20 ++++++++------------
>  include/linux/mmc/host.h  |   10 ++++++----

What about arch/arm/mach-omap2/mmc-twl4030.c ?


>  6 files changed, 49 insertions(+), 49 deletions(-)
> 
> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
> index 7dab2e5..9acb655 100644
> --- a/drivers/mmc/core/core.c
> +++ b/drivers/mmc/core/core.c
> @@ -727,13 +727,13 @@ EXPORT_SYMBOL(mmc_vddrange_to_ocrmask);
>   * regulator.  This would normally be called before registering the
>   * MMC host adapter.
>   */
> -int mmc_regulator_get_ocrmask(struct regulator *supply)
> +int mmc_regulator_get_ocrmask(struct mmc_host *host)
>  {
>  	int			result = 0;
>  	int			count;
>  	int			i;
>  
> -	count = regulator_count_voltages(supply);
> +	count = regulator_count_voltages(host->vcc);
>  	if (count < 0)
>  		return count;
>  
> @@ -741,7 +741,7 @@ int mmc_regulator_get_ocrmask(struct regulator *supply)
>  		int		vdd_uV;
>  		int		vdd_mV;
>  
> -		vdd_uV = regulator_list_voltage(supply, i);
> +		vdd_uV = regulator_list_voltage(host->vcc, i);
>  		if (vdd_uV <= 0)
>  			continue;
>  
> @@ -755,24 +755,22 @@ EXPORT_SYMBOL(mmc_regulator_get_ocrmask);
>  
>  /**
>   * mmc_regulator_set_ocr - set regulator to match host->ios voltage
> + * @host: the mmc_host
>   * @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
> + * the registered 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 mmc_regulator_set_ocr(struct mmc_host *host, 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 (!host->vcc || IS_ERR(host->vcc))
> +		return -EINVAL;
>  
>  	if (vdd_bit) {
>  		int		tmp;
> @@ -795,18 +793,24 @@ int mmc_regulator_set_ocr(struct regulator *supply, unsigned short vdd_bit)
>  		/* avoid needless changes to this voltage; the regulator
>  		 * might not allow this operation
>  		 */
> -		voltage = regulator_get_voltage(supply);
> +		voltage = regulator_get_voltage(host->vcc);
>  		if (voltage < 0)
>  			result = voltage;
>  		else if (voltage < min_uV || voltage > max_uV)
> -			result = regulator_set_voltage(supply, min_uV, max_uV);
> +			result = regulator_set_voltage(host->vcc, min_uV, max_uV);
>  		else
>  			result = 0;
>  
> -		if (result == 0 && !enabled)
> -			result = regulator_enable(supply);
> -	} else if (enabled) {
> -		result = regulator_disable(supply);
> +		if (result == 0 && !host->vcc_enabled) {
> +			result = regulator_enable(host->vcc);
> +
> +			if (result == 0)
> +				host->vcc_enabled = 1;
> +		}
> +	} else if (host->vcc_enabled) {
> +		result = regulator_disable(host->vcc);
> +		if (result == 0)
> +			host->vcc_enabled = 0;
>  	}
>  
>  	return result;
> diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
> index a268d12..f422d1f 100644
> --- a/drivers/mmc/core/host.c
> +++ b/drivers/mmc/core/host.c
> @@ -18,6 +18,7 @@
>  #include <linux/leds.h>
>  
>  #include <linux/mmc/host.h>
> +#include <linux/regulator/consumer.h>
>  
>  #include "core.h"
>  #include "host.h"
> @@ -154,6 +155,8 @@ void mmc_remove_host(struct mmc_host *host)
>  	mmc_remove_host_debugfs(host);
>  #endif
>  
> +	regulator_put(host->vcc);
> +

If the core is doing a 'regulator_put()' shouldn't it also be doing
a 'regulator_get()'?  Why not leave it to the drivers?

>  	device_del(&host->class_dev);
>  
>  	led_trigger_unregister_simple(host->led);
> diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
> index 705a589..eea9cde 100644
> --- a/drivers/mmc/host/mmci.c
> +++ b/drivers/mmc/host/mmci.c
> @@ -455,15 +455,15 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>  
>  	switch (ios->power_mode) {
>  	case MMC_POWER_OFF:
> -		if(host->vcc &&
> -		   regulator_is_enabled(host->vcc))
> -			regulator_disable(host->vcc);
> +		if(mmc->vcc && mmc->vcc_enabled) {
> +			regulator_disable(mmc->vcc);
> +			mmc->vcc_enabled = 0;
> +		}
>  		break;
>  	case MMC_POWER_UP:
>  #ifdef CONFIG_REGULATOR
> -		if (host->vcc)
> -			/* This implicitly enables the regulator */
> -			mmc_regulator_set_ocr(host->vcc, ios->vdd);
> +		/* This implicitly enables the regulator */
> +		mmc_regulator_set_ocr(mmc, ios->vdd);
>  #endif
>  		/*
>  		 * The translate_vdd function is not used if you have
> @@ -473,7 +473,7 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>  		 * a regulator, we might have some other platform specific
>  		 * power control behind this translate function.
>  		 */
> -		if (!host->vcc && host->plat->translate_vdd)
> +		if (!mmc->vcc && host->plat->translate_vdd)
>  			pwr |= host->plat->translate_vdd(mmc_dev(mmc), ios->vdd);
>  		/* The ST version does not have this, fall through to POWER_ON */
>  		if (host->hw_designer != AMBA_VENDOR_ST) {
> @@ -621,11 +621,11 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
>  	mmc->f_max = min(host->mclk, fmax);
>  #ifdef CONFIG_REGULATOR
>  	/* If we're using the regulator framework, try to fetch a regulator */
> -	host->vcc = regulator_get(&dev->dev, "vmmc");
> -	if (IS_ERR(host->vcc))
> -		host->vcc = NULL;
> +	mmc->vcc = regulator_get(&dev->dev, "vmmc");
> +	if (IS_ERR(mmc->vcc))
> +		mmc->vcc = NULL;
>  	else {
> -		int mask = mmc_regulator_get_ocrmask(host->vcc);
> +		int mask = mmc_regulator_get_ocrmask(mmc);
>  
>  		if (mask < 0)
>  			dev_err(&dev->dev, "error getting OCR mask (%d)\n",
> @@ -640,7 +640,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
>  	}
>  #endif
>  	/* Fall back to platform data if no regulator is found */
> -	if (host->vcc == NULL)
> +	if (mmc->vcc == NULL)
>  		mmc->ocr_avail = plat->ocr_mask;
>  	mmc->caps = plat->capabilities;
>  
> @@ -777,10 +777,6 @@ static int __devexit mmci_remove(struct amba_device *dev)
>  		clk_disable(host->clk);
>  		clk_put(host->clk);
>  
> -		if (regulator_is_enabled(host->vcc))
> -			regulator_disable(host->vcc);
> -		regulator_put(host->vcc);
> -
>  		mmc_free_host(mmc);
>  
>  		amba_release_regions(dev);
> diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
> index 1ceb9a9..a7f9a51 100644
> --- a/drivers/mmc/host/mmci.h
> +++ b/drivers/mmc/host/mmci.h
> @@ -175,7 +175,6 @@ struct mmci_host {
>  	struct scatterlist	*sg_ptr;
>  	unsigned int		sg_off;
>  	unsigned int		size;
> -	struct regulator	*vcc;
>  };
>  
>  static inline void mmci_init_sg(struct mmci_host *host, struct mmc_data *data)
> diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
> index fb0978c..25d2367 100644
> --- a/drivers/mmc/host/pxamci.c
> +++ b/drivers/mmc/host/pxamci.c
> @@ -69,25 +69,23 @@ struct pxamci_host {
>  	unsigned int		dma_dir;
>  	unsigned int		dma_drcmrrx;
>  	unsigned int		dma_drcmrtx;
> -
> -	struct regulator	*vcc;
>  };
>  
>  static inline void pxamci_init_ocr(struct pxamci_host *host)
>  {
>  #ifdef CONFIG_REGULATOR
> -	host->vcc = regulator_get(mmc_dev(host->mmc), "vmmc");
> +	host->mmc->vcc = regulator_get(mmc_dev(host->mmc), "vmmc");
>  
> -	if (IS_ERR(host->vcc))
> -		host->vcc = NULL;
> +	if (IS_ERR(host->mmc->vcc))
> +		host->mmc->vcc = NULL;
>  	else {
> -		host->mmc->ocr_avail = mmc_regulator_get_ocrmask(host->vcc);
> +		host->mmc->ocr_avail = mmc_regulator_get_ocrmask(host->mmc);
>  		if (host->pdata && host->pdata->ocr_mask)
>  			dev_warn(mmc_dev(host->mmc),
>  				"given ocr_mask will not be used\n");
>  	}
>  #endif
> -	if (host->vcc == NULL) {
> +	if (host->mmc->vcc == NULL) {
>  		/* fall-back to platform data */
>  		host->mmc->ocr_avail = host->pdata ?
>  			host->pdata->ocr_mask :
> @@ -100,10 +98,10 @@ static inline void pxamci_set_power(struct pxamci_host *host, unsigned int vdd)
>  	int on;
>  
>  #ifdef CONFIG_REGULATOR
> -	if (host->vcc)
> -		mmc_regulator_set_ocr(host->vcc, vdd);
> +	if (host->mmc->vcc)
> +		mmc_regulator_set_ocr(host->mmc, vdd);
>  #endif
> -	if (!host->vcc && host->pdata &&
> +	if (!host->mmc->vcc && host->pdata &&
>  	    gpio_is_valid(host->pdata->gpio_power)) {
>  		on = ((1 << vdd) & host->pdata->ocr_mask);
>  		gpio_set_value(host->pdata->gpio_power,
> @@ -775,8 +773,6 @@ static int pxamci_remove(struct platform_device *pdev)
>  			gpio_free(gpio_ro);
>  		if (gpio_is_valid(gpio_power))
>  			gpio_free(gpio_power);
> -		if (host->vcc)
> -			regulator_put(host->vcc);
>  
>  		if (host->pdata && host->pdata->exit)
>  			host->pdata->exit(&pdev->dev, mmc);
> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
> index eaf3636..2c1b079 100644
> --- a/include/linux/mmc/host.h
> +++ b/include/linux/mmc/host.h
> @@ -111,6 +111,7 @@ struct mmc_host_ops {
>  
>  struct mmc_card;
>  struct device;
> +struct regulator;
>  
>  struct mmc_host {
>  	struct device		*parent;
> @@ -203,6 +204,9 @@ struct mmc_host {
>  
>  	struct dentry		*debugfs_root;
>  
> +	struct regulator	*vcc;
> +	unsigned int		 vcc_enabled:1;
> +
>  	unsigned long		private[0] ____cacheline_aligned;
>  };
>  
> @@ -237,10 +241,8 @@ static inline void mmc_signal_sdio_irq(struct mmc_host *host)
>  	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);
> +int mmc_regulator_get_ocrmask(struct mmc_host *host);
> +int mmc_regulator_set_ocr(struct mmc_host *host, unsigned short vdd_bit);
>  
>  int mmc_card_awake(struct mmc_host *host);
>  int mmc_card_sleep(struct mmc_host *host);

  parent reply	other threads:[~2009-12-03 14:29 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-12-03 12:46 [PATCH] mmc: move regulator handling to core Daniel Mack
2009-12-03 12:46 ` Daniel Mack
2009-12-03 13:06 ` Mark Brown
2009-12-03 13:06   ` Mark Brown
2009-12-03 13:14   ` Daniel Mack
2009-12-03 13:14     ` Daniel Mack
2009-12-03 13:22     ` Mark Brown
2009-12-03 13:22       ` Mark Brown
2009-12-03 13:32       ` Daniel Mack
2009-12-03 13:32         ` Daniel Mack
2009-12-03 13:40         ` Mark Brown
2009-12-03 13:40           ` Mark Brown
2009-12-03 13:43           ` Daniel Mack
2009-12-03 13:43             ` Daniel Mack
2009-12-03 14:58       ` Russell King - ARM Linux
2009-12-03 14:58         ` Russell King - ARM Linux
2009-12-03 15:09         ` Mark Brown
2009-12-03 15:09           ` Mark Brown
2009-12-03 14:27 ` Adrian Hunter [this message]
2009-12-03 14:27   ` Adrian Hunter
2009-12-03 19:20   ` Daniel Mack
2009-12-03 19:20     ` Daniel Mack
2009-12-03 20:12     ` Adrian Hunter
2009-12-03 20:12       ` Adrian Hunter
2009-12-04 11:58       ` Daniel Mack
2009-12-04 11:58         ` Daniel Mack
2009-12-12  0:58         ` Daniel Mack
2009-12-12  0:58           ` Daniel Mack
2009-12-14 17:43           ` Madhusudhan
2009-12-14 17:43             ` Madhusudhan
2009-12-14 17:43             ` Madhusudhan
2009-12-15  5:44         ` David Brownell
2009-12-15  5:44           ` David Brownell
2009-12-15  5:44           ` David Brownell
2010-08-27 19:03 ` Chris Ball
2010-08-27 19:03   ` Chris Ball
2010-08-28 14:48   ` Linus Walleij
2010-08-28 14:48     ` Linus Walleij
2010-08-29 13:27     ` Mark Brown
2010-08-29 13:27       ` Mark Brown
2010-08-29 15:30       ` Linus Walleij
2010-08-29 15:30         ` Linus Walleij
2010-08-31 11:07         ` Mark Brown
2010-08-31 11:07           ` Mark Brown
2010-08-31 12:15           ` Linus Walleij
2010-08-31 12:15             ` Linus Walleij
2010-08-31 12:15             ` Linus Walleij

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=4B17CADB.1070406@nokia.com \
    --to=adrian.hunter@nokia.com \
    --cc=akpm@linux-foundation.org \
    --cc=broonie@opensource.wolfsonmicro.com \
    --cc=cbrake@bec-systems.com \
    --cc=daniel@caiaq.de \
    --cc=dbrownell@users.sourceforge.net \
    --cc=eric.y.miao@gmail.com \
    --cc=jarkko.lavinen@nokia.com \
    --cc=linus.walleij@stericsson.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mmc@vger.kernel.org \
    --cc=lrg@slimlogic.co.uk \
    --cc=matt@console-pimps.org \
    --cc=pierre@ossman.eu \
    --cc=rmk+kernel@arm.linux.org.uk \
    --cc=robert.jarzmik@free.fr \
    /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.