All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv3 0/3] mmc: dw_mmc: Make the use of the hold reg generic
@ 2013-12-09  4:51 dinguyen
  2013-12-09  4:51 ` [PATCHv3 1/3] mmc: dw_mmc: Enable the hold reg for certain speed modes dinguyen
                   ` (3 more replies)
  0 siblings, 4 replies; 11+ messages in thread
From: dinguyen @ 2013-12-09  4:51 UTC (permalink / raw)
  To: dinh.linux, arnd, cjb, jh80.chung, tgih.jun, heiko, dianders,
	alim.akhtar, bzhao
  Cc: linux-mmc, Dinh Nguyen

From: Dinh Nguyen <dinguyen@altera.com>

Hi,

This is v3 of the patch series that makes the setting of the SDMMC_CMD_USE_HOLD_REG
bit generic.

v3 differences:

* Read the IHR(Implement HOLD Register) bit in the HCON register. Will not use
the SDMMC_CMD_USE_HOLD_REG if the IHR bit is 0 and cclk_in_drv = 0.

* Changes the cclk_in_drv and use_hold_reg register type from bool to u32.

* Add can_use_hold_reg variable that is condition on whether or not we can use
the hold reg.

* v2 of (1/3, 2/3) was Acked-by: and Tested-by: Heiko Stuebner <heiko@sntech.de>

Thanks,

Dinh Nguyen (3):
  mmc: dw_mmc: Enable the hold reg for certain speed modes
  mmc: dw_mmc-pltm: Remove Rockchip's custom dw_mmc driver structure
  mmc: dw_mmc-exynos: Remove Exynos' custom prepare_command function

 drivers/mmc/host/dw_mmc-exynos.c |   14 -----------
 drivers/mmc/host/dw_mmc-pltfm.c  |   12 +--------
 drivers/mmc/host/dw_mmc.c        |   51 ++++++++++++++++++++++++++++++++++++++
 drivers/mmc/host/dw_mmc.h        |    4 +++
 include/linux/mmc/dw_mmc.h       |    3 +++
 5 files changed, 59 insertions(+), 25 deletions(-)

-- 
1.7.9.5



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

* [PATCHv3 1/3] mmc: dw_mmc: Enable the hold reg for certain speed modes
  2013-12-09  4:51 [PATCHv3 0/3] mmc: dw_mmc: Make the use of the hold reg generic dinguyen
@ 2013-12-09  4:51 ` dinguyen
  2013-12-09  9:56   ` Heiko Stübner
  2013-12-16  4:23   ` Seungwon Jeon
  2013-12-09  4:51 ` [PATCHv3 2/3] mmc: dw_mmc-pltm: Remove Rockchip's custom dw_mmc driver structure dinguyen
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 11+ messages in thread
From: dinguyen @ 2013-12-09  4:51 UTC (permalink / raw)
  To: dinh.linux, arnd, cjb, jh80.chung, tgih.jun, heiko, dianders,
	alim.akhtar, bzhao
  Cc: linux-mmc, Dinh Nguyen

From: Dinh Nguyen <dinguyen@altera.com>

This patch will enable the SDMMC_CMD_USE_HOLD_REG bit when the slot is
operating all timing modes, except for SDR50, DDR50, SDR104, and MMC_HS200.

According to the Synopsys databook :"To meet the relatively high Input Hold
Time requirement for SDR12, SDR25, and other MMC speed modes, you should
program bit[29]use_hold_Reg of the CMD register to 1'b1;"..."However, for
the higher speed modes of SDR104, SDR50 and DDR50, you can meet the much
smaller Input Hold Time requirement of 0.8ns by bypassing the Hold Register
(Path A in Figure 10-8, programming CMD.use_hold_reg = 1'b0) and then adding
delay elements on the output path as indicated.

Also, "Never set CMD.use_hold_reg = 1 and cclk_in_drv phase shift to 0 at the
same time. This would add an extra one-cycle delay on the output path, resulting
in incorrect behavior."

This patch also checks the IHR(Implement Hold Register) in the HCON register.

This information is taking from the v2.50a of the Synopsys Designware Cores
Mobile Storage Host Databook.

Signed-off-by: Dinh Nguyen <dinguyen@altera.com>
Acked-by: Heiko Stuebner <heiko@sntech.de>
Tested-by: Heiko Stuebner <heiko@sntech.de>
---
v3: Read the IHR(Implement Hold Register) in the HCON
v2: Add check for cclk_in_drv phase shift in conjunction with use_hold_reg.
---
 drivers/mmc/host/dw_mmc.c  |   51 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/mmc/host/dw_mmc.h  |    4 ++++
 include/linux/mmc/dw_mmc.h |    3 +++
 3 files changed, 58 insertions(+)

diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 4bce0de..480dafe 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -279,6 +279,9 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
 			cmdr |= SDMMC_CMD_DAT_WR;
 	}
 
+	if (slot->host->use_hold_reg)
+		cmdr |= SDMMC_CMD_USE_HOLD_REG;
+
 	if (drv_data && drv_data->prepare_command)
 		drv_data->prepare_command(slot->host, &cmdr);
 
@@ -969,6 +972,24 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	mci_writel(slot->host, UHS_REG, regs);
 	slot->host->timing = ios->timing;
 
+	/* Per Synopsys spec, use_hold_reg should be set for all modes except for
+	 * high-speed SDR50, DDR50, SDR104, and MMC_HS200. However, use_hold_reg
+	 * should be cleared if the cclk_in_drv is 0.
+	 */
+	switch (slot->host->timing) {
+	case MMC_TIMING_UHS_SDR50:
+	case MMC_TIMING_UHS_SDR104:
+	case MMC_TIMING_UHS_DDR50:
+	case MMC_TIMING_MMC_HS200:
+		slot->host->use_hold_reg = 0;
+		break;
+	default:
+		slot->host->use_hold_reg = 1;
+	}
+
+	if (slot->host->can_use_hold_reg == 0)
+		slot->host->use_hold_reg = 0;
+
 	/*
 	 * Use mirror of ios->clock to prevent race with mmc
 	 * core ios update when finding the minimum.
@@ -2339,6 +2360,8 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
 	const struct dw_mci_drv_data *drv_data = host->drv_data;
 	int idx, ret;
 	u32 clock_frequency;
+	int sdr_timing[2];
+	int ddr_timing[2];
 
 	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata) {
@@ -2389,6 +2412,25 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
 	if (of_find_property(np, "caps2-mmc-hs200-1_2v", NULL))
 		pdata->caps2 |= MMC_CAP2_HS200_1_2V_SDR;
 
+	/* Check for the "samsung,dw-mshc-sdr-timing" and the
+	 * "samsung,dw-mshc-ddr-timing" bindings as this will tell us if we
+	 * can safely set the SDMMC_CMD_USE_HOLD_REG bit. The second paramater
+	 * in these 2 bindings is the value of the cclk_in_drv. If cclk_in_drv
+	 * is 0, we cannot set the SDMMC_CMD_USE_HOLD_REG bit. The default
+	 * behavior will be to set cclk_in_drv, as some platforms do not have
+	 * to set the sdr or ddr timing parameters.
+	 */
+	sdr_timing[1] = ddr_timing[1] = 1;
+	of_property_read_u32_array(np,
+			"samsung,dw-mshc-sdr-timing", sdr_timing, 2);
+
+	of_property_read_u32_array(np,
+			"samsung,dw-mshc-ddr-timing", ddr_timing, 2);
+
+	pdata->cclk_in_drv = 1;
+	if ((sdr_timing[1] == 0) || (ddr_timing[1] == 0))
+		pdata->cclk_in_drv = 0;
+
 	return pdata;
 }
 
@@ -2495,6 +2537,15 @@ int dw_mci_probe(struct dw_mci *host)
 		goto err_regulator;
 	}
 
+	/* Check to see if the HOLD REG is implemented. */
+	host->can_use_hold_reg = (mci_readl(host, HCON) & SDMMC_HCON_IHR) >> 22;
+
+	/* Can only use the HOLD REG is both conditions are true:
+	 * Hardware has implemented HOLD_REG and
+	 * cclk_in_drv is non-zero.
+	 */
+	host->can_use_hold_reg &= host->pdata->cclk_in_drv;
+
 	host->quirks = host->pdata->quirks;
 
 	spin_lock_init(&host->lock);
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index 6bf24ab..dfd05c9 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -145,6 +145,10 @@
 #define SDMMC_IDMAC_ENABLE		BIT(7)
 #define SDMMC_IDMAC_FB			BIT(1)
 #define SDMMC_IDMAC_SWRESET		BIT(0)
+
+/* Hardware Configuration(HCON) register */
+#define SDMMC_HCON_IHR			BIT(22)
+
 /* Version ID register define */
 #define SDMMC_GET_VERID(x)		((x) & 0xFFFF)
 /* Card read threshold */
diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
index 6ce7d2c..2b5b8bf 100644
--- a/include/linux/mmc/dw_mmc.h
+++ b/include/linux/mmc/dw_mmc.h
@@ -191,6 +191,8 @@ struct dw_mci {
 	struct regulator	*vmmc;	/* Power regulator */
 	unsigned long		irq_flags; /* IRQ flags */
 	int			irq;
+	u32			can_use_hold_reg;
+	bool			use_hold_reg;
 };
 
 /* DMA ops for Internal/External DMAC interface */
@@ -238,6 +240,7 @@ struct dw_mci_board {
 	u32 caps;	/* Capabilities */
 	u32 caps2;	/* More capabilities */
 	u32 pm_caps;	/* PM capabilities */
+	u32 cclk_in_drv;	/*cclk_in_drv phase shift */
 	/*
 	 * Override fifo depth. If 0, autodetect it from the FIFOTH register,
 	 * but note that this may not be reliable after a bootloader has used
-- 
1.7.9.5



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

* [PATCHv3 2/3] mmc: dw_mmc-pltm: Remove Rockchip's custom dw_mmc driver structure
  2013-12-09  4:51 [PATCHv3 0/3] mmc: dw_mmc: Make the use of the hold reg generic dinguyen
  2013-12-09  4:51 ` [PATCHv3 1/3] mmc: dw_mmc: Enable the hold reg for certain speed modes dinguyen
@ 2013-12-09  4:51 ` dinguyen
  2013-12-09  4:51 ` [PATCHv3 3/3] mmc: dw_mmc-exynos: Remove Exynos' custom prepare_command function dinguyen
  2013-12-09 16:12 ` [PATCHv3 0/3] mmc: dw_mmc: Make the use of the hold reg generic Arnd Bergmann
  3 siblings, 0 replies; 11+ messages in thread
From: dinguyen @ 2013-12-09  4:51 UTC (permalink / raw)
  To: dinh.linux, arnd, cjb, jh80.chung, tgih.jun, heiko, dianders,
	alim.akhtar, bzhao
  Cc: linux-mmc, Dinh Nguyen

From: Dinh Nguyen <dinguyen@altera.com>

Rockchip's implementation of the dw_mmc controller only requires the setting
of the SDMMC_CMD_USE_HOLD_REG on every command. With the patch to set the
SDMMC_CMD_USE_HOLD_REG by checking the slot's speed mode, this Rockchip
custom driver structure is no longer necessary.

Signed-off-by: Dinh Nguyen <dinguyen@altera.com>
Acked-by: Heiko Stuebner <heiko@sntech.de>
Tested-by: Heiko Stuebner <heiko@sntech.de>
---
v3: none
v2: none
---
 drivers/mmc/host/dw_mmc-pltfm.c |   12 +-----------
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c
index 5c49656..8f15d05 100644
--- a/drivers/mmc/host/dw_mmc-pltfm.c
+++ b/drivers/mmc/host/dw_mmc-pltfm.c
@@ -25,15 +25,6 @@
 #include "dw_mmc.h"
 #include "dw_mmc-pltfm.h"
 
-static void dw_mci_rockchip_prepare_command(struct dw_mci *host, u32 *cmdr)
-{
-	*cmdr |= SDMMC_CMD_USE_HOLD_REG;
-}
-
-static const struct dw_mci_drv_data rockchip_drv_data = {
-	.prepare_command	= dw_mci_rockchip_prepare_command,
-};
-
 int dw_mci_pltfm_register(struct platform_device *pdev,
 			  const struct dw_mci_drv_data *drv_data)
 {
@@ -90,8 +81,7 @@ EXPORT_SYMBOL_GPL(dw_mci_pltfm_pmops);
 
 static const struct of_device_id dw_mci_pltfm_match[] = {
 	{ .compatible = "snps,dw-mshc", },
-	{ .compatible = "rockchip,rk2928-dw-mshc",
-		.data = &rockchip_drv_data },
+	{ .compatible = "rockchip,rk2928-dw-mshc", },
 	{},
 };
 MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match);
-- 
1.7.9.5



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

* [PATCHv3 3/3] mmc: dw_mmc-exynos: Remove Exynos' custom prepare_command function
  2013-12-09  4:51 [PATCHv3 0/3] mmc: dw_mmc: Make the use of the hold reg generic dinguyen
  2013-12-09  4:51 ` [PATCHv3 1/3] mmc: dw_mmc: Enable the hold reg for certain speed modes dinguyen
  2013-12-09  4:51 ` [PATCHv3 2/3] mmc: dw_mmc-pltm: Remove Rockchip's custom dw_mmc driver structure dinguyen
@ 2013-12-09  4:51 ` dinguyen
  2013-12-09 16:12 ` [PATCHv3 0/3] mmc: dw_mmc: Make the use of the hold reg generic Arnd Bergmann
  3 siblings, 0 replies; 11+ messages in thread
From: dinguyen @ 2013-12-09  4:51 UTC (permalink / raw)
  To: dinh.linux, arnd, cjb, jh80.chung, tgih.jun, heiko, dianders,
	alim.akhtar, bzhao
  Cc: linux-mmc, Dinh Nguyen

From: Dinh Nguyen <dinguyen@altera.com>

The Exynos prepare_command function is only checking when to set the
SDMMC_CMD_USE_HOLD_REG bit. Now that there is a generic way to check
on when to set SDMMC_CMD_USE_HOLD_REG bit.

Signed-off-by: Dinh Nguyen <dinguyen@altera.com>
---
v3: none
v2: none
---
 drivers/mmc/host/dw_mmc-exynos.c |   14 --------------
 1 file changed, 14 deletions(-)

diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c
index 3423c5e..8ce24c8 100644
--- a/drivers/mmc/host/dw_mmc-exynos.c
+++ b/drivers/mmc/host/dw_mmc-exynos.c
@@ -167,19 +167,6 @@ static int dw_mci_exynos_resume_noirq(struct device *dev)
 #define dw_mci_exynos_resume_noirq	NULL
 #endif /* CONFIG_PM_SLEEP */
 
-static void dw_mci_exynos_prepare_command(struct dw_mci *host, u32 *cmdr)
-{
-	/*
-	 * Exynos4412 and Exynos5250 extends the use of CMD register with the
-	 * use of bit 29 (which is reserved on standard MSHC controllers) for
-	 * optionally bypassing the HOLD register for command and data. The
-	 * HOLD register should be bypassed in case there is no phase shift
-	 * applied on CMD/DATA that is sent to the card.
-	 */
-	if (SDMMC_CLKSEL_GET_DRV_WD3(mci_readl(host, CLKSEL)))
-		*cmdr |= SDMMC_CMD_USE_HOLD_REG;
-}
-
 static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios)
 {
 	struct dw_mci_exynos_priv_data *priv = host->priv;
@@ -397,7 +384,6 @@ static const struct dw_mci_drv_data exynos_drv_data = {
 	.caps			= exynos_dwmmc_caps,
 	.init			= dw_mci_exynos_priv_init,
 	.setup_clock		= dw_mci_exynos_setup_clock,
-	.prepare_command	= dw_mci_exynos_prepare_command,
 	.set_ios		= dw_mci_exynos_set_ios,
 	.parse_dt		= dw_mci_exynos_parse_dt,
 	.execute_tuning		= dw_mci_exynos_execute_tuning,
-- 
1.7.9.5



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

* Re: [PATCHv3 1/3] mmc: dw_mmc: Enable the hold reg for certain speed modes
  2013-12-09  4:51 ` [PATCHv3 1/3] mmc: dw_mmc: Enable the hold reg for certain speed modes dinguyen
@ 2013-12-09  9:56   ` Heiko Stübner
  2013-12-09 16:15     ` Dinh Nguyen
  2013-12-16  4:23   ` Seungwon Jeon
  1 sibling, 1 reply; 11+ messages in thread
From: Heiko Stübner @ 2013-12-09  9:56 UTC (permalink / raw)
  To: dinguyen
  Cc: dinh.linux, arnd, cjb, jh80.chung, tgih.jun, dianders,
	alim.akhtar, bzhao, linux-mmc

Hi,

Am Montag, 9. Dezember 2013, 05:51:06 schrieb dinguyen@altera.com:
> From: Dinh Nguyen <dinguyen@altera.com>
> 
> This patch will enable the SDMMC_CMD_USE_HOLD_REG bit when the slot is
> operating all timing modes, except for SDR50, DDR50, SDR104, and MMC_HS200.
> 
> According to the Synopsys databook :"To meet the relatively high Input Hold
> Time requirement for SDR12, SDR25, and other MMC speed modes, you should
> program bit[29]use_hold_Reg of the CMD register to 1'b1;"..."However, for
> the higher speed modes of SDR104, SDR50 and DDR50, you can meet the much
> smaller Input Hold Time requirement of 0.8ns by bypassing the Hold Register
> (Path A in Figure 10-8, programming CMD.use_hold_reg = 1'b0) and then
> adding delay elements on the output path as indicated.
> 
> Also, "Never set CMD.use_hold_reg = 1 and cclk_in_drv phase shift to 0 at
> the same time. This would add an extra one-cycle delay on the output path,
> resulting in incorrect behavior."
> 
> This patch also checks the IHR(Implement Hold Register) in the HCON
> register.
> 
> This information is taking from the v2.50a of the Synopsys Designware Cores
> Mobile Storage Host Databook.
> 
> Signed-off-by: Dinh Nguyen <dinguyen@altera.com>
> Acked-by: Heiko Stuebner <heiko@sntech.de>
> Tested-by: Heiko Stuebner <heiko@sntech.de>
> ---
> v3: Read the IHR(Implement Hold Register) in the HCON
> v2: Add check for cclk_in_drv phase shift in conjunction with use_hold_reg.

just to say it still works with the v3 changes.

Interestingly, the rockchip manual does not specify the hcon register at all, 
but reading it, I get a value of 0x4c534c1 - letting BIT(22) be the required 
one.


Heiko

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

* Re: [PATCHv3 0/3] mmc: dw_mmc: Make the use of the hold reg generic
  2013-12-09  4:51 [PATCHv3 0/3] mmc: dw_mmc: Make the use of the hold reg generic dinguyen
                   ` (2 preceding siblings ...)
  2013-12-09  4:51 ` [PATCHv3 3/3] mmc: dw_mmc-exynos: Remove Exynos' custom prepare_command function dinguyen
@ 2013-12-09 16:12 ` Arnd Bergmann
  3 siblings, 0 replies; 11+ messages in thread
From: Arnd Bergmann @ 2013-12-09 16:12 UTC (permalink / raw)
  To: dinguyen
  Cc: dinh.linux, cjb, jh80.chung, tgih.jun, heiko, dianders,
	alim.akhtar, bzhao, linux-mmc

On Monday 09 December 2013, dinguyen@altera.com wrote:
> This is v3 of the patch series that makes the setting of the SDMMC_CMD_USE_HOLD_REG
> bit generic.
> 
> v3 differences:
> 
> * Read the IHR(Implement HOLD Register) bit in the HCON register. Will not use
> the SDMMC_CMD_USE_HOLD_REG if the IHR bit is 0 and cclk_in_drv = 0.
> 
> * Changes the cclk_in_drv and use_hold_reg register type from bool to u32.
> 
> * Add can_use_hold_reg variable that is condition on whether or not we can use
> the hold reg.
> 
> * v2 of (1/3, 2/3) was Acked-by: and Tested-by: Heiko Stuebner <heiko@sntech.de>
> 

Acked-by: Arnd Bergmann <arnd@arndb.de>

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

* Re: [PATCHv3 1/3] mmc: dw_mmc: Enable the hold reg for certain speed modes
  2013-12-09  9:56   ` Heiko Stübner
@ 2013-12-09 16:15     ` Dinh Nguyen
  0 siblings, 0 replies; 11+ messages in thread
From: Dinh Nguyen @ 2013-12-09 16:15 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: dinh.linux, arnd, cjb, jh80.chung, tgih.jun, dianders,
	alim.akhtar, bzhao, linux-mmc

On Mon, 2013-12-09 at 10:56 +0100, Heiko Stübner wrote:
> Hi,
> 
> Am Montag, 9. Dezember 2013, 05:51:06 schrieb dinguyen@altera.com:
> > From: Dinh Nguyen <dinguyen@altera.com>
> > 
> > This patch will enable the SDMMC_CMD_USE_HOLD_REG bit when the slot is
> > operating all timing modes, except for SDR50, DDR50, SDR104, and MMC_HS200.
> > 
> > According to the Synopsys databook :"To meet the relatively high Input Hold
> > Time requirement for SDR12, SDR25, and other MMC speed modes, you should
> > program bit[29]use_hold_Reg of the CMD register to 1'b1;"..."However, for
> > the higher speed modes of SDR104, SDR50 and DDR50, you can meet the much
> > smaller Input Hold Time requirement of 0.8ns by bypassing the Hold Register
> > (Path A in Figure 10-8, programming CMD.use_hold_reg = 1'b0) and then
> > adding delay elements on the output path as indicated.
> > 
> > Also, "Never set CMD.use_hold_reg = 1 and cclk_in_drv phase shift to 0 at
> > the same time. This would add an extra one-cycle delay on the output path,
> > resulting in incorrect behavior."
> > 
> > This patch also checks the IHR(Implement Hold Register) in the HCON
> > register.
> > 
> > This information is taking from the v2.50a of the Synopsys Designware Cores
> > Mobile Storage Host Databook.
> > 
> > Signed-off-by: Dinh Nguyen <dinguyen@altera.com>
> > Acked-by: Heiko Stuebner <heiko@sntech.de>
> > Tested-by: Heiko Stuebner <heiko@sntech.de>
> > ---
> > v3: Read the IHR(Implement Hold Register) in the HCON
> > v2: Add check for cclk_in_drv phase shift in conjunction with use_hold_reg.
> 
> just to say it still works with the v3 changes.

Thanks for testing.
> 
> Interestingly, the rockchip manual does not specify the hcon register at all, 
> but reading it, I get a value of 0x4c534c1 - letting BIT(22) be the required 
> one.

I believe that the hcon register is there for all versions of this IP,
as the driver is reading this register to get the bus data width.

But then again there this comment before the read:
/*
 * Get the host data width - this assumes that HCON has been set with
 * the correct values.
*/

Dinh
> 
> 
> Heiko
> 




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

* RE: [PATCHv3 1/3] mmc: dw_mmc: Enable the hold reg for certain speed modes
  2013-12-09  4:51 ` [PATCHv3 1/3] mmc: dw_mmc: Enable the hold reg for certain speed modes dinguyen
  2013-12-09  9:56   ` Heiko Stübner
@ 2013-12-16  4:23   ` Seungwon Jeon
  2013-12-16  4:44     ` Dinh Nguyen
  1 sibling, 1 reply; 11+ messages in thread
From: Seungwon Jeon @ 2013-12-16  4:23 UTC (permalink / raw)
  To: dinguyen, dinh.linux, arnd, cjb, jh80.chung, heiko, dianders,
	alim.akhtar, bzhao
  Cc: linux-mmc

On Mon, December 09, 2013, Dinh Nguyen wrote:
> From: Dinh Nguyen <dinguyen@altera.com>
> 
> This patch will enable the SDMMC_CMD_USE_HOLD_REG bit when the slot is
> operating all timing modes, except for SDR50, DDR50, SDR104, and MMC_HS200.
> 
> According to the Synopsys databook :"To meet the relatively high Input Hold
> Time requirement for SDR12, SDR25, and other MMC speed modes, you should
> program bit[29]use_hold_Reg of the CMD register to 1'b1;"..."However, for
> the higher speed modes of SDR104, SDR50 and DDR50, you can meet the much
> smaller Input Hold Time requirement of 0.8ns by bypassing the Hold Register
> (Path A in Figure 10-8, programming CMD.use_hold_reg = 1'b0) and then adding
> delay elements on the output path as indicated.
> 
> Also, "Never set CMD.use_hold_reg = 1 and cclk_in_drv phase shift to 0 at the
> same time. This would add an extra one-cycle delay on the output path, resulting
> in incorrect behavior."
> 
> This patch also checks the IHR(Implement Hold Register) in the HCON register.
> 
> This information is taking from the v2.50a of the Synopsys Designware Cores
> Mobile Storage Host Databook.

If cclk_in_drv has non-zero, hold_reg_bit should be 1'b1 for SDR50, DDR50, SDR104, and MMC_HS200 mode.
Can you check it?

And samsung,dw-mshc-sdr(ddr)-timing property is still specific for Exynos.
It will be modified with adding new cell element soon.

Thanks,
Seungwon Jeon

> 
> Signed-off-by: Dinh Nguyen <dinguyen@altera.com>
> Acked-by: Heiko Stuebner <heiko@sntech.de>
> Tested-by: Heiko Stuebner <heiko@sntech.de>
> ---
> v3: Read the IHR(Implement Hold Register) in the HCON
> v2: Add check for cclk_in_drv phase shift in conjunction with use_hold_reg.
> ---
>  drivers/mmc/host/dw_mmc.c  |   51 ++++++++++++++++++++++++++++++++++++++++++++
>  drivers/mmc/host/dw_mmc.h  |    4 ++++
>  include/linux/mmc/dw_mmc.h |    3 +++
>  3 files changed, 58 insertions(+)
> 
> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> index 4bce0de..480dafe 100644
> --- a/drivers/mmc/host/dw_mmc.c
> +++ b/drivers/mmc/host/dw_mmc.c
> @@ -279,6 +279,9 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
>  			cmdr |= SDMMC_CMD_DAT_WR;
>  	}
> 
> +	if (slot->host->use_hold_reg)
> +		cmdr |= SDMMC_CMD_USE_HOLD_REG;
> +
>  	if (drv_data && drv_data->prepare_command)
>  		drv_data->prepare_command(slot->host, &cmdr);
> 
> @@ -969,6 +972,24 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>  	mci_writel(slot->host, UHS_REG, regs);
>  	slot->host->timing = ios->timing;
> 
> +	/* Per Synopsys spec, use_hold_reg should be set for all modes except for
> +	 * high-speed SDR50, DDR50, SDR104, and MMC_HS200. However, use_hold_reg
> +	 * should be cleared if the cclk_in_drv is 0.
> +	 */
> +	switch (slot->host->timing) {
> +	case MMC_TIMING_UHS_SDR50:
> +	case MMC_TIMING_UHS_SDR104:
> +	case MMC_TIMING_UHS_DDR50:
> +	case MMC_TIMING_MMC_HS200:
> +		slot->host->use_hold_reg = 0;
> +		break;
> +	default:
> +		slot->host->use_hold_reg = 1;
> +	}
> +
> +	if (slot->host->can_use_hold_reg == 0)
> +		slot->host->use_hold_reg = 0;
> +
>  	/*
>  	 * Use mirror of ios->clock to prevent race with mmc
>  	 * core ios update when finding the minimum.
> @@ -2339,6 +2360,8 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
>  	const struct dw_mci_drv_data *drv_data = host->drv_data;
>  	int idx, ret;
>  	u32 clock_frequency;
> +	int sdr_timing[2];
> +	int ddr_timing[2];
> 
>  	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
>  	if (!pdata) {
> @@ -2389,6 +2412,25 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
>  	if (of_find_property(np, "caps2-mmc-hs200-1_2v", NULL))
>  		pdata->caps2 |= MMC_CAP2_HS200_1_2V_SDR;
> 
> +	/* Check for the "samsung,dw-mshc-sdr-timing" and the
> +	 * "samsung,dw-mshc-ddr-timing" bindings as this will tell us if we
> +	 * can safely set the SDMMC_CMD_USE_HOLD_REG bit. The second paramater
> +	 * in these 2 bindings is the value of the cclk_in_drv. If cclk_in_drv
> +	 * is 0, we cannot set the SDMMC_CMD_USE_HOLD_REG bit. The default
> +	 * behavior will be to set cclk_in_drv, as some platforms do not have
> +	 * to set the sdr or ddr timing parameters.
> +	 */
> +	sdr_timing[1] = ddr_timing[1] = 1;
> +	of_property_read_u32_array(np,
> +			"samsung,dw-mshc-sdr-timing", sdr_timing, 2);
> +
> +	of_property_read_u32_array(np,
> +			"samsung,dw-mshc-ddr-timing", ddr_timing, 2);
> +
> +	pdata->cclk_in_drv = 1;
> +	if ((sdr_timing[1] == 0) || (ddr_timing[1] == 0))
> +		pdata->cclk_in_drv = 0;
> +
>  	return pdata;
>  }
> 
> @@ -2495,6 +2537,15 @@ int dw_mci_probe(struct dw_mci *host)
>  		goto err_regulator;
>  	}
> 
> +	/* Check to see if the HOLD REG is implemented. */
> +	host->can_use_hold_reg = (mci_readl(host, HCON) & SDMMC_HCON_IHR) >> 22;
> +
> +	/* Can only use the HOLD REG is both conditions are true:
> +	 * Hardware has implemented HOLD_REG and
> +	 * cclk_in_drv is non-zero.
> +	 */
> +	host->can_use_hold_reg &= host->pdata->cclk_in_drv;
> +
>  	host->quirks = host->pdata->quirks;
> 
>  	spin_lock_init(&host->lock);
> diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
> index 6bf24ab..dfd05c9 100644
> --- a/drivers/mmc/host/dw_mmc.h
> +++ b/drivers/mmc/host/dw_mmc.h
> @@ -145,6 +145,10 @@
>  #define SDMMC_IDMAC_ENABLE		BIT(7)
>  #define SDMMC_IDMAC_FB			BIT(1)
>  #define SDMMC_IDMAC_SWRESET		BIT(0)
> +
> +/* Hardware Configuration(HCON) register */
> +#define SDMMC_HCON_IHR			BIT(22)
> +
>  /* Version ID register define */
>  #define SDMMC_GET_VERID(x)		((x) & 0xFFFF)
>  /* Card read threshold */
> diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
> index 6ce7d2c..2b5b8bf 100644
> --- a/include/linux/mmc/dw_mmc.h
> +++ b/include/linux/mmc/dw_mmc.h
> @@ -191,6 +191,8 @@ struct dw_mci {
>  	struct regulator	*vmmc;	/* Power regulator */
>  	unsigned long		irq_flags; /* IRQ flags */
>  	int			irq;
> +	u32			can_use_hold_reg;
> +	bool			use_hold_reg;
>  };
> 
>  /* DMA ops for Internal/External DMAC interface */
> @@ -238,6 +240,7 @@ struct dw_mci_board {
>  	u32 caps;	/* Capabilities */
>  	u32 caps2;	/* More capabilities */
>  	u32 pm_caps;	/* PM capabilities */
> +	u32 cclk_in_drv;	/*cclk_in_drv phase shift */
>  	/*
>  	 * Override fifo depth. If 0, autodetect it from the FIFOTH register,
>  	 * but note that this may not be reliable after a bootloader has used
> --
> 1.7.9.5
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


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

* Re: [PATCHv3 1/3] mmc: dw_mmc: Enable the hold reg for certain speed modes
  2013-12-16  4:23   ` Seungwon Jeon
@ 2013-12-16  4:44     ` Dinh Nguyen
  2013-12-16  7:20       ` Seungwon Jeon
  0 siblings, 1 reply; 11+ messages in thread
From: Dinh Nguyen @ 2013-12-16  4:44 UTC (permalink / raw)
  To: Seungwon Jeon, dinguyen, arnd, cjb, jh80.chung, heiko, dianders,
	alim.akhtar, bzhao
  Cc: linux-mmc


On 12/15/13 10:23 PM, Seungwon Jeon wrote:
> On Mon, December 09, 2013, Dinh Nguyen wrote:
>> From: Dinh Nguyen <dinguyen@altera.com>
>>
>> This patch will enable the SDMMC_CMD_USE_HOLD_REG bit when the slot is
>> operating all timing modes, except for SDR50, DDR50, SDR104, and MMC_HS200.
>>
>> According to the Synopsys databook :"To meet the relatively high Input Hold
>> Time requirement for SDR12, SDR25, and other MMC speed modes, you should
>> program bit[29]use_hold_Reg of the CMD register to 1'b1;"..."However, for
>> the higher speed modes of SDR104, SDR50 and DDR50, you can meet the much
>> smaller Input Hold Time requirement of 0.8ns by bypassing the Hold Register
>> (Path A in Figure 10-8, programming CMD.use_hold_reg = 1'b0) and then adding
>> delay elements on the output path as indicated.
>>
>> Also, "Never set CMD.use_hold_reg = 1 and cclk_in_drv phase shift to 0 at the
>> same time. This would add an extra one-cycle delay on the output path, resulting
>> in incorrect behavior."
>>
>> This patch also checks the IHR(Implement Hold Register) in the HCON register.
>>
>> This information is taking from the v2.50a of the Synopsys Designware Cores
>> Mobile Storage Host Databook.
> If cclk_in_drv has non-zero, hold_reg_bit should be 1'b1 for SDR50, DDR50, SDR104, and MMC_HS200 mode.
> Can you check it?
The code is already doing that. By default, use_hold_reg is 1'b1.
use_hold_reg gets cleared to 1'b0 only if
cclk_in_drv is zero.
>
> And samsung,dw-mshc-sdr(ddr)-timing property is still specific for Exynos.
> It will be modified with adding new cell element soon.
That's fine, I think that the K3 and SOCFPGA can get put the clock phase
information in the
clock binding.

Dinh
>
> Thanks,
> Seungwon Jeon
>
>> Signed-off-by: Dinh Nguyen <dinguyen@altera.com>
>> Acked-by: Heiko Stuebner <heiko@sntech.de>
>> Tested-by: Heiko Stuebner <heiko@sntech.de>
>> ---
>> v3: Read the IHR(Implement Hold Register) in the HCON
>> v2: Add check for cclk_in_drv phase shift in conjunction with use_hold_reg.
>> ---
>>  drivers/mmc/host/dw_mmc.c  |   51 ++++++++++++++++++++++++++++++++++++++++++++
>>  drivers/mmc/host/dw_mmc.h  |    4 ++++
>>  include/linux/mmc/dw_mmc.h |    3 +++
>>  3 files changed, 58 insertions(+)
>>
>> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
>> index 4bce0de..480dafe 100644
>> --- a/drivers/mmc/host/dw_mmc.c
>> +++ b/drivers/mmc/host/dw_mmc.c
>> @@ -279,6 +279,9 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
>>  			cmdr |= SDMMC_CMD_DAT_WR;
>>  	}
>>
>> +	if (slot->host->use_hold_reg)
>> +		cmdr |= SDMMC_CMD_USE_HOLD_REG;
>> +
>>  	if (drv_data && drv_data->prepare_command)
>>  		drv_data->prepare_command(slot->host, &cmdr);
>>
>> @@ -969,6 +972,24 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>>  	mci_writel(slot->host, UHS_REG, regs);
>>  	slot->host->timing = ios->timing;
>>
>> +	/* Per Synopsys spec, use_hold_reg should be set for all modes except for
>> +	 * high-speed SDR50, DDR50, SDR104, and MMC_HS200. However, use_hold_reg
>> +	 * should be cleared if the cclk_in_drv is 0.
>> +	 */
>> +	switch (slot->host->timing) {
>> +	case MMC_TIMING_UHS_SDR50:
>> +	case MMC_TIMING_UHS_SDR104:
>> +	case MMC_TIMING_UHS_DDR50:
>> +	case MMC_TIMING_MMC_HS200:
>> +		slot->host->use_hold_reg = 0;
>> +		break;
>> +	default:
>> +		slot->host->use_hold_reg = 1;
>> +	}
>> +
>> +	if (slot->host->can_use_hold_reg == 0)
>> +		slot->host->use_hold_reg = 0;
>> +
>>  	/*
>>  	 * Use mirror of ios->clock to prevent race with mmc
>>  	 * core ios update when finding the minimum.
>> @@ -2339,6 +2360,8 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
>>  	const struct dw_mci_drv_data *drv_data = host->drv_data;
>>  	int idx, ret;
>>  	u32 clock_frequency;
>> +	int sdr_timing[2];
>> +	int ddr_timing[2];
>>
>>  	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
>>  	if (!pdata) {
>> @@ -2389,6 +2412,25 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
>>  	if (of_find_property(np, "caps2-mmc-hs200-1_2v", NULL))
>>  		pdata->caps2 |= MMC_CAP2_HS200_1_2V_SDR;
>>
>> +	/* Check for the "samsung,dw-mshc-sdr-timing" and the
>> +	 * "samsung,dw-mshc-ddr-timing" bindings as this will tell us if we
>> +	 * can safely set the SDMMC_CMD_USE_HOLD_REG bit. The second paramater
>> +	 * in these 2 bindings is the value of the cclk_in_drv. If cclk_in_drv
>> +	 * is 0, we cannot set the SDMMC_CMD_USE_HOLD_REG bit. The default
>> +	 * behavior will be to set cclk_in_drv, as some platforms do not have
>> +	 * to set the sdr or ddr timing parameters.
>> +	 */
>> +	sdr_timing[1] = ddr_timing[1] = 1;
>> +	of_property_read_u32_array(np,
>> +			"samsung,dw-mshc-sdr-timing", sdr_timing, 2);
>> +
>> +	of_property_read_u32_array(np,
>> +			"samsung,dw-mshc-ddr-timing", ddr_timing, 2);
>> +
>> +	pdata->cclk_in_drv = 1;
>> +	if ((sdr_timing[1] == 0) || (ddr_timing[1] == 0))
>> +		pdata->cclk_in_drv = 0;
>> +
>>  	return pdata;
>>  }
>>
>> @@ -2495,6 +2537,15 @@ int dw_mci_probe(struct dw_mci *host)
>>  		goto err_regulator;
>>  	}
>>
>> +	/* Check to see if the HOLD REG is implemented. */
>> +	host->can_use_hold_reg = (mci_readl(host, HCON) & SDMMC_HCON_IHR) >> 22;
>> +
>> +	/* Can only use the HOLD REG is both conditions are true:
>> +	 * Hardware has implemented HOLD_REG and
>> +	 * cclk_in_drv is non-zero.
>> +	 */
>> +	host->can_use_hold_reg &= host->pdata->cclk_in_drv;
>> +
>>  	host->quirks = host->pdata->quirks;
>>
>>  	spin_lock_init(&host->lock);
>> diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
>> index 6bf24ab..dfd05c9 100644
>> --- a/drivers/mmc/host/dw_mmc.h
>> +++ b/drivers/mmc/host/dw_mmc.h
>> @@ -145,6 +145,10 @@
>>  #define SDMMC_IDMAC_ENABLE		BIT(7)
>>  #define SDMMC_IDMAC_FB			BIT(1)
>>  #define SDMMC_IDMAC_SWRESET		BIT(0)
>> +
>> +/* Hardware Configuration(HCON) register */
>> +#define SDMMC_HCON_IHR			BIT(22)
>> +
>>  /* Version ID register define */
>>  #define SDMMC_GET_VERID(x)		((x) & 0xFFFF)
>>  /* Card read threshold */
>> diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
>> index 6ce7d2c..2b5b8bf 100644
>> --- a/include/linux/mmc/dw_mmc.h
>> +++ b/include/linux/mmc/dw_mmc.h
>> @@ -191,6 +191,8 @@ struct dw_mci {
>>  	struct regulator	*vmmc;	/* Power regulator */
>>  	unsigned long		irq_flags; /* IRQ flags */
>>  	int			irq;
>> +	u32			can_use_hold_reg;
>> +	bool			use_hold_reg;
>>  };
>>
>>  /* DMA ops for Internal/External DMAC interface */
>> @@ -238,6 +240,7 @@ struct dw_mci_board {
>>  	u32 caps;	/* Capabilities */
>>  	u32 caps2;	/* More capabilities */
>>  	u32 pm_caps;	/* PM capabilities */
>> +	u32 cclk_in_drv;	/*cclk_in_drv phase shift */
>>  	/*
>>  	 * Override fifo depth. If 0, autodetect it from the FIFOTH register,
>>  	 * but note that this may not be reliable after a bootloader has used
>> --
>> 1.7.9.5
>>
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html


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

* RE: [PATCHv3 1/3] mmc: dw_mmc: Enable the hold reg for certain speed modes
  2013-12-16  4:44     ` Dinh Nguyen
@ 2013-12-16  7:20       ` Seungwon Jeon
  2013-12-16 16:38         ` Dinh Nguyen
  0 siblings, 1 reply; 11+ messages in thread
From: Seungwon Jeon @ 2013-12-16  7:20 UTC (permalink / raw)
  To: 'Dinh Nguyen',
	dinguyen, arnd, cjb, jh80.chung, heiko, dianders, alim.akhtar,
	bzhao
  Cc: linux-mmc

On Mon, December 16, 2013, Dinh Nguyen wrote:
> On 12/15/13 10:23 PM, Seungwon Jeon wrote:
> > On Mon, December 09, 2013, Dinh Nguyen wrote:
> >> From: Dinh Nguyen <dinguyen@altera.com>
> >>
> >> This patch will enable the SDMMC_CMD_USE_HOLD_REG bit when the slot is
> >> operating all timing modes, except for SDR50, DDR50, SDR104, and MMC_HS200.
> >>
> >> According to the Synopsys databook :"To meet the relatively high Input Hold
> >> Time requirement for SDR12, SDR25, and other MMC speed modes, you should
> >> program bit[29]use_hold_Reg of the CMD register to 1'b1;"..."However, for
> >> the higher speed modes of SDR104, SDR50 and DDR50, you can meet the much
> >> smaller Input Hold Time requirement of 0.8ns by bypassing the Hold Register
> >> (Path A in Figure 10-8, programming CMD.use_hold_reg = 1'b0) and then adding
> >> delay elements on the output path as indicated.
> >>
> >> Also, "Never set CMD.use_hold_reg = 1 and cclk_in_drv phase shift to 0 at the
> >> same time. This would add an extra one-cycle delay on the output path, resulting
> >> in incorrect behavior."
> >>
> >> This patch also checks the IHR(Implement Hold Register) in the HCON register.
> >>
> >> This information is taking from the v2.50a of the Synopsys Designware Cores
> >> Mobile Storage Host Databook.
> > If cclk_in_drv has non-zero, hold_reg_bit should be 1'b1 for SDR50, DDR50, SDR104, and MMC_HS200
> mode.
> > Can you check it?
> The code is already doing that. By default, use_hold_reg is 1'b1.
> use_hold_reg gets cleared to 1'b0 only if
> cclk_in_drv is zero.
I'm seeing that your change is always set 'use_hold_reg = 0'
in case of SDR50, DDR50, SDR104, and MMC_HS200 mode.

Thanks,
Seungwon Jeon

> >
> > And samsung,dw-mshc-sdr(ddr)-timing property is still specific for Exynos.
> > It will be modified with adding new cell element soon.
> That's fine, I think that the K3 and SOCFPGA can get put the clock phase
> information in the
> clock binding.
> 
> Dinh
> >
> > Thanks,
> > Seungwon Jeon
> >
> >> Signed-off-by: Dinh Nguyen <dinguyen@altera.com>
> >> Acked-by: Heiko Stuebner <heiko@sntech.de>
> >> Tested-by: Heiko Stuebner <heiko@sntech.de>
> >> ---
> >> v3: Read the IHR(Implement Hold Register) in the HCON
> >> v2: Add check for cclk_in_drv phase shift in conjunction with use_hold_reg.
> >> ---
> >>  drivers/mmc/host/dw_mmc.c  |   51 ++++++++++++++++++++++++++++++++++++++++++++
> >>  drivers/mmc/host/dw_mmc.h  |    4 ++++
> >>  include/linux/mmc/dw_mmc.h |    3 +++
> >>  3 files changed, 58 insertions(+)
> >>
> >> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> >> index 4bce0de..480dafe 100644
> >> --- a/drivers/mmc/host/dw_mmc.c
> >> +++ b/drivers/mmc/host/dw_mmc.c
> >> @@ -279,6 +279,9 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
> >>  			cmdr |= SDMMC_CMD_DAT_WR;
> >>  	}
> >>
> >> +	if (slot->host->use_hold_reg)
> >> +		cmdr |= SDMMC_CMD_USE_HOLD_REG;
> >> +
> >>  	if (drv_data && drv_data->prepare_command)
> >>  		drv_data->prepare_command(slot->host, &cmdr);
> >>
> >> @@ -969,6 +972,24 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
> >>  	mci_writel(slot->host, UHS_REG, regs);
> >>  	slot->host->timing = ios->timing;
> >>
> >> +	/* Per Synopsys spec, use_hold_reg should be set for all modes except for
> >> +	 * high-speed SDR50, DDR50, SDR104, and MMC_HS200. However, use_hold_reg
> >> +	 * should be cleared if the cclk_in_drv is 0.
> >> +	 */
> >> +	switch (slot->host->timing) {
> >> +	case MMC_TIMING_UHS_SDR50:
> >> +	case MMC_TIMING_UHS_SDR104:
> >> +	case MMC_TIMING_UHS_DDR50:
> >> +	case MMC_TIMING_MMC_HS200:
> >> +		slot->host->use_hold_reg = 0;
> >> +		break;
> >> +	default:
> >> +		slot->host->use_hold_reg = 1;
> >> +	}
> >> +
> >> +	if (slot->host->can_use_hold_reg == 0)
> >> +		slot->host->use_hold_reg = 0;
> >> +
> >>  	/*
> >>  	 * Use mirror of ios->clock to prevent race with mmc
> >>  	 * core ios update when finding the minimum.
> >> @@ -2339,6 +2360,8 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
> >>  	const struct dw_mci_drv_data *drv_data = host->drv_data;
> >>  	int idx, ret;
> >>  	u32 clock_frequency;
> >> +	int sdr_timing[2];
> >> +	int ddr_timing[2];
> >>
> >>  	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
> >>  	if (!pdata) {
> >> @@ -2389,6 +2412,25 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
> >>  	if (of_find_property(np, "caps2-mmc-hs200-1_2v", NULL))
> >>  		pdata->caps2 |= MMC_CAP2_HS200_1_2V_SDR;
> >>
> >> +	/* Check for the "samsung,dw-mshc-sdr-timing" and the
> >> +	 * "samsung,dw-mshc-ddr-timing" bindings as this will tell us if we
> >> +	 * can safely set the SDMMC_CMD_USE_HOLD_REG bit. The second paramater
> >> +	 * in these 2 bindings is the value of the cclk_in_drv. If cclk_in_drv
> >> +	 * is 0, we cannot set the SDMMC_CMD_USE_HOLD_REG bit. The default
> >> +	 * behavior will be to set cclk_in_drv, as some platforms do not have
> >> +	 * to set the sdr or ddr timing parameters.
> >> +	 */
> >> +	sdr_timing[1] = ddr_timing[1] = 1;
> >> +	of_property_read_u32_array(np,
> >> +			"samsung,dw-mshc-sdr-timing", sdr_timing, 2);
> >> +
> >> +	of_property_read_u32_array(np,
> >> +			"samsung,dw-mshc-ddr-timing", ddr_timing, 2);
> >> +
> >> +	pdata->cclk_in_drv = 1;
> >> +	if ((sdr_timing[1] == 0) || (ddr_timing[1] == 0))
> >> +		pdata->cclk_in_drv = 0;
> >> +
> >>  	return pdata;
> >>  }
> >>
> >> @@ -2495,6 +2537,15 @@ int dw_mci_probe(struct dw_mci *host)
> >>  		goto err_regulator;
> >>  	}
> >>
> >> +	/* Check to see if the HOLD REG is implemented. */
> >> +	host->can_use_hold_reg = (mci_readl(host, HCON) & SDMMC_HCON_IHR) >> 22;
> >> +
> >> +	/* Can only use the HOLD REG is both conditions are true:
> >> +	 * Hardware has implemented HOLD_REG and
> >> +	 * cclk_in_drv is non-zero.
> >> +	 */
> >> +	host->can_use_hold_reg &= host->pdata->cclk_in_drv;
> >> +
> >>  	host->quirks = host->pdata->quirks;
> >>
> >>  	spin_lock_init(&host->lock);
> >> diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
> >> index 6bf24ab..dfd05c9 100644
> >> --- a/drivers/mmc/host/dw_mmc.h
> >> +++ b/drivers/mmc/host/dw_mmc.h
> >> @@ -145,6 +145,10 @@
> >>  #define SDMMC_IDMAC_ENABLE		BIT(7)
> >>  #define SDMMC_IDMAC_FB			BIT(1)
> >>  #define SDMMC_IDMAC_SWRESET		BIT(0)
> >> +
> >> +/* Hardware Configuration(HCON) register */
> >> +#define SDMMC_HCON_IHR			BIT(22)
> >> +
> >>  /* Version ID register define */
> >>  #define SDMMC_GET_VERID(x)		((x) & 0xFFFF)
> >>  /* Card read threshold */
> >> diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
> >> index 6ce7d2c..2b5b8bf 100644
> >> --- a/include/linux/mmc/dw_mmc.h
> >> +++ b/include/linux/mmc/dw_mmc.h
> >> @@ -191,6 +191,8 @@ struct dw_mci {
> >>  	struct regulator	*vmmc;	/* Power regulator */
> >>  	unsigned long		irq_flags; /* IRQ flags */
> >>  	int			irq;
> >> +	u32			can_use_hold_reg;
> >> +	bool			use_hold_reg;
> >>  };
> >>
> >>  /* DMA ops for Internal/External DMAC interface */
> >> @@ -238,6 +240,7 @@ struct dw_mci_board {
> >>  	u32 caps;	/* Capabilities */
> >>  	u32 caps2;	/* More capabilities */
> >>  	u32 pm_caps;	/* PM capabilities */
> >> +	u32 cclk_in_drv;	/*cclk_in_drv phase shift */
> >>  	/*
> >>  	 * Override fifo depth. If 0, autodetect it from the FIFOTH register,
> >>  	 * but note that this may not be reliable after a bootloader has used
> >> --
> >> 1.7.9.5
> >>
> >>
> >> --
> >> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> >> the body of a message to majordomo@vger.kernel.org
> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


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

* RE: [PATCHv3 1/3] mmc: dw_mmc: Enable the hold reg for certain speed modes
  2013-12-16  7:20       ` Seungwon Jeon
@ 2013-12-16 16:38         ` Dinh Nguyen
  0 siblings, 0 replies; 11+ messages in thread
From: Dinh Nguyen @ 2013-12-16 16:38 UTC (permalink / raw)
  To: Seungwon Jeon
  Cc: 'Dinh Nguyen',
	arnd, cjb, jh80.chung, heiko, dianders, alim.akhtar, bzhao,
	linux-mmc

On Mon, 2013-12-16 at 16:20 +0900, Seungwon Jeon wrote:
> On Mon, December 16, 2013, Dinh Nguyen wrote:
> > On 12/15/13 10:23 PM, Seungwon Jeon wrote:
> > > On Mon, December 09, 2013, Dinh Nguyen wrote:
> > >> From: Dinh Nguyen <dinguyen@altera.com>
> > >>
> > >> This patch will enable the SDMMC_CMD_USE_HOLD_REG bit when the slot is
> > >> operating all timing modes, except for SDR50, DDR50, SDR104, and MMC_HS200.
> > >>
> > >> According to the Synopsys databook :"To meet the relatively high Input Hold
> > >> Time requirement for SDR12, SDR25, and other MMC speed modes, you should
> > >> program bit[29]use_hold_Reg of the CMD register to 1'b1;"..."However, for
> > >> the higher speed modes of SDR104, SDR50 and DDR50, you can meet the much
> > >> smaller Input Hold Time requirement of 0.8ns by bypassing the Hold Register
> > >> (Path A in Figure 10-8, programming CMD.use_hold_reg = 1'b0) and then adding
> > >> delay elements on the output path as indicated.
> > >>
> > >> Also, "Never set CMD.use_hold_reg = 1 and cclk_in_drv phase shift to 0 at the
> > >> same time. This would add an extra one-cycle delay on the output path, resulting
> > >> in incorrect behavior."
> > >>
> > >> This patch also checks the IHR(Implement Hold Register) in the HCON register.
> > >>
> > >> This information is taking from the v2.50a of the Synopsys Designware Cores
> > >> Mobile Storage Host Databook.
> > > If cclk_in_drv has non-zero, hold_reg_bit should be 1'b1 for SDR50, DDR50, SDR104, and MMC_HS200
> > mode.
> > > Can you check it?
> > The code is already doing that. By default, use_hold_reg is 1'b1.
> > use_hold_reg gets cleared to 1'b0 only if
> > cclk_in_drv is zero.
> I'm seeing that your change is always set 'use_hold_reg = 0'
> in case of SDR50, DDR50, SDR104, and MMC_HS200 mode.

Ah ok...I will add a check in v4.

Thanks,
Dinh
> 
> Thanks,
> Seungwon Jeon
> 
> > >
> > > And samsung,dw-mshc-sdr(ddr)-timing property is still specific for Exynos.
> > > It will be modified with adding new cell element soon.
> > That's fine, I think that the K3 and SOCFPGA can get put the clock phase
> > information in the
> > clock binding.
> > 
> > Dinh
> > >
> > > Thanks,
> > > Seungwon Jeon
> > >
> > >> Signed-off-by: Dinh Nguyen <dinguyen@altera.com>
> > >> Acked-by: Heiko Stuebner <heiko@sntech.de>
> > >> Tested-by: Heiko Stuebner <heiko@sntech.de>
> > >> ---
> > >> v3: Read the IHR(Implement Hold Register) in the HCON
> > >> v2: Add check for cclk_in_drv phase shift in conjunction with use_hold_reg.
> > >> ---
> > >>  drivers/mmc/host/dw_mmc.c  |   51 ++++++++++++++++++++++++++++++++++++++++++++
> > >>  drivers/mmc/host/dw_mmc.h  |    4 ++++
> > >>  include/linux/mmc/dw_mmc.h |    3 +++
> > >>  3 files changed, 58 insertions(+)
> > >>
> > >> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> > >> index 4bce0de..480dafe 100644
> > >> --- a/drivers/mmc/host/dw_mmc.c
> > >> +++ b/drivers/mmc/host/dw_mmc.c
> > >> @@ -279,6 +279,9 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
> > >>  			cmdr |= SDMMC_CMD_DAT_WR;
> > >>  	}
> > >>
> > >> +	if (slot->host->use_hold_reg)
> > >> +		cmdr |= SDMMC_CMD_USE_HOLD_REG;
> > >> +
> > >>  	if (drv_data && drv_data->prepare_command)
> > >>  		drv_data->prepare_command(slot->host, &cmdr);
> > >>
> > >> @@ -969,6 +972,24 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
> > >>  	mci_writel(slot->host, UHS_REG, regs);
> > >>  	slot->host->timing = ios->timing;
> > >>
> > >> +	/* Per Synopsys spec, use_hold_reg should be set for all modes except for
> > >> +	 * high-speed SDR50, DDR50, SDR104, and MMC_HS200. However, use_hold_reg
> > >> +	 * should be cleared if the cclk_in_drv is 0.
> > >> +	 */
> > >> +	switch (slot->host->timing) {
> > >> +	case MMC_TIMING_UHS_SDR50:
> > >> +	case MMC_TIMING_UHS_SDR104:
> > >> +	case MMC_TIMING_UHS_DDR50:
> > >> +	case MMC_TIMING_MMC_HS200:
> > >> +		slot->host->use_hold_reg = 0;
> > >> +		break;
> > >> +	default:
> > >> +		slot->host->use_hold_reg = 1;
> > >> +	}
> > >> +
> > >> +	if (slot->host->can_use_hold_reg == 0)
> > >> +		slot->host->use_hold_reg = 0;
> > >> +
> > >>  	/*
> > >>  	 * Use mirror of ios->clock to prevent race with mmc
> > >>  	 * core ios update when finding the minimum.
> > >> @@ -2339,6 +2360,8 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
> > >>  	const struct dw_mci_drv_data *drv_data = host->drv_data;
> > >>  	int idx, ret;
> > >>  	u32 clock_frequency;
> > >> +	int sdr_timing[2];
> > >> +	int ddr_timing[2];
> > >>
> > >>  	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
> > >>  	if (!pdata) {
> > >> @@ -2389,6 +2412,25 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
> > >>  	if (of_find_property(np, "caps2-mmc-hs200-1_2v", NULL))
> > >>  		pdata->caps2 |= MMC_CAP2_HS200_1_2V_SDR;
> > >>
> > >> +	/* Check for the "samsung,dw-mshc-sdr-timing" and the
> > >> +	 * "samsung,dw-mshc-ddr-timing" bindings as this will tell us if we
> > >> +	 * can safely set the SDMMC_CMD_USE_HOLD_REG bit. The second paramater
> > >> +	 * in these 2 bindings is the value of the cclk_in_drv. If cclk_in_drv
> > >> +	 * is 0, we cannot set the SDMMC_CMD_USE_HOLD_REG bit. The default
> > >> +	 * behavior will be to set cclk_in_drv, as some platforms do not have
> > >> +	 * to set the sdr or ddr timing parameters.
> > >> +	 */
> > >> +	sdr_timing[1] = ddr_timing[1] = 1;
> > >> +	of_property_read_u32_array(np,
> > >> +			"samsung,dw-mshc-sdr-timing", sdr_timing, 2);
> > >> +
> > >> +	of_property_read_u32_array(np,
> > >> +			"samsung,dw-mshc-ddr-timing", ddr_timing, 2);
> > >> +
> > >> +	pdata->cclk_in_drv = 1;
> > >> +	if ((sdr_timing[1] == 0) || (ddr_timing[1] == 0))
> > >> +		pdata->cclk_in_drv = 0;
> > >> +
> > >>  	return pdata;
> > >>  }
> > >>
> > >> @@ -2495,6 +2537,15 @@ int dw_mci_probe(struct dw_mci *host)
> > >>  		goto err_regulator;
> > >>  	}
> > >>
> > >> +	/* Check to see if the HOLD REG is implemented. */
> > >> +	host->can_use_hold_reg = (mci_readl(host, HCON) & SDMMC_HCON_IHR) >> 22;
> > >> +
> > >> +	/* Can only use the HOLD REG is both conditions are true:
> > >> +	 * Hardware has implemented HOLD_REG and
> > >> +	 * cclk_in_drv is non-zero.
> > >> +	 */
> > >> +	host->can_use_hold_reg &= host->pdata->cclk_in_drv;
> > >> +
> > >>  	host->quirks = host->pdata->quirks;
> > >>
> > >>  	spin_lock_init(&host->lock);
> > >> diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
> > >> index 6bf24ab..dfd05c9 100644
> > >> --- a/drivers/mmc/host/dw_mmc.h
> > >> +++ b/drivers/mmc/host/dw_mmc.h
> > >> @@ -145,6 +145,10 @@
> > >>  #define SDMMC_IDMAC_ENABLE		BIT(7)
> > >>  #define SDMMC_IDMAC_FB			BIT(1)
> > >>  #define SDMMC_IDMAC_SWRESET		BIT(0)
> > >> +
> > >> +/* Hardware Configuration(HCON) register */
> > >> +#define SDMMC_HCON_IHR			BIT(22)
> > >> +
> > >>  /* Version ID register define */
> > >>  #define SDMMC_GET_VERID(x)		((x) & 0xFFFF)
> > >>  /* Card read threshold */
> > >> diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
> > >> index 6ce7d2c..2b5b8bf 100644
> > >> --- a/include/linux/mmc/dw_mmc.h
> > >> +++ b/include/linux/mmc/dw_mmc.h
> > >> @@ -191,6 +191,8 @@ struct dw_mci {
> > >>  	struct regulator	*vmmc;	/* Power regulator */
> > >>  	unsigned long		irq_flags; /* IRQ flags */
> > >>  	int			irq;
> > >> +	u32			can_use_hold_reg;
> > >> +	bool			use_hold_reg;
> > >>  };
> > >>
> > >>  /* DMA ops for Internal/External DMAC interface */
> > >> @@ -238,6 +240,7 @@ struct dw_mci_board {
> > >>  	u32 caps;	/* Capabilities */
> > >>  	u32 caps2;	/* More capabilities */
> > >>  	u32 pm_caps;	/* PM capabilities */
> > >> +	u32 cclk_in_drv;	/*cclk_in_drv phase shift */
> > >>  	/*
> > >>  	 * Override fifo depth. If 0, autodetect it from the FIFOTH register,
> > >>  	 * but note that this may not be reliable after a bootloader has used
> > >> --
> > >> 1.7.9.5
> > >>
> > >>
> > >> --
> > >> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> > >> the body of a message to majordomo@vger.kernel.org
> > >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 




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

end of thread, other threads:[~2013-12-16 16:40 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-12-09  4:51 [PATCHv3 0/3] mmc: dw_mmc: Make the use of the hold reg generic dinguyen
2013-12-09  4:51 ` [PATCHv3 1/3] mmc: dw_mmc: Enable the hold reg for certain speed modes dinguyen
2013-12-09  9:56   ` Heiko Stübner
2013-12-09 16:15     ` Dinh Nguyen
2013-12-16  4:23   ` Seungwon Jeon
2013-12-16  4:44     ` Dinh Nguyen
2013-12-16  7:20       ` Seungwon Jeon
2013-12-16 16:38         ` Dinh Nguyen
2013-12-09  4:51 ` [PATCHv3 2/3] mmc: dw_mmc-pltm: Remove Rockchip's custom dw_mmc driver structure dinguyen
2013-12-09  4:51 ` [PATCHv3 3/3] mmc: dw_mmc-exynos: Remove Exynos' custom prepare_command function dinguyen
2013-12-09 16:12 ` [PATCHv3 0/3] mmc: dw_mmc: Make the use of the hold reg generic Arnd Bergmann

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.