mmc: add required delays when retrying commands
authorYann Gautier <yann.gautier@st.com>
Thu, 2 Aug 2018 11:46:17 +0000 (13:46 +0200)
committerYann Gautier <yann.gautier@st.com>
Thu, 2 Aug 2018 11:48:17 +0000 (13:48 +0200)
A new function mmc_reset_to_idle is also created.

Signed-off-by: Yann Gautier <yann.gautier@st.com>
drivers/mmc/mmc.c

index 8fe3239e5126fa23747f3c8e757fb78ce76007ab..0c9ec1017e30bbe7531a4c26b9c750ca81e4c0f4 100644 (file)
@@ -9,6 +9,7 @@
 #include <arch_helpers.h>
 #include <assert.h>
 #include <debug.h>
+#include <delay_timer.h>
 #include <errno.h>
 #include <mmc.h>
 #include <stdbool.h>
@@ -319,18 +320,12 @@ static int mmc_fill_device_info(void)
 
 static int sd_send_op_cond(void)
 {
-       int retries = SEND_OP_COND_MAX_RETRIES;
+       int n;
        unsigned int resp_data[4];
 
-       do {
+       for (n = 0; n < SEND_OP_COND_MAX_RETRIES; n++) {
                int ret;
 
-               if (retries == 0) {
-                       ERROR("ACMD41 failed after %d retries\n",
-                             SEND_OP_COND_MAX_RETRIES);
-                       return -EIO;
-               }
-
                /* CMD55: Application Specific Command */
                ret = mmc_send_cmd(MMC_CMD(55), 0, MMC_RESPONSE_R(1), NULL);
                if (ret != 0) {
@@ -344,25 +339,31 @@ static int sd_send_op_cond(void)
                        return ret;
                }
 
-               retries--;
-       } while ((resp_data[0] & OCR_POWERUP) == 0U);
+               if ((resp_data[0] & OCR_POWERUP) != 0U) {
+                       mmc_ocr_value = resp_data[0];
 
-       mmc_ocr_value = resp_data[0];
+                       if ((mmc_ocr_value & OCR_HCS) != 0U) {
+                               mmc_dev_info->mmc_dev_type = MMC_IS_SD_HC;
+                       } else {
+                               mmc_dev_info->mmc_dev_type = MMC_IS_SD;
+                       }
 
-       if ((mmc_ocr_value & OCR_HCS) != 0U) {
-               mmc_dev_info->mmc_dev_type = MMC_IS_SD_HC;
-       } else {
-               mmc_dev_info->mmc_dev_type = MMC_IS_SD;
+                       return 0;
+               }
+
+               mdelay(1);
        }
 
-       return 0;
+       ERROR("ACMD41 failed after %d retries\n", SEND_OP_COND_MAX_RETRIES);
+
+       return -EIO;
 }
 
-static int mmc_send_op_cond(void)
+static int mmc_reset_to_idle(void)
 {
        int ret;
-       int retries = SEND_OP_COND_MAX_RETRIES;
-       unsigned int resp_data[4];
+
+       mdelay(1);
 
        /* CMD0: reset to IDLE */
        ret = mmc_send_cmd(MMC_CMD(0), 0, 0, NULL);
@@ -370,14 +371,19 @@ static int mmc_send_op_cond(void)
                return ret;
        }
 
-       do {
-               if (retries == 0) {
-                       ERROR("CMD1 failed after %d retries\n",
-                             SEND_OP_COND_MAX_RETRIES);
-                       return -EIO;
-               }
+       mdelay(2);
 
-               /* CMD1: get OCR register (SEND_OP_COND) */
+       return 0;
+}
+
+static int mmc_send_op_cond(void)
+{
+       int ret, n;
+       unsigned int resp_data[4];
+
+       mmc_reset_to_idle();
+
+       for (n = 0; n < SEND_OP_COND_MAX_RETRIES; n++) {
                ret = mmc_send_cmd(MMC_CMD(1), OCR_SECTOR_MODE |
                                   OCR_VDD_MIN_2V7 | OCR_VDD_MIN_1V7,
                                   MMC_RESPONSE_R(3), &resp_data[0]);
@@ -385,12 +391,17 @@ static int mmc_send_op_cond(void)
                        return ret;
                }
 
-               retries--;
-       } while ((resp_data[0] & OCR_POWERUP) == 0U);
+               if ((resp_data[0] & OCR_POWERUP) != 0U) {
+                       mmc_ocr_value = resp_data[0];
+                       return 0;
+               }
 
-       mmc_ocr_value = resp_data[0];
+               mdelay(1);
+       }
 
-       return 0;
+       ERROR("CMD1 failed after %d retries\n", SEND_OP_COND_MAX_RETRIES);
+
+       return -EIO;
 }
 
 static int mmc_enumerate(unsigned int clk, unsigned int bus_width)
@@ -400,11 +411,7 @@ static int mmc_enumerate(unsigned int clk, unsigned int bus_width)
 
        ops->init();
 
-       /* CMD0: reset to IDLE */
-       ret = mmc_send_cmd(MMC_CMD(0), 0, 0, NULL);
-       if (ret != 0) {
-               return ret;
-       }
+       mmc_reset_to_idle();
 
        /* CMD8: Send Interface Condition Command */
        ret = mmc_send_cmd(MMC_CMD(8), VHS_2_7_3_6_V | CMD8_CHECK_PATTERN,