]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/armv7/exynos/clock.c
Merge branch 'master' of git://git.denx.de/u-boot-video
[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  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 #include <common.h>
9 #include <asm/io.h>
10 #include <asm/arch/clock.h>
11 #include <asm/arch/clk.h>
12 #include <asm/arch/periph.h>
13
14 #define PLL_DIV_1024    1024
15 #define PLL_DIV_65535   65535
16 #define PLL_DIV_65536   65536
17
18 /* *
19  * This structure is to store the src bit, div bit and prediv bit
20  * positions of the peripheral clocks of the src and div registers
21  */
22 struct clk_bit_info {
23         int8_t src_bit;
24         int8_t div_bit;
25         int8_t prediv_bit;
26 };
27
28 /* src_bit div_bit prediv_bit */
29 static struct clk_bit_info clk_bit_info[PERIPH_ID_COUNT] = {
30         {0,     0,      -1},
31         {4,     4,      -1},
32         {8,     8,      -1},
33         {12,    12,     -1},
34         {0,     0,      8},
35         {4,     16,     24},
36         {8,     0,      8},
37         {12,    16,     24},
38         {-1,    -1,     -1},
39         {16,    0,      8},
40         {20,    16,     24},
41         {24,    0,      8},
42         {0,     0,      4},
43         {4,     12,     16},
44         {-1,    -1,     -1},
45         {-1,    -1,     -1},
46         {-1,    24,     0},
47         {-1,    24,     0},
48         {-1,    24,     0},
49         {-1,    24,     0},
50         {-1,    24,     0},
51         {-1,    24,     0},
52         {-1,    24,     0},
53         {-1,    24,     0},
54         {24,    0,      -1},
55         {24,    0,      -1},
56         {24,    0,      -1},
57         {24,    0,      -1},
58         {24,    0,      -1},
59 };
60
61 /* Epll Clock division values to achive different frequency output */
62 static struct set_epll_con_val exynos5_epll_div[] = {
63         { 192000000, 0, 48, 3, 1, 0 },
64         { 180000000, 0, 45, 3, 1, 0 },
65         {  73728000, 1, 73, 3, 3, 47710 },
66         {  67737600, 1, 90, 4, 3, 20762 },
67         {  49152000, 0, 49, 3, 3, 9961 },
68         {  45158400, 0, 45, 3, 3, 10381 },
69         { 180633600, 0, 45, 3, 1, 10381 }
70 };
71
72 /* exynos: return pll clock frequency */
73 static int exynos_get_pll_clk(int pllreg, unsigned int r, unsigned int k)
74 {
75         unsigned long m, p, s = 0, mask, fout;
76         unsigned int div;
77         unsigned int freq;
78         /*
79          * APLL_CON: MIDV [25:16]
80          * MPLL_CON: MIDV [25:16]
81          * EPLL_CON: MIDV [24:16]
82          * VPLL_CON: MIDV [24:16]
83          * BPLL_CON: MIDV [25:16]: Exynos5
84          */
85         if (pllreg == APLL || pllreg == MPLL || pllreg == BPLL)
86                 mask = 0x3ff;
87         else
88                 mask = 0x1ff;
89
90         m = (r >> 16) & mask;
91
92         /* PDIV [13:8] */
93         p = (r >> 8) & 0x3f;
94         /* SDIV [2:0] */
95         s = r & 0x7;
96
97         freq = CONFIG_SYS_CLK_FREQ;
98
99         if (pllreg == EPLL) {
100                 k = k & 0xffff;
101                 /* FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV) */
102                 fout = (m + k / PLL_DIV_65536) * (freq / (p * (1 << s)));
103         } else if (pllreg == VPLL) {
104                 k = k & 0xfff;
105
106                 /*
107                  * Exynos4210
108                  * FOUT = (MDIV + K / 1024) * FIN / (PDIV * 2^SDIV)
109                  *
110                  * Exynos4412
111                  * FOUT = (MDIV + K / 65535) * FIN / (PDIV * 2^SDIV)
112                  *
113                  * Exynos5250
114                  * FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV)
115                  */
116                 if (proid_is_exynos4210())
117                         div = PLL_DIV_1024;
118                 else if (proid_is_exynos4412())
119                         div = PLL_DIV_65535;
120                 else if (proid_is_exynos5250())
121                         div = PLL_DIV_65536;
122                 else
123                         return 0;
124
125                 fout = (m + k / div) * (freq / (p * (1 << s)));
126         } else {
127                 /*
128                  * Exynos4412 / Exynos5250
129                  * FOUT = MDIV * FIN / (PDIV * 2^SDIV)
130                  *
131                  * Exynos4210
132                  * FOUT = MDIV * FIN / (PDIV * 2^(SDIV-1))
133                  */
134                 if (proid_is_exynos4210())
135                         fout = m * (freq / (p * (1 << (s - 1))));
136                 else
137                         fout = m * (freq / (p * (1 << s)));
138         }
139         return fout;
140 }
141
142 /* exynos4: return pll clock frequency */
143 static unsigned long exynos4_get_pll_clk(int pllreg)
144 {
145         struct exynos4_clock *clk =
146                 (struct exynos4_clock *)samsung_get_base_clock();
147         unsigned long r, k = 0;
148
149         switch (pllreg) {
150         case APLL:
151                 r = readl(&clk->apll_con0);
152                 break;
153         case MPLL:
154                 r = readl(&clk->mpll_con0);
155                 break;
156         case EPLL:
157                 r = readl(&clk->epll_con0);
158                 k = readl(&clk->epll_con1);
159                 break;
160         case VPLL:
161                 r = readl(&clk->vpll_con0);
162                 k = readl(&clk->vpll_con1);
163                 break;
164         default:
165                 printf("Unsupported PLL (%d)\n", pllreg);
166                 return 0;
167         }
168
169         return exynos_get_pll_clk(pllreg, r, k);
170 }
171
172 /* exynos4x12: return pll clock frequency */
173 static unsigned long exynos4x12_get_pll_clk(int pllreg)
174 {
175         struct exynos4x12_clock *clk =
176                 (struct exynos4x12_clock *)samsung_get_base_clock();
177         unsigned long r, k = 0;
178
179         switch (pllreg) {
180         case APLL:
181                 r = readl(&clk->apll_con0);
182                 break;
183         case MPLL:
184                 r = readl(&clk->mpll_con0);
185                 break;
186         case EPLL:
187                 r = readl(&clk->epll_con0);
188                 k = readl(&clk->epll_con1);
189                 break;
190         case VPLL:
191                 r = readl(&clk->vpll_con0);
192                 k = readl(&clk->vpll_con1);
193                 break;
194         default:
195                 printf("Unsupported PLL (%d)\n", pllreg);
196                 return 0;
197         }
198
199         return exynos_get_pll_clk(pllreg, r, k);
200 }
201
202 /* exynos5: return pll clock frequency */
203 static unsigned long exynos5_get_pll_clk(int pllreg)
204 {
205         struct exynos5_clock *clk =
206                 (struct exynos5_clock *)samsung_get_base_clock();
207         unsigned long r, k = 0, fout;
208         unsigned int pll_div2_sel, fout_sel;
209
210         switch (pllreg) {
211         case APLL:
212                 r = readl(&clk->apll_con0);
213                 break;
214         case MPLL:
215                 r = readl(&clk->mpll_con0);
216                 break;
217         case EPLL:
218                 r = readl(&clk->epll_con0);
219                 k = readl(&clk->epll_con1);
220                 break;
221         case VPLL:
222                 r = readl(&clk->vpll_con0);
223                 k = readl(&clk->vpll_con1);
224                 break;
225         case BPLL:
226                 r = readl(&clk->bpll_con0);
227                 break;
228         default:
229                 printf("Unsupported PLL (%d)\n", pllreg);
230                 return 0;
231         }
232
233         fout = exynos_get_pll_clk(pllreg, r, k);
234
235         /* According to the user manual, in EVT1 MPLL and BPLL always gives
236          * 1.6GHz clock, so divide by 2 to get 800MHz MPLL clock.*/
237         if (pllreg == MPLL || pllreg == BPLL) {
238                 pll_div2_sel = readl(&clk->pll_div2_sel);
239
240                 switch (pllreg) {
241                 case MPLL:
242                         fout_sel = (pll_div2_sel >> MPLL_FOUT_SEL_SHIFT)
243                                         & MPLL_FOUT_SEL_MASK;
244                         break;
245                 case BPLL:
246                         fout_sel = (pll_div2_sel >> BPLL_FOUT_SEL_SHIFT)
247                                         & BPLL_FOUT_SEL_MASK;
248                         break;
249                 default:
250                         fout_sel = -1;
251                         break;
252                 }
253
254                 if (fout_sel == 0)
255                         fout /= 2;
256         }
257
258         return fout;
259 }
260
261 static unsigned long exynos5_get_periph_rate(int peripheral)
262 {
263         struct clk_bit_info *bit_info = &clk_bit_info[peripheral];
264         unsigned long sclk, sub_clk;
265         unsigned int src, div, sub_div;
266         struct exynos5_clock *clk =
267                         (struct exynos5_clock *)samsung_get_base_clock();
268
269         switch (peripheral) {
270         case PERIPH_ID_UART0:
271         case PERIPH_ID_UART1:
272         case PERIPH_ID_UART2:
273         case PERIPH_ID_UART3:
274                 src = readl(&clk->src_peric0);
275                 div = readl(&clk->div_peric0);
276                 break;
277         case PERIPH_ID_PWM0:
278         case PERIPH_ID_PWM1:
279         case PERIPH_ID_PWM2:
280         case PERIPH_ID_PWM3:
281         case PERIPH_ID_PWM4:
282                 src = readl(&clk->src_peric0);
283                 div = readl(&clk->div_peric3);
284                 break;
285         case PERIPH_ID_I2S0:
286                 src = readl(&clk->src_mau);
287                 div = readl(&clk->div_mau);
288         case PERIPH_ID_SPI0:
289         case PERIPH_ID_SPI1:
290                 src = readl(&clk->src_peric1);
291                 div = readl(&clk->div_peric1);
292                 break;
293         case PERIPH_ID_SPI2:
294                 src = readl(&clk->src_peric1);
295                 div = readl(&clk->div_peric2);
296                 break;
297         case PERIPH_ID_SPI3:
298         case PERIPH_ID_SPI4:
299                 src = readl(&clk->sclk_src_isp);
300                 div = readl(&clk->sclk_div_isp);
301                 break;
302         case PERIPH_ID_SDMMC0:
303         case PERIPH_ID_SDMMC1:
304         case PERIPH_ID_SDMMC2:
305         case PERIPH_ID_SDMMC3:
306                 src = readl(&clk->src_fsys);
307                 div = readl(&clk->div_fsys1);
308                 break;
309         case PERIPH_ID_I2C0:
310         case PERIPH_ID_I2C1:
311         case PERIPH_ID_I2C2:
312         case PERIPH_ID_I2C3:
313         case PERIPH_ID_I2C4:
314         case PERIPH_ID_I2C5:
315         case PERIPH_ID_I2C6:
316         case PERIPH_ID_I2C7:
317                 sclk = exynos5_get_pll_clk(MPLL);
318                 sub_div = ((readl(&clk->div_top1) >> bit_info->div_bit)
319                                                                 & 0x7) + 1;
320                 div = ((readl(&clk->div_top0) >> bit_info->prediv_bit)
321                                                                 & 0x7) + 1;
322                 return (sclk / sub_div) / div;
323         default:
324                 debug("%s: invalid peripheral %d", __func__, peripheral);
325                 return -1;
326         };
327
328         src = (src >> bit_info->src_bit) & 0xf;
329
330         switch (src) {
331         case EXYNOS_SRC_MPLL:
332                 sclk = exynos5_get_pll_clk(MPLL);
333                 break;
334         case EXYNOS_SRC_EPLL:
335                 sclk = exynos5_get_pll_clk(EPLL);
336                 break;
337         case EXYNOS_SRC_VPLL:
338                 sclk = exynos5_get_pll_clk(VPLL);
339                 break;
340         default:
341                 return 0;
342         }
343
344         /* Ratio clock division for this peripheral */
345         sub_div = (div >> bit_info->div_bit) & 0xf;
346         sub_clk = sclk / (sub_div + 1);
347
348         /* Pre-ratio clock division for SDMMC0 and 2 */
349         if (peripheral == PERIPH_ID_SDMMC0 || peripheral == PERIPH_ID_SDMMC2) {
350                 div = (div >> bit_info->prediv_bit) & 0xff;
351                 return sub_clk / (div + 1);
352         }
353
354         return sub_clk;
355 }
356
357 unsigned long clock_get_periph_rate(int peripheral)
358 {
359         if (cpu_is_exynos5())
360                 return exynos5_get_periph_rate(peripheral);
361         else
362                 return 0;
363 }
364
365 /* exynos4: return ARM clock frequency */
366 static unsigned long exynos4_get_arm_clk(void)
367 {
368         struct exynos4_clock *clk =
369                 (struct exynos4_clock *)samsung_get_base_clock();
370         unsigned long div;
371         unsigned long armclk;
372         unsigned int core_ratio;
373         unsigned int core2_ratio;
374
375         div = readl(&clk->div_cpu0);
376
377         /* CORE_RATIO: [2:0], CORE2_RATIO: [30:28] */
378         core_ratio = (div >> 0) & 0x7;
379         core2_ratio = (div >> 28) & 0x7;
380
381         armclk = get_pll_clk(APLL) / (core_ratio + 1);
382         armclk /= (core2_ratio + 1);
383
384         return armclk;
385 }
386
387 /* exynos4x12: return ARM clock frequency */
388 static unsigned long exynos4x12_get_arm_clk(void)
389 {
390         struct exynos4x12_clock *clk =
391                 (struct exynos4x12_clock *)samsung_get_base_clock();
392         unsigned long div;
393         unsigned long armclk;
394         unsigned int core_ratio;
395         unsigned int core2_ratio;
396
397         div = readl(&clk->div_cpu0);
398
399         /* CORE_RATIO: [2:0], CORE2_RATIO: [30:28] */
400         core_ratio = (div >> 0) & 0x7;
401         core2_ratio = (div >> 28) & 0x7;
402
403         armclk = get_pll_clk(APLL) / (core_ratio + 1);
404         armclk /= (core2_ratio + 1);
405
406         return armclk;
407 }
408
409 /* exynos5: return ARM clock frequency */
410 static unsigned long exynos5_get_arm_clk(void)
411 {
412         struct exynos5_clock *clk =
413                 (struct exynos5_clock *)samsung_get_base_clock();
414         unsigned long div;
415         unsigned long armclk;
416         unsigned int arm_ratio;
417         unsigned int arm2_ratio;
418
419         div = readl(&clk->div_cpu0);
420
421         /* ARM_RATIO: [2:0], ARM2_RATIO: [30:28] */
422         arm_ratio = (div >> 0) & 0x7;
423         arm2_ratio = (div >> 28) & 0x7;
424
425         armclk = get_pll_clk(APLL) / (arm_ratio + 1);
426         armclk /= (arm2_ratio + 1);
427
428         return armclk;
429 }
430
431 /* exynos4: return pwm clock frequency */
432 static unsigned long exynos4_get_pwm_clk(void)
433 {
434         struct exynos4_clock *clk =
435                 (struct exynos4_clock *)samsung_get_base_clock();
436         unsigned long pclk, sclk;
437         unsigned int sel;
438         unsigned int ratio;
439
440         if (s5p_get_cpu_rev() == 0) {
441                 /*
442                  * CLK_SRC_PERIL0
443                  * PWM_SEL [27:24]
444                  */
445                 sel = readl(&clk->src_peril0);
446                 sel = (sel >> 24) & 0xf;
447
448                 if (sel == 0x6)
449                         sclk = get_pll_clk(MPLL);
450                 else if (sel == 0x7)
451                         sclk = get_pll_clk(EPLL);
452                 else if (sel == 0x8)
453                         sclk = get_pll_clk(VPLL);
454                 else
455                         return 0;
456
457                 /*
458                  * CLK_DIV_PERIL3
459                  * PWM_RATIO [3:0]
460                  */
461                 ratio = readl(&clk->div_peril3);
462                 ratio = ratio & 0xf;
463         } else if (s5p_get_cpu_rev() == 1) {
464                 sclk = get_pll_clk(MPLL);
465                 ratio = 8;
466         } else
467                 return 0;
468
469         pclk = sclk / (ratio + 1);
470
471         return pclk;
472 }
473
474 /* exynos4x12: return pwm clock frequency */
475 static unsigned long exynos4x12_get_pwm_clk(void)
476 {
477         unsigned long pclk, sclk;
478         unsigned int ratio;
479
480         sclk = get_pll_clk(MPLL);
481         ratio = 8;
482
483         pclk = sclk / (ratio + 1);
484
485         return pclk;
486 }
487
488 /* exynos4: return uart clock frequency */
489 static unsigned long exynos4_get_uart_clk(int dev_index)
490 {
491         struct exynos4_clock *clk =
492                 (struct exynos4_clock *)samsung_get_base_clock();
493         unsigned long uclk, sclk;
494         unsigned int sel;
495         unsigned int ratio;
496
497         /*
498          * CLK_SRC_PERIL0
499          * UART0_SEL [3:0]
500          * UART1_SEL [7:4]
501          * UART2_SEL [8:11]
502          * UART3_SEL [12:15]
503          * UART4_SEL [16:19]
504          * UART5_SEL [23:20]
505          */
506         sel = readl(&clk->src_peril0);
507         sel = (sel >> (dev_index << 2)) & 0xf;
508
509         if (sel == 0x6)
510                 sclk = get_pll_clk(MPLL);
511         else if (sel == 0x7)
512                 sclk = get_pll_clk(EPLL);
513         else if (sel == 0x8)
514                 sclk = get_pll_clk(VPLL);
515         else
516                 return 0;
517
518         /*
519          * CLK_DIV_PERIL0
520          * UART0_RATIO [3:0]
521          * UART1_RATIO [7:4]
522          * UART2_RATIO [8:11]
523          * UART3_RATIO [12:15]
524          * UART4_RATIO [16:19]
525          * UART5_RATIO [23:20]
526          */
527         ratio = readl(&clk->div_peril0);
528         ratio = (ratio >> (dev_index << 2)) & 0xf;
529
530         uclk = sclk / (ratio + 1);
531
532         return uclk;
533 }
534
535 /* exynos4x12: return uart clock frequency */
536 static unsigned long exynos4x12_get_uart_clk(int dev_index)
537 {
538         struct exynos4x12_clock *clk =
539                 (struct exynos4x12_clock *)samsung_get_base_clock();
540         unsigned long uclk, sclk;
541         unsigned int sel;
542         unsigned int ratio;
543
544         /*
545          * CLK_SRC_PERIL0
546          * UART0_SEL [3:0]
547          * UART1_SEL [7:4]
548          * UART2_SEL [8:11]
549          * UART3_SEL [12:15]
550          * UART4_SEL [16:19]
551          */
552         sel = readl(&clk->src_peril0);
553         sel = (sel >> (dev_index << 2)) & 0xf;
554
555         if (sel == 0x6)
556                 sclk = get_pll_clk(MPLL);
557         else if (sel == 0x7)
558                 sclk = get_pll_clk(EPLL);
559         else if (sel == 0x8)
560                 sclk = get_pll_clk(VPLL);
561         else
562                 return 0;
563
564         /*
565          * CLK_DIV_PERIL0
566          * UART0_RATIO [3:0]
567          * UART1_RATIO [7:4]
568          * UART2_RATIO [8:11]
569          * UART3_RATIO [12:15]
570          * UART4_RATIO [16:19]
571          */
572         ratio = readl(&clk->div_peril0);
573         ratio = (ratio >> (dev_index << 2)) & 0xf;
574
575         uclk = sclk / (ratio + 1);
576
577         return uclk;
578 }
579
580 /* exynos5: return uart clock frequency */
581 static unsigned long exynos5_get_uart_clk(int dev_index)
582 {
583         struct exynos5_clock *clk =
584                 (struct exynos5_clock *)samsung_get_base_clock();
585         unsigned long uclk, sclk;
586         unsigned int sel;
587         unsigned int ratio;
588
589         /*
590          * CLK_SRC_PERIC0
591          * UART0_SEL [3:0]
592          * UART1_SEL [7:4]
593          * UART2_SEL [8:11]
594          * UART3_SEL [12:15]
595          * UART4_SEL [16:19]
596          * UART5_SEL [23:20]
597          */
598         sel = readl(&clk->src_peric0);
599         sel = (sel >> (dev_index << 2)) & 0xf;
600
601         if (sel == 0x6)
602                 sclk = get_pll_clk(MPLL);
603         else if (sel == 0x7)
604                 sclk = get_pll_clk(EPLL);
605         else if (sel == 0x8)
606                 sclk = get_pll_clk(VPLL);
607         else
608                 return 0;
609
610         /*
611          * CLK_DIV_PERIC0
612          * UART0_RATIO [3:0]
613          * UART1_RATIO [7:4]
614          * UART2_RATIO [8:11]
615          * UART3_RATIO [12:15]
616          * UART4_RATIO [16:19]
617          * UART5_RATIO [23:20]
618          */
619         ratio = readl(&clk->div_peric0);
620         ratio = (ratio >> (dev_index << 2)) & 0xf;
621
622         uclk = sclk / (ratio + 1);
623
624         return uclk;
625 }
626
627 static unsigned long exynos4_get_mmc_clk(int dev_index)
628 {
629         struct exynos4_clock *clk =
630                 (struct exynos4_clock *)samsung_get_base_clock();
631         unsigned long uclk, sclk;
632         unsigned int sel, ratio, pre_ratio;
633         int shift = 0;
634
635         sel = readl(&clk->src_fsys);
636         sel = (sel >> (dev_index << 2)) & 0xf;
637
638         if (sel == 0x6)
639                 sclk = get_pll_clk(MPLL);
640         else if (sel == 0x7)
641                 sclk = get_pll_clk(EPLL);
642         else if (sel == 0x8)
643                 sclk = get_pll_clk(VPLL);
644         else
645                 return 0;
646
647         switch (dev_index) {
648         case 0:
649         case 1:
650                 ratio = readl(&clk->div_fsys1);
651                 pre_ratio = readl(&clk->div_fsys1);
652                 break;
653         case 2:
654         case 3:
655                 ratio = readl(&clk->div_fsys2);
656                 pre_ratio = readl(&clk->div_fsys2);
657                 break;
658         case 4:
659                 ratio = readl(&clk->div_fsys3);
660                 pre_ratio = readl(&clk->div_fsys3);
661                 break;
662         default:
663                 return 0;
664         }
665
666         if (dev_index == 1 || dev_index == 3)
667                 shift = 16;
668
669         ratio = (ratio >> shift) & 0xf;
670         pre_ratio = (pre_ratio >> (shift + 8)) & 0xff;
671         uclk = (sclk / (ratio + 1)) / (pre_ratio + 1);
672
673         return uclk;
674 }
675
676 static unsigned long exynos5_get_mmc_clk(int dev_index)
677 {
678         struct exynos5_clock *clk =
679                 (struct exynos5_clock *)samsung_get_base_clock();
680         unsigned long uclk, sclk;
681         unsigned int sel, ratio, pre_ratio;
682         int shift = 0;
683
684         sel = readl(&clk->src_fsys);
685         sel = (sel >> (dev_index << 2)) & 0xf;
686
687         if (sel == 0x6)
688                 sclk = get_pll_clk(MPLL);
689         else if (sel == 0x7)
690                 sclk = get_pll_clk(EPLL);
691         else if (sel == 0x8)
692                 sclk = get_pll_clk(VPLL);
693         else
694                 return 0;
695
696         switch (dev_index) {
697         case 0:
698         case 1:
699                 ratio = readl(&clk->div_fsys1);
700                 pre_ratio = readl(&clk->div_fsys1);
701                 break;
702         case 2:
703         case 3:
704                 ratio = readl(&clk->div_fsys2);
705                 pre_ratio = readl(&clk->div_fsys2);
706                 break;
707         default:
708                 return 0;
709         }
710
711         if (dev_index == 1 || dev_index == 3)
712                 shift = 16;
713
714         ratio = (ratio >> shift) & 0xf;
715         pre_ratio = (pre_ratio >> (shift + 8)) & 0xff;
716         uclk = (sclk / (ratio + 1)) / (pre_ratio + 1);
717
718         return uclk;
719 }
720
721 /* exynos4: set the mmc clock */
722 static void exynos4_set_mmc_clk(int dev_index, unsigned int div)
723 {
724         struct exynos4_clock *clk =
725                 (struct exynos4_clock *)samsung_get_base_clock();
726         unsigned int addr;
727         unsigned int val;
728
729         /*
730          * CLK_DIV_FSYS1
731          * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24]
732          * CLK_DIV_FSYS2
733          * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24]
734          * CLK_DIV_FSYS3
735          * MMC4_PRE_RATIO [15:8]
736          */
737         if (dev_index < 2) {
738                 addr = (unsigned int)&clk->div_fsys1;
739         }  else if (dev_index == 4) {
740                 addr = (unsigned int)&clk->div_fsys3;
741                 dev_index -= 4;
742         } else {
743                 addr = (unsigned int)&clk->div_fsys2;
744                 dev_index -= 2;
745         }
746
747         val = readl(addr);
748         val &= ~(0xff << ((dev_index << 4) + 8));
749         val |= (div & 0xff) << ((dev_index << 4) + 8);
750         writel(val, addr);
751 }
752
753 /* exynos4x12: set the mmc clock */
754 static void exynos4x12_set_mmc_clk(int dev_index, unsigned int div)
755 {
756         struct exynos4x12_clock *clk =
757                 (struct exynos4x12_clock *)samsung_get_base_clock();
758         unsigned int addr;
759         unsigned int val;
760
761         /*
762          * CLK_DIV_FSYS1
763          * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24]
764          * CLK_DIV_FSYS2
765          * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24]
766          */
767         if (dev_index < 2) {
768                 addr = (unsigned int)&clk->div_fsys1;
769         } else {
770                 addr = (unsigned int)&clk->div_fsys2;
771                 dev_index -= 2;
772         }
773
774         val = readl(addr);
775         val &= ~(0xff << ((dev_index << 4) + 8));
776         val |= (div & 0xff) << ((dev_index << 4) + 8);
777         writel(val, addr);
778 }
779
780 /* exynos5: set the mmc clock */
781 static void exynos5_set_mmc_clk(int dev_index, unsigned int div)
782 {
783         struct exynos5_clock *clk =
784                 (struct exynos5_clock *)samsung_get_base_clock();
785         unsigned int addr;
786         unsigned int val;
787
788         /*
789          * CLK_DIV_FSYS1
790          * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24]
791          * CLK_DIV_FSYS2
792          * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24]
793          */
794         if (dev_index < 2) {
795                 addr = (unsigned int)&clk->div_fsys1;
796         } else {
797                 addr = (unsigned int)&clk->div_fsys2;
798                 dev_index -= 2;
799         }
800
801         val = readl(addr);
802         val &= ~(0xff << ((dev_index << 4) + 8));
803         val |= (div & 0xff) << ((dev_index << 4) + 8);
804         writel(val, addr);
805 }
806
807 /* get_lcd_clk: return lcd clock frequency */
808 static unsigned long exynos4_get_lcd_clk(void)
809 {
810         struct exynos4_clock *clk =
811                 (struct exynos4_clock *)samsung_get_base_clock();
812         unsigned long pclk, sclk;
813         unsigned int sel;
814         unsigned int ratio;
815
816         /*
817          * CLK_SRC_LCD0
818          * FIMD0_SEL [3:0]
819          */
820         sel = readl(&clk->src_lcd0);
821         sel = sel & 0xf;
822
823         /*
824          * 0x6: SCLK_MPLL
825          * 0x7: SCLK_EPLL
826          * 0x8: SCLK_VPLL
827          */
828         if (sel == 0x6)
829                 sclk = get_pll_clk(MPLL);
830         else if (sel == 0x7)
831                 sclk = get_pll_clk(EPLL);
832         else if (sel == 0x8)
833                 sclk = get_pll_clk(VPLL);
834         else
835                 return 0;
836
837         /*
838          * CLK_DIV_LCD0
839          * FIMD0_RATIO [3:0]
840          */
841         ratio = readl(&clk->div_lcd0);
842         ratio = ratio & 0xf;
843
844         pclk = sclk / (ratio + 1);
845
846         return pclk;
847 }
848
849 /* get_lcd_clk: return lcd clock frequency */
850 static unsigned long exynos5_get_lcd_clk(void)
851 {
852         struct exynos5_clock *clk =
853                 (struct exynos5_clock *)samsung_get_base_clock();
854         unsigned long pclk, sclk;
855         unsigned int sel;
856         unsigned int ratio;
857
858         /*
859          * CLK_SRC_LCD0
860          * FIMD0_SEL [3:0]
861          */
862         sel = readl(&clk->src_disp1_0);
863         sel = sel & 0xf;
864
865         /*
866          * 0x6: SCLK_MPLL
867          * 0x7: SCLK_EPLL
868          * 0x8: SCLK_VPLL
869          */
870         if (sel == 0x6)
871                 sclk = get_pll_clk(MPLL);
872         else if (sel == 0x7)
873                 sclk = get_pll_clk(EPLL);
874         else if (sel == 0x8)
875                 sclk = get_pll_clk(VPLL);
876         else
877                 return 0;
878
879         /*
880          * CLK_DIV_LCD0
881          * FIMD0_RATIO [3:0]
882          */
883         ratio = readl(&clk->div_disp1_0);
884         ratio = ratio & 0xf;
885
886         pclk = sclk / (ratio + 1);
887
888         return pclk;
889 }
890
891 void exynos4_set_lcd_clk(void)
892 {
893         struct exynos4_clock *clk =
894             (struct exynos4_clock *)samsung_get_base_clock();
895         unsigned int cfg = 0;
896
897         /*
898          * CLK_GATE_BLOCK
899          * CLK_CAM      [0]
900          * CLK_TV       [1]
901          * CLK_MFC      [2]
902          * CLK_G3D      [3]
903          * CLK_LCD0     [4]
904          * CLK_LCD1     [5]
905          * CLK_GPS      [7]
906          */
907         cfg = readl(&clk->gate_block);
908         cfg |= 1 << 4;
909         writel(cfg, &clk->gate_block);
910
911         /*
912          * CLK_SRC_LCD0
913          * FIMD0_SEL            [3:0]
914          * MDNIE0_SEL           [7:4]
915          * MDNIE_PWM0_SEL       [8:11]
916          * MIPI0_SEL            [12:15]
917          * set lcd0 src clock 0x6: SCLK_MPLL
918          */
919         cfg = readl(&clk->src_lcd0);
920         cfg &= ~(0xf);
921         cfg |= 0x6;
922         writel(cfg, &clk->src_lcd0);
923
924         /*
925          * CLK_GATE_IP_LCD0
926          * CLK_FIMD0            [0]
927          * CLK_MIE0             [1]
928          * CLK_MDNIE0           [2]
929          * CLK_DSIM0            [3]
930          * CLK_SMMUFIMD0        [4]
931          * CLK_PPMULCD0         [5]
932          * Gating all clocks for FIMD0
933          */
934         cfg = readl(&clk->gate_ip_lcd0);
935         cfg |= 1 << 0;
936         writel(cfg, &clk->gate_ip_lcd0);
937
938         /*
939          * CLK_DIV_LCD0
940          * FIMD0_RATIO          [3:0]
941          * MDNIE0_RATIO         [7:4]
942          * MDNIE_PWM0_RATIO     [11:8]
943          * MDNIE_PWM_PRE_RATIO  [15:12]
944          * MIPI0_RATIO          [19:16]
945          * MIPI0_PRE_RATIO      [23:20]
946          * set fimd ratio
947          */
948         cfg &= ~(0xf);
949         cfg |= 0x1;
950         writel(cfg, &clk->div_lcd0);
951 }
952
953 void exynos5_set_lcd_clk(void)
954 {
955         struct exynos5_clock *clk =
956             (struct exynos5_clock *)samsung_get_base_clock();
957         unsigned int cfg = 0;
958
959         /*
960          * CLK_GATE_BLOCK
961          * CLK_CAM      [0]
962          * CLK_TV       [1]
963          * CLK_MFC      [2]
964          * CLK_G3D      [3]
965          * CLK_LCD0     [4]
966          * CLK_LCD1     [5]
967          * CLK_GPS      [7]
968          */
969         cfg = readl(&clk->gate_block);
970         cfg |= 1 << 4;
971         writel(cfg, &clk->gate_block);
972
973         /*
974          * CLK_SRC_LCD0
975          * FIMD0_SEL            [3:0]
976          * MDNIE0_SEL           [7:4]
977          * MDNIE_PWM0_SEL       [8:11]
978          * MIPI0_SEL            [12:15]
979          * set lcd0 src clock 0x6: SCLK_MPLL
980          */
981         cfg = readl(&clk->src_disp1_0);
982         cfg &= ~(0xf);
983         cfg |= 0x6;
984         writel(cfg, &clk->src_disp1_0);
985
986         /*
987          * CLK_GATE_IP_LCD0
988          * CLK_FIMD0            [0]
989          * CLK_MIE0             [1]
990          * CLK_MDNIE0           [2]
991          * CLK_DSIM0            [3]
992          * CLK_SMMUFIMD0        [4]
993          * CLK_PPMULCD0         [5]
994          * Gating all clocks for FIMD0
995          */
996         cfg = readl(&clk->gate_ip_disp1);
997         cfg |= 1 << 0;
998         writel(cfg, &clk->gate_ip_disp1);
999
1000         /*
1001          * CLK_DIV_LCD0
1002          * FIMD0_RATIO          [3:0]
1003          * MDNIE0_RATIO         [7:4]
1004          * MDNIE_PWM0_RATIO     [11:8]
1005          * MDNIE_PWM_PRE_RATIO  [15:12]
1006          * MIPI0_RATIO          [19:16]
1007          * MIPI0_PRE_RATIO      [23:20]
1008          * set fimd ratio
1009          */
1010         cfg &= ~(0xf);
1011         cfg |= 0x0;
1012         writel(cfg, &clk->div_disp1_0);
1013 }
1014
1015 void exynos4_set_mipi_clk(void)
1016 {
1017         struct exynos4_clock *clk =
1018             (struct exynos4_clock *)samsung_get_base_clock();
1019         unsigned int cfg = 0;
1020
1021         /*
1022          * CLK_SRC_LCD0
1023          * FIMD0_SEL            [3:0]
1024          * MDNIE0_SEL           [7:4]
1025          * MDNIE_PWM0_SEL       [8:11]
1026          * MIPI0_SEL            [12:15]
1027          * set mipi0 src clock 0x6: SCLK_MPLL
1028          */
1029         cfg = readl(&clk->src_lcd0);
1030         cfg &= ~(0xf << 12);
1031         cfg |= (0x6 << 12);
1032         writel(cfg, &clk->src_lcd0);
1033
1034         /*
1035          * CLK_SRC_MASK_LCD0
1036          * FIMD0_MASK           [0]
1037          * MDNIE0_MASK          [4]
1038          * MDNIE_PWM0_MASK      [8]
1039          * MIPI0_MASK           [12]
1040          * set src mask mipi0 0x1: Unmask
1041          */
1042         cfg = readl(&clk->src_mask_lcd0);
1043         cfg |= (0x1 << 12);
1044         writel(cfg, &clk->src_mask_lcd0);
1045
1046         /*
1047          * CLK_GATE_IP_LCD0
1048          * CLK_FIMD0            [0]
1049          * CLK_MIE0             [1]
1050          * CLK_MDNIE0           [2]
1051          * CLK_DSIM0            [3]
1052          * CLK_SMMUFIMD0        [4]
1053          * CLK_PPMULCD0         [5]
1054          * Gating all clocks for MIPI0
1055          */
1056         cfg = readl(&clk->gate_ip_lcd0);
1057         cfg |= 1 << 3;
1058         writel(cfg, &clk->gate_ip_lcd0);
1059
1060         /*
1061          * CLK_DIV_LCD0
1062          * FIMD0_RATIO          [3:0]
1063          * MDNIE0_RATIO         [7:4]
1064          * MDNIE_PWM0_RATIO     [11:8]
1065          * MDNIE_PWM_PRE_RATIO  [15:12]
1066          * MIPI0_RATIO          [19:16]
1067          * MIPI0_PRE_RATIO      [23:20]
1068          * set mipi ratio
1069          */
1070         cfg &= ~(0xf << 16);
1071         cfg |= (0x1 << 16);
1072         writel(cfg, &clk->div_lcd0);
1073 }
1074
1075 /*
1076  * I2C
1077  *
1078  * exynos5: obtaining the I2C clock
1079  */
1080 static unsigned long exynos5_get_i2c_clk(void)
1081 {
1082         struct exynos5_clock *clk =
1083                 (struct exynos5_clock *)samsung_get_base_clock();
1084         unsigned long aclk_66, aclk_66_pre, sclk;
1085         unsigned int ratio;
1086
1087         sclk = get_pll_clk(MPLL);
1088
1089         ratio = (readl(&clk->div_top1)) >> 24;
1090         ratio &= 0x7;
1091         aclk_66_pre = sclk / (ratio + 1);
1092         ratio = readl(&clk->div_top0);
1093         ratio &= 0x7;
1094         aclk_66 = aclk_66_pre / (ratio + 1);
1095         return aclk_66;
1096 }
1097
1098 int exynos5_set_epll_clk(unsigned long rate)
1099 {
1100         unsigned int epll_con, epll_con_k;
1101         unsigned int i;
1102         unsigned int lockcnt;
1103         unsigned int start;
1104         struct exynos5_clock *clk =
1105                 (struct exynos5_clock *)samsung_get_base_clock();
1106
1107         epll_con = readl(&clk->epll_con0);
1108         epll_con &= ~((EPLL_CON0_LOCK_DET_EN_MASK <<
1109                         EPLL_CON0_LOCK_DET_EN_SHIFT) |
1110                 EPLL_CON0_MDIV_MASK << EPLL_CON0_MDIV_SHIFT |
1111                 EPLL_CON0_PDIV_MASK << EPLL_CON0_PDIV_SHIFT |
1112                 EPLL_CON0_SDIV_MASK << EPLL_CON0_SDIV_SHIFT);
1113
1114         for (i = 0; i < ARRAY_SIZE(exynos5_epll_div); i++) {
1115                 if (exynos5_epll_div[i].freq_out == rate)
1116                         break;
1117         }
1118
1119         if (i == ARRAY_SIZE(exynos5_epll_div))
1120                 return -1;
1121
1122         epll_con_k = exynos5_epll_div[i].k_dsm << 0;
1123         epll_con |= exynos5_epll_div[i].en_lock_det <<
1124                                 EPLL_CON0_LOCK_DET_EN_SHIFT;
1125         epll_con |= exynos5_epll_div[i].m_div << EPLL_CON0_MDIV_SHIFT;
1126         epll_con |= exynos5_epll_div[i].p_div << EPLL_CON0_PDIV_SHIFT;
1127         epll_con |= exynos5_epll_div[i].s_div << EPLL_CON0_SDIV_SHIFT;
1128
1129         /*
1130          * Required period ( in cycles) to genarate a stable clock output.
1131          * The maximum clock time can be up to 3000 * PDIV cycles of PLLs
1132          * frequency input (as per spec)
1133          */
1134         lockcnt = 3000 * exynos5_epll_div[i].p_div;
1135
1136         writel(lockcnt, &clk->epll_lock);
1137         writel(epll_con, &clk->epll_con0);
1138         writel(epll_con_k, &clk->epll_con1);
1139
1140         start = get_timer(0);
1141
1142          while (!(readl(&clk->epll_con0) &
1143                         (0x1 << EXYNOS5_EPLLCON0_LOCKED_SHIFT))) {
1144                 if (get_timer(start) > TIMEOUT_EPLL_LOCK) {
1145                         debug("%s: Timeout waiting for EPLL lock\n", __func__);
1146                         return -1;
1147                 }
1148         }
1149         return 0;
1150 }
1151
1152 int exynos5_set_i2s_clk_source(unsigned int i2s_id)
1153 {
1154         struct exynos5_clock *clk =
1155                 (struct exynos5_clock *)samsung_get_base_clock();
1156         unsigned int *audio_ass = (unsigned int *)samsung_get_base_audio_ass();
1157
1158         if (i2s_id == 0) {
1159                 setbits_le32(&clk->src_top2, CLK_SRC_MOUT_EPLL);
1160                 clrsetbits_le32(&clk->src_mau, AUDIO0_SEL_MASK,
1161                                 (CLK_SRC_SCLK_EPLL));
1162                 setbits_le32(audio_ass, AUDIO_CLKMUX_ASS);
1163         } else if (i2s_id == 1) {
1164                 clrsetbits_le32(&clk->src_peric1, AUDIO1_SEL_MASK,
1165                                 (CLK_SRC_SCLK_EPLL));
1166         } else {
1167                 return -1;
1168         }
1169         return 0;
1170 }
1171
1172 int exynos5_set_i2s_clk_prescaler(unsigned int src_frq,
1173                                   unsigned int dst_frq,
1174                                   unsigned int i2s_id)
1175 {
1176         struct exynos5_clock *clk =
1177                 (struct exynos5_clock *)samsung_get_base_clock();
1178         unsigned int div;
1179
1180         if ((dst_frq == 0) || (src_frq == 0)) {
1181                 debug("%s: Invalid requency input for prescaler\n", __func__);
1182                 debug("src frq = %d des frq = %d ", src_frq, dst_frq);
1183                 return -1;
1184         }
1185
1186         div = (src_frq / dst_frq);
1187         if (i2s_id == 0) {
1188                 if (div > AUDIO_0_RATIO_MASK) {
1189                         debug("%s: Frequency ratio is out of range\n",
1190                               __func__);
1191                         debug("src frq = %d des frq = %d ", src_frq, dst_frq);
1192                         return -1;
1193                 }
1194                 clrsetbits_le32(&clk->div_mau, AUDIO_0_RATIO_MASK,
1195                                 (div & AUDIO_0_RATIO_MASK));
1196         } else if(i2s_id == 1) {
1197                 if (div > AUDIO_1_RATIO_MASK) {
1198                         debug("%s: Frequency ratio is out of range\n",
1199                               __func__);
1200                         debug("src frq = %d des frq = %d ", src_frq, dst_frq);
1201                         return -1;
1202                 }
1203                 clrsetbits_le32(&clk->div_peric4, AUDIO_1_RATIO_MASK,
1204                                 (div & AUDIO_1_RATIO_MASK));
1205         } else {
1206                 return -1;
1207         }
1208         return 0;
1209 }
1210
1211 /**
1212  * Linearly searches for the most accurate main and fine stage clock scalars
1213  * (divisors) for a specified target frequency and scalar bit sizes by checking
1214  * all multiples of main_scalar_bits values. Will always return scalars up to or
1215  * slower than target.
1216  *
1217  * @param main_scalar_bits      Number of main scalar bits, must be > 0 and < 32
1218  * @param fine_scalar_bits      Number of fine scalar bits, must be > 0 and < 32
1219  * @param input_freq            Clock frequency to be scaled in Hz
1220  * @param target_freq           Desired clock frequency in Hz
1221  * @param best_fine_scalar      Pointer to store the fine stage divisor
1222  *
1223  * @return best_main_scalar     Main scalar for desired frequency or -1 if none
1224  * found
1225  */
1226 static int clock_calc_best_scalar(unsigned int main_scaler_bits,
1227         unsigned int fine_scalar_bits, unsigned int input_rate,
1228         unsigned int target_rate, unsigned int *best_fine_scalar)
1229 {
1230         int i;
1231         int best_main_scalar = -1;
1232         unsigned int best_error = target_rate;
1233         const unsigned int cap = (1 << fine_scalar_bits) - 1;
1234         const unsigned int loops = 1 << main_scaler_bits;
1235
1236         debug("Input Rate is %u, Target is %u, Cap is %u\n", input_rate,
1237                         target_rate, cap);
1238
1239         assert(best_fine_scalar != NULL);
1240         assert(main_scaler_bits <= fine_scalar_bits);
1241
1242         *best_fine_scalar = 1;
1243
1244         if (input_rate == 0 || target_rate == 0)
1245                 return -1;
1246
1247         if (target_rate >= input_rate)
1248                 return 1;
1249
1250         for (i = 1; i <= loops; i++) {
1251                 const unsigned int effective_div = max(min(input_rate / i /
1252                                                         target_rate, cap), 1);
1253                 const unsigned int effective_rate = input_rate / i /
1254                                                         effective_div;
1255                 const int error = target_rate - effective_rate;
1256
1257                 debug("%d|effdiv:%u, effrate:%u, error:%d\n", i, effective_div,
1258                                 effective_rate, error);
1259
1260                 if (error >= 0 && error <= best_error) {
1261                         best_error = error;
1262                         best_main_scalar = i;
1263                         *best_fine_scalar = effective_div;
1264                 }
1265         }
1266
1267         return best_main_scalar;
1268 }
1269
1270 static int exynos5_set_spi_clk(enum periph_id periph_id,
1271                                         unsigned int rate)
1272 {
1273         struct exynos5_clock *clk =
1274                 (struct exynos5_clock *)samsung_get_base_clock();
1275         int main;
1276         unsigned int fine;
1277         unsigned shift, pre_shift;
1278         unsigned mask = 0xff;
1279         u32 *reg;
1280
1281         main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine);
1282         if (main < 0) {
1283                 debug("%s: Cannot set clock rate for periph %d",
1284                                 __func__, periph_id);
1285                 return -1;
1286         }
1287         main = main - 1;
1288         fine = fine - 1;
1289
1290         switch (periph_id) {
1291         case PERIPH_ID_SPI0:
1292                 reg = &clk->div_peric1;
1293                 shift = 0;
1294                 pre_shift = 8;
1295                 break;
1296         case PERIPH_ID_SPI1:
1297                 reg = &clk->div_peric1;
1298                 shift = 16;
1299                 pre_shift = 24;
1300                 break;
1301         case PERIPH_ID_SPI2:
1302                 reg = &clk->div_peric2;
1303                 shift = 0;
1304                 pre_shift = 8;
1305                 break;
1306         case PERIPH_ID_SPI3:
1307                 reg = &clk->sclk_div_isp;
1308                 shift = 0;
1309                 pre_shift = 4;
1310                 break;
1311         case PERIPH_ID_SPI4:
1312                 reg = &clk->sclk_div_isp;
1313                 shift = 12;
1314                 pre_shift = 16;
1315                 break;
1316         default:
1317                 debug("%s: Unsupported peripheral ID %d\n", __func__,
1318                       periph_id);
1319                 return -1;
1320         }
1321         clrsetbits_le32(reg, mask << shift, (main & mask) << shift);
1322         clrsetbits_le32(reg, mask << pre_shift, (fine & mask) << pre_shift);
1323
1324         return 0;
1325 }
1326
1327 static unsigned long exynos4_get_i2c_clk(void)
1328 {
1329         struct exynos4_clock *clk =
1330                 (struct exynos4_clock *)samsung_get_base_clock();
1331         unsigned long sclk, aclk_100;
1332         unsigned int ratio;
1333
1334         sclk = get_pll_clk(APLL);
1335
1336         ratio = (readl(&clk->div_top)) >> 4;
1337         ratio &= 0xf;
1338         aclk_100 = sclk / (ratio + 1);
1339         return aclk_100;
1340 }
1341
1342 unsigned long get_pll_clk(int pllreg)
1343 {
1344         if (cpu_is_exynos5())
1345                 return exynos5_get_pll_clk(pllreg);
1346         else {
1347                 if (proid_is_exynos4412())
1348                         return exynos4x12_get_pll_clk(pllreg);
1349                 return exynos4_get_pll_clk(pllreg);
1350         }
1351 }
1352
1353 unsigned long get_arm_clk(void)
1354 {
1355         if (cpu_is_exynos5())
1356                 return exynos5_get_arm_clk();
1357         else {
1358                 if (proid_is_exynos4412())
1359                         return exynos4x12_get_arm_clk();
1360                 return exynos4_get_arm_clk();
1361         }
1362 }
1363
1364 unsigned long get_i2c_clk(void)
1365 {
1366         if (cpu_is_exynos5()) {
1367                 return exynos5_get_i2c_clk();
1368         } else if (cpu_is_exynos4()) {
1369                 return exynos4_get_i2c_clk();
1370         } else {
1371                 debug("I2C clock is not set for this CPU\n");
1372                 return 0;
1373         }
1374 }
1375
1376 unsigned long get_pwm_clk(void)
1377 {
1378         if (cpu_is_exynos5())
1379                 return clock_get_periph_rate(PERIPH_ID_PWM0);
1380         else {
1381                 if (proid_is_exynos4412())
1382                         return exynos4x12_get_pwm_clk();
1383                 return exynos4_get_pwm_clk();
1384         }
1385 }
1386
1387 unsigned long get_uart_clk(int dev_index)
1388 {
1389         if (cpu_is_exynos5())
1390                 return exynos5_get_uart_clk(dev_index);
1391         else {
1392                 if (proid_is_exynos4412())
1393                         return exynos4x12_get_uart_clk(dev_index);
1394                 return exynos4_get_uart_clk(dev_index);
1395         }
1396 }
1397
1398 unsigned long get_mmc_clk(int dev_index)
1399 {
1400         if (cpu_is_exynos5())
1401                 return exynos5_get_mmc_clk(dev_index);
1402         else
1403                 return exynos4_get_mmc_clk(dev_index);
1404 }
1405
1406 void set_mmc_clk(int dev_index, unsigned int div)
1407 {
1408         if (cpu_is_exynos5())
1409                 exynos5_set_mmc_clk(dev_index, div);
1410         else {
1411                 if (proid_is_exynos4412())
1412                         exynos4x12_set_mmc_clk(dev_index, div);
1413                 else
1414                         exynos4_set_mmc_clk(dev_index, div);
1415         }
1416 }
1417
1418 unsigned long get_lcd_clk(void)
1419 {
1420         if (cpu_is_exynos4())
1421                 return exynos4_get_lcd_clk();
1422         else
1423                 return exynos5_get_lcd_clk();
1424 }
1425
1426 void set_lcd_clk(void)
1427 {
1428         if (cpu_is_exynos4())
1429                 exynos4_set_lcd_clk();
1430         else
1431                 exynos5_set_lcd_clk();
1432 }
1433
1434 void set_mipi_clk(void)
1435 {
1436         if (cpu_is_exynos4())
1437                 exynos4_set_mipi_clk();
1438 }
1439
1440 int set_spi_clk(int periph_id, unsigned int rate)
1441 {
1442         if (cpu_is_exynos5())
1443                 return exynos5_set_spi_clk(periph_id, rate);
1444         else
1445                 return 0;
1446 }
1447
1448 int set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq,
1449                           unsigned int i2s_id)
1450 {
1451         if (cpu_is_exynos5())
1452                 return exynos5_set_i2s_clk_prescaler(src_frq, dst_frq, i2s_id);
1453         else
1454                 return 0;
1455 }
1456
1457 int set_i2s_clk_source(unsigned int i2s_id)
1458 {
1459         if (cpu_is_exynos5())
1460                 return exynos5_set_i2s_clk_source(i2s_id);
1461         else
1462                 return 0;
1463 }
1464
1465 int set_epll_clk(unsigned long rate)
1466 {
1467         if (cpu_is_exynos5())
1468                 return exynos5_set_epll_clk(rate);
1469         else
1470                 return 0;
1471 }