From 61a6cc27bce36ce2c27a8e4970796caa653c8529 Mon Sep 17 00:00:00 2001 From: Oleksandr Tyshchenko Date: Tue, 6 Aug 2013 13:44:16 +0300 Subject: [PATCH] omap_hsmmc: omap4+/am335x: modify MMC controller internal fsm reset func "mmc_send_cmd: timeout: No status update" error sometimes happens in omap_hsmmc driver func mmc_send_cmd() when the MMC controller card identification and selection sequence is executed for eMMC on OMAP4 boards. It happens due to incorrect execution of CMD line reset procedure for OMAP4. Because CMD(DAT) lines reset procedures are slightly different for OMAP3 and OMAP4(AM335x,OMAP5,DRA7xx). According to OMAP3 TRM: Set SRC(SRD) bit in MMCHS_SYSCTL register to 0x1 and wait until it returns to 0x0. According to OMAP4(AM335x,OMAP5,DRA7xx) TRMs, CMD(DATA) lines reset procedure steps must be as follows: 1. Initiate CMD(DAT) line reset by writing 0x1 to SRC(SRD) bit in MMCHS_SYSCTL register (SD_SYSCTL for AM335x). 2. Poll the SRC(SRD) bit until it is set to 0x1. 3. Wait until the SRC(SRD) bit returns to 0x0 (reset procedure is completed). Unfortunately, at present omap_hsmmc driver has support only for OMAP3. And as result step #2 is missing for OMAP4(AM335x,OMAP5,DRA7xx). This sometimes leads to the fact that the waiting loop which is required in step #3 does not executed, because SRC bit does not set yet (at the moment of checking a condition of a loop execution). And as a result this can cause to timeout error when sending a next command. In the particular case (working with eMMC witch do not respond to some SD specific command) due to incorrect reset sequence after command SD_CMD_SEND_IF_COND which finished with CTO flag within 64 clock cycles, the next command MMC_CMD_APP_CMD leads to a timeout error within 1s. So, extend CMD(DATA) lines reset procedure in func mmc_reset_controller_fsm() by adding the missing step #2 for OMAP4+/AM335x boards. Signed-off-by: Oleksandr Tyshchenko Acked-by: Pantelis Antoniou --- drivers/mmc/omap_hsmmc.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index 975b2c5ba4..0e36bf9214 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -288,6 +288,30 @@ static void mmc_reset_controller_fsm(struct hsmmc *mmc_base, u32 bit) mmc_reg_out(&mmc_base->sysctl, bit, bit); + /* + * CMD(DAT) lines reset procedures are slightly different + * for OMAP3 and OMAP4(AM335x,OMAP5,DRA7xx). + * According to OMAP3 TRM: + * Set SRC(SRD) bit in MMCHS_SYSCTL register to 0x1 and wait until it + * returns to 0x0. + * According to OMAP4(AM335x,OMAP5,DRA7xx) TRMs, CMD(DATA) lines reset + * procedure steps must be as follows: + * 1. Initiate CMD(DAT) line reset by writing 0x1 to SRC(SRD) bit in + * MMCHS_SYSCTL register (SD_SYSCTL for AM335x). + * 2. Poll the SRC(SRD) bit until it is set to 0x1. + * 3. Wait until the SRC (SRD) bit returns to 0x0 + * (reset procedure is completed). + */ +#if defined(CONFIG_OMAP44XX) || defined(CONFIG_OMAP54XX) || \ + defined(CONFIG_AM33XX) + if (!(readl(&mmc_base->sysctl) & bit)) { + start = get_timer(0); + while (!(readl(&mmc_base->sysctl) & bit)) { + if (get_timer(0) - start > MAX_RETRY_MS) + return; + } + } +#endif start = get_timer(0); while ((readl(&mmc_base->sysctl) & bit) != 0) { if (get_timer(0) - start > MAX_RETRY_MS) { -- 2.39.5