All of lore.kernel.org
 help / color / mirror / Atom feed
* [v2, 00/11] mmc: fsl_esdhc: support eMMC HS200/HS400 modes
@ 2020-07-17  8:50 Yangbo Lu
  2020-07-17  8:50 ` [v2, 01/11] mmc: add a reinit() API Yangbo Lu
                   ` (10 more replies)
  0 siblings, 11 replies; 23+ messages in thread
From: Yangbo Lu @ 2020-07-17  8:50 UTC (permalink / raw)
  To: u-boot

This patch-set is to support eMMC HS200 and HS400 speed modes for
eSDHC, and enable them on LX2160ARDB board.

CI build link
https://travis-ci.org/github/yangbolu1991/u-boot-test/builds/709088861

Changes for v2:
- Added two patches to fix stability issue.

Yangbo Lu (11):
  mmc: add a reinit() API
  mmc: fsl_esdhc: add a reinit() callback
  mmc: fsl_esdhc: support tuning for eMMC HS200
  mmc: fsl_esdhc: clean TBCTL[TB_EN] manually during init
  mmc: add a hs400_tuning flag
  mmc: add a mmc_hs400_prepare_ddr() interface
  mmc: fsl_esdhc: support eMMC HS400 mode
  mmc: fsl_esdhc: fix mmc->clock with actual clock
  mmc: fsl_esdhc: fix eMMC HS400 stability issue
  arm: dts: lx2160ardb: support eMMC HS400 mode
  configs: lx2160ardb: enable eMMC HS400 mode support

 arch/arm/dts/fsl-lx2160a-rdb.dts             |   2 +
 configs/lx2160ardb_tfa_SECURE_BOOT_defconfig |   1 +
 configs/lx2160ardb_tfa_defconfig             |   1 +
 configs/lx2160ardb_tfa_stmm_defconfig        |   1 +
 drivers/mmc/fsl_esdhc.c                      | 154 ++++++++++++++++++++++++++-
 drivers/mmc/mmc-uclass.c                     |  30 ++++++
 drivers/mmc/mmc.c                            |  12 ++-
 include/fsl_esdhc.h                          |  29 ++++-
 include/mmc.h                                |  26 ++++-
 9 files changed, 246 insertions(+), 10 deletions(-)

-- 
2.7.4

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [v2, 01/11] mmc: add a reinit() API
  2020-07-17  8:50 [v2, 00/11] mmc: fsl_esdhc: support eMMC HS200/HS400 modes Yangbo Lu
@ 2020-07-17  8:50 ` Yangbo Lu
  2020-07-20  1:33   ` Peng Fan
  2020-07-17  8:50 ` [v2, 02/11] mmc: fsl_esdhc: add a reinit() callback Yangbo Lu
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Yangbo Lu @ 2020-07-17  8:50 UTC (permalink / raw)
  To: u-boot

For DM_MMC, the controller re-initialization is needed to
clear old configuration for mmc rescan.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
	- None.
---
 drivers/mmc/mmc-uclass.c | 15 +++++++++++++++
 drivers/mmc/mmc.c        |  8 ++++++--
 include/mmc.h            | 10 ++++++++++
 3 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index c5b7872..b9f0880 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -170,6 +170,21 @@ int mmc_deferred_probe(struct mmc *mmc)
 	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 50f47d4..a53f93a 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -2813,13 +2813,17 @@ int mmc_get_op_cond(struct mmc *mmc)
 		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/include/mmc.h b/include/mmc.h
index 8256219..161b8bc 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -422,6 +422,14 @@ struct dm_mmc_ops {
 	 */
 	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
@@ -518,6 +526,7 @@ int dm_mmc_execute_tuning(struct udevice *dev, uint opcode);
 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,6 +538,7 @@ int mmc_wait_dat0(struct mmc *mmc, int state, int timeout_us);
 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);
 
 #else
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [v2, 02/11] mmc: fsl_esdhc: add a reinit() callback
  2020-07-17  8:50 [v2, 00/11] mmc: fsl_esdhc: support eMMC HS200/HS400 modes Yangbo Lu
  2020-07-17  8:50 ` [v2, 01/11] mmc: add a reinit() API Yangbo Lu
@ 2020-07-17  8:50 ` Yangbo Lu
  2020-07-17  8:50 ` [v2, 03/11] mmc: fsl_esdhc: support tuning for eMMC HS200 Yangbo Lu
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Yangbo Lu @ 2020-07-17  8:50 UTC (permalink / raw)
  To: u-boot

Add a reinit() callback for mmc rescan.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
	- None.
---
 drivers/mmc/fsl_esdhc.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index a4b923a..d1f2e4a 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -946,6 +946,14 @@ static int fsl_esdhc_set_ios(struct udevice *dev)
 	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);
+}
+
 static const struct dm_mmc_ops fsl_esdhc_ops = {
 	.get_cd		= fsl_esdhc_get_cd,
 	.send_cmd	= fsl_esdhc_send_cmd,
@@ -953,6 +961,7 @@ static const struct dm_mmc_ops fsl_esdhc_ops = {
 #ifdef MMC_SUPPORTS_TUNING
 	.execute_tuning = fsl_esdhc_execute_tuning,
 #endif
+	.reinit = fsl_esdhc_reinit,
 };
 
 static const struct udevice_id fsl_esdhc_ids[] = {
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [v2, 03/11] mmc: fsl_esdhc: support tuning for eMMC HS200
  2020-07-17  8:50 [v2, 00/11] mmc: fsl_esdhc: support eMMC HS200/HS400 modes Yangbo Lu
  2020-07-17  8:50 ` [v2, 01/11] mmc: add a reinit() API Yangbo Lu
  2020-07-17  8:50 ` [v2, 02/11] mmc: fsl_esdhc: add a reinit() callback Yangbo Lu
@ 2020-07-17  8:50 ` Yangbo Lu
  2020-07-17  8:50 ` [v2, 04/11] mmc: fsl_esdhc: clean TBCTL[TB_EN] manually during init Yangbo Lu
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Yangbo Lu @ 2020-07-17  8:50 UTC (permalink / raw)
  To: u-boot

Support tuning process for eMMC HS200 for eSDHC.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
	- None.
---
 drivers/mmc/fsl_esdhc.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++--
 include/fsl_esdhc.h     |  17 ++++++--
 2 files changed, 116 insertions(+), 7 deletions(-)

diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index d1f2e4a..5ad01ac 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -60,7 +60,9 @@ struct fsl_esdhc {
 	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[744];	/* reserved */
 	uint    esdhcctl;	/* eSDHC control register */
 };
 
@@ -101,7 +103,9 @@ static uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data)
 	if (data) {
 		xfertyp |= XFERTYP_DPSEL;
 #ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
-		xfertyp |= XFERTYP_DMAEN;
+		if (cmd->cmdidx != MMC_CMD_SEND_TUNING_BLOCK &&
+		    cmd->cmdidx != MMC_CMD_SEND_TUNING_BLOCK_HS200)
+			xfertyp |= XFERTYP_DMAEN;
 #endif
 		if (data->blocks > 1) {
 			xfertyp |= XFERTYP_MSBSEL;
@@ -380,6 +384,10 @@ static int esdhc_send_cmd_common(struct fsl_esdhc_priv *priv, struct mmc *mmc,
 	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)) {
@@ -439,6 +447,11 @@ static int esdhc_send_cmd_common(struct fsl_esdhc_priv *priv, struct mmc *mmc,
 #ifdef 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;
+
 		do {
 			irqstat = esdhc_read32(&regs->irqstat);
 
@@ -451,7 +464,7 @@ static int esdhc_send_cmd_common(struct fsl_esdhc_priv *priv, struct mmc *mmc,
 				err = -ECOMM;
 				goto out;
 			}
-		} while ((irqstat & DATA_COMPLETE) != DATA_COMPLETE);
+		} while ((irqstat & flags) != flags);
 
 		/*
 		 * Need invalidate the dcache here again to avoid any
@@ -555,6 +568,19 @@ static void esdhc_clock_control(struct fsl_esdhc_priv *priv, bool enable)
 	}
 }
 
+static void esdhc_set_timing(struct fsl_esdhc_priv *priv, enum bus_mode mode)
+{
+	struct fsl_esdhc *regs = priv->esdhc_regs;
+
+	esdhc_clock_control(priv, false);
+
+	if (mode == MMC_HS_200)
+		esdhc_clrsetbits32(&regs->autoc12err, UHSM_MASK,
+				   UHSM_SDR104_HS200);
+
+	esdhc_clock_control(priv, true);
+}
+
 static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
 {
 	struct fsl_esdhc *regs = priv->esdhc_regs;
@@ -570,6 +596,9 @@ static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
 	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);
 
@@ -954,6 +983,77 @@ static int fsl_esdhc_reinit(struct udevice *dev)
 	return esdhc_init_common(priv, &plat->mmc);
 }
 
+#ifdef MMC_SUPPORTS_TUNING
+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 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)
+		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
+
 static const struct dm_mmc_ops fsl_esdhc_ops = {
 	.get_cd		= fsl_esdhc_get_cd,
 	.send_cmd	= fsl_esdhc_send_cmd,
diff --git a/include/fsl_esdhc.h b/include/fsl_esdhc.h
index e148eaa..ada95bc 100644
--- a/include/fsl_esdhc.h
+++ b/include/fsl_esdhc.h
@@ -78,8 +78,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)
@@ -158,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
@@ -166,6 +174,11 @@
 #define HOSTCAPBLT_DMAS		0x00400000
 #define HOSTCAPBLT_HSS		0x00200000
 
+/* Tuning block control register */
+#define TBCTL_TB_EN		0x00000004
+
+#define MAX_TUNING_LOOP		40
+
 struct fsl_esdhc_cfg {
 	phys_addr_t esdhc_base;
 	u32	sdhc_clk;
@@ -207,10 +220,6 @@ struct fsl_esdhc_cfg {
 int fsl_esdhc_mmc_init(bd_t *bis);
 int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg);
 void fdt_fixup_esdhc(void *blob, bd_t *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(bd_t *bis) { return -ENOSYS; }
 static inline void fdt_fixup_esdhc(void *blob, bd_t *bd) {}
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [v2, 04/11] mmc: fsl_esdhc: clean TBCTL[TB_EN] manually during init
  2020-07-17  8:50 [v2, 00/11] mmc: fsl_esdhc: support eMMC HS200/HS400 modes Yangbo Lu
                   ` (2 preceding siblings ...)
  2020-07-17  8:50 ` [v2, 03/11] mmc: fsl_esdhc: support tuning for eMMC HS200 Yangbo Lu
@ 2020-07-17  8:50 ` Yangbo Lu
  2020-07-17  8:50 ` [v2, 05/11] mmc: add a hs400_tuning flag Yangbo Lu
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Yangbo Lu @ 2020-07-17  8:50 UTC (permalink / raw)
  To: u-boot

Clean TBCTL[TB_EN] manually during init since it is not able to
be reset by reset all operation.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
	- None.
---
 drivers/mmc/fsl_esdhc.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index 5ad01ac..607b420 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -637,6 +637,9 @@ static int esdhc_init_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
 			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);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [v2, 05/11] mmc: add a hs400_tuning flag
  2020-07-17  8:50 [v2, 00/11] mmc: fsl_esdhc: support eMMC HS200/HS400 modes Yangbo Lu
                   ` (3 preceding siblings ...)
  2020-07-17  8:50 ` [v2, 04/11] mmc: fsl_esdhc: clean TBCTL[TB_EN] manually during init Yangbo Lu
@ 2020-07-17  8:50 ` Yangbo Lu
  2020-07-20  1:36   ` Peng Fan
  2020-07-17  8:50 ` [v2, 06/11] mmc: add a mmc_hs400_prepare_ddr() interface Yangbo Lu
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Yangbo Lu @ 2020-07-17  8:50 UTC (permalink / raw)
  To: u-boot

Add a hs400_tuning flag to identify the tuning for HS400 mode.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
	- None.
---
 drivers/mmc/mmc.c | 2 ++
 include/mmc.h     | 1 +
 2 files changed, 3 insertions(+)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index a53f93a..a18e75d 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1976,7 +1976,9 @@ static int mmc_select_hs400(struct mmc *mmc)
 	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;
diff --git a/include/mmc.h b/include/mmc.h
index 161b8bc..2399cc2 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -707,6 +707,7 @@ struct mmc {
 				  * accessing the boot partitions
 				  */
 	u32 quirks;
+	u8 hs400_tuning;
 };
 
 struct mmc_hwpart_conf {
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [v2, 06/11] mmc: add a mmc_hs400_prepare_ddr() interface
  2020-07-17  8:50 [v2, 00/11] mmc: fsl_esdhc: support eMMC HS200/HS400 modes Yangbo Lu
                   ` (4 preceding siblings ...)
  2020-07-17  8:50 ` [v2, 05/11] mmc: add a hs400_tuning flag Yangbo Lu
@ 2020-07-17  8:50 ` Yangbo Lu
  2020-07-20  1:40   ` Peng Fan
  2020-07-17  8:50 ` [v2, 07/11] mmc: fsl_esdhc: support eMMC HS400 mode Yangbo Lu
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Yangbo Lu @ 2020-07-17  8:50 UTC (permalink / raw)
  To: u-boot

Add a mmc_hs400_prepare_ddr() interface for controllers
which needs preparation before switching to DDR mode for
HS400 mode.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
	- None.
---
 drivers/mmc/mmc-uclass.c | 15 +++++++++++++++
 drivers/mmc/mmc.c        |  2 ++
 include/mmc.h            | 15 ++++++++++++++-
 3 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index b9f0880..240b205 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -141,6 +141,21 @@ int mmc_set_enhanced_strobe(struct mmc *mmc)
 }
 #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);
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index a18e75d..e396207 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1987,6 +1987,8 @@ static int mmc_select_hs400(struct mmc *mmc)
 	/* Set back to HS */
 	mmc_set_card_speed(mmc, MMC_HS, true);
 
+	mmc_hs400_prepare_ddr(mmc);
+
 	err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
 			 EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_FLAG);
 	if (err)
diff --git a/include/mmc.h b/include/mmc.h
index 2399cc2..659df75 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -513,6 +513,14 @@ struct dm_mmc_ops {
 	 * @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)
@@ -540,7 +548,7 @@ 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,
@@ -552,6 +560,11 @@ struct mmc_ops {
 	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 {
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [v2, 07/11] mmc: fsl_esdhc: support eMMC HS400 mode
  2020-07-17  8:50 [v2, 00/11] mmc: fsl_esdhc: support eMMC HS200/HS400 modes Yangbo Lu
                   ` (5 preceding siblings ...)
  2020-07-17  8:50 ` [v2, 06/11] mmc: add a mmc_hs400_prepare_ddr() interface Yangbo Lu
@ 2020-07-17  8:50 ` Yangbo Lu
  2020-07-20  1:41   ` Peng Fan
  2020-07-17  8:50 ` [v2, 08/11] mmc: fsl_esdhc: fix mmc->clock with actual clock Yangbo Lu
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Yangbo Lu @ 2020-07-17  8:50 UTC (permalink / raw)
  To: u-boot

The process for eMMC HS400 mode for eSDHC is,

1. Perform the Tuning Process at the HS400 target operating frequency.
   Latched the clock division value.
2. if read transaction, then set the SDTIMNGCTL[FLW_CTL_BG].
3. Switch to High Speed mode and then set the card clock frequency to
   a value not greater than 52Mhz
4. Clear TBCTL[TB_EN],tuning block enable bit.
5. Change to 8 bit DDR Mode
6. Switch the card to HS400 mode.
7. Set TBCTL[TB_EN], tuning block enable bit.
8. Clear SYSCTL[SDCLKEN]
9. Wait for PRSSTAT[SDSTB] to be set
10. Change the clock division to latched value.Set TBCTL[HS 400 mode]
    and Set SDCLKCTL[CMD_CLK_CTRL]
11. Set SYSCTL[SDCLKEN]
12. Wait for PRSSTAT[SDSTB] to be set
13. Set DLLCFG0[DLL_ENABLE] and DLLCFG0[DLL_FREQ_SEL].
14. Wait for delay chain to lock.
15. Set TBCTL[HS400_WNDW_ADJUST]
16. Again clear SYSCTL[SDCLKEN]
17. Wait for PRSSTAT[SDSTB] to be set
18. Set ESDHCCTL[FAF]
19. Wait for ESDHCCTL[FAF] to be cleared
20. Set SYSCTL[SDCLKEN]
21. Wait for PRSSTAT[SDSTB] to be set.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
	- None.
---
 drivers/mmc/fsl_esdhc.c | 98 ++++++++++++++++++++++++++++++++-----------------
 include/fsl_esdhc.h     | 12 ++++++
 2 files changed, 76 insertions(+), 34 deletions(-)

diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index 607b420..c1a127c 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -62,7 +62,12 @@ struct fsl_esdhc {
 	uint    hostcapblt2;	/* Host controller capabilities register 2 */
 	char	reserved6[8];	/* reserved */
 	uint	tbctl;		/* Tuning block control register */
-	char    reserved7[744];	/* reserved */
+	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 */
 };
 
@@ -568,6 +573,38 @@ static void esdhc_clock_control(struct fsl_esdhc_priv *priv, bool enable)
 	}
 }
 
+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_set_timing(struct fsl_esdhc_priv *priv, enum bus_mode mode)
 {
 	struct fsl_esdhc *regs = priv->esdhc_regs;
@@ -577,7 +614,17 @@ static void esdhc_set_timing(struct fsl_esdhc_priv *priv, enum bus_mode mode)
 	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);
 
+		esdhc_setbits32(&regs->dllcfg0, DLL_ENABLE | DLL_FREQ_SEL);
+		esdhc_setbits32(&regs->tbctl, HS400_WNDW_ADJUST);
+
+		esdhc_clock_control(priv, false);
+		esdhc_flush_async_fifo(priv);
+	}
 	esdhc_clock_control(priv, true);
 }
 
@@ -592,6 +639,9 @@ static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
 		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);
@@ -987,38 +1037,6 @@ static int fsl_esdhc_reinit(struct udevice *dev)
 }
 
 #ifdef MMC_SUPPORTS_TUNING
-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 int fsl_esdhc_execute_tuning(struct udevice *dev, uint32_t opcode)
 {
 	struct fsl_esdhc_plat *plat = dev_get_platdata(dev);
@@ -1046,8 +1064,11 @@ static int fsl_esdhc_execute_tuning(struct udevice *dev, uint32_t opcode)
 
 	esdhc_write32(&regs->irqstaten, irqstaten);
 
-	if (i != MAX_TUNING_LOOP)
+	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);
@@ -1057,6 +1078,14 @@ static int fsl_esdhc_execute_tuning(struct udevice *dev, uint32_t opcode)
 }
 #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,
@@ -1065,6 +1094,7 @@ static const struct dm_mmc_ops fsl_esdhc_ops = {
 	.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/include/fsl_esdhc.h b/include/fsl_esdhc.h
index ada95bc..cbb2c34 100644
--- a/include/fsl_esdhc.h
+++ b/include/fsl_esdhc.h
@@ -176,6 +176,18 @@
 
 /* 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
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [v2, 08/11] mmc: fsl_esdhc: fix mmc->clock with actual clock
  2020-07-17  8:50 [v2, 00/11] mmc: fsl_esdhc: support eMMC HS200/HS400 modes Yangbo Lu
                   ` (6 preceding siblings ...)
  2020-07-17  8:50 ` [v2, 07/11] mmc: fsl_esdhc: support eMMC HS400 mode Yangbo Lu
@ 2020-07-17  8:50 ` Yangbo Lu
  2020-07-17  8:50 ` [v2, 09/11] mmc: fsl_esdhc: fix eMMC HS400 stability issue Yangbo Lu
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Yangbo Lu @ 2020-07-17  8:50 UTC (permalink / raw)
  To: u-boot

Fix mmc->clock with actual clock which is divided by the
controller, and record it with priv->clock which was removed
accidentally.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
	- Added this patch.
---
 drivers/mmc/fsl_esdhc.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index c1a127c..8999b74 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -523,6 +523,9 @@ static void set_sysctl(struct fsl_esdhc_priv *priv, struct mmc *mmc, uint clock)
 	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;
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [v2, 09/11] mmc: fsl_esdhc: fix eMMC HS400 stability issue
  2020-07-17  8:50 [v2, 00/11] mmc: fsl_esdhc: support eMMC HS200/HS400 modes Yangbo Lu
                   ` (7 preceding siblings ...)
  2020-07-17  8:50 ` [v2, 08/11] mmc: fsl_esdhc: fix mmc->clock with actual clock Yangbo Lu
@ 2020-07-17  8:50 ` Yangbo Lu
  2020-07-17  8:50 ` [v2, 10/11] arm: dts: lx2160ardb: support eMMC HS400 mode Yangbo Lu
  2020-07-17  8:50 ` [v2, 11/11] configs: lx2160ardb: enable eMMC HS400 mode support Yangbo Lu
  10 siblings, 0 replies; 23+ messages in thread
From: Yangbo Lu @ 2020-07-17  8:50 UTC (permalink / raw)
  To: u-boot

There was a fix-up for eMMC HS400 stability issue in Linux.

Patch link:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/
commit/?id=58d0bf843b49fa99588ac9f85178bd8dfd651b53

Description:
Currently only LX2160A eSDHC supports eMMC HS400. According to
a large number of tests, eMMC HS400 failed to work at 150MHz,
and for a few boards failed to work at 175MHz. But eMMC HS400
worked fine on 200MHz. We hadn't found the root cause but
setting eSDHC_DLLCFG0[DLL_FREQ_SEL] = 0 using slow delay chain
seemed to resovle this issue. Let's use this as fixup for now.

Introduce the fix-up in u-boot since the issue could be reproduced
in u-boot too.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
	- Added this patch.
---
 drivers/mmc/fsl_esdhc.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index 8999b74..0879739 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -622,7 +622,10 @@ static void esdhc_set_timing(struct fsl_esdhc_priv *priv, enum bus_mode mode)
 		esdhc_setbits32(&regs->sdclkctl, CMD_CLK_CTL);
 		esdhc_clock_control(priv, true);
 
-		esdhc_setbits32(&regs->dllcfg0, DLL_ENABLE | DLL_FREQ_SEL);
+		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);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [v2, 10/11] arm: dts: lx2160ardb: support eMMC HS400 mode
  2020-07-17  8:50 [v2, 00/11] mmc: fsl_esdhc: support eMMC HS200/HS400 modes Yangbo Lu
                   ` (8 preceding siblings ...)
  2020-07-17  8:50 ` [v2, 09/11] mmc: fsl_esdhc: fix eMMC HS400 stability issue Yangbo Lu
@ 2020-07-17  8:50 ` Yangbo Lu
  2020-07-20  1:44   ` Peng Fan
  2020-07-17  8:50 ` [v2, 11/11] configs: lx2160ardb: enable eMMC HS400 mode support Yangbo Lu
  10 siblings, 1 reply; 23+ messages in thread
From: Yangbo Lu @ 2020-07-17  8:50 UTC (permalink / raw)
  To: u-boot

Add properties related to eMMC HS400 mode.

mmc-hs400-1_8v;
bus-width = <8>;

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
	- None.
---
 arch/arm/dts/fsl-lx2160a-rdb.dts | 2 ++
 1 file changed, 2 insertions(+)

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 {
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [v2, 11/11] configs: lx2160ardb: enable eMMC HS400 mode support
  2020-07-17  8:50 [v2, 00/11] mmc: fsl_esdhc: support eMMC HS200/HS400 modes Yangbo Lu
                   ` (9 preceding siblings ...)
  2020-07-17  8:50 ` [v2, 10/11] arm: dts: lx2160ardb: support eMMC HS400 mode Yangbo Lu
@ 2020-07-17  8:50 ` Yangbo Lu
  10 siblings, 0 replies; 23+ messages in thread
From: Yangbo Lu @ 2020-07-17  8:50 UTC (permalink / raw)
  To: u-boot

Enable eMMC HS400 mode support on LX2160ARDB.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
	- None.
---
 configs/lx2160ardb_tfa_SECURE_BOOT_defconfig | 1 +
 configs/lx2160ardb_tfa_defconfig             | 1 +
 configs/lx2160ardb_tfa_stmm_defconfig        | 1 +
 3 files changed, 3 insertions(+)

diff --git a/configs/lx2160ardb_tfa_SECURE_BOOT_defconfig b/configs/lx2160ardb_tfa_SECURE_BOOT_defconfig
index 12e224f..6c65853 100644
--- a/configs/lx2160ardb_tfa_SECURE_BOOT_defconfig
+++ b/configs/lx2160ardb_tfa_SECURE_BOOT_defconfig
@@ -40,6 +40,7 @@ CONFIG_DM_I2C=y
 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 a5c78d2..a5c60c8 100644
--- a/configs/lx2160ardb_tfa_defconfig
+++ b/configs/lx2160ardb_tfa_defconfig
@@ -46,6 +46,7 @@ CONFIG_DM_I2C=y
 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 e97c9b0..869d4e2 100644
--- a/configs/lx2160ardb_tfa_stmm_defconfig
+++ b/configs/lx2160ardb_tfa_stmm_defconfig
@@ -48,6 +48,7 @@ CONFIG_DM_I2C=y
 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
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [v2, 01/11] mmc: add a reinit() API
  2020-07-17  8:50 ` [v2, 01/11] mmc: add a reinit() API Yangbo Lu
@ 2020-07-20  1:33   ` Peng Fan
  2020-07-20  7:10     ` Y.b. Lu
  0 siblings, 1 reply; 23+ messages in thread
From: Peng Fan @ 2020-07-20  1:33 UTC (permalink / raw)
  To: u-boot

> Subject: [v2, 01/11] mmc: add a reinit() API
> 
> For DM_MMC, the controller re-initialization is needed to clear old
> configuration for mmc rescan.
> 
> Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
> ---
> Changes for v2:
> 	- None.
> ---
>  drivers/mmc/mmc-uclass.c | 15 +++++++++++++++
>  drivers/mmc/mmc.c        |  8 ++++++--
>  include/mmc.h            | 10 ++++++++++
>  3 files changed, 31 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c index
> c5b7872..b9f0880 100644
> --- a/drivers/mmc/mmc-uclass.c
> +++ b/drivers/mmc/mmc-uclass.c
> @@ -170,6 +170,21 @@ int mmc_deferred_probe(struct mmc *mmc)
>  	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
> 50f47d4..a53f93a 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -2813,13 +2813,17 @@ int mmc_get_op_cond(struct mmc *mmc)
>  		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.

You mean cmd "mmc rescan" ?

> +	 */
> +	err = mmc_reinit(mmc);

Probe could not provide what you need? You need a different settings?

Regards,
Peng.

>  #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/include/mmc.h b/include/mmc.h index 8256219..161b8bc 100644
> --- a/include/mmc.h
> +++ b/include/mmc.h
> @@ -422,6 +422,14 @@ struct dm_mmc_ops {
>  	 */
>  	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
> @@ -518,6 +526,7 @@ int dm_mmc_execute_tuning(struct udevice *dev,
> uint opcode);  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,6 +538,7 @@ int
> mmc_wait_dat0(struct mmc *mmc, int state, int timeout_us);  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);
> 
>  #else
> --
> 2.7.4

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [v2, 05/11] mmc: add a hs400_tuning flag
  2020-07-17  8:50 ` [v2, 05/11] mmc: add a hs400_tuning flag Yangbo Lu
@ 2020-07-20  1:36   ` Peng Fan
  2020-07-20  7:30     ` Y.b. Lu
  0 siblings, 1 reply; 23+ messages in thread
From: Peng Fan @ 2020-07-20  1:36 UTC (permalink / raw)
  To: u-boot

> Subject: [v2, 05/11] mmc: add a hs400_tuning flag
> 
> Add a hs400_tuning flag to identify the tuning for HS400 mode.

Why? Please explain a bit more.

Thanks,
Peng.

> 
> Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
> ---
> Changes for v2:
> 	- None.
> ---
>  drivers/mmc/mmc.c | 2 ++
>  include/mmc.h     | 1 +
>  2 files changed, 3 insertions(+)
> 
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index
> a53f93a..a18e75d 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -1976,7 +1976,9 @@ static int mmc_select_hs400(struct mmc *mmc)
>  	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;
> diff --git a/include/mmc.h b/include/mmc.h index 161b8bc..2399cc2 100644
> --- a/include/mmc.h
> +++ b/include/mmc.h
> @@ -707,6 +707,7 @@ struct mmc {
>  				  * accessing the boot partitions
>  				  */
>  	u32 quirks;
> +	u8 hs400_tuning;
>  };
> 
>  struct mmc_hwpart_conf {
> --
> 2.7.4

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [v2, 06/11] mmc: add a mmc_hs400_prepare_ddr() interface
  2020-07-17  8:50 ` [v2, 06/11] mmc: add a mmc_hs400_prepare_ddr() interface Yangbo Lu
@ 2020-07-20  1:40   ` Peng Fan
  2020-07-20  7:46     ` Y.b. Lu
  0 siblings, 1 reply; 23+ messages in thread
From: Peng Fan @ 2020-07-20  1:40 UTC (permalink / raw)
  To: u-boot

> Subject: [v2, 06/11] mmc: add a mmc_hs400_prepare_ddr() interface
> 
> Add a mmc_hs400_prepare_ddr() interface for controllers which needs
> preparation before switching to DDR mode for
> HS400 mode.

This is LSx specific? If yes, could this be done in fsl_esdhc.c?

Thanks,
Peng.

> 
> Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
> ---
> Changes for v2:
> 	- None.
> ---
>  drivers/mmc/mmc-uclass.c | 15 +++++++++++++++
>  drivers/mmc/mmc.c        |  2 ++
>  include/mmc.h            | 15 ++++++++++++++-
>  3 files changed, 31 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c index
> b9f0880..240b205 100644
> --- a/drivers/mmc/mmc-uclass.c
> +++ b/drivers/mmc/mmc-uclass.c
> @@ -141,6 +141,21 @@ int mmc_set_enhanced_strobe(struct mmc
> *mmc)  }  #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); diff --git
> a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index a18e75d..e396207
> 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -1987,6 +1987,8 @@ static int mmc_select_hs400(struct mmc *mmc)
>  	/* Set back to HS */
>  	mmc_set_card_speed(mmc, MMC_HS, true);
> 
> +	mmc_hs400_prepare_ddr(mmc);
> +
>  	err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
> EXT_CSD_BUS_WIDTH,
>  			 EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_FLAG);
>  	if (err)
> diff --git a/include/mmc.h b/include/mmc.h index 2399cc2..659df75 100644
> --- a/include/mmc.h
> +++ b/include/mmc.h
> @@ -513,6 +513,14 @@ struct dm_mmc_ops {
>  	 * @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)
> @@ -540,7 +548,7 @@ 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,
> @@ -552,6 +560,11 @@ struct mmc_ops {
>  	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 {
> --
> 2.7.4

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [v2, 07/11] mmc: fsl_esdhc: support eMMC HS400 mode
  2020-07-17  8:50 ` [v2, 07/11] mmc: fsl_esdhc: support eMMC HS400 mode Yangbo Lu
@ 2020-07-20  1:41   ` Peng Fan
  2020-07-20  7:49     ` Y.b. Lu
  0 siblings, 1 reply; 23+ messages in thread
From: Peng Fan @ 2020-07-20  1:41 UTC (permalink / raw)
  To: u-boot

> Subject: [v2, 07/11] mmc: fsl_esdhc: support eMMC HS400 mode
> 
> The process for eMMC HS400 mode for eSDHC is,
> 
> 1. Perform the Tuning Process at the HS400 target operating frequency.
>    Latched the clock division value.
> 2. if read transaction, then set the SDTIMNGCTL[FLW_CTL_BG].
> 3. Switch to High Speed mode and then set the card clock frequency to
>    a value not greater than 52Mhz
> 4. Clear TBCTL[TB_EN],tuning block enable bit.
> 5. Change to 8 bit DDR Mode
> 6. Switch the card to HS400 mode.
> 7. Set TBCTL[TB_EN], tuning block enable bit.
> 8. Clear SYSCTL[SDCLKEN]
> 9. Wait for PRSSTAT[SDSTB] to be set
> 10. Change the clock division to latched value.Set TBCTL[HS 400 mode]
>     and Set SDCLKCTL[CMD_CLK_CTRL]
> 11. Set SYSCTL[SDCLKEN]
> 12. Wait for PRSSTAT[SDSTB] to be set
> 13. Set DLLCFG0[DLL_ENABLE] and DLLCFG0[DLL_FREQ_SEL].
> 14. Wait for delay chain to lock.
> 15. Set TBCTL[HS400_WNDW_ADJUST]
> 16. Again clear SYSCTL[SDCLKEN]
> 17. Wait for PRSSTAT[SDSTB] to be set
> 18. Set ESDHCCTL[FAF]
> 19. Wait for ESDHCCTL[FAF] to be cleared 20. Set SYSCTL[SDCLKEN] 21. Wait
> for PRSSTAT[SDSTB] to be set.
> 
> Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
> ---
> Changes for v2:
> 	- None.
> ---
>  drivers/mmc/fsl_esdhc.c | 98
> ++++++++++++++++++++++++++++++++-----------------
>  include/fsl_esdhc.h     | 12 ++++++
>  2 files changed, 76 insertions(+), 34 deletions(-)
> 
> diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index
> 607b420..c1a127c 100644
> --- a/drivers/mmc/fsl_esdhc.c
> +++ b/drivers/mmc/fsl_esdhc.c
> @@ -62,7 +62,12 @@ struct fsl_esdhc {
>  	uint    hostcapblt2;	/* Host controller capabilities register 2 */
>  	char	reserved6[8];	/* reserved */
>  	uint	tbctl;		/* Tuning block control register */
> -	char    reserved7[744];	/* reserved */
> +	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 */
>  };
> 
> @@ -568,6 +573,38 @@ static void esdhc_clock_control(struct
> fsl_esdhc_priv *priv, bool enable)
>  	}
>  }
> 
> +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_set_timing(struct fsl_esdhc_priv *priv, enum bus_mode
> mode)  {
>  	struct fsl_esdhc *regs = priv->esdhc_regs; @@ -577,7 +614,17 @@
> static void esdhc_set_timing(struct fsl_esdhc_priv *priv, enum bus_mode
> mode)
>  	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);
> 
> +		esdhc_setbits32(&regs->dllcfg0, DLL_ENABLE | DLL_FREQ_SEL);
> +		esdhc_setbits32(&regs->tbctl, HS400_WNDW_ADJUST);
> +
> +		esdhc_clock_control(priv, false);
> +		esdhc_flush_async_fifo(priv);
> +	}
>  	esdhc_clock_control(priv, true);
>  }
> 
> @@ -592,6 +639,9 @@ static int esdhc_set_ios_common(struct
> fsl_esdhc_priv *priv, struct mmc *mmc)
>  		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);
> @@ -987,38 +1037,6 @@ static int fsl_esdhc_reinit(struct udevice *dev)  }
> 
>  #ifdef MMC_SUPPORTS_TUNING
> -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 int fsl_esdhc_execute_tuning(struct udevice *dev, uint32_t opcode)  {
>  	struct fsl_esdhc_plat *plat = dev_get_platdata(dev); @@ -1046,8
> +1064,11 @@ static int fsl_esdhc_execute_tuning(struct udevice *dev,
> uint32_t opcode)
> 
>  	esdhc_write32(&regs->irqstaten, irqstaten);
> 
> -	if (i != MAX_TUNING_LOOP)
> +	if (i != MAX_TUNING_LOOP) {
> +		if (plat->mmc.hs400_tuning)

Ok, it is used here, but I not see the benefit putting hs400_tunning into common
mmc structure.

Regards,
Peng.

> +			esdhc_setbits32(&regs->sdtimingctl, FLW_CTL_BG);
>  		return 0;
> +	}
> 
>  	printf("fsl_esdhc: tuning failed!\n");
>  	esdhc_clrbits32(&regs->autoc12err, SMPCLKSEL); @@ -1057,6 +1078,14
> @@ static int fsl_esdhc_execute_tuning(struct udevice *dev, uint32_t
> opcode)  }  #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,
> @@ -1065,6 +1094,7 @@ static const struct dm_mmc_ops fsl_esdhc_ops = {
>  	.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/include/fsl_esdhc.h b/include/fsl_esdhc.h index ada95bc..cbb2c34 100644
> --- a/include/fsl_esdhc.h
> +++ b/include/fsl_esdhc.h
> @@ -176,6 +176,18 @@
> 
>  /* 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
> 
> --
> 2.7.4

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [v2, 10/11] arm: dts: lx2160ardb: support eMMC HS400 mode
  2020-07-17  8:50 ` [v2, 10/11] arm: dts: lx2160ardb: support eMMC HS400 mode Yangbo Lu
@ 2020-07-20  1:44   ` Peng Fan
  2020-07-20  7:52     ` Y.b. Lu
  0 siblings, 1 reply; 23+ messages in thread
From: Peng Fan @ 2020-07-20  1:44 UTC (permalink / raw)
  To: u-boot

> Subject: [v2, 10/11] arm: dts: lx2160ardb: support eMMC HS400 mode
> 
> Add properties related to eMMC HS400 mode.
> 
> mmc-hs400-1_8v;
> bus-width = <8>;
> 
> Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
> ---
> Changes for v2:
> 	- None.
> ---
>  arch/arm/dts/fsl-lx2160a-rdb.dts | 2 ++
>  1 file changed, 2 insertions(+)
> 
> 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>;

If kernel already has this, please add kernel commit.
If not, please use fsl-lx2160a-rdb-u-boot.dtsi to include.

Regards,
Peng.

>  };
> 
>  &fspi {
> --
> 2.7.4

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [v2, 01/11] mmc: add a reinit() API
  2020-07-20  1:33   ` Peng Fan
@ 2020-07-20  7:10     ` Y.b. Lu
  0 siblings, 0 replies; 23+ messages in thread
From: Y.b. Lu @ 2020-07-20  7:10 UTC (permalink / raw)
  To: u-boot

Hi Peng,

> -----Original Message-----
> From: Peng Fan <peng.fan@nxp.com>
> Sent: Monday, July 20, 2020 9:33 AM
> To: Y.b. Lu <yangbo.lu@nxp.com>; u-boot at lists.denx.de; Priyanka Jain
> <priyanka.jain@nxp.com>; 'Jaehoon Chung' <jh80.chung@samsung.com>
> Cc: Y.b. Lu <yangbo.lu@nxp.com>
> Subject: RE: [v2, 01/11] mmc: add a reinit() API
> 
> > Subject: [v2, 01/11] mmc: add a reinit() API
> >
> > For DM_MMC, the controller re-initialization is needed to clear old
> > configuration for mmc rescan.
> >
> > Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
> > ---
> > Changes for v2:
> > 	- None.
> > ---
> >  drivers/mmc/mmc-uclass.c | 15 +++++++++++++++
> >  drivers/mmc/mmc.c        |  8 ++++++--
> >  include/mmc.h            | 10 ++++++++++
> >  3 files changed, 31 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c index
> > c5b7872..b9f0880 100644
> > --- a/drivers/mmc/mmc-uclass.c
> > +++ b/drivers/mmc/mmc-uclass.c
> > @@ -170,6 +170,21 @@ int mmc_deferred_probe(struct mmc *mmc)
> >  	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
> > 50f47d4..a53f93a 100644
> > --- a/drivers/mmc/mmc.c
> > +++ b/drivers/mmc/mmc.c
> > @@ -2813,13 +2813,17 @@ int mmc_get_op_cond(struct mmc *mmc)
> >  		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.
> 
> You mean cmd "mmc rescan" ?

Yes. The flag has_init is being used to skip the reinitialization if the card has been initialized once.
Going through the mmc driver, the only place where we want to actually and completely reinitialize the SD card is "mmc rescan".
For "mmc rescan", before sending CMD0 to reset card, the controller is still needed to be reset/re-initialized.
Otherwise the controller may be still in previous status (registers setting) communicating with the card.

> 
> > +	 */
> > +	err = mmc_reinit(mmc);
> 
> Probe could not provide what you need? You need a different settings?

Probe is called only once. The controller still needs to be reset/re-initialized to clean all previous registers setting, before sending CMD0 for mmc rescan.
For example, the eSDHC controller is now in 8-bit 200MHz eMMC HS400 mode (in tuning mode).
When we want mmc rescan to completely reinitialize the card starting from CMD0, we needs to reset/re-initialize the controller to clean previous HS400 mode setting.

> 
> Regards,
> Peng.
> 
> >  #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/include/mmc.h b/include/mmc.h index 8256219..161b8bc
> 100644
> > --- a/include/mmc.h
> > +++ b/include/mmc.h
> > @@ -422,6 +422,14 @@ struct dm_mmc_ops {
> >  	 */
> >  	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
> > @@ -518,6 +526,7 @@ int dm_mmc_execute_tuning(struct udevice *dev,
> > uint opcode);  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,6 +538,7 @@ int
> > mmc_wait_dat0(struct mmc *mmc, int state, int timeout_us);  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);
> >
> >  #else
> > --
> > 2.7.4

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [v2, 05/11] mmc: add a hs400_tuning flag
  2020-07-20  1:36   ` Peng Fan
@ 2020-07-20  7:30     ` Y.b. Lu
  0 siblings, 0 replies; 23+ messages in thread
From: Y.b. Lu @ 2020-07-20  7:30 UTC (permalink / raw)
  To: u-boot

Hi Peng,

> -----Original Message-----
> From: Peng Fan <peng.fan@nxp.com>
> Sent: Monday, July 20, 2020 9:37 AM
> To: Y.b. Lu <yangbo.lu@nxp.com>; u-boot at lists.denx.de; Priyanka Jain
> <priyanka.jain@nxp.com>; 'Jaehoon Chung' <jh80.chung@samsung.com>
> Cc: Y.b. Lu <yangbo.lu@nxp.com>
> Subject: RE: [v2, 05/11] mmc: add a hs400_tuning flag
> 
> > Subject: [v2, 05/11] mmc: add a hs400_tuning flag
> >
> > Add a hs400_tuning flag to identify the tuning for HS400 mode.
> 
> Why? Please explain a bit more.

Some specific controllers may have difference between HS400 tuning and HS200 tuning.
For eSDHC, as you saw in my patch #7, and there are also some eSDHC errata related to HS400 tuning which I will upstream patches in the future.
In kernel drivers/mmc/host/sdhci.c, there is a flag SDHCI_HS400_TUNING used by sdhci-msm.c and sdhci-of-esdhc.c for specific handling.
I will explain more in commit message.

> 
> Thanks,
> Peng.
> 
> >
> > Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
> > ---
> > Changes for v2:
> > 	- None.
> > ---
> >  drivers/mmc/mmc.c | 2 ++
> >  include/mmc.h     | 1 +
> >  2 files changed, 3 insertions(+)
> >
> > diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index
> > a53f93a..a18e75d 100644
> > --- a/drivers/mmc/mmc.c
> > +++ b/drivers/mmc/mmc.c
> > @@ -1976,7 +1976,9 @@ static int mmc_select_hs400(struct mmc *mmc)
> >  	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;
> > diff --git a/include/mmc.h b/include/mmc.h index 161b8bc..2399cc2 100644
> > --- a/include/mmc.h
> > +++ b/include/mmc.h
> > @@ -707,6 +707,7 @@ struct mmc {
> >  				  * accessing the boot partitions
> >  				  */
> >  	u32 quirks;
> > +	u8 hs400_tuning;
> >  };
> >
> >  struct mmc_hwpart_conf {
> > --
> > 2.7.4

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [v2, 06/11] mmc: add a mmc_hs400_prepare_ddr() interface
  2020-07-20  1:40   ` Peng Fan
@ 2020-07-20  7:46     ` Y.b. Lu
  0 siblings, 0 replies; 23+ messages in thread
From: Y.b. Lu @ 2020-07-20  7:46 UTC (permalink / raw)
  To: u-boot

Hi Peng,

> -----Original Message-----
> From: Peng Fan <peng.fan@nxp.com>
> Sent: Monday, July 20, 2020 9:40 AM
> To: Y.b. Lu <yangbo.lu@nxp.com>; u-boot at lists.denx.de; Priyanka Jain
> <priyanka.jain@nxp.com>; 'Jaehoon Chung' <jh80.chung@samsung.com>
> Cc: Y.b. Lu <yangbo.lu@nxp.com>
> Subject: RE: [v2, 06/11] mmc: add a mmc_hs400_prepare_ddr() interface
> 
> > Subject: [v2, 06/11] mmc: add a mmc_hs400_prepare_ddr() interface
> >
> > Add a mmc_hs400_prepare_ddr() interface for controllers which needs
> > preparation before switching to DDR mode for
> > HS400 mode.
> 
> This is LSx specific? If yes, could this be done in fsl_esdhc.c?

Yes. Actually I desire to put these esdhc specific setting in its own driver too.
However the HS400 procedure of esdhc indeed break the standard process.
As you see in my patch #7 commit message, the tuning block has to be disabled after switching to HS and before switching to DDR.

> 3. Switch to High Speed mode and then set the card clock frequency to
>    a value not greater than 52Mhz
> 4. Clear TBCTL[TB_EN],tuning block enable bit.
> 5. Change to 8 bit DDR Mode

I have to make code changed as below expecting some controllers drivers may utilize mmc_hs400_prepare_ddr() too.
We had done same thing in linux too. (cc14eec mmc: core: Add ->hs400_prepare_ddr() callback)
Do you have any suggestion?

mmc_set_card_speed(mmc, MMC_HS, true);

+	mmc_hs400_prepare_ddr(mmc);
+
err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
               EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_FLAG);

Thanks.

> 
> Thanks,
> Peng.
> 
> >
> > Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
> > ---
> > Changes for v2:
> > 	- None.
> > ---
> >  drivers/mmc/mmc-uclass.c | 15 +++++++++++++++
> >  drivers/mmc/mmc.c        |  2 ++
> >  include/mmc.h            | 15 ++++++++++++++-
> >  3 files changed, 31 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c index
> > b9f0880..240b205 100644
> > --- a/drivers/mmc/mmc-uclass.c
> > +++ b/drivers/mmc/mmc-uclass.c
> > @@ -141,6 +141,21 @@ int mmc_set_enhanced_strobe(struct mmc
> > *mmc)  }  #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); diff --git
> > a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index a18e75d..e396207
> > 100644
> > --- a/drivers/mmc/mmc.c
> > +++ b/drivers/mmc/mmc.c
> > @@ -1987,6 +1987,8 @@ static int mmc_select_hs400(struct mmc *mmc)
> >  	/* Set back to HS */
> >  	mmc_set_card_speed(mmc, MMC_HS, true);
> >
> > +	mmc_hs400_prepare_ddr(mmc);
> > +
> >  	err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
> > EXT_CSD_BUS_WIDTH,
> >  			 EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_FLAG);
> >  	if (err)
> > diff --git a/include/mmc.h b/include/mmc.h index 2399cc2..659df75 100644
> > --- a/include/mmc.h
> > +++ b/include/mmc.h
> > @@ -513,6 +513,14 @@ struct dm_mmc_ops {
> >  	 * @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)
> > @@ -540,7 +548,7 @@ 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,
> > @@ -552,6 +560,11 @@ struct mmc_ops {
> >  	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 {
> > --
> > 2.7.4

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [v2, 07/11] mmc: fsl_esdhc: support eMMC HS400 mode
  2020-07-20  1:41   ` Peng Fan
@ 2020-07-20  7:49     ` Y.b. Lu
  0 siblings, 0 replies; 23+ messages in thread
From: Y.b. Lu @ 2020-07-20  7:49 UTC (permalink / raw)
  To: u-boot

Hi Peng,

> -----Original Message-----
> From: Peng Fan <peng.fan@nxp.com>
> Sent: Monday, July 20, 2020 9:42 AM
> To: Y.b. Lu <yangbo.lu@nxp.com>; u-boot at lists.denx.de; Priyanka Jain
> <priyanka.jain@nxp.com>; 'Jaehoon Chung' <jh80.chung@samsung.com>
> Cc: Y.b. Lu <yangbo.lu@nxp.com>
> Subject: RE: [v2, 07/11] mmc: fsl_esdhc: support eMMC HS400 mode
> 
> > Subject: [v2, 07/11] mmc: fsl_esdhc: support eMMC HS400 mode
> >
> > The process for eMMC HS400 mode for eSDHC is,
> >
> > 1. Perform the Tuning Process at the HS400 target operating frequency.
> >    Latched the clock division value.
> > 2. if read transaction, then set the SDTIMNGCTL[FLW_CTL_BG].
> > 3. Switch to High Speed mode and then set the card clock frequency to
> >    a value not greater than 52Mhz
> > 4. Clear TBCTL[TB_EN],tuning block enable bit.
> > 5. Change to 8 bit DDR Mode
> > 6. Switch the card to HS400 mode.
> > 7. Set TBCTL[TB_EN], tuning block enable bit.
> > 8. Clear SYSCTL[SDCLKEN]
> > 9. Wait for PRSSTAT[SDSTB] to be set
> > 10. Change the clock division to latched value.Set TBCTL[HS 400 mode]
> >     and Set SDCLKCTL[CMD_CLK_CTRL]
> > 11. Set SYSCTL[SDCLKEN]
> > 12. Wait for PRSSTAT[SDSTB] to be set
> > 13. Set DLLCFG0[DLL_ENABLE] and DLLCFG0[DLL_FREQ_SEL].
> > 14. Wait for delay chain to lock.
> > 15. Set TBCTL[HS400_WNDW_ADJUST]
> > 16. Again clear SYSCTL[SDCLKEN]
> > 17. Wait for PRSSTAT[SDSTB] to be set
> > 18. Set ESDHCCTL[FAF]
> > 19. Wait for ESDHCCTL[FAF] to be cleared 20. Set SYSCTL[SDCLKEN] 21. Wait
> > for PRSSTAT[SDSTB] to be set.
> >
> > Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
> > ---
> > Changes for v2:
> > 	- None.
> > ---
> >  drivers/mmc/fsl_esdhc.c | 98
> > ++++++++++++++++++++++++++++++++-----------------
> >  include/fsl_esdhc.h     | 12 ++++++
> >  2 files changed, 76 insertions(+), 34 deletions(-)
> >
> > diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index
> > 607b420..c1a127c 100644
> > --- a/drivers/mmc/fsl_esdhc.c
> > +++ b/drivers/mmc/fsl_esdhc.c
> > @@ -62,7 +62,12 @@ struct fsl_esdhc {
> >  	uint    hostcapblt2;	/* Host controller capabilities register 2 */
> >  	char	reserved6[8];	/* reserved */
> >  	uint	tbctl;		/* Tuning block control register */
> > -	char    reserved7[744];	/* reserved */
> > +	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 */
> >  };
> >
> > @@ -568,6 +573,38 @@ static void esdhc_clock_control(struct
> > fsl_esdhc_priv *priv, bool enable)
> >  	}
> >  }
> >
> > +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_set_timing(struct fsl_esdhc_priv *priv, enum bus_mode
> > mode)  {
> >  	struct fsl_esdhc *regs = priv->esdhc_regs; @@ -577,7 +614,17 @@
> > static void esdhc_set_timing(struct fsl_esdhc_priv *priv, enum bus_mode
> > mode)
> >  	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);
> >
> > +		esdhc_setbits32(&regs->dllcfg0, DLL_ENABLE | DLL_FREQ_SEL);
> > +		esdhc_setbits32(&regs->tbctl, HS400_WNDW_ADJUST);
> > +
> > +		esdhc_clock_control(priv, false);
> > +		esdhc_flush_async_fifo(priv);
> > +	}
> >  	esdhc_clock_control(priv, true);
> >  }
> >
> > @@ -592,6 +639,9 @@ static int esdhc_set_ios_common(struct
> > fsl_esdhc_priv *priv, struct mmc *mmc)
> >  		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);
> > @@ -987,38 +1037,6 @@ static int fsl_esdhc_reinit(struct udevice *dev)  }
> >
> >  #ifdef MMC_SUPPORTS_TUNING
> > -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 int fsl_esdhc_execute_tuning(struct udevice *dev, uint32_t opcode)
> {
> >  	struct fsl_esdhc_plat *plat = dev_get_platdata(dev); @@ -1046,8
> > +1064,11 @@ static int fsl_esdhc_execute_tuning(struct udevice *dev,
> > uint32_t opcode)
> >
> >  	esdhc_write32(&regs->irqstaten, irqstaten);
> >
> > -	if (i != MAX_TUNING_LOOP)
> > +	if (i != MAX_TUNING_LOOP) {
> > +		if (plat->mmc.hs400_tuning)
> 
> Ok, it is used here, but I not see the benefit putting hs400_tunning into
> common
> mmc structure.

Do you have any suggestion if we don't use a flag to identify HS400 and HS200 tuning in common mmc structure?
Thanks.

> 
> Regards,
> Peng.
> 
> > +			esdhc_setbits32(&regs->sdtimingctl, FLW_CTL_BG);
> >  		return 0;
> > +	}
> >
> >  	printf("fsl_esdhc: tuning failed!\n");
> >  	esdhc_clrbits32(&regs->autoc12err, SMPCLKSEL); @@ -1057,6 +1078,14
> > @@ static int fsl_esdhc_execute_tuning(struct udevice *dev, uint32_t
> > opcode)  }  #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,
> > @@ -1065,6 +1094,7 @@ static const struct dm_mmc_ops fsl_esdhc_ops =
> {
> >  	.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/include/fsl_esdhc.h b/include/fsl_esdhc.h index ada95bc..cbb2c34 100644
> > --- a/include/fsl_esdhc.h
> > +++ b/include/fsl_esdhc.h
> > @@ -176,6 +176,18 @@
> >
> >  /* 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
> >
> > --
> > 2.7.4

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [v2, 10/11] arm: dts: lx2160ardb: support eMMC HS400 mode
  2020-07-20  1:44   ` Peng Fan
@ 2020-07-20  7:52     ` Y.b. Lu
  2020-07-20  8:21       ` Peng Fan
  0 siblings, 1 reply; 23+ messages in thread
From: Y.b. Lu @ 2020-07-20  7:52 UTC (permalink / raw)
  To: u-boot

Hi Peng,

> -----Original Message-----
> From: Peng Fan <peng.fan@nxp.com>
> Sent: Monday, July 20, 2020 9:45 AM
> To: Y.b. Lu <yangbo.lu@nxp.com>; u-boot at lists.denx.de; Priyanka Jain
> <priyanka.jain@nxp.com>; 'Jaehoon Chung' <jh80.chung@samsung.com>
> Cc: Y.b. Lu <yangbo.lu@nxp.com>
> Subject: RE: [v2, 10/11] arm: dts: lx2160ardb: support eMMC HS400 mode
> 
> > Subject: [v2, 10/11] arm: dts: lx2160ardb: support eMMC HS400 mode
> >
> > Add properties related to eMMC HS400 mode.
> >
> > mmc-hs400-1_8v;
> > bus-width = <8>;
> >
> > Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
> > ---
> > Changes for v2:
> > 	- None.
> > ---
> >  arch/arm/dts/fsl-lx2160a-rdb.dts | 2 ++
> >  1 file changed, 2 insertions(+)
> >
> > 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>;
> 
> If kernel already has this, please add kernel commit.
> If not, please use fsl-lx2160a-rdb-u-boot.dtsi to include.

Thanks! Kernel had already has this since the first board dts patch.
b068890 arm64: dts: add LX2160ARDB board support

Do you want me to mention it in commit message?

> 
> Regards,
> Peng.
> 
> >  };
> >
> >  &fspi {
> > --
> > 2.7.4

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [v2, 10/11] arm: dts: lx2160ardb: support eMMC HS400 mode
  2020-07-20  7:52     ` Y.b. Lu
@ 2020-07-20  8:21       ` Peng Fan
  0 siblings, 0 replies; 23+ messages in thread
From: Peng Fan @ 2020-07-20  8:21 UTC (permalink / raw)
  To: u-boot


> Subject: RE: [v2, 10/11] arm: dts: lx2160ardb: support eMMC HS400 mode
> 
> Hi Peng,
> 
> > -----Original Message-----
> > From: Peng Fan <peng.fan@nxp.com>
> > Sent: Monday, July 20, 2020 9:45 AM
> > To: Y.b. Lu <yangbo.lu@nxp.com>; u-boot at lists.denx.de; Priyanka Jain
> > <priyanka.jain@nxp.com>; 'Jaehoon Chung' <jh80.chung@samsung.com>
> > Cc: Y.b. Lu <yangbo.lu@nxp.com>
> > Subject: RE: [v2, 10/11] arm: dts: lx2160ardb: support eMMC HS400 mode
> >
> > > Subject: [v2, 10/11] arm: dts: lx2160ardb: support eMMC HS400 mode
> > >
> > > Add properties related to eMMC HS400 mode.
> > >
> > > mmc-hs400-1_8v;
> > > bus-width = <8>;
> > >
> > > Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
> > > ---
> > > Changes for v2:
> > > 	- None.
> > > ---
> > >  arch/arm/dts/fsl-lx2160a-rdb.dts | 2 ++
> > >  1 file changed, 2 insertions(+)
> > >
> > > 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>;
> >
> > If kernel already has this, please add kernel commit.
> > If not, please use fsl-lx2160a-rdb-u-boot.dtsi to include.
> 
> Thanks! Kernel had already has this since the first board dts patch.
> b068890 arm64: dts: add LX2160ARDB board support
> 
> Do you want me to mention it in commit message?

Yes, please.

Thanks,
Peng.

> 
> >
> > Regards,
> > Peng.
> >
> > >  };
> > >
> > >  &fspi {
> > > --
> > > 2.7.4

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2020-07-20  8:21 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-17  8:50 [v2, 00/11] mmc: fsl_esdhc: support eMMC HS200/HS400 modes Yangbo Lu
2020-07-17  8:50 ` [v2, 01/11] mmc: add a reinit() API Yangbo Lu
2020-07-20  1:33   ` Peng Fan
2020-07-20  7:10     ` Y.b. Lu
2020-07-17  8:50 ` [v2, 02/11] mmc: fsl_esdhc: add a reinit() callback Yangbo Lu
2020-07-17  8:50 ` [v2, 03/11] mmc: fsl_esdhc: support tuning for eMMC HS200 Yangbo Lu
2020-07-17  8:50 ` [v2, 04/11] mmc: fsl_esdhc: clean TBCTL[TB_EN] manually during init Yangbo Lu
2020-07-17  8:50 ` [v2, 05/11] mmc: add a hs400_tuning flag Yangbo Lu
2020-07-20  1:36   ` Peng Fan
2020-07-20  7:30     ` Y.b. Lu
2020-07-17  8:50 ` [v2, 06/11] mmc: add a mmc_hs400_prepare_ddr() interface Yangbo Lu
2020-07-20  1:40   ` Peng Fan
2020-07-20  7:46     ` Y.b. Lu
2020-07-17  8:50 ` [v2, 07/11] mmc: fsl_esdhc: support eMMC HS400 mode Yangbo Lu
2020-07-20  1:41   ` Peng Fan
2020-07-20  7:49     ` Y.b. Lu
2020-07-17  8:50 ` [v2, 08/11] mmc: fsl_esdhc: fix mmc->clock with actual clock Yangbo Lu
2020-07-17  8:50 ` [v2, 09/11] mmc: fsl_esdhc: fix eMMC HS400 stability issue Yangbo Lu
2020-07-17  8:50 ` [v2, 10/11] arm: dts: lx2160ardb: support eMMC HS400 mode Yangbo Lu
2020-07-20  1:44   ` Peng Fan
2020-07-20  7:52     ` Y.b. Lu
2020-07-20  8:21       ` Peng Fan
2020-07-17  8:50 ` [v2, 11/11] configs: lx2160ardb: enable eMMC HS400 mode support Yangbo Lu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.