- 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:
Tom Rini 2020-11-29 11:12:59 -05:00
commit a7ab4b71d5
3 changed files with 95 additions and 94 deletions

View File

@ -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(&regs->tbctl) & HS400_MODE &&
@ -640,17 +644,33 @@ static void esdhc_set_timing(struct fsl_esdhc_priv *priv, enum bus_mode mode)
esdhc_setbits32(&regs->dllcfg0, DLL_FREQ_SEL);
esdhc_setbits32(&regs->dllcfg0, DLL_ENABLE);
esdhc_setbits32(&regs->dllcfg0, DLL_RESET);
udelay(1);
esdhc_clrbits32(&regs->dllcfg0, DLL_RESET);
start = get_timer(0);
val = DLL_STS_SLV_LOCK;
while (!(esdhc_read32(&regs->dllstat0) & val)) {
if (get_timer(start) > 1000) {
printf("fsl_esdhc: delay chain lock timeout\n");
return -ETIMEDOUT;
}
}
esdhc_setbits32(&regs->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(&regs->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(&regs->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(&regs->irqstaten, IRQSTATEN_BRR | IRQSTATEN_BWR);

View File

@ -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;
}

View File

@ -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)