diff options
author | Kishon Vijay Abraham I <kishon@ti.com> | 2017-09-21 17:30:10 +0300 |
---|---|---|
committer | Jaehoon Chung <jh80.chung@samsung.com> | 2018-01-12 12:11:04 +0300 |
commit | 83dc42271f79202b746bc9614817b41a6911c88f (patch) | |
tree | 493393ae4d5d9b0cd3997d19f647f7a377a4ca12 /drivers | |
parent | 01298da31d92ecc46cf9130d8cff68bc51698197 (diff) | |
download | u-boot-83dc42271f79202b746bc9614817b41a6911c88f.tar.xz |
mmc: Retry some MMC cmds on failure
With certain SD cards like Kingston 8GB/16GB UHS card, it is seen that
MMC_CMD_ALL_SEND_CID cmd fails on first attempt, but succeeds
subsequently. Therefore, retry MMC_CMD_ALL_SEND_CID cmd a few time
as done in Linux kernel.
Similarly, it is seen that MMC_CMD_SET_BLOCKLEN may fail on first
attempt, therefore retry this cmd a few times as done in kernel.
To make it clear that those are optionnal workarounds, a new Kconfig
option 'MMC_QUIRKS' is added (enabled by default).
Signed-off-by: Vignesh R <vigneshr@ti.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mmc/Kconfig | 9 | ||||
-rw-r--r-- | drivers/mmc/mmc.c | 41 |
2 files changed, 48 insertions, 2 deletions
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index a8a689f4f5..006c9016a6 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -42,6 +42,15 @@ config ARM_PL180_MMCI If you have an ARM(R) platform with a Multimedia Card slot, say Y or M here. +config MMC_QUIRKS + bool "Enable quirks" + default y + help + Some cards and hosts may sometimes behave unexpectedly (quirks). + This option enable workarounds to handle those quirks. Some of them + are enabled by default, other may require additionnal flags or are + enabled by the host driver. + config MMC_VERBOSE bool "Output more information about the MMC" default y diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 6278d1fa0c..26589b8771 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -279,6 +279,7 @@ int mmc_send_status(struct mmc *mmc, int timeout) int mmc_set_blocklen(struct mmc *mmc, int len) { struct mmc_cmd cmd; + int err; if (mmc->ddr_mode) return 0; @@ -287,7 +288,24 @@ int mmc_set_blocklen(struct mmc *mmc, int len) cmd.resp_type = MMC_RSP_R1; cmd.cmdarg = len; - return mmc_send_cmd(mmc, &cmd, NULL); + err = mmc_send_cmd(mmc, &cmd, NULL); + +#ifdef CONFIG_MMC_QUIRKS + if (err && (mmc->quirks & MMC_QUIRK_RETRY_SET_BLOCKLEN)) { + int retries = 4; + /* + * It has been seen that SET_BLOCKLEN may fail on the first + * attempt, let's try a few more time + */ + do { + err = mmc_send_cmd(mmc, &cmd, NULL); + if (!err) + break; + } while (retries--); + } +#endif + + return err; } static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start, @@ -1881,7 +1899,6 @@ static int mmc_startup(struct mmc *mmc) cmd.resp_type = MMC_RSP_R1; cmd.cmdarg = 1; err = mmc_send_cmd(mmc, &cmd, NULL); - if (err) return err; } @@ -1895,6 +1912,21 @@ static int mmc_startup(struct mmc *mmc) err = mmc_send_cmd(mmc, &cmd, NULL); +#ifdef CONFIG_MMC_QUIRKS + if (err && (mmc->quirks & MMC_QUIRK_RETRY_SEND_CID)) { + int retries = 4; + /* + * It has been seen that SEND_CID may fail on the first + * attempt, let's try a few more time + */ + do { + err = mmc_send_cmd(mmc, &cmd, NULL); + if (!err) + break; + } while (retries--); + } +#endif + if (err) return err; @@ -2239,6 +2271,11 @@ int mmc_start_init(struct mmc *mmc) if (err) return err; +#ifdef CONFIG_MMC_QUIRKS + mmc->quirks = MMC_QUIRK_RETRY_SET_BLOCKLEN | + MMC_QUIRK_RETRY_SEND_CID; +#endif + err = mmc_power_cycle(mmc); if (err) { /* |