Merge tag 'mmc-2021-4-6' of https://source.denx.de/u-boot/custodians/u-boot-mmc

Update hwpartition usage
Check bootbus's arguments
workaround for erratum A-011334 for fsl_esdhc driver
add pulse width detection workaround for fsl_esdhc driver
Use alias num before checking mmc index when creating device
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
index ae0b7b2..9d1ba4c 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
+++ b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
@@ -47,6 +47,8 @@
 	select SYS_FSL_ERRATUM_A009663 if !TFABOOT
 	select SYS_FSL_ERRATUM_A009942 if !TFABOOT
 	select SYS_FSL_ERRATUM_A050382
+	select SYS_FSL_ERRATUM_A011334
+	select SYS_FSL_ESDHC_UNRELIABLE_PULSE_DETECTION_WORKAROUND
 	select RESV_RAM if GIC_V3_ITS
 	imply PANIC_HANG
 
diff --git a/cmd/mmc.c b/cmd/mmc.c
index cb6b59f..a10f137 100644
--- a/cmd/mmc.c
+++ b/cmd/mmc.c
@@ -735,8 +735,45 @@
 		return CMD_RET_FAILURE;
 	}
 
+	/*
+	 * BOOT_BUS_CONDITIONS[177]
+	 * BOOT_MODE[4:3]
+	 * 0x0 : Use SDR + Backward compatible timing in boot operation
+	 * 0x1 : Use SDR + High Speed Timing in boot operation mode
+	 * 0x2 : Use DDR in boot operation
+	 * RESET_BOOT_BUS_CONDITIONS
+	 * 0x0 : Reset bus width to x1, SDR, Backward compatible
+	 * 0x1 : Retain BOOT_BUS_WIDTH and BOOT_MODE
+	 * BOOT_BUS_WIDTH
+	 * 0x0 : x1(sdr) or x4 (ddr) buswidth
+	 * 0x1 : x4(sdr/ddr) buswith
+	 * 0x2 : x8(sdr/ddr) buswith
+	 *
+	 */
+	if (width >= 0x3) {
+		printf("boot_bus_width %d is invalid\n", width);
+		return CMD_RET_FAILURE;
+	}
+
+	if (reset >= 0x2) {
+		printf("reset_boot_bus_width %d is invalid\n", reset);
+		return CMD_RET_FAILURE;
+	}
+
+	if (mode >= 0x3) {
+		printf("reset_boot_bus_width %d is invalid\n", mode);
+		return CMD_RET_FAILURE;
+	}
+
 	/* acknowledge to be sent during boot operation */
-	return mmc_set_boot_bus_width(mmc, width, reset, mode);
+	if (mmc_set_boot_bus_width(mmc, width, reset, mode)) {
+		puts("BOOT_BUS_WIDTH is failed to change.\n");
+		return CMD_RET_FAILURE;
+	}
+
+	printf("Set to BOOT_BUS_WIDTH = 0x%x, RESET = 0x%x, BOOT_MODE = 0x%x\n",
+			width, reset, mode);
+	return CMD_RET_SUCCESS;
 }
 
 static int do_mmc_boot_resize(struct cmd_tbl *cmdtp, int flag,
@@ -1008,11 +1045,14 @@
 	"mmc list - lists available devices\n"
 	"mmc wp - power on write protect boot partitions\n"
 #if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING)
-	"mmc hwpartition [args...] - does hardware partitioning\n"
+	"mmc hwpartition <USER> <GP> <MODE> - does hardware partitioning\n"
 	"  arguments (sizes in 512-byte blocks):\n"
-	"    [user [enh start cnt] [wrrel {on|off}]] - sets user data area attributes\n"
-	"    [gp1|gp2|gp3|gp4 cnt [enh] [wrrel {on|off}]] - general purpose partition\n"
-	"    [check|set|complete] - mode, complete set partitioning completed\n"
+	"   USER - <user> <enh> <start> <cnt> <wrrel> <{on|off}>\n"
+	"	: sets user data area attributes\n"
+	"   GP - <{gp1|gp2|gp3|gp4}> <cnt> <enh> <wrrel> <{on|off}>\n"
+	"	: general purpose partition\n"
+	"   MODE - <{check|set|complete}>\n"
+	"	: mode, complete set partitioning completed\n"
 	"  WARNING: Partitioning is a write-once setting once it is set to complete.\n"
 	"  Power cycling is required to initialize partitions after set to complete.\n"
 #endif
diff --git a/configs/kontron_sl28_defconfig b/configs/kontron_sl28_defconfig
index 0c6c191..1c781e0 100644
--- a/configs/kontron_sl28_defconfig
+++ b/configs/kontron_sl28_defconfig
@@ -70,7 +70,7 @@
 CONFIG_I2C_DEFAULT_BUS_NUMBER=0
 CONFIG_I2C_MUX=y
 CONFIG_DM_MMC=y
-CONFIG_MMC_HS200_SUPPORT=y
+CONFIG_MMC_HS400_SUPPORT=y
 CONFIG_FSL_ESDHC=y
 CONFIG_FSL_ESDHC_SUPPORT_ADMA2=y
 CONFIG_DM_SPI_FLASH=y
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index c34fce3..4925675 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -813,3 +813,9 @@
 
 config SYS_FSL_ERRATUM_ESDHC_A001
 	bool
+
+config SYS_FSL_ERRATUM_A011334
+	bool
+
+config SYS_FSL_ESDHC_UNRELIABLE_PULSE_DETECTION_WORKAROUND
+	bool
diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index 6014e1c..7501fdb 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -71,7 +71,8 @@
 	uint	sdtimingctl;	/* SD timing control register */
 	char    reserved8[20];	/* reserved */
 	uint	dllcfg0;	/* DLL config 0 register */
-	char	reserved9[12];	/* reserved */
+	uint	dllcfg1;	/* DLL config 1 register */
+	char	reserved9[8];	/* reserved */
 	uint	dllstat0;	/* DLL status 0 register */
 	char    reserved10[664];/* reserved */
 	uint    esdhcctl;	/* eSDHC control register */
@@ -518,6 +519,24 @@
 	while (sdhc_clk / (div * pre_div) > clock && div < 16)
 		div++;
 
+	if (IS_ENABLED(CONFIG_SYS_FSL_ERRATUM_A011334) &&
+	    clock == 200000000 && mmc->selected_mode == MMC_HS_400) {
+		u32 div_ratio = pre_div * div;
+
+		if (div_ratio <= 4) {
+			pre_div = 4;
+			div = 1;
+		} else if (div_ratio <= 8) {
+			pre_div = 4;
+			div = 2;
+		} else if (div_ratio <= 12) {
+			pre_div = 4;
+			div = 3;
+		} else {
+			printf("unsupported clock division.\n");
+		}
+	}
+
 	mmc->clock = sdhc_clk / pre_div / div;
 	priv->clock = mmc->clock;
 
@@ -749,6 +768,9 @@
 	/* Set timout to the maximum value */
 	esdhc_clrsetbits32(&regs->sysctl, SYSCTL_TIMEOUT_MASK, 14 << 16);
 
+	if (IS_ENABLED(CONFIG_SYS_FSL_ESDHC_UNRELIABLE_PULSE_DETECTION_WORKAROUND))
+		esdhc_clrbits32(&regs->dllcfg1, DLL_PD_PULSE_STRETCH_SEL);
+
 	return 0;
 }
 
@@ -1063,9 +1085,14 @@
 	struct fsl_esdhc_plat *plat = dev_get_plat(dev);
 	struct fsl_esdhc_priv *priv = dev_get_priv(dev);
 	struct fsl_esdhc *regs = priv->esdhc_regs;
+	struct mmc *mmc = &plat->mmc;
 	u32 val, irqstaten;
 	int i;
 
+	if (IS_ENABLED(CONFIG_SYS_FSL_ERRATUM_A011334) &&
+	    plat->mmc.hs400_tuning)
+		set_sysctl(priv, mmc, mmc->clock);
+
 	esdhc_tuning_block_enable(priv, true);
 	esdhc_setbits32(&regs->autoc12err, EXECUTE_TUNING);
 
@@ -1073,7 +1100,7 @@
 	esdhc_write32(&regs->irqstaten, IRQSTATEN_BRR);
 
 	for (i = 0; i < MAX_TUNING_LOOP; i++) {
-		mmc_send_tuning(&plat->mmc, opcode, NULL);
+		mmc_send_tuning(mmc, opcode, NULL);
 		mdelay(1);
 
 		val = esdhc_read32(&regs->autoc12err);
diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index 53eabc9..d36aae3 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -383,18 +383,16 @@
 {
 	struct blk_desc *bdesc;
 	struct udevice *bdev;
-	int ret, devnum = -1;
+	int ret;
 
 	if (!mmc_get_ops(dev))
 		return -ENOSYS;
-#ifndef CONFIG_SPL_BUILD
-	/* Use the fixed index with aliase node's index */
-	ret = dev_read_alias_seq(dev, &devnum);
-	debug("%s: alias ret=%d, devnum=%d\n", __func__, ret, devnum);
-#endif
+
+	/* Use the fixed index with aliases node's index */
+	debug("%s: alias devnum=%d\n", __func__, dev_seq(dev));
 
 	ret = blk_create_devicef(dev, "mmc_blk", "blk", IF_TYPE_MMC,
-			devnum, 512, 0, &bdev);
+			dev_seq(dev), 512, 0, &bdev);
 	if (ret) {
 		debug("Cannot create block device\n");
 		return ret;
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index b4c8e7f..1e83007 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -3052,9 +3052,11 @@
 	struct mmc *m;
 	int ret;
 
-	ret = uclass_get_device(UCLASS_MMC, num, &dev);
-	if (ret)
-		return ret;
+	if (uclass_get_device_by_seq(UCLASS_MMC, num, &dev)) {
+		ret = uclass_get_device(UCLASS_MMC, num, &dev);
+		if (ret)
+			return ret;
+	}
 
 	m = mmc_get_mmc_dev(dev);
 	if (!m)
diff --git a/include/fsl_esdhc.h b/include/fsl_esdhc.h
index 850a304..f86afe5 100644
--- a/include/fsl_esdhc.h
+++ b/include/fsl_esdhc.h
@@ -190,6 +190,9 @@
 #define DLL_RESET		0x40000000
 #define DLL_FREQ_SEL		0x08000000
 
+/* DLL config 1 register */
+#define DLL_PD_PULSE_STRETCH_SEL 0x80000000
+
 /* DLL status 0 register */
 #define DLL_STS_SLV_LOCK	0x08000000