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