Revert "UPSTREAM: mmc: mmc: do not use CMD13 to get status after speed mode switch"
This reverts commit 63128ee66b07ff0e5532bba3aad6797b780c663e.
Reason for revert:
It triggers a regression where Hynix eMMC needs to be power cycled.
BUG=chromium:997389,b:138033787
TEST=Compile ToT Bob without it, able to install R78.
Original change's description:
> UPSTREAM: mmc: mmc: do not use CMD13 to get status after speed mode switch
>
> Per JEDEC spec, it is not recommended to use CMD13 to get card status
> after speed mode switch. below are two reason about this:
> 1. CMD13 cannot be guaranteed due to the asynchronous operation.
> Therefore it is not recommended to use CMD13 to check busy completion
> of the timing change indication.
> 2. After switch to HS200, CMD13 will get response of 0x800, and even the
> busy signal gets de-asserted, the response of CMD13 is aslo 0x800.
>
> BUG=b:138033787
> TEST=compile
>
> Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com>
> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> (cherry picked from commit 08573eaf1a70104f83fdbee9b84e5be03480e9ed)
>
>
> Change-Id: I32935cffeae3e89b658bfd7b8260f7f09b726793
> Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
> Reviewed-on: https://chromium-review.googlesource.com/1716943
> Legacy-Commit-Queue: Commit Bot <commit-bot@chromium.org>
> Reviewed-by: Douglas Anderson <dianders@chromium.org>
> Reviewed-by: Sean Paul <seanpaul@chromium.org>
> (cherry picked from commit 1392a26757ce4b1770754dacb4dbbb9666b63ce0)
>
> Signed-off-by: Tim Chen <tim-chen@quanta.corp-partner.google.com>
> Cq-Depend: chromium:1727139
> Change-Id: I32935cffeae3e89b658bfd7b8260f7f09b726793
> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/1753485
> Reviewed-by: Vincent Wang <vwang@chromium.org>
> Reviewed-by: Douglas Anderson <dianders@chromium.org>
> Reviewed-by: Sean Paul <seanpaul@chromium.org>
Bug: b:138033787
Change-Id: I5051d9163ccf0a33891a61534738bae694da88ee
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/1770858
Tested-by: Gwendal Grignou <gwendal@chromium.org>
Reviewed-by: Gwendal Grignou <gwendal@chromium.org>
Commit-Queue: Gwendal Grignou <gwendal@chromium.org>
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index d5fa335..fb974e7 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -983,19 +983,6 @@
return err;
}
-/* Caller must hold re-tuning */
-static int mmc_switch_status(struct mmc_card *card)
-{
- u32 status;
- int err;
-
- err = mmc_send_status(card, &status);
- if (err)
- return err;
-
- return mmc_switch_status_error(card->host, status);
-}
-
/*
* Switch to the high-speed mode
*/
@@ -1006,11 +993,9 @@
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS,
card->ext_csd.generic_cmd6_time,
- true, false, true);
- if (!err) {
+ true, true, true);
+ if (!err)
mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
- err = mmc_switch_status(card);
- }
return err;
}
@@ -1086,9 +1071,23 @@
return err;
}
+/* Caller must hold re-tuning */
+static int mmc_switch_status(struct mmc_card *card)
+{
+ u32 status;
+ int err;
+
+ err = mmc_send_status(card, &status);
+ if (err)
+ return err;
+
+ return mmc_switch_status_error(card->host, status);
+}
+
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;
@@ -1100,6 +1099,9 @@
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);
@@ -1109,7 +1111,7 @@
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_HS_TIMING, val,
card->ext_csd.generic_cmd6_time,
- true, false, true);
+ true, send_status, true);
if (err) {
pr_err("%s: switch to high-speed from hs200 failed, err:%d\n",
mmc_hostname(host), err);
@@ -1119,9 +1121,11 @@
/* Set host controller to HS timing */
mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
- err = mmc_switch_status(card);
- if (err)
- goto out_err;
+ 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,
@@ -1140,7 +1144,7 @@
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_HS_TIMING, val,
card->ext_csd.generic_cmd6_time,
- true, false, true);
+ true, send_status, true);
if (err) {
pr_err("%s: switch to hs400 failed, err:%d\n",
mmc_hostname(host), err);
@@ -1151,9 +1155,11 @@
mmc_set_timing(host, MMC_TIMING_MMC_HS400);
mmc_set_bus_speed(card);
- err = mmc_switch_status(card);
- if (err)
- goto out_err;
+ if (!send_status) {
+ err = mmc_switch_status(card);
+ if (err)
+ goto out_err;
+ }
return 0;
@@ -1171,10 +1177,14 @@
int mmc_hs400_to_hs200(struct mmc_card *card)
{
struct mmc_host *host = card->host;
+ bool send_status = true;
unsigned int max_dtr;
int err;
u8 val;
+ if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
+ send_status = false;
+
/* Reduce frequency to HS */
max_dtr = card->ext_csd.hs_max_dtr;
mmc_set_clock(host, max_dtr);
@@ -1183,43 +1193,49 @@
val = EXT_CSD_TIMING_HS;
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
val, card->ext_csd.generic_cmd6_time,
- true, false, true);
+ true, send_status, true);
if (err)
goto out_err;
mmc_set_timing(host, MMC_TIMING_MMC_DDR52);
- err = mmc_switch_status(card);
- if (err)
- goto out_err;
+ if (!send_status) {
+ err = mmc_switch_status(card);
+ if (err)
+ goto out_err;
+ }
/* Switch HS DDR to HS */
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
EXT_CSD_BUS_WIDTH_8, card->ext_csd.generic_cmd6_time,
- true, false, true);
+ true, send_status, true);
if (err)
goto out_err;
mmc_set_timing(host, MMC_TIMING_MMC_HS);
- err = mmc_switch_status(card);
- if (err)
- goto out_err;
+ if (!send_status) {
+ err = mmc_switch_status(card);
+ if (err)
+ goto out_err;
+ }
/* Switch HS to HS200 */
val = EXT_CSD_TIMING_HS200 |
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, false, true);
+ val, card->ext_csd.generic_cmd6_time, true,
+ send_status, true);
if (err)
goto out_err;
mmc_set_timing(host, MMC_TIMING_MMC_HS200);
- err = mmc_switch_status(card);
- if (err)
- goto out_err;
+ if (!send_status) {
+ err = mmc_switch_status(card);
+ if (err)
+ goto out_err;
+ }
mmc_set_bus_speed(card);
@@ -1342,6 +1358,7 @@
static int mmc_select_hs200(struct mmc_card *card)
{
struct mmc_host *host = card->host;
+ bool send_status = true;
unsigned int old_timing, old_signal_voltage;
int err = -EINVAL;
u8 val;
@@ -1359,6 +1376,9 @@
mmc_select_driver_type(card);
+ if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
+ send_status = false;
+
/*
* Set the bus width(4 or 8) with host's support and
* switch to HS200 mode if bus width is set successfully.
@@ -1370,19 +1390,20 @@
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_HS_TIMING, val,
card->ext_csd.generic_cmd6_time,
- true, false, true);
+ true, send_status, true);
if (err)
goto err;
old_timing = host->ios.timing;
mmc_set_timing(host, MMC_TIMING_MMC_HS200);
-
- err = mmc_switch_status(card);
- /*
- * mmc_select_timing() assumes timing has not changed if
- * it is a switch error.
- */
- if (err == -EBADMSG)
- mmc_set_timing(host, old_timing);
+ if (!send_status) {
+ err = mmc_switch_status(card);
+ /*
+ * mmc_select_timing() assumes timing has not changed if
+ * it is a switch error.
+ */
+ if (err == -EBADMSG)
+ mmc_set_timing(host, old_timing);
+ }
}
err:
if (err) {