]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - arch/arm/cpu/armv7/exynos/clock.c
Merge branch 'master' of http://git.denx.de/u-boot-samsung
[karo-tx-uboot.git] / arch / arm / cpu / armv7 / exynos / clock.c
index 1fea4d66639870faa1d869f4caa1e3c057abe3da..8fab135bebf4ef6900677847b60a8e1a1520254c 100644 (file)
@@ -82,7 +82,8 @@ static int exynos_get_pll_clk(int pllreg, unsigned int r, unsigned int k)
         * VPLL_CON: MIDV [24:16]
         * BPLL_CON: MIDV [25:16]: Exynos5
         */
-       if (pllreg == APLL || pllreg == MPLL || pllreg == BPLL)
+       if (pllreg == APLL || pllreg == MPLL || pllreg == BPLL ||
+           pllreg == SPLL)
                mask = 0x3ff;
        else
                mask = 0x1ff;
@@ -117,7 +118,8 @@ static int exynos_get_pll_clk(int pllreg, unsigned int r, unsigned int k)
                        div = PLL_DIV_1024;
                else if (proid_is_exynos4412())
                        div = PLL_DIV_65535;
-               else if (proid_is_exynos5250() || proid_is_exynos5420())
+               else if (proid_is_exynos5250() || proid_is_exynos5420()
+                        || proid_is_exynos5800())
                        div = PLL_DIV_65536;
                else
                        return 0;
@@ -391,6 +393,9 @@ static unsigned long exynos5420_get_pll_clk(int pllreg)
                r = readl(&clk->rpll_con0);
                k = readl(&clk->rpll_con1);
                break;
+       case SPLL:
+               r = readl(&clk->spll_con0);
+               break;
        default:
                printf("Unsupported PLL (%d)\n", pllreg);
                return 0;
@@ -869,7 +874,7 @@ static void exynos4_set_mmc_clk(int dev_index, unsigned int div)
 {
        struct exynos4_clock *clk =
                (struct exynos4_clock *)samsung_get_base_clock();
-       unsigned int addr;
+       unsigned int addr, clear_bit, set_bit;
 
        /*
         * CLK_DIV_FSYS1
@@ -877,44 +882,26 @@ static void exynos4_set_mmc_clk(int dev_index, unsigned int div)
         * CLK_DIV_FSYS2
         * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24]
         * CLK_DIV_FSYS3
-        * MMC4_PRE_RATIO [15:8]
+        * MMC4_RATIO [3:0]
         */
        if (dev_index < 2) {
                addr = (unsigned int)&clk->div_fsys1;
-       }  else if (dev_index == 4) {
+               clear_bit = MASK_PRE_RATIO(dev_index);
+               set_bit = SET_PRE_RATIO(dev_index, div);
+       } else if (dev_index == 4) {
                addr = (unsigned int)&clk->div_fsys3;
                dev_index -= 4;
+               /* MMC4 is controlled with the MMC4_RATIO value */
+               clear_bit = MASK_RATIO(dev_index);
+               set_bit = SET_RATIO(dev_index, div);
        } else {
                addr = (unsigned int)&clk->div_fsys2;
                dev_index -= 2;
+               clear_bit = MASK_PRE_RATIO(dev_index);
+               set_bit = SET_PRE_RATIO(dev_index, div);
        }
 
-       clrsetbits_le32(addr, 0xff << ((dev_index << 4) + 8),
-                       (div & 0xff) << ((dev_index << 4) + 8));
-}
-
-/* exynos4x12: set the mmc clock */
-static void exynos4x12_set_mmc_clk(int dev_index, unsigned int div)
-{
-       struct exynos4x12_clock *clk =
-               (struct exynos4x12_clock *)samsung_get_base_clock();
-       unsigned int addr;
-
-       /*
-        * CLK_DIV_FSYS1
-        * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24]
-        * CLK_DIV_FSYS2
-        * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24]
-        */
-       if (dev_index < 2) {
-               addr = (unsigned int)&clk->div_fsys1;
-       } else {
-               addr = (unsigned int)&clk->div_fsys2;
-               dev_index -= 2;
-       }
-
-       clrsetbits_le32(addr, 0xff << ((dev_index << 4) + 8),
-                       (div & 0xff) << ((dev_index << 4) + 8));
+       clrsetbits_le32(addr, clear_bit, set_bit);
 }
 
 /* exynos5: set the mmc clock */
@@ -1045,6 +1032,40 @@ static unsigned long exynos5_get_lcd_clk(void)
        return pclk;
 }
 
+static unsigned long exynos5420_get_lcd_clk(void)
+{
+       struct exynos5420_clock *clk =
+               (struct exynos5420_clock *)samsung_get_base_clock();
+       unsigned long pclk, sclk;
+       unsigned int sel;
+       unsigned int ratio;
+
+       /*
+        * CLK_SRC_DISP10
+        * FIMD1_SEL [4]
+        * 0: SCLK_RPLL
+        * 1: SCLK_SPLL
+        */
+       sel = readl(&clk->src_disp10);
+       sel &= (1 << 4);
+
+       if (sel)
+               sclk = get_pll_clk(SPLL);
+       else
+               sclk = get_pll_clk(RPLL);
+
+       /*
+        * CLK_DIV_DISP10
+        * FIMD1_RATIO [3:0]
+        */
+       ratio = readl(&clk->div_disp10);
+       ratio = ratio & 0xf;
+
+       pclk = sclk / (ratio + 1);
+
+       return pclk;
+}
+
 void exynos4_set_lcd_clk(void)
 {
        struct exynos4_clock *clk =
@@ -1149,6 +1170,33 @@ void exynos5_set_lcd_clk(void)
        clrsetbits_le32(&clk->div_disp1_0, 0xf, 0x0);
 }
 
+void exynos5420_set_lcd_clk(void)
+{
+       struct exynos5420_clock *clk =
+               (struct exynos5420_clock *)samsung_get_base_clock();
+       unsigned int cfg;
+
+       /*
+        * CLK_SRC_DISP10
+        * FIMD1_SEL [4]
+        * 0: SCLK_RPLL
+        * 1: SCLK_SPLL
+        */
+       cfg = readl(&clk->src_disp10);
+       cfg &= ~(0x1 << 4);
+       cfg |= (0 << 4);
+       writel(cfg, &clk->src_disp10);
+
+       /*
+        * CLK_DIV_DISP10
+        * FIMD1_RATIO          [3:0]
+        */
+       cfg = readl(&clk->div_disp10);
+       cfg &= ~(0xf << 0);
+       cfg |= (0 << 0);
+       writel(cfg, &clk->div_disp10);
+}
+
 void exynos4_set_mipi_clk(void)
 {
        struct exynos4_clock *clk =
@@ -1375,8 +1423,8 @@ static int clock_calc_best_scalar(unsigned int main_scaler_bits,
                return 1;
 
        for (i = 1; i <= loops; i++) {
-               const unsigned int effective_div = max(min(input_rate / i /
-                                                       target_rate, cap), 1);
+               const unsigned int effective_div =
+                       max(min(input_rate / i / target_rate, cap), 1U);
                const unsigned int effective_rate = input_rate / i /
                                                        effective_div;
                const int error = target_rate - effective_rate;
@@ -1534,7 +1582,7 @@ static unsigned long exynos4_get_i2c_clk(void)
 unsigned long get_pll_clk(int pllreg)
 {
        if (cpu_is_exynos5()) {
-               if (proid_is_exynos5420())
+               if (proid_is_exynos5420() || proid_is_exynos5800())
                        return exynos5420_get_pll_clk(pllreg);
                return exynos5_get_pll_clk(pllreg);
        } else {
@@ -1570,7 +1618,7 @@ unsigned long get_i2c_clk(void)
 unsigned long get_pwm_clk(void)
 {
        if (cpu_is_exynos5()) {
-               if (proid_is_exynos5420())
+               if (proid_is_exynos5420() || proid_is_exynos5800())
                        return exynos5420_get_pwm_clk();
                return clock_get_periph_rate(PERIPH_ID_PWM0);
        } else {
@@ -1583,7 +1631,7 @@ unsigned long get_pwm_clk(void)
 unsigned long get_uart_clk(int dev_index)
 {
        if (cpu_is_exynos5()) {
-               if (proid_is_exynos5420())
+               if (proid_is_exynos5420() || proid_is_exynos5800())
                        return exynos5420_get_uart_clk(dev_index);
                return exynos5_get_uart_clk(dev_index);
        } else {
@@ -1596,7 +1644,7 @@ unsigned long get_uart_clk(int dev_index)
 unsigned long get_mmc_clk(int dev_index)
 {
        if (cpu_is_exynos5()) {
-               if (proid_is_exynos5420())
+               if (proid_is_exynos5420() || proid_is_exynos5800())
                        return exynos5420_get_mmc_clk(dev_index);
                return exynos5_get_mmc_clk(dev_index);
        } else {
@@ -1607,15 +1655,12 @@ unsigned long get_mmc_clk(int dev_index)
 void set_mmc_clk(int dev_index, unsigned int div)
 {
        if (cpu_is_exynos5()) {
-               if (proid_is_exynos5420())
+               if (proid_is_exynos5420() || proid_is_exynos5800())
                        exynos5420_set_mmc_clk(dev_index, div);
                else
                        exynos5_set_mmc_clk(dev_index, div);
        } else {
-               if (proid_is_exynos4412())
-                       exynos4x12_set_mmc_clk(dev_index, div);
-               else
-                       exynos4_set_mmc_clk(dev_index, div);
+               exynos4_set_mmc_clk(dev_index, div);
        }
 }
 
@@ -1623,16 +1668,24 @@ unsigned long get_lcd_clk(void)
 {
        if (cpu_is_exynos4())
                return exynos4_get_lcd_clk();
-       else
-               return exynos5_get_lcd_clk();
+       else {
+               if (proid_is_exynos5420() || proid_is_exynos5800())
+                       return exynos5420_get_lcd_clk();
+               else
+                       return exynos5_get_lcd_clk();
+       }
 }
 
 void set_lcd_clk(void)
 {
        if (cpu_is_exynos4())
                exynos4_set_lcd_clk();
-       else
-               exynos5_set_lcd_clk();
+       else {
+               if (proid_is_exynos5250())
+                       exynos5_set_lcd_clk();
+               else if (proid_is_exynos5420() || proid_is_exynos5800())
+                       exynos5420_set_lcd_clk();
+       }
 }
 
 void set_mipi_clk(void)
@@ -1644,7 +1697,7 @@ void set_mipi_clk(void)
 int set_spi_clk(int periph_id, unsigned int rate)
 {
        if (cpu_is_exynos5()) {
-               if (proid_is_exynos5420())
+               if (proid_is_exynos5420() || proid_is_exynos5800())
                        return exynos5420_set_spi_clk(periph_id, rate);
                return exynos5_set_spi_clk(periph_id, rate);
        } else {