linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/8] mmc: sdhci-esdhc-imx: add std tuning for mx6sl and DDR mode support
@ 2013-10-18 10:54 Dong Aisheng
  2013-10-18 10:54 ` [PATCH v2 1/8] mmc: sdhci-esdhc-imx: add std tuning support for mx6sl Dong Aisheng
                   ` (8 more replies)
  0 siblings, 9 replies; 16+ messages in thread
From: Dong Aisheng @ 2013-10-18 10:54 UTC (permalink / raw)
  To: linux-arm-kernel

The i.MX6SL supports standard tuning as defined in standard host control spec v3.0.
So this patch series add std tuning support for i.MX6SL.
(NOTE i.MX6SL can also work on the old manual tuning mode as i.MX6Q/DL)
In the meanwhile, it also adds DDR mode support.
Then SD3.0 cards which can only support DDR50 can work properly now
with this patch series.

Patch 1~3 add stardard tuning support for i.MX6SL.
Patch 4~5 add DDR mode and delay line support
Patch 6~8 some other related minor fixes.

Tested on i.MX6SL EVK board.

The patch series is generated based on the latest mmc-next branch with Shawn's
(1)[PATCH v2 0/4] mmc: sdhci-esdhc-imx: eliminate enum imx_esdhc_type in Chris' tree.

1. http://www.spinics.net/lists/arm-kernel/msg280517.html

ChangeLog:
v1->v2:
 - Only a few minor changes on patch 1 and 5 based on comments from Shawn
   while other patches have no change.
 - rebase on Shawn's patch series
   [PATCH v2 0/4] mmc: sdhci-esdhc-imx: eliminate enum imx_esdhc_type

Dong Aisheng (8):
  mmc: sdhci-esdhc-imx: add std tuning support for mx6sl
  mmc: sdhci-esdhc-imx: fix reading cap_1 register value for mx6sl
  mmc: sdhci: report error once the maximum tuning loops exhausted or
    timeout
  mmc: sdhci-esdhc-imx: add DDR mode support for mx6
  mmc: sdhci-esdhc-imx: add delay line setting support
  mmc: sdhci-esdhc-imx: enable SDR50 tuning for imx6q/dl
  mmc: sdhci-esdhc-imx: add preset value quirk for mx6
  mmc: sdhci: remove unneeded call when have preset value quirk

 .../devicetree/bindings/mmc/fsl-imx-esdhc.txt      |    5 +
 drivers/mmc/host/sdhci-esdhc-imx.c                 |  134 +++++++++++++++++---
 drivers/mmc/host/sdhci.c                           |    4 +-
 include/linux/platform_data/mmc-esdhc-imx.h        |    1 +
 4 files changed, 122 insertions(+), 22 deletions(-)

-- 
1.7.2.rc3

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

* [PATCH v2 1/8] mmc: sdhci-esdhc-imx: add std tuning support for mx6sl
  2013-10-18 10:54 [PATCH v2 0/8] mmc: sdhci-esdhc-imx: add std tuning for mx6sl and DDR mode support Dong Aisheng
@ 2013-10-18 10:54 ` Dong Aisheng
  2013-10-18 11:33   ` Shawn Guo
  2013-10-18 10:54 ` [PATCH v2 2/8] mmc: sdhci-esdhc-imx: fix reading cap_1 register value " Dong Aisheng
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 16+ messages in thread
From: Dong Aisheng @ 2013-10-18 10:54 UTC (permalink / raw)
  To: linux-arm-kernel

The mx6sl supports standard sdhci tuning, then esdhc_executing_tuning
is only needed for mx6q/dl. We introduce is_imx6_usdhc() and
is_imx6sl_usdhc() to handle the difference.

The standard tuning is enabled by setting ESDHC_TUNE_CTRL_STD_TUNING_EN bit
in new register ESDHC_TUNE_CTRL and operates with new tuning bits
defined in SDHCI_ACMD12_ERR register.

Note: mx6sl can also work on the old manually tuning mode as mx6q/dl if
not enable standard tuning mode.

Signed-off-by: Dong Aisheng <b29396@freescale.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c |   90 +++++++++++++++++++++++++++++-------
 1 files changed, 73 insertions(+), 17 deletions(-)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index c84c808..a4e0e3b 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -51,6 +51,11 @@
 #define  ESDHC_TUNE_CTRL_MIN		0
 #define  ESDHC_TUNE_CTRL_MAX		((1 << 7) - 1)
 
+#define ESDHC_TUNING_CTRL		0xcc
+#define ESDHC_STD_TUNING_EN		(1 << 24)
+/* NOTE: the minimum valid tuning start tap for mx6sl is 1 */
+#define ESDHC_TUNING_START_TAP		0x1
+
 #define ESDHC_TUNING_BLOCK_PATTERN_LEN	64
 
 /* pinctrl state */
@@ -94,6 +99,12 @@
  * integrated on the i.MX6 series.
  */
 #define ESDHC_FLAG_USDHC		BIT(3)
+/* The IP supports manual tuning process */
+#define ESDHC_FLAG_MAN_TUNING		BIT(4)
+/* The IP supports standard tuning process */
+#define ESDHC_FLAG_STD_TUNING		BIT(4)
+/* The IP has SDHCI_CAPABILITIES_1 register */
+#define ESDHC_FLAG_HAVE_CAP1		BIT(5)
 
 struct esdhc_soc_data {
 	u32 flags;
@@ -116,7 +127,12 @@ static struct esdhc_soc_data esdhc_imx53_data = {
 };
 
 static struct esdhc_soc_data usdhc_imx6q_data = {
-	.flags = ESDHC_FLAG_USDHC,
+	.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_MAN_TUNING,
+};
+
+static struct esdhc_soc_data usdhc_imx6sl_data = {
+	.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
+			| ESDHC_FLAG_HAVE_CAP1,
 };
 
 struct pltfm_imx_data {
@@ -159,6 +175,7 @@ static const struct of_device_id imx_esdhc_dt_ids[] = {
 	{ .compatible = "fsl,imx35-esdhc", .data = &esdhc_imx35_data, },
 	{ .compatible = "fsl,imx51-esdhc", .data = &esdhc_imx51_data, },
 	{ .compatible = "fsl,imx53-esdhc", .data = &esdhc_imx53_data, },
+	{ .compatible = "fsl,imx6sl-usdhc", .data = &usdhc_imx6sl_data, },
 	{ .compatible = "fsl,imx6q-usdhc", .data = &usdhc_imx6q_data, },
 	{ /* sentinel */ }
 };
@@ -222,9 +239,16 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
 		}
 	}
 
-	if (unlikely(reg == SDHCI_CAPABILITIES_1) && esdhc_is_usdhc(imx_data))
-		val = SDHCI_SUPPORT_DDR50 | SDHCI_SUPPORT_SDR104
-				| SDHCI_SUPPORT_SDR50;
+	if (unlikely(reg == SDHCI_CAPABILITIES_1)) {
+		if (esdhc_is_usdhc(imx_data)) {
+			if (imx_data->socdata->flags & ESDHC_FLAG_HAVE_CAP1)
+				val = readl(host->ioaddr + SDHCI_CAPABILITIES) & 0xFFFF;
+			else
+				/* imx6q/dl does not have cap_1 register, fake one */
+				val = SDHCI_SUPPORT_DDR50 | SDHCI_SUPPORT_SDR104
+					| SDHCI_SUPPORT_SDR50;
+		}
+	}
 
 	if (unlikely(reg == SDHCI_MAX_CURRENT) && esdhc_is_usdhc(imx_data)) {
 		val = 0;
@@ -331,13 +355,18 @@ static u16 esdhc_readw_le(struct sdhci_host *host, int reg)
 			ret |= SDHCI_CTRL_VDD_180;
 
 		if (esdhc_is_usdhc(imx_data)) {
-			val = readl(host->ioaddr + ESDHC_MIX_CTRL);
-			if (val & ESDHC_MIX_CTRL_EXE_TUNE)
-				ret |= SDHCI_CTRL_EXEC_TUNING;
-			if (val & ESDHC_MIX_CTRL_SMPCLK_SEL)
-				ret |= SDHCI_CTRL_TUNED_CLK;
+			if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
+				val = readl(host->ioaddr + ESDHC_MIX_CTRL);
+			else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING)
+				/* the std tuning bits is in ACMD12_ERR for imx6sl */
+				val = readl(host->ioaddr + SDHCI_ACMD12_ERR);
 		}
 
+		if (val & ESDHC_MIX_CTRL_EXE_TUNE)
+			ret |= SDHCI_CTRL_EXEC_TUNING;
+		if (val & ESDHC_MIX_CTRL_SMPCLK_SEL)
+			ret |= SDHCI_CTRL_TUNED_CLK;
+
 		ret |= (imx_data->uhs_mode & SDHCI_CTRL_UHS_MASK);
 		ret &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
 
@@ -370,12 +399,37 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
 			new_val &= ~ESDHC_VENDOR_SPEC_VSELECT;
 		writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC);
 		imx_data->uhs_mode = val & SDHCI_CTRL_UHS_MASK;
-		new_val = readl(host->ioaddr + ESDHC_MIX_CTRL);
-		if (val & SDHCI_CTRL_TUNED_CLK)
-			new_val |= ESDHC_MIX_CTRL_SMPCLK_SEL;
-		else
-			new_val &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
-		writel(new_val , host->ioaddr + ESDHC_MIX_CTRL);
+		if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) {
+			new_val = readl(host->ioaddr + ESDHC_MIX_CTRL);
+			if (val & SDHCI_CTRL_TUNED_CLK)
+				new_val |= ESDHC_MIX_CTRL_SMPCLK_SEL;
+			else
+				new_val &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
+			writel(new_val , host->ioaddr + ESDHC_MIX_CTRL);
+		} else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
+			u32 v = readl(host->ioaddr + SDHCI_ACMD12_ERR);
+			u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL);
+			new_val = readl(host->ioaddr + ESDHC_TUNING_CTRL);
+			if (val & SDHCI_CTRL_EXEC_TUNING) {
+				new_val |= ESDHC_STD_TUNING_EN |
+						ESDHC_TUNING_START_TAP;
+				v |= ESDHC_MIX_CTRL_EXE_TUNE;
+				m |= ESDHC_MIX_CTRL_FBCLK_SEL;
+			} else {
+				new_val &= ~ESDHC_STD_TUNING_EN;
+				v &= ~ESDHC_MIX_CTRL_EXE_TUNE;
+				m &= ~ESDHC_MIX_CTRL_FBCLK_SEL;
+			}
+
+			if (val & SDHCI_CTRL_TUNED_CLK)
+				v |= ESDHC_MIX_CTRL_SMPCLK_SEL;
+			else
+				v &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
+
+			writel(new_val, host->ioaddr + ESDHC_TUNING_CTRL);
+			writel(v, host->ioaddr + SDHCI_ACMD12_ERR);
+			writel(m, host->ioaddr + ESDHC_MIX_CTRL);
+		}
 		return;
 	case SDHCI_TRANSFER_MODE:
 		if ((imx_data->socdata->flags & ESDHC_FLAG_MULTIBLK_NO_INT)
@@ -774,7 +828,7 @@ static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
 	return esdhc_change_pinstate(host, uhs);
 }
 
-static const struct sdhci_ops sdhci_esdhc_ops = {
+static struct sdhci_ops sdhci_esdhc_ops = {
 	.read_l = esdhc_readl_le,
 	.read_w = esdhc_readw_le,
 	.write_l = esdhc_writel_le,
@@ -786,7 +840,6 @@ static const struct sdhci_ops sdhci_esdhc_ops = {
 	.get_ro = esdhc_pltfm_get_ro,
 	.platform_bus_width = esdhc_pltfm_bus_width,
 	.set_uhs_signaling = esdhc_set_uhs_signaling,
-	.platform_execute_tuning = esdhc_executing_tuning,
 };
 
 static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
@@ -922,6 +975,9 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
 	if (esdhc_is_usdhc(imx_data))
 		writel(0x08100810, host->ioaddr + ESDHC_WTMK_LVL);
 
+	if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
+		sdhci_esdhc_ops.platform_execute_tuning =
+					esdhc_executing_tuning;
 	boarddata = &imx_data->boarddata;
 	if (sdhci_esdhc_imx_probe_dt(pdev, boarddata) < 0) {
 		if (!host->mmc->parent->platform_data) {
-- 
1.7.2.rc3

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

* [PATCH v2 2/8] mmc: sdhci-esdhc-imx: fix reading cap_1 register value for mx6sl
  2013-10-18 10:54 [PATCH v2 0/8] mmc: sdhci-esdhc-imx: add std tuning for mx6sl and DDR mode support Dong Aisheng
  2013-10-18 10:54 ` [PATCH v2 1/8] mmc: sdhci-esdhc-imx: add std tuning support for mx6sl Dong Aisheng
@ 2013-10-18 10:54 ` Dong Aisheng
  2013-10-18 10:54 ` [PATCH v2 3/8] mmc: sdhci: report error once the maximum tuning loops exhausted or timeout Dong Aisheng
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 16+ messages in thread
From: Dong Aisheng @ 2013-10-18 10:54 UTC (permalink / raw)
  To: linux-arm-kernel

When reading CAP_1 register for mx6sl, ignore bit[0-15] as it stores
CAP_2 register value which is new introduced in mx6sl.

Without this fix, the max clock for mx6sl may not be correct since
it's wrongly calculated by reading CAP_1 register.

Signed-off-by: Dong Aisheng <b29396@freescale.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index a4e0e3b..52c0760 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -226,6 +226,10 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
 	}
 
 	if (unlikely(reg == SDHCI_CAPABILITIES)) {
+		/* ignore bit[0-15] as it stores cap_1 register val for mx6sl */
+		if (imx_data->socdata->flags & ESDHC_FLAG_HAVE_CAP1)
+			val &= 0xffff0000;
+
 		/* In FSL esdhc IC module, only bit20 is used to indicate the
 		 * ADMA2 capability of esdhc, but this bit is messed up on
 		 * some SOCs (e.g. on MX25, MX35 this bit is set, but they
-- 
1.7.2.rc3

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

* [PATCH v2 3/8] mmc: sdhci: report error once the maximum tuning loops exhausted or timeout
  2013-10-18 10:54 [PATCH v2 0/8] mmc: sdhci-esdhc-imx: add std tuning for mx6sl and DDR mode support Dong Aisheng
  2013-10-18 10:54 ` [PATCH v2 1/8] mmc: sdhci-esdhc-imx: add std tuning support for mx6sl Dong Aisheng
  2013-10-18 10:54 ` [PATCH v2 2/8] mmc: sdhci-esdhc-imx: fix reading cap_1 register value " Dong Aisheng
@ 2013-10-18 10:54 ` Dong Aisheng
  2013-10-18 10:54 ` [PATCH v2 4/8] mmc: sdhci-esdhc-imx: add DDR mode support for mx6 Dong Aisheng
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 16+ messages in thread
From: Dong Aisheng @ 2013-10-18 10:54 UTC (permalink / raw)
  To: linux-arm-kernel

The original code missed to report an error when the maximum tuning loops exhausted
or timeout, it will cause the upper layer to wrongly think the tuning process
is passed.

Signed-off-by: Dong Aisheng <b29396@freescale.com>
---
 drivers/mmc/host/sdhci.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 66bce7a..cbde17d 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1989,6 +1989,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
 	if (!tuning_loop_counter || !timeout) {
 		ctrl &= ~SDHCI_CTRL_TUNED_CLK;
 		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+		err = -EIO;
 	} else {
 		if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) {
 			pr_info(DRIVER_NAME ": Tuning procedure"
-- 
1.7.2.rc3

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

* [PATCH v2 4/8] mmc: sdhci-esdhc-imx: add DDR mode support for mx6
  2013-10-18 10:54 [PATCH v2 0/8] mmc: sdhci-esdhc-imx: add std tuning for mx6sl and DDR mode support Dong Aisheng
                   ` (2 preceding siblings ...)
  2013-10-18 10:54 ` [PATCH v2 3/8] mmc: sdhci: report error once the maximum tuning loops exhausted or timeout Dong Aisheng
@ 2013-10-18 10:54 ` Dong Aisheng
  2013-10-18 10:54 ` [PATCH v2 5/8] mmc: sdhci-esdhc-imx: add delay line setting support Dong Aisheng
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 16+ messages in thread
From: Dong Aisheng @ 2013-10-18 10:54 UTC (permalink / raw)
  To: linux-arm-kernel

When DDR mode is enabled, the initial pre_div should be 2.
And the pre_div value should be changed accordingly
from
...
02h) Base clock divided by 4
01h) Base clock divided by 2
00h) Base clock divided by 1
to
..
02h) Base clock divided by 8
01h) Base clock divided by 4
00h) Base clock divided by 2

Signed-off-by: Dong Aisheng <b29396@freescale.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c |   17 ++++++++++++++---
 1 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 52c0760..c5c26bd 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -38,6 +38,7 @@
 #define  ESDHC_VENDOR_SPEC_FRC_SDCLK_ON	(1 << 8)
 #define ESDHC_WTMK_LVL			0x44
 #define ESDHC_MIX_CTRL			0x48
+#define  ESDHC_MIX_CTRL_DDREN		(1 << 3)
 #define  ESDHC_MIX_CTRL_AC23EN		(1 << 7)
 #define  ESDHC_MIX_CTRL_EXE_TUNE	(1 << 22)
 #define  ESDHC_MIX_CTRL_SMPCLK_SEL	(1 << 23)
@@ -152,6 +153,7 @@ struct pltfm_imx_data {
 		WAIT_FOR_INT,        /* sent CMD12, waiting for response INT */
 	} multiblock_status;
 	u32 uhs_mode;
+	u32 is_ddr;
 };
 
 static struct platform_device_id imx_esdhc_devtype[] = {
@@ -537,8 +539,10 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg)
 		 * The reset on usdhc fails to clear MIX_CTRL register.
 		 * Do it manually here.
 		 */
-		if (esdhc_is_usdhc(imx_data))
+		if (esdhc_is_usdhc(imx_data)) {
 			writel(0, host->ioaddr + ESDHC_MIX_CTRL);
+			imx_data->is_ddr = 0;
+		}
 	}
 }
 
@@ -582,7 +586,7 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host,
 		goto out;
 	}
 
-	if (esdhc_is_usdhc(imx_data))
+	if (esdhc_is_usdhc(imx_data) && !imx_data->is_ddr)
 		pre_div = 1;
 
 	temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
@@ -600,7 +604,10 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host,
 	dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n",
 		clock, host->mmc->actual_clock);
 
-	pre_div >>= 1;
+	if (imx_data->is_ddr)
+		pre_div >>= 2;
+	else
+		pre_div >>= 1;
 	div--;
 
 	temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
@@ -826,6 +833,10 @@ static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
 		break;
 	case MMC_TIMING_UHS_DDR50:
 		imx_data->uhs_mode = SDHCI_CTRL_UHS_DDR50;
+		writel(readl(host->ioaddr + ESDHC_MIX_CTRL) |
+				ESDHC_MIX_CTRL_DDREN,
+				host->ioaddr + ESDHC_MIX_CTRL);
+		imx_data->is_ddr = 1;
 		break;
 	}
 
-- 
1.7.2.rc3

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

* [PATCH v2 5/8] mmc: sdhci-esdhc-imx: add delay line setting support
  2013-10-18 10:54 [PATCH v2 0/8] mmc: sdhci-esdhc-imx: add std tuning for mx6sl and DDR mode support Dong Aisheng
                   ` (3 preceding siblings ...)
  2013-10-18 10:54 ` [PATCH v2 4/8] mmc: sdhci-esdhc-imx: add DDR mode support for mx6 Dong Aisheng
@ 2013-10-18 10:54 ` Dong Aisheng
  2013-10-18 11:42   ` Shawn Guo
  2013-10-18 10:54 ` [PATCH v2 6/8] mmc: sdhci-esdhc-imx: enable SDR50 tuning for imx6q/dl Dong Aisheng
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 16+ messages in thread
From: Dong Aisheng @ 2013-10-18 10:54 UTC (permalink / raw)
  To: linux-arm-kernel

The DLL(Delay Line) is newly added to assist in sampling read data.
The DLL provides the ability to programmatically select a quantized
delay (in fractions of the clock period) regardless of on-chip variations
such as process, voltage and temperature (PVT).

This patch adds a user interface to set slave delay line via device tree.
It's usually used in high speed mode like mmc DDR mode when the signal
quality is not good caused by board design, e.g. the signal path is too long.
User can manual set delay line to find a suitable data sampling window
for card to work properly.

Signed-off-by: Dong Aisheng <b29396@freescale.com>
---
 .../devicetree/bindings/mmc/fsl-imx-esdhc.txt      |    5 +++++
 drivers/mmc/host/sdhci-esdhc-imx.c                 |   18 ++++++++++++++++++
 include/linux/platform_data/mmc-esdhc-imx.h        |    1 +
 3 files changed, 24 insertions(+), 0 deletions(-)

diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
index 1dd6225..78a45c5 100644
--- a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
+++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
@@ -12,6 +12,11 @@ Required properties:
 Optional properties:
 - fsl,cd-controller : Indicate to use controller internal card detection
 - fsl,wp-controller : Indicate to use controller internal write protection
+- fsl,delay-line : Specify the number of delay cells for override mode.
+  This is used to set the clock delay for DLL(Delay Line) on override mode
+  to select a proper data sampling window in case the clock quality is not good
+  due to signal path is too long on the board.
+  please refer to DLL chapter in RM for details.
 
 Examples:
 
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index c5c26bd..87d202b 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -46,6 +46,11 @@
 /* Bits 3 and 6 are not SDHCI standard definitions */
 #define  ESDHC_MIX_CTRL_SDHCI_MASK	0xb7
 
+/* dll control register */
+#define ESDHC_DLL_CTRL			0x60
+#define ESDHC_DLL_OVERRIDE_VAL_SHIFT	9
+#define ESDHC_DLL_OVERRIDE_EN_SHIFT	8
+
 /* tune control register */
 #define ESDHC_TUNE_CTRL_STATUS		0x68
 #define  ESDHC_TUNE_CTRL_STEP		1
@@ -817,6 +822,7 @@ static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct pltfm_imx_data *imx_data = pltfm_host->priv;
+	struct esdhc_platform_data *boarddata = &imx_data->boarddata;
 
 	switch (uhs) {
 	case MMC_TIMING_UHS_SDR12:
@@ -837,6 +843,15 @@ static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
 				ESDHC_MIX_CTRL_DDREN,
 				host->ioaddr + ESDHC_MIX_CTRL);
 		imx_data->is_ddr = 1;
+		if (boarddata->delay_line) {
+			u32 v;
+			v = boarddata->delay_line <<
+				ESDHC_DLL_OVERRIDE_VAL_SHIFT |
+				(1 << ESDHC_DLL_OVERRIDE_EN_SHIFT);
+			if (is_imx53_esdhc(imx_data))
+				v <<= 1;
+			writel(v, host->ioaddr + ESDHC_DLL_CTRL);
+		}
 		break;
 	}
 
@@ -901,6 +916,9 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
 	else
 		boarddata->support_vsel = true;
 
+	if (of_property_read_u32(np, "fsl,delay-line", &boarddata->delay_line))
+		boarddata->delay_line = 0;
+
 	return 0;
 }
 #else
diff --git a/include/linux/platform_data/mmc-esdhc-imx.h b/include/linux/platform_data/mmc-esdhc-imx.h
index a0f5a8f..75f70f6 100644
--- a/include/linux/platform_data/mmc-esdhc-imx.h
+++ b/include/linux/platform_data/mmc-esdhc-imx.h
@@ -45,5 +45,6 @@ struct esdhc_platform_data {
 	int max_bus_width;
 	unsigned int f_max;
 	bool support_vsel;
+	unsigned int delay_line;
 };
 #endif /* __ASM_ARCH_IMX_ESDHC_H */
-- 
1.7.2.rc3

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

* [PATCH v2 6/8] mmc: sdhci-esdhc-imx: enable SDR50 tuning for imx6q/dl
  2013-10-18 10:54 [PATCH v2 0/8] mmc: sdhci-esdhc-imx: add std tuning for mx6sl and DDR mode support Dong Aisheng
                   ` (4 preceding siblings ...)
  2013-10-18 10:54 ` [PATCH v2 5/8] mmc: sdhci-esdhc-imx: add delay line setting support Dong Aisheng
@ 2013-10-18 10:54 ` Dong Aisheng
  2013-10-18 10:54 ` [PATCH v2 7/8] mmc: sdhci-esdhc-imx: add preset value quirk for mx6 Dong Aisheng
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 16+ messages in thread
From: Dong Aisheng @ 2013-10-18 10:54 UTC (permalink / raw)
  To: linux-arm-kernel

The imx6q/dl supports SDR50 tunning, enable it for a better timing
on SDR50 mode.

Signed-off-by: Dong Aisheng <b29396@freescale.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 87d202b..bdbca0e 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -257,7 +257,8 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
 			else
 				/* imx6q/dl does not have cap_1 register, fake one */
 				val = SDHCI_SUPPORT_DDR50 | SDHCI_SUPPORT_SDR104
-					| SDHCI_SUPPORT_SDR50;
+					| SDHCI_SUPPORT_SDR50
+					| SDHCI_USE_SDR50_TUNING;
 		}
 	}
 
-- 
1.7.2.rc3

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

* [PATCH v2 7/8] mmc: sdhci-esdhc-imx: add preset value quirk for mx6
  2013-10-18 10:54 [PATCH v2 0/8] mmc: sdhci-esdhc-imx: add std tuning for mx6sl and DDR mode support Dong Aisheng
                   ` (5 preceding siblings ...)
  2013-10-18 10:54 ` [PATCH v2 6/8] mmc: sdhci-esdhc-imx: enable SDR50 tuning for imx6q/dl Dong Aisheng
@ 2013-10-18 10:54 ` Dong Aisheng
  2013-10-18 10:54 ` [PATCH v2 8/8] mmc: sdhci: remove unneeded call when have preset value quirk Dong Aisheng
  2013-10-18 11:46 ` [PATCH v2 0/8] mmc: sdhci-esdhc-imx: add std tuning for mx6sl and DDR mode support Shawn Guo
  8 siblings, 0 replies; 16+ messages in thread
From: Dong Aisheng @ 2013-10-18 10:54 UTC (permalink / raw)
  To: linux-arm-kernel

The i.MX6 does not support preset value feature.

Signed-off-by: Dong Aisheng <b29396@freescale.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index bdbca0e..8f2d995 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -1006,8 +1006,10 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
 	 * The imx6q ROM code will change the default watermark level setting
 	 * to something insane.  Change it back here.
 	 */
-	if (esdhc_is_usdhc(imx_data))
+	if (esdhc_is_usdhc(imx_data)) {
 		writel(0x08100810, host->ioaddr + ESDHC_WTMK_LVL);
+		host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN;
+	}
 
 	if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
 		sdhci_esdhc_ops.platform_execute_tuning =
-- 
1.7.2.rc3

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

* [PATCH v2 8/8] mmc: sdhci: remove unneeded call when have preset value quirk
  2013-10-18 10:54 [PATCH v2 0/8] mmc: sdhci-esdhc-imx: add std tuning for mx6sl and DDR mode support Dong Aisheng
                   ` (6 preceding siblings ...)
  2013-10-18 10:54 ` [PATCH v2 7/8] mmc: sdhci-esdhc-imx: add preset value quirk for mx6 Dong Aisheng
@ 2013-10-18 10:54 ` Dong Aisheng
  2013-10-18 11:46 ` [PATCH v2 0/8] mmc: sdhci-esdhc-imx: add std tuning for mx6sl and DDR mode support Shawn Guo
  8 siblings, 0 replies; 16+ messages in thread
From: Dong Aisheng @ 2013-10-18 10:54 UTC (permalink / raw)
  To: linux-arm-kernel

Remove unneeded call of call sdhci_enable_preset_value when having
SDHCI_QUIRK2_PRESET_VALUE_BROKEN.

Signed-off-by: Dong Aisheng <b29396@freescale.com>
---
 drivers/mmc/host/sdhci.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index cbde17d..a21a710 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1435,7 +1435,8 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 	}
 
 	if (host->version >= SDHCI_SPEC_300 &&
-		(ios->power_mode == MMC_POWER_UP))
+		(ios->power_mode == MMC_POWER_UP) &&
+		!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN))
 		sdhci_enable_preset_value(host, false);
 
 	sdhci_set_clock(host, ios->clock);
-- 
1.7.2.rc3

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

* [PATCH v2 1/8] mmc: sdhci-esdhc-imx: add std tuning support for mx6sl
  2013-10-18 11:33   ` Shawn Guo
@ 2013-10-18 11:18     ` Dong Aisheng
  0 siblings, 0 replies; 16+ messages in thread
From: Dong Aisheng @ 2013-10-18 11:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 18, 2013 at 07:33:50PM +0800, Shawn Guo wrote:
> On Fri, Oct 18, 2013 at 06:54:14PM +0800, Dong Aisheng wrote:
> > The mx6sl supports standard sdhci tuning, then esdhc_executing_tuning
> > is only needed for mx6q/dl. We introduce is_imx6_usdhc() and
> > is_imx6sl_usdhc() to handle the difference.
> > 
> > The standard tuning is enabled by setting ESDHC_TUNE_CTRL_STD_TUNING_EN bit
> > in new register ESDHC_TUNE_CTRL and operates with new tuning bits
> > defined in SDHCI_ACMD12_ERR register.
> > 
> > Note: mx6sl can also work on the old manually tuning mode as mx6q/dl if
> > not enable standard tuning mode.
> > 
> > Signed-off-by: Dong Aisheng <b29396@freescale.com>
> > ---
> >  drivers/mmc/host/sdhci-esdhc-imx.c |   90 +++++++++++++++++++++++++++++-------
> >  1 files changed, 73 insertions(+), 17 deletions(-)
> > 
> > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> > index c84c808..a4e0e3b 100644
> > --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> > @@ -51,6 +51,11 @@
> >  #define  ESDHC_TUNE_CTRL_MIN		0
> >  #define  ESDHC_TUNE_CTRL_MAX		((1 << 7) - 1)
> >  
> > +#define ESDHC_TUNING_CTRL		0xcc
> > +#define ESDHC_STD_TUNING_EN		(1 << 24)
> > +/* NOTE: the minimum valid tuning start tap for mx6sl is 1 */
> > +#define ESDHC_TUNING_START_TAP		0x1
> > +
> >  #define ESDHC_TUNING_BLOCK_PATTERN_LEN	64
> >  
> >  /* pinctrl state */
> > @@ -94,6 +99,12 @@
> >   * integrated on the i.MX6 series.
> >   */
> >  #define ESDHC_FLAG_USDHC		BIT(3)
> > +/* The IP supports manual tuning process */
> > +#define ESDHC_FLAG_MAN_TUNING		BIT(4)
> > +/* The IP supports standard tuning process */
> > +#define ESDHC_FLAG_STD_TUNING		BIT(4)
> 
> BIT(4) for both flags?
> 

Oh no, it's copy&paste error.
My mistake.
Will update it.

Regards
Dong Aisheng

> Shawn
> 
> > +/* The IP has SDHCI_CAPABILITIES_1 register */
> > +#define ESDHC_FLAG_HAVE_CAP1		BIT(5)
> >  
> >  struct esdhc_soc_data {
> >  	u32 flags;
> > @@ -116,7 +127,12 @@ static struct esdhc_soc_data esdhc_imx53_data = {
> >  };
> >  
> >  static struct esdhc_soc_data usdhc_imx6q_data = {
> > -	.flags = ESDHC_FLAG_USDHC,
> > +	.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_MAN_TUNING,
> > +};
> > +
> > +static struct esdhc_soc_data usdhc_imx6sl_data = {
> > +	.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
> > +			| ESDHC_FLAG_HAVE_CAP1,
> >  };
> >  
> >  struct pltfm_imx_data {
> > @@ -159,6 +175,7 @@ static const struct of_device_id imx_esdhc_dt_ids[] = {
> >  	{ .compatible = "fsl,imx35-esdhc", .data = &esdhc_imx35_data, },
> >  	{ .compatible = "fsl,imx51-esdhc", .data = &esdhc_imx51_data, },
> >  	{ .compatible = "fsl,imx53-esdhc", .data = &esdhc_imx53_data, },
> > +	{ .compatible = "fsl,imx6sl-usdhc", .data = &usdhc_imx6sl_data, },
> >  	{ .compatible = "fsl,imx6q-usdhc", .data = &usdhc_imx6q_data, },
> >  	{ /* sentinel */ }
> >  };
> > @@ -222,9 +239,16 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
> >  		}
> >  	}
> >  
> > -	if (unlikely(reg == SDHCI_CAPABILITIES_1) && esdhc_is_usdhc(imx_data))
> > -		val = SDHCI_SUPPORT_DDR50 | SDHCI_SUPPORT_SDR104
> > -				| SDHCI_SUPPORT_SDR50;
> > +	if (unlikely(reg == SDHCI_CAPABILITIES_1)) {
> > +		if (esdhc_is_usdhc(imx_data)) {
> > +			if (imx_data->socdata->flags & ESDHC_FLAG_HAVE_CAP1)
> > +				val = readl(host->ioaddr + SDHCI_CAPABILITIES) & 0xFFFF;
> > +			else
> > +				/* imx6q/dl does not have cap_1 register, fake one */
> > +				val = SDHCI_SUPPORT_DDR50 | SDHCI_SUPPORT_SDR104
> > +					| SDHCI_SUPPORT_SDR50;
> > +		}
> > +	}
> >  
> >  	if (unlikely(reg == SDHCI_MAX_CURRENT) && esdhc_is_usdhc(imx_data)) {
> >  		val = 0;
> > @@ -331,13 +355,18 @@ static u16 esdhc_readw_le(struct sdhci_host *host, int reg)
> >  			ret |= SDHCI_CTRL_VDD_180;
> >  
> >  		if (esdhc_is_usdhc(imx_data)) {
> > -			val = readl(host->ioaddr + ESDHC_MIX_CTRL);
> > -			if (val & ESDHC_MIX_CTRL_EXE_TUNE)
> > -				ret |= SDHCI_CTRL_EXEC_TUNING;
> > -			if (val & ESDHC_MIX_CTRL_SMPCLK_SEL)
> > -				ret |= SDHCI_CTRL_TUNED_CLK;
> > +			if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
> > +				val = readl(host->ioaddr + ESDHC_MIX_CTRL);
> > +			else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING)
> > +				/* the std tuning bits is in ACMD12_ERR for imx6sl */
> > +				val = readl(host->ioaddr + SDHCI_ACMD12_ERR);
> >  		}
> >  
> > +		if (val & ESDHC_MIX_CTRL_EXE_TUNE)
> > +			ret |= SDHCI_CTRL_EXEC_TUNING;
> > +		if (val & ESDHC_MIX_CTRL_SMPCLK_SEL)
> > +			ret |= SDHCI_CTRL_TUNED_CLK;
> > +
> >  		ret |= (imx_data->uhs_mode & SDHCI_CTRL_UHS_MASK);
> >  		ret &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
> >  
> > @@ -370,12 +399,37 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
> >  			new_val &= ~ESDHC_VENDOR_SPEC_VSELECT;
> >  		writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC);
> >  		imx_data->uhs_mode = val & SDHCI_CTRL_UHS_MASK;
> > -		new_val = readl(host->ioaddr + ESDHC_MIX_CTRL);
> > -		if (val & SDHCI_CTRL_TUNED_CLK)
> > -			new_val |= ESDHC_MIX_CTRL_SMPCLK_SEL;
> > -		else
> > -			new_val &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
> > -		writel(new_val , host->ioaddr + ESDHC_MIX_CTRL);
> > +		if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) {
> > +			new_val = readl(host->ioaddr + ESDHC_MIX_CTRL);
> > +			if (val & SDHCI_CTRL_TUNED_CLK)
> > +				new_val |= ESDHC_MIX_CTRL_SMPCLK_SEL;
> > +			else
> > +				new_val &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
> > +			writel(new_val , host->ioaddr + ESDHC_MIX_CTRL);
> > +		} else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
> > +			u32 v = readl(host->ioaddr + SDHCI_ACMD12_ERR);
> > +			u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL);
> > +			new_val = readl(host->ioaddr + ESDHC_TUNING_CTRL);
> > +			if (val & SDHCI_CTRL_EXEC_TUNING) {
> > +				new_val |= ESDHC_STD_TUNING_EN |
> > +						ESDHC_TUNING_START_TAP;
> > +				v |= ESDHC_MIX_CTRL_EXE_TUNE;
> > +				m |= ESDHC_MIX_CTRL_FBCLK_SEL;
> > +			} else {
> > +				new_val &= ~ESDHC_STD_TUNING_EN;
> > +				v &= ~ESDHC_MIX_CTRL_EXE_TUNE;
> > +				m &= ~ESDHC_MIX_CTRL_FBCLK_SEL;
> > +			}
> > +
> > +			if (val & SDHCI_CTRL_TUNED_CLK)
> > +				v |= ESDHC_MIX_CTRL_SMPCLK_SEL;
> > +			else
> > +				v &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
> > +
> > +			writel(new_val, host->ioaddr + ESDHC_TUNING_CTRL);
> > +			writel(v, host->ioaddr + SDHCI_ACMD12_ERR);
> > +			writel(m, host->ioaddr + ESDHC_MIX_CTRL);
> > +		}
> >  		return;
> >  	case SDHCI_TRANSFER_MODE:
> >  		if ((imx_data->socdata->flags & ESDHC_FLAG_MULTIBLK_NO_INT)
> > @@ -774,7 +828,7 @@ static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
> >  	return esdhc_change_pinstate(host, uhs);
> >  }
> >  
> > -static const struct sdhci_ops sdhci_esdhc_ops = {
> > +static struct sdhci_ops sdhci_esdhc_ops = {
> >  	.read_l = esdhc_readl_le,
> >  	.read_w = esdhc_readw_le,
> >  	.write_l = esdhc_writel_le,
> > @@ -786,7 +840,6 @@ static const struct sdhci_ops sdhci_esdhc_ops = {
> >  	.get_ro = esdhc_pltfm_get_ro,
> >  	.platform_bus_width = esdhc_pltfm_bus_width,
> >  	.set_uhs_signaling = esdhc_set_uhs_signaling,
> > -	.platform_execute_tuning = esdhc_executing_tuning,
> >  };
> >  
> >  static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
> > @@ -922,6 +975,9 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
> >  	if (esdhc_is_usdhc(imx_data))
> >  		writel(0x08100810, host->ioaddr + ESDHC_WTMK_LVL);
> >  
> > +	if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
> > +		sdhci_esdhc_ops.platform_execute_tuning =
> > +					esdhc_executing_tuning;
> >  	boarddata = &imx_data->boarddata;
> >  	if (sdhci_esdhc_imx_probe_dt(pdev, boarddata) < 0) {
> >  		if (!host->mmc->parent->platform_data) {
> > -- 
> > 1.7.2.rc3
> > 
> > 

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

* [PATCH v2 5/8] mmc: sdhci-esdhc-imx: add delay line setting support
  2013-10-18 11:42   ` Shawn Guo
@ 2013-10-18 11:30     ` Dong Aisheng
  2013-10-18 11:57       ` Shawn Guo
  0 siblings, 1 reply; 16+ messages in thread
From: Dong Aisheng @ 2013-10-18 11:30 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 18, 2013 at 07:42:35PM +0800, Shawn Guo wrote:
> On Fri, Oct 18, 2013 at 06:54:18PM +0800, Dong Aisheng wrote:
> > The DLL(Delay Line) is newly added to assist in sampling read data.
> > The DLL provides the ability to programmatically select a quantized
> > delay (in fractions of the clock period) regardless of on-chip variations
> > such as process, voltage and temperature (PVT).
> > 
> > This patch adds a user interface to set slave delay line via device tree.
> > It's usually used in high speed mode like mmc DDR mode when the signal
> > quality is not good caused by board design, e.g. the signal path is too long.
> > User can manual set delay line to find a suitable data sampling window
> > for card to work properly.
> > 
> > Signed-off-by: Dong Aisheng <b29396@freescale.com>
> > ---
> >  .../devicetree/bindings/mmc/fsl-imx-esdhc.txt      |    5 +++++
> >  drivers/mmc/host/sdhci-esdhc-imx.c                 |   18 ++++++++++++++++++
> >  include/linux/platform_data/mmc-esdhc-imx.h        |    1 +
> >  3 files changed, 24 insertions(+), 0 deletions(-)
> > 
> > diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
> > index 1dd6225..78a45c5 100644
> > --- a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
> > +++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
> > @@ -12,6 +12,11 @@ Required properties:
> >  Optional properties:
> >  - fsl,cd-controller : Indicate to use controller internal card detection
> >  - fsl,wp-controller : Indicate to use controller internal write protection
> > +- fsl,delay-line : Specify the number of delay cells for override mode.
> > +  This is used to set the clock delay for DLL(Delay Line) on override mode
> > +  to select a proper data sampling window in case the clock quality is not good
> > +  due to signal path is too long on the board.
> > +  please refer to DLL chapter in RM for details.
> 
> It might be better to reword it like:
> 
> Please refer to eSDHC/uSDHC DLL_CTRL register bit field
> DLL_CTRL_SLV_OVERRIDE_VAL in Reference Manual for details.
> 

There is a DLL (Delay Line) chapter in the reference manual which
has more detailed descriptions on the delay line including override mode.
So i think it may be better to point user to the DLL chapter for understanding,
then naturally user will refer to register for bit defines later too.
Does it make sense?

Regards
Dong Aisheng

> >  
> >  Examples:
> >  
> > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> > index c5c26bd..87d202b 100644
> > --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> > @@ -46,6 +46,11 @@
> >  /* Bits 3 and 6 are not SDHCI standard definitions */
> >  #define  ESDHC_MIX_CTRL_SDHCI_MASK	0xb7
> >  
> > +/* dll control register */
> > +#define ESDHC_DLL_CTRL			0x60
> > +#define ESDHC_DLL_OVERRIDE_VAL_SHIFT	9
> > +#define ESDHC_DLL_OVERRIDE_EN_SHIFT	8
> > +
> >  /* tune control register */
> >  #define ESDHC_TUNE_CTRL_STATUS		0x68
> >  #define  ESDHC_TUNE_CTRL_STEP		1
> > @@ -817,6 +822,7 @@ static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
> >  {
> >  	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> >  	struct pltfm_imx_data *imx_data = pltfm_host->priv;
> > +	struct esdhc_platform_data *boarddata = &imx_data->boarddata;
> >  
> >  	switch (uhs) {
> >  	case MMC_TIMING_UHS_SDR12:
> > @@ -837,6 +843,15 @@ static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
> >  				ESDHC_MIX_CTRL_DDREN,
> >  				host->ioaddr + ESDHC_MIX_CTRL);
> >  		imx_data->is_ddr = 1;
> > +		if (boarddata->delay_line) {
> > +			u32 v;
> > +			v = boarddata->delay_line <<
> > +				ESDHC_DLL_OVERRIDE_VAL_SHIFT |
> > +				(1 << ESDHC_DLL_OVERRIDE_EN_SHIFT);
> > +			if (is_imx53_esdhc(imx_data))
> > +				v <<= 1;
> > +			writel(v, host->ioaddr + ESDHC_DLL_CTRL);
> > +		}
> >  		break;
> >  	}
> >  
> > @@ -901,6 +916,9 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
> >  	else
> >  		boarddata->support_vsel = true;
> >  
> > +	if (of_property_read_u32(np, "fsl,delay-line", &boarddata->delay_line))
> > +		boarddata->delay_line = 0;
> > +
> >  	return 0;
> >  }
> >  #else
> > diff --git a/include/linux/platform_data/mmc-esdhc-imx.h b/include/linux/platform_data/mmc-esdhc-imx.h
> > index a0f5a8f..75f70f6 100644
> > --- a/include/linux/platform_data/mmc-esdhc-imx.h
> > +++ b/include/linux/platform_data/mmc-esdhc-imx.h
> > @@ -45,5 +45,6 @@ struct esdhc_platform_data {
> >  	int max_bus_width;
> >  	unsigned int f_max;
> >  	bool support_vsel;
> > +	unsigned int delay_line;
> >  };
> >  #endif /* __ASM_ARCH_IMX_ESDHC_H */
> > -- 
> > 1.7.2.rc3
> > 
> > 

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

* [PATCH v2 1/8] mmc: sdhci-esdhc-imx: add std tuning support for mx6sl
  2013-10-18 10:54 ` [PATCH v2 1/8] mmc: sdhci-esdhc-imx: add std tuning support for mx6sl Dong Aisheng
@ 2013-10-18 11:33   ` Shawn Guo
  2013-10-18 11:18     ` Dong Aisheng
  0 siblings, 1 reply; 16+ messages in thread
From: Shawn Guo @ 2013-10-18 11:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 18, 2013 at 06:54:14PM +0800, Dong Aisheng wrote:
> The mx6sl supports standard sdhci tuning, then esdhc_executing_tuning
> is only needed for mx6q/dl. We introduce is_imx6_usdhc() and
> is_imx6sl_usdhc() to handle the difference.
> 
> The standard tuning is enabled by setting ESDHC_TUNE_CTRL_STD_TUNING_EN bit
> in new register ESDHC_TUNE_CTRL and operates with new tuning bits
> defined in SDHCI_ACMD12_ERR register.
> 
> Note: mx6sl can also work on the old manually tuning mode as mx6q/dl if
> not enable standard tuning mode.
> 
> Signed-off-by: Dong Aisheng <b29396@freescale.com>
> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c |   90 +++++++++++++++++++++++++++++-------
>  1 files changed, 73 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index c84c808..a4e0e3b 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -51,6 +51,11 @@
>  #define  ESDHC_TUNE_CTRL_MIN		0
>  #define  ESDHC_TUNE_CTRL_MAX		((1 << 7) - 1)
>  
> +#define ESDHC_TUNING_CTRL		0xcc
> +#define ESDHC_STD_TUNING_EN		(1 << 24)
> +/* NOTE: the minimum valid tuning start tap for mx6sl is 1 */
> +#define ESDHC_TUNING_START_TAP		0x1
> +
>  #define ESDHC_TUNING_BLOCK_PATTERN_LEN	64
>  
>  /* pinctrl state */
> @@ -94,6 +99,12 @@
>   * integrated on the i.MX6 series.
>   */
>  #define ESDHC_FLAG_USDHC		BIT(3)
> +/* The IP supports manual tuning process */
> +#define ESDHC_FLAG_MAN_TUNING		BIT(4)
> +/* The IP supports standard tuning process */
> +#define ESDHC_FLAG_STD_TUNING		BIT(4)

BIT(4) for both flags?

Shawn

> +/* The IP has SDHCI_CAPABILITIES_1 register */
> +#define ESDHC_FLAG_HAVE_CAP1		BIT(5)
>  
>  struct esdhc_soc_data {
>  	u32 flags;
> @@ -116,7 +127,12 @@ static struct esdhc_soc_data esdhc_imx53_data = {
>  };
>  
>  static struct esdhc_soc_data usdhc_imx6q_data = {
> -	.flags = ESDHC_FLAG_USDHC,
> +	.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_MAN_TUNING,
> +};
> +
> +static struct esdhc_soc_data usdhc_imx6sl_data = {
> +	.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
> +			| ESDHC_FLAG_HAVE_CAP1,
>  };
>  
>  struct pltfm_imx_data {
> @@ -159,6 +175,7 @@ static const struct of_device_id imx_esdhc_dt_ids[] = {
>  	{ .compatible = "fsl,imx35-esdhc", .data = &esdhc_imx35_data, },
>  	{ .compatible = "fsl,imx51-esdhc", .data = &esdhc_imx51_data, },
>  	{ .compatible = "fsl,imx53-esdhc", .data = &esdhc_imx53_data, },
> +	{ .compatible = "fsl,imx6sl-usdhc", .data = &usdhc_imx6sl_data, },
>  	{ .compatible = "fsl,imx6q-usdhc", .data = &usdhc_imx6q_data, },
>  	{ /* sentinel */ }
>  };
> @@ -222,9 +239,16 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
>  		}
>  	}
>  
> -	if (unlikely(reg == SDHCI_CAPABILITIES_1) && esdhc_is_usdhc(imx_data))
> -		val = SDHCI_SUPPORT_DDR50 | SDHCI_SUPPORT_SDR104
> -				| SDHCI_SUPPORT_SDR50;
> +	if (unlikely(reg == SDHCI_CAPABILITIES_1)) {
> +		if (esdhc_is_usdhc(imx_data)) {
> +			if (imx_data->socdata->flags & ESDHC_FLAG_HAVE_CAP1)
> +				val = readl(host->ioaddr + SDHCI_CAPABILITIES) & 0xFFFF;
> +			else
> +				/* imx6q/dl does not have cap_1 register, fake one */
> +				val = SDHCI_SUPPORT_DDR50 | SDHCI_SUPPORT_SDR104
> +					| SDHCI_SUPPORT_SDR50;
> +		}
> +	}
>  
>  	if (unlikely(reg == SDHCI_MAX_CURRENT) && esdhc_is_usdhc(imx_data)) {
>  		val = 0;
> @@ -331,13 +355,18 @@ static u16 esdhc_readw_le(struct sdhci_host *host, int reg)
>  			ret |= SDHCI_CTRL_VDD_180;
>  
>  		if (esdhc_is_usdhc(imx_data)) {
> -			val = readl(host->ioaddr + ESDHC_MIX_CTRL);
> -			if (val & ESDHC_MIX_CTRL_EXE_TUNE)
> -				ret |= SDHCI_CTRL_EXEC_TUNING;
> -			if (val & ESDHC_MIX_CTRL_SMPCLK_SEL)
> -				ret |= SDHCI_CTRL_TUNED_CLK;
> +			if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
> +				val = readl(host->ioaddr + ESDHC_MIX_CTRL);
> +			else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING)
> +				/* the std tuning bits is in ACMD12_ERR for imx6sl */
> +				val = readl(host->ioaddr + SDHCI_ACMD12_ERR);
>  		}
>  
> +		if (val & ESDHC_MIX_CTRL_EXE_TUNE)
> +			ret |= SDHCI_CTRL_EXEC_TUNING;
> +		if (val & ESDHC_MIX_CTRL_SMPCLK_SEL)
> +			ret |= SDHCI_CTRL_TUNED_CLK;
> +
>  		ret |= (imx_data->uhs_mode & SDHCI_CTRL_UHS_MASK);
>  		ret &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
>  
> @@ -370,12 +399,37 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
>  			new_val &= ~ESDHC_VENDOR_SPEC_VSELECT;
>  		writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC);
>  		imx_data->uhs_mode = val & SDHCI_CTRL_UHS_MASK;
> -		new_val = readl(host->ioaddr + ESDHC_MIX_CTRL);
> -		if (val & SDHCI_CTRL_TUNED_CLK)
> -			new_val |= ESDHC_MIX_CTRL_SMPCLK_SEL;
> -		else
> -			new_val &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
> -		writel(new_val , host->ioaddr + ESDHC_MIX_CTRL);
> +		if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) {
> +			new_val = readl(host->ioaddr + ESDHC_MIX_CTRL);
> +			if (val & SDHCI_CTRL_TUNED_CLK)
> +				new_val |= ESDHC_MIX_CTRL_SMPCLK_SEL;
> +			else
> +				new_val &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
> +			writel(new_val , host->ioaddr + ESDHC_MIX_CTRL);
> +		} else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
> +			u32 v = readl(host->ioaddr + SDHCI_ACMD12_ERR);
> +			u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL);
> +			new_val = readl(host->ioaddr + ESDHC_TUNING_CTRL);
> +			if (val & SDHCI_CTRL_EXEC_TUNING) {
> +				new_val |= ESDHC_STD_TUNING_EN |
> +						ESDHC_TUNING_START_TAP;
> +				v |= ESDHC_MIX_CTRL_EXE_TUNE;
> +				m |= ESDHC_MIX_CTRL_FBCLK_SEL;
> +			} else {
> +				new_val &= ~ESDHC_STD_TUNING_EN;
> +				v &= ~ESDHC_MIX_CTRL_EXE_TUNE;
> +				m &= ~ESDHC_MIX_CTRL_FBCLK_SEL;
> +			}
> +
> +			if (val & SDHCI_CTRL_TUNED_CLK)
> +				v |= ESDHC_MIX_CTRL_SMPCLK_SEL;
> +			else
> +				v &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
> +
> +			writel(new_val, host->ioaddr + ESDHC_TUNING_CTRL);
> +			writel(v, host->ioaddr + SDHCI_ACMD12_ERR);
> +			writel(m, host->ioaddr + ESDHC_MIX_CTRL);
> +		}
>  		return;
>  	case SDHCI_TRANSFER_MODE:
>  		if ((imx_data->socdata->flags & ESDHC_FLAG_MULTIBLK_NO_INT)
> @@ -774,7 +828,7 @@ static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
>  	return esdhc_change_pinstate(host, uhs);
>  }
>  
> -static const struct sdhci_ops sdhci_esdhc_ops = {
> +static struct sdhci_ops sdhci_esdhc_ops = {
>  	.read_l = esdhc_readl_le,
>  	.read_w = esdhc_readw_le,
>  	.write_l = esdhc_writel_le,
> @@ -786,7 +840,6 @@ static const struct sdhci_ops sdhci_esdhc_ops = {
>  	.get_ro = esdhc_pltfm_get_ro,
>  	.platform_bus_width = esdhc_pltfm_bus_width,
>  	.set_uhs_signaling = esdhc_set_uhs_signaling,
> -	.platform_execute_tuning = esdhc_executing_tuning,
>  };
>  
>  static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
> @@ -922,6 +975,9 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
>  	if (esdhc_is_usdhc(imx_data))
>  		writel(0x08100810, host->ioaddr + ESDHC_WTMK_LVL);
>  
> +	if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
> +		sdhci_esdhc_ops.platform_execute_tuning =
> +					esdhc_executing_tuning;
>  	boarddata = &imx_data->boarddata;
>  	if (sdhci_esdhc_imx_probe_dt(pdev, boarddata) < 0) {
>  		if (!host->mmc->parent->platform_data) {
> -- 
> 1.7.2.rc3
> 
> 

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

* [PATCH v2 5/8] mmc: sdhci-esdhc-imx: add delay line setting support
  2013-10-18 11:57       ` Shawn Guo
@ 2013-10-18 11:41         ` Dong Aisheng
  0 siblings, 0 replies; 16+ messages in thread
From: Dong Aisheng @ 2013-10-18 11:41 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 18, 2013 at 07:57:56PM +0800, Shawn Guo wrote:
> On Fri, Oct 18, 2013 at 07:30:47PM +0800, Dong Aisheng wrote:
> > On Fri, Oct 18, 2013 at 07:42:35PM +0800, Shawn Guo wrote:
> > > On Fri, Oct 18, 2013 at 06:54:18PM +0800, Dong Aisheng wrote:
> > > > The DLL(Delay Line) is newly added to assist in sampling read data.
> > > > The DLL provides the ability to programmatically select a quantized
> > > > delay (in fractions of the clock period) regardless of on-chip variations
> > > > such as process, voltage and temperature (PVT).
> > > > 
> > > > This patch adds a user interface to set slave delay line via device tree.
> > > > It's usually used in high speed mode like mmc DDR mode when the signal
> > > > quality is not good caused by board design, e.g. the signal path is too long.
> > > > User can manual set delay line to find a suitable data sampling window
> > > > for card to work properly.
> > > > 
> > > > Signed-off-by: Dong Aisheng <b29396@freescale.com>
> > > > ---
> > > >  .../devicetree/bindings/mmc/fsl-imx-esdhc.txt      |    5 +++++
> > > >  drivers/mmc/host/sdhci-esdhc-imx.c                 |   18 ++++++++++++++++++
> > > >  include/linux/platform_data/mmc-esdhc-imx.h        |    1 +
> > > >  3 files changed, 24 insertions(+), 0 deletions(-)
> > > > 
> > > > diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
> > > > index 1dd6225..78a45c5 100644
> > > > --- a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
> > > > +++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
> > > > @@ -12,6 +12,11 @@ Required properties:
> > > >  Optional properties:
> > > >  - fsl,cd-controller : Indicate to use controller internal card detection
> > > >  - fsl,wp-controller : Indicate to use controller internal write protection
> > > > +- fsl,delay-line : Specify the number of delay cells for override mode.
> > > > +  This is used to set the clock delay for DLL(Delay Line) on override mode
> > > > +  to select a proper data sampling window in case the clock quality is not good
> > > > +  due to signal path is too long on the board.
> > > > +  please refer to DLL chapter in RM for details.
> > > 
> > > It might be better to reword it like:
> > > 
> > > Please refer to eSDHC/uSDHC DLL_CTRL register bit field
> > > DLL_CTRL_SLV_OVERRIDE_VAL in Reference Manual for details.
> > > 
> > 
> > There is a DLL (Delay Line) chapter in the reference manual which
> > has more detailed descriptions on the delay line including override mode.
> > So i think it may be better to point user to the DLL chapter for understanding,
> > then naturally user will refer to register for bit defines later too.
> > Does it make sense?
> 
> Okay.  But "eSDHC/uSDHC chapter, DLL (Delay Line) section" please.
> 

Okay, i'm fine with it.

Regards
Dong Aisheng
> Shawn

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

* [PATCH v2 5/8] mmc: sdhci-esdhc-imx: add delay line setting support
  2013-10-18 10:54 ` [PATCH v2 5/8] mmc: sdhci-esdhc-imx: add delay line setting support Dong Aisheng
@ 2013-10-18 11:42   ` Shawn Guo
  2013-10-18 11:30     ` Dong Aisheng
  0 siblings, 1 reply; 16+ messages in thread
From: Shawn Guo @ 2013-10-18 11:42 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 18, 2013 at 06:54:18PM +0800, Dong Aisheng wrote:
> The DLL(Delay Line) is newly added to assist in sampling read data.
> The DLL provides the ability to programmatically select a quantized
> delay (in fractions of the clock period) regardless of on-chip variations
> such as process, voltage and temperature (PVT).
> 
> This patch adds a user interface to set slave delay line via device tree.
> It's usually used in high speed mode like mmc DDR mode when the signal
> quality is not good caused by board design, e.g. the signal path is too long.
> User can manual set delay line to find a suitable data sampling window
> for card to work properly.
> 
> Signed-off-by: Dong Aisheng <b29396@freescale.com>
> ---
>  .../devicetree/bindings/mmc/fsl-imx-esdhc.txt      |    5 +++++
>  drivers/mmc/host/sdhci-esdhc-imx.c                 |   18 ++++++++++++++++++
>  include/linux/platform_data/mmc-esdhc-imx.h        |    1 +
>  3 files changed, 24 insertions(+), 0 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
> index 1dd6225..78a45c5 100644
> --- a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
> +++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
> @@ -12,6 +12,11 @@ Required properties:
>  Optional properties:
>  - fsl,cd-controller : Indicate to use controller internal card detection
>  - fsl,wp-controller : Indicate to use controller internal write protection
> +- fsl,delay-line : Specify the number of delay cells for override mode.
> +  This is used to set the clock delay for DLL(Delay Line) on override mode
> +  to select a proper data sampling window in case the clock quality is not good
> +  due to signal path is too long on the board.
> +  please refer to DLL chapter in RM for details.

It might be better to reword it like:

Please refer to eSDHC/uSDHC DLL_CTRL register bit field
DLL_CTRL_SLV_OVERRIDE_VAL in Reference Manual for details.

>  
>  Examples:
>  
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index c5c26bd..87d202b 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -46,6 +46,11 @@
>  /* Bits 3 and 6 are not SDHCI standard definitions */
>  #define  ESDHC_MIX_CTRL_SDHCI_MASK	0xb7
>  
> +/* dll control register */
> +#define ESDHC_DLL_CTRL			0x60
> +#define ESDHC_DLL_OVERRIDE_VAL_SHIFT	9
> +#define ESDHC_DLL_OVERRIDE_EN_SHIFT	8
> +
>  /* tune control register */
>  #define ESDHC_TUNE_CTRL_STATUS		0x68
>  #define  ESDHC_TUNE_CTRL_STEP		1
> @@ -817,6 +822,7 @@ static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
>  {
>  	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>  	struct pltfm_imx_data *imx_data = pltfm_host->priv;
> +	struct esdhc_platform_data *boarddata = &imx_data->boarddata;
>  
>  	switch (uhs) {
>  	case MMC_TIMING_UHS_SDR12:
> @@ -837,6 +843,15 @@ static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
>  				ESDHC_MIX_CTRL_DDREN,
>  				host->ioaddr + ESDHC_MIX_CTRL);
>  		imx_data->is_ddr = 1;
> +		if (boarddata->delay_line) {
> +			u32 v;
> +			v = boarddata->delay_line <<
> +				ESDHC_DLL_OVERRIDE_VAL_SHIFT |
> +				(1 << ESDHC_DLL_OVERRIDE_EN_SHIFT);
> +			if (is_imx53_esdhc(imx_data))
> +				v <<= 1;
> +			writel(v, host->ioaddr + ESDHC_DLL_CTRL);
> +		}
>  		break;
>  	}
>  
> @@ -901,6 +916,9 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
>  	else
>  		boarddata->support_vsel = true;
>  
> +	if (of_property_read_u32(np, "fsl,delay-line", &boarddata->delay_line))
> +		boarddata->delay_line = 0;
> +
>  	return 0;
>  }
>  #else
> diff --git a/include/linux/platform_data/mmc-esdhc-imx.h b/include/linux/platform_data/mmc-esdhc-imx.h
> index a0f5a8f..75f70f6 100644
> --- a/include/linux/platform_data/mmc-esdhc-imx.h
> +++ b/include/linux/platform_data/mmc-esdhc-imx.h
> @@ -45,5 +45,6 @@ struct esdhc_platform_data {
>  	int max_bus_width;
>  	unsigned int f_max;
>  	bool support_vsel;
> +	unsigned int delay_line;
>  };
>  #endif /* __ASM_ARCH_IMX_ESDHC_H */
> -- 
> 1.7.2.rc3
> 
> 

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

* [PATCH v2 0/8] mmc: sdhci-esdhc-imx: add std tuning for mx6sl and DDR mode support
  2013-10-18 10:54 [PATCH v2 0/8] mmc: sdhci-esdhc-imx: add std tuning for mx6sl and DDR mode support Dong Aisheng
                   ` (7 preceding siblings ...)
  2013-10-18 10:54 ` [PATCH v2 8/8] mmc: sdhci: remove unneeded call when have preset value quirk Dong Aisheng
@ 2013-10-18 11:46 ` Shawn Guo
  8 siblings, 0 replies; 16+ messages in thread
From: Shawn Guo @ 2013-10-18 11:46 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 18, 2013 at 06:54:13PM +0800, Dong Aisheng wrote:
> ChangeLog:
> v1->v2:
>  - Only a few minor changes on patch 1 and 5 based on comments from Shawn
>    while other patches have no change.
>  - rebase on Shawn's patch series
>    [PATCH v2 0/4] mmc: sdhci-esdhc-imx: eliminate enum imx_esdhc_type
> 
> Dong Aisheng (8):
>   mmc: sdhci-esdhc-imx: add std tuning support for mx6sl
>   mmc: sdhci-esdhc-imx: fix reading cap_1 register value for mx6sl
>   mmc: sdhci: report error once the maximum tuning loops exhausted or
>     timeout
>   mmc: sdhci-esdhc-imx: add DDR mode support for mx6
>   mmc: sdhci-esdhc-imx: add delay line setting support
>   mmc: sdhci-esdhc-imx: enable SDR50 tuning for imx6q/dl
>   mmc: sdhci-esdhc-imx: add preset value quirk for mx6
>   mmc: sdhci: remove unneeded call when have preset value quirk

Other than 2 small comments I gave on patch #1 and #5, for the series:

Acked-by: Shawn Guo <shawn.guo@linaro.org>

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

* [PATCH v2 5/8] mmc: sdhci-esdhc-imx: add delay line setting support
  2013-10-18 11:30     ` Dong Aisheng
@ 2013-10-18 11:57       ` Shawn Guo
  2013-10-18 11:41         ` Dong Aisheng
  0 siblings, 1 reply; 16+ messages in thread
From: Shawn Guo @ 2013-10-18 11:57 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 18, 2013 at 07:30:47PM +0800, Dong Aisheng wrote:
> On Fri, Oct 18, 2013 at 07:42:35PM +0800, Shawn Guo wrote:
> > On Fri, Oct 18, 2013 at 06:54:18PM +0800, Dong Aisheng wrote:
> > > The DLL(Delay Line) is newly added to assist in sampling read data.
> > > The DLL provides the ability to programmatically select a quantized
> > > delay (in fractions of the clock period) regardless of on-chip variations
> > > such as process, voltage and temperature (PVT).
> > > 
> > > This patch adds a user interface to set slave delay line via device tree.
> > > It's usually used in high speed mode like mmc DDR mode when the signal
> > > quality is not good caused by board design, e.g. the signal path is too long.
> > > User can manual set delay line to find a suitable data sampling window
> > > for card to work properly.
> > > 
> > > Signed-off-by: Dong Aisheng <b29396@freescale.com>
> > > ---
> > >  .../devicetree/bindings/mmc/fsl-imx-esdhc.txt      |    5 +++++
> > >  drivers/mmc/host/sdhci-esdhc-imx.c                 |   18 ++++++++++++++++++
> > >  include/linux/platform_data/mmc-esdhc-imx.h        |    1 +
> > >  3 files changed, 24 insertions(+), 0 deletions(-)
> > > 
> > > diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
> > > index 1dd6225..78a45c5 100644
> > > --- a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
> > > +++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
> > > @@ -12,6 +12,11 @@ Required properties:
> > >  Optional properties:
> > >  - fsl,cd-controller : Indicate to use controller internal card detection
> > >  - fsl,wp-controller : Indicate to use controller internal write protection
> > > +- fsl,delay-line : Specify the number of delay cells for override mode.
> > > +  This is used to set the clock delay for DLL(Delay Line) on override mode
> > > +  to select a proper data sampling window in case the clock quality is not good
> > > +  due to signal path is too long on the board.
> > > +  please refer to DLL chapter in RM for details.
> > 
> > It might be better to reword it like:
> > 
> > Please refer to eSDHC/uSDHC DLL_CTRL register bit field
> > DLL_CTRL_SLV_OVERRIDE_VAL in Reference Manual for details.
> > 
> 
> There is a DLL (Delay Line) chapter in the reference manual which
> has more detailed descriptions on the delay line including override mode.
> So i think it may be better to point user to the DLL chapter for understanding,
> then naturally user will refer to register for bit defines later too.
> Does it make sense?

Okay.  But "eSDHC/uSDHC chapter, DLL (Delay Line) section" please.

Shawn

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

end of thread, other threads:[~2013-10-18 11:57 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-10-18 10:54 [PATCH v2 0/8] mmc: sdhci-esdhc-imx: add std tuning for mx6sl and DDR mode support Dong Aisheng
2013-10-18 10:54 ` [PATCH v2 1/8] mmc: sdhci-esdhc-imx: add std tuning support for mx6sl Dong Aisheng
2013-10-18 11:33   ` Shawn Guo
2013-10-18 11:18     ` Dong Aisheng
2013-10-18 10:54 ` [PATCH v2 2/8] mmc: sdhci-esdhc-imx: fix reading cap_1 register value " Dong Aisheng
2013-10-18 10:54 ` [PATCH v2 3/8] mmc: sdhci: report error once the maximum tuning loops exhausted or timeout Dong Aisheng
2013-10-18 10:54 ` [PATCH v2 4/8] mmc: sdhci-esdhc-imx: add DDR mode support for mx6 Dong Aisheng
2013-10-18 10:54 ` [PATCH v2 5/8] mmc: sdhci-esdhc-imx: add delay line setting support Dong Aisheng
2013-10-18 11:42   ` Shawn Guo
2013-10-18 11:30     ` Dong Aisheng
2013-10-18 11:57       ` Shawn Guo
2013-10-18 11:41         ` Dong Aisheng
2013-10-18 10:54 ` [PATCH v2 6/8] mmc: sdhci-esdhc-imx: enable SDR50 tuning for imx6q/dl Dong Aisheng
2013-10-18 10:54 ` [PATCH v2 7/8] mmc: sdhci-esdhc-imx: add preset value quirk for mx6 Dong Aisheng
2013-10-18 10:54 ` [PATCH v2 8/8] mmc: sdhci: remove unneeded call when have preset value quirk Dong Aisheng
2013-10-18 11:46 ` [PATCH v2 0/8] mmc: sdhci-esdhc-imx: add std tuning for mx6sl and DDR mode support Shawn Guo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).