mmc: sdhci: introduce adma_write_desc() hook to struct sdhci_ops

Add this hook so that it can be overridden with driver specific
implementations. We also let the original sdhci_adma_write_desc()
accept &desc so that the function can set its new value. Then export
the function so that it could be reused by driver's specific
implementations.

The above is a port of Linux kernel commit 54552e4948cbf

In addition, allow drivers to allocate their own ADMA descriptor
tables if additional space is required.

Finally, fix the assignment of adma_addr to fix compiler warning
on 64-bit platforms that still use 32-bit DMA addressing.

Co-developed-by: Nathan Barrett-Morrison <nathan.morrison@timesys.com>
Signed-off-by: Nathan Barrett-Morrison <nathan.morrison@timesys.com>
Co-developed-by: Greg Malysa <greg.malysa@timesys.com>
Signed-off-by: Greg Malysa <greg.malysa@timesys.com>
Signed-off-by: Ian Roberts <ian.roberts@timesys.com>
diff --git a/drivers/mmc/sdhci-adma.c b/drivers/mmc/sdhci-adma.c
index 8213223..8c38448 100644
--- a/drivers/mmc/sdhci-adma.c
+++ b/drivers/mmc/sdhci-adma.c
@@ -9,9 +9,10 @@
 #include <malloc.h>
 #include <asm/cache.h>
 
-static void sdhci_adma_desc(struct sdhci_adma_desc *desc,
-			    dma_addr_t addr, u16 len, bool end)
+void sdhci_adma_write_desc(struct sdhci_host *host, void **next_desc,
+			   dma_addr_t addr, int len, bool end)
 {
+	struct sdhci_adma_desc *desc = *next_desc;
 	u8 attr;
 
 	attr = ADMA_DESC_ATTR_VALID | ADMA_DESC_TRANSFER_DATA;
@@ -19,17 +20,30 @@
 		attr |= ADMA_DESC_ATTR_END;
 
 	desc->attr = attr;
-	desc->len = len;
+	desc->len = len & 0xffff;
 	desc->reserved = 0;
 	desc->addr_lo = lower_32_bits(addr);
 #ifdef CONFIG_DMA_ADDR_T_64BIT
 	desc->addr_hi = upper_32_bits(addr);
 #endif
+
+	*next_desc += ADMA_DESC_LEN;
+}
+
+static inline void __sdhci_adma_write_desc(struct sdhci_host *host,
+					   void **desc, dma_addr_t addr,
+					   int len, bool end)
+{
+	if (host && host->ops && host->ops->adma_write_desc)
+		host->ops->adma_write_desc(host, desc, addr, len, end);
+	else
+		sdhci_adma_write_desc(host, desc, addr, len, end);
 }
 
 /**
  * sdhci_prepare_adma_table() - Populate the ADMA table
  *
+ * @host:	Pointer to the sdhci_host
  * @table:	Pointer to the ADMA table
  * @data:	Pointer to MMC data
  * @addr:	DMA address to write to or read from
@@ -39,25 +53,26 @@
  * Please note, that the table size depends on CONFIG_SYS_MMC_MAX_BLK_COUNT and
  * we don't have to check for overflow.
  */
-void sdhci_prepare_adma_table(struct sdhci_adma_desc *table,
-			      struct mmc_data *data, dma_addr_t addr)
+void sdhci_prepare_adma_table(struct sdhci_host *host,
+			      struct sdhci_adma_desc *table,
+			      struct mmc_data *data, dma_addr_t start_addr)
 {
+	dma_addr_t addr = start_addr;
 	uint trans_bytes = data->blocksize * data->blocks;
-	uint desc_count = DIV_ROUND_UP(trans_bytes, ADMA_MAX_LEN);
-	struct sdhci_adma_desc *desc = table;
-	int i = desc_count;
+	void *next_desc = table;
+	int i = DIV_ROUND_UP(trans_bytes, ADMA_MAX_LEN);
 
 	while (--i) {
-		sdhci_adma_desc(desc, addr, ADMA_MAX_LEN, false);
+		__sdhci_adma_write_desc(host, &next_desc, addr,
+					ADMA_MAX_LEN, false);
 		addr += ADMA_MAX_LEN;
 		trans_bytes -= ADMA_MAX_LEN;
-		desc++;
 	}
 
-	sdhci_adma_desc(desc, addr, trans_bytes, true);
+	__sdhci_adma_write_desc(host, &next_desc, addr, trans_bytes, true);
 
-	flush_cache((dma_addr_t)table,
-		    ROUND(desc_count * sizeof(struct sdhci_adma_desc),
+	flush_cache((phys_addr_t)table,
+		    ROUND(next_desc - (void *)table,
 			  ARCH_DMA_MINALIGN));
 }