From: Adrian Hunter <adrian.hunter@intel.com>
To: Ulf Hansson <ulf.hansson@linaro.org>
Cc: linux-mmc <linux-mmc@vger.kernel.org>,
Seungwon Jeon <tgih.jun@samsung.com>,
Jaehoon Chung <jh80.chung@samsung.com>,
Chaotian Jing <chaotian.jing@mediatek.com>
Subject: [PATCH 4/4] mmc: mmc: Improve reliability of mmc_select_hs400()
Date: Wed, 28 Oct 2015 14:25:43 +0200 [thread overview]
Message-ID: <1446035143-4949-5-git-send-email-adrian.hunter@intel.com> (raw)
In-Reply-To: <1446035143-4949-1-git-send-email-adrian.hunter@intel.com>
mmc_select_hs400() calls __mmc_switch() which checks the switch is
successful using CMD13 (SEND_STATUS). The problem is that it does that
using the timing settings of the previous mode. That is prone to error,
especially when switching from HS to HS400 because the timing parameters
for HS mode are tighter than the timing parameters for HS400 mode.
In the case when CMD13 polling is used (i.e. not MMC_CAP_WAIT_WHILE_BUSY)
with the switch command, it must be assumed that using different modes on
the card and host must work.
However in the case when CMD13 polling is not used
(i.e. MMC_CAP_WAIT_WHILE_BUSY) mmc_select_hs400() can be made more
reliable by setting the host to the correct timing before sending CMD13.
This patch does that.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
drivers/mmc/core/mmc.c | 28 ++++++++++++++++++++++++++--
1 file changed, 26 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 5884c79346da..3a9a79ec4343 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1056,6 +1056,7 @@ static int mmc_switch_status(struct mmc_card *card)
static int mmc_select_hs400(struct mmc_card *card)
{
struct mmc_host *host = card->host;
+ bool send_status = true;
unsigned int max_dtr;
int err = 0;
u8 val;
@@ -1067,6 +1068,9 @@ static int mmc_select_hs400(struct mmc_card *card)
host->ios.bus_width == MMC_BUS_WIDTH_8))
return 0;
+ if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
+ send_status = false;
+
/* Reduce frequency to HS frequency */
max_dtr = card->ext_csd.hs_max_dtr;
mmc_set_clock(host, max_dtr);
@@ -1077,7 +1081,7 @@ static int mmc_select_hs400(struct mmc_card *card)
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_HS_TIMING, val,
card->ext_csd.generic_cmd6_time,
- true, true, true);
+ true, send_status, true);
if (err) {
pr_err("%s: switch to high-speed from hs200 failed, err:%d\n",
mmc_hostname(host), err);
@@ -1087,6 +1091,13 @@ static int mmc_select_hs400(struct mmc_card *card)
/* Set host controller to HS timing */
mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
+ if (!send_status) {
+ err = mmc_switch_status(card);
+ if (err)
+ goto out_err;
+ }
+
+ /* Switch card to DDR */
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_BUS_WIDTH,
EXT_CSD_DDR_BUS_WIDTH_8,
@@ -1097,22 +1108,35 @@ static int mmc_select_hs400(struct mmc_card *card)
return err;
}
+ /* Switch card to HS400 */
val = EXT_CSD_TIMING_HS400 |
card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_HS_TIMING, val,
card->ext_csd.generic_cmd6_time,
- true, true, true);
+ true, send_status, true);
if (err) {
pr_err("%s: switch to hs400 failed, err:%d\n",
mmc_hostname(host), err);
return err;
}
+ /* Set host controller to HS400 timing and frequency */
mmc_set_timing(host, MMC_TIMING_MMC_HS400);
mmc_set_bus_speed(card);
+ if (!send_status) {
+ err = mmc_switch_status(card);
+ if (err)
+ goto out_err;
+ }
+
return 0;
+
+out_err:
+ pr_err("%s: %s failed, error %d\n", mmc_hostname(card->host),
+ __func__, err);
+ return err;
}
int mmc_hs200_to_hs400(struct mmc_card *card)
--
1.9.1
next prev parent reply other threads:[~2015-10-28 12:29 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-10-28 12:25 [PATCH 0/4] mmc: mmc: Improve reliability of HS200/HS400 selection Adrian Hunter
2015-10-28 12:25 ` [PATCH 1/4] mmc: mmc: Improve reliability of mmc_select_hs200() Adrian Hunter
2015-10-28 12:25 ` [PATCH 2/4] mmc: mmc: Fix HS setting in mmc_select_hs400() Adrian Hunter
2015-10-28 12:25 ` [PATCH 3/4] mmc: mmc: Move mmc_switch_status() Adrian Hunter
2015-10-28 12:25 ` Adrian Hunter [this message]
2015-11-06 11:03 ` [PATCH 0/4] mmc: mmc: Improve reliability of HS200/HS400 selection Ulf Hansson
2015-11-06 12:55 ` Adrian Hunter
2015-11-09 12:43 ` Ulf Hansson
2015-11-06 16:32 ` Alim Akhtar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1446035143-4949-5-git-send-email-adrian.hunter@intel.com \
--to=adrian.hunter@intel.com \
--cc=chaotian.jing@mediatek.com \
--cc=jh80.chung@samsung.com \
--cc=linux-mmc@vger.kernel.org \
--cc=tgih.jun@samsung.com \
--cc=ulf.hansson@linaro.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).