summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSahitya Tummala <stummala@codeaurora.org>2014-04-18 13:00:20 +0530
committerSubhash Jadavani <subhashj@codeaurora.org>2016-05-31 15:27:44 -0700
commit71728d8db1686f38faaef0f07326d2aaff753a01 (patch)
treebb7501b341bb070a018d33e3c77436250e1793e2
parente3a22cb14423fa5189393214e55ad50db03b7710 (diff)
mmc: core: fix issue with sleep cmd that follows an RPMB access
If the last access to eMMC before runtime/system suspend is an RPMB access, the partition type within EXT_CSD[179] will be set to RPMB. As per specification, the deselect CMD7 and sleep CMD5 are ignored by the card and are treated as illegal commands in this state. This causes eMMC sleep command to timeout and thus fails runtime/system suspend. Hence, switch to default partition config before sending deselect CMD7 and sleep CMD5. CRs-fixed: 630894 Change-Id: I40f3fb590aeba787de8ca3356a8eed5f2780bcc1 Signed-off-by: Sahitya Tummala <stummala@codeaurora.org> Signed-off-by: Venkat Gopalakrishnan <venkatg@codeaurora.org> [subhashj@codeaurora.org: fixed merge conflicts] Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
-rw-r--r--drivers/mmc/core/mmc.c32
1 files changed, 31 insertions, 1 deletions
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 65b2581e3195..e9827c52e283 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -2195,9 +2195,39 @@ static int mmc_sleepawake(struct mmc_host *host, bool sleep)
{
struct mmc_command cmd = {0};
struct mmc_card *card = host->card;
- unsigned int timeout_ms = DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000);
+ unsigned int timeout_ms;
int err;
+ if (!card) {
+ pr_err("%s: %s: invalid card\n", mmc_hostname(host), __func__);
+ return -EINVAL;
+ }
+
+ timeout_ms = DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000);
+ if (card->ext_csd.rev >= 3 &&
+ card->part_curr == EXT_CSD_PART_CONFIG_ACC_RPMB) {
+ u8 part_config = card->ext_csd.part_config;
+
+ /*
+ * If the last access before suspend is RPMB access, then
+ * switch to default part config so that sleep command CMD5
+ * and deselect CMD7 can be sent to the card.
+ */
+ part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK;
+ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_PART_CONFIG,
+ part_config,
+ card->ext_csd.part_time);
+ if (err) {
+ pr_err("%s: %s: failed to switch to default part config %x\n",
+ mmc_hostname(host), __func__, part_config);
+ return err;
+ }
+ card->ext_csd.part_config = part_config;
+ card->part_curr = card->ext_csd.part_config &
+ EXT_CSD_PART_CONFIG_ACC_MASK;
+ }
+
/* Re-tuning can't be done once the card is deselected */
mmc_retune_hold(host);