mirror of
https://github.com/AsahiLinux/u-boot
synced 2025-02-18 06:58:54 +00:00
mmc: stm32_sdmmc2: Fix r1b timeout issue
On response type r1b, if DTIME is not defined or too short, the Datatimeout and DPSM flag occurs. Like the DPSM is activated all next data transfer will be frozen. To avoid this freeze: -The driver must define a DTIME on all r1b response type. -DTIME of SDMMC must be defined for alls stop transmission (for read and write request) even if MMC_RSP_BUSY is not set. -If busy timeout occur, an abort request must be sent to reinitialize the DPSM. Signed-off-by: Christophe Kerello <christophe.kerello@st.com> Signed-off-by: Patrice Chotard <patrice.chotard@st.com> Tested-by: Patrick DELAUNAY <patrick.delaunay@st.com>
This commit is contained in:
parent
b611535238
commit
c406a47431
1 changed files with 55 additions and 6 deletions
|
@ -190,6 +190,7 @@ struct stm32_sdmmc2_ctx {
|
|||
#define SDMMC_IDMACTRL_IDMAEN BIT(0)
|
||||
|
||||
#define SDMMC_CMD_TIMEOUT 0xFFFFFFFF
|
||||
#define SDMMC_BUSYD0END_TIMEOUT_US 1000000
|
||||
|
||||
static void stm32_sdmmc2_start_data(struct stm32_sdmmc2_priv *priv,
|
||||
struct mmc_data *data,
|
||||
|
@ -209,9 +210,6 @@ static void stm32_sdmmc2_start_data(struct stm32_sdmmc2_priv *priv,
|
|||
idmabase0 = (u32)data->src;
|
||||
}
|
||||
|
||||
/* Set the SDMMC Data TimeOut value */
|
||||
writel(SDMMC_CMD_TIMEOUT, priv->base + SDMMC_DTIMER);
|
||||
|
||||
/* Set the SDMMC DataLength value */
|
||||
writel(ctx->data_length, priv->base + SDMMC_DLEN);
|
||||
|
||||
|
@ -236,8 +234,11 @@ static void stm32_sdmmc2_start_data(struct stm32_sdmmc2_priv *priv,
|
|||
}
|
||||
|
||||
static void stm32_sdmmc2_start_cmd(struct stm32_sdmmc2_priv *priv,
|
||||
struct mmc_cmd *cmd, u32 cmd_param)
|
||||
struct mmc_cmd *cmd, u32 cmd_param,
|
||||
struct stm32_sdmmc2_ctx *ctx)
|
||||
{
|
||||
u32 timeout = 0;
|
||||
|
||||
if (readl(priv->base + SDMMC_CMD) & SDMMC_CMD_CPSMEN)
|
||||
writel(0, priv->base + SDMMC_CMD);
|
||||
|
||||
|
@ -251,6 +252,26 @@ static void stm32_sdmmc2_start_cmd(struct stm32_sdmmc2_priv *priv,
|
|||
cmd_param |= SDMMC_CMD_WAITRESP_1;
|
||||
}
|
||||
|
||||
/*
|
||||
* SDMMC_DTIME must be set in two case:
|
||||
* - on data transfert.
|
||||
* - on busy request.
|
||||
* If not done or too short, the dtimeout flag occurs and DPSM stays
|
||||
* enabled/busy and waits for abort (stop transmission cmd).
|
||||
* Next data command is not possible whereas DPSM is activated.
|
||||
*/
|
||||
if (ctx->data_length) {
|
||||
timeout = SDMMC_CMD_TIMEOUT;
|
||||
} else {
|
||||
writel(0, priv->base + SDMMC_DCTRL);
|
||||
|
||||
if (cmd->resp_type & MMC_RSP_BUSY)
|
||||
timeout = SDMMC_CMD_TIMEOUT;
|
||||
}
|
||||
|
||||
/* Set the SDMMC Data TimeOut value */
|
||||
writel(timeout, priv->base + SDMMC_DTIMER);
|
||||
|
||||
/* Clear flags */
|
||||
writel(SDMMC_ICR_STATIC_FLAGS, priv->base + SDMMC_ICR);
|
||||
|
||||
|
@ -309,6 +330,31 @@ static int stm32_sdmmc2_end_cmd(struct stm32_sdmmc2_priv *priv,
|
|||
cmd->response[2] = readl(priv->base + SDMMC_RESP3);
|
||||
cmd->response[3] = readl(priv->base + SDMMC_RESP4);
|
||||
}
|
||||
|
||||
/* Wait for BUSYD0END flag if busy status is detected */
|
||||
if (cmd->resp_type & MMC_RSP_BUSY &&
|
||||
status & SDMMC_STA_BUSYD0) {
|
||||
mask = SDMMC_STA_DTIMEOUT | SDMMC_STA_BUSYD0END;
|
||||
|
||||
/* Polling status register */
|
||||
ret = readl_poll_timeout(priv->base + SDMMC_STA,
|
||||
status, status & mask,
|
||||
SDMMC_BUSYD0END_TIMEOUT_US);
|
||||
|
||||
if (ret < 0) {
|
||||
debug("%s: timeout reading SDMMC_STA\n",
|
||||
__func__);
|
||||
ctx->dpsm_abort = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (status & SDMMC_STA_DTIMEOUT) {
|
||||
debug("%s: error SDMMC_STA_DTIMEOUT (0x%x)\n",
|
||||
__func__, status);
|
||||
ctx->dpsm_abort = true;
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -395,7 +441,7 @@ retry_cmd:
|
|||
stm32_sdmmc2_start_data(priv, data, &ctx);
|
||||
}
|
||||
|
||||
stm32_sdmmc2_start_cmd(priv, cmd, cmdat);
|
||||
stm32_sdmmc2_start_cmd(priv, cmd, cmdat, &ctx);
|
||||
|
||||
debug("%s: send cmd %d data: 0x%x @ 0x%x\n",
|
||||
__func__, cmd->cmdidx,
|
||||
|
@ -425,7 +471,10 @@ retry_cmd:
|
|||
debug("%s: send STOP command to abort dpsm treatments\n",
|
||||
__func__);
|
||||
|
||||
stm32_sdmmc2_start_cmd(priv, &stop_cmd, SDMMC_CMD_CMDSTOP);
|
||||
ctx.data_length = 0;
|
||||
|
||||
stm32_sdmmc2_start_cmd(priv, &stop_cmd,
|
||||
SDMMC_CMD_CMDSTOP, &ctx);
|
||||
stm32_sdmmc2_end_cmd(priv, &stop_cmd, &ctx);
|
||||
|
||||
writel(SDMMC_ICR_STATIC_FLAGS, priv->base + SDMMC_ICR);
|
||||
|
|
Loading…
Add table
Reference in a new issue