diff options
| author | Philip Rakity <prakity@marvell.com> | 2012-05-27 18:36:44 -0700 | 
|---|---|---|
| committer | Chris Ball <cjb@laptop.org> | 2012-07-21 00:02:22 -0400 | 
| commit | bad37e1ac6b1a73ed30702b24a45c27c4f53aada (patch) | |
| tree | f296dfee6adbb7c7b781285cd447b3aed53fa0ed | |
| parent | e480606ad43bb72fd82a9bd99cdcf21829a6e9c0 (diff) | |
| download | olio-linux-3.10-bad37e1ac6b1a73ed30702b24a45c27c4f53aada.tar.xz olio-linux-3.10-bad37e1ac6b1a73ed30702b24a45c27c4f53aada.zip  | |
mmc: sdhci: if MAX_CURRENT is 0, try getting current from regulator
The sd host controller spec indicates the the MAX_CURRENT value may
be returned as 0.  In this case other methods need to be used to
return the current.  If 0 is returned and there is a regulator,
ask the regulator for how much current is available.
Signed-off-by: Philip Rakity <prakity@marvell.com>
Signed-off-by: Mark F. Brown <mark.brown314@gmail.com>
Reviewed-by: Aaron Lu <aaron.lu@amd.com>
Signed-off-by: Chris Ball <cjb@laptop.org>
| -rw-r--r-- | drivers/mmc/host/sdhci.c | 28 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci.h | 1 | 
2 files changed, 23 insertions, 6 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index f4b8b4db3a9..a0853d03b33 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2837,6 +2837,13 @@ int sdhci_add_host(struct sdhci_host *host)  			     SDHCI_RETUNING_MODE_SHIFT;  	ocr_avail = 0; + +	host->vmmc = regulator_get(mmc_dev(mmc), "vmmc"); +	if (IS_ERR(host->vmmc)) { +		pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc)); +		host->vmmc = NULL; +	} +  	/*  	 * According to SD Host Controller spec v3.00, if the Host System  	 * can afford more than 150mA, Host Driver should set XPC to 1. Also @@ -2845,6 +2852,21 @@ int sdhci_add_host(struct sdhci_host *host)  	 * value.  	 */  	max_current_caps = sdhci_readl(host, SDHCI_MAX_CURRENT); +	if (!max_current_caps && host->vmmc) { +		u32 curr = regulator_get_current_limit(host->vmmc); +		if (curr > 0) { + +			/* convert to SDHCI_MAX_CURRENT format */ +			curr = curr/1000;  /* convert to mA */ +			curr = curr/SDHCI_MAX_CURRENT_MULTIPLIER; + +			curr = min_t(u32, curr, SDHCI_MAX_CURRENT_LIMIT); +			max_current_caps = +				(curr << SDHCI_MAX_CURRENT_330_SHIFT) | +				(curr << SDHCI_MAX_CURRENT_300_SHIFT) | +				(curr << SDHCI_MAX_CURRENT_180_SHIFT); +		} +	}  	if (caps[0] & SDHCI_CAN_VDD_330) {  		int max_current_330; @@ -2995,12 +3017,6 @@ int sdhci_add_host(struct sdhci_host *host)  	if (ret)  		goto untasklet; -	host->vmmc = regulator_get(mmc_dev(mmc), "vmmc"); -	if (IS_ERR(host->vmmc)) { -		pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc)); -		host->vmmc = NULL; -	} -  	sdhci_init(host, 0);  #ifdef CONFIG_MMC_DEBUG diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index f761f23d2a2..97653ea8942 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -205,6 +205,7 @@  #define SDHCI_CAPABILITIES_1	0x44  #define SDHCI_MAX_CURRENT		0x48 +#define  SDHCI_MAX_CURRENT_LIMIT	0xFF  #define  SDHCI_MAX_CURRENT_330_MASK	0x0000FF  #define  SDHCI_MAX_CURRENT_330_SHIFT	0  #define  SDHCI_MAX_CURRENT_300_MASK	0x00FF00  |