platform: msm_shared: Handle data timeout & transfer complete status

As per sdhci spec data timeout & transfer compelte can be set together.
Transfer complete takes higher priority, in such case we need to ignore
data timeout error.

CRs-Fixed: 547639
Change-Id: I97324ef06a778de57d00fb48f89ef59816ecfe5f
diff --git a/platform/msm_shared/sdhci.c b/platform/msm_shared/sdhci.c
index 03996f9..4399c60 100644
--- a/platform/msm_shared/sdhci.c
+++ b/platform/msm_shared/sdhci.c
@@ -383,8 +383,11 @@
 static uint8_t sdhci_cmd_complete(struct sdhci_host *host, struct mmc_command *cmd)
 {
 	uint8_t i;
+	uint8_t ret = 0;
+	uint8_t need_reset = 0;
 	uint32_t retry = 0;
 	uint32_t int_status;
+	uint32_t trans_complete = 0;
 
 	do {
 		int_status = REG_READ16(host, SDHCI_NRML_INT_STS_REG);
@@ -397,6 +400,7 @@
 		udelay(500);
 		if (retry == SDHCI_MAX_CMD_RETRY) {
 			dprintf(CRITICAL, "Error: Command never completed\n");
+			ret = 1;
 			goto err;
 		}
 	} while(1);
@@ -435,12 +439,16 @@
 			int_status &= SDHCI_INT_STS_TRANS_COMPLETE;
 
 			if (int_status & SDHCI_INT_STS_TRANS_COMPLETE)
+			{
+				trans_complete = 1;
 				break;
+			}
 
 			retry++;
 			udelay(1000);
 			if (retry == SDHCI_MAX_TRANS_RETRY) {
 				dprintf(CRITICAL, "Error: Transfer never completed\n");
+				ret = 1;
 				goto err;
 			}
 		} while(1);
@@ -452,20 +460,41 @@
 err:
 	/* Look for errors */
 	int_status = REG_READ16(host, SDHCI_NRML_INT_STS_REG);
-	if (int_status & SDHCI_ERR_INT_STAT_MASK) {
-		if (sdhci_cmd_err_status(host)) {
-			dprintf(CRITICAL, "Error: Command completed with errors\n");
-			/* Reset the command & Data line */
-			sdhci_reset(host, (SOFT_RESET_CMD | SOFT_RESET_DATA));
-			return 1;
+
+	if (int_status & SDHCI_ERR_INT_STAT_MASK)
+	{
+		/*
+		 * As per SDHC spec transfer complete has higher priority than data timeout
+		 * If both transfer complete & data timeout are set then we should ignore
+		 * data timeout error.
+		 * ---------------------------------------------------------------------------
+		 * | Transfer complete | Data timeout error | Meaning of the Status           |
+		 * |--------------------------------------------------------------------------|
+		 * |      0            |       0            | Interrupted by another factor   |
+		 * |--------------------------------------------------------------------------|
+		 * |      0            |       1            | Time out occured during transfer|
+		 * |--------------------------------------------------------------------------|
+		 * |      1            |  Don't Care        | Command execution complete      |
+		 *  --------------------------------------------------------------------------
+		 */
+		if ((REG_READ16(host, SDHCI_ERR_INT_STS_REG) & SDHCI_DAT_TIMEOUT_MASK) && trans_complete)
+		{
+			ret = 0;
 		}
+		else if (sdhci_cmd_err_status(host))
+		{
+			dprintf(CRITICAL, "Error: Command completed with errors\n");
+			ret = 1;
+		}
+		/* Reset Command & Dat lines on error */
+		need_reset = 1;
 	}
 
 	/* Reset data & command line */
-	if (cmd->data_present)
+	if (cmd->data_present || need_reset)
 		sdhci_reset(host, (SOFT_RESET_CMD | SOFT_RESET_DATA));
 
-	return 0;
+	return ret;
 }
 
 /*