1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include <common.h>
25#include <asm/io.h>
26#include <asm/arch/clock.h>
27#include <asm/arch/clk.h>
28
29
30static unsigned long exynos4_get_pll_clk(int pllreg)
31{
32 struct exynos4_clock *clk =
33 (struct exynos4_clock *)samsung_get_base_clock();
34 unsigned long r, m, p, s, k = 0, mask, fout;
35 unsigned int freq;
36
37 switch (pllreg) {
38 case APLL:
39 r = readl(&clk->apll_con0);
40 break;
41 case MPLL:
42 r = readl(&clk->mpll_con0);
43 break;
44 case EPLL:
45 r = readl(&clk->epll_con0);
46 k = readl(&clk->epll_con1);
47 break;
48 case VPLL:
49 r = readl(&clk->vpll_con0);
50 k = readl(&clk->vpll_con1);
51 break;
52 default:
53 printf("Unsupported PLL (%d)\n", pllreg);
54 return 0;
55 }
56
57
58
59
60
61
62
63 if (pllreg == APLL || pllreg == MPLL)
64 mask = 0x3ff;
65 else
66 mask = 0x1ff;
67
68 m = (r >> 16) & mask;
69
70
71 p = (r >> 8) & 0x3f;
72
73 s = r & 0x7;
74
75 freq = CONFIG_SYS_CLK_FREQ;
76
77 if (pllreg == EPLL) {
78 k = k & 0xffff;
79
80 fout = (m + k / 65536) * (freq / (p * (1 << s)));
81 } else if (pllreg == VPLL) {
82 k = k & 0xfff;
83
84 fout = (m + k / 1024) * (freq / (p * (1 << s)));
85 } else {
86 if (s < 1)
87 s = 1;
88
89 fout = m * (freq / (p * (1 << (s - 1))));
90 }
91
92 return fout;
93}
94
95
96static unsigned long exynos5_get_pll_clk(int pllreg)
97{
98 struct exynos5_clock *clk =
99 (struct exynos5_clock *)samsung_get_base_clock();
100 unsigned long r, m, p, s, k = 0, mask, fout;
101 unsigned int freq;
102
103 switch (pllreg) {
104 case APLL:
105 r = readl(&clk->apll_con0);
106 break;
107 case MPLL:
108 r = readl(&clk->mpll_con0);
109 break;
110 case EPLL:
111 r = readl(&clk->epll_con0);
112 k = readl(&clk->epll_con1);
113 break;
114 case VPLL:
115 r = readl(&clk->vpll_con0);
116 k = readl(&clk->vpll_con1);
117 break;
118 default:
119 printf("Unsupported PLL (%d)\n", pllreg);
120 return 0;
121 }
122
123
124
125
126
127
128
129 if (pllreg == APLL || pllreg == MPLL)
130 mask = 0x3ff;
131 else
132 mask = 0x1ff;
133
134 m = (r >> 16) & mask;
135
136
137 p = (r >> 8) & 0x3f;
138
139 s = r & 0x7;
140
141 freq = CONFIG_SYS_CLK_FREQ;
142
143 if (pllreg == EPLL) {
144 k = k & 0xffff;
145
146 fout = (m + k / 65536) * (freq / (p * (1 << s)));
147 } else if (pllreg == VPLL) {
148 k = k & 0xfff;
149
150 fout = (m + k / 1024) * (freq / (p * (1 << s)));
151 } else {
152 if (s < 1)
153 s = 1;
154
155 fout = m * (freq / (p * (1 << (s - 1))));
156 }
157
158 return fout;
159}
160
161
162static unsigned long exynos4_get_arm_clk(void)
163{
164 struct exynos4_clock *clk =
165 (struct exynos4_clock *)samsung_get_base_clock();
166 unsigned long div;
167 unsigned long armclk;
168 unsigned int core_ratio;
169 unsigned int core2_ratio;
170
171 div = readl(&clk->div_cpu0);
172
173
174 core_ratio = (div >> 0) & 0x7;
175 core2_ratio = (div >> 28) & 0x7;
176
177 armclk = get_pll_clk(APLL) / (core_ratio + 1);
178 armclk /= (core2_ratio + 1);
179
180 return armclk;
181}
182
183
184static unsigned long exynos5_get_arm_clk(void)
185{
186 struct exynos5_clock *clk =
187 (struct exynos5_clock *)samsung_get_base_clock();
188 unsigned long div;
189 unsigned long armclk;
190 unsigned int arm_ratio;
191 unsigned int arm2_ratio;
192
193 div = readl(&clk->div_cpu0);
194
195
196 arm_ratio = (div >> 0) & 0x7;
197 arm2_ratio = (div >> 28) & 0x7;
198
199 armclk = get_pll_clk(APLL) / (arm_ratio + 1);
200 armclk /= (arm2_ratio + 1);
201
202 return armclk;
203}
204
205
206static unsigned long exynos4_get_pwm_clk(void)
207{
208 struct exynos4_clock *clk =
209 (struct exynos4_clock *)samsung_get_base_clock();
210 unsigned long pclk, sclk;
211 unsigned int sel;
212 unsigned int ratio;
213
214 if (s5p_get_cpu_rev() == 0) {
215
216
217
218
219 sel = readl(&clk->src_peril0);
220 sel = (sel >> 24) & 0xf;
221
222 if (sel == 0x6)
223 sclk = get_pll_clk(MPLL);
224 else if (sel == 0x7)
225 sclk = get_pll_clk(EPLL);
226 else if (sel == 0x8)
227 sclk = get_pll_clk(VPLL);
228 else
229 return 0;
230
231
232
233
234
235 ratio = readl(&clk->div_peril3);
236 ratio = ratio & 0xf;
237 } else if (s5p_get_cpu_rev() == 1) {
238 sclk = get_pll_clk(MPLL);
239 ratio = 8;
240 } else
241 return 0;
242
243 pclk = sclk / (ratio + 1);
244
245 return pclk;
246}
247
248
249static unsigned long exynos5_get_pwm_clk(void)
250{
251 struct exynos5_clock *clk =
252 (struct exynos5_clock *)samsung_get_base_clock();
253 unsigned long pclk, sclk;
254 unsigned int ratio;
255
256
257
258
259
260 ratio = readl(&clk->div_peric3);
261 ratio = ratio & 0xf;
262 sclk = get_pll_clk(MPLL);
263
264 pclk = sclk / (ratio + 1);
265
266 return pclk;
267}
268
269
270static unsigned long exynos4_get_uart_clk(int dev_index)
271{
272 struct exynos4_clock *clk =
273 (struct exynos4_clock *)samsung_get_base_clock();
274 unsigned long uclk, sclk;
275 unsigned int sel;
276 unsigned int ratio;
277
278
279
280
281
282
283
284
285
286
287 sel = readl(&clk->src_peril0);
288 sel = (sel >> (dev_index << 2)) & 0xf;
289
290 if (sel == 0x6)
291 sclk = get_pll_clk(MPLL);
292 else if (sel == 0x7)
293 sclk = get_pll_clk(EPLL);
294 else if (sel == 0x8)
295 sclk = get_pll_clk(VPLL);
296 else
297 return 0;
298
299
300
301
302
303
304
305
306
307
308 ratio = readl(&clk->div_peril0);
309 ratio = (ratio >> (dev_index << 2)) & 0xf;
310
311 uclk = sclk / (ratio + 1);
312
313 return uclk;
314}
315
316
317static unsigned long exynos5_get_uart_clk(int dev_index)
318{
319 struct exynos5_clock *clk =
320 (struct exynos5_clock *)samsung_get_base_clock();
321 unsigned long uclk, sclk;
322 unsigned int sel;
323 unsigned int ratio;
324
325
326
327
328
329
330
331
332
333
334 sel = readl(&clk->src_peric0);
335 sel = (sel >> (dev_index << 2)) & 0xf;
336
337 if (sel == 0x6)
338 sclk = get_pll_clk(MPLL);
339 else if (sel == 0x7)
340 sclk = get_pll_clk(EPLL);
341 else if (sel == 0x8)
342 sclk = get_pll_clk(VPLL);
343 else
344 return 0;
345
346
347
348
349
350
351
352
353
354
355 ratio = readl(&clk->div_peric0);
356 ratio = (ratio >> (dev_index << 2)) & 0xf;
357
358 uclk = sclk / (ratio + 1);
359
360 return uclk;
361}
362
363
364static void exynos4_set_mmc_clk(int dev_index, unsigned int div)
365{
366 struct exynos4_clock *clk =
367 (struct exynos4_clock *)samsung_get_base_clock();
368 unsigned int addr;
369 unsigned int val;
370
371
372
373
374
375
376
377 if (dev_index < 2) {
378 addr = (unsigned int)&clk->div_fsys1;
379 } else {
380 addr = (unsigned int)&clk->div_fsys2;
381 dev_index -= 2;
382 }
383
384 val = readl(addr);
385 val &= ~(0xff << ((dev_index << 4) + 8));
386 val |= (div & 0xff) << ((dev_index << 4) + 8);
387 writel(val, addr);
388}
389
390
391static void exynos5_set_mmc_clk(int dev_index, unsigned int div)
392{
393 struct exynos5_clock *clk =
394 (struct exynos5_clock *)samsung_get_base_clock();
395 unsigned int addr;
396 unsigned int val;
397
398
399
400
401
402
403
404 if (dev_index < 2) {
405 addr = (unsigned int)&clk->div_fsys1;
406 } else {
407 addr = (unsigned int)&clk->div_fsys2;
408 dev_index -= 2;
409 }
410
411 val = readl(addr);
412 val &= ~(0xff << ((dev_index << 4) + 8));
413 val |= (div & 0xff) << ((dev_index << 4) + 8);
414 writel(val, addr);
415}
416
417
418static unsigned long exynos4_get_lcd_clk(void)
419{
420 struct exynos4_clock *clk =
421 (struct exynos4_clock *)samsung_get_base_clock();
422 unsigned long pclk, sclk;
423 unsigned int sel;
424 unsigned int ratio;
425
426
427
428
429
430 sel = readl(&clk->src_lcd0);
431 sel = sel & 0xf;
432
433
434
435
436
437
438 if (sel == 0x6)
439 sclk = get_pll_clk(MPLL);
440 else if (sel == 0x7)
441 sclk = get_pll_clk(EPLL);
442 else if (sel == 0x8)
443 sclk = get_pll_clk(VPLL);
444 else
445 return 0;
446
447
448
449
450
451 ratio = readl(&clk->div_lcd0);
452 ratio = ratio & 0xf;
453
454 pclk = sclk / (ratio + 1);
455
456 return pclk;
457}
458
459void exynos4_set_lcd_clk(void)
460{
461 struct exynos4_clock *clk =
462 (struct exynos4_clock *)samsung_get_base_clock();
463 unsigned int cfg = 0;
464
465
466
467
468
469
470
471
472
473
474
475 cfg = readl(&clk->gate_block);
476 cfg |= 1 << 4;
477 writel(cfg, &clk->gate_block);
478
479
480
481
482
483
484
485
486
487 cfg = readl(&clk->src_lcd0);
488 cfg &= ~(0xf);
489 cfg |= 0x6;
490 writel(cfg, &clk->src_lcd0);
491
492
493
494
495
496
497
498
499
500
501
502 cfg = readl(&clk->gate_ip_lcd0);
503 cfg |= 1 << 0;
504 writel(cfg, &clk->gate_ip_lcd0);
505
506
507
508
509
510
511
512
513
514
515
516 cfg &= ~(0xf);
517 cfg |= 0x1;
518 writel(cfg, &clk->div_lcd0);
519}
520
521void exynos4_set_mipi_clk(void)
522{
523 struct exynos4_clock *clk =
524 (struct exynos4_clock *)samsung_get_base_clock();
525 unsigned int cfg = 0;
526
527
528
529
530
531
532
533
534
535 cfg = readl(&clk->src_lcd0);
536 cfg &= ~(0xf << 12);
537 cfg |= (0x6 << 12);
538 writel(cfg, &clk->src_lcd0);
539
540
541
542
543
544
545
546
547
548 cfg = readl(&clk->src_mask_lcd0);
549 cfg |= (0x1 << 12);
550 writel(cfg, &clk->src_mask_lcd0);
551
552
553
554
555
556
557
558
559
560
561
562 cfg = readl(&clk->gate_ip_lcd0);
563 cfg |= 1 << 3;
564 writel(cfg, &clk->gate_ip_lcd0);
565
566
567
568
569
570
571
572
573
574
575
576 cfg &= ~(0xf << 16);
577 cfg |= (0x1 << 16);
578 writel(cfg, &clk->div_lcd0);
579}
580
581unsigned long get_pll_clk(int pllreg)
582{
583 if (cpu_is_exynos5())
584 return exynos5_get_pll_clk(pllreg);
585 else
586 return exynos4_get_pll_clk(pllreg);
587}
588
589unsigned long get_arm_clk(void)
590{
591 if (cpu_is_exynos5())
592 return exynos5_get_arm_clk();
593 else
594 return exynos4_get_arm_clk();
595}
596
597unsigned long get_pwm_clk(void)
598{
599 if (cpu_is_exynos5())
600 return exynos5_get_pwm_clk();
601 else
602 return exynos4_get_pwm_clk();
603}
604
605unsigned long get_uart_clk(int dev_index)
606{
607 if (cpu_is_exynos5())
608 return exynos5_get_uart_clk(dev_index);
609 else
610 return exynos4_get_uart_clk(dev_index);
611}
612
613void set_mmc_clk(int dev_index, unsigned int div)
614{
615 if (cpu_is_exynos5())
616 exynos5_set_mmc_clk(dev_index, div);
617 else
618 exynos4_set_mmc_clk(dev_index, div);
619}
620
621unsigned long get_lcd_clk(void)
622{
623 if (cpu_is_exynos4())
624 return exynos4_get_lcd_clk();
625 else
626 return 0;
627}
628
629void set_lcd_clk(void)
630{
631 if (cpu_is_exynos4())
632 exynos4_set_lcd_clk();
633}
634
635void set_mipi_clk(void)
636{
637 if (cpu_is_exynos4())
638 exynos4_set_mipi_clk();
639}
640