arm: exynos: fix clock calculation
authorMinkyu Kang <mk7.kang@samsung.com>
Fri, 5 Jul 2013 10:08:33 +0000 (19:08 +0900)
committerMinkyu Kang <mk7.kang@samsung.com>
Tue, 9 Jul 2013 07:15:30 +0000 (16:15 +0900)
There are differnce with clock calcuation by cpu variations.
This patch will fix it according to user manual.

Signed-off-by: Minkyu Kang <mk7.kang@samsung.com>
Signed-off-by: Rajeshwari Shinde <rajeshwari.s@samsung.com>
arch/arm/cpu/armv7/exynos/clock.c

index e1c4246..9f07181 100644 (file)
 #include <asm/arch/clk.h>
 #include <asm/arch/periph.h>
 
+#define PLL_DIV_1024   1024
+#define PLL_DIV_65535  65535
+#define PLL_DIV_65536  65536
+
 /* *
  * This structure is to store the src bit, div bit and prediv bit
  * positions of the peripheral clocks of the src and div registers
@@ -85,6 +89,7 @@ static struct set_epll_con_val exynos5_epll_div[] = {
 static int exynos_get_pll_clk(int pllreg, unsigned int r, unsigned int k)
 {
        unsigned long m, p, s = 0, mask, fout;
+       unsigned int div;
        unsigned int freq;
        /*
         * APLL_CON: MIDV [25:16]
@@ -110,14 +115,42 @@ static int exynos_get_pll_clk(int pllreg, unsigned int r, unsigned int k)
        if (pllreg == EPLL) {
                k = k & 0xffff;
                /* FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV) */
-               fout = (m + k / 65536) * (freq / (p * (1 << s)));
+               fout = (m + k / PLL_DIV_65536) * (freq / (p * (1 << s)));
        } else if (pllreg == VPLL) {
                k = k & 0xfff;
-               /* FOUT = (MDIV + K / 1024) * FIN / (PDIV * 2^SDIV) */
-               fout = (m + k / 1024) * (freq / (p * (1 << s)));
+
+               /*
+                * Exynos4210
+                * FOUT = (MDIV + K / 1024) * FIN / (PDIV * 2^SDIV)
+                *
+                * Exynos4412
+                * FOUT = (MDIV + K / 65535) * FIN / (PDIV * 2^SDIV)
+                *
+                * Exynos5250
+                * FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV)
+                */
+               if (proid_is_exynos4210())
+                       div = PLL_DIV_1024;
+               else if (proid_is_exynos4412())
+                       div = PLL_DIV_65535;
+               else if (proid_is_exynos5250())
+                       div = PLL_DIV_65536;
+               else
+                       return 0;
+
+               fout = (m + k / div) * (freq / (p * (1 << s)));
        } else {
-               /* FOUT = MDIV * FIN / (PDIV * 2^SDIV) */
-               fout = m * (freq / (p * (1 << s)));
+               /*
+                * Exynos4210
+                * FOUT = MDIV * FIN / (PDIV * 2^SDIV)
+                *
+                * Exynos4412 / Exynos5250
+                * FOUT = MDIV * FIN / (PDIV * 2^(SDIV-1))
+                */
+               if (proid_is_exynos4210())
+                       fout = m * (freq / (p * (1 << s)));
+               else
+                       fout = m * (freq / (p * (1 << (s - 1))));
        }
 
        return fout;