Commit 3e73c36b4dc224529d0b0c0d5d69c0dacd793c42

Authored by Girish K S
Committed by Chris Ball
1 parent 012e4671e4

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>

Showing 3 changed files with 35 additions and 12 deletions Side-by-side Diff

drivers/mmc/core/core.c
... ... @@ -1256,6 +1256,7 @@
1256 1256 int err = 0;
1257 1257  
1258 1258 card = host->card;
  1259 + mmc_claim_host(host);
1259 1260  
1260 1261 /*
1261 1262 * Send power notify command only if card
... ... @@ -1286,6 +1287,7 @@
1286 1287 /* Set the card state to no notification after the poweroff */
1287 1288 card->poweroff_notify_state = MMC_NO_POWER_NOTIFICATION;
1288 1289 }
  1290 + mmc_release_host(host);
1289 1291 }
1290 1292  
1291 1293 /*
1292 1294  
1293 1295  
... ... @@ -1344,13 +1346,29 @@
1344 1346  
1345 1347 void mmc_power_off(struct mmc_host *host)
1346 1348 {
  1349 + int err = 0;
1347 1350 mmc_host_clk_hold(host);
1348 1351  
1349 1352 host->ios.clock = 0;
1350 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);
1353 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 + }
  1371 +
1354 1372 /*
1355 1373 * Reset ocr mask to be the highest possible voltage supported for
1356 1374 * this mmc host. This value will be used at next power up.
... ... @@ -2403,12 +2421,6 @@
2403 2421 */
2404 2422 if (mmc_try_claim_host(host)) {
2405 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 2424 err = host->bus_ops->suspend(host);
2413 2425 }
2414 2426 mmc_do_release_host(host);
drivers/mmc/core/mmc.c
... ... @@ -1316,11 +1316,13 @@
1316 1316 BUG_ON(!host->card);
1317 1317  
1318 1318 mmc_claim_host(host);
1319   - if (mmc_card_can_sleep(host))
  1319 + if (mmc_card_can_sleep(host)) {
1320 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 1324 mmc_deselect_cards(host);
1323   - host->card->state &= ~MMC_STATE_HIGHSPEED;
  1325 + host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
1324 1326 mmc_release_host(host);
1325 1327  
1326 1328 return err;
... ... @@ -1340,7 +1342,11 @@
1340 1342 BUG_ON(!host->card);
1341 1343  
1342 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 1350 mmc_release_host(host);
1345 1351  
1346 1352 return err;
... ... @@ -1350,7 +1356,8 @@
1350 1356 {
1351 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 1361 mmc_claim_host(host);
1355 1362 ret = mmc_init_card(host, host->ocr, host->card);
1356 1363 mmc_release_host(host);
include/linux/mmc/card.h
... ... @@ -217,6 +217,7 @@
217 217 #define MMC_CARD_SDXC (1<<6) /* card is SDXC */
218 218 #define MMC_CARD_REMOVED (1<<7) /* card has been removed */
219 219 #define MMC_STATE_HIGHSPEED_200 (1<<8) /* card is in HS200 mode */
  220 +#define MMC_STATE_SLEEP (1<<9) /* card is in sleep state */
220 221 unsigned int quirks; /* card quirks */
221 222 #define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */
222 223 #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func->cur_blksize */
... ... @@ -382,6 +383,7 @@
382 383 #define mmc_sd_card_uhs(c) ((c)->state & MMC_STATE_ULTRAHIGHSPEED)
383 384 #define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC)
384 385 #define mmc_card_removed(c) ((c) && ((c)->state & MMC_CARD_REMOVED))
  386 +#define mmc_card_is_sleep(c) ((c)->state & MMC_STATE_SLEEP)
385 387  
386 388 #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT)
387 389 #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
388 390  
... ... @@ -393,7 +395,9 @@
393 395 #define mmc_sd_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED)
394 396 #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC)
395 397 #define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED)
  398 +#define mmc_card_set_sleep(c) ((c)->state |= MMC_STATE_SLEEP)
396 399  
  400 +#define mmc_card_clr_sleep(c) ((c)->state &= ~MMC_STATE_SLEEP)
397 401 /*
398 402 * Quirk add/remove for MMC products.
399 403 */