Merge tag 'mmc-2020-11-29' of https://gitlab.denx.de/u-boot/custodians/u-boot-mmc
- mmc minor update for better debug and error check - fsl_esdhc sysctl set and make sure delay check for HS400
This commit is contained in:
commit
a7ab4b71d5
@ -70,7 +70,9 @@ struct fsl_esdhc {
|
||||
uint sdtimingctl; /* SD timing control register */
|
||||
char reserved8[20]; /* reserved */
|
||||
uint dllcfg0; /* DLL config 0 register */
|
||||
char reserved9[680]; /* reserved */
|
||||
char reserved9[12]; /* reserved */
|
||||
uint dllstat0; /* DLL status 0 register */
|
||||
char reserved10[664];/* reserved */
|
||||
uint esdhcctl; /* eSDHC control register */
|
||||
};
|
||||
|
||||
@ -617,9 +619,11 @@ static void esdhc_exit_hs400(struct fsl_esdhc_priv *priv)
|
||||
esdhc_tuning_block_enable(priv, false);
|
||||
}
|
||||
|
||||
static void esdhc_set_timing(struct fsl_esdhc_priv *priv, enum bus_mode mode)
|
||||
static int esdhc_set_timing(struct fsl_esdhc_priv *priv, enum bus_mode mode)
|
||||
{
|
||||
struct fsl_esdhc *regs = priv->esdhc_regs;
|
||||
ulong start;
|
||||
u32 val;
|
||||
|
||||
/* Exit HS400 mode before setting any other mode */
|
||||
if (esdhc_read32(®s->tbctl) & HS400_MODE &&
|
||||
@ -640,17 +644,33 @@ static void esdhc_set_timing(struct fsl_esdhc_priv *priv, enum bus_mode mode)
|
||||
esdhc_setbits32(®s->dllcfg0, DLL_FREQ_SEL);
|
||||
|
||||
esdhc_setbits32(®s->dllcfg0, DLL_ENABLE);
|
||||
|
||||
esdhc_setbits32(®s->dllcfg0, DLL_RESET);
|
||||
udelay(1);
|
||||
esdhc_clrbits32(®s->dllcfg0, DLL_RESET);
|
||||
|
||||
start = get_timer(0);
|
||||
val = DLL_STS_SLV_LOCK;
|
||||
while (!(esdhc_read32(®s->dllstat0) & val)) {
|
||||
if (get_timer(start) > 1000) {
|
||||
printf("fsl_esdhc: delay chain lock timeout\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
|
||||
esdhc_setbits32(®s->tbctl, HS400_WNDW_ADJUST);
|
||||
|
||||
esdhc_clock_control(priv, false);
|
||||
esdhc_flush_async_fifo(priv);
|
||||
}
|
||||
esdhc_clock_control(priv, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
|
||||
{
|
||||
struct fsl_esdhc *regs = priv->esdhc_regs;
|
||||
int ret;
|
||||
|
||||
if (priv->is_sdhc_per_clk) {
|
||||
/* Select to use peripheral clock */
|
||||
@ -667,7 +687,9 @@ static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
|
||||
set_sysctl(priv, mmc, mmc->clock);
|
||||
|
||||
/* Set timing */
|
||||
esdhc_set_timing(priv, mmc->selected_mode);
|
||||
ret = esdhc_set_timing(priv, mmc->selected_mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Set the bus width */
|
||||
esdhc_clrbits32(®s->proctl, PROCTL_DTW_4 | PROCTL_DTW_8);
|
||||
@ -715,7 +737,7 @@ static int esdhc_init_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
|
||||
esdhc_setbits32(®s->sysctl, SYSCTL_HCKEN | SYSCTL_IPGEN);
|
||||
|
||||
/* Set the initial clock speed */
|
||||
mmc_set_clock(mmc, 400000, MMC_CLK_ENABLE);
|
||||
set_sysctl(priv, mmc, 400000);
|
||||
|
||||
/* Disable the BRR and BWR bits in IRQSTAT */
|
||||
esdhc_clrbits32(®s->irqstaten, IRQSTATEN_BRR | IRQSTATEN_BWR);
|
||||
|
@ -207,26 +207,65 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* mmc_send_cmd_retry() - send a command to the mmc device, retrying on error
|
||||
*
|
||||
* @dev: device to receive the command
|
||||
* @cmd: command to send
|
||||
* @data: additional data to send/receive
|
||||
* @retries: how many times to retry; mmc_send_cmd is always called at least
|
||||
* once
|
||||
* @return 0 if ok, -ve on error
|
||||
*/
|
||||
static int mmc_send_cmd_retry(struct mmc *mmc, struct mmc_cmd *cmd,
|
||||
struct mmc_data *data, uint retries)
|
||||
{
|
||||
int ret;
|
||||
|
||||
do {
|
||||
ret = mmc_send_cmd(mmc, cmd, data);
|
||||
} while (ret && retries--);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* mmc_send_cmd_quirks() - send a command to the mmc device, retrying if a
|
||||
* specific quirk is enabled
|
||||
*
|
||||
* @dev: device to receive the command
|
||||
* @cmd: command to send
|
||||
* @data: additional data to send/receive
|
||||
* @quirk: retry only if this quirk is enabled
|
||||
* @retries: how many times to retry; mmc_send_cmd is always called at least
|
||||
* once
|
||||
* @return 0 if ok, -ve on error
|
||||
*/
|
||||
static int mmc_send_cmd_quirks(struct mmc *mmc, struct mmc_cmd *cmd,
|
||||
struct mmc_data *data, u32 quirk, uint retries)
|
||||
{
|
||||
if (CONFIG_IS_ENABLED(MMC_QUIRKS) && mmc->quirks & quirk)
|
||||
return mmc_send_cmd_retry(mmc, cmd, data, retries);
|
||||
else
|
||||
return mmc_send_cmd(mmc, cmd, data);
|
||||
}
|
||||
|
||||
int mmc_send_status(struct mmc *mmc, unsigned int *status)
|
||||
{
|
||||
struct mmc_cmd cmd;
|
||||
int err, retries = 5;
|
||||
int ret;
|
||||
|
||||
cmd.cmdidx = MMC_CMD_SEND_STATUS;
|
||||
cmd.resp_type = MMC_RSP_R1;
|
||||
if (!mmc_host_is_spi(mmc))
|
||||
cmd.cmdarg = mmc->rca << 16;
|
||||
|
||||
while (retries--) {
|
||||
err = mmc_send_cmd(mmc, &cmd, NULL);
|
||||
if (!err) {
|
||||
mmc_trace_state(mmc, &cmd);
|
||||
*status = cmd.response[0];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
ret = mmc_send_cmd_retry(mmc, &cmd, NULL, 4);
|
||||
mmc_trace_state(mmc, &cmd);
|
||||
return -ECOMM;
|
||||
if (!ret)
|
||||
*status = cmd.response[0];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mmc_poll_for_busy(struct mmc *mmc, int timeout_ms)
|
||||
@ -274,7 +313,6 @@ int mmc_poll_for_busy(struct mmc *mmc, int timeout_ms)
|
||||
int mmc_set_blocklen(struct mmc *mmc, int len)
|
||||
{
|
||||
struct mmc_cmd cmd;
|
||||
int err;
|
||||
|
||||
if (mmc->ddr_mode)
|
||||
return 0;
|
||||
@ -283,24 +321,8 @@ int mmc_set_blocklen(struct mmc *mmc, int len)
|
||||
cmd.resp_type = MMC_RSP_R1;
|
||||
cmd.cmdarg = len;
|
||||
|
||||
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;
|
||||
return mmc_send_cmd_quirks(mmc, &cmd, NULL,
|
||||
MMC_QUIRK_RETRY_SET_BLOCKLEN, 4);
|
||||
}
|
||||
|
||||
#ifdef MMC_SUPPORTS_TUNING
|
||||
@ -771,7 +793,6 @@ static int __mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value,
|
||||
int timeout_ms = DEFAULT_CMD6_TIMEOUT_MS;
|
||||
bool is_part_switch = (set == EXT_CSD_CMD_SET_NORMAL) &&
|
||||
(index == EXT_CSD_PART_CONF);
|
||||
int retries = 3;
|
||||
int ret;
|
||||
|
||||
if (mmc->gen_cmd6_time)
|
||||
@ -786,10 +807,7 @@ static int __mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value,
|
||||
(index << 16) |
|
||||
(value << 8);
|
||||
|
||||
do {
|
||||
ret = mmc_send_cmd(mmc, &cmd, NULL);
|
||||
} while (ret && retries-- > 0);
|
||||
|
||||
ret = mmc_send_cmd_retry(mmc, &cmd, NULL, 3);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -1287,22 +1305,15 @@ static int sd_get_capabilities(struct mmc *mmc)
|
||||
cmd.resp_type = MMC_RSP_R1;
|
||||
cmd.cmdarg = 0;
|
||||
|
||||
timeout = 3;
|
||||
|
||||
retry_scr:
|
||||
data.dest = (char *)scr;
|
||||
data.blocksize = 8;
|
||||
data.blocks = 1;
|
||||
data.flags = MMC_DATA_READ;
|
||||
|
||||
err = mmc_send_cmd(mmc, &cmd, &data);
|
||||
|
||||
if (err) {
|
||||
if (timeout--)
|
||||
goto retry_scr;
|
||||
err = mmc_send_cmd_retry(mmc, &cmd, &data, 3);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
mmc->scr[0] = __be32_to_cpu(scr[0]);
|
||||
mmc->scr[1] = __be32_to_cpu(scr[1]);
|
||||
@ -1463,28 +1474,13 @@ static int sd_read_ssr(struct mmc *mmc)
|
||||
struct mmc_cmd cmd;
|
||||
ALLOC_CACHE_ALIGN_BUFFER(uint, ssr, 16);
|
||||
struct mmc_data data;
|
||||
int timeout = 3;
|
||||
unsigned int au, eo, et, es;
|
||||
|
||||
cmd.cmdidx = MMC_CMD_APP_CMD;
|
||||
cmd.resp_type = MMC_RSP_R1;
|
||||
cmd.cmdarg = mmc->rca << 16;
|
||||
|
||||
err = mmc_send_cmd(mmc, &cmd, NULL);
|
||||
#ifdef CONFIG_MMC_QUIRKS
|
||||
if (err && (mmc->quirks & MMC_QUIRK_RETRY_APP_CMD)) {
|
||||
int retries = 4;
|
||||
/*
|
||||
* It has been seen that APP_CMD may fail on the first
|
||||
* attempt, let's try a few more times
|
||||
*/
|
||||
do {
|
||||
err = mmc_send_cmd(mmc, &cmd, NULL);
|
||||
if (!err)
|
||||
break;
|
||||
} while (retries--);
|
||||
}
|
||||
#endif
|
||||
err = mmc_send_cmd_quirks(mmc, &cmd, NULL, MMC_QUIRK_RETRY_APP_CMD, 4);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@ -1492,19 +1488,14 @@ static int sd_read_ssr(struct mmc *mmc)
|
||||
cmd.resp_type = MMC_RSP_R1;
|
||||
cmd.cmdarg = 0;
|
||||
|
||||
retry_ssr:
|
||||
data.dest = (char *)ssr;
|
||||
data.blocksize = 64;
|
||||
data.blocks = 1;
|
||||
data.flags = MMC_DATA_READ;
|
||||
|
||||
err = mmc_send_cmd(mmc, &cmd, &data);
|
||||
if (err) {
|
||||
if (timeout--)
|
||||
goto retry_ssr;
|
||||
|
||||
err = mmc_send_cmd_retry(mmc, &cmd, &data, 3);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
ssr[i] = be32_to_cpu(ssr[i]);
|
||||
@ -2179,7 +2170,7 @@ static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps)
|
||||
err = mmc_execute_tuning(mmc,
|
||||
mwt->tuning);
|
||||
if (err) {
|
||||
pr_debug("tuning failed\n");
|
||||
pr_debug("tuning failed : %d\n", err);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
@ -2200,7 +2191,7 @@ error:
|
||||
}
|
||||
}
|
||||
|
||||
pr_err("unable to select a mode\n");
|
||||
pr_err("unable to select a mode : %d\n", err);
|
||||
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
@ -2441,23 +2432,7 @@ static int mmc_startup(struct mmc *mmc)
|
||||
cmd.resp_type = MMC_RSP_R2;
|
||||
cmd.cmdarg = 0;
|
||||
|
||||
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
|
||||
|
||||
err = mmc_send_cmd_quirks(mmc, &cmd, NULL, MMC_QUIRK_RETRY_SEND_CID, 4);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@ -2745,8 +2720,8 @@ static int mmc_power_on(struct mmc *mmc)
|
||||
if (mmc->vmmc_supply) {
|
||||
int ret = regulator_set_enable(mmc->vmmc_supply, true);
|
||||
|
||||
if (ret) {
|
||||
puts("Error enabling VMMC supply\n");
|
||||
if (ret && ret != -EACCES) {
|
||||
printf("Error enabling VMMC supply : %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -2761,8 +2736,8 @@ static int mmc_power_off(struct mmc *mmc)
|
||||
if (mmc->vmmc_supply) {
|
||||
int ret = regulator_set_enable(mmc->vmmc_supply, false);
|
||||
|
||||
if (ret) {
|
||||
pr_debug("Error disabling VMMC supply\n");
|
||||
if (ret && ret != -EACCES) {
|
||||
pr_debug("Error disabling VMMC supply : %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -2866,7 +2841,7 @@ retry:
|
||||
|
||||
if (err) {
|
||||
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
|
||||
pr_err("Card did not respond to voltage select!\n");
|
||||
pr_err("Card did not respond to voltage select! : %d\n", err);
|
||||
#endif
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
@ -187,8 +187,12 @@
|
||||
|
||||
/* DLL config 0 register */
|
||||
#define DLL_ENABLE 0x80000000
|
||||
#define DLL_RESET 0x40000000
|
||||
#define DLL_FREQ_SEL 0x08000000
|
||||
|
||||
/* DLL status 0 register */
|
||||
#define DLL_STS_SLV_LOCK 0x08000000
|
||||
|
||||
#define MAX_TUNING_LOOP 40
|
||||
|
||||
#define HOSTVER_VENDOR(x) (((x) >> 8) & 0xff)
|
||||
|
Loading…
Reference in New Issue
Block a user