mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-06-06 06:41:40 +00:00
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>
This commit is contained in:
parent
01298da31d
commit
83dc42271f
3 changed files with 52 additions and 2 deletions
|
@ -42,6 +42,15 @@ config ARM_PL180_MMCI
|
||||||
If you have an ARM(R) platform with a Multimedia Card slot,
|
If you have an ARM(R) platform with a Multimedia Card slot,
|
||||||
say Y or M here.
|
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
|
config MMC_VERBOSE
|
||||||
bool "Output more information about the MMC"
|
bool "Output more information about the MMC"
|
||||||
default y
|
default y
|
||||||
|
|
|
@ -279,6 +279,7 @@ int mmc_send_status(struct mmc *mmc, int timeout)
|
||||||
int mmc_set_blocklen(struct mmc *mmc, int len)
|
int mmc_set_blocklen(struct mmc *mmc, int len)
|
||||||
{
|
{
|
||||||
struct mmc_cmd cmd;
|
struct mmc_cmd cmd;
|
||||||
|
int err;
|
||||||
|
|
||||||
if (mmc->ddr_mode)
|
if (mmc->ddr_mode)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -287,7 +288,24 @@ int mmc_set_blocklen(struct mmc *mmc, int len)
|
||||||
cmd.resp_type = MMC_RSP_R1;
|
cmd.resp_type = MMC_RSP_R1;
|
||||||
cmd.cmdarg = len;
|
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,
|
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.resp_type = MMC_RSP_R1;
|
||||||
cmd.cmdarg = 1;
|
cmd.cmdarg = 1;
|
||||||
err = mmc_send_cmd(mmc, &cmd, NULL);
|
err = mmc_send_cmd(mmc, &cmd, NULL);
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -1895,6 +1912,21 @@ static int mmc_startup(struct mmc *mmc)
|
||||||
|
|
||||||
err = mmc_send_cmd(mmc, &cmd, NULL);
|
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)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -2239,6 +2271,11 @@ int mmc_start_init(struct mmc *mmc)
|
||||||
if (err)
|
if (err)
|
||||||
return 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);
|
err = mmc_power_cycle(mmc);
|
||||||
if (err) {
|
if (err) {
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -306,6 +306,9 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx)
|
||||||
#define ENHNCD_SUPPORT (0x2)
|
#define ENHNCD_SUPPORT (0x2)
|
||||||
#define PART_ENH_ATTRIB (0x1f)
|
#define PART_ENH_ATTRIB (0x1f)
|
||||||
|
|
||||||
|
#define MMC_QUIRK_RETRY_SEND_CID BIT(0)
|
||||||
|
#define MMC_QUIRK_RETRY_SET_BLOCKLEN BIT(1)
|
||||||
|
|
||||||
enum mmc_voltage {
|
enum mmc_voltage {
|
||||||
MMC_SIGNAL_VOLTAGE_000 = 0,
|
MMC_SIGNAL_VOLTAGE_000 = 0,
|
||||||
MMC_SIGNAL_VOLTAGE_120,
|
MMC_SIGNAL_VOLTAGE_120,
|
||||||
|
@ -591,6 +594,7 @@ struct mmc {
|
||||||
* operating mode due to limitations when
|
* operating mode due to limitations when
|
||||||
* accessing the boot partitions
|
* accessing the boot partitions
|
||||||
*/
|
*/
|
||||||
|
u32 quirks;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mmc_hwpart_conf {
|
struct mmc_hwpart_conf {
|
||||||
|
|
Loading…
Add table
Reference in a new issue