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