All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 1/2] mmc: tmio: sdhi: Minor macro cleanup
@ 2019-05-19 17:17 Marek Vasut
  2019-05-19 17:17 ` [U-Boot] [PATCH 2/2] mmc: tmio: sdhi: HS400 manual adjustment Marek Vasut
  0 siblings, 1 reply; 2+ messages in thread
From: Marek Vasut @ 2019-05-19 17:17 UTC (permalink / raw)
  To: u-boot

Clean up the whitespaces in macros, no functional change.

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
Cc: Peng Fan <peng.fan@nxp.com>
---
 drivers/mmc/renesas-sdhi.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c
index 6c51ccc294..698ecf69bd 100644
--- a/drivers/mmc/renesas-sdhi.c
+++ b/drivers/mmc/renesas-sdhi.c
@@ -23,21 +23,21 @@
 
 /* SCC registers */
 #define RENESAS_SDHI_SCC_DTCNTL			0x800
-#define   RENESAS_SDHI_SCC_DTCNTL_TAPEN		BIT(0)
-#define   RENESAS_SDHI_SCC_DTCNTL_TAPNUM_SHIFT	16
-#define   RENESAS_SDHI_SCC_DTCNTL_TAPNUM_MASK		0xff
+#define RENESAS_SDHI_SCC_DTCNTL_TAPEN		BIT(0)
+#define RENESAS_SDHI_SCC_DTCNTL_TAPNUM_SHIFT	16
+#define RENESAS_SDHI_SCC_DTCNTL_TAPNUM_MASK	0xff
 #define RENESAS_SDHI_SCC_TAPSET			0x804
 #define RENESAS_SDHI_SCC_DT2FF			0x808
 #define RENESAS_SDHI_SCC_CKSEL			0x80c
-#define   RENESAS_SDHI_SCC_CKSEL_DTSEL		BIT(0)
-#define RENESAS_SDHI_SCC_RVSCNTL			0x810
-#define   RENESAS_SDHI_SCC_RVSCNTL_RVSEN		BIT(0)
+#define RENESAS_SDHI_SCC_CKSEL_DTSEL		BIT(0)
+#define RENESAS_SDHI_SCC_RVSCNTL		0x810
+#define RENESAS_SDHI_SCC_RVSCNTL_RVSEN		BIT(0)
 #define RENESAS_SDHI_SCC_RVSREQ			0x814
-#define   RENESAS_SDHI_SCC_RVSREQ_RVSERR		BIT(2)
+#define RENESAS_SDHI_SCC_RVSREQ_RVSERR		BIT(2)
 #define RENESAS_SDHI_SCC_SMPCMP			0x818
-#define RENESAS_SDHI_SCC_TMPPORT2			0x81c
-#define   RENESAS_SDHI_SCC_TMPPORT2_HS400EN		BIT(31)
-#define   RENESAS_SDHI_SCC_TMPPORT2_HS400OSEL		BIT(4)
+#define RENESAS_SDHI_SCC_TMPPORT2		0x81c
+#define RENESAS_SDHI_SCC_TMPPORT2_HS400EN	BIT(31)
+#define RENESAS_SDHI_SCC_TMPPORT2_HS400OSEL	BIT(4)
 
 #define RENESAS_SDHI_MAX_TAP 3
 
-- 
2.20.1

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

* [U-Boot] [PATCH 2/2] mmc: tmio: sdhi: HS400 manual adjustment
  2019-05-19 17:17 [U-Boot] [PATCH 1/2] mmc: tmio: sdhi: Minor macro cleanup Marek Vasut
@ 2019-05-19 17:17 ` Marek Vasut
  0 siblings, 0 replies; 2+ messages in thread
From: Marek Vasut @ 2019-05-19 17:17 UTC (permalink / raw)
  To: u-boot

Since Gen3 SDHI has an internal DS signal AC-spec violation in HS400 mode,
CRC-error may occur in read command in HS400 mode. This phoenomenon occurs
at low/high temperature.

To fix this, after completion of HS400 tuning, enable manual calibration.
However, Gen3 M3 Ver.1.2 or earlier and H3 1.x does not support HS400.
These SoC forcibly use HS200 mode by SoC attribute.

The DT adjustment of the tuning parameters is not supported until the
DT property names become clear.

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Adapted from a patch by Takeshi Saito <takeshi.saito.xv@renesas.com>
Cc: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
Cc: Peng Fan <peng.fan@nxp.com>
---
 drivers/mmc/renesas-sdhi.c | 165 ++++++++++++++++++++++++++++++++++++-
 drivers/mmc/tmio-common.h  |   4 +
 2 files changed, 166 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c
index 698ecf69bd..7c53aa221e 100644
--- a/drivers/mmc/renesas-sdhi.c
+++ b/drivers/mmc/renesas-sdhi.c
@@ -38,9 +38,111 @@
 #define RENESAS_SDHI_SCC_TMPPORT2		0x81c
 #define RENESAS_SDHI_SCC_TMPPORT2_HS400EN	BIT(31)
 #define RENESAS_SDHI_SCC_TMPPORT2_HS400OSEL	BIT(4)
+#define RENESAS_SDHI_SCC_TMPPORT3		0x828
+#define RENESAS_SDHI_SCC_TMPPORT3_OFFSET_0	3
+#define RENESAS_SDHI_SCC_TMPPORT3_OFFSET_1	2
+#define RENESAS_SDHI_SCC_TMPPORT3_OFFSET_2	1
+#define RENESAS_SDHI_SCC_TMPPORT3_OFFSET_3	0
+#define RENESAS_SDHI_SCC_TMPPORT3_OFFSET_MASK	0x3
+#define RENESAS_SDHI_SCC_TMPPORT4		0x82c
+#define RENESAS_SDHI_SCC_TMPPORT4_DLL_ACC_START	BIT(0)
+#define RENESAS_SDHI_SCC_TMPPORT5		0x830
+#define RENESAS_SDHI_SCC_TMPPORT5_DLL_RW_SEL_R	BIT(8)
+#define RENESAS_SDHI_SCC_TMPPORT5_DLL_RW_SEL_W	(0 << 8)
+#define RENESAS_SDHI_SCC_TMPPORT5_DLL_ADR_MASK	0x3F
+#define RENESAS_SDHI_SCC_TMPPORT6		0x834
+#define RENESAS_SDHI_SCC_TMPPORT7		0x838
+#define RENESAS_SDHI_SCC_TMPPORT_DISABLE_WP_CODE	0xa5000000
+#define RENESAS_SDHI_SCC_TMPPORT_CALIB_CODE_MASK	0x1f
+#define RENESAS_SDHI_SCC_TMPPORT_MANUAL_MODE		BIT(7)
 
 #define RENESAS_SDHI_MAX_TAP 3
 
+static u32 sd_scc_tmpport_read32(struct tmio_sd_priv *priv, u32 addr)
+{
+	/* read mode */
+	tmio_sd_writel(priv, RENESAS_SDHI_SCC_TMPPORT5_DLL_RW_SEL_R |
+		       (RENESAS_SDHI_SCC_TMPPORT5_DLL_ADR_MASK & addr),
+		       RENESAS_SDHI_SCC_TMPPORT5);
+
+	/* access start and stop */
+	tmio_sd_writel(priv, RENESAS_SDHI_SCC_TMPPORT4_DLL_ACC_START,
+		       RENESAS_SDHI_SCC_TMPPORT4);
+	tmio_sd_writel(priv, 0, RENESAS_SDHI_SCC_TMPPORT4);
+
+	return tmio_sd_readl(priv, RENESAS_SDHI_SCC_TMPPORT7);
+}
+
+static void sd_scc_tmpport_write32(struct tmio_sd_priv *priv, u32 addr, u32 val)
+{
+	/* write mode */
+	tmio_sd_writel(priv, RENESAS_SDHI_SCC_TMPPORT5_DLL_RW_SEL_W |
+		       (RENESAS_SDHI_SCC_TMPPORT5_DLL_ADR_MASK & addr),
+		       RENESAS_SDHI_SCC_TMPPORT5);
+	tmio_sd_writel(priv, val, RENESAS_SDHI_SCC_TMPPORT6);
+
+	/* access start and stop */
+	tmio_sd_writel(priv, RENESAS_SDHI_SCC_TMPPORT4_DLL_ACC_START,
+		       RENESAS_SDHI_SCC_TMPPORT4);
+	tmio_sd_writel(priv, 0, RENESAS_SDHI_SCC_TMPPORT4);
+}
+
+static void renesas_sdhi_adjust_hs400_mode_enable(struct tmio_sd_priv *priv)
+{
+	u32 calib_code;
+
+	if (!priv->adjust_hs400_enable)
+		return;
+
+	if (!priv->needs_adjust_hs400)
+		return;
+
+	/*
+	 * Enabled Manual adjust HS400 mode
+	 *
+	 * 1) Disabled Write Protect
+	 *    W(addr=0x00, WP_DISABLE_CODE)
+	 * 2) Read Calibration code and adjust
+	 *    R(addr=0x26) - adjust value
+	 * 3) Enabled Manual Calibration
+	 *    W(addr=0x22, manual mode | Calibration code)
+	 * 4) Set Offset value to TMPPORT3 Reg
+	 */
+	sd_scc_tmpport_write32(priv, 0x00,
+			       RENESAS_SDHI_SCC_TMPPORT_DISABLE_WP_CODE);
+	calib_code = sd_scc_tmpport_read32(priv, 0x26);
+	calib_code &= RENESAS_SDHI_SCC_TMPPORT_CALIB_CODE_MASK;
+	if (calib_code > priv->adjust_hs400_calibrate)
+		calib_code -= priv->adjust_hs400_calibrate;
+	else
+		calib_code = 0;
+	sd_scc_tmpport_write32(priv, 0x22,
+			       RENESAS_SDHI_SCC_TMPPORT_MANUAL_MODE |
+			       calib_code);
+	tmio_sd_writel(priv, priv->adjust_hs400_offset,
+		       RENESAS_SDHI_SCC_TMPPORT3);
+
+	/* Clear flag */
+	priv->needs_adjust_hs400 = false;
+}
+
+static void renesas_sdhi_adjust_hs400_mode_disable(struct tmio_sd_priv *priv)
+{
+
+	/* Disabled Manual adjust HS400 mode
+	 *
+	 * 1) Disabled Write Protect
+	 *    W(addr=0x00, WP_DISABLE_CODE)
+	 * 2) Disabled Manual Calibration
+	 *    W(addr=0x22, 0)
+	 * 3) Clear offset value to TMPPORT3 Reg
+	 */
+	sd_scc_tmpport_write32(priv, 0x00,
+			       RENESAS_SDHI_SCC_TMPPORT_DISABLE_WP_CODE);
+	sd_scc_tmpport_write32(priv, 0x22, 0);
+	tmio_sd_writel(priv, 0, RENESAS_SDHI_SCC_TMPPORT3);
+}
+
 static unsigned int renesas_sdhi_init_tuning(struct tmio_sd_priv *priv)
 {
 	u32 reg;
@@ -96,6 +198,9 @@ static void renesas_sdhi_reset_tuning(struct tmio_sd_priv *priv)
 		 RENESAS_SDHI_SCC_TMPPORT2_HS400OSEL);
 	tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_TMPPORT2);
 
+	/* Disable HS400 mode adjustment */
+	renesas_sdhi_adjust_hs400_mode_disable(priv);
+
 	reg = tmio_sd_readl(priv, TMIO_SD_CLKCTL);
 	reg |= TMIO_SD_CLKCTL_SCLKEN;
 	tmio_sd_writel(priv, reg, TMIO_SD_CLKCTL);
@@ -137,6 +242,10 @@ static int renesas_sdhi_hs400(struct udevice *dev)
 
 	tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_TMPPORT2);
 
+	/* Disable HS400 mode adjustment */
+	if (!hs400)
+		renesas_sdhi_adjust_hs400_mode_disable(priv);
+
 	tmio_sd_writel(priv, (0x8 << RENESAS_SDHI_SCC_DTCNTL_TAPNUM_SHIFT) |
 			     RENESAS_SDHI_SCC_DTCNTL_TAPEN,
 			     RENESAS_SDHI_SCC_DTCNTL);
@@ -159,6 +268,10 @@ static int renesas_sdhi_hs400(struct udevice *dev)
 	reg |= RENESAS_SDHI_SCC_RVSCNTL_RVSEN;
 	tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_RVSCNTL);
 
+	/* Execute adjust hs400 offset after setting to HS400 mode */
+	if (hs400)
+		priv->needs_adjust_hs400 = true;
+
 	return 0;
 }
 
@@ -188,6 +301,8 @@ static int renesas_sdhi_select_tuning(struct tmio_sd_priv *priv,
 	bool select = false;
 	u32 reg;
 
+	priv->needs_adjust_hs400 = false;
+
 	/* Clear SCC_RVSREQ */
 	tmio_sd_writel(priv, 0, RENESAS_SDHI_SCC_RVSREQ);
 
@@ -405,8 +520,29 @@ static int renesas_sdhi_wait_dat0(struct udevice *dev, int state, int timeout)
 }
 #endif
 
+static int renesas_sdhi_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
+				 struct mmc_data *data)
+{
+	int ret;
+
+	ret = tmio_sd_send_cmd(dev, cmd, data);
+	if (ret)
+		return ret;
+
+#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
+    CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
+    CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
+	struct tmio_sd_priv *priv = dev_get_priv(dev);
+
+	if (cmd->cmdidx == MMC_CMD_SEND_STATUS)
+		renesas_sdhi_adjust_hs400_mode_enable(priv);
+#endif
+
+	return 0;
+}
+
 static const struct dm_mmc_ops renesas_sdhi_ops = {
-	.send_cmd = tmio_sd_send_cmd,
+	.send_cmd = renesas_sdhi_send_cmd,
 	.set_ios = renesas_sdhi_set_ios,
 	.get_cd = tmio_sd_get_cd,
 #if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
@@ -451,14 +587,37 @@ static void renesas_sdhi_filter_caps(struct udevice *dev)
 	if (!(priv->caps & TMIO_SD_CAP_RCAR_GEN3))
 		return;
 
-	/* HS400 is not supported on H3 ES1.x and M3W ES1.0,ES1.1 */
+	/* HS400 is not supported on H3 ES1.x and M3W ES1.0,ES1.1,ES1.2 */
 	if (((rmobile_get_cpu_type() == RMOBILE_CPU_TYPE_R8A7795) &&
 	    (rmobile_get_cpu_rev_integer() <= 1)) ||
 	    ((rmobile_get_cpu_type() == RMOBILE_CPU_TYPE_R8A7796) &&
 	    (rmobile_get_cpu_rev_integer() == 1) &&
-	    (rmobile_get_cpu_rev_fraction() <= 1)))
+	    (rmobile_get_cpu_rev_fraction() <= 2)))
 		plat->cfg.host_caps &= ~MMC_MODE_HS400;
 
+	/* M3W ES1.x for x>2 can use HS400 with manual adjustment */
+	if ((rmobile_get_cpu_type() == RMOBILE_CPU_TYPE_R8A7796) &&
+	    (rmobile_get_cpu_rev_integer() == 1) &&
+	    (rmobile_get_cpu_rev_fraction() > 2)) {
+		priv->adjust_hs400_enable = true;
+		priv->adjust_hs400_offset = 0;
+		priv->adjust_hs400_calibrate = 0x9;
+	}
+
+	/* M3N can use HS400 with manual adjustment */
+	if (rmobile_get_cpu_type() == RMOBILE_CPU_TYPE_R8A77965) {
+		priv->adjust_hs400_enable = true;
+		priv->adjust_hs400_offset = 0;
+		priv->adjust_hs400_calibrate = 0x0;
+	}
+
+	/* E3 can use HS400 with manual adjustment */
+	if (rmobile_get_cpu_type() == RMOBILE_CPU_TYPE_R8A77990) {
+		priv->adjust_hs400_enable = true;
+		priv->adjust_hs400_offset = 0;
+		priv->adjust_hs400_calibrate = 0x2;
+	}
+
 	/* H3 ES2.0 uses 4 tuning taps */
 	if ((rmobile_get_cpu_type() == RMOBILE_CPU_TYPE_R8A7795) &&
 	    (rmobile_get_cpu_rev_integer() == 2))
diff --git a/drivers/mmc/tmio-common.h b/drivers/mmc/tmio-common.h
index 58ce3d65b0..51607de142 100644
--- a/drivers/mmc/tmio-common.h
+++ b/drivers/mmc/tmio-common.h
@@ -139,6 +139,10 @@ struct tmio_sd_priv {
 #if CONFIG_IS_ENABLED(RENESAS_SDHI)
 	u8				tap_set;
 	u8				nrtaps;
+	bool				needs_adjust_hs400;
+	bool				adjust_hs400_enable;
+	u8				adjust_hs400_offset;
+	u8				adjust_hs400_calibrate;
 #endif
 	ulong (*clk_get_rate)(struct tmio_sd_priv *);
 };
-- 
2.20.1

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

end of thread, other threads:[~2019-05-19 17:17 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-19 17:17 [U-Boot] [PATCH 1/2] mmc: tmio: sdhi: Minor macro cleanup Marek Vasut
2019-05-19 17:17 ` [U-Boot] [PATCH 2/2] mmc: tmio: sdhi: HS400 manual adjustment Marek Vasut

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.