mmc: make mmc_send_status() more reliable
authorJan Kloetzke <jan.kloetzke@dspg.com>
Sun, 5 Feb 2012 22:29:12 +0000 (22:29 +0000)
committerAndy Fleming <afleming@freescale.com>
Wed, 15 Feb 2012 23:42:22 +0000 (17:42 -0600)
Align the card status polling with the Linux kernel and retry the
command at least five times. Also some cards apparently mishandle the
status bits, so make sure to check the card state too.

Signed-off-by: Jan Kloetzke <jan.kloetzke@dspg.com>
Cc: Andy Fleming <afleming@gmail.com>
drivers/mmc/mmc.c
include/mmc.h

index 7b0927257bdf1a8ec5b8c0c09ea8530fc57a7cd6..49c3349f55f237e02682a4c9d65043aafd7cd2c1 100644 (file)
@@ -108,7 +108,7 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 int mmc_send_status(struct mmc *mmc, int timeout)
 {
        struct mmc_cmd cmd;
-       int err;
+       int err, retries = 5;
 #ifdef CONFIG_MMC_TRACE
        int status;
 #endif
@@ -121,17 +121,21 @@ int mmc_send_status(struct mmc *mmc, int timeout)
 
        do {
                err = mmc_send_cmd(mmc, &cmd, NULL);
-               if (err)
+               if (!err) {
+                       if ((cmd.response[0] & MMC_STATUS_RDY_FOR_DATA) &&
+                           (cmd.response[0] & MMC_STATUS_CURR_STATE) !=
+                            MMC_STATE_PRG)
+                               break;
+                       else if (cmd.response[0] & MMC_STATUS_MASK) {
+                               printf("Status Error: 0x%08X\n",
+                                       cmd.response[0]);
+                               return COMM_ERR;
+                       }
+               } else if (--retries < 0)
                        return err;
-               else if (cmd.response[0] & MMC_STATUS_RDY_FOR_DATA)
-                       break;
 
                udelay(1000);
 
-               if (cmd.response[0] & MMC_STATUS_MASK) {
-                       printf("Status Error: 0x%08X\n", cmd.response[0]);
-                       return COMM_ERR;
-               }
        } while (timeout--);
 
 #ifdef CONFIG_MMC_TRACE
index 8744604ead1b7db30287d744494e0957c285bbd9..30c2375357fb8ab76ff6b131c71afc330ada22f0 100644 (file)
 #define MMC_STATUS_CURR_STATE  (0xf << 9)
 #define MMC_STATUS_ERROR       (1 << 19)
 
+#define MMC_STATE_PRG          (7 << 9)
+
 #define MMC_VDD_165_195                0x00000080      /* VDD voltage 1.65 - 1.95 */
 #define MMC_VDD_20_21          0x00000100      /* VDD voltage 2.0 ~ 2.1 */
 #define MMC_VDD_21_22          0x00000200      /* VDD voltage 2.1 ~ 2.2 */