summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2017-01-15 07:06:01 -0800
committerGerrit - the friendly Code Review server <code-review@localhost>2017-01-15 07:06:01 -0800
commit5c470dc1df813eb71a2c8b820a99dcfd2d2d06d0 (patch)
treedb975e5981e40458a072186632150cfc8d30ce50
parent4ee892e2358078ed7ef2033f06d2565707e2b117 (diff)
parentb93aab4d22dc1dd67238f8e06dbe08f0fadab679 (diff)
Merge "mmc: mmc: Don't send CMD13 after switch command while switching speed modes"
-rw-r--r--drivers/mmc/core/mmc.c52
-rw-r--r--drivers/mmc/core/mmc_ops.c2
-rw-r--r--drivers/mmc/core/mmc_ops.h3
3 files changed, 37 insertions, 20 deletions
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 7aa01372412d..449514bae4f3 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -61,6 +61,7 @@ static const unsigned int tacc_mant[] = {
__res & __mask; \
})
+static int mmc_switch_status(struct mmc_card *card, bool ignore_crc);
/*
* Given the decoded CSD structure, decode the raw CID to our CID structure.
*/
@@ -1064,9 +1065,11 @@ static int mmc_select_hs(struct mmc_card *card)
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS,
card->ext_csd.generic_cmd6_time,
- true, true, true);
- if (!err)
+ true, false, true);
+ if (!err) {
mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
+ err = mmc_switch_status(card, false);
+ }
return err;
}
@@ -1090,10 +1093,11 @@ static int mmc_select_hs_ddr(struct mmc_card *card)
ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ?
EXT_CSD_DDR_BUS_WIDTH_8 : EXT_CSD_DDR_BUS_WIDTH_4;
- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_BUS_WIDTH,
ext_csd_bits,
- card->ext_csd.generic_cmd6_time);
+ card->ext_csd.generic_cmd6_time,
+ true, false, false);
if (err) {
pr_err("%s: switch to bus width %d ddr failed\n",
mmc_hostname(host), 1 << bus_width);
@@ -1136,19 +1140,21 @@ static int mmc_select_hs_ddr(struct mmc_card *card)
if (err)
err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330);
- if (!err)
+ if (!err) {
mmc_set_timing(host, MMC_TIMING_MMC_DDR52);
+ err = mmc_switch_status(card, false);
+ }
return err;
}
/* Caller must hold re-tuning */
-static int mmc_switch_status(struct mmc_card *card)
+static int mmc_switch_status(struct mmc_card *card, bool ignore_crc)
{
u32 status;
int err;
- err = mmc_send_status(card, &status);
+ err = __mmc_send_status(card, &status, ignore_crc);
if (err)
return err;
@@ -1212,7 +1218,7 @@ static int mmc_select_hs400(struct mmc_card *card)
mmc_set_clock(host, max_dtr);
if (!send_status) {
- err = mmc_switch_status(card);
+ err = mmc_switch_status(card, false);
if (err)
goto out_err;
}
@@ -1253,12 +1259,6 @@ static int mmc_select_hs400(struct mmc_card *card)
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;
- }
-
if (card->ext_csd.strobe_support && host->ops->enhanced_strobe) {
mmc_host_clk_hold(host);
err = host->ops->enhanced_strobe(host);
@@ -1275,6 +1275,17 @@ static int mmc_select_hs400(struct mmc_card *card)
mmc_hostname(host));
}
+ /*
+ * Sending of CMD13 should be done after the host calibration
+ * for enhanced_strobe or HS400 mode is completed.
+ * Otherwise may see CMD13 timeouts or CRC errors.
+ */
+ if (!send_status) {
+ err = mmc_switch_status(card, false);
+ if (err)
+ goto out_err;
+ }
+
return 0;
out_err:
@@ -1314,7 +1325,7 @@ int mmc_hs400_to_hs200(struct mmc_card *card)
mmc_set_timing(host, MMC_TIMING_MMC_DDR52);
if (!send_status) {
- err = mmc_switch_status(card);
+ err = mmc_switch_status(card, false);
if (err)
goto out_err;
}
@@ -1329,7 +1340,7 @@ int mmc_hs400_to_hs200(struct mmc_card *card)
mmc_set_timing(host, MMC_TIMING_MMC_HS);
if (!send_status) {
- err = mmc_switch_status(card);
+ err = mmc_switch_status(card, false);
if (err)
goto out_err;
}
@@ -1346,7 +1357,7 @@ int mmc_hs400_to_hs200(struct mmc_card *card)
mmc_set_timing(host, MMC_TIMING_MMC_HS200);
if (!send_status) {
- err = mmc_switch_status(card);
+ err = mmc_switch_status(card, false);
if (err)
goto out_err;
}
@@ -1425,7 +1436,12 @@ static int mmc_select_hs200(struct mmc_card *card)
old_timing = host->ios.timing;
mmc_set_timing(host, MMC_TIMING_MMC_HS200);
if (!send_status) {
- err = mmc_switch_status(card);
+ /*
+ * Since after switching to hs200, crc errors might
+ * occur for commands send before tuning.
+ * So ignore crc error for cmd13.
+ */
+ err = mmc_switch_status(card, true);
/*
* mmc_select_timing() assumes timing has not changed if
* it is a switch error.
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 4a978898af84..de406431e5a4 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -54,7 +54,7 @@ static const u8 tuning_blk_pattern_8bit[] = {
0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
};
-static inline int __mmc_send_status(struct mmc_card *card, u32 *status,
+int __mmc_send_status(struct mmc_card *card, u32 *status,
bool ignore_crc)
{
int err;
diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h
index 1eea7bd51367..ad1058c1adfd 100644
--- a/drivers/mmc/core/mmc_ops.h
+++ b/drivers/mmc/core/mmc_ops.h
@@ -32,6 +32,7 @@ int mmc_switch_status_error(struct mmc_host *host, u32 status);
int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
unsigned int timeout_ms, bool use_busy_signal, bool send_status,
bool ignore_crc);
-
+int __mmc_send_status(struct mmc_card *card, u32 *status,
+ bool ignore_crc);
#endif