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