All of lore.kernel.org
 help / color / mirror / Atom feed
From: Yangbo Lu <yangbo.lu@nxp.com>
To: u-boot@lists.denx.de
Subject: [PATCH 3/9] mmc: fsl_esdhc: support tuning for eMMC HS200
Date: Thu, 16 Jul 2020 10:29:48 +0800	[thread overview]
Message-ID: <20200716022954.36774-4-yangbo.lu@nxp.com> (raw)
In-Reply-To: <20200716022954.36774-1-yangbo.lu@nxp.com>

Support tuning process for eMMC HS200 for eSDHC.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
 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

  parent reply	other threads:[~2020-07-16  2:29 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <CGME20200716023643epcas1p475c3faedb3936066fad28809057a79a8@epcas1p4.samsung.com>
2020-07-16  2:29 ` [PATCH 0/9] mmc: fsl_esdhc: support eMMC HS200/HS400 modes Yangbo Lu
2020-07-16  2:29   ` [PATCH 1/9] mmc: add a reinit() API Yangbo Lu
2020-07-16  2:29   ` [PATCH 2/9] mmc: fsl_esdhc: add a reinit() callback Yangbo Lu
2020-07-16  2:29   ` Yangbo Lu [this message]
2020-07-16  2:29   ` [PATCH 4/9] mmc: fsl_esdhc: clean TBCTL[TB_EN] manually during init Yangbo Lu
2020-07-16  2:29   ` [PATCH 5/9] mmc: add a hs400_tuning flag Yangbo Lu
2020-07-16  2:29   ` [PATCH 6/9] mmc: add a mmc_hs400_prepare_ddr() interface Yangbo Lu
2020-07-16  2:29   ` [PATCH 7/9] mmc: fsl_esdhc: support eMMC HS400 mode Yangbo Lu
2020-07-16  2:29   ` [PATCH 8/9] arm: dts: lx2160ardb: " Yangbo Lu
2020-07-16  2:29   ` [PATCH 9/9] configs: lx2160ardb: enable eMMC HS400 mode support Yangbo Lu
2020-07-17  0:31   ` [PATCH 0/9] mmc: fsl_esdhc: support eMMC HS200/HS400 modes Jaehoon Chung
2020-07-17  8:48     ` Y.b. Lu
2020-07-18  1:21       ` Jaehoon Chung

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200716022954.36774-4-yangbo.lu@nxp.com \
    --to=yangbo.lu@nxp.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.