Commit a27fbf2f authored by Seungwon Jeon's avatar Seungwon Jeon Committed by Chris Ball

mmc: add ignorance case for CMD13 CRC error

While speed mode is changed, CMD13 cannot be guaranteed.
According to the spec., it is not recommended to use CMD13
to check the busy completion of the timing change.
If CMD13 is used in this case, CRC error must be ignored.
Signed-off-by: default avatarSeungwon Jeon <tgih.jun@samsung.com>
Acked-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
Signed-off-by: default avatarChris Ball <cjb@laptop.org>
parent aa50f259
...@@ -23,6 +23,40 @@ ...@@ -23,6 +23,40 @@
#define MMC_OPS_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */ #define MMC_OPS_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */
static inline int __mmc_send_status(struct mmc_card *card, u32 *status,
bool ignore_crc)
{
int err;
struct mmc_command cmd = {0};
BUG_ON(!card);
BUG_ON(!card->host);
cmd.opcode = MMC_SEND_STATUS;
if (!mmc_host_is_spi(card->host))
cmd.arg = card->rca << 16;
cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
if (ignore_crc)
cmd.flags &= ~MMC_RSP_CRC;
err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
if (err)
return err;
/* NOTE: callers are required to understand the difference
* between "native" and SPI format status words!
*/
if (status)
*status = cmd.resp[0];
return 0;
}
int mmc_send_status(struct mmc_card *card, u32 *status)
{
return __mmc_send_status(card, status, false);
}
static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card) static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card)
{ {
int err; int err;
...@@ -380,6 +414,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, ...@@ -380,6 +414,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
struct mmc_command cmd = {0}; struct mmc_command cmd = {0};
unsigned long timeout; unsigned long timeout;
u32 status; u32 status;
bool ignore_crc = false;
BUG_ON(!card); BUG_ON(!card);
BUG_ON(!card->host); BUG_ON(!card->host);
...@@ -408,10 +443,18 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, ...@@ -408,10 +443,18 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
if (!use_busy_signal) if (!use_busy_signal)
return 0; return 0;
/* Must check status to be sure of no errors */ /*
* Must check status to be sure of no errors
* If CMD13 is to check the busy completion of the timing change,
* disable the check of CRC error.
*/
if (index == EXT_CSD_HS_TIMING &&
!(card->host->caps & MMC_CAP_WAIT_WHILE_BUSY))
ignore_crc = true;
timeout = jiffies + msecs_to_jiffies(MMC_OPS_TIMEOUT_MS); timeout = jiffies + msecs_to_jiffies(MMC_OPS_TIMEOUT_MS);
do { do {
err = mmc_send_status(card, &status); err = __mmc_send_status(card, &status, ignore_crc);
if (err) if (err)
return err; return err;
if (card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) if (card->host->caps & MMC_CAP_WAIT_WHILE_BUSY)
...@@ -449,32 +492,6 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, ...@@ -449,32 +492,6 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
} }
EXPORT_SYMBOL_GPL(mmc_switch); EXPORT_SYMBOL_GPL(mmc_switch);
int mmc_send_status(struct mmc_card *card, u32 *status)
{
int err;
struct mmc_command cmd = {0};
BUG_ON(!card);
BUG_ON(!card->host);
cmd.opcode = MMC_SEND_STATUS;
if (!mmc_host_is_spi(card->host))
cmd.arg = card->rca << 16;
cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
if (err)
return err;
/* NOTE: callers are required to understand the difference
* between "native" and SPI format status words!
*/
if (status)
*status = cmd.resp[0];
return 0;
}
static int static int
mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode, mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode,
u8 len) u8 len)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment