Merge tag 'mmc-2020-10-14' of https://gitlab.denx.de/u-boot/custodians/u-boot-mmc

- fsl_esdhc_imx cleanup
- not send cm13 if send_status is 0.
- Add reinit API
- Add mmc HS400 for fsl_esdhc
- Several cleanup for fsl_esdhc
- Add ADMA2 for sdhci
diff --git a/arch/arm/dts/fsl-lx2160a-rdb.dts b/arch/arm/dts/fsl-lx2160a-rdb.dts
index d787778..5fbdd90 100644
--- a/arch/arm/dts/fsl-lx2160a-rdb.dts
+++ b/arch/arm/dts/fsl-lx2160a-rdb.dts
@@ -80,6 +80,8 @@
 &esdhc1 {
 	status = "okay";
 	mmc-hs200-1_8v;
+	mmc-hs400-1_8v;
+	bus-width = <8>;
 };
 
 &fspi {
diff --git a/configs/lx2160ardb_tfa_SECURE_BOOT_defconfig b/configs/lx2160ardb_tfa_SECURE_BOOT_defconfig
index 5e30890..159ae9d 100644
--- a/configs/lx2160ardb_tfa_SECURE_BOOT_defconfig
+++ b/configs/lx2160ardb_tfa_SECURE_BOOT_defconfig
@@ -41,6 +41,7 @@
 CONFIG_I2C_SET_DEFAULT_BUS_NUM=y
 CONFIG_I2C_DEFAULT_BUS_NUMBER=0
 CONFIG_DM_MMC=y
+CONFIG_MMC_HS400_SUPPORT=y
 CONFIG_FSL_ESDHC=y
 CONFIG_MTD=y
 CONFIG_DM_SPI_FLASH=y
diff --git a/configs/lx2160ardb_tfa_defconfig b/configs/lx2160ardb_tfa_defconfig
index 7021223..8a4e6ef 100644
--- a/configs/lx2160ardb_tfa_defconfig
+++ b/configs/lx2160ardb_tfa_defconfig
@@ -48,6 +48,7 @@
 CONFIG_I2C_SET_DEFAULT_BUS_NUM=y
 CONFIG_I2C_DEFAULT_BUS_NUMBER=0
 CONFIG_DM_MMC=y
+CONFIG_MMC_HS400_SUPPORT=y
 CONFIG_FSL_ESDHC=y
 CONFIG_MTD=y
 CONFIG_DM_SPI_FLASH=y
diff --git a/configs/lx2160ardb_tfa_stmm_defconfig b/configs/lx2160ardb_tfa_stmm_defconfig
index b0dc3c0..bd9c1e9 100644
--- a/configs/lx2160ardb_tfa_stmm_defconfig
+++ b/configs/lx2160ardb_tfa_stmm_defconfig
@@ -49,6 +49,7 @@
 CONFIG_I2C_SET_DEFAULT_BUS_NUM=y
 CONFIG_I2C_DEFAULT_BUS_NUMBER=0
 CONFIG_DM_MMC=y
+CONFIG_MMC_HS400_SUPPORT=y
 CONFIG_SUPPORT_EMMC_RPMB=y
 CONFIG_FSL_ESDHC=y
 CONFIG_MTD=y
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 0c252e3..14d7913 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -46,6 +46,9 @@
 
 if MMC
 
+config MMC_SDHCI_ADMA_HELPERS
+	bool
+
 config MMC_SPI
 	bool "Support for SPI-based MMC controller"
 	depends on DM_MMC && DM_SPI
@@ -445,6 +448,7 @@
 config MMC_SDHCI_ADMA
 	bool "Support SDHCI ADMA2"
 	depends on MMC_SDHCI
+	select MMC_SDHCI_ADMA_HELPERS
 	help
 	  This enables support for the ADMA (Advanced DMA) defined
 	  in the SD Host Controller Standard Specification Version 3.00
@@ -452,6 +456,7 @@
 config SPL_MMC_SDHCI_ADMA
 	bool "Support SDHCI ADMA2 in SPL"
 	depends on MMC_SDHCI
+	select MMC_SDHCI_ADMA_HELPERS
 	help
 	  This enables support for the ADMA (Advanced DMA) defined
 	  in the SD Host Controller Standard Specification Version 3.00 in SPL.
@@ -750,6 +755,14 @@
 	  This selects support for the eSDHC (Enhanced Secure Digital Host
 	  Controller) found on numerous Freescale/NXP SoCs.
 
+config FSL_ESDHC_SUPPORT_ADMA2
+	bool "enable ADMA2 support"
+	depends on FSL_ESDHC
+	select MMC_SDHCI_ADMA_HELPERS
+	help
+	  This enables support for the ADMA2 transfer mode. If supported by the
+	  eSDHC it will allow 64bit DMA addresses.
+
 config FSL_ESDHC_33V_IO_RELIABILITY_WORKAROUND
 	bool "enable eSDHC workaround for 3.3v IO reliability issue"
 	depends on FSL_ESDHC && DM_MMC
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 22266ec..1c849cb 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -6,6 +6,7 @@
 obj-y += mmc.o
 obj-$(CONFIG_$(SPL_)DM_MMC) += mmc-uclass.o
 obj-$(CONFIG_$(SPL_)MMC_WRITE) += mmc_write.o
+obj-$(CONFIG_MMC_SDHCI_ADMA_HELPERS) += sdhci-adma.o
 
 ifndef CONFIG_$(SPL_)BLK
 obj-y += mmc_legacy.o
diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index de9fe01..642784e 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -26,6 +26,8 @@
 #include <dm/device_compat.h>
 #include <linux/bitops.h>
 #include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <sdhci.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -51,8 +53,9 @@
 	char    reserved1[8];	/* reserved */
 	uint    fevt;		/* Force event register */
 	uint    admaes;		/* ADMA error status register */
-	uint    adsaddr;	/* ADMA system address register */
-	char    reserved2[160];
+	uint    adsaddrl;	/* ADMA system address low register */
+	uint    adsaddrh;	/* ADMA system address high register */
+	char    reserved2[156];
 	uint    hostver;	/* Host controller version register */
 	char    reserved3[4];	/* reserved */
 	uint    dmaerraddr;	/* DMA error address register */
@@ -60,7 +63,14 @@
 	uint    dmaerrattr;	/* DMA error attribute register */
 	char    reserved5[4];	/* reserved */
 	uint    hostcapblt2;	/* Host controller capabilities register 2 */
-	char    reserved6[756];	/* reserved */
+	char	reserved6[8];	/* reserved */
+	uint	tbctl;		/* Tuning block control register */
+	char    reserved7[32];	/* reserved */
+	uint	sdclkctl;	/* SD clock control register */
+	uint	sdtimingctl;	/* SD timing control register */
+	char    reserved8[20];	/* reserved */
+	uint	dllcfg0;	/* DLL config 0 register */
+	char    reserved9[680];	/* reserved */
 	uint    esdhcctl;	/* eSDHC control register */
 };
 
@@ -91,6 +101,8 @@
 	struct mmc *mmc;
 #endif
 	struct udevice *dev;
+	struct sdhci_adma_desc *adma_desc_table;
+	dma_addr_t dma_addr;
 };
 
 /* Return the XFERTYP flags for a given command and data packet */
@@ -100,15 +112,15 @@
 
 	if (data) {
 		xfertyp |= XFERTYP_DPSEL;
-#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
-		xfertyp |= XFERTYP_DMAEN;
-#endif
+		if (!IS_ENABLED(CONFIG_SYS_FSL_ESDHC_USE_PIO) &&
+		    cmd->cmdidx != MMC_CMD_SEND_TUNING_BLOCK &&
+		    cmd->cmdidx != MMC_CMD_SEND_TUNING_BLOCK_HS200)
+			xfertyp |= XFERTYP_DMAEN;
 		if (data->blocks > 1) {
 			xfertyp |= XFERTYP_MSBSEL;
 			xfertyp |= XFERTYP_BCEN;
-#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111
-			xfertyp |= XFERTYP_AC12EN;
-#endif
+			if (IS_ENABLED(CONFIG_SYS_FSL_ERRATUM_ESDHC111))
+				xfertyp |= XFERTYP_AC12EN;
 		}
 
 		if (data->flags & MMC_DATA_READ)
@@ -132,7 +144,6 @@
 	return XFERTYP_CMD(cmd->cmdidx) | xfertyp;
 }
 
-#ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO
 /*
  * PIO Read/Write Mode reduce the performace as DMA is not used in this mode.
  */
@@ -195,66 +206,83 @@
 		}
 	}
 }
-#endif
 
-static int esdhc_setup_data(struct fsl_esdhc_priv *priv, struct mmc *mmc,
-			    struct mmc_data *data)
+static void esdhc_setup_watermark_level(struct fsl_esdhc_priv *priv,
+					struct mmc_data *data)
 {
-	int timeout;
 	struct fsl_esdhc *regs = priv->esdhc_regs;
-#if defined(CONFIG_FSL_LAYERSCAPE)
-	dma_addr_t addr;
-#endif
-	uint wml_value;
-
-	wml_value = data->blocksize/4;
+	uint wml_value = data->blocksize / 4;
 
 	if (data->flags & MMC_DATA_READ) {
 		if (wml_value > WML_RD_WML_MAX)
 			wml_value = WML_RD_WML_MAX_VAL;
 
 		esdhc_clrsetbits32(&regs->wml, WML_RD_WML_MASK, wml_value);
-#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
-#if defined(CONFIG_FSL_LAYERSCAPE)
-		addr = virt_to_phys((void *)(data->dest));
-		if (upper_32_bits(addr))
-			printf("Error found for upper 32 bits\n");
-		else
-			esdhc_write32(&regs->dsaddr, lower_32_bits(addr));
-#else
-		esdhc_write32(&regs->dsaddr, (u32)data->dest);
-#endif
-#endif
 	} else {
-#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
-		flush_dcache_range((ulong)data->src,
-				   (ulong)data->src+data->blocks
-					 *data->blocksize);
-#endif
 		if (wml_value > WML_WR_WML_MAX)
 			wml_value = WML_WR_WML_MAX_VAL;
 
-		if (!(esdhc_read32(&regs->prsstat) & PRSSTAT_WPSPL)) {
-			printf("Can not write to locked SD card.\n");
-			return -EINVAL;
-		}
-
 		esdhc_clrsetbits32(&regs->wml, WML_WR_WML_MASK,
-					wml_value << 16);
-#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
-#if defined(CONFIG_FSL_LAYERSCAPE)
-		addr = virt_to_phys((void *)(data->src));
-		if (upper_32_bits(addr))
-			printf("Error found for upper 32 bits\n");
-		else
-			esdhc_write32(&regs->dsaddr, lower_32_bits(addr));
-#else
-		esdhc_write32(&regs->dsaddr, (u32)data->src);
-#endif
-#endif
+				   wml_value << 16);
 	}
+}
+
+static void esdhc_setup_dma(struct fsl_esdhc_priv *priv, struct mmc_data *data)
+{
+	uint trans_bytes = data->blocksize * data->blocks;
+	struct fsl_esdhc *regs = priv->esdhc_regs;
+	phys_addr_t adma_addr;
+	void *buf;
+
+	if (data->flags & MMC_DATA_WRITE)
+		buf = (void *)data->src;
+	else
+		buf = data->dest;
+
+	priv->dma_addr = dma_map_single(buf, trans_bytes,
+					mmc_get_dma_dir(data));
+
+	if (IS_ENABLED(CONFIG_FSL_ESDHC_SUPPORT_ADMA2) &&
+	    priv->adma_desc_table) {
+		debug("Using ADMA2\n");
+		/* prefer ADMA2 if it is available */
+		sdhci_prepare_adma_table(priv->adma_desc_table, data,
+					 priv->dma_addr);
+
+		adma_addr = virt_to_phys(priv->adma_desc_table);
+		esdhc_write32(&regs->adsaddrl, lower_32_bits(adma_addr));
+		if (IS_ENABLED(CONFIG_DMA_ADDR_T_64BIT))
+			esdhc_write32(&regs->adsaddrh, upper_32_bits(adma_addr));
+		esdhc_clrsetbits32(&regs->proctl, PROCTL_DMAS_MASK,
+				   PROCTL_DMAS_ADMA2);
+	} else {
+		debug("Using SDMA\n");
+		if (upper_32_bits(priv->dma_addr))
+			printf("Cannot use 64 bit addresses with SDMA\n");
+		esdhc_write32(&regs->dsaddr, lower_32_bits(priv->dma_addr));
+		esdhc_clrsetbits32(&regs->proctl, PROCTL_DMAS_MASK,
+				   PROCTL_DMAS_SDMA);
+	}
 
 	esdhc_write32(&regs->blkattr, data->blocks << 16 | data->blocksize);
+}
+
+static int esdhc_setup_data(struct fsl_esdhc_priv *priv, struct mmc *mmc,
+			    struct mmc_data *data)
+{
+	int timeout;
+	bool is_write = data->flags & MMC_DATA_WRITE;
+	struct fsl_esdhc *regs = priv->esdhc_regs;
+
+	if (is_write && !(esdhc_read32(&regs->prsstat) & PRSSTAT_WPSPL)) {
+		printf("Can not write to locked SD card.\n");
+		return -EINVAL;
+	}
+
+	if (IS_ENABLED(CONFIG_SYS_FSL_ESDHC_USE_PIO))
+		esdhc_setup_watermark_level(priv, data);
+	else
+		esdhc_setup_dma(priv, data);
 
 	/* Calculate the timeout period for data transactions */
 	/*
@@ -287,41 +315,18 @@
 	if (timeout < 0)
 		timeout = 0;
 
-#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC_A001
-	if ((timeout == 4) || (timeout == 8) || (timeout == 12))
+	if (IS_ENABLED(CONFIG_SYS_FSL_ERRATUM_ESDHC_A001) &&
+	    (timeout == 4 || timeout == 8 || timeout == 12))
 		timeout++;
-#endif
 
-#ifdef ESDHCI_QUIRK_BROKEN_TIMEOUT_VALUE
-	timeout = 0xE;
-#endif
+	if (IS_ENABLED(ESDHCI_QUIRK_BROKEN_TIMEOUT_VALUE))
+		timeout = 0xE;
+
 	esdhc_clrsetbits32(&regs->sysctl, SYSCTL_TIMEOUT_MASK, timeout << 16);
 
 	return 0;
 }
 
-static void check_and_invalidate_dcache_range
-	(struct mmc_cmd *cmd,
-	 struct mmc_data *data) {
-	unsigned start = 0;
-	unsigned end = 0;
-	unsigned size = roundup(ARCH_DMA_MINALIGN,
-				data->blocks*data->blocksize);
-#if defined(CONFIG_FSL_LAYERSCAPE)
-	dma_addr_t addr;
-
-	addr = virt_to_phys((void *)(data->dest));
-	if (upper_32_bits(addr))
-		printf("Error found for upper 32 bits\n");
-	else
-		start = lower_32_bits(addr);
-#else
-	start = (unsigned)data->dest;
-#endif
-	end = start + size;
-	invalidate_dcache_range(start, end);
-}
-
 /*
  * Sends a command out on the bus.  Takes the mmc pointer,
  * a command pointer, and an optional data pointer.
@@ -336,10 +341,9 @@
 	struct fsl_esdhc *regs = priv->esdhc_regs;
 	unsigned long start;
 
-#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111
-	if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
+	if (IS_ENABLED(CONFIG_SYS_FSL_ERRATUM_ESDHC111) &&
+	    cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
 		return 0;
-#endif
 
 	esdhc_write32(&regs->irqstat, -1);
 
@@ -365,9 +369,6 @@
 		err = esdhc_setup_data(priv, mmc, data);
 		if(err)
 			return err;
-
-		if (data->flags & MMC_DATA_READ)
-			check_and_invalidate_dcache_range(cmd, data);
 	}
 
 	/* Figure out the transfer arguments */
@@ -380,6 +381,10 @@
 	esdhc_write32(&regs->cmdarg, cmd->cmdarg);
 	esdhc_write32(&regs->xfertyp, xfertyp);
 
+	if (cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK ||
+	    cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK_HS200)
+		flags = IRQSTAT_BRR;
+
 	/* Wait for the command to complete */
 	start = get_timer(0);
 	while (!(esdhc_read32(&regs->irqstat) & flags)) {
@@ -436,32 +441,37 @@
 
 	/* Wait until all of the blocks are transferred */
 	if (data) {
-#ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO
-		esdhc_pio_read_write(priv, data);
-#else
-		do {
-			irqstat = esdhc_read32(&regs->irqstat);
+		if (IS_ENABLED(CONFIG_SYS_FSL_ESDHC_USE_PIO)) {
+			esdhc_pio_read_write(priv, data);
+		} else {
+			flags = DATA_COMPLETE;
+			if (cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK ||
+			    cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK_HS200)
+				flags = IRQSTAT_BRR;
 
-			if (irqstat & IRQSTAT_DTOE) {
-				err = -ETIMEDOUT;
-				goto out;
-			}
+			do {
+				irqstat = esdhc_read32(&regs->irqstat);
 
-			if (irqstat & DATA_ERR) {
-				err = -ECOMM;
-				goto out;
-			}
-		} while ((irqstat & DATA_COMPLETE) != DATA_COMPLETE);
+				if (irqstat & IRQSTAT_DTOE) {
+					err = -ETIMEDOUT;
+					goto out;
+				}
 
-		/*
-		 * Need invalidate the dcache here again to avoid any
-		 * cache-fill during the DMA operations such as the
-		 * speculative pre-fetching etc.
-		 */
-		if (data->flags & MMC_DATA_READ) {
-			check_and_invalidate_dcache_range(cmd, data);
+				if (irqstat & DATA_ERR) {
+					err = -ECOMM;
+					goto out;
+				}
+			} while ((irqstat & flags) != flags);
+
+			/*
+			 * Need invalidate the dcache here again to avoid any
+			 * cache-fill during the DMA operations such as the
+			 * speculative pre-fetching etc.
+			 */
+			dma_unmap_single(priv->dma_addr,
+					 data->blocks * data->blocksize,
+					 mmc_get_dma_dir(data));
 		}
-#endif
 	}
 
 out:
@@ -505,6 +515,9 @@
 	while (sdhc_clk / (div * pre_div) > clock && div < 16)
 		div++;
 
+	mmc->clock = sdhc_clk / pre_div / div;
+	priv->clock = mmc->clock;
+
 	pre_div >>= 1;
 	div -= 1;
 
@@ -553,6 +566,86 @@
 		time_out--;
 		mdelay(1);
 	}
+}
+
+static void esdhc_flush_async_fifo(struct fsl_esdhc_priv *priv)
+{
+	struct fsl_esdhc *regs = priv->esdhc_regs;
+	u32 time_out;
+
+	esdhc_setbits32(&regs->esdhcctl, ESDHCCTL_FAF);
+
+	time_out = 20;
+	while (esdhc_read32(&regs->esdhcctl) & ESDHCCTL_FAF) {
+		if (time_out == 0) {
+			printf("fsl_esdhc: Flush asynchronous FIFO timeout.\n");
+			break;
+		}
+		time_out--;
+		mdelay(1);
+	}
+}
+
+static void esdhc_tuning_block_enable(struct fsl_esdhc_priv *priv,
+				      bool en)
+{
+	struct fsl_esdhc *regs = priv->esdhc_regs;
+
+	esdhc_clock_control(priv, false);
+	esdhc_flush_async_fifo(priv);
+	if (en)
+		esdhc_setbits32(&regs->tbctl, TBCTL_TB_EN);
+	else
+		esdhc_clrbits32(&regs->tbctl, TBCTL_TB_EN);
+	esdhc_clock_control(priv, true);
+}
+
+static void esdhc_exit_hs400(struct fsl_esdhc_priv *priv)
+{
+	struct fsl_esdhc *regs = priv->esdhc_regs;
+
+	esdhc_clrbits32(&regs->sdtimingctl, FLW_CTL_BG);
+	esdhc_clrbits32(&regs->sdclkctl, CMD_CLK_CTL);
+
+	esdhc_clock_control(priv, false);
+	esdhc_clrbits32(&regs->tbctl, HS400_MODE);
+	esdhc_clock_control(priv, true);
+
+	esdhc_clrbits32(&regs->dllcfg0, DLL_FREQ_SEL | DLL_ENABLE);
+	esdhc_clrbits32(&regs->tbctl, HS400_WNDW_ADJUST);
+
+	esdhc_tuning_block_enable(priv, false);
+}
+
+static void esdhc_set_timing(struct fsl_esdhc_priv *priv, enum bus_mode mode)
+{
+	struct fsl_esdhc *regs = priv->esdhc_regs;
+
+	/* Exit HS400 mode before setting any other mode */
+	if (esdhc_read32(&regs->tbctl) & HS400_MODE &&
+	    mode != MMC_HS_400)
+		esdhc_exit_hs400(priv);
+
+	esdhc_clock_control(priv, false);
+
+	if (mode == MMC_HS_200)
+		esdhc_clrsetbits32(&regs->autoc12err, UHSM_MASK,
+				   UHSM_SDR104_HS200);
+	if (mode == MMC_HS_400) {
+		esdhc_setbits32(&regs->tbctl, HS400_MODE);
+		esdhc_setbits32(&regs->sdclkctl, CMD_CLK_CTL);
+		esdhc_clock_control(priv, true);
+
+		if (priv->clock == 200000000)
+			esdhc_setbits32(&regs->dllcfg0, DLL_FREQ_SEL);
+
+		esdhc_setbits32(&regs->dllcfg0, DLL_ENABLE);
+		esdhc_setbits32(&regs->tbctl, HS400_WNDW_ADJUST);
+
+		esdhc_clock_control(priv, false);
+		esdhc_flush_async_fifo(priv);
+	}
+	esdhc_clock_control(priv, true);
 }
 
 static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
@@ -566,10 +659,16 @@
 		esdhc_clock_control(priv, true);
 	}
 
+	if (mmc->selected_mode == MMC_HS_400)
+		esdhc_tuning_block_enable(priv, true);
+
 	/* Set the clock speed */
 	if (priv->clock != mmc->clock)
 		set_sysctl(priv, mmc, mmc->clock);
 
+	/* Set timing */
+	esdhc_set_timing(priv, mmc->selected_mode);
+
 	/* Set the bus width */
 	esdhc_clrbits32(&regs->proctl, PROCTL_DTW_4 | PROCTL_DTW_8);
 
@@ -608,6 +707,9 @@
 			return -ETIMEDOUT;
 	}
 
+	/* Clean TBCTL[TB_EN] which is not able to be reset by reset all */
+	esdhc_clrbits32(&regs->tbctl, TBCTL_TB_EN);
+
 	esdhc_enable_cache_snooping(regs);
 
 	esdhc_setbits32(&regs->sysctl, SYSCTL_HCKEN | SYSCTL_IPGEN);
@@ -648,12 +750,10 @@
 	u32 caps;
 
 	caps = esdhc_read32(&regs->hostcapblt);
-#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC135
-	caps &= ~(HOSTCAPBLT_SRS | HOSTCAPBLT_VS18 | HOSTCAPBLT_VS30);
-#endif
-#ifdef CONFIG_SYS_FSL_MMC_HAS_CAPBLT_VS33
-	caps |= HOSTCAPBLT_VS33;
-#endif
+	if (IS_ENABLED(CONFIG_SYS_FSL_ERRATUM_ESDHC135))
+		caps &= ~(HOSTCAPBLT_SRS | HOSTCAPBLT_VS18 | HOSTCAPBLT_VS30);
+	if (IS_ENABLED(CONFIG_SYS_FSL_MMC_HAS_CAPBLT_VS33))
+		caps |= HOSTCAPBLT_VS33;
 	if (caps & HOSTCAPBLT_VS18)
 		cfg->voltages |= MMC_VDD_165_195;
 	if (caps & HOSTCAPBLT_VS30)
@@ -674,19 +774,18 @@
 #ifdef CONFIG_OF_LIBFDT
 __weak int esdhc_status_fixup(void *blob, const char *compat)
 {
-#ifdef CONFIG_FSL_ESDHC_PIN_MUX
-	if (!hwconfig("esdhc")) {
+	if (IS_ENABLED(CONFIG_FSL_ESDHC_PIN_MUX) && !hwconfig("esdhc")) {
 		do_fixup_by_compat(blob, compat, "status", "disabled",
 				sizeof("disabled"), 1);
 		return 1;
 	}
-#endif
+
 	return 0;
 }
 
-#ifdef CONFIG_FSL_ESDHC_33V_IO_RELIABILITY_WORKAROUND
-static int fsl_esdhc_get_cd(struct udevice *dev);
 
+#if CONFIG_IS_ENABLED(DM_MMC)
+static int fsl_esdhc_get_cd(struct udevice *dev);
 static void esdhc_disable_for_no_card(void *blob)
 {
 	struct udevice *dev;
@@ -705,6 +804,10 @@
 				 sizeof("disabled"), 1);
 	}
 }
+#else
+static void esdhc_disable_for_no_card(void *blob)
+{
+}
 #endif
 
 void fdt_fixup_esdhc(void *blob, struct bd_info *bd)
@@ -713,9 +816,10 @@
 
 	if (esdhc_status_fixup(blob, compat))
 		return;
-#ifdef CONFIG_FSL_ESDHC_33V_IO_RELIABILITY_WORKAROUND
-	esdhc_disable_for_no_card(blob);
-#endif
+
+	if (IS_ENABLED(CONFIG_FSL_ESDHC_33V_IO_RELIABILITY_WORKAROUND))
+		esdhc_disable_for_no_card(blob);
+
 	do_fixup_by_compat_u32(blob, compat, "clock-frequency",
 			       gd->arch.sdhc_clk, 1);
 }
@@ -797,10 +901,9 @@
 		printf("No max bus width provided. Assume 8-bit supported.\n");
 	}
 
-#ifdef CONFIG_ESDHC_DETECT_8_BIT_QUIRK
-	if (CONFIG_ESDHC_DETECT_8_BIT_QUIRK)
+	if (IS_ENABLED(CONFIG_ESDHC_DETECT_8_BIT_QUIRK))
 		mmc_cfg->host_caps &= ~MMC_MODE_8BIT;
-#endif
+
 	mmc_cfg->ops = &esdhc_ops;
 
 	fsl_esdhc_get_cfg_common(priv, mmc_cfg);
@@ -832,6 +935,7 @@
 	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
 	struct fsl_esdhc_plat *plat = dev_get_platdata(dev);
 	struct fsl_esdhc_priv *priv = dev_get_priv(dev);
+	u32 caps, hostver;
 	fdt_addr_t addr;
 	struct mmc *mmc;
 	int ret;
@@ -846,6 +950,21 @@
 #endif
 	priv->dev = dev;
 
+	if (IS_ENABLED(CONFIG_FSL_ESDHC_SUPPORT_ADMA2)) {
+		/*
+		 * Only newer eSDHC controllers can do ADMA2 if the ADMA flag
+		 * is set in the host capabilities register.
+		 */
+		caps = esdhc_read32(&priv->esdhc_regs->hostcapblt);
+		hostver = esdhc_read32(&priv->esdhc_regs->hostver);
+		if (caps & HOSTCAPBLT_DMAS &&
+		    HOSTVER_VENDOR(hostver) > VENDOR_V_22) {
+			priv->adma_desc_table = sdhci_adma_init();
+			if (!priv->adma_desc_table)
+				debug("Could not allocate ADMA tables, falling back to SDMA\n");
+		}
+	}
+
 	if (gd->arch.sdhc_per_clk) {
 		priv->sdhc_clk = gd->arch.sdhc_per_clk;
 		priv->is_sdhc_per_clk = true;
@@ -872,10 +991,10 @@
 	if (ret)
 		return ret;
 
-#ifdef CONFIG_FSL_ESDHC_33V_IO_RELIABILITY_WORKAROUND
-	if (!fsl_esdhc_get_cd(dev))
+	if (IS_ENABLED(CONFIG_FSL_ESDHC_33V_IO_RELIABILITY_WORKAROUND) &&
+	    !fsl_esdhc_get_cd(dev))
 		esdhc_setbits32(&priv->esdhc_regs->proctl, PROCTL_VOLT_SEL);
-#endif
+
 	return 0;
 }
 
@@ -907,6 +1026,64 @@
 	return esdhc_set_ios_common(priv, &plat->mmc);
 }
 
+static int fsl_esdhc_reinit(struct udevice *dev)
+{
+	struct fsl_esdhc_plat *plat = dev_get_platdata(dev);
+	struct fsl_esdhc_priv *priv = dev_get_priv(dev);
+
+	return esdhc_init_common(priv, &plat->mmc);
+}
+
+#ifdef MMC_SUPPORTS_TUNING
+static int fsl_esdhc_execute_tuning(struct udevice *dev, uint32_t opcode)
+{
+	struct fsl_esdhc_plat *plat = dev_get_platdata(dev);
+	struct fsl_esdhc_priv *priv = dev_get_priv(dev);
+	struct fsl_esdhc *regs = priv->esdhc_regs;
+	u32 val, irqstaten;
+	int i;
+
+	esdhc_tuning_block_enable(priv, true);
+	esdhc_setbits32(&regs->autoc12err, EXECUTE_TUNING);
+
+	irqstaten = esdhc_read32(&regs->irqstaten);
+	esdhc_write32(&regs->irqstaten, IRQSTATEN_BRR);
+
+	for (i = 0; i < MAX_TUNING_LOOP; i++) {
+		mmc_send_tuning(&plat->mmc, opcode, NULL);
+		mdelay(1);
+
+		val = esdhc_read32(&regs->autoc12err);
+		if (!(val & EXECUTE_TUNING)) {
+			if (val & SMPCLKSEL)
+				break;
+		}
+	}
+
+	esdhc_write32(&regs->irqstaten, irqstaten);
+
+	if (i != MAX_TUNING_LOOP) {
+		if (plat->mmc.hs400_tuning)
+			esdhc_setbits32(&regs->sdtimingctl, FLW_CTL_BG);
+		return 0;
+	}
+
+	printf("fsl_esdhc: tuning failed!\n");
+	esdhc_clrbits32(&regs->autoc12err, SMPCLKSEL);
+	esdhc_clrbits32(&regs->autoc12err, EXECUTE_TUNING);
+	esdhc_tuning_block_enable(priv, false);
+	return -ETIMEDOUT;
+}
+#endif
+
+int fsl_esdhc_hs400_prepare_ddr(struct udevice *dev)
+{
+	struct fsl_esdhc_priv *priv = dev_get_priv(dev);
+
+	esdhc_tuning_block_enable(priv, false);
+	return 0;
+}
+
 static const struct dm_mmc_ops fsl_esdhc_ops = {
 	.get_cd		= fsl_esdhc_get_cd,
 	.send_cmd	= fsl_esdhc_send_cmd,
@@ -914,6 +1091,8 @@
 #ifdef MMC_SUPPORTS_TUNING
 	.execute_tuning = fsl_esdhc_execute_tuning,
 #endif
+	.reinit = fsl_esdhc_reinit,
+	.hs400_prepare_ddr = fsl_esdhc_hs400_prepare_ddr,
 };
 
 static const struct udevice_id fsl_esdhc_ids[] = {
diff --git a/drivers/mmc/fsl_esdhc_imx.c b/drivers/mmc/fsl_esdhc_imx.c
index 0c866b1..1c015ab 100644
--- a/drivers/mmc/fsl_esdhc_imx.c
+++ b/drivers/mmc/fsl_esdhc_imx.c
@@ -462,13 +462,6 @@
 	while (esdhc_read32(&regs->prsstat) & PRSSTAT_DLA)
 		;
 
-	/* Wait at least 8 SD clock cycles before the next command */
-	/*
-	 * Note: This is way more than 8 cycles, but 1ms seems to
-	 * resolve timing issues with some cards
-	 */
-	udelay(1000);
-
 	/* Set up for a data transfer if we have one */
 	if (data) {
 		err = esdhc_setup_data(priv, mmc, data);
@@ -729,7 +722,7 @@
 	u32 val;
 
 	if (priv->clock > ESDHC_STROBE_DLL_CLK_FREQ) {
-		writel(ESDHC_STROBE_DLL_CTRL_RESET, &regs->strobe_dllctrl);
+		esdhc_write32(&regs->strobe_dllctrl, ESDHC_STROBE_DLL_CTRL_RESET);
 
 		/*
 		 * enable strobe dll ctrl and adjust the delay target
@@ -738,10 +731,10 @@
 		val = ESDHC_STROBE_DLL_CTRL_ENABLE |
 			(priv->strobe_dll_delay_target <<
 			 ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT);
-		writel(val, &regs->strobe_dllctrl);
+		esdhc_write32(&regs->strobe_dllctrl, val);
 		/* wait 1us to make sure strobe dll status register stable */
 		mdelay(1);
-		val = readl(&regs->strobe_dllstat);
+		val = esdhc_read32(&regs->strobe_dllstat);
 		if (!(val & ESDHC_STROBE_DLL_STS_REF_LOCK))
 			pr_warn("HS400 strobe DLL status REF not lock!\n");
 		if (!(val & ESDHC_STROBE_DLL_STS_SLV_LOCK))
@@ -755,18 +748,18 @@
 	struct fsl_esdhc *regs = priv->esdhc_regs;
 	u32 mixctrl;
 
-	mixctrl = readl(&regs->mixctrl);
+	mixctrl = esdhc_read32(&regs->mixctrl);
 	mixctrl &= ~(MIX_CTRL_DDREN | MIX_CTRL_HS400_EN);
 
 	switch (mmc->selected_mode) {
 	case MMC_LEGACY:
 		esdhc_reset_tuning(mmc);
-		writel(mixctrl, &regs->mixctrl);
+		esdhc_write32(&regs->mixctrl, mixctrl);
 		break;
 	case MMC_HS_400:
 	case MMC_HS_400_ES:
 		mixctrl |= MIX_CTRL_DDREN | MIX_CTRL_HS400_EN;
-		writel(mixctrl, &regs->mixctrl);
+		esdhc_write32(&regs->mixctrl, mixctrl);
 		esdhc_set_strobe_dll(mmc);
 		break;
 	case MMC_HS:
@@ -777,12 +770,12 @@
 	case UHS_SDR25:
 	case UHS_SDR50:
 	case UHS_SDR104:
-		writel(mixctrl, &regs->mixctrl);
+		esdhc_write32(&regs->mixctrl, mixctrl);
 		break;
 	case UHS_DDR50:
 	case MMC_DDR_52:
 		mixctrl |= MIX_CTRL_DDREN;
-		writel(mixctrl, &regs->mixctrl);
+		esdhc_write32(&regs->mixctrl, mixctrl);
 		break;
 	default:
 		printf("Not supported %d\n", mmc->selected_mode);
@@ -862,8 +855,8 @@
 	struct fsl_esdhc_priv *priv = dev_get_priv(dev);
 	struct fsl_esdhc *regs = priv->esdhc_regs;
 	struct mmc *mmc = &plat->mmc;
-	u32 irqstaten = readl(&regs->irqstaten);
-	u32 irqsigen = readl(&regs->irqsigen);
+	u32 irqstaten = esdhc_read32(&regs->irqstaten);
+	u32 irqsigen = esdhc_read32(&regs->irqsigen);
 	int i, ret = -ETIMEDOUT;
 	u32 val, mixctrl;
 
@@ -873,25 +866,25 @@
 
 	/* This is readw/writew SDHCI_HOST_CONTROL2 when tuning */
 	if (priv->flags & ESDHC_FLAG_STD_TUNING) {
-		val = readl(&regs->autoc12err);
-		mixctrl = readl(&regs->mixctrl);
+		val = esdhc_read32(&regs->autoc12err);
+		mixctrl = esdhc_read32(&regs->mixctrl);
 		val &= ~MIX_CTRL_SMPCLK_SEL;
 		mixctrl &= ~(MIX_CTRL_FBCLK_SEL | MIX_CTRL_AUTO_TUNE_EN);
 
 		val |= MIX_CTRL_EXE_TUNE;
 		mixctrl |= MIX_CTRL_FBCLK_SEL | MIX_CTRL_AUTO_TUNE_EN;
 
-		writel(val, &regs->autoc12err);
-		writel(mixctrl, &regs->mixctrl);
+		esdhc_write32(&regs->autoc12err, val);
+		esdhc_write32(&regs->mixctrl, mixctrl);
 	}
 
 	/* sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE); */
-	mixctrl = readl(&regs->mixctrl);
+	mixctrl = esdhc_read32(&regs->mixctrl);
 	mixctrl = MIX_CTRL_DTDSEL_READ | (mixctrl & ~MIX_CTRL_SDHCI_MASK);
-	writel(mixctrl, &regs->mixctrl);
+	esdhc_write32(&regs->mixctrl, mixctrl);
 
-	writel(IRQSTATEN_BRR, &regs->irqstaten);
-	writel(IRQSTATEN_BRR, &regs->irqsigen);
+	esdhc_write32(&regs->irqstaten, IRQSTATEN_BRR);
+	esdhc_write32(&regs->irqsigen, IRQSTATEN_BRR);
 
 	/*
 	 * Issue opcode repeatedly till Execute Tuning is set to 0 or the number
@@ -902,22 +895,22 @@
 
 		if (opcode == MMC_CMD_SEND_TUNING_BLOCK_HS200) {
 			if (mmc->bus_width == 8)
-				writel(0x7080, &regs->blkattr);
+				esdhc_write32(&regs->blkattr, 0x7080);
 			else if (mmc->bus_width == 4)
-				writel(0x7040, &regs->blkattr);
+				esdhc_write32(&regs->blkattr, 0x7040);
 		} else {
-			writel(0x7040, &regs->blkattr);
+			esdhc_write32(&regs->blkattr, 0x7040);
 		}
 
 		/* sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE) */
-		val = readl(&regs->mixctrl);
+		val = esdhc_read32(&regs->mixctrl);
 		val = MIX_CTRL_DTDSEL_READ | (val & ~MIX_CTRL_SDHCI_MASK);
-		writel(val, &regs->mixctrl);
+		esdhc_write32(&regs->mixctrl, val);
 
 		/* We are using STD tuning, no need to check return value */
 		mmc_send_tuning(mmc, opcode, NULL);
 
-		ctrl = readl(&regs->autoc12err);
+		ctrl = esdhc_read32(&regs->autoc12err);
 		if ((!(ctrl & MIX_CTRL_EXE_TUNE)) &&
 		    (ctrl & MIX_CTRL_SMPCLK_SEL)) {
 			ret = 0;
@@ -925,8 +918,8 @@
 		}
 	}
 
-	writel(irqstaten, &regs->irqstaten);
-	writel(irqsigen, &regs->irqsigen);
+	esdhc_write32(&regs->irqstaten, irqstaten);
+	esdhc_write32(&regs->irqsigen, irqsigen);
 
 	esdhc_stop_tuning(mmc);
 
@@ -1179,7 +1172,7 @@
 	if (priv->vs18_enable)
 		esdhc_setbits32(&regs->vendorspec, ESDHC_VENDORSPEC_VSELECT);
 
-	writel(SDHCI_IRQ_EN_BITS, &regs->irqstaten);
+	esdhc_write32(&regs->irqstaten, SDHCI_IRQ_EN_BITS);
 	cfg = &plat->cfg;
 #ifndef CONFIG_DM_MMC
 	memset(cfg, '\0', sizeof(*cfg));
@@ -1260,10 +1253,10 @@
 
 	cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
 
-	writel(0, &regs->dllctrl);
+	esdhc_write32(&regs->dllctrl, 0);
 	if (priv->flags & ESDHC_FLAG_USDHC) {
 		if (priv->flags & ESDHC_FLAG_STD_TUNING) {
-			u32 val = readl(&regs->tuning_ctrl);
+			u32 val = esdhc_read32(&regs->tuning_ctrl);
 
 			val |= ESDHC_STD_TUNING_EN;
 			val &= ~ESDHC_TUNING_START_TAP_MASK;
@@ -1282,7 +1275,7 @@
 			 * after the whole tuning procedure always can't get any response.
 			 */
 			val |= ESDHC_TUNING_CMD_CRC_CHECK_DISABLE;
-			writel(val, &regs->tuning_ctrl);
+			esdhc_write32(&regs->tuning_ctrl, val);
 		}
 	}
 
@@ -1648,9 +1641,9 @@
 	struct fsl_esdhc *regs = priv->esdhc_regs;
 	u32 m;
 
-	m = readl(&regs->mixctrl);
+	m = esdhc_read32(&regs->mixctrl);
 	m |= MIX_CTRL_HS400_ES;
-	writel(m, &regs->mixctrl);
+	esdhc_write32(&regs->mixctrl, m);
 
 	return 0;
 }
diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index 90690c8..ec59bcd 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -142,6 +142,21 @@
 }
 #endif
 
+int dm_mmc_hs400_prepare_ddr(struct udevice *dev)
+{
+	struct dm_mmc_ops *ops = mmc_get_ops(dev);
+
+	if (ops->hs400_prepare_ddr)
+		return ops->hs400_prepare_ddr(dev);
+
+	return 0;
+}
+
+int mmc_hs400_prepare_ddr(struct mmc *mmc)
+{
+	return dm_mmc_hs400_prepare_ddr(mmc->dev);
+}
+
 int dm_mmc_host_power_cycle(struct udevice *dev)
 {
 	struct dm_mmc_ops *ops = mmc_get_ops(dev);
@@ -171,6 +186,21 @@
 	return dm_mmc_deferred_probe(mmc->dev);
 }
 
+int dm_mmc_reinit(struct udevice *dev)
+{
+	struct dm_mmc_ops *ops = mmc_get_ops(dev);
+
+	if (ops->reinit)
+		return ops->reinit(dev);
+
+	return 0;
+}
+
+int mmc_reinit(struct mmc *mmc)
+{
+	return dm_mmc_reinit(mmc->dev);
+}
+
 int mmc_of_parse(struct udevice *dev, struct mmc_config *cfg)
 {
 	int val;
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 11ce110..c46fa4e 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -805,8 +805,10 @@
 	 * capable of polling by using mmc_wait_dat0, then rely on waiting the
 	 * stated timeout to be sufficient.
 	 */
-	if (ret == -ENOSYS && !send_status)
+	if (ret == -ENOSYS && !send_status) {
 		mdelay(timeout_ms);
+		return 0;
+	}
 
 	/* Finally wait until the card is ready or indicates a failure
 	 * to switch. It doesn't hurt to use CMD13 here even if send_status
@@ -1982,7 +1984,9 @@
 	mmc_set_clock(mmc, mmc->tran_speed, false);
 
 	/* execute tuning if needed */
+	mmc->hs400_tuning = 1;
 	err = mmc_execute_tuning(mmc, MMC_CMD_SEND_TUNING_BLOCK_HS200);
+	mmc->hs400_tuning = 0;
 	if (err) {
 		debug("tuning failed\n");
 		return err;
@@ -1991,6 +1995,10 @@
 	/* Set back to HS */
 	mmc_set_card_speed(mmc, MMC_HS, true);
 
+	err = mmc_hs400_prepare_ddr(mmc);
+	if (err)
+		return err;
+
 	err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
 			 EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_FLAG);
 	if (err)
@@ -2816,13 +2824,17 @@
 		return err;
 
 #if CONFIG_IS_ENABLED(DM_MMC)
-	/* The device has already been probed ready for use */
+	/*
+	 * Re-initialization is needed to clear old configuration for
+	 * mmc rescan.
+	 */
+	err = mmc_reinit(mmc);
 #else
 	/* made sure it's not NULL earlier */
 	err = mmc->cfg->ops->init(mmc);
+#endif
 	if (err)
 		return err;
-#endif
 	mmc->ddr_mode = 0;
 
 retry:
diff --git a/drivers/mmc/sdhci-adma.c b/drivers/mmc/sdhci-adma.c
new file mode 100644
index 0000000..2ec057f
--- /dev/null
+++ b/drivers/mmc/sdhci-adma.c
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * SDHCI ADMA2 helper functions.
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <sdhci.h>
+#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)
+{
+	u8 attr;
+
+	attr = ADMA_DESC_ATTR_VALID | ADMA_DESC_TRANSFER_DATA;
+	if (end)
+		attr |= ADMA_DESC_ATTR_END;
+
+	desc->attr = attr;
+	desc->len = len;
+	desc->reserved = 0;
+	desc->addr_lo = lower_32_bits(addr);
+#ifdef CONFIG_DMA_ADDR_T_64BIT
+	desc->addr_hi = upper_32_bits(addr);
+#endif
+}
+
+/**
+ * sdhci_prepare_adma_table() - Populate the ADMA table
+ *
+ * @table:	Pointer to the ADMA table
+ * @data:	Pointer to MMC data
+ * @addr:	DMA address to write to or read from
+ *
+ * Fill the ADMA table according to the MMC data to read from or write to the
+ * given DMA address.
+ * 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)
+{
+	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;
+
+	while (--i) {
+		sdhci_adma_desc(desc, addr, ADMA_MAX_LEN, false);
+		addr += ADMA_MAX_LEN;
+		trans_bytes -= ADMA_MAX_LEN;
+		desc++;
+	}
+
+	sdhci_adma_desc(desc, addr, trans_bytes, true);
+
+	flush_cache((dma_addr_t)table,
+		    ROUND(desc_count * sizeof(struct sdhci_adma_desc),
+			  ARCH_DMA_MINALIGN));
+}
+
+/**
+ * sdhci_adma_init() - initialize the ADMA descriptor table
+ *
+ * @return pointer to the allocated descriptor table or NULL in case of an
+ * error.
+ */
+struct sdhci_adma_desc *sdhci_adma_init(void)
+{
+	return memalign(ARCH_DMA_MINALIGN, ADMA_TABLE_SZ);
+}
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 7673219..d549a26 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -69,57 +69,6 @@
 	}
 }
 
-#if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA)
-static void sdhci_adma_desc(struct sdhci_host *host, dma_addr_t dma_addr,
-			    u16 len, bool end)
-{
-	struct sdhci_adma_desc *desc;
-	u8 attr;
-
-	desc = &host->adma_desc_table[host->desc_slot];
-
-	attr = ADMA_DESC_ATTR_VALID | ADMA_DESC_TRANSFER_DATA;
-	if (!end)
-		host->desc_slot++;
-	else
-		attr |= ADMA_DESC_ATTR_END;
-
-	desc->attr = attr;
-	desc->len = len;
-	desc->reserved = 0;
-	desc->addr_lo = lower_32_bits(dma_addr);
-#ifdef CONFIG_DMA_ADDR_T_64BIT
-	desc->addr_hi = upper_32_bits(dma_addr);
-#endif
-}
-
-static void sdhci_prepare_adma_table(struct sdhci_host *host,
-				     struct mmc_data *data)
-{
-	uint trans_bytes = data->blocksize * data->blocks;
-	uint desc_count = DIV_ROUND_UP(trans_bytes, ADMA_MAX_LEN);
-	int i = desc_count;
-	dma_addr_t dma_addr = host->start_addr;
-
-	host->desc_slot = 0;
-
-	while (--i) {
-		sdhci_adma_desc(host, dma_addr, ADMA_MAX_LEN, false);
-		dma_addr += ADMA_MAX_LEN;
-		trans_bytes -= ADMA_MAX_LEN;
-	}
-
-	sdhci_adma_desc(host, dma_addr, trans_bytes, true);
-
-	flush_cache((dma_addr_t)host->adma_desc_table,
-		    ROUND(desc_count * sizeof(struct sdhci_adma_desc),
-			  ARCH_DMA_MINALIGN));
-}
-#elif defined(CONFIG_MMC_SDHCI_SDMA)
-static void sdhci_prepare_adma_table(struct sdhci_host *host,
-				     struct mmc_data *data)
-{}
-#endif
 #if (defined(CONFIG_MMC_SDHCI_SDMA) || CONFIG_IS_ENABLED(MMC_SDHCI_ADMA))
 static void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data,
 			      int *is_aligned, int trans_bytes)
@@ -156,8 +105,11 @@
 	if (host->flags & USE_SDMA) {
 		sdhci_writel(host, phys_to_bus((ulong)host->start_addr),
 				SDHCI_DMA_ADDRESS);
-	} else if (host->flags & (USE_ADMA | USE_ADMA64)) {
-		sdhci_prepare_adma_table(host, data);
+	}
+#if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA)
+	else if (host->flags & (USE_ADMA | USE_ADMA64)) {
+		sdhci_prepare_adma_table(host->adma_desc_table, data,
+					 host->start_addr);
 
 		sdhci_writel(host, lower_32_bits(host->adma_addr),
 			     SDHCI_ADMA_ADDRESS);
@@ -165,6 +117,7 @@
 			sdhci_writel(host, upper_32_bits(host->adma_addr),
 				     SDHCI_ADMA_ADDRESS_HI);
 	}
+#endif
 }
 #else
 static void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data,
@@ -770,9 +723,9 @@
 		       __func__);
 		return -EINVAL;
 	}
-	host->adma_desc_table = memalign(ARCH_DMA_MINALIGN, ADMA_TABLE_SZ);
-
+	host->adma_desc_table = sdhci_adma_init();
 	host->adma_addr = (dma_addr_t)host->adma_desc_table;
+
 #ifdef CONFIG_DMA_ADDR_T_64BIT
 	host->flags |= USE_ADMA64;
 #else
diff --git a/drivers/mmc/sh_sdhi.c b/drivers/mmc/sh_sdhi.c
index 315f95c..29f83b6 100644
--- a/drivers/mmc/sh_sdhi.c
+++ b/drivers/mmc/sh_sdhi.c
@@ -784,8 +784,7 @@
 
 	return ret;
 error:
-	if (host)
-		free(host);
+	free(host);
 	return ret;
 }
 
diff --git a/include/fsl_esdhc.h b/include/fsl_esdhc.h
index 7f8f8ed..e6f1c75 100644
--- a/include/fsl_esdhc.h
+++ b/include/fsl_esdhc.h
@@ -74,8 +74,10 @@
 #define IRQSTATEN_TC		(0x00000002)
 #define IRQSTATEN_CC		(0x00000001)
 
+/* eSDHC control register */
 #define ESDHCCTL		0x0002e40c
 #define ESDHCCTL_PCS		(0x00080000)
+#define ESDHCCTL_FAF		(0x00040000)
 
 #define PRSSTAT			0x0002e024
 #define PRSSTAT_DAT0		(0x01000000)
@@ -95,6 +97,10 @@
 #define PROCTL_DTW_4		0x00000002
 #define PROCTL_DTW_8		0x00000004
 #define PROCTL_D3CD		0x00000008
+#define PROCTL_DMAS_MASK	0x00000300
+#define PROCTL_DMAS_SDMA	0x00000000
+#define PROCTL_DMAS_ADMA1	0x00000100
+#define PROCTL_DMAS_ADMA2	0x00000300
 #define PROCTL_VOLT_SEL		0x00000400
 
 #define CMDARG			0x0002e008
@@ -154,6 +160,12 @@
 #define BLKATTR_SIZE(x)	(x & 0x1fff)
 #define MAX_BLK_CNT	0x7fff	/* so malloc will have enough room with 32M */
 
+/* Auto CMD error status register / system control 2 register */
+#define EXECUTE_TUNING		0x00400000
+#define SMPCLKSEL		0x00800000
+#define UHSM_MASK		0x00070000
+#define UHSM_SDR104_HS200	0x00030000
+
 /* Host controller capabilities register */
 #define HOSTCAPBLT_VS18		0x04000000
 #define HOSTCAPBLT_VS30		0x02000000
@@ -162,6 +174,33 @@
 #define HOSTCAPBLT_DMAS		0x00400000
 #define HOSTCAPBLT_HSS		0x00200000
 
+/* Tuning block control register */
+#define TBCTL_TB_EN		0x00000004
+#define HS400_MODE		0x00000010
+#define HS400_WNDW_ADJUST	0x00000040
+
+/* SD clock control register */
+#define CMD_CLK_CTL		0x00008000
+
+/* SD timing control register */
+#define FLW_CTL_BG		0x00008000
+
+/* DLL config 0 register */
+#define DLL_ENABLE		0x80000000
+#define DLL_FREQ_SEL		0x08000000
+
+#define MAX_TUNING_LOOP		40
+
+#define HOSTVER_VENDOR(x)	(((x) >> 8) & 0xff)
+#define VENDOR_V_10		0x00
+#define VENDOR_V_20		0x10
+#define VENDOR_V_21		0x11
+#define VENDOR_V_22		0x12
+#define VENDOR_V_23		0x13
+#define VENDOR_V_30		0x20
+#define VENDOR_V_31		0x21
+#define VENDOR_V_32		0x22
+
 struct fsl_esdhc_cfg {
 	phys_addr_t esdhc_base;
 	u32	sdhc_clk;
@@ -203,10 +242,6 @@
 int fsl_esdhc_mmc_init(struct bd_info *bis);
 int fsl_esdhc_initialize(struct bd_info *bis, struct fsl_esdhc_cfg *cfg);
 void fdt_fixup_esdhc(void *blob, struct bd_info *bd);
-#ifdef MMC_SUPPORTS_TUNING
-static inline int fsl_esdhc_execute_tuning(struct udevice *dev,
-					   uint32_t opcode) {return 0; }
-#endif
 #else
 static inline int fsl_esdhc_mmc_init(struct bd_info *bis) { return -ENOSYS; }
 static inline void fdt_fixup_esdhc(void *blob, struct bd_info *bd) {}
diff --git a/include/mmc.h b/include/mmc.h
index 75bcaaf..ac7b54f 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -422,6 +422,14 @@
 	 */
 	int (*deferred_probe)(struct udevice *dev);
 	/**
+	 * reinit() - Re-initialization to clear old configuration for
+	 * mmc rescan.
+	 *
+	 * @dev:	Device to reinit
+	 * @return 0 if Ok, -ve if error
+	 */
+	int (*reinit)(struct udevice *dev);
+	/**
 	 * send_cmd() - Send a command to the MMC device
 	 *
 	 * @dev:	Device to receive the command
@@ -505,6 +513,14 @@
 	 * @return maximum number of blocks for this transfer
 	 */
 	int (*get_b_max)(struct udevice *dev, void *dst, lbaint_t blkcnt);
+
+	/**
+	 * hs400_prepare_ddr - prepare to switch to DDR mode
+	 *
+	 * @dev:	Device to check
+	 * @return 0 if success, -ve on error
+	 */
+	int (*hs400_prepare_ddr)(struct udevice *dev);
 };
 
 #define mmc_get_ops(dev)        ((struct dm_mmc_ops *)(dev)->driver->ops)
@@ -518,6 +534,7 @@
 int dm_mmc_wait_dat0(struct udevice *dev, int state, int timeout_us);
 int dm_mmc_host_power_cycle(struct udevice *dev);
 int dm_mmc_deferred_probe(struct udevice *dev);
+int dm_mmc_reinit(struct udevice *dev);
 int dm_mmc_get_b_max(struct udevice *dev, void *dst, lbaint_t blkcnt);
 
 /* Transition functions for compatibility */
@@ -529,8 +546,9 @@
 int mmc_set_enhanced_strobe(struct mmc *mmc);
 int mmc_host_power_cycle(struct mmc *mmc);
 int mmc_deferred_probe(struct mmc *mmc);
+int mmc_reinit(struct mmc *mmc);
 int mmc_get_b_max(struct mmc *mmc, void *dst, lbaint_t blkcnt);
-
+int mmc_hs400_prepare_ddr(struct mmc *mmc);
 #else
 struct mmc_ops {
 	int (*send_cmd)(struct mmc *mmc,
@@ -542,6 +560,11 @@
 	int (*host_power_cycle)(struct mmc *mmc);
 	int (*get_b_max)(struct mmc *mmc, void *dst, lbaint_t blkcnt);
 };
+
+static inline int mmc_hs400_prepare_ddr(struct mmc *mmc)
+{
+	return 0;
+}
 #endif
 
 struct mmc_config {
@@ -697,6 +720,7 @@
 				  * accessing the boot partitions
 				  */
 	u32 quirks;
+	u8 hs400_tuning;
 };
 
 struct mmc_hwpart_conf {
diff --git a/include/sdhci.h b/include/sdhci.h
index 94fc3ed..f69d5f8 100644
--- a/include/sdhci.h
+++ b/include/sdhci.h
@@ -271,7 +271,6 @@
 	int	(*deferred_probe)(struct sdhci_host *host);
 };
 
-#if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA)
 #define ADMA_MAX_LEN	65532
 #ifdef CONFIG_DMA_ADDR_T_64BIT
 #define ADMA_DESC_LEN	16
@@ -302,7 +301,7 @@
 	u32 addr_hi;
 #endif
 } __packed;
-#endif
+
 struct sdhci_host {
 	const char *name;
 	void *ioaddr;
@@ -334,7 +333,6 @@
 	dma_addr_t adma_addr;
 #if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA)
 	struct sdhci_adma_desc *adma_desc_table;
-	uint desc_slot;
 #endif
 };
 
@@ -496,4 +494,8 @@
 #else
 #endif
 
+struct sdhci_adma_desc *sdhci_adma_init(void);
+void sdhci_prepare_adma_table(struct sdhci_adma_desc *table,
+			      struct mmc_data *data, dma_addr_t addr);
+
 #endif /* __SDHCI_HW_H */