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