aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorGirish K S <girish.shivananjappa@linaro.org>2012-01-31 05:14:03 -0500
committerChris Ball <cjb@laptop.org>2012-02-13 20:39:02 -0500
commit3e73c36b4dc224529d0b0c0d5d69c0dacd793c42 (patch)
tree9c6df98a296ca4865db3621f0bc295d687272f66 /drivers/mmc
parent012e4671e445ac1dd04f40c0b974685280bedca3 (diff)
mmc: core: Fix PowerOff Notify suspend/resume
Modified the mmc_poweroff to resume before sending the poweroff notification command. In sleep mode only AWAKE and RESET commands are allowed, so before sending the poweroff notification command resume from sleep mode and then send the notification command. PowerOff Notify is tested on a Synopsis Designware Host Controller (eMMC 4.5). The suspend to RAM and resume works fine. Signed-off-by: Girish K S <girish.shivananjappa@linaro.org> Tested-by: Girish K S <girish.shivananjappa@linaro.org> Reviewed-by: Saugata Das <saugata.das@linaro.org> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/core/core.c26
-rw-r--r--drivers/mmc/core/mmc.c17
2 files changed, 31 insertions, 12 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 18661554e79c..690255c7d4dc 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1256,6 +1256,7 @@ static void mmc_poweroff_notify(struct mmc_host *host)
1256 int err = 0; 1256 int err = 0;
1257 1257
1258 card = host->card; 1258 card = host->card;
1259 mmc_claim_host(host);
1259 1260
1260 /* 1261 /*
1261 * Send power notify command only if card 1262 * Send power notify command only if card
@@ -1286,6 +1287,7 @@ static void mmc_poweroff_notify(struct mmc_host *host)
1286 /* Set the card state to no notification after the poweroff */ 1287 /* Set the card state to no notification after the poweroff */
1287 card->poweroff_notify_state = MMC_NO_POWER_NOTIFICATION; 1288 card->poweroff_notify_state = MMC_NO_POWER_NOTIFICATION;
1288 } 1289 }
1290 mmc_release_host(host);
1289} 1291}
1290 1292
1291/* 1293/*
@@ -1344,12 +1346,28 @@ static void mmc_power_up(struct mmc_host *host)
1344 1346
1345void mmc_power_off(struct mmc_host *host) 1347void mmc_power_off(struct mmc_host *host)
1346{ 1348{
1349 int err = 0;
1347 mmc_host_clk_hold(host); 1350 mmc_host_clk_hold(host);
1348 1351
1349 host->ios.clock = 0; 1352 host->ios.clock = 0;
1350 host->ios.vdd = 0; 1353 host->ios.vdd = 0;
1351 1354
1352 mmc_poweroff_notify(host); 1355 /*
1356 * For eMMC 4.5 device send AWAKE command before
1357 * POWER_OFF_NOTIFY command, because in sleep state
1358 * eMMC 4.5 devices respond to only RESET and AWAKE cmd
1359 */
1360 if (host->card && mmc_card_is_sleep(host->card) &&
1361 host->bus_ops->resume) {
1362 err = host->bus_ops->resume(host);
1363
1364 if (!err)
1365 mmc_poweroff_notify(host);
1366 else
1367 pr_warning("%s: error %d during resume "
1368 "(continue with poweroff sequence)\n",
1369 mmc_hostname(host), err);
1370 }
1353 1371
1354 /* 1372 /*
1355 * Reset ocr mask to be the highest possible voltage supported for 1373 * Reset ocr mask to be the highest possible voltage supported for
@@ -2403,12 +2421,6 @@ int mmc_suspend_host(struct mmc_host *host)
2403 */ 2421 */
2404 if (mmc_try_claim_host(host)) { 2422 if (mmc_try_claim_host(host)) {
2405 if (host->bus_ops->suspend) { 2423 if (host->bus_ops->suspend) {
2406 /*
2407 * For eMMC 4.5 device send notify command
2408 * before sleep, because in sleep state eMMC 4.5
2409 * devices respond to only RESET and AWAKE cmd
2410 */
2411 mmc_poweroff_notify(host);
2412 err = host->bus_ops->suspend(host); 2424 err = host->bus_ops->suspend(host);
2413 } 2425 }
2414 mmc_do_release_host(host); 2426 mmc_do_release_host(host);
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index dd3fcac684a3..9be031934e33 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1316,11 +1316,13 @@ static int mmc_suspend(struct mmc_host *host)
1316 BUG_ON(!host->card); 1316 BUG_ON(!host->card);
1317 1317
1318 mmc_claim_host(host); 1318 mmc_claim_host(host);
1319 if (mmc_card_can_sleep(host)) 1319 if (mmc_card_can_sleep(host)) {
1320 err = mmc_card_sleep(host); 1320 err = mmc_card_sleep(host);
1321 else if (!mmc_host_is_spi(host)) 1321 if (!err)
1322 mmc_card_set_sleep(host->card);
1323 } else if (!mmc_host_is_spi(host))
1322 mmc_deselect_cards(host); 1324 mmc_deselect_cards(host);
1323 host->card->state &= ~MMC_STATE_HIGHSPEED; 1325 host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
1324 mmc_release_host(host); 1326 mmc_release_host(host);
1325 1327
1326 return err; 1328 return err;
@@ -1340,7 +1342,11 @@ static int mmc_resume(struct mmc_host *host)
1340 BUG_ON(!host->card); 1342 BUG_ON(!host->card);
1341 1343
1342 mmc_claim_host(host); 1344 mmc_claim_host(host);
1343 err = mmc_init_card(host, host->ocr, host->card); 1345 if (mmc_card_is_sleep(host->card)) {
1346 err = mmc_card_awake(host);
1347 mmc_card_clr_sleep(host->card);
1348 } else
1349 err = mmc_init_card(host, host->ocr, host->card);
1344 mmc_release_host(host); 1350 mmc_release_host(host);
1345 1351
1346 return err; 1352 return err;
@@ -1350,7 +1356,8 @@ static int mmc_power_restore(struct mmc_host *host)
1350{ 1356{
1351 int ret; 1357 int ret;
1352 1358
1353 host->card->state &= ~MMC_STATE_HIGHSPEED; 1359 host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
1360 mmc_card_clr_sleep(host->card);
1354 mmc_claim_host(host); 1361 mmc_claim_host(host);
1355 ret = mmc_init_card(host, host->ocr, host->card); 1362 ret = mmc_init_card(host, host->ocr, host->card);
1356 mmc_release_host(host); 1363 mmc_release_host(host);