Commit fafc23d5 authored by Ye Li's avatar Ye Li Committed by Jason Liu

MLK-16288 fsl_esdhc: Workaround for eMMC HS200 and SD SDR104 switch fail issue

Met randomly switch fail (60%) on 8QXP ARM2 A1 board, when entering eMMC HS200 or SD SDR104 mode.
The failure happens on the first command (CMD55 for SD,  CMD8 for eMMC) after the tuning process
is done.  The failure error is CTOE (command timeout).  Can't reproduce it on QXP MEK.

This patch addes a workaround to send CMD12 after tuning process is done.  This helps to stop any
transmission that device may involve during tuning. The stress test is passed on QXP ARM A1 with
this workaround added.

Also this patch fixes a issue for tuning parameter "tuning_start_tap".
Signed-off-by: default avatarYe Li <ye.li@nxp.com>
Reviewed-by: default avatarPeng Fan <peng.fan@nxp.com>
parent 0767e4ca
......@@ -27,6 +27,7 @@
#include <power/regulator.h>
#include <asm/arch/sys_proto.h>
#include <dm/pinctrl.h>
#include "mmc_private.h"
DECLARE_GLOBAL_DATA_PTR;
......@@ -148,6 +149,29 @@ struct fsl_esdhc_priv {
#endif
};
static void esdhc_dump(struct mmc *mmc)
{
#ifdef DEBUG
struct fsl_esdhc_priv *priv = mmc->priv;
struct fsl_esdhc *regs = priv->esdhc_regs;
ulong addr = (ulong)regs;
int i = 0;
for (i = 0; i < 0xd0; i+=4) {
if (i % 16 == 0) {
printf("\n");
printf("0x%08x: ", addr + i);
}
printf("0x%08x ", readl(addr + i));
}
printf("\n");
#endif
}
/* Return the XFERTYP flags for a given command and data packet */
static uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data)
{
......@@ -299,7 +323,7 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
}
} else {
#ifdef CONFIG_DM_GPIO
if (dm_gpio_is_valid(&priv->wp_gpio) && dm_gpio_get_value(&priv->wp_gpio)) {
if (dm_gpio_is_valid(&priv->wp_gpio) && dm_gpio_get_value(&priv->wp_gpio)) {
printf("\nThe SD card is locked. Can not write to a locked card.\n\n");
return -ETIMEDOUT;
}
......@@ -559,6 +583,8 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
out:
/* Reset CMD and DATA portions on error */
if (err) {
esdhc_dump(mmc);
esdhc_write32(&regs->sysctl, esdhc_read32(&regs->sysctl) |
SYSCTL_RSTC);
while (esdhc_read32(&regs->sysctl) & SYSCTL_RSTC)
......@@ -786,6 +812,16 @@ static int esdhc_set_voltage(struct mmc *mmc)
}
}
static void esdhc_stop_tuning(struct mmc *mmc)
{
struct mmc_cmd cmd;
cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
cmd.cmdarg = 0;
cmd.resp_type = MMC_RSP_R1b;
mmc_send_cmd(mmc, &cmd, NULL);
}
static int esdhc_execute_tuning(struct mmc *mmc, uint32_t opcode)
{
struct fsl_esdhc_priv *priv = mmc->priv;
......@@ -857,6 +893,8 @@ static int esdhc_execute_tuning(struct mmc *mmc, uint32_t opcode)
writel(irqstaten, &regs->irqstaten);
writel(irqsigen, &regs->irqsigen);
esdhc_stop_tuning(mmc);
return ret;
}
......@@ -1154,7 +1192,6 @@ static int fsl_esdhc_init(struct fsl_esdhc_priv *priv)
if (priv->flags & ESDHC_FLAG_STD_TUNING) {
val = readl(&regs->tuning_ctrl);
val |= ESDHC_STD_TUNING_EN;
val |= ESDHC_TUNING_START_TAP_DEFAULT;
val &= ~ESDHC_TUNING_START_TAP_MASK;
val |= priv->tuning_start_tap;
val &= ~ESDHC_TUNING_STEP_MASK;
......@@ -1343,8 +1380,8 @@ static int fsl_esdhc_probe(struct udevice *dev)
val = fdtdec_get_int(fdt, node, "fsl,tuning-step", 1);
priv->tuning_step = val;
val = fdtdec_get_int(fdt, node, "fsl,tuning-start-tap", 0);
priv->tuning_step = val;
val = fdtdec_get_int(fdt, node, "fsl,tuning-start-tap", ESDHC_TUNING_START_TAP_DEFAULT);
priv->tuning_start_tap = val;
if (fdt_get_property(fdt, node, "non-removable", NULL)) {
priv->non_removable = 1;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment