]> 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 61cd8cf425d6c3c62467dbe7d7194349d6562517..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,8 +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 val;
+       unsigned int addr, clear_bit, set_bit;
 
        /*
         * CLK_DIV_FSYS1
@@ -878,49 +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);
        }
 
-       val = readl(addr);
-       val &= ~(0xff << ((dev_index << 4) + 8));
-       val |= (div & 0xff) << ((dev_index << 4) + 8);
-       writel(val, addr);
-}
-
-/* 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;
-       unsigned int val;
-
-       /*
-        * 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;
-       }
-
-       val = readl(addr);
-       val &= ~(0xff << ((dev_index << 4) + 8));
-       val |= (div & 0xff) << ((dev_index << 4) + 8);
-       writel(val, addr);
+       clrsetbits_le32(addr, clear_bit, set_bit);
 }
 
 /* exynos5: set the mmc clock */
@@ -929,7 +910,6 @@ static void exynos5_set_mmc_clk(int dev_index, unsigned int div)
        struct exynos5_clock *clk =
                (struct exynos5_clock *)samsung_get_base_clock();
        unsigned int addr;
-       unsigned int val;
 
        /*
         * CLK_DIV_FSYS1
@@ -944,10 +924,8 @@ static void exynos5_set_mmc_clk(int dev_index, unsigned int div)
                dev_index -= 2;
        }
 
-       val = readl(addr);
-       val &= ~(0xff << ((dev_index << 4) + 8));
-       val |= (div & 0xff) << ((dev_index << 4) + 8);
-       writel(val, addr);
+       clrsetbits_le32(addr, 0xff << ((dev_index << 4) + 8),
+                       (div & 0xff) << ((dev_index << 4) + 8));
 }
 
 /* exynos5: set the mmc clock */
@@ -956,7 +934,7 @@ static void exynos5420_set_mmc_clk(int dev_index, unsigned int div)
        struct exynos5420_clock *clk =
                (struct exynos5420_clock *)samsung_get_base_clock();
        unsigned int addr;
-       unsigned int val, shift;
+       unsigned int shift;
 
        /*
         * CLK_DIV_FSYS1
@@ -967,10 +945,7 @@ static void exynos5420_set_mmc_clk(int dev_index, unsigned int div)
        addr = (unsigned int)&clk->div_fsys1;
        shift = dev_index * 10;
 
-       val = readl(addr);
-       val &= ~(0x3ff << shift);
-       val |= (div & 0x3ff) << shift;
-       writel(val, addr);
+       clrsetbits_le32(addr, 0x3ff << shift, (div & 0x3ff) << shift);
 }
 
 /* get_lcd_clk: return lcd clock frequency */
@@ -1057,11 +1032,44 @@ 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 =
            (struct exynos4_clock *)samsung_get_base_clock();
-       unsigned int cfg = 0;
 
        /*
         * CLK_GATE_BLOCK
@@ -1073,9 +1081,7 @@ void exynos4_set_lcd_clk(void)
         * CLK_LCD1     [5]
         * CLK_GPS      [7]
         */
-       cfg = readl(&clk->gate_block);
-       cfg |= 1 << 4;
-       writel(cfg, &clk->gate_block);
+       setbits_le32(&clk->gate_block, 1 << 4);
 
        /*
         * CLK_SRC_LCD0
@@ -1085,10 +1091,7 @@ void exynos4_set_lcd_clk(void)
         * MIPI0_SEL            [12:15]
         * set lcd0 src clock 0x6: SCLK_MPLL
         */
-       cfg = readl(&clk->src_lcd0);
-       cfg &= ~(0xf);
-       cfg |= 0x6;
-       writel(cfg, &clk->src_lcd0);
+       clrsetbits_le32(&clk->src_lcd0, 0xf, 0x6);
 
        /*
         * CLK_GATE_IP_LCD0
@@ -1100,9 +1103,7 @@ void exynos4_set_lcd_clk(void)
         * CLK_PPMULCD0         [5]
         * Gating all clocks for FIMD0
         */
-       cfg = readl(&clk->gate_ip_lcd0);
-       cfg |= 1 << 0;
-       writel(cfg, &clk->gate_ip_lcd0);
+       setbits_le32(&clk->gate_ip_lcd0, 1 << 0);
 
        /*
         * CLK_DIV_LCD0
@@ -1114,17 +1115,13 @@ void exynos4_set_lcd_clk(void)
         * MIPI0_PRE_RATIO      [23:20]
         * set fimd ratio
         */
-       cfg = readl(&clk->div_lcd0);
-       cfg &= ~(0xf);
-       cfg |= 0x1;
-       writel(cfg, &clk->div_lcd0);
+       clrsetbits_le32(&clk->div_lcd0, 0xf, 0x1);
 }
 
 void exynos5_set_lcd_clk(void)
 {
        struct exynos5_clock *clk =
            (struct exynos5_clock *)samsung_get_base_clock();
-       unsigned int cfg = 0;
 
        /*
         * CLK_GATE_BLOCK
@@ -1136,9 +1133,7 @@ void exynos5_set_lcd_clk(void)
         * CLK_LCD1     [5]
         * CLK_GPS      [7]
         */
-       cfg = readl(&clk->gate_block);
-       cfg |= 1 << 4;
-       writel(cfg, &clk->gate_block);
+       setbits_le32(&clk->gate_block, 1 << 4);
 
        /*
         * CLK_SRC_LCD0
@@ -1148,10 +1143,7 @@ void exynos5_set_lcd_clk(void)
         * MIPI0_SEL            [12:15]
         * set lcd0 src clock 0x6: SCLK_MPLL
         */
-       cfg = readl(&clk->src_disp1_0);
-       cfg &= ~(0xf);
-       cfg |= 0x6;
-       writel(cfg, &clk->src_disp1_0);
+       clrsetbits_le32(&clk->src_disp1_0, 0xf, 0x6);
 
        /*
         * CLK_GATE_IP_LCD0
@@ -1163,9 +1155,7 @@ void exynos5_set_lcd_clk(void)
         * CLK_PPMULCD0         [5]
         * Gating all clocks for FIMD0
         */
-       cfg = readl(&clk->gate_ip_disp1);
-       cfg |= 1 << 0;
-       writel(cfg, &clk->gate_ip_disp1);
+       setbits_le32(&clk->gate_ip_disp1, 1 << 0);
 
        /*
         * CLK_DIV_LCD0
@@ -1177,17 +1167,40 @@ void exynos5_set_lcd_clk(void)
         * MIPI0_PRE_RATIO      [23:20]
         * set fimd ratio
         */
-       cfg = readl(&clk->div_disp1_0);
-       cfg &= ~(0xf);
-       cfg |= 0x0;
-       writel(cfg, &clk->div_disp1_0);
+       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 =
            (struct exynos4_clock *)samsung_get_base_clock();
-       unsigned int cfg = 0;
 
        /*
         * CLK_SRC_LCD0
@@ -1197,10 +1210,7 @@ void exynos4_set_mipi_clk(void)
         * MIPI0_SEL            [12:15]
         * set mipi0 src clock 0x6: SCLK_MPLL
         */
-       cfg = readl(&clk->src_lcd0);
-       cfg &= ~(0xf << 12);
-       cfg |= (0x6 << 12);
-       writel(cfg, &clk->src_lcd0);
+       clrsetbits_le32(&clk->src_lcd0, 0xf << 12, 0x6 << 12);
 
        /*
         * CLK_SRC_MASK_LCD0
@@ -1210,9 +1220,7 @@ void exynos4_set_mipi_clk(void)
         * MIPI0_MASK           [12]
         * set src mask mipi0 0x1: Unmask
         */
-       cfg = readl(&clk->src_mask_lcd0);
-       cfg |= (0x1 << 12);
-       writel(cfg, &clk->src_mask_lcd0);
+       setbits_le32(&clk->src_mask_lcd0, 0x1 << 12);
 
        /*
         * CLK_GATE_IP_LCD0
@@ -1224,9 +1232,7 @@ void exynos4_set_mipi_clk(void)
         * CLK_PPMULCD0         [5]
         * Gating all clocks for MIPI0
         */
-       cfg = readl(&clk->gate_ip_lcd0);
-       cfg |= 1 << 3;
-       writel(cfg, &clk->gate_ip_lcd0);
+       setbits_le32(&clk->gate_ip_lcd0, 1 << 3);
 
        /*
         * CLK_DIV_LCD0
@@ -1238,10 +1244,7 @@ void exynos4_set_mipi_clk(void)
         * MIPI0_PRE_RATIO      [23:20]
         * set mipi ratio
         */
-       cfg = readl(&clk->div_lcd0);
-       cfg &= ~(0xf << 16);
-       cfg |= (0x1 << 16);
-       writel(cfg, &clk->div_lcd0);
+       clrsetbits_le32(&clk->div_lcd0, 0xf << 16, 0x1 << 16);
 }
 
 /*
@@ -1420,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;
@@ -1579,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 {
@@ -1615,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 {
@@ -1628,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 {
@@ -1641,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 {
@@ -1652,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);
        }
 }
 
@@ -1668,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)
@@ -1689,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 {