MMC: DWMMC: Correct the CLKDIV register value
authorRajeshwari S Shinde <rajeshwari.s@samsung.com>
Wed, 5 Feb 2014 05:18:15 +0000 (10:48 +0530)
committerPantelis Antoniou <panto@antoniou-consulting.com>
Fri, 7 Feb 2014 15:42:26 +0000 (17:42 +0200)
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@samsung.com>
Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
arch/arm/include/asm/arch-exynos/dwmmc.h
drivers/mmc/dw_mmc.c
drivers/mmc/exynos_dw_mmc.c
include/dwmmc.h

index 09d739dfca998a5e1ddd3e2fa5e05bad2158fbfc..a7ca12c477e2689e361085286f6d20f581f4358f 100644 (file)
 #define MPSCTRL_ENCRYPTION             (0x1<<1)
 #define MPSCTRL_VALID                  (0x1<<0)
 
+/* CLKSEL Register */
+#define DWMCI_DIVRATIO_BIT             24
+#define DWMCI_DIVRATIO_MASK            0x7
+
 #ifdef CONFIG_OF_CONTROL
 int exynos_dwmmc_init(const void *blob);
 #endif
index 4cec5aaa604b0fdba8bedbfed149e2405a6e7ded..d45c15cfa4e539887cd2500cf12ee4c85efb9cd6 100644 (file)
@@ -237,7 +237,7 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
         * host->bus_hz should be set from user.
         */
        if (host->get_mmc_clk)
-               sclk = host->get_mmc_clk(host->dev_index);
+               sclk = host->get_mmc_clk(host);
        else if (host->bus_hz)
                sclk = host->bus_hz;
        else {
index b3e5c5e5e09b5db5d04bfac1b8bd3093b9d3d655..de8cdcc42b3db83f631b358f24e90cc1d2c5dbed 100644 (file)
@@ -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;
 }
 
 static void exynos_dwmci_board_init(struct dwmci_host *host)
index a02dd67c1370f05cdc5b6571d2070ec5dc0e66cb..b64155851d6491a5093068848c8fe5627d62e363 100644 (file)
@@ -142,7 +142,7 @@ struct dwmci_host {
 
        void (*clksel)(struct dwmci_host *host);
        void (*board_init)(struct dwmci_host *host);
-       unsigned int (*get_mmc_clk)(int dev_index);
+       unsigned int (*get_mmc_clk)(struct dwmci_host *host);
 };
 
 struct dwmci_idmac {