Merge https://source.denx.de/u-boot/custodians/u-boot-mmc
diff --git a/board/purism/librem5/librem5.c b/board/purism/librem5/librem5.c
index caa0265..386ed1b 100644
--- a/board/purism/librem5/librem5.c
+++ b/board/purism/librem5/librem5.c
@@ -41,7 +41,7 @@
 #if IS_ENABLED(CONFIG_LOAD_ENV_FROM_MMC_BOOT_PARTITION)
 uint board_mmc_get_env_part(struct mmc *mmc)
 {
-	uint part = (mmc->part_config >> 3) & PART_ACCESS_MASK;
+	uint part = EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config);
 
 	if (part == 7)
 		part = 0;
diff --git a/cmd/mmc.c b/cmd/mmc.c
index 94deb9a..c6bd81c 100644
--- a/cmd/mmc.c
+++ b/cmd/mmc.c
@@ -175,7 +175,7 @@
 			curr_device = 0;
 		else {
 			puts("No MMC device available\n");
-			return 1;
+			return CMD_RET_FAILURE;
 		}
 	}
 
@@ -927,7 +927,7 @@
 static int do_mmc_partconf(struct cmd_tbl *cmdtp, int flag,
 			   int argc, char *const argv[])
 {
-	int dev;
+	int ret, dev;
 	struct mmc *mmc;
 	u8 ack, part_num, access;
 
@@ -953,13 +953,17 @@
 	access = dectoul(argv[4], NULL);
 
 	/* acknowledge to be sent during boot operation */
-	return mmc_set_part_conf(mmc, ack, part_num, access);
+	ret = mmc_set_part_conf(mmc, ack, part_num, access);
+	if (ret != 0)
+		return CMD_RET_FAILURE;
+
+	return CMD_RET_SUCCESS;
 }
 
 static int do_mmc_rst_func(struct cmd_tbl *cmdtp, int flag,
 			   int argc, char *const argv[])
 {
-	int dev;
+	int ret, dev;
 	struct mmc *mmc;
 	u8 enable;
 
@@ -988,7 +992,11 @@
 		return CMD_RET_FAILURE;
 	}
 
+	ret = mmc_set_rst_n_function(mmc, enable);
+	if (ret != 0)
+		return CMD_RET_FAILURE;
+
-	return mmc_set_rst_n_function(mmc, enable);
+	return CMD_RET_SUCCESS;
 }
 #endif
 static int do_mmc_setdsr(struct cmd_tbl *cmdtp, int flag,
diff --git a/cmd/mvebu/bubt.c b/cmd/mvebu/bubt.c
index 49797b2..37ff9c4 100644
--- a/cmd/mvebu/bubt.c
+++ b/cmd/mvebu/bubt.c
@@ -223,8 +223,7 @@
 	orig_part = mmc->block_dev.hwpart;
 #endif
 
-	part = (mmc->part_config >> 3) & PART_ACCESS_MASK;
-
+	part = EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config);
 	if (part == 7)
 		part = 0;
 
diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c
index bd5e6ad..a072216 100644
--- a/common/spl/spl_mmc.c
+++ b/common/spl/spl_mmc.c
@@ -378,7 +378,7 @@
 	 * 1 and 2 match up to boot0 / boot1 and 7 is user data
 	 * which is the first physical partition (0).
 	 */
-	part = (mmc->part_config >> 3) & PART_ACCESS_MASK;
+	part = EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config);
 	if (part == 7)
 		part = 0;
 #endif
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 80641e1..59fb0fb 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -621,6 +621,7 @@
 	bool "SDHCI support on Marvell platform"
 	depends on ARCH_MVEBU
 	depends on MMC_SDHCI
+	depends on DM_MMC
 	help
 	  This selects the Secure Digital Host Controller Interface on
 	  Marvell platform.
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index dde251c..1af6af8 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -2432,6 +2432,9 @@
 
 	mmc->wr_rel_set = ext_csd[EXT_CSD_WR_REL_SET];
 
+	mmc->can_trim =
+		!!(ext_csd[EXT_CSD_SEC_FEATURE] & EXT_CSD_SEC_FEATURE_TRIM_EN);
+
 	return 0;
 error:
 	if (mmc->ext_csd) {
diff --git a/drivers/mmc/mmc_write.c b/drivers/mmc/mmc_write.c
index 5b7aeeb..a6f9338 100644
--- a/drivers/mmc/mmc_write.c
+++ b/drivers/mmc/mmc_write.c
@@ -15,7 +15,7 @@
 #include <linux/math64.h>
 #include "mmc_private.h"
 
-static ulong mmc_erase_t(struct mmc *mmc, ulong start, lbaint_t blkcnt)
+static ulong mmc_erase_t(struct mmc *mmc, ulong start, lbaint_t blkcnt, u32 args)
 {
 	struct mmc_cmd cmd;
 	ulong end;
@@ -52,7 +52,7 @@
 		goto err_out;
 
 	cmd.cmdidx = MMC_CMD_ERASE;
-	cmd.cmdarg = MMC_ERASE_ARG;
+	cmd.cmdarg = args ? args : MMC_ERASE_ARG;
 	cmd.resp_type = MMC_RSP_R1b;
 
 	err = mmc_send_cmd(mmc, &cmd, NULL);
@@ -77,7 +77,7 @@
 #endif
 	int dev_num = block_dev->devnum;
 	int err = 0;
-	u32 start_rem, blkcnt_rem;
+	u32 start_rem, blkcnt_rem, erase_args = 0;
 	struct mmc *mmc = find_mmc_device(dev_num);
 	lbaint_t blk = 0, blk_r = 0;
 	int timeout_ms = 1000;
@@ -97,13 +97,25 @@
 	 */
 	err = div_u64_rem(start, mmc->erase_grp_size, &start_rem);
 	err = div_u64_rem(blkcnt, mmc->erase_grp_size, &blkcnt_rem);
-	if (start_rem || blkcnt_rem)
-		printf("\n\nCaution! Your devices Erase group is 0x%x\n"
-		       "The erase range would be change to "
-		       "0x" LBAF "~0x" LBAF "\n\n",
-		       mmc->erase_grp_size, start & ~(mmc->erase_grp_size - 1),
-		       ((start + blkcnt + mmc->erase_grp_size - 1)
-		       & ~(mmc->erase_grp_size - 1)) - 1);
+	if (start_rem || blkcnt_rem) {
+		if (mmc->can_trim) {
+			/* Trim function applies the erase operation to write
+			 * blocks instead of erase groups.
+			 */
+			erase_args = MMC_TRIM_ARG;
+		} else {
+			/* The card ignores all LSB's below the erase group
+			 * size, rounding down the addess to a erase group
+			 * boundary.
+			 */
+			printf("\n\nCaution! Your devices Erase group is 0x%x\n"
+			       "The erase range would be change to "
+			       "0x" LBAF "~0x" LBAF "\n\n",
+			       mmc->erase_grp_size, start & ~(mmc->erase_grp_size - 1),
+			       ((start + blkcnt + mmc->erase_grp_size - 1)
+			       & ~(mmc->erase_grp_size - 1)) - 1);
+		}
+	}
 
 	while (blk < blkcnt) {
 		if (IS_SD(mmc) && mmc->ssr.au) {
@@ -113,7 +125,7 @@
 			blk_r = ((blkcnt - blk) > mmc->erase_grp_size) ?
 				mmc->erase_grp_size : (blkcnt - blk);
 		}
-		err = mmc_erase_t(mmc, start + blk, blk_r);
+		err = mmc_erase_t(mmc, start + blk, blk_r, erase_args);
 		if (err)
 			break;
 
diff --git a/drivers/mmc/mv_sdhci.c b/drivers/mmc/mv_sdhci.c
index 336ebf1..dbdd671 100644
--- a/drivers/mmc/mv_sdhci.c
+++ b/drivers/mmc/mv_sdhci.c
@@ -15,6 +15,13 @@
 #define SDHCI_WINDOW_CTRL(win)		(0x4080 + ((win) << 4))
 #define SDHCI_WINDOW_BASE(win)		(0x4084 + ((win) << 4))
 
+DECLARE_GLOBAL_DATA_PTR;
+
+struct mv_sdhci_plat {
+	struct mmc_config cfg;
+	struct mmc mmc;
+};
+
 static void sdhci_mvebu_mbus_config(void __iomem *base)
 {
 	const struct mbus_dram_target_info *dram;
@@ -40,47 +47,6 @@
 	}
 }
 
-#ifndef CONFIG_DM_MMC
-
-#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
-static struct sdhci_ops mv_ops;
-#endif /* CONFIG_MMC_SDHCI_IO_ACCESSORS */
-
-int mv_sdh_init(unsigned long regbase, u32 max_clk, u32 min_clk, u32 quirks)
-{
-	struct sdhci_host *host = NULL;
-	host = calloc(1, sizeof(*host));
-	if (!host) {
-		printf("sdh_host malloc fail!\n");
-		return -ENOMEM;
-	}
-
-	host->name = MVSDH_NAME;
-	host->ioaddr = (void *)regbase;
-	host->quirks = quirks;
-	host->max_clk = max_clk;
-#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
-	memset(&mv_ops, 0, sizeof(struct sdhci_ops));
-	host->ops = &mv_ops;
-#endif
-
-	if (CONFIG_IS_ENABLED(ARCH_MVEBU)) {
-		/* Configure SDHCI MBUS mbus bridge windows */
-		sdhci_mvebu_mbus_config((void __iomem *)regbase);
-	}
-
-	return add_sdhci(host, 0, min_clk);
-}
-
-#else
-
-DECLARE_GLOBAL_DATA_PTR;
-
-struct mv_sdhci_plat {
-	struct mmc_config cfg;
-	struct mmc mmc;
-};
-
 static int mv_sdhci_probe(struct udevice *dev)
 {
 	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
@@ -103,10 +69,8 @@
 	if (ret)
 		return ret;
 
-	if (CONFIG_IS_ENABLED(ARCH_MVEBU)) {
-		/* Configure SDHCI MBUS mbus bridge windows */
-		sdhci_mvebu_mbus_config(host->ioaddr);
-	}
+	/* Configure SDHCI MBUS mbus bridge windows */
+	sdhci_mvebu_mbus_config(host->ioaddr);
 
 	upriv->mmc = host->mmc;
 
@@ -135,4 +99,3 @@
 	.priv_auto	= sizeof(struct sdhci_host),
 	.plat_auto	= sizeof(struct mv_sdhci_plat),
 };
-#endif /* CONFIG_DM_MMC */
diff --git a/include/mmc.h b/include/mmc.h
index 36dd841..b8fbff1 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -241,6 +241,7 @@
 #define EXT_CSD_HC_WP_GRP_SIZE		221	/* RO */
 #define EXT_CSD_HC_ERASE_GRP_SIZE	224	/* RO */
 #define EXT_CSD_BOOT_MULT		226	/* RO */
+#define EXT_CSD_SEC_FEATURE		231	/* RO */
 #define EXT_CSD_GENERIC_CMD6_TIME       248     /* RO */
 #define EXT_CSD_BKOPS_SUPPORT		502	/* RO */
 
@@ -315,6 +316,8 @@
 #define EXT_CSD_WR_DATA_REL_USR		(1 << 0)	/* user data area WR_REL */
 #define EXT_CSD_WR_DATA_REL_GP(x)	(1 << ((x)+1))	/* GP part (x+1) WR_REL */
 
+#define EXT_CSD_SEC_FEATURE_TRIM_EN	(1 << 4) /* Support secure & insecure trim */
+
 #define R1_ILLEGAL_COMMAND		(1 << 22)
 #define R1_APP_CMD			(1 << 5)
 
@@ -687,6 +690,7 @@
 	uint tran_speed;
 	uint legacy_speed; /* speed for the legacy mode provided by the card */
 	uint read_bl_len;
+	bool can_trim;
 #if CONFIG_IS_ENABLED(MMC_WRITE)
 	uint write_bl_len;
 	uint erase_grp_size;	/* in 512-byte sectors */
diff --git a/test/dm/mmc.c b/test/dm/mmc.c
index f744452..b1eb8be 100644
--- a/test/dm/mmc.c
+++ b/test/dm/mmc.c
@@ -30,7 +30,7 @@
 	struct udevice *dev;
 	struct blk_desc *dev_desc;
 	int i;
-	char write[1024], read[1024];
+	char write[4 * 512], read[4 * 512];
 
 	ut_assertok(uclass_get_device(UCLASS_MMC, 0, &dev));
 	ut_assertok(blk_get_device_by_str("mmc", "0", &dev_desc));
@@ -39,14 +39,14 @@
 	ut_asserteq(512, dev_desc->blksz);
 	for (i = 0; i < sizeof(write); i++)
 		write[i] = i;
-	ut_asserteq(2, blk_dwrite(dev_desc, 0, 2, write));
-	ut_asserteq(2, blk_dread(dev_desc, 0, 2, read));
+	ut_asserteq(4, blk_dwrite(dev_desc, 0, 4, write));
+	ut_asserteq(4, blk_dread(dev_desc, 0, 4, read));
 	ut_asserteq_mem(write, read, sizeof(write));
 
-	/* Now erase them */
-	memset(write, '\0', sizeof(write));
-	ut_asserteq(2, blk_derase(dev_desc, 0, 2));
-	ut_asserteq(2, blk_dread(dev_desc, 0, 2, read));
+	/* Now erase two of them [1 - 2] and verify all blocks */
+	memset(&write[512], '\0', 2 * 512);
+	ut_asserteq(2, blk_derase(dev_desc, 1, 2));
+	ut_asserteq(4, blk_dread(dev_desc, 0, 4, read));
 	ut_asserteq_mem(write, read, sizeof(write));
 
 	return 0;