]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/armv7/exynos/clock.c
EXYNOS: Add clock for I2S
[karo-tx-uboot.git] / arch / arm / cpu / armv7 / exynos / clock.c
1 /*
2  * Copyright (C) 2010 Samsung Electronics
3  * Minkyu Kang <mk7.kang@samsung.com>
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
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.
12  *
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.
17  *
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,
21  * MA 02111-1307 USA
22  */
23
24 #include <common.h>
25 #include <asm/io.h>
26 #include <asm/arch/clock.h>
27 #include <asm/arch/clk.h>
28
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 }
38 };
39
40 /* exynos: return pll clock frequency */
41 static int exynos_get_pll_clk(int pllreg, unsigned int r, unsigned int k)
42 {
43         unsigned long m, p, s = 0, mask, fout;
44         unsigned int freq;
45         /*
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
51          */
52         if (pllreg == APLL || pllreg == MPLL || pllreg == BPLL)
53                 mask = 0x3ff;
54         else
55                 mask = 0x1ff;
56
57         m = (r >> 16) & mask;
58
59         /* PDIV [13:8] */
60         p = (r >> 8) & 0x3f;
61         /* SDIV [2:0] */
62         s = r & 0x7;
63
64         freq = CONFIG_SYS_CLK_FREQ;
65
66         if (pllreg == EPLL) {
67                 k = k & 0xffff;
68                 /* FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV) */
69                 fout = (m + k / 65536) * (freq / (p * (1 << s)));
70         } else if (pllreg == VPLL) {
71                 k = k & 0xfff;
72                 /* FOUT = (MDIV + K / 1024) * FIN / (PDIV * 2^SDIV) */
73                 fout = (m + k / 1024) * (freq / (p * (1 << s)));
74         } else {
75                 if (s < 1)
76                         s = 1;
77                 /* FOUT = MDIV * FIN / (PDIV * 2^(SDIV - 1)) */
78                 fout = m * (freq / (p * (1 << (s - 1))));
79         }
80
81         return fout;
82 }
83
84 /* exynos4: return pll clock frequency */
85 static unsigned long exynos4_get_pll_clk(int pllreg)
86 {
87         struct exynos4_clock *clk =
88                 (struct exynos4_clock *)samsung_get_base_clock();
89         unsigned long r, k = 0;
90
91         switch (pllreg) {
92         case APLL:
93                 r = readl(&clk->apll_con0);
94                 break;
95         case MPLL:
96                 r = readl(&clk->mpll_con0);
97                 break;
98         case EPLL:
99                 r = readl(&clk->epll_con0);
100                 k = readl(&clk->epll_con1);
101                 break;
102         case VPLL:
103                 r = readl(&clk->vpll_con0);
104                 k = readl(&clk->vpll_con1);
105                 break;
106         default:
107                 printf("Unsupported PLL (%d)\n", pllreg);
108                 return 0;
109         }
110
111         return exynos_get_pll_clk(pllreg, r, k);
112 }
113
114 /* exynos5: return pll clock frequency */
115 static unsigned long exynos5_get_pll_clk(int pllreg)
116 {
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;
121
122         switch (pllreg) {
123         case APLL:
124                 r = readl(&clk->apll_con0);
125                 break;
126         case MPLL:
127                 r = readl(&clk->mpll_con0);
128                 break;
129         case EPLL:
130                 r = readl(&clk->epll_con0);
131                 k = readl(&clk->epll_con1);
132                 break;
133         case VPLL:
134                 r = readl(&clk->vpll_con0);
135                 k = readl(&clk->vpll_con1);
136                 break;
137         case BPLL:
138                 r = readl(&clk->bpll_con0);
139                 break;
140         default:
141                 printf("Unsupported PLL (%d)\n", pllreg);
142                 return 0;
143         }
144
145         fout = exynos_get_pll_clk(pllreg, r, k);
146
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);
151
152                 switch (pllreg) {
153                 case MPLL:
154                         fout_sel = (pll_div2_sel >> MPLL_FOUT_SEL_SHIFT)
155                                         & MPLL_FOUT_SEL_MASK;
156                         break;
157                 case BPLL:
158                         fout_sel = (pll_div2_sel >> BPLL_FOUT_SEL_SHIFT)
159                                         & BPLL_FOUT_SEL_MASK;
160                         break;
161                 default:
162                         fout_sel = -1;
163                         break;
164                 }
165
166                 if (fout_sel == 0)
167                         fout /= 2;
168         }
169
170         return fout;
171 }
172
173 /* exynos4: return ARM clock frequency */
174 static unsigned long exynos4_get_arm_clk(void)
175 {
176         struct exynos4_clock *clk =
177                 (struct exynos4_clock *)samsung_get_base_clock();
178         unsigned long div;
179         unsigned long armclk;
180         unsigned int core_ratio;
181         unsigned int core2_ratio;
182
183         div = readl(&clk->div_cpu0);
184
185         /* CORE_RATIO: [2:0], CORE2_RATIO: [30:28] */
186         core_ratio = (div >> 0) & 0x7;
187         core2_ratio = (div >> 28) & 0x7;
188
189         armclk = get_pll_clk(APLL) / (core_ratio + 1);
190         armclk /= (core2_ratio + 1);
191
192         return armclk;
193 }
194
195 /* exynos5: return ARM clock frequency */
196 static unsigned long exynos5_get_arm_clk(void)
197 {
198         struct exynos5_clock *clk =
199                 (struct exynos5_clock *)samsung_get_base_clock();
200         unsigned long div;
201         unsigned long armclk;
202         unsigned int arm_ratio;
203         unsigned int arm2_ratio;
204
205         div = readl(&clk->div_cpu0);
206
207         /* ARM_RATIO: [2:0], ARM2_RATIO: [30:28] */
208         arm_ratio = (div >> 0) & 0x7;
209         arm2_ratio = (div >> 28) & 0x7;
210
211         armclk = get_pll_clk(APLL) / (arm_ratio + 1);
212         armclk /= (arm2_ratio + 1);
213
214         return armclk;
215 }
216
217 /* exynos4: return pwm clock frequency */
218 static unsigned long exynos4_get_pwm_clk(void)
219 {
220         struct exynos4_clock *clk =
221                 (struct exynos4_clock *)samsung_get_base_clock();
222         unsigned long pclk, sclk;
223         unsigned int sel;
224         unsigned int ratio;
225
226         if (s5p_get_cpu_rev() == 0) {
227                 /*
228                  * CLK_SRC_PERIL0
229                  * PWM_SEL [27:24]
230                  */
231                 sel = readl(&clk->src_peril0);
232                 sel = (sel >> 24) & 0xf;
233
234                 if (sel == 0x6)
235                         sclk = get_pll_clk(MPLL);
236                 else if (sel == 0x7)
237                         sclk = get_pll_clk(EPLL);
238                 else if (sel == 0x8)
239                         sclk = get_pll_clk(VPLL);
240                 else
241                         return 0;
242
243                 /*
244                  * CLK_DIV_PERIL3
245                  * PWM_RATIO [3:0]
246                  */
247                 ratio = readl(&clk->div_peril3);
248                 ratio = ratio & 0xf;
249         } else if (s5p_get_cpu_rev() == 1) {
250                 sclk = get_pll_clk(MPLL);
251                 ratio = 8;
252         } else
253                 return 0;
254
255         pclk = sclk / (ratio + 1);
256
257         return pclk;
258 }
259
260 /* exynos5: return pwm clock frequency */
261 static unsigned long exynos5_get_pwm_clk(void)
262 {
263         struct exynos5_clock *clk =
264                 (struct exynos5_clock *)samsung_get_base_clock();
265         unsigned long pclk, sclk;
266         unsigned int ratio;
267
268         /*
269          * CLK_DIV_PERIC3
270          * PWM_RATIO [3:0]
271          */
272         ratio = readl(&clk->div_peric3);
273         ratio = ratio & 0xf;
274         sclk = get_pll_clk(MPLL);
275
276         pclk = sclk / (ratio + 1);
277
278         return pclk;
279 }
280
281 /* exynos4: return uart clock frequency */
282 static unsigned long exynos4_get_uart_clk(int dev_index)
283 {
284         struct exynos4_clock *clk =
285                 (struct exynos4_clock *)samsung_get_base_clock();
286         unsigned long uclk, sclk;
287         unsigned int sel;
288         unsigned int ratio;
289
290         /*
291          * CLK_SRC_PERIL0
292          * UART0_SEL [3:0]
293          * UART1_SEL [7:4]
294          * UART2_SEL [8:11]
295          * UART3_SEL [12:15]
296          * UART4_SEL [16:19]
297          * UART5_SEL [23:20]
298          */
299         sel = readl(&clk->src_peril0);
300         sel = (sel >> (dev_index << 2)) & 0xf;
301
302         if (sel == 0x6)
303                 sclk = get_pll_clk(MPLL);
304         else if (sel == 0x7)
305                 sclk = get_pll_clk(EPLL);
306         else if (sel == 0x8)
307                 sclk = get_pll_clk(VPLL);
308         else
309                 return 0;
310
311         /*
312          * CLK_DIV_PERIL0
313          * UART0_RATIO [3:0]
314          * UART1_RATIO [7:4]
315          * UART2_RATIO [8:11]
316          * UART3_RATIO [12:15]
317          * UART4_RATIO [16:19]
318          * UART5_RATIO [23:20]
319          */
320         ratio = readl(&clk->div_peril0);
321         ratio = (ratio >> (dev_index << 2)) & 0xf;
322
323         uclk = sclk / (ratio + 1);
324
325         return uclk;
326 }
327
328 /* exynos5: return uart clock frequency */
329 static unsigned long exynos5_get_uart_clk(int dev_index)
330 {
331         struct exynos5_clock *clk =
332                 (struct exynos5_clock *)samsung_get_base_clock();
333         unsigned long uclk, sclk;
334         unsigned int sel;
335         unsigned int ratio;
336
337         /*
338          * CLK_SRC_PERIC0
339          * UART0_SEL [3:0]
340          * UART1_SEL [7:4]
341          * UART2_SEL [8:11]
342          * UART3_SEL [12:15]
343          * UART4_SEL [16:19]
344          * UART5_SEL [23:20]
345          */
346         sel = readl(&clk->src_peric0);
347         sel = (sel >> (dev_index << 2)) & 0xf;
348
349         if (sel == 0x6)
350                 sclk = get_pll_clk(MPLL);
351         else if (sel == 0x7)
352                 sclk = get_pll_clk(EPLL);
353         else if (sel == 0x8)
354                 sclk = get_pll_clk(VPLL);
355         else
356                 return 0;
357
358         /*
359          * CLK_DIV_PERIC0
360          * UART0_RATIO [3:0]
361          * UART1_RATIO [7:4]
362          * UART2_RATIO [8:11]
363          * UART3_RATIO [12:15]
364          * UART4_RATIO [16:19]
365          * UART5_RATIO [23:20]
366          */
367         ratio = readl(&clk->div_peric0);
368         ratio = (ratio >> (dev_index << 2)) & 0xf;
369
370         uclk = sclk / (ratio + 1);
371
372         return uclk;
373 }
374
375 /* exynos4: set the mmc clock */
376 static void exynos4_set_mmc_clk(int dev_index, unsigned int div)
377 {
378         struct exynos4_clock *clk =
379                 (struct exynos4_clock *)samsung_get_base_clock();
380         unsigned int addr;
381         unsigned int val;
382
383         /*
384          * CLK_DIV_FSYS1
385          * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24]
386          * CLK_DIV_FSYS2
387          * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24]
388          */
389         if (dev_index < 2) {
390                 addr = (unsigned int)&clk->div_fsys1;
391         } else {
392                 addr = (unsigned int)&clk->div_fsys2;
393                 dev_index -= 2;
394         }
395
396         val = readl(addr);
397         val &= ~(0xff << ((dev_index << 4) + 8));
398         val |= (div & 0xff) << ((dev_index << 4) + 8);
399         writel(val, addr);
400 }
401
402 /* exynos5: set the mmc clock */
403 static void exynos5_set_mmc_clk(int dev_index, unsigned int div)
404 {
405         struct exynos5_clock *clk =
406                 (struct exynos5_clock *)samsung_get_base_clock();
407         unsigned int addr;
408         unsigned int val;
409
410         /*
411          * CLK_DIV_FSYS1
412          * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24]
413          * CLK_DIV_FSYS2
414          * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24]
415          */
416         if (dev_index < 2) {
417                 addr = (unsigned int)&clk->div_fsys1;
418         } else {
419                 addr = (unsigned int)&clk->div_fsys2;
420                 dev_index -= 2;
421         }
422
423         val = readl(addr);
424         val &= ~(0xff << ((dev_index << 4) + 8));
425         val |= (div & 0xff) << ((dev_index << 4) + 8);
426         writel(val, addr);
427 }
428
429 /* get_lcd_clk: return lcd clock frequency */
430 static unsigned long exynos4_get_lcd_clk(void)
431 {
432         struct exynos4_clock *clk =
433                 (struct exynos4_clock *)samsung_get_base_clock();
434         unsigned long pclk, sclk;
435         unsigned int sel;
436         unsigned int ratio;
437
438         /*
439          * CLK_SRC_LCD0
440          * FIMD0_SEL [3:0]
441          */
442         sel = readl(&clk->src_lcd0);
443         sel = sel & 0xf;
444
445         /*
446          * 0x6: SCLK_MPLL
447          * 0x7: SCLK_EPLL
448          * 0x8: SCLK_VPLL
449          */
450         if (sel == 0x6)
451                 sclk = get_pll_clk(MPLL);
452         else if (sel == 0x7)
453                 sclk = get_pll_clk(EPLL);
454         else if (sel == 0x8)
455                 sclk = get_pll_clk(VPLL);
456         else
457                 return 0;
458
459         /*
460          * CLK_DIV_LCD0
461          * FIMD0_RATIO [3:0]
462          */
463         ratio = readl(&clk->div_lcd0);
464         ratio = ratio & 0xf;
465
466         pclk = sclk / (ratio + 1);
467
468         return pclk;
469 }
470
471 /* get_lcd_clk: return lcd clock frequency */
472 static unsigned long exynos5_get_lcd_clk(void)
473 {
474         struct exynos5_clock *clk =
475                 (struct exynos5_clock *)samsung_get_base_clock();
476         unsigned long pclk, sclk;
477         unsigned int sel;
478         unsigned int ratio;
479
480         /*
481          * CLK_SRC_LCD0
482          * FIMD0_SEL [3:0]
483          */
484         sel = readl(&clk->src_disp1_0);
485         sel = sel & 0xf;
486
487         /*
488          * 0x6: SCLK_MPLL
489          * 0x7: SCLK_EPLL
490          * 0x8: SCLK_VPLL
491          */
492         if (sel == 0x6)
493                 sclk = get_pll_clk(MPLL);
494         else if (sel == 0x7)
495                 sclk = get_pll_clk(EPLL);
496         else if (sel == 0x8)
497                 sclk = get_pll_clk(VPLL);
498         else
499                 return 0;
500
501         /*
502          * CLK_DIV_LCD0
503          * FIMD0_RATIO [3:0]
504          */
505         ratio = readl(&clk->div_disp1_0);
506         ratio = ratio & 0xf;
507
508         pclk = sclk / (ratio + 1);
509
510         return pclk;
511 }
512
513 void exynos4_set_lcd_clk(void)
514 {
515         struct exynos4_clock *clk =
516             (struct exynos4_clock *)samsung_get_base_clock();
517         unsigned int cfg = 0;
518
519         /*
520          * CLK_GATE_BLOCK
521          * CLK_CAM      [0]
522          * CLK_TV       [1]
523          * CLK_MFC      [2]
524          * CLK_G3D      [3]
525          * CLK_LCD0     [4]
526          * CLK_LCD1     [5]
527          * CLK_GPS      [7]
528          */
529         cfg = readl(&clk->gate_block);
530         cfg |= 1 << 4;
531         writel(cfg, &clk->gate_block);
532
533         /*
534          * CLK_SRC_LCD0
535          * FIMD0_SEL            [3:0]
536          * MDNIE0_SEL           [7:4]
537          * MDNIE_PWM0_SEL       [8:11]
538          * MIPI0_SEL            [12:15]
539          * set lcd0 src clock 0x6: SCLK_MPLL
540          */
541         cfg = readl(&clk->src_lcd0);
542         cfg &= ~(0xf);
543         cfg |= 0x6;
544         writel(cfg, &clk->src_lcd0);
545
546         /*
547          * CLK_GATE_IP_LCD0
548          * CLK_FIMD0            [0]
549          * CLK_MIE0             [1]
550          * CLK_MDNIE0           [2]
551          * CLK_DSIM0            [3]
552          * CLK_SMMUFIMD0        [4]
553          * CLK_PPMULCD0         [5]
554          * Gating all clocks for FIMD0
555          */
556         cfg = readl(&clk->gate_ip_lcd0);
557         cfg |= 1 << 0;
558         writel(cfg, &clk->gate_ip_lcd0);
559
560         /*
561          * CLK_DIV_LCD0
562          * FIMD0_RATIO          [3:0]
563          * MDNIE0_RATIO         [7:4]
564          * MDNIE_PWM0_RATIO     [11:8]
565          * MDNIE_PWM_PRE_RATIO  [15:12]
566          * MIPI0_RATIO          [19:16]
567          * MIPI0_PRE_RATIO      [23:20]
568          * set fimd ratio
569          */
570         cfg &= ~(0xf);
571         cfg |= 0x1;
572         writel(cfg, &clk->div_lcd0);
573 }
574
575 void exynos5_set_lcd_clk(void)
576 {
577         struct exynos5_clock *clk =
578             (struct exynos5_clock *)samsung_get_base_clock();
579         unsigned int cfg = 0;
580
581         /*
582          * CLK_GATE_BLOCK
583          * CLK_CAM      [0]
584          * CLK_TV       [1]
585          * CLK_MFC      [2]
586          * CLK_G3D      [3]
587          * CLK_LCD0     [4]
588          * CLK_LCD1     [5]
589          * CLK_GPS      [7]
590          */
591         cfg = readl(&clk->gate_block);
592         cfg |= 1 << 4;
593         writel(cfg, &clk->gate_block);
594
595         /*
596          * CLK_SRC_LCD0
597          * FIMD0_SEL            [3:0]
598          * MDNIE0_SEL           [7:4]
599          * MDNIE_PWM0_SEL       [8:11]
600          * MIPI0_SEL            [12:15]
601          * set lcd0 src clock 0x6: SCLK_MPLL
602          */
603         cfg = readl(&clk->src_disp1_0);
604         cfg &= ~(0xf);
605         cfg |= 0x8;
606         writel(cfg, &clk->src_disp1_0);
607
608         /*
609          * CLK_GATE_IP_LCD0
610          * CLK_FIMD0            [0]
611          * CLK_MIE0             [1]
612          * CLK_MDNIE0           [2]
613          * CLK_DSIM0            [3]
614          * CLK_SMMUFIMD0        [4]
615          * CLK_PPMULCD0         [5]
616          * Gating all clocks for FIMD0
617          */
618         cfg = readl(&clk->gate_ip_disp1);
619         cfg |= 1 << 0;
620         writel(cfg, &clk->gate_ip_disp1);
621
622         /*
623          * CLK_DIV_LCD0
624          * FIMD0_RATIO          [3:0]
625          * MDNIE0_RATIO         [7:4]
626          * MDNIE_PWM0_RATIO     [11:8]
627          * MDNIE_PWM_PRE_RATIO  [15:12]
628          * MIPI0_RATIO          [19:16]
629          * MIPI0_PRE_RATIO      [23:20]
630          * set fimd ratio
631          */
632         cfg &= ~(0xf);
633         cfg |= 0x0;
634         writel(cfg, &clk->div_disp1_0);
635 }
636
637 void exynos4_set_mipi_clk(void)
638 {
639         struct exynos4_clock *clk =
640             (struct exynos4_clock *)samsung_get_base_clock();
641         unsigned int cfg = 0;
642
643         /*
644          * CLK_SRC_LCD0
645          * FIMD0_SEL            [3:0]
646          * MDNIE0_SEL           [7:4]
647          * MDNIE_PWM0_SEL       [8:11]
648          * MIPI0_SEL            [12:15]
649          * set mipi0 src clock 0x6: SCLK_MPLL
650          */
651         cfg = readl(&clk->src_lcd0);
652         cfg &= ~(0xf << 12);
653         cfg |= (0x6 << 12);
654         writel(cfg, &clk->src_lcd0);
655
656         /*
657          * CLK_SRC_MASK_LCD0
658          * FIMD0_MASK           [0]
659          * MDNIE0_MASK          [4]
660          * MDNIE_PWM0_MASK      [8]
661          * MIPI0_MASK           [12]
662          * set src mask mipi0 0x1: Unmask
663          */
664         cfg = readl(&clk->src_mask_lcd0);
665         cfg |= (0x1 << 12);
666         writel(cfg, &clk->src_mask_lcd0);
667
668         /*
669          * CLK_GATE_IP_LCD0
670          * CLK_FIMD0            [0]
671          * CLK_MIE0             [1]
672          * CLK_MDNIE0           [2]
673          * CLK_DSIM0            [3]
674          * CLK_SMMUFIMD0        [4]
675          * CLK_PPMULCD0         [5]
676          * Gating all clocks for MIPI0
677          */
678         cfg = readl(&clk->gate_ip_lcd0);
679         cfg |= 1 << 3;
680         writel(cfg, &clk->gate_ip_lcd0);
681
682         /*
683          * CLK_DIV_LCD0
684          * FIMD0_RATIO          [3:0]
685          * MDNIE0_RATIO         [7:4]
686          * MDNIE_PWM0_RATIO     [11:8]
687          * MDNIE_PWM_PRE_RATIO  [15:12]
688          * MIPI0_RATIO          [19:16]
689          * MIPI0_PRE_RATIO      [23:20]
690          * set mipi ratio
691          */
692         cfg &= ~(0xf << 16);
693         cfg |= (0x1 << 16);
694         writel(cfg, &clk->div_lcd0);
695 }
696
697 /*
698  * I2C
699  *
700  * exynos5: obtaining the I2C clock
701  */
702 static unsigned long exynos5_get_i2c_clk(void)
703 {
704         struct exynos5_clock *clk =
705                 (struct exynos5_clock *)samsung_get_base_clock();
706         unsigned long aclk_66, aclk_66_pre, sclk;
707         unsigned int ratio;
708
709         sclk = get_pll_clk(MPLL);
710
711         ratio = (readl(&clk->div_top1)) >> 24;
712         ratio &= 0x7;
713         aclk_66_pre = sclk / (ratio + 1);
714         ratio = readl(&clk->div_top0);
715         ratio &= 0x7;
716         aclk_66 = aclk_66_pre / (ratio + 1);
717         return aclk_66;
718 }
719
720 int exynos5_set_epll_clk(unsigned long rate)
721 {
722         unsigned int epll_con, epll_con_k;
723         unsigned int i;
724         unsigned int lockcnt;
725         unsigned int start;
726         struct exynos5_clock *clk =
727                 (struct exynos5_clock *)samsung_get_base_clock();
728
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);
735
736         for (i = 0; i < ARRAY_SIZE(exynos5_epll_div); i++) {
737                 if (exynos5_epll_div[i].freq_out == rate)
738                         break;
739         }
740
741         if (i == ARRAY_SIZE(exynos5_epll_div))
742                 return -1;
743
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;
750
751         /*
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)
755          */
756         lockcnt = 3000 * exynos5_epll_div[i].p_div;
757
758         writel(lockcnt, &clk->epll_lock);
759         writel(epll_con, &clk->epll_con0);
760         writel(epll_con_k, &clk->epll_con1);
761
762         start = get_timer(0);
763
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__);
768                         return -1;
769                 }
770         }
771         return 0;
772 }
773
774 void exynos5_set_i2s_clk_source(void)
775 {
776         struct exynos5_clock *clk =
777                 (struct exynos5_clock *)samsung_get_base_clock();
778
779         clrsetbits_le32(&clk->src_peric1, AUDIO1_SEL_MASK,
780                         (CLK_SRC_SCLK_EPLL));
781 }
782
783 int exynos5_set_i2s_clk_prescaler(unsigned int src_frq,
784                                         unsigned int dst_frq)
785 {
786         struct exynos5_clock *clk =
787                 (struct exynos5_clock *)samsung_get_base_clock();
788         unsigned int div;
789
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);
793                 return -1;
794         }
795
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);
800                 return -1;
801         }
802         clrsetbits_le32(&clk->div_peric4, AUDIO_1_RATIO_MASK,
803                                 (div & AUDIO_1_RATIO_MASK));
804         return 0;
805 }
806
807 unsigned long get_pll_clk(int pllreg)
808 {
809         if (cpu_is_exynos5())
810                 return exynos5_get_pll_clk(pllreg);
811         else
812                 return exynos4_get_pll_clk(pllreg);
813 }
814
815 unsigned long get_arm_clk(void)
816 {
817         if (cpu_is_exynos5())
818                 return exynos5_get_arm_clk();
819         else
820                 return exynos4_get_arm_clk();
821 }
822
823 unsigned long get_i2c_clk(void)
824 {
825         if (cpu_is_exynos5()) {
826                 return exynos5_get_i2c_clk();
827         } else {
828                 debug("I2C clock is not set for this CPU\n");
829                 return 0;
830         }
831 }
832
833 unsigned long get_pwm_clk(void)
834 {
835         if (cpu_is_exynos5())
836                 return exynos5_get_pwm_clk();
837         else
838                 return exynos4_get_pwm_clk();
839 }
840
841 unsigned long get_uart_clk(int dev_index)
842 {
843         if (cpu_is_exynos5())
844                 return exynos5_get_uart_clk(dev_index);
845         else
846                 return exynos4_get_uart_clk(dev_index);
847 }
848
849 void set_mmc_clk(int dev_index, unsigned int div)
850 {
851         if (cpu_is_exynos5())
852                 exynos5_set_mmc_clk(dev_index, div);
853         else
854                 exynos4_set_mmc_clk(dev_index, div);
855 }
856
857 unsigned long get_lcd_clk(void)
858 {
859         if (cpu_is_exynos4())
860                 return exynos4_get_lcd_clk();
861         else
862                 return exynos5_get_lcd_clk();
863 }
864
865 void set_lcd_clk(void)
866 {
867         if (cpu_is_exynos4())
868                 exynos4_set_lcd_clk();
869         else
870                 exynos5_set_lcd_clk();
871 }
872
873 void set_mipi_clk(void)
874 {
875         if (cpu_is_exynos4())
876                 exynos4_set_mipi_clk();
877 }
878
879 int set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq)
880 {
881
882         if (cpu_is_exynos5())
883                 return exynos5_set_i2s_clk_prescaler(src_frq, dst_frq);
884         else
885                 return 0;
886 }
887
888 void set_i2s_clk_source(void)
889 {
890         if (cpu_is_exynos5())
891                 exynos5_set_i2s_clk_source();
892 }
893
894 int set_epll_clk(unsigned long rate)
895 {
896         if (cpu_is_exynos5())
897                 return exynos5_set_epll_clk(rate);
898         else
899                 return 0;
900 }