aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@intel.com>2011-12-27 08:48:41 -0500
committerChris Ball <cjb@laptop.org>2012-01-11 23:58:47 -0500
commitceb6143b2df81c8a554bd5de898087926568cc51 (patch)
treed424e582d5d8ea0e350a30e0c4516345b86950ce /drivers/mmc/host
parent17e9ff559a7dbb7a6df332007d2ffcd3e7d83fba (diff)
mmc: sdhci: fix vmmc handling
Presently the vmmc regulator is enabled when the host controller is added and disabled when it is removed. However, the vmmc regulator should be under the control of the upper layers via ->set_ios(). Make it so. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/host')
-rw-r--r--drivers/mmc/host/sdhci.c43
1 files changed, 21 insertions, 22 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index ab6018fc2338..6a35d0368117 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1170,7 +1170,7 @@ out:
1170 host->clock = clock; 1170 host->clock = clock;
1171} 1171}
1172 1172
1173static void sdhci_set_power(struct sdhci_host *host, unsigned short power) 1173static int sdhci_set_power(struct sdhci_host *host, unsigned short power)
1174{ 1174{
1175 u8 pwr = 0; 1175 u8 pwr = 0;
1176 1176
@@ -1193,13 +1193,13 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
1193 } 1193 }
1194 1194
1195 if (host->pwr == pwr) 1195 if (host->pwr == pwr)
1196 return; 1196 return -1;
1197 1197
1198 host->pwr = pwr; 1198 host->pwr = pwr;
1199 1199
1200 if (pwr == 0) { 1200 if (pwr == 0) {
1201 sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); 1201 sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
1202 return; 1202 return 0;
1203 } 1203 }
1204 1204
1205 /* 1205 /*
@@ -1226,6 +1226,8 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
1226 */ 1226 */
1227 if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER) 1227 if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER)
1228 mdelay(10); 1228 mdelay(10);
1229
1230 return power;
1229} 1231}
1230 1232
1231/*****************************************************************************\ 1233/*****************************************************************************\
@@ -1307,12 +1309,17 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
1307static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) 1309static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
1308{ 1310{
1309 unsigned long flags; 1311 unsigned long flags;
1312 int vdd_bit = -1;
1310 u8 ctrl; 1313 u8 ctrl;
1311 1314
1312 spin_lock_irqsave(&host->lock, flags); 1315 spin_lock_irqsave(&host->lock, flags);
1313 1316
1314 if (host->flags & SDHCI_DEVICE_DEAD) 1317 if (host->flags & SDHCI_DEVICE_DEAD) {
1315 goto out; 1318 spin_unlock_irqrestore(&host->lock, flags);
1319 if (host->vmmc && ios->power_mode == MMC_POWER_OFF)
1320 mmc_regulator_set_ocr(host->mmc, host->vmmc, 0);
1321 return;
1322 }
1316 1323
1317 /* 1324 /*
1318 * Reset the chip on each power off. 1325 * Reset the chip on each power off.
@@ -1326,9 +1333,15 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
1326 sdhci_set_clock(host, ios->clock); 1333 sdhci_set_clock(host, ios->clock);
1327 1334
1328 if (ios->power_mode == MMC_POWER_OFF) 1335 if (ios->power_mode == MMC_POWER_OFF)
1329 sdhci_set_power(host, -1); 1336 vdd_bit = sdhci_set_power(host, -1);
1330 else 1337 else
1331 sdhci_set_power(host, ios->vdd); 1338 vdd_bit = sdhci_set_power(host, ios->vdd);
1339
1340 if (host->vmmc && vdd_bit != -1) {
1341 spin_unlock_irqrestore(&host->lock, flags);
1342 mmc_regulator_set_ocr(host->mmc, host->vmmc, vdd_bit);
1343 spin_lock_irqsave(&host->lock, flags);
1344 }
1332 1345
1333 if (host->ops->platform_send_init_74_clocks) 1346 if (host->ops->platform_send_init_74_clocks)
1334 host->ops->platform_send_init_74_clocks(host, ios->power_mode); 1347 host->ops->platform_send_init_74_clocks(host, ios->power_mode);
@@ -1453,7 +1466,6 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
1453 if(host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS) 1466 if(host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS)
1454 sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); 1467 sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
1455 1468
1456out:
1457 mmiowb(); 1469 mmiowb();
1458 spin_unlock_irqrestore(&host->lock, flags); 1470 spin_unlock_irqrestore(&host->lock, flags);
1459} 1471}
@@ -2357,9 +2369,6 @@ int sdhci_suspend_host(struct sdhci_host *host)
2357 2369
2358 free_irq(host->irq, host); 2370 free_irq(host->irq, host);
2359 2371
2360 if (host->vmmc)
2361 ret = regulator_disable(host->vmmc);
2362
2363 return ret; 2372 return ret;
2364} 2373}
2365 2374
@@ -2369,12 +2378,6 @@ int sdhci_resume_host(struct sdhci_host *host)
2369{ 2378{
2370 int ret; 2379 int ret;
2371 2380
2372 if (host->vmmc) {
2373 int ret = regulator_enable(host->vmmc);
2374 if (ret)
2375 return ret;
2376 }
2377
2378 if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 2381 if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
2379 if (host->ops->enable_dma) 2382 if (host->ops->enable_dma)
2380 host->ops->enable_dma(host); 2383 host->ops->enable_dma(host);
@@ -2936,8 +2939,6 @@ int sdhci_add_host(struct sdhci_host *host)
2936 if (IS_ERR(host->vmmc)) { 2939 if (IS_ERR(host->vmmc)) {
2937 pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc)); 2940 pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc));
2938 host->vmmc = NULL; 2941 host->vmmc = NULL;
2939 } else {
2940 regulator_enable(host->vmmc);
2941 } 2942 }
2942 2943
2943 sdhci_init(host, 0); 2944 sdhci_init(host, 0);
@@ -3026,10 +3027,8 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
3026 tasklet_kill(&host->card_tasklet); 3027 tasklet_kill(&host->card_tasklet);
3027 tasklet_kill(&host->finish_tasklet); 3028 tasklet_kill(&host->finish_tasklet);
3028 3029
3029 if (host->vmmc) { 3030 if (host->vmmc)
3030 regulator_disable(host->vmmc);
3031 regulator_put(host->vmmc); 3031 regulator_put(host->vmmc);
3032 }
3033 3032
3034 kfree(host->adma_desc); 3033 kfree(host->adma_desc);
3035 kfree(host->align_buffer); 3034 kfree(host->align_buffer);