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