summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYe Li <ye.li@nxp.com>2017-08-29 02:18:55 -0500
committerYe Li <ye.li@nxp.com>2017-08-29 21:42:05 -0500
commit2282451d00b19375550374ef4998b89cda57ca7a (patch)
tree977642531086eb7e19658c0241e23df3af58325b
parentbf9bf218258b550c51980b0f2065a3054c865b23 (diff)
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: Ye Li <ye.li@nxp.com> Reviewed-by: Peng Fan <peng.fan@nxp.com>
-rw-r--r--drivers/mmc/fsl_esdhc.c45
1 files changed, 41 insertions, 4 deletions
diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index 53a264c399..84088f9950 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -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;