[U-Boot] [PATCH] MMC: DWMMC: Correct the CLKDIV register value

Rajeshwari S Shinde rajeshwari.s at samsung.com
Thu Aug 29 12:52:24 CEST 2013


This patch corrects the divider value written to CLKDIV register.
Since SDCLKIN is divided inside controller by the DIVRATIO value set
in the CLKSEL register, we need to use the same output clock value to
calculate the CLKDIV value.
as per user manual: cclk_in = SDCLKIN / (DIVRATIO + 1)

Input parameter to mmc_clk is changed to dwmci_host, since
we need the same to read DWMCI_CLKSEL register.

This improves the read timing values for channel 0 on SMDK5250 
from 0.288sec to 0.144sec

Signed-off-by: Rajeshwari S Shinde <rajeshwari.s at samsung.com>
---
 arch/arm/include/asm/arch-exynos/dwmmc.h |  4 ++++
 drivers/mmc/dw_mmc.c                     |  2 +-
 drivers/mmc/exynos_dw_mmc.c              | 17 +++++++++++++++--
 include/dwmmc.h                          |  2 +-
 4 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/arch/arm/include/asm/arch-exynos/dwmmc.h b/arch/arm/include/asm/arch-exynos/dwmmc.h
index b9eca76..f1c8d8a 100644
--- a/arch/arm/include/asm/arch-exynos/dwmmc.h
+++ b/arch/arm/include/asm/arch-exynos/dwmmc.h
@@ -14,6 +14,10 @@
 #define DWMCI_SET_DRV_CLK(x)	((x) << 16)
 #define DWMCI_SET_DIV_RATIO(x)	((x) << 24)
 
+/* CLKSEL Register */
+#define DWMCI_DIVRATIO_BIT		24
+#define DWMCI_DIVRATIO_MASK		0x7
+
 #ifdef CONFIG_OF_CONTROL
 int exynos_dwmmc_init(const void *blob);
 #endif
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index a82ee17..3406bdd 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -224,7 +224,7 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
 	 * host->bus_hz should be set from user.
 	 */
 	if (host->mmc_clk)
-		sclk = host->mmc_clk(host->dev_index);
+		sclk = host->mmc_clk(host);
 	else if (host->bus_hz)
 		sclk = host->bus_hz;
 	else {
diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c
index 4ef9fec..1ed4afe 100644
--- a/drivers/mmc/exynos_dw_mmc.c
+++ b/drivers/mmc/exynos_dw_mmc.c
@@ -29,9 +29,22 @@ static void exynos_dwmci_clksel(struct dwmci_host *host)
 	dwmci_writel(host, DWMCI_CLKSEL, host->clksel_val);
 }
 
-unsigned int exynos_dwmci_get_clk(int dev_index)
+unsigned int exynos_dwmci_get_clk(struct dwmci_host *host)
 {
-	return get_mmc_clk(dev_index);
+	unsigned long sclk;
+	int8_t clk_div;
+
+	/*
+	 * Since SDCLKIN is divided inside controller by the DIVRATIO
+	 * value set in the CLKSEL register, we need to use the same output
+	 * clock value to calculate the CLKDIV value.
+	 * as per user manual:cclk_in = SDCLKIN / (DIVRATIO + 1)
+	 */
+	clk_div = ((dwmci_readl(host, DWMCI_CLKSEL) >> DWMCI_DIVRATIO_BIT)
+			& DWMCI_DIVRATIO_MASK) + 1;
+	sclk = get_mmc_clk(host->dev_index);
+
+	return sclk / clk_div;
 }
 
 /*
diff --git a/include/dwmmc.h b/include/dwmmc.h
index 08ced0b..26b53af 100644
--- a/include/dwmmc.h
+++ b/include/dwmmc.h
@@ -138,7 +138,7 @@ struct dwmci_host {
 	struct mmc *mmc;
 
 	void (*clksel)(struct dwmci_host *host);
-	unsigned int (*mmc_clk)(int dev_index);
+	unsigned int (*mmc_clk)(struct dwmci_host *host);
 };
 
 struct dwmci_idmac {
-- 
1.7.12.4



More information about the U-Boot mailing list