Merge "platform: msm_shared: Fix ADMA error"
diff --git a/platform/msm_shared/include/sdhci.h b/platform/msm_shared/include/sdhci.h
index 0c15c06..b555d76 100644
--- a/platform/msm_shared/include/sdhci.h
+++ b/platform/msm_shared/include/sdhci.h
@@ -88,7 +88,7 @@
 struct desc_entry {
 	uint16_t tran_att;   /* Attribute for transfer data */
 	uint16_t len;        /* Length of data */
-	void *addr;          /* Address of the data */
+	uint32_t addr;       /* Address of the data */
 };
 
 /*
diff --git a/platform/msm_shared/sdhci.c b/platform/msm_shared/sdhci.c
index 221d2dd..21e3097 100644
--- a/platform/msm_shared/sdhci.c
+++ b/platform/msm_shared/sdhci.c
@@ -386,7 +386,7 @@
 static uint8_t sdhci_cmd_complete(struct sdhci_host *host, struct mmc_command *cmd)
 {
 	uint8_t i;
-	uint16_t retry = 0;
+	uint32_t retry = 0;
 	uint32_t int_status;
 
 	do {
@@ -485,14 +485,14 @@
 
 	if (len <= SDHCI_ADMA_DESC_LINE_SZ) {
 		/* Allocate only one descriptor */
-		sg_list = (struct desc_entry *) memalign(4, sizeof(struct desc_entry));
+		sg_list = (struct desc_entry *) memalign(lcm(4, CACHE_LINE), ROUNDUP(sizeof(struct desc_entry), CACHE_LINE));
 
 		if (!sg_list) {
 			dprintf(CRITICAL, "Error allocating memory\n");
 			ASSERT(0);
 		}
 
-		sg_list[0].addr = data;
+		sg_list[0].addr = (uint32_t)data;
 		sg_list[0].len = len;
 		sg_list[0].tran_att = SDHCI_ADMA_TRANS_VALID | SDHCI_ADMA_TRANS_DATA
 							  | SDHCI_ADMA_TRANS_END;
@@ -502,13 +502,14 @@
 		/* Calculate the number of entries in desc table */
 		sg_len = len / SDHCI_ADMA_DESC_LINE_SZ;
 		remain = len - (sg_len * SDHCI_ADMA_DESC_LINE_SZ);
-		/* Allocate sg_len + 1 entries */
+
+		/* Allocate sg_len + 1 entries if there are remaining bytes at the end */
 		if (remain)
 			sg_len++;
 
 		table_len = (sg_len * sizeof(struct desc_entry));
 
-		sg_list = (struct desc_entry *) memalign(4, table_len);
+		sg_list = (struct desc_entry *) memalign(lcm(4, CACHE_LINE), ROUNDUP(table_len, CACHE_LINE));
 
 		if (!sg_list) {
 			dprintf(CRITICAL, "Error allocating memory\n");
@@ -525,7 +526,7 @@
 		 * |_____________|_______________|_____________________|
 		 */
 		for (i = 0; i < (sg_len - 1); i++) {
-				sg_list[i].addr = data;
+				sg_list[i].addr = (uint32_t)data;
 				sg_list[i].len = SDHCI_ADMA_DESC_LINE_SZ;
 				sg_list[i].tran_att = SDHCI_ADMA_TRANS_VALID | SDHCI_ADMA_TRANS_DATA;
 				data += SDHCI_ADMA_DESC_LINE_SZ;
@@ -535,10 +536,10 @@
 			/* Fill the last entry of the table with Valid & End
 			 * attributes
 			 */
-			sg_list[sg_len - 1].addr = data;
+			sg_list[sg_len - 1].addr = (uint32_t)data;
 			sg_list[sg_len - 1].len = len;
-			sg_list[sg_len - 1].tran_att = SDHCI_ADMA_TRANS_VALID | SDHCI_ADMA_TRANS_DATA
-										   | SDHCI_ADMA_TRANS_END;
+			sg_list[sg_len - 1].tran_att = SDHCI_ADMA_TRANS_VALID | SDHCI_ADMA_TRANS_DATA |
+										   SDHCI_ADMA_TRANS_END;
 		}
 
 	arch_clean_invalidate_cache_range((addr_t)sg_list, table_len);
@@ -550,16 +551,15 @@
  * Function: sdhci adma transfer
  * Arg     : Host structure & command stucture
  * Return  : Pointer to desc table
- * Flow    : 1. Prepare data transfer properties
+ * Flow    : 1. Prepare descriptor table
  *           2. Write adma register
- *           3. Write transfer mode register
+ *           3. Write block size & block count register
  */
 static struct desc_entry *sdhci_adma_transfer(struct sdhci_host *host,
 											  struct mmc_command *cmd)
 {
 	uint32_t num_blks = 0;
 	uint32_t sz;
-	uint16_t trans_mode = 0;
 	void *data;
 	struct desc_entry *adma_addr;
 
@@ -583,35 +583,20 @@
 	/* Prepare adma descriptor table */
 	adma_addr = sdhci_prep_desc_table(data, sz);
 
+	/* Write adma address to adma register */
+	REG_WRITE32(host, (uint32_t) adma_addr, SDHCI_ADM_ADDR_REG);
+
 	/* Write the block size */
 	if (cmd->data.blk_sz)
 		REG_WRITE16(host, cmd->data.blk_sz, SDHCI_BLKSZ_REG);
 	else
 		REG_WRITE16(host, SDHCI_MMC_BLK_SZ, SDHCI_BLKSZ_REG);
 
-	/* Enalbe auto cmd 23 for multi block transfer */
-	if (num_blks > 1) {
-		trans_mode |= SDHCI_TRANS_MULTI | SDHCI_AUTO_CMD23_EN | SDHCI_BLK_CNT_EN;
-		REG_WRITE32(host, num_blks, SDHCI_ARG2_REG);
-	}
-
 	/*
 	 * Set block count in block count register
 	 */
-
 	REG_WRITE16(host, num_blks, SDHCI_BLK_CNT_REG);
 
-	if (cmd->trans_mode == SDHCI_MMC_READ)
-		trans_mode |= SDHCI_READ_MODE;
-
-	trans_mode |= SDHCI_DMA_EN;
-
-	/* Write adma address to adma register */
-	REG_WRITE32(host, (uint32_t) adma_addr, SDHCI_ADM_ADDR_REG);
-
-	/* Set transfer mode */
-	REG_WRITE16(host, trans_mode, SDHCI_TRANS_MODE_REG);
-
 	return adma_addr;
 }
 
@@ -628,6 +613,7 @@
 {
 	uint8_t retry = 0;
 	uint32_t resp_type = 0;
+	uint16_t trans_mode = 0;
 	uint16_t present_state;
 	uint32_t flags;
 	struct desc_entry *sg_list = NULL;
@@ -711,6 +697,25 @@
 	/* Write the argument 1 */
 	REG_WRITE32(host, cmd->argument, SDHCI_ARGUMENT_REG);
 
+	/* Set the Transfer mode */
+	if (cmd->data_present)
+	{
+		/* Enable DMA */
+		trans_mode |= SDHCI_DMA_EN;
+
+		if (cmd->trans_mode == SDHCI_MMC_READ)
+			trans_mode |= SDHCI_READ_MODE;
+
+		/* Enable auto cmd 23 for multi block transfer */
+		if (cmd->data.num_blocks > 1) {
+			trans_mode |= SDHCI_TRANS_MULTI | SDHCI_AUTO_CMD23_EN | SDHCI_BLK_CNT_EN;
+			REG_WRITE32(host, cmd->data.num_blocks, SDHCI_ARG2_REG);
+		}
+	}
+
+	/* Write to transfer mode register */
+	REG_WRITE16(host, trans_mode, SDHCI_TRANS_MODE_REG);
+
 	/* Write the command register */
 	REG_WRITE16(host, SDHCI_PREP_CMD(cmd->cmd_index, flags), SDHCI_CMD_REG);