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