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 /* Epll Clock division values to achive different frequency output */
30 static struct set_epll_con_val exynos5_epll_div[] = {
31 { 192000000, 0, 48, 3, 1, 0 },
32 { 180000000, 0, 45, 3, 1, 0 },
33 { 73728000, 1, 73, 3, 3, 47710 },
34 { 67737600, 1, 90, 4, 3, 20762 },
35 { 49152000, 0, 49, 3, 3, 9961 },
36 { 45158400, 0, 45, 3, 3, 10381 },
37 { 180633600, 0, 45, 3, 1, 10381 }
40 /* exynos: return pll clock frequency */
41 static int exynos_get_pll_clk(int pllreg, unsigned int r, unsigned int k)
43 unsigned long m, p, s = 0, mask, fout;
46 * APLL_CON: MIDV [25:16]
47 * MPLL_CON: MIDV [25:16]
48 * EPLL_CON: MIDV [24:16]
49 * VPLL_CON: MIDV [24:16]
50 * BPLL_CON: MIDV [25:16]: Exynos5
52 if (pllreg == APLL || pllreg == MPLL || pllreg == BPLL)
64 freq = CONFIG_SYS_CLK_FREQ;
68 /* FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV) */
69 fout = (m + k / 65536) * (freq / (p * (1 << s)));
70 } else if (pllreg == VPLL) {
72 /* FOUT = (MDIV + K / 1024) * FIN / (PDIV * 2^SDIV) */
73 fout = (m + k / 1024) * (freq / (p * (1 << s)));
77 /* FOUT = MDIV * FIN / (PDIV * 2^(SDIV - 1)) */
78 fout = m * (freq / (p * (1 << (s - 1))));
84 /* exynos4: return pll clock frequency */
85 static unsigned long exynos4_get_pll_clk(int pllreg)
87 struct exynos4_clock *clk =
88 (struct exynos4_clock *)samsung_get_base_clock();
89 unsigned long r, k = 0;
93 r = readl(&clk->apll_con0);
96 r = readl(&clk->mpll_con0);
99 r = readl(&clk->epll_con0);
100 k = readl(&clk->epll_con1);
103 r = readl(&clk->vpll_con0);
104 k = readl(&clk->vpll_con1);
107 printf("Unsupported PLL (%d)\n", pllreg);
111 return exynos_get_pll_clk(pllreg, r, k);
114 /* exynos5: return pll clock frequency */
115 static unsigned long exynos5_get_pll_clk(int pllreg)
117 struct exynos5_clock *clk =
118 (struct exynos5_clock *)samsung_get_base_clock();
119 unsigned long r, k = 0, fout;
120 unsigned int pll_div2_sel, fout_sel;
124 r = readl(&clk->apll_con0);
127 r = readl(&clk->mpll_con0);
130 r = readl(&clk->epll_con0);
131 k = readl(&clk->epll_con1);
134 r = readl(&clk->vpll_con0);
135 k = readl(&clk->vpll_con1);
138 r = readl(&clk->bpll_con0);
141 printf("Unsupported PLL (%d)\n", pllreg);
145 fout = exynos_get_pll_clk(pllreg, r, k);
147 /* According to the user manual, in EVT1 MPLL and BPLL always gives
148 * 1.6GHz clock, so divide by 2 to get 800MHz MPLL clock.*/
149 if (pllreg == MPLL || pllreg == BPLL) {
150 pll_div2_sel = readl(&clk->pll_div2_sel);
154 fout_sel = (pll_div2_sel >> MPLL_FOUT_SEL_SHIFT)
155 & MPLL_FOUT_SEL_MASK;
158 fout_sel = (pll_div2_sel >> BPLL_FOUT_SEL_SHIFT)
159 & BPLL_FOUT_SEL_MASK;
173 /* exynos4: return ARM clock frequency */
174 static unsigned long exynos4_get_arm_clk(void)
176 struct exynos4_clock *clk =
177 (struct exynos4_clock *)samsung_get_base_clock();
179 unsigned long armclk;
180 unsigned int core_ratio;
181 unsigned int core2_ratio;
183 div = readl(&clk->div_cpu0);
185 /* CORE_RATIO: [2:0], CORE2_RATIO: [30:28] */
186 core_ratio = (div >> 0) & 0x7;
187 core2_ratio = (div >> 28) & 0x7;
189 armclk = get_pll_clk(APLL) / (core_ratio + 1);
190 armclk /= (core2_ratio + 1);
195 /* exynos5: return ARM clock frequency */
196 static unsigned long exynos5_get_arm_clk(void)
198 struct exynos5_clock *clk =
199 (struct exynos5_clock *)samsung_get_base_clock();
201 unsigned long armclk;
202 unsigned int arm_ratio;
203 unsigned int arm2_ratio;
205 div = readl(&clk->div_cpu0);
207 /* ARM_RATIO: [2:0], ARM2_RATIO: [30:28] */
208 arm_ratio = (div >> 0) & 0x7;
209 arm2_ratio = (div >> 28) & 0x7;
211 armclk = get_pll_clk(APLL) / (arm_ratio + 1);
212 armclk /= (arm2_ratio + 1);
217 /* exynos4: return pwm clock frequency */
218 static unsigned long exynos4_get_pwm_clk(void)
220 struct exynos4_clock *clk =
221 (struct exynos4_clock *)samsung_get_base_clock();
222 unsigned long pclk, sclk;
226 if (s5p_get_cpu_rev() == 0) {
231 sel = readl(&clk->src_peril0);
232 sel = (sel >> 24) & 0xf;
235 sclk = get_pll_clk(MPLL);
237 sclk = get_pll_clk(EPLL);
239 sclk = get_pll_clk(VPLL);
247 ratio = readl(&clk->div_peril3);
249 } else if (s5p_get_cpu_rev() == 1) {
250 sclk = get_pll_clk(MPLL);
255 pclk = sclk / (ratio + 1);
260 /* exynos5: return pwm clock frequency */
261 static unsigned long exynos5_get_pwm_clk(void)
263 struct exynos5_clock *clk =
264 (struct exynos5_clock *)samsung_get_base_clock();
265 unsigned long pclk, sclk;
272 ratio = readl(&clk->div_peric3);
274 sclk = get_pll_clk(MPLL);
276 pclk = sclk / (ratio + 1);
281 /* exynos4: return uart clock frequency */
282 static unsigned long exynos4_get_uart_clk(int dev_index)
284 struct exynos4_clock *clk =
285 (struct exynos4_clock *)samsung_get_base_clock();
286 unsigned long uclk, sclk;
299 sel = readl(&clk->src_peril0);
300 sel = (sel >> (dev_index << 2)) & 0xf;
303 sclk = get_pll_clk(MPLL);
305 sclk = get_pll_clk(EPLL);
307 sclk = get_pll_clk(VPLL);
316 * UART3_RATIO [12:15]
317 * UART4_RATIO [16:19]
318 * UART5_RATIO [23:20]
320 ratio = readl(&clk->div_peril0);
321 ratio = (ratio >> (dev_index << 2)) & 0xf;
323 uclk = sclk / (ratio + 1);
328 /* exynos5: return uart clock frequency */
329 static unsigned long exynos5_get_uart_clk(int dev_index)
331 struct exynos5_clock *clk =
332 (struct exynos5_clock *)samsung_get_base_clock();
333 unsigned long uclk, sclk;
346 sel = readl(&clk->src_peric0);
347 sel = (sel >> (dev_index << 2)) & 0xf;
350 sclk = get_pll_clk(MPLL);
352 sclk = get_pll_clk(EPLL);
354 sclk = get_pll_clk(VPLL);
363 * UART3_RATIO [12:15]
364 * UART4_RATIO [16:19]
365 * UART5_RATIO [23:20]
367 ratio = readl(&clk->div_peric0);
368 ratio = (ratio >> (dev_index << 2)) & 0xf;
370 uclk = sclk / (ratio + 1);
375 /* exynos4: set the mmc clock */
376 static void exynos4_set_mmc_clk(int dev_index, unsigned int div)
378 struct exynos4_clock *clk =
379 (struct exynos4_clock *)samsung_get_base_clock();
385 * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24]
387 * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24]
390 addr = (unsigned int)&clk->div_fsys1;
392 addr = (unsigned int)&clk->div_fsys2;
397 val &= ~(0xff << ((dev_index << 4) + 8));
398 val |= (div & 0xff) << ((dev_index << 4) + 8);
402 /* exynos5: set the mmc clock */
403 static void exynos5_set_mmc_clk(int dev_index, unsigned int div)
405 struct exynos5_clock *clk =
406 (struct exynos5_clock *)samsung_get_base_clock();
412 * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24]
414 * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24]
417 addr = (unsigned int)&clk->div_fsys1;
419 addr = (unsigned int)&clk->div_fsys2;
424 val &= ~(0xff << ((dev_index << 4) + 8));
425 val |= (div & 0xff) << ((dev_index << 4) + 8);
429 /* get_lcd_clk: return lcd clock frequency */
430 static unsigned long exynos4_get_lcd_clk(void)
432 struct exynos4_clock *clk =
433 (struct exynos4_clock *)samsung_get_base_clock();
434 unsigned long pclk, sclk;
442 sel = readl(&clk->src_lcd0);
451 sclk = get_pll_clk(MPLL);
453 sclk = get_pll_clk(EPLL);
455 sclk = get_pll_clk(VPLL);
463 ratio = readl(&clk->div_lcd0);
466 pclk = sclk / (ratio + 1);
471 /* get_lcd_clk: return lcd clock frequency */
472 static unsigned long exynos5_get_lcd_clk(void)
474 struct exynos5_clock *clk =
475 (struct exynos5_clock *)samsung_get_base_clock();
476 unsigned long pclk, sclk;
484 sel = readl(&clk->src_disp1_0);
493 sclk = get_pll_clk(MPLL);
495 sclk = get_pll_clk(EPLL);
497 sclk = get_pll_clk(VPLL);
505 ratio = readl(&clk->div_disp1_0);
508 pclk = sclk / (ratio + 1);
513 void exynos4_set_lcd_clk(void)
515 struct exynos4_clock *clk =
516 (struct exynos4_clock *)samsung_get_base_clock();
517 unsigned int cfg = 0;
529 cfg = readl(&clk->gate_block);
531 writel(cfg, &clk->gate_block);
537 * MDNIE_PWM0_SEL [8:11]
539 * set lcd0 src clock 0x6: SCLK_MPLL
541 cfg = readl(&clk->src_lcd0);
544 writel(cfg, &clk->src_lcd0);
554 * Gating all clocks for FIMD0
556 cfg = readl(&clk->gate_ip_lcd0);
558 writel(cfg, &clk->gate_ip_lcd0);
564 * MDNIE_PWM0_RATIO [11:8]
565 * MDNIE_PWM_PRE_RATIO [15:12]
566 * MIPI0_RATIO [19:16]
567 * MIPI0_PRE_RATIO [23:20]
572 writel(cfg, &clk->div_lcd0);
575 void exynos5_set_lcd_clk(void)
577 struct exynos5_clock *clk =
578 (struct exynos5_clock *)samsung_get_base_clock();
579 unsigned int cfg = 0;
591 cfg = readl(&clk->gate_block);
593 writel(cfg, &clk->gate_block);
599 * MDNIE_PWM0_SEL [8:11]
601 * set lcd0 src clock 0x6: SCLK_MPLL
603 cfg = readl(&clk->src_disp1_0);
606 writel(cfg, &clk->src_disp1_0);
616 * Gating all clocks for FIMD0
618 cfg = readl(&clk->gate_ip_disp1);
620 writel(cfg, &clk->gate_ip_disp1);
626 * MDNIE_PWM0_RATIO [11:8]
627 * MDNIE_PWM_PRE_RATIO [15:12]
628 * MIPI0_RATIO [19:16]
629 * MIPI0_PRE_RATIO [23:20]
634 writel(cfg, &clk->div_disp1_0);
637 void exynos4_set_mipi_clk(void)
639 struct exynos4_clock *clk =
640 (struct exynos4_clock *)samsung_get_base_clock();
641 unsigned int cfg = 0;
647 * MDNIE_PWM0_SEL [8:11]
649 * set mipi0 src clock 0x6: SCLK_MPLL
651 cfg = readl(&clk->src_lcd0);
654 writel(cfg, &clk->src_lcd0);
660 * MDNIE_PWM0_MASK [8]
662 * set src mask mipi0 0x1: Unmask
664 cfg = readl(&clk->src_mask_lcd0);
666 writel(cfg, &clk->src_mask_lcd0);
676 * Gating all clocks for MIPI0
678 cfg = readl(&clk->gate_ip_lcd0);
680 writel(cfg, &clk->gate_ip_lcd0);
686 * MDNIE_PWM0_RATIO [11:8]
687 * MDNIE_PWM_PRE_RATIO [15:12]
688 * MIPI0_RATIO [19:16]
689 * MIPI0_PRE_RATIO [23:20]
694 writel(cfg, &clk->div_lcd0);
700 * exynos5: obtaining the I2C clock
702 static unsigned long exynos5_get_i2c_clk(void)
704 struct exynos5_clock *clk =
705 (struct exynos5_clock *)samsung_get_base_clock();
706 unsigned long aclk_66, aclk_66_pre, sclk;
709 sclk = get_pll_clk(MPLL);
711 ratio = (readl(&clk->div_top1)) >> 24;
713 aclk_66_pre = sclk / (ratio + 1);
714 ratio = readl(&clk->div_top0);
716 aclk_66 = aclk_66_pre / (ratio + 1);
720 int exynos5_set_epll_clk(unsigned long rate)
722 unsigned int epll_con, epll_con_k;
724 unsigned int lockcnt;
726 struct exynos5_clock *clk =
727 (struct exynos5_clock *)samsung_get_base_clock();
729 epll_con = readl(&clk->epll_con0);
730 epll_con &= ~((EPLL_CON0_LOCK_DET_EN_MASK <<
731 EPLL_CON0_LOCK_DET_EN_SHIFT) |
732 EPLL_CON0_MDIV_MASK << EPLL_CON0_MDIV_SHIFT |
733 EPLL_CON0_PDIV_MASK << EPLL_CON0_PDIV_SHIFT |
734 EPLL_CON0_SDIV_MASK << EPLL_CON0_SDIV_SHIFT);
736 for (i = 0; i < ARRAY_SIZE(exynos5_epll_div); i++) {
737 if (exynos5_epll_div[i].freq_out == rate)
741 if (i == ARRAY_SIZE(exynos5_epll_div))
744 epll_con_k = exynos5_epll_div[i].k_dsm << 0;
745 epll_con |= exynos5_epll_div[i].en_lock_det <<
746 EPLL_CON0_LOCK_DET_EN_SHIFT;
747 epll_con |= exynos5_epll_div[i].m_div << EPLL_CON0_MDIV_SHIFT;
748 epll_con |= exynos5_epll_div[i].p_div << EPLL_CON0_PDIV_SHIFT;
749 epll_con |= exynos5_epll_div[i].s_div << EPLL_CON0_SDIV_SHIFT;
752 * Required period ( in cycles) to genarate a stable clock output.
753 * The maximum clock time can be up to 3000 * PDIV cycles of PLLs
754 * frequency input (as per spec)
756 lockcnt = 3000 * exynos5_epll_div[i].p_div;
758 writel(lockcnt, &clk->epll_lock);
759 writel(epll_con, &clk->epll_con0);
760 writel(epll_con_k, &clk->epll_con1);
762 start = get_timer(0);
764 while (!(readl(&clk->epll_con0) &
765 (0x1 << EXYNOS5_EPLLCON0_LOCKED_SHIFT))) {
766 if (get_timer(start) > TIMEOUT_EPLL_LOCK) {
767 debug("%s: Timeout waiting for EPLL lock\n", __func__);
774 void exynos5_set_i2s_clk_source(void)
776 struct exynos5_clock *clk =
777 (struct exynos5_clock *)samsung_get_base_clock();
779 clrsetbits_le32(&clk->src_peric1, AUDIO1_SEL_MASK,
780 (CLK_SRC_SCLK_EPLL));
783 int exynos5_set_i2s_clk_prescaler(unsigned int src_frq,
784 unsigned int dst_frq)
786 struct exynos5_clock *clk =
787 (struct exynos5_clock *)samsung_get_base_clock();
790 if ((dst_frq == 0) || (src_frq == 0)) {
791 debug("%s: Invalid requency input for prescaler\n", __func__);
792 debug("src frq = %d des frq = %d ", src_frq, dst_frq);
796 div = (src_frq / dst_frq);
797 if (div > AUDIO_1_RATIO_MASK) {
798 debug("%s: Frequency ratio is out of range\n", __func__);
799 debug("src frq = %d des frq = %d ", src_frq, dst_frq);
802 clrsetbits_le32(&clk->div_peric4, AUDIO_1_RATIO_MASK,
803 (div & AUDIO_1_RATIO_MASK));
807 unsigned long get_pll_clk(int pllreg)
809 if (cpu_is_exynos5())
810 return exynos5_get_pll_clk(pllreg);
812 return exynos4_get_pll_clk(pllreg);
815 unsigned long get_arm_clk(void)
817 if (cpu_is_exynos5())
818 return exynos5_get_arm_clk();
820 return exynos4_get_arm_clk();
823 unsigned long get_i2c_clk(void)
825 if (cpu_is_exynos5()) {
826 return exynos5_get_i2c_clk();
828 debug("I2C clock is not set for this CPU\n");
833 unsigned long get_pwm_clk(void)
835 if (cpu_is_exynos5())
836 return exynos5_get_pwm_clk();
838 return exynos4_get_pwm_clk();
841 unsigned long get_uart_clk(int dev_index)
843 if (cpu_is_exynos5())
844 return exynos5_get_uart_clk(dev_index);
846 return exynos4_get_uart_clk(dev_index);
849 void set_mmc_clk(int dev_index, unsigned int div)
851 if (cpu_is_exynos5())
852 exynos5_set_mmc_clk(dev_index, div);
854 exynos4_set_mmc_clk(dev_index, div);
857 unsigned long get_lcd_clk(void)
859 if (cpu_is_exynos4())
860 return exynos4_get_lcd_clk();
862 return exynos5_get_lcd_clk();
865 void set_lcd_clk(void)
867 if (cpu_is_exynos4())
868 exynos4_set_lcd_clk();
870 exynos5_set_lcd_clk();
873 void set_mipi_clk(void)
875 if (cpu_is_exynos4())
876 exynos4_set_mipi_clk();
879 int set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq)
882 if (cpu_is_exynos5())
883 return exynos5_set_i2s_clk_prescaler(src_frq, dst_frq);
888 void set_i2s_clk_source(void)
890 if (cpu_is_exynos5())
891 exynos5_set_i2s_clk_source();
894 int set_epll_clk(unsigned long rate)
896 if (cpu_is_exynos5())
897 return exynos5_set_epll_clk(rate);