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(®s->cmdarg, cmd->cmdarg);
esdhc_write32(®s->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(®s->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(®s->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(®s->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(®s->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(®s->esdhcctl, ESDHCCTL_FAF);
+
+ time_out = 20;
+ while (esdhc_read32(®s->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(®s->tbctl, TBCTL_TB_EN);
+ else
+ esdhc_clrbits32(®s->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(®s->autoc12err, EXECUTE_TUNING);
+
+ irqstaten = esdhc_read32(®s->irqstaten);
+ esdhc_write32(®s->irqstaten, IRQSTATEN_BRR);
+
+ for (i = 0; i < MAX_TUNING_LOOP; i++) {
+ mmc_send_tuning(&plat->mmc, opcode, NULL);
+ mdelay(1);
+
+ val = esdhc_read32(®s->autoc12err);
+ if (!(val & EXECUTE_TUNING)) {
+ if (val & SMPCLKSEL)
+ break;
+ }
+ }
+
+ esdhc_write32(®s->irqstaten, irqstaten);
+
+ if (i != MAX_TUNING_LOOP)
+ return 0;
+
+ printf("fsl_esdhc: tuning failed!\n");
+ esdhc_clrbits32(®s->autoc12err, SMPCLKSEL);
+ esdhc_clrbits32(®s->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
next prev 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.