aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorPhilip Rakity <prakity@marvell.com>2012-05-27 21:36:44 -0400
committerChris Ball <cjb@laptop.org>2012-07-21 00:02:22 -0400
commitbad37e1ac6b1a73ed30702b24a45c27c4f53aada (patch)
treef296dfee6adbb7c7b781285cd447b3aed53fa0ed /drivers
parente480606ad43bb72fd82a9bd99cdcf21829a6e9c0 (diff)
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/host/sdhci.c28
-rw-r--r--drivers/mmc/host/sdhci.h1
2 files changed, 23 insertions, 6 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index f4b8b4db3a9a..a0853d03b330 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)
2837 SDHCI_RETUNING_MODE_SHIFT; 2837 SDHCI_RETUNING_MODE_SHIFT;
2838 2838
2839 ocr_avail = 0; 2839 ocr_avail = 0;
2840
2841 host->vmmc = regulator_get(mmc_dev(mmc), "vmmc");
2842 if (IS_ERR(host->vmmc)) {
2843 pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc));
2844 host->vmmc = NULL;
2845 }
2846
2840 /* 2847 /*
2841 * According to SD Host Controller spec v3.00, if the Host System 2848 * According to SD Host Controller spec v3.00, if the Host System
2842 * can afford more than 150mA, Host Driver should set XPC to 1. Also 2849 * 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)
2845 * value. 2852 * value.
2846 */ 2853 */
2847 max_current_caps = sdhci_readl(host, SDHCI_MAX_CURRENT); 2854 max_current_caps = sdhci_readl(host, SDHCI_MAX_CURRENT);
2855 if (!max_current_caps && host->vmmc) {
2856 u32 curr = regulator_get_current_limit(host->vmmc);
2857 if (curr > 0) {
2858
2859 /* convert to SDHCI_MAX_CURRENT format */
2860 curr = curr/1000; /* convert to mA */
2861 curr = curr/SDHCI_MAX_CURRENT_MULTIPLIER;
2862
2863 curr = min_t(u32, curr, SDHCI_MAX_CURRENT_LIMIT);
2864 max_current_caps =
2865 (curr << SDHCI_MAX_CURRENT_330_SHIFT) |
2866 (curr << SDHCI_MAX_CURRENT_300_SHIFT) |
2867 (curr << SDHCI_MAX_CURRENT_180_SHIFT);
2868 }
2869 }
2848 2870
2849 if (caps[0] & SDHCI_CAN_VDD_330) { 2871 if (caps[0] & SDHCI_CAN_VDD_330) {
2850 int max_current_330; 2872 int max_current_330;
@@ -2995,12 +3017,6 @@ int sdhci_add_host(struct sdhci_host *host)
2995 if (ret) 3017 if (ret)
2996 goto untasklet; 3018 goto untasklet;
2997 3019
2998 host->vmmc = regulator_get(mmc_dev(mmc), "vmmc");
2999 if (IS_ERR(host->vmmc)) {
3000 pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc));
3001 host->vmmc = NULL;
3002 }
3003
3004 sdhci_init(host, 0); 3020 sdhci_init(host, 0);
3005 3021
3006#ifdef CONFIG_MMC_DEBUG 3022#ifdef CONFIG_MMC_DEBUG
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index f761f23d2a28..97653ea8942b 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -205,6 +205,7 @@
205#define SDHCI_CAPABILITIES_1 0x44 205#define SDHCI_CAPABILITIES_1 0x44
206 206
207#define SDHCI_MAX_CURRENT 0x48 207#define SDHCI_MAX_CURRENT 0x48
208#define SDHCI_MAX_CURRENT_LIMIT 0xFF
208#define SDHCI_MAX_CURRENT_330_MASK 0x0000FF 209#define SDHCI_MAX_CURRENT_330_MASK 0x0000FF
209#define SDHCI_MAX_CURRENT_330_SHIFT 0 210#define SDHCI_MAX_CURRENT_330_SHIFT 0
210#define SDHCI_MAX_CURRENT_300_MASK 0x00FF00 211#define SDHCI_MAX_CURRENT_300_MASK 0x00FF00