2 * Copyright (C) 2010 Samsung Electronics
3 * Minkyu Kang <mk7.kang@samsung.com>
5 * See file CREDITS for list of people who contributed to this
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
26 #include <asm/arch/clock.h>
27 #include <asm/arch/clk.h>
29 /* exynos: return pll clock frequency */
30 static int exynos_get_pll_clk(int pllreg, unsigned int r, unsigned int k)
32 unsigned long m, p, s = 0, mask, fout;
35 * APLL_CON: MIDV [25:16]
36 * MPLL_CON: MIDV [25:16]
37 * EPLL_CON: MIDV [24:16]
38 * VPLL_CON: MIDV [24:16]
39 * BPLL_CON: MIDV [25:16]: Exynos5
41 if (pllreg == APLL || pllreg == MPLL || pllreg == BPLL)
53 freq = CONFIG_SYS_CLK_FREQ;
57 /* FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV) */
58 fout = (m + k / 65536) * (freq / (p * (1 << s)));
59 } else if (pllreg == VPLL) {
61 /* FOUT = (MDIV + K / 1024) * FIN / (PDIV * 2^SDIV) */
62 fout = (m + k / 1024) * (freq / (p * (1 << s)));
66 /* FOUT = MDIV * FIN / (PDIV * 2^(SDIV - 1)) */
67 fout = m * (freq / (p * (1 << (s - 1))));
73 /* exynos4: return pll clock frequency */
74 static unsigned long exynos4_get_pll_clk(int pllreg)
76 struct exynos4_clock *clk =
77 (struct exynos4_clock *)samsung_get_base_clock();
78 unsigned long r, k = 0;
82 r = readl(&clk->apll_con0);
85 r = readl(&clk->mpll_con0);
88 r = readl(&clk->epll_con0);
89 k = readl(&clk->epll_con1);
92 r = readl(&clk->vpll_con0);
93 k = readl(&clk->vpll_con1);
96 printf("Unsupported PLL (%d)\n", pllreg);
100 return exynos_get_pll_clk(pllreg, r, k);
103 /* exynos5: return pll clock frequency */
104 static unsigned long exynos5_get_pll_clk(int pllreg)
106 struct exynos5_clock *clk =
107 (struct exynos5_clock *)samsung_get_base_clock();
108 unsigned long r, k = 0, fout;
109 unsigned int pll_div2_sel, fout_sel;
113 r = readl(&clk->apll_con0);
116 r = readl(&clk->mpll_con0);
119 r = readl(&clk->epll_con0);
120 k = readl(&clk->epll_con1);
123 r = readl(&clk->vpll_con0);
124 k = readl(&clk->vpll_con1);
127 r = readl(&clk->bpll_con0);
130 printf("Unsupported PLL (%d)\n", pllreg);
134 fout = exynos_get_pll_clk(pllreg, r, k);
136 /* According to the user manual, in EVT1 MPLL and BPLL always gives
137 * 1.6GHz clock, so divide by 2 to get 800MHz MPLL clock.*/
138 if (pllreg == MPLL || pllreg == BPLL) {
139 pll_div2_sel = readl(&clk->pll_div2_sel);
143 fout_sel = (pll_div2_sel >> MPLL_FOUT_SEL_SHIFT)
144 & MPLL_FOUT_SEL_MASK;
147 fout_sel = (pll_div2_sel >> BPLL_FOUT_SEL_SHIFT)
148 & BPLL_FOUT_SEL_MASK;
162 /* exynos4: return ARM clock frequency */
163 static unsigned long exynos4_get_arm_clk(void)
165 struct exynos4_clock *clk =
166 (struct exynos4_clock *)samsung_get_base_clock();
168 unsigned long armclk;
169 unsigned int core_ratio;
170 unsigned int core2_ratio;
172 div = readl(&clk->div_cpu0);
174 /* CORE_RATIO: [2:0], CORE2_RATIO: [30:28] */
175 core_ratio = (div >> 0) & 0x7;
176 core2_ratio = (div >> 28) & 0x7;
178 armclk = get_pll_clk(APLL) / (core_ratio + 1);
179 armclk /= (core2_ratio + 1);
184 /* exynos5: return ARM clock frequency */
185 static unsigned long exynos5_get_arm_clk(void)
187 struct exynos5_clock *clk =
188 (struct exynos5_clock *)samsung_get_base_clock();
190 unsigned long armclk;
191 unsigned int arm_ratio;
192 unsigned int arm2_ratio;
194 div = readl(&clk->div_cpu0);
196 /* ARM_RATIO: [2:0], ARM2_RATIO: [30:28] */
197 arm_ratio = (div >> 0) & 0x7;
198 arm2_ratio = (div >> 28) & 0x7;
200 armclk = get_pll_clk(APLL) / (arm_ratio + 1);
201 armclk /= (arm2_ratio + 1);
206 /* exynos4: return pwm clock frequency */
207 static unsigned long exynos4_get_pwm_clk(void)
209 struct exynos4_clock *clk =
210 (struct exynos4_clock *)samsung_get_base_clock();
211 unsigned long pclk, sclk;
215 if (s5p_get_cpu_rev() == 0) {
220 sel = readl(&clk->src_peril0);
221 sel = (sel >> 24) & 0xf;
224 sclk = get_pll_clk(MPLL);
226 sclk = get_pll_clk(EPLL);
228 sclk = get_pll_clk(VPLL);
236 ratio = readl(&clk->div_peril3);
238 } else if (s5p_get_cpu_rev() == 1) {
239 sclk = get_pll_clk(MPLL);
244 pclk = sclk / (ratio + 1);
249 /* exynos5: return pwm clock frequency */
250 static unsigned long exynos5_get_pwm_clk(void)
252 struct exynos5_clock *clk =
253 (struct exynos5_clock *)samsung_get_base_clock();
254 unsigned long pclk, sclk;
261 ratio = readl(&clk->div_peric3);
263 sclk = get_pll_clk(MPLL);
265 pclk = sclk / (ratio + 1);
270 /* exynos4: return uart clock frequency */
271 static unsigned long exynos4_get_uart_clk(int dev_index)
273 struct exynos4_clock *clk =
274 (struct exynos4_clock *)samsung_get_base_clock();
275 unsigned long uclk, sclk;
288 sel = readl(&clk->src_peril0);
289 sel = (sel >> (dev_index << 2)) & 0xf;
292 sclk = get_pll_clk(MPLL);
294 sclk = get_pll_clk(EPLL);
296 sclk = get_pll_clk(VPLL);
305 * UART3_RATIO [12:15]
306 * UART4_RATIO [16:19]
307 * UART5_RATIO [23:20]
309 ratio = readl(&clk->div_peril0);
310 ratio = (ratio >> (dev_index << 2)) & 0xf;
312 uclk = sclk / (ratio + 1);
317 /* exynos5: return uart clock frequency */
318 static unsigned long exynos5_get_uart_clk(int dev_index)
320 struct exynos5_clock *clk =
321 (struct exynos5_clock *)samsung_get_base_clock();
322 unsigned long uclk, sclk;
335 sel = readl(&clk->src_peric0);
336 sel = (sel >> (dev_index << 2)) & 0xf;
339 sclk = get_pll_clk(MPLL);
341 sclk = get_pll_clk(EPLL);
343 sclk = get_pll_clk(VPLL);
352 * UART3_RATIO [12:15]
353 * UART4_RATIO [16:19]
354 * UART5_RATIO [23:20]
356 ratio = readl(&clk->div_peric0);
357 ratio = (ratio >> (dev_index << 2)) & 0xf;
359 uclk = sclk / (ratio + 1);
364 /* exynos4: set the mmc clock */
365 static void exynos4_set_mmc_clk(int dev_index, unsigned int div)
367 struct exynos4_clock *clk =
368 (struct exynos4_clock *)samsung_get_base_clock();
374 * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24]
376 * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24]
379 addr = (unsigned int)&clk->div_fsys1;
381 addr = (unsigned int)&clk->div_fsys2;
386 val &= ~(0xff << ((dev_index << 4) + 8));
387 val |= (div & 0xff) << ((dev_index << 4) + 8);
391 /* exynos5: set the mmc clock */
392 static void exynos5_set_mmc_clk(int dev_index, unsigned int div)
394 struct exynos5_clock *clk =
395 (struct exynos5_clock *)samsung_get_base_clock();
401 * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24]
403 * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24]
406 addr = (unsigned int)&clk->div_fsys1;
408 addr = (unsigned int)&clk->div_fsys2;
413 val &= ~(0xff << ((dev_index << 4) + 8));
414 val |= (div & 0xff) << ((dev_index << 4) + 8);
418 /* get_lcd_clk: return lcd clock frequency */
419 static unsigned long exynos4_get_lcd_clk(void)
421 struct exynos4_clock *clk =
422 (struct exynos4_clock *)samsung_get_base_clock();
423 unsigned long pclk, sclk;
431 sel = readl(&clk->src_lcd0);
440 sclk = get_pll_clk(MPLL);
442 sclk = get_pll_clk(EPLL);
444 sclk = get_pll_clk(VPLL);
452 ratio = readl(&clk->div_lcd0);
455 pclk = sclk / (ratio + 1);
460 /* get_lcd_clk: return lcd clock frequency */
461 static unsigned long exynos5_get_lcd_clk(void)
463 struct exynos5_clock *clk =
464 (struct exynos5_clock *)samsung_get_base_clock();
465 unsigned long pclk, sclk;
473 sel = readl(&clk->src_disp1_0);
482 sclk = get_pll_clk(MPLL);
484 sclk = get_pll_clk(EPLL);
486 sclk = get_pll_clk(VPLL);
494 ratio = readl(&clk->div_disp1_0);
497 pclk = sclk / (ratio + 1);
502 void exynos4_set_lcd_clk(void)
504 struct exynos4_clock *clk =
505 (struct exynos4_clock *)samsung_get_base_clock();
506 unsigned int cfg = 0;
518 cfg = readl(&clk->gate_block);
520 writel(cfg, &clk->gate_block);
526 * MDNIE_PWM0_SEL [8:11]
528 * set lcd0 src clock 0x6: SCLK_MPLL
530 cfg = readl(&clk->src_lcd0);
533 writel(cfg, &clk->src_lcd0);
543 * Gating all clocks for FIMD0
545 cfg = readl(&clk->gate_ip_lcd0);
547 writel(cfg, &clk->gate_ip_lcd0);
553 * MDNIE_PWM0_RATIO [11:8]
554 * MDNIE_PWM_PRE_RATIO [15:12]
555 * MIPI0_RATIO [19:16]
556 * MIPI0_PRE_RATIO [23:20]
561 writel(cfg, &clk->div_lcd0);
564 void exynos5_set_lcd_clk(void)
566 struct exynos5_clock *clk =
567 (struct exynos5_clock *)samsung_get_base_clock();
568 unsigned int cfg = 0;
580 cfg = readl(&clk->gate_block);
582 writel(cfg, &clk->gate_block);
588 * MDNIE_PWM0_SEL [8:11]
590 * set lcd0 src clock 0x6: SCLK_MPLL
592 cfg = readl(&clk->src_disp1_0);
595 writel(cfg, &clk->src_disp1_0);
605 * Gating all clocks for FIMD0
607 cfg = readl(&clk->gate_ip_disp1);
609 writel(cfg, &clk->gate_ip_disp1);
615 * MDNIE_PWM0_RATIO [11:8]
616 * MDNIE_PWM_PRE_RATIO [15:12]
617 * MIPI0_RATIO [19:16]
618 * MIPI0_PRE_RATIO [23:20]
623 writel(cfg, &clk->div_disp1_0);
626 void exynos4_set_mipi_clk(void)
628 struct exynos4_clock *clk =
629 (struct exynos4_clock *)samsung_get_base_clock();
630 unsigned int cfg = 0;
636 * MDNIE_PWM0_SEL [8:11]
638 * set mipi0 src clock 0x6: SCLK_MPLL
640 cfg = readl(&clk->src_lcd0);
643 writel(cfg, &clk->src_lcd0);
649 * MDNIE_PWM0_MASK [8]
651 * set src mask mipi0 0x1: Unmask
653 cfg = readl(&clk->src_mask_lcd0);
655 writel(cfg, &clk->src_mask_lcd0);
665 * Gating all clocks for MIPI0
667 cfg = readl(&clk->gate_ip_lcd0);
669 writel(cfg, &clk->gate_ip_lcd0);
675 * MDNIE_PWM0_RATIO [11:8]
676 * MDNIE_PWM_PRE_RATIO [15:12]
677 * MIPI0_RATIO [19:16]
678 * MIPI0_PRE_RATIO [23:20]
683 writel(cfg, &clk->div_lcd0);
689 * exynos5: obtaining the I2C clock
691 static unsigned long exynos5_get_i2c_clk(void)
693 struct exynos5_clock *clk =
694 (struct exynos5_clock *)samsung_get_base_clock();
695 unsigned long aclk_66, aclk_66_pre, sclk;
698 sclk = get_pll_clk(MPLL);
700 ratio = (readl(&clk->div_top1)) >> 24;
702 aclk_66_pre = sclk / (ratio + 1);
703 ratio = readl(&clk->div_top0);
705 aclk_66 = aclk_66_pre / (ratio + 1);
709 unsigned long get_pll_clk(int pllreg)
711 if (cpu_is_exynos5())
712 return exynos5_get_pll_clk(pllreg);
714 return exynos4_get_pll_clk(pllreg);
717 unsigned long get_arm_clk(void)
719 if (cpu_is_exynos5())
720 return exynos5_get_arm_clk();
722 return exynos4_get_arm_clk();
725 unsigned long get_i2c_clk(void)
727 if (cpu_is_exynos5()) {
728 return exynos5_get_i2c_clk();
730 debug("I2C clock is not set for this CPU\n");
735 unsigned long get_pwm_clk(void)
737 if (cpu_is_exynos5())
738 return exynos5_get_pwm_clk();
740 return exynos4_get_pwm_clk();
743 unsigned long get_uart_clk(int dev_index)
745 if (cpu_is_exynos5())
746 return exynos5_get_uart_clk(dev_index);
748 return exynos4_get_uart_clk(dev_index);
751 void set_mmc_clk(int dev_index, unsigned int div)
753 if (cpu_is_exynos5())
754 exynos5_set_mmc_clk(dev_index, div);
756 exynos4_set_mmc_clk(dev_index, div);
759 unsigned long get_lcd_clk(void)
761 if (cpu_is_exynos4())
762 return exynos4_get_lcd_clk();
764 return exynos5_get_lcd_clk();
767 void set_lcd_clk(void)
769 if (cpu_is_exynos4())
770 exynos4_set_lcd_clk();
772 exynos5_set_lcd_clk();
775 void set_mipi_clk(void)
777 if (cpu_is_exynos4())
778 exynos4_set_mipi_clk();