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