]> git.kernelconcepts.de Git - karo-tx-uboot.git/commitdiff
omap_hsmmc: omap4+/am335x: modify MMC controller internal fsm reset func
authorOleksandr Tyshchenko <oleksandr.tyshchenko@ti.com>
Tue, 6 Aug 2013 10:44:16 +0000 (13:44 +0300)
committerPantelis Antoniou <panto@antoniou-consulting.com>
Tue, 17 Sep 2013 17:03:44 +0000 (20:03 +0300)
"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 <oleksandr.tyshchenko@ti.com>
Acked-by: Pantelis Antoniou <panto@antoniou-consulting.com>
drivers/mmc/omap_hsmmc.c

index 975b2c5ba4d74b1ae875a205341efec5bd233e82..0e36bf92149301e25682300ef5e8b43869a5c5cc 100644 (file)
@@ -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) {