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