Merge "mmc: mmc: Don't send CMD13 after switch command while switching speed modes"
This commit is contained in:
commit
5c470dc1df
3 changed files with 37 additions and 20 deletions
|
@ -61,6 +61,7 @@ static const unsigned int tacc_mant[] = {
|
||||||
__res & __mask; \
|
__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.
|
* 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,
|
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
||||||
EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS,
|
EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS,
|
||||||
card->ext_csd.generic_cmd6_time,
|
card->ext_csd.generic_cmd6_time,
|
||||||
true, true, true);
|
true, false, true);
|
||||||
if (!err)
|
if (!err) {
|
||||||
mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
|
mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
|
||||||
|
err = mmc_switch_status(card, false);
|
||||||
|
}
|
||||||
|
|
||||||
return err;
|
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_bits = (bus_width == MMC_BUS_WIDTH_8) ?
|
||||||
EXT_CSD_DDR_BUS_WIDTH_8 : EXT_CSD_DDR_BUS_WIDTH_4;
|
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_BUS_WIDTH,
|
||||||
ext_csd_bits,
|
ext_csd_bits,
|
||||||
card->ext_csd.generic_cmd6_time);
|
card->ext_csd.generic_cmd6_time,
|
||||||
|
true, false, false);
|
||||||
if (err) {
|
if (err) {
|
||||||
pr_err("%s: switch to bus width %d ddr failed\n",
|
pr_err("%s: switch to bus width %d ddr failed\n",
|
||||||
mmc_hostname(host), 1 << bus_width);
|
mmc_hostname(host), 1 << bus_width);
|
||||||
|
@ -1136,19 +1140,21 @@ static int mmc_select_hs_ddr(struct mmc_card *card)
|
||||||
if (err)
|
if (err)
|
||||||
err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330);
|
err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330);
|
||||||
|
|
||||||
if (!err)
|
if (!err) {
|
||||||
mmc_set_timing(host, MMC_TIMING_MMC_DDR52);
|
mmc_set_timing(host, MMC_TIMING_MMC_DDR52);
|
||||||
|
err = mmc_switch_status(card, false);
|
||||||
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Caller must hold re-tuning */
|
/* 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;
|
u32 status;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = mmc_send_status(card, &status);
|
err = __mmc_send_status(card, &status, ignore_crc);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -1212,7 +1218,7 @@ static int mmc_select_hs400(struct mmc_card *card)
|
||||||
mmc_set_clock(host, max_dtr);
|
mmc_set_clock(host, max_dtr);
|
||||||
|
|
||||||
if (!send_status) {
|
if (!send_status) {
|
||||||
err = mmc_switch_status(card);
|
err = mmc_switch_status(card, false);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_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_timing(host, MMC_TIMING_MMC_HS400);
|
||||||
mmc_set_bus_speed(card);
|
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) {
|
if (card->ext_csd.strobe_support && host->ops->enhanced_strobe) {
|
||||||
mmc_host_clk_hold(host);
|
mmc_host_clk_hold(host);
|
||||||
err = host->ops->enhanced_strobe(host);
|
err = host->ops->enhanced_strobe(host);
|
||||||
|
@ -1275,6 +1275,17 @@ static int mmc_select_hs400(struct mmc_card *card)
|
||||||
mmc_hostname(host));
|
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;
|
return 0;
|
||||||
|
|
||||||
out_err:
|
out_err:
|
||||||
|
@ -1314,7 +1325,7 @@ int mmc_hs400_to_hs200(struct mmc_card *card)
|
||||||
mmc_set_timing(host, MMC_TIMING_MMC_DDR52);
|
mmc_set_timing(host, MMC_TIMING_MMC_DDR52);
|
||||||
|
|
||||||
if (!send_status) {
|
if (!send_status) {
|
||||||
err = mmc_switch_status(card);
|
err = mmc_switch_status(card, false);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_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);
|
mmc_set_timing(host, MMC_TIMING_MMC_HS);
|
||||||
|
|
||||||
if (!send_status) {
|
if (!send_status) {
|
||||||
err = mmc_switch_status(card);
|
err = mmc_switch_status(card, false);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_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);
|
mmc_set_timing(host, MMC_TIMING_MMC_HS200);
|
||||||
|
|
||||||
if (!send_status) {
|
if (!send_status) {
|
||||||
err = mmc_switch_status(card);
|
err = mmc_switch_status(card, false);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
@ -1425,7 +1436,12 @@ static int mmc_select_hs200(struct mmc_card *card)
|
||||||
old_timing = host->ios.timing;
|
old_timing = host->ios.timing;
|
||||||
mmc_set_timing(host, MMC_TIMING_MMC_HS200);
|
mmc_set_timing(host, MMC_TIMING_MMC_HS200);
|
||||||
if (!send_status) {
|
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
|
* mmc_select_timing() assumes timing has not changed if
|
||||||
* it is a switch error.
|
* it is a switch error.
|
||||||
|
|
|
@ -54,7 +54,7 @@ static const u8 tuning_blk_pattern_8bit[] = {
|
||||||
0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
|
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)
|
bool ignore_crc)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
|
@ -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,
|
int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
|
||||||
unsigned int timeout_ms, bool use_busy_signal, bool send_status,
|
unsigned int timeout_ms, bool use_busy_signal, bool send_status,
|
||||||
bool ignore_crc);
|
bool ignore_crc);
|
||||||
|
int __mmc_send_status(struct mmc_card *card, u32 *status,
|
||||||
|
bool ignore_crc);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue