diff options
Diffstat (limited to 'drivers/mmc/core/mmc_ops.c')
-rw-r--r-- | drivers/mmc/core/mmc_ops.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 34ce2703d29a..355c6042cf65 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -57,6 +57,42 @@ int mmc_deselect_cards(struct mmc_host *host) return _mmc_select_card(host, NULL); } +int mmc_card_sleepawake(struct mmc_host *host, int sleep) +{ + struct mmc_command cmd; + struct mmc_card *card = host->card; + int err; + + if (sleep) + mmc_deselect_cards(host); + + memset(&cmd, 0, sizeof(struct mmc_command)); + + cmd.opcode = MMC_SLEEP_AWAKE; + cmd.arg = card->rca << 16; + if (sleep) + cmd.arg |= 1 << 15; + + cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; + err = mmc_wait_for_cmd(host, &cmd, 0); + if (err) + return err; + + /* + * If the host does not wait while the card signals busy, then we will + * will have to wait the sleep/awake timeout. Note, we cannot use the + * SEND_STATUS command to poll the status because that command (and most + * others) is invalid while the card sleeps. + */ + if (!(host->caps & MMC_CAP_WAIT_WHILE_BUSY)) + mmc_delay(DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000)); + + if (!sleep) + err = mmc_select_card(card); + + return err; +} + int mmc_go_idle(struct mmc_host *host) { int err; |