diff options
-rw-r--r-- | drivers/mmc/core/core.c | 26 | ||||
-rw-r--r-- | drivers/mmc/core/mmc.c | 17 | ||||
-rw-r--r-- | include/linux/mmc/card.h | 4 |
3 files changed, 35 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 | ||
1345 | void mmc_power_off(struct mmc_host *host) | 1347 | void 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); |
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 9f22ba572de0..19a41d1737af 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h | |||
@@ -217,6 +217,7 @@ struct mmc_card { | |||
217 | #define MMC_CARD_SDXC (1<<6) /* card is SDXC */ | 217 | #define MMC_CARD_SDXC (1<<6) /* card is SDXC */ |
218 | #define MMC_CARD_REMOVED (1<<7) /* card has been removed */ | 218 | #define MMC_CARD_REMOVED (1<<7) /* card has been removed */ |
219 | #define MMC_STATE_HIGHSPEED_200 (1<<8) /* card is in HS200 mode */ | 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 | unsigned int quirks; /* card quirks */ | 221 | unsigned int quirks; /* card quirks */ |
221 | #define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */ | 222 | #define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */ |
222 | #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func->cur_blksize */ | 223 | #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func->cur_blksize */ |
@@ -382,6 +383,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data) | |||
382 | #define mmc_sd_card_uhs(c) ((c)->state & MMC_STATE_ULTRAHIGHSPEED) | 383 | #define mmc_sd_card_uhs(c) ((c)->state & MMC_STATE_ULTRAHIGHSPEED) |
383 | #define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC) | 384 | #define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC) |
384 | #define mmc_card_removed(c) ((c) && ((c)->state & MMC_CARD_REMOVED)) | 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 | #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) | 388 | #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) |
387 | #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY) | 389 | #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY) |
@@ -393,7 +395,9 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data) | |||
393 | #define mmc_sd_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED) | 395 | #define mmc_sd_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED) |
394 | #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC) | 396 | #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC) |
395 | #define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED) | 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 | * Quirk add/remove for MMC products. | 402 | * Quirk add/remove for MMC products. |
399 | */ | 403 | */ |