소스 검색

mmc: make mmc_send_status() more reliable

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>
Jan Kloetzke 13 년 전
부모
커밋
d617c426a6
2개의 변경된 파일14개의 추가작업 그리고 8개의 파일을 삭제
  1. 12 8
      drivers/mmc/mmc.c
  2. 2 0
      include/mmc.h

+ 12 - 8
drivers/mmc/mmc.c

@@ -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

+ 2 - 0
include/mmc.h

@@ -112,6 +112,8 @@
 #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 */