Merge tag 'mmc-2021-2-19' of https://gitlab.denx.de/u-boot/custodians/u-boot-mmc

- mmc_spi improvement
- added mmc-pwrseq to remove duplicated code
- fix response timeout after switch command
- sdhci: skip cache invalidation if DMA is not used
diff --git a/arch/arm/mach-meson/Kconfig b/arch/arm/mach-meson/Kconfig
index 513a33d..6cba2c4 100644
--- a/arch/arm/mach-meson/Kconfig
+++ b/arch/arm/mach-meson/Kconfig
@@ -9,6 +9,7 @@
 	select SYSCON
 	select REGMAP
 	select PWRSEQ
+	select MMC_PWRSEQ
 	select BOARD_LATE_INIT
 	imply CMD_DM
 
diff --git a/cmd/mmc.c b/cmd/mmc.c
index 1529a3e..cb6b59f 100644
--- a/cmd/mmc.c
+++ b/cmd/mmc.c
@@ -1017,13 +1017,13 @@
 	"  Power cycling is required to initialize partitions after set to complete.\n"
 #endif
 #ifdef CONFIG_SUPPORT_EMMC_BOOT
-	"mmc bootbus dev boot_bus_width reset_boot_bus_width boot_mode\n"
+	"mmc bootbus <dev> <boot_bus_width> <reset_boot_bus_width> <boot_mode>\n"
 	" - Set the BOOT_BUS_WIDTH field of the specified device\n"
 	"mmc bootpart-resize <dev> <boot part size MB> <RPMB part size MB>\n"
 	" - Change sizes of boot and RPMB partitions of specified device\n"
-	"mmc partconf dev [boot_ack boot_partition partition_access]\n"
+	"mmc partconf <dev> [boot_ack boot_partition partition_access]\n"
 	" - Show or change the bits of the PARTITION_CONFIG field of the specified device\n"
-	"mmc rst-function dev value\n"
+	"mmc rst-function <dev> <value>\n"
 	" - Change the RST_n_FUNCTION field of the specified device\n"
 	"   WARNING: This is a write-once field and 0 / 1 / 2 are the only valid values.\n"
 #endif
diff --git a/configs/chromebit_mickey_defconfig b/configs/chromebit_mickey_defconfig
index ba1215b..c09b63b 100644
--- a/configs/chromebit_mickey_defconfig
+++ b/configs/chromebit_mickey_defconfig
@@ -63,6 +63,7 @@
 CONFIG_CROS_EC=y
 CONFIG_CROS_EC_SPI=y
 CONFIG_PWRSEQ=y
+CONFIG_MMC_PWRSEQ=y
 # CONFIG_SPL_DM_MMC is not set
 CONFIG_MMC_DW=y
 CONFIG_MMC_DW_ROCKCHIP=y
diff --git a/configs/chromebook_bob_defconfig b/configs/chromebook_bob_defconfig
index 73635f0..a846b64 100644
--- a/configs/chromebook_bob_defconfig
+++ b/configs/chromebook_bob_defconfig
@@ -55,6 +55,7 @@
 CONFIG_CROS_EC=y
 CONFIG_CROS_EC_SPI=y
 CONFIG_PWRSEQ=y
+CONFIG_MMC_PWRSEQ=y
 CONFIG_MMC_DW=y
 CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_MMC_SDHCI=y
diff --git a/configs/chromebook_jerry_defconfig b/configs/chromebook_jerry_defconfig
index dada557..692b630 100644
--- a/configs/chromebook_jerry_defconfig
+++ b/configs/chromebook_jerry_defconfig
@@ -65,6 +65,7 @@
 CONFIG_CROS_EC=y
 CONFIG_CROS_EC_SPI=y
 CONFIG_PWRSEQ=y
+CONFIG_MMC_PWRSEQ=y
 # CONFIG_SPL_DM_MMC is not set
 CONFIG_MMC_DW=y
 CONFIG_MMC_DW_ROCKCHIP=y
diff --git a/configs/chromebook_minnie_defconfig b/configs/chromebook_minnie_defconfig
index 985ca94..ae55842 100644
--- a/configs/chromebook_minnie_defconfig
+++ b/configs/chromebook_minnie_defconfig
@@ -65,6 +65,7 @@
 CONFIG_CROS_EC=y
 CONFIG_CROS_EC_SPI=y
 CONFIG_PWRSEQ=y
+CONFIG_MMC_PWRSEQ=y
 # CONFIG_SPL_DM_MMC is not set
 CONFIG_MMC_DW=y
 CONFIG_MMC_DW_ROCKCHIP=y
diff --git a/configs/chromebook_speedy_defconfig b/configs/chromebook_speedy_defconfig
index e3d4c30..4b460ee 100644
--- a/configs/chromebook_speedy_defconfig
+++ b/configs/chromebook_speedy_defconfig
@@ -64,6 +64,7 @@
 CONFIG_CROS_EC=y
 CONFIG_CROS_EC_SPI=y
 CONFIG_PWRSEQ=y
+CONFIG_MMC_PWRSEQ=y
 # CONFIG_SPL_DM_MMC is not set
 CONFIG_MMC_DW=y
 CONFIG_MMC_DW_ROCKCHIP=y
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index f8ea921..f8ca52e 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -18,6 +18,13 @@
 	help
 	  Enable write access to MMC and SD Cards
 
+config MMC_PWRSEQ
+	bool "HW reset support for eMMC"
+	depends on PWRSEQ
+	help
+	  Ths select Hardware reset support aka pwrseq-emmc for eMMC
+	  devices.
+
 config MMC_BROKEN_CD
 	bool "Poll for broken card detection case"
 	help
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 1c849cb..89d6af3 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_PWRSEQ) += mmc-pwrseq.o
 obj-$(CONFIG_MMC_SDHCI_ADMA_HELPERS) += sdhci-adma.o
 
 ifndef CONFIG_$(SPL_)BLK
diff --git a/drivers/mmc/meson_gx_mmc.c b/drivers/mmc/meson_gx_mmc.c
index 8b6dfa3..fcf4f03 100644
--- a/drivers/mmc/meson_gx_mmc.c
+++ b/drivers/mmc/meson_gx_mmc.c
@@ -265,10 +265,6 @@
 	uint32_t val;
 	int ret;
 
-#ifdef CONFIG_PWRSEQ
-	struct udevice *pwr_dev;
-#endif
-
 	/* Enable the clocks feeding the MMC controller */
 	ret = clk_get_bulk(dev, &clocks);
 	if (ret)
@@ -292,12 +288,11 @@
 
 	mmc_set_clock(mmc, cfg->f_min, MMC_CLK_ENABLE);
 
-#ifdef CONFIG_PWRSEQ
+#ifdef CONFIG_MMC_PWRSEQ
 	/* Enable power if needed */
-	ret = uclass_get_device_by_phandle(UCLASS_PWRSEQ, dev, "mmc-pwrseq",
-					   &pwr_dev);
+	ret = mmc_pwrseq_get_power(dev, cfg);
 	if (!ret) {
-		ret = pwrseq_set_power(pwr_dev, true);
+		ret = pwrseq_set_power(cfg->pwr_dev, true);
 		if (ret)
 			return ret;
 	}
@@ -342,37 +337,3 @@
 	.of_to_plat = meson_mmc_of_to_plat,
 	.plat_auto	= sizeof(struct meson_mmc_plat),
 };
-
-#ifdef CONFIG_PWRSEQ
-static int meson_mmc_pwrseq_set_power(struct udevice *dev, bool enable)
-{
-	struct gpio_desc reset;
-	int ret;
-
-	ret = gpio_request_by_name(dev, "reset-gpios", 0, &reset, GPIOD_IS_OUT);
-	if (ret)
-		return ret;
-	dm_gpio_set_value(&reset, 1);
-	udelay(1);
-	dm_gpio_set_value(&reset, 0);
-	udelay(200);
-
-	return 0;
-}
-
-static const struct pwrseq_ops meson_mmc_pwrseq_ops = {
-	.set_power	= meson_mmc_pwrseq_set_power,
-};
-
-static const struct udevice_id meson_mmc_pwrseq_ids[] = {
-	{ .compatible = "mmc-pwrseq-emmc" },
-	{ }
-};
-
-U_BOOT_DRIVER(meson_mmc_pwrseq_drv) = {
-	.name		= "mmc_pwrseq_emmc",
-	.id		= UCLASS_PWRSEQ,
-	.of_match	= meson_mmc_pwrseq_ids,
-	.ops		= &meson_mmc_pwrseq_ops,
-};
-#endif
diff --git a/drivers/mmc/mmc-pwrseq.c b/drivers/mmc/mmc-pwrseq.c
new file mode 100644
index 0000000..2539f61
--- /dev/null
+++ b/drivers/mmc/mmc-pwrseq.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2021 SAMSUNG Electronics
+ * Jaehoon Chung <jh80.chung@samsung.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <mmc.h>
+#include <pwrseq.h>
+#include <asm/gpio.h>
+#include <linux/delay.h>
+
+int mmc_pwrseq_get_power(struct udevice *dev, struct mmc_config *cfg)
+{
+	/* Enable power if needed */
+	return uclass_get_device_by_phandle(UCLASS_PWRSEQ, dev, "mmc-pwrseq",
+					   &cfg->pwr_dev);
+}
+
+static int mmc_pwrseq_set_power(struct udevice *dev, bool enable)
+{
+	struct gpio_desc reset;
+	int ret;
+
+	ret = gpio_request_by_name(dev, "reset-gpios", 0, &reset, GPIOD_IS_OUT);
+	if (ret)
+		return ret;
+	dm_gpio_set_value(&reset, 1);
+	udelay(1);
+	dm_gpio_set_value(&reset, 0);
+	udelay(200);
+
+	return 0;
+}
+
+static const struct pwrseq_ops mmc_pwrseq_ops = {
+	.set_power	= mmc_pwrseq_set_power,
+};
+
+static const struct udevice_id mmc_pwrseq_ids[] = {
+	{ .compatible = "mmc-pwrseq-emmc" },
+	{ }
+};
+
+U_BOOT_DRIVER(mmc_pwrseq_drv) = {
+	.name		= "mmc_pwrseq_emmc",
+	.id		= UCLASS_PWRSEQ,
+	.of_match	= mmc_pwrseq_ids,
+	.ops		= &mmc_pwrseq_ops,
+};
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 36aab50..b4c8e7f 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -841,7 +841,8 @@
 				 value);
 			return -EIO;
 		}
-		if (!ret && (status & MMC_STATUS_RDY_FOR_DATA))
+		if (!ret && (status & MMC_STATUS_RDY_FOR_DATA) &&
+		    (status & MMC_STATUS_CURR_STATE) == MMC_STATE_TRANS)
 			return 0;
 		udelay(100);
 	} while (get_timer(start) < timeout_ms);
@@ -2062,7 +2063,7 @@
 
 static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps)
 {
-	int err;
+	int err = 0;
 	const struct mode_width_tuning *mwt;
 	const struct ext_csd_bus_width *ecbw;
 
diff --git a/drivers/mmc/mmc_spi.c b/drivers/mmc/mmc_spi.c
index 46800bb..e2d7879 100644
--- a/drivers/mmc/mmc_spi.c
+++ b/drivers/mmc/mmc_spi.c
@@ -37,7 +37,8 @@
 #define SPI_RESPONSE_CRC_ERR		((5 << 1)|1)
 #define SPI_RESPONSE_WRITE_ERR		((6 << 1)|1)
 
-/* Read and write blocks start with these tokens and end with crc;
+/*
+ * Read and write blocks start with these tokens and end with crc;
  * on error, read tokens act like a subset of R2_SPI_* values.
  */
 /* single block write multiblock read */
@@ -70,6 +71,20 @@
 	struct spi_slave *spi;
 };
 
+/**
+ * mmc_spi_sendcmd() - send a command to the SD card
+ *
+ * @dev:	mmc_spi device
+ * @cmdidx:	command index
+ * @cmdarg:	command argument
+ * @resp_type:	card response type
+ * @resp:	buffer to store the card response
+ * @resp_size:	size of the card response
+ * @resp_match:	if true, compare each of received bytes with @resp_match_value
+ * @resp_match_value:	a value to be compared with each of received bytes
+ * @r1b:	if true, receive additional bytes for busy signal token
+ * @return 0 if OK, -ETIMEDOUT if no card response is received, -ve on error
+ */
 static int mmc_spi_sendcmd(struct udevice *dev,
 			   ushort cmdidx, u32 cmdarg, u32 resp_type,
 			   u8 *resp, u32 resp_size,
@@ -78,6 +93,9 @@
 	int i, rpos = 0, ret = 0;
 	u8 cmdo[7], r;
 
+	if (!resp || !resp_size)
+		return 0;
+
 	debug("%s: cmd%d cmdarg=0x%x resp_type=0x%x "
 	      "resp_size=%d resp_match=%d resp_match_value=0x%x\n",
 	      __func__, cmdidx, cmdarg, resp_type,
@@ -98,34 +116,33 @@
 	if (ret)
 		return ret;
 
-	if (!resp || !resp_size)
-		return 0;
-
 	debug("%s: cmd%d", __func__, cmdidx);
 
-	if (resp_match) {
+	if (resp_match)
 		r = ~resp_match_value;
-		i = CMD_TIMEOUT;
-		while (i) {
-			ret = dm_spi_xfer(dev, 1 * 8, NULL, &r, 0);
-			if (ret)
-				return ret;
-			debug(" resp%d=0x%x", rpos, r);
-			rpos++;
-			i--;
+	i = CMD_TIMEOUT;
+	while (i) {
+		ret = dm_spi_xfer(dev, 1 * 8, NULL, &r, 0);
+		if (ret)
+			return ret;
+		debug(" resp%d=0x%x", rpos, r);
+		rpos++;
+		i--;
 
+		if (resp_match) {
 			if (r == resp_match_value)
 				break;
+		} else {
+			if (!(r & 0x80))
+				break;
 		}
-		if (!i && (r != resp_match_value))
+
+		if (!i)
 			return -ETIMEDOUT;
 	}
 
-	for (i = 0; i < resp_size; i++) {
-		if (i == 0 && resp_match) {
-			resp[i] = resp_match_value;
-			continue;
-		}
+	resp[0] = r;
+	for (i = 1; i < resp_size; i++) {
 		ret = dm_spi_xfer(dev, 1 * 8, NULL, &r, 0);
 		if (ret)
 			return ret;
@@ -157,6 +174,15 @@
 	return 0;
 }
 
+/**
+ * mmc_spi_readdata() - read data block(s) from the SD card
+ *
+ * @dev:	mmc_spi device
+ * @xbuf:	buffer of the actual data (excluding token and crc) to read
+ * @bcnt:	number of data blocks to transfer
+ * @bsize:	size of the actual data (excluding token and crc) in bytes
+ * @return 0 if OK, -ECOMM if crc error, -ETIMEDOUT on other errors
+ */
 static int mmc_spi_readdata(struct udevice *dev,
 			    void *xbuf, u32 bcnt, u32 bsize)
 {
@@ -181,8 +207,10 @@
 			if (ret)
 				return ret;
 #ifdef CONFIG_MMC_SPI_CRC_ON
-			if (be16_to_cpu(crc16_ccitt(0, buf, bsize)) != crc) {
-				debug("%s: data crc error\n", __func__);
+			u16 crc_ok = be16_to_cpu(crc16_ccitt(0, buf, bsize));
+			if (crc_ok != crc) {
+				debug("%s: data crc error, expected %04x got %04x\n",
+				      __func__, crc_ok, crc);
 				r1 = R1_SPI_COM_CRC;
 				break;
 			}
@@ -203,6 +231,16 @@
 	return ret;
 }
 
+/**
+ * mmc_spi_writedata() - write data block(s) to the SD card
+ *
+ * @dev:	mmc_spi device
+ * @xbuf:	buffer of the actual data (excluding token and crc) to write
+ * @bcnt:	number of data blocks to transfer
+ * @bsize:	size of actual data (excluding token and crc) in bytes
+ * @multi:	indicate a transfer by multiple block write command (CMD25)
+ * @return 0 if OK, -ECOMM if crc error, -ETIMEDOUT on other errors
+ */
 static int mmc_spi_writedata(struct udevice *dev, const void *xbuf,
 			     u32 bcnt, u32 bsize, int multi)
 {
diff --git a/drivers/mmc/rockchip_dw_mmc.c b/drivers/mmc/rockchip_dw_mmc.c
index 1be3c17..d7d5361 100644
--- a/drivers/mmc/rockchip_dw_mmc.c
+++ b/drivers/mmc/rockchip_dw_mmc.c
@@ -105,7 +105,6 @@
 	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
 	struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
 	struct dwmci_host *host = &priv->host;
-	struct udevice *pwr_dev __maybe_unused;
 	int ret;
 
 #if CONFIG_IS_ENABLED(OF_PLATDATA)
@@ -136,12 +135,11 @@
 
 	host->fifo_mode = priv->fifo_mode;
 
-#ifdef CONFIG_PWRSEQ
+#ifdef CONFIG_MMC_PWRSEQ
 	/* Enable power if needed */
-	ret = uclass_get_device_by_phandle(UCLASS_PWRSEQ, dev, "mmc-pwrseq",
-					   &pwr_dev);
+	ret = mmc_pwrseq_get_power(dev, &plat->cfg);
 	if (!ret) {
-		ret = pwrseq_set_power(pwr_dev, true);
+		ret = pwrseq_set_power(plat->cfg.pwr_dev, true);
 		if (ret)
 			return ret;
 	}
@@ -182,37 +180,3 @@
 
 DM_DRIVER_ALIAS(rockchip_rk3288_dw_mshc, rockchip_rk3328_dw_mshc)
 DM_DRIVER_ALIAS(rockchip_rk3288_dw_mshc, rockchip_rk3368_dw_mshc)
-
-#ifdef CONFIG_PWRSEQ
-static int rockchip_dwmmc_pwrseq_set_power(struct udevice *dev, bool enable)
-{
-	struct gpio_desc reset;
-	int ret;
-
-	ret = gpio_request_by_name(dev, "reset-gpios", 0, &reset, GPIOD_IS_OUT);
-	if (ret)
-		return ret;
-	dm_gpio_set_value(&reset, 1);
-	udelay(1);
-	dm_gpio_set_value(&reset, 0);
-	udelay(200);
-
-	return 0;
-}
-
-static const struct pwrseq_ops rockchip_dwmmc_pwrseq_ops = {
-	.set_power	= rockchip_dwmmc_pwrseq_set_power,
-};
-
-static const struct udevice_id rockchip_dwmmc_pwrseq_ids[] = {
-	{ .compatible = "mmc-pwrseq-emmc" },
-	{ }
-};
-
-U_BOOT_DRIVER(rockchip_dwmmc_pwrseq_drv) = {
-	.name		= "mmc_pwrseq_emmc",
-	.id		= UCLASS_PWRSEQ,
-	.of_match	= rockchip_dwmmc_pwrseq_ids,
-	.ops		= &rockchip_dwmmc_pwrseq_ops,
-};
-#endif
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 5f18d47..d9ab6a0 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -177,8 +177,10 @@
 		}
 	} while (!(stat & SDHCI_INT_DATA_END));
 
+#if (defined(CONFIG_MMC_SDHCI_SDMA) || CONFIG_IS_ENABLED(MMC_SDHCI_ADMA))
 	dma_unmap_single(host->start_addr, data->blocks * data->blocksize,
 			 mmc_get_dma_dir(data));
+#endif
 
 	return 0;
 }
diff --git a/include/mmc.h b/include/mmc.h
index c12c7a0..8600881 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -178,6 +178,7 @@
 #define MMC_STATUS_ERROR	(1 << 19)
 
 #define MMC_STATE_PRG		(7 << 9)
+#define MMC_STATE_TRANS		(4 << 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 */
@@ -591,6 +592,9 @@
 	uint f_max;
 	uint b_max;
 	unsigned char part_type;
+#ifdef CONFIG_MMC_PWRSEQ
+	struct udevice *pwr_dev;
+#endif
 };
 
 struct sd_ssr {
@@ -807,6 +811,17 @@
  */
 int mmc_of_parse(struct udevice *dev, struct mmc_config *cfg);
 
+#ifdef CONFIG_MMC_PWRSEQ
+/**
+ * mmc_pwrseq_get_power() - get a power device from device tree
+ *
+ * @dev:	MMC device
+ * @cfg:	MMC configuration
+ * @return 0 if OK, -ve on error
+ */
+int mmc_pwrseq_get_power(struct udevice *dev, struct mmc_config *cfg);
+#endif
+
 int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size);
 
 /**