blob: 400d134d549de542a532022a3ecf6e20c0093d27 [file] [log] [blame]
Minkyu Kangb1b24682011-01-24 15:22:23 +09001/*
2 * Copyright (C) 2010 Samsung Electronics
3 * Minkyu Kang <mk7.kang@samsung.com>
4 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
Minkyu Kangb1b24682011-01-24 15:22:23 +09006 */
7
8#include <common.h>
9#include <asm/io.h>
10#include <asm/arch/clock.h>
11#include <asm/arch/clk.h>
Hatim RVe6365b62012-11-02 01:15:34 +000012#include <asm/arch/periph.h>
Minkyu Kangb1b24682011-01-24 15:22:23 +090013
Minkyu Kang368588e2013-07-05 19:08:33 +090014#define PLL_DIV_1024 1024
15#define PLL_DIV_65535 65535
16#define PLL_DIV_65536 65536
17
Padmavathi Venna37feb7b2013-03-28 04:32:21 +000018/* *
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 */
22struct clk_bit_info {
23 int8_t src_bit;
24 int8_t div_bit;
25 int8_t prediv_bit;
26};
27
28/* src_bit div_bit prediv_bit */
Minkyu Kang30e472f2014-01-29 17:03:58 +090029static struct clk_bit_info clk_bit_info[] = {
Padmavathi Venna37feb7b2013-03-28 04:32:21 +000030 {0, 0, -1},
31 {4, 4, -1},
32 {8, 8, -1},
33 {12, 12, -1},
34 {0, 0, 8},
35 {4, 16, 24},
36 {8, 0, 8},
37 {12, 16, 24},
38 {-1, -1, -1},
39 {16, 0, 8},
40 {20, 16, 24},
41 {24, 0, 8},
42 {0, 0, 4},
43 {4, 12, 16},
44 {-1, -1, -1},
45 {-1, -1, -1},
46 {-1, 24, 0},
47 {-1, 24, 0},
48 {-1, 24, 0},
49 {-1, 24, 0},
50 {-1, 24, 0},
51 {-1, 24, 0},
52 {-1, 24, 0},
53 {-1, 24, 0},
54 {24, 0, -1},
55 {24, 0, -1},
56 {24, 0, -1},
57 {24, 0, -1},
58 {24, 0, -1},
59};
60
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +000061/* Epll Clock division values to achive different frequency output */
62static struct set_epll_con_val exynos5_epll_div[] = {
63 { 192000000, 0, 48, 3, 1, 0 },
64 { 180000000, 0, 45, 3, 1, 0 },
65 { 73728000, 1, 73, 3, 3, 47710 },
66 { 67737600, 1, 90, 4, 3, 20762 },
67 { 49152000, 0, 49, 3, 3, 9961 },
68 { 45158400, 0, 45, 3, 3, 10381 },
69 { 180633600, 0, 45, 3, 1, 10381 }
70};
71
Minkyu Kang1a055aa2012-10-15 01:58:00 +000072/* exynos: return pll clock frequency */
73static int exynos_get_pll_clk(int pllreg, unsigned int r, unsigned int k)
Minkyu Kangb1b24682011-01-24 15:22:23 +090074{
Minkyu Kang1a055aa2012-10-15 01:58:00 +000075 unsigned long m, p, s = 0, mask, fout;
Minkyu Kang368588e2013-07-05 19:08:33 +090076 unsigned int div;
Minkyu Kangb1b24682011-01-24 15:22:23 +090077 unsigned int freq;
Minkyu Kangb1b24682011-01-24 15:22:23 +090078 /*
79 * APLL_CON: MIDV [25:16]
80 * MPLL_CON: MIDV [25:16]
81 * EPLL_CON: MIDV [24:16]
82 * VPLL_CON: MIDV [24:16]
Minkyu Kang1a055aa2012-10-15 01:58:00 +000083 * BPLL_CON: MIDV [25:16]: Exynos5
Minkyu Kangb1b24682011-01-24 15:22:23 +090084 */
Minkyu Kang1a055aa2012-10-15 01:58:00 +000085 if (pllreg == APLL || pllreg == MPLL || pllreg == BPLL)
Minkyu Kangb1b24682011-01-24 15:22:23 +090086 mask = 0x3ff;
87 else
88 mask = 0x1ff;
89
90 m = (r >> 16) & mask;
91
92 /* PDIV [13:8] */
93 p = (r >> 8) & 0x3f;
94 /* SDIV [2:0] */
95 s = r & 0x7;
96
Chander Kashyap6a870e12012-02-05 23:01:45 +000097 freq = CONFIG_SYS_CLK_FREQ;
Minkyu Kangb1b24682011-01-24 15:22:23 +090098
Rajeshwari Birjeac892d02013-12-26 09:44:21 +053099 if (pllreg == EPLL || pllreg == RPLL) {
Minkyu Kangb1b24682011-01-24 15:22:23 +0900100 k = k & 0xffff;
101 /* FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV) */
Minkyu Kang368588e2013-07-05 19:08:33 +0900102 fout = (m + k / PLL_DIV_65536) * (freq / (p * (1 << s)));
Minkyu Kangb1b24682011-01-24 15:22:23 +0900103 } else if (pllreg == VPLL) {
104 k = k & 0xfff;
Minkyu Kang368588e2013-07-05 19:08:33 +0900105
106 /*
107 * Exynos4210
108 * FOUT = (MDIV + K / 1024) * FIN / (PDIV * 2^SDIV)
109 *
110 * Exynos4412
111 * FOUT = (MDIV + K / 65535) * FIN / (PDIV * 2^SDIV)
112 *
113 * Exynos5250
114 * FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV)
115 */
116 if (proid_is_exynos4210())
117 div = PLL_DIV_1024;
118 else if (proid_is_exynos4412())
119 div = PLL_DIV_65535;
Rajeshwari Birjeac892d02013-12-26 09:44:21 +0530120 else if (proid_is_exynos5250() || proid_is_exynos5420())
Minkyu Kang368588e2013-07-05 19:08:33 +0900121 div = PLL_DIV_65536;
122 else
123 return 0;
124
125 fout = (m + k / div) * (freq / (p * (1 << s)));
Minkyu Kangb1b24682011-01-24 15:22:23 +0900126 } else {
Minkyu Kang368588e2013-07-05 19:08:33 +0900127 /*
Łukasz Majewski326c4592013-07-12 19:08:25 +0200128 * Exynos4412 / Exynos5250
Minkyu Kang368588e2013-07-05 19:08:33 +0900129 * FOUT = MDIV * FIN / (PDIV * 2^SDIV)
130 *
Łukasz Majewski326c4592013-07-12 19:08:25 +0200131 * Exynos4210
Minkyu Kang368588e2013-07-05 19:08:33 +0900132 * FOUT = MDIV * FIN / (PDIV * 2^(SDIV-1))
133 */
134 if (proid_is_exynos4210())
Minkyu Kang368588e2013-07-05 19:08:33 +0900135 fout = m * (freq / (p * (1 << (s - 1))));
Łukasz Majewski326c4592013-07-12 19:08:25 +0200136 else
137 fout = m * (freq / (p * (1 << s)));
Minkyu Kangb1b24682011-01-24 15:22:23 +0900138 }
Minkyu Kangb1b24682011-01-24 15:22:23 +0900139 return fout;
140}
141
Minkyu Kang1a055aa2012-10-15 01:58:00 +0000142/* exynos4: return pll clock frequency */
143static unsigned long exynos4_get_pll_clk(int pllreg)
144{
145 struct exynos4_clock *clk =
146 (struct exynos4_clock *)samsung_get_base_clock();
147 unsigned long r, k = 0;
148
149 switch (pllreg) {
150 case APLL:
151 r = readl(&clk->apll_con0);
152 break;
153 case MPLL:
154 r = readl(&clk->mpll_con0);
155 break;
156 case EPLL:
157 r = readl(&clk->epll_con0);
158 k = readl(&clk->epll_con1);
159 break;
160 case VPLL:
161 r = readl(&clk->vpll_con0);
162 k = readl(&clk->vpll_con1);
163 break;
164 default:
165 printf("Unsupported PLL (%d)\n", pllreg);
166 return 0;
167 }
168
169 return exynos_get_pll_clk(pllreg, r, k);
170}
171
Chander Kashyap400ab162012-10-07 01:43:17 +0000172/* exynos4x12: return pll clock frequency */
173static unsigned long exynos4x12_get_pll_clk(int pllreg)
174{
175 struct exynos4x12_clock *clk =
176 (struct exynos4x12_clock *)samsung_get_base_clock();
177 unsigned long r, k = 0;
178
179 switch (pllreg) {
180 case APLL:
181 r = readl(&clk->apll_con0);
182 break;
183 case MPLL:
184 r = readl(&clk->mpll_con0);
185 break;
186 case EPLL:
187 r = readl(&clk->epll_con0);
188 k = readl(&clk->epll_con1);
189 break;
190 case VPLL:
191 r = readl(&clk->vpll_con0);
192 k = readl(&clk->vpll_con1);
193 break;
194 default:
195 printf("Unsupported PLL (%d)\n", pllreg);
196 return 0;
197 }
198
199 return exynos_get_pll_clk(pllreg, r, k);
200}
201
Chander Kashyap34076a02012-02-05 23:01:46 +0000202/* exynos5: return pll clock frequency */
203static unsigned long exynos5_get_pll_clk(int pllreg)
204{
205 struct exynos5_clock *clk =
206 (struct exynos5_clock *)samsung_get_base_clock();
Minkyu Kang1a055aa2012-10-15 01:58:00 +0000207 unsigned long r, k = 0, fout;
208 unsigned int pll_div2_sel, fout_sel;
Chander Kashyap34076a02012-02-05 23:01:46 +0000209
210 switch (pllreg) {
211 case APLL:
212 r = readl(&clk->apll_con0);
213 break;
214 case MPLL:
215 r = readl(&clk->mpll_con0);
216 break;
217 case EPLL:
218 r = readl(&clk->epll_con0);
219 k = readl(&clk->epll_con1);
220 break;
221 case VPLL:
222 r = readl(&clk->vpll_con0);
223 k = readl(&clk->vpll_con1);
224 break;
Rajeshwari Shinde84112862012-07-03 20:02:58 +0000225 case BPLL:
226 r = readl(&clk->bpll_con0);
227 break;
Chander Kashyap34076a02012-02-05 23:01:46 +0000228 default:
229 printf("Unsupported PLL (%d)\n", pllreg);
230 return 0;
231 }
232
Minkyu Kang1a055aa2012-10-15 01:58:00 +0000233 fout = exynos_get_pll_clk(pllreg, r, k);
Chander Kashyap34076a02012-02-05 23:01:46 +0000234
Rajeshwari Shinde84112862012-07-03 20:02:58 +0000235 /* According to the user manual, in EVT1 MPLL and BPLL always gives
Rajeshwari Shinde7b9afce2012-07-03 20:02:57 +0000236 * 1.6GHz clock, so divide by 2 to get 800MHz MPLL clock.*/
Rajeshwari Shinde84112862012-07-03 20:02:58 +0000237 if (pllreg == MPLL || pllreg == BPLL) {
Rajeshwari Shinde7b9afce2012-07-03 20:02:57 +0000238 pll_div2_sel = readl(&clk->pll_div2_sel);
Rajeshwari Shinde84112862012-07-03 20:02:58 +0000239
240 switch (pllreg) {
241 case MPLL:
242 fout_sel = (pll_div2_sel >> MPLL_FOUT_SEL_SHIFT)
243 & MPLL_FOUT_SEL_MASK;
244 break;
245 case BPLL:
246 fout_sel = (pll_div2_sel >> BPLL_FOUT_SEL_SHIFT)
247 & BPLL_FOUT_SEL_MASK;
248 break;
Jaehoon Chung0fc779c2012-07-09 21:20:34 +0000249 default:
250 fout_sel = -1;
251 break;
Rajeshwari Shinde84112862012-07-03 20:02:58 +0000252 }
253
254 if (fout_sel == 0)
Rajeshwari Shinde7b9afce2012-07-03 20:02:57 +0000255 fout /= 2;
256 }
257
Chander Kashyap34076a02012-02-05 23:01:46 +0000258 return fout;
259}
260
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000261static unsigned long exynos5_get_periph_rate(int peripheral)
262{
263 struct clk_bit_info *bit_info = &clk_bit_info[peripheral];
264 unsigned long sclk, sub_clk;
265 unsigned int src, div, sub_div;
266 struct exynos5_clock *clk =
267 (struct exynos5_clock *)samsung_get_base_clock();
268
269 switch (peripheral) {
270 case PERIPH_ID_UART0:
271 case PERIPH_ID_UART1:
272 case PERIPH_ID_UART2:
273 case PERIPH_ID_UART3:
274 src = readl(&clk->src_peric0);
275 div = readl(&clk->div_peric0);
276 break;
277 case PERIPH_ID_PWM0:
278 case PERIPH_ID_PWM1:
279 case PERIPH_ID_PWM2:
280 case PERIPH_ID_PWM3:
281 case PERIPH_ID_PWM4:
282 src = readl(&clk->src_peric0);
283 div = readl(&clk->div_peric3);
284 break;
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +0530285 case PERIPH_ID_I2S0:
286 src = readl(&clk->src_mau);
287 div = readl(&clk->div_mau);
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000288 case PERIPH_ID_SPI0:
289 case PERIPH_ID_SPI1:
290 src = readl(&clk->src_peric1);
291 div = readl(&clk->div_peric1);
292 break;
293 case PERIPH_ID_SPI2:
294 src = readl(&clk->src_peric1);
295 div = readl(&clk->div_peric2);
296 break;
297 case PERIPH_ID_SPI3:
298 case PERIPH_ID_SPI4:
299 src = readl(&clk->sclk_src_isp);
300 div = readl(&clk->sclk_div_isp);
301 break;
302 case PERIPH_ID_SDMMC0:
303 case PERIPH_ID_SDMMC1:
304 case PERIPH_ID_SDMMC2:
305 case PERIPH_ID_SDMMC3:
306 src = readl(&clk->src_fsys);
307 div = readl(&clk->div_fsys1);
308 break;
309 case PERIPH_ID_I2C0:
310 case PERIPH_ID_I2C1:
311 case PERIPH_ID_I2C2:
312 case PERIPH_ID_I2C3:
313 case PERIPH_ID_I2C4:
314 case PERIPH_ID_I2C5:
315 case PERIPH_ID_I2C6:
316 case PERIPH_ID_I2C7:
317 sclk = exynos5_get_pll_clk(MPLL);
318 sub_div = ((readl(&clk->div_top1) >> bit_info->div_bit)
319 & 0x7) + 1;
320 div = ((readl(&clk->div_top0) >> bit_info->prediv_bit)
321 & 0x7) + 1;
322 return (sclk / sub_div) / div;
323 default:
324 debug("%s: invalid peripheral %d", __func__, peripheral);
325 return -1;
326 };
327
328 src = (src >> bit_info->src_bit) & 0xf;
329
330 switch (src) {
331 case EXYNOS_SRC_MPLL:
332 sclk = exynos5_get_pll_clk(MPLL);
333 break;
334 case EXYNOS_SRC_EPLL:
335 sclk = exynos5_get_pll_clk(EPLL);
336 break;
337 case EXYNOS_SRC_VPLL:
338 sclk = exynos5_get_pll_clk(VPLL);
339 break;
340 default:
341 return 0;
342 }
343
344 /* Ratio clock division for this peripheral */
345 sub_div = (div >> bit_info->div_bit) & 0xf;
346 sub_clk = sclk / (sub_div + 1);
347
348 /* Pre-ratio clock division for SDMMC0 and 2 */
349 if (peripheral == PERIPH_ID_SDMMC0 || peripheral == PERIPH_ID_SDMMC2) {
350 div = (div >> bit_info->prediv_bit) & 0xff;
351 return sub_clk / (div + 1);
352 }
353
354 return sub_clk;
355}
356
357unsigned long clock_get_periph_rate(int peripheral)
358{
359 if (cpu_is_exynos5())
360 return exynos5_get_periph_rate(peripheral);
361 else
362 return 0;
363}
364
Rajeshwari Birjeac892d02013-12-26 09:44:21 +0530365/* exynos5420: return pll clock frequency */
366static unsigned long exynos5420_get_pll_clk(int pllreg)
367{
368 struct exynos5420_clock *clk =
369 (struct exynos5420_clock *)samsung_get_base_clock();
370 unsigned long r, k = 0;
371
372 switch (pllreg) {
373 case APLL:
374 r = readl(&clk->apll_con0);
375 break;
376 case MPLL:
377 r = readl(&clk->mpll_con0);
378 break;
379 case EPLL:
380 r = readl(&clk->epll_con0);
381 k = readl(&clk->epll_con1);
382 break;
383 case VPLL:
384 r = readl(&clk->vpll_con0);
385 k = readl(&clk->vpll_con1);
386 break;
387 case BPLL:
388 r = readl(&clk->bpll_con0);
389 break;
390 case RPLL:
391 r = readl(&clk->rpll_con0);
392 k = readl(&clk->rpll_con1);
393 break;
394 default:
395 printf("Unsupported PLL (%d)\n", pllreg);
396 return 0;
397 }
398
399 return exynos_get_pll_clk(pllreg, r, k);
400}
401
Chander Kashyap4131a772011-12-06 23:34:12 +0000402/* exynos4: return ARM clock frequency */
403static unsigned long exynos4_get_arm_clk(void)
Minkyu Kangb1b24682011-01-24 15:22:23 +0900404{
Chander Kashyap4131a772011-12-06 23:34:12 +0000405 struct exynos4_clock *clk =
406 (struct exynos4_clock *)samsung_get_base_clock();
Minkyu Kangb1b24682011-01-24 15:22:23 +0900407 unsigned long div;
Chander Kashyap3c7721f2011-12-18 22:56:44 +0000408 unsigned long armclk;
409 unsigned int core_ratio;
410 unsigned int core2_ratio;
Minkyu Kangb1b24682011-01-24 15:22:23 +0900411
412 div = readl(&clk->div_cpu0);
413
Chander Kashyap3c7721f2011-12-18 22:56:44 +0000414 /* CORE_RATIO: [2:0], CORE2_RATIO: [30:28] */
415 core_ratio = (div >> 0) & 0x7;
416 core2_ratio = (div >> 28) & 0x7;
Minkyu Kangb1b24682011-01-24 15:22:23 +0900417
Chander Kashyap3c7721f2011-12-18 22:56:44 +0000418 armclk = get_pll_clk(APLL) / (core_ratio + 1);
419 armclk /= (core2_ratio + 1);
Minkyu Kangb1b24682011-01-24 15:22:23 +0900420
Chander Kashyap3c7721f2011-12-18 22:56:44 +0000421 return armclk;
Minkyu Kangb1b24682011-01-24 15:22:23 +0900422}
423
Chander Kashyap400ab162012-10-07 01:43:17 +0000424/* exynos4x12: return ARM clock frequency */
425static unsigned long exynos4x12_get_arm_clk(void)
426{
427 struct exynos4x12_clock *clk =
428 (struct exynos4x12_clock *)samsung_get_base_clock();
429 unsigned long div;
430 unsigned long armclk;
431 unsigned int core_ratio;
432 unsigned int core2_ratio;
433
434 div = readl(&clk->div_cpu0);
435
436 /* CORE_RATIO: [2:0], CORE2_RATIO: [30:28] */
437 core_ratio = (div >> 0) & 0x7;
438 core2_ratio = (div >> 28) & 0x7;
439
440 armclk = get_pll_clk(APLL) / (core_ratio + 1);
441 armclk /= (core2_ratio + 1);
442
443 return armclk;
444}
445
Chander Kashyap34076a02012-02-05 23:01:46 +0000446/* exynos5: return ARM clock frequency */
447static unsigned long exynos5_get_arm_clk(void)
448{
449 struct exynos5_clock *clk =
450 (struct exynos5_clock *)samsung_get_base_clock();
451 unsigned long div;
452 unsigned long armclk;
453 unsigned int arm_ratio;
454 unsigned int arm2_ratio;
455
456 div = readl(&clk->div_cpu0);
457
458 /* ARM_RATIO: [2:0], ARM2_RATIO: [30:28] */
459 arm_ratio = (div >> 0) & 0x7;
460 arm2_ratio = (div >> 28) & 0x7;
461
462 armclk = get_pll_clk(APLL) / (arm_ratio + 1);
463 armclk /= (arm2_ratio + 1);
464
465 return armclk;
466}
467
Chander Kashyap4131a772011-12-06 23:34:12 +0000468/* exynos4: return pwm clock frequency */
469static unsigned long exynos4_get_pwm_clk(void)
Minkyu Kangb1b24682011-01-24 15:22:23 +0900470{
Chander Kashyap4131a772011-12-06 23:34:12 +0000471 struct exynos4_clock *clk =
472 (struct exynos4_clock *)samsung_get_base_clock();
Minkyu Kangb1b24682011-01-24 15:22:23 +0900473 unsigned long pclk, sclk;
474 unsigned int sel;
475 unsigned int ratio;
476
Minkyu Kang69b28242011-05-18 16:57:55 +0900477 if (s5p_get_cpu_rev() == 0) {
478 /*
479 * CLK_SRC_PERIL0
480 * PWM_SEL [27:24]
481 */
482 sel = readl(&clk->src_peril0);
483 sel = (sel >> 24) & 0xf;
Minkyu Kangb1b24682011-01-24 15:22:23 +0900484
Minkyu Kang69b28242011-05-18 16:57:55 +0900485 if (sel == 0x6)
486 sclk = get_pll_clk(MPLL);
487 else if (sel == 0x7)
488 sclk = get_pll_clk(EPLL);
489 else if (sel == 0x8)
490 sclk = get_pll_clk(VPLL);
491 else
492 return 0;
493
494 /*
495 * CLK_DIV_PERIL3
496 * PWM_RATIO [3:0]
497 */
498 ratio = readl(&clk->div_peril3);
499 ratio = ratio & 0xf;
500 } else if (s5p_get_cpu_rev() == 1) {
Minkyu Kangb1b24682011-01-24 15:22:23 +0900501 sclk = get_pll_clk(MPLL);
Minkyu Kang69b28242011-05-18 16:57:55 +0900502 ratio = 8;
503 } else
Minkyu Kangb1b24682011-01-24 15:22:23 +0900504 return 0;
505
Minkyu Kangb1b24682011-01-24 15:22:23 +0900506 pclk = sclk / (ratio + 1);
507
508 return pclk;
509}
510
Chander Kashyap400ab162012-10-07 01:43:17 +0000511/* exynos4x12: return pwm clock frequency */
512static unsigned long exynos4x12_get_pwm_clk(void)
513{
514 unsigned long pclk, sclk;
515 unsigned int ratio;
516
517 sclk = get_pll_clk(MPLL);
518 ratio = 8;
519
520 pclk = sclk / (ratio + 1);
521
522 return pclk;
523}
524
Rajeshwari Birjeac892d02013-12-26 09:44:21 +0530525/* exynos5420: return pwm clock frequency */
526static unsigned long exynos5420_get_pwm_clk(void)
527{
528 struct exynos5420_clock *clk =
529 (struct exynos5420_clock *)samsung_get_base_clock();
530 unsigned long pclk, sclk;
531 unsigned int ratio;
532
533 /*
534 * CLK_DIV_PERIC0
535 * PWM_RATIO [31:28]
536 */
537 ratio = readl(&clk->div_peric0);
538 ratio = (ratio >> 28) & 0xf;
539 sclk = get_pll_clk(MPLL);
540
541 pclk = sclk / (ratio + 1);
542
543 return pclk;
544}
545
Chander Kashyap4131a772011-12-06 23:34:12 +0000546/* exynos4: return uart clock frequency */
547static unsigned long exynos4_get_uart_clk(int dev_index)
Minkyu Kangb1b24682011-01-24 15:22:23 +0900548{
Chander Kashyap4131a772011-12-06 23:34:12 +0000549 struct exynos4_clock *clk =
550 (struct exynos4_clock *)samsung_get_base_clock();
Minkyu Kangb1b24682011-01-24 15:22:23 +0900551 unsigned long uclk, sclk;
552 unsigned int sel;
553 unsigned int ratio;
554
555 /*
556 * CLK_SRC_PERIL0
557 * UART0_SEL [3:0]
558 * UART1_SEL [7:4]
559 * UART2_SEL [8:11]
560 * UART3_SEL [12:15]
561 * UART4_SEL [16:19]
562 * UART5_SEL [23:20]
563 */
564 sel = readl(&clk->src_peril0);
565 sel = (sel >> (dev_index << 2)) & 0xf;
566
567 if (sel == 0x6)
568 sclk = get_pll_clk(MPLL);
569 else if (sel == 0x7)
570 sclk = get_pll_clk(EPLL);
571 else if (sel == 0x8)
572 sclk = get_pll_clk(VPLL);
573 else
574 return 0;
575
576 /*
577 * CLK_DIV_PERIL0
578 * UART0_RATIO [3:0]
579 * UART1_RATIO [7:4]
580 * UART2_RATIO [8:11]
581 * UART3_RATIO [12:15]
582 * UART4_RATIO [16:19]
583 * UART5_RATIO [23:20]
584 */
585 ratio = readl(&clk->div_peril0);
586 ratio = (ratio >> (dev_index << 2)) & 0xf;
587
588 uclk = sclk / (ratio + 1);
589
590 return uclk;
591}
592
Chander Kashyap400ab162012-10-07 01:43:17 +0000593/* exynos4x12: return uart clock frequency */
594static unsigned long exynos4x12_get_uart_clk(int dev_index)
595{
596 struct exynos4x12_clock *clk =
597 (struct exynos4x12_clock *)samsung_get_base_clock();
598 unsigned long uclk, sclk;
599 unsigned int sel;
600 unsigned int ratio;
601
602 /*
603 * CLK_SRC_PERIL0
604 * UART0_SEL [3:0]
605 * UART1_SEL [7:4]
606 * UART2_SEL [8:11]
607 * UART3_SEL [12:15]
608 * UART4_SEL [16:19]
609 */
610 sel = readl(&clk->src_peril0);
611 sel = (sel >> (dev_index << 2)) & 0xf;
612
613 if (sel == 0x6)
614 sclk = get_pll_clk(MPLL);
615 else if (sel == 0x7)
616 sclk = get_pll_clk(EPLL);
617 else if (sel == 0x8)
618 sclk = get_pll_clk(VPLL);
619 else
620 return 0;
621
622 /*
623 * CLK_DIV_PERIL0
624 * UART0_RATIO [3:0]
625 * UART1_RATIO [7:4]
626 * UART2_RATIO [8:11]
627 * UART3_RATIO [12:15]
628 * UART4_RATIO [16:19]
629 */
630 ratio = readl(&clk->div_peril0);
631 ratio = (ratio >> (dev_index << 2)) & 0xf;
632
633 uclk = sclk / (ratio + 1);
634
635 return uclk;
636}
637
Chander Kashyap34076a02012-02-05 23:01:46 +0000638/* exynos5: return uart clock frequency */
639static unsigned long exynos5_get_uart_clk(int dev_index)
640{
641 struct exynos5_clock *clk =
642 (struct exynos5_clock *)samsung_get_base_clock();
643 unsigned long uclk, sclk;
644 unsigned int sel;
645 unsigned int ratio;
646
647 /*
648 * CLK_SRC_PERIC0
649 * UART0_SEL [3:0]
650 * UART1_SEL [7:4]
651 * UART2_SEL [8:11]
652 * UART3_SEL [12:15]
653 * UART4_SEL [16:19]
654 * UART5_SEL [23:20]
655 */
656 sel = readl(&clk->src_peric0);
657 sel = (sel >> (dev_index << 2)) & 0xf;
658
659 if (sel == 0x6)
660 sclk = get_pll_clk(MPLL);
661 else if (sel == 0x7)
662 sclk = get_pll_clk(EPLL);
663 else if (sel == 0x8)
664 sclk = get_pll_clk(VPLL);
665 else
666 return 0;
667
668 /*
669 * CLK_DIV_PERIC0
670 * UART0_RATIO [3:0]
671 * UART1_RATIO [7:4]
672 * UART2_RATIO [8:11]
673 * UART3_RATIO [12:15]
674 * UART4_RATIO [16:19]
675 * UART5_RATIO [23:20]
676 */
677 ratio = readl(&clk->div_peric0);
678 ratio = (ratio >> (dev_index << 2)) & 0xf;
679
680 uclk = sclk / (ratio + 1);
681
682 return uclk;
683}
684
Rajeshwari Birjeac892d02013-12-26 09:44:21 +0530685/* exynos5420: return uart clock frequency */
686static unsigned long exynos5420_get_uart_clk(int dev_index)
687{
688 struct exynos5420_clock *clk =
689 (struct exynos5420_clock *)samsung_get_base_clock();
690 unsigned long uclk, sclk;
691 unsigned int sel;
692 unsigned int ratio;
693
694 /*
695 * CLK_SRC_PERIC0
696 * UART0_SEL [6:4]
697 * UART1_SEL [10:8]
698 * UART2_SEL [14:12]
699 * UART3_SEL [18:16]
700 * generalised calculation as follows
701 * sel = (sel >> ((dev_index * 4) + 4)) & mask;
702 */
703 sel = readl(&clk->src_peric0);
704 sel = (sel >> ((dev_index * 4) + 4)) & 0x7;
705
706 if (sel == 0x3)
707 sclk = get_pll_clk(MPLL);
708 else if (sel == 0x6)
709 sclk = get_pll_clk(EPLL);
710 else if (sel == 0x7)
711 sclk = get_pll_clk(RPLL);
712 else
713 return 0;
714
715 /*
716 * CLK_DIV_PERIC0
717 * UART0_RATIO [11:8]
718 * UART1_RATIO [15:12]
719 * UART2_RATIO [19:16]
720 * UART3_RATIO [23:20]
721 * generalised calculation as follows
722 * ratio = (ratio >> ((dev_index * 4) + 8)) & mask;
723 */
724 ratio = readl(&clk->div_peric0);
725 ratio = (ratio >> ((dev_index * 4) + 8)) & 0xf;
726
727 uclk = sclk / (ratio + 1);
728
729 return uclk;
730}
731
Jaehoon Chung8788e062012-12-27 22:30:32 +0000732static unsigned long exynos4_get_mmc_clk(int dev_index)
733{
734 struct exynos4_clock *clk =
735 (struct exynos4_clock *)samsung_get_base_clock();
736 unsigned long uclk, sclk;
737 unsigned int sel, ratio, pre_ratio;
Amare1df6282013-04-27 11:42:56 +0530738 int shift = 0;
Jaehoon Chung8788e062012-12-27 22:30:32 +0000739
740 sel = readl(&clk->src_fsys);
741 sel = (sel >> (dev_index << 2)) & 0xf;
742
743 if (sel == 0x6)
744 sclk = get_pll_clk(MPLL);
745 else if (sel == 0x7)
746 sclk = get_pll_clk(EPLL);
747 else if (sel == 0x8)
748 sclk = get_pll_clk(VPLL);
749 else
750 return 0;
751
752 switch (dev_index) {
753 case 0:
754 case 1:
755 ratio = readl(&clk->div_fsys1);
756 pre_ratio = readl(&clk->div_fsys1);
757 break;
758 case 2:
759 case 3:
760 ratio = readl(&clk->div_fsys2);
761 pre_ratio = readl(&clk->div_fsys2);
762 break;
763 case 4:
764 ratio = readl(&clk->div_fsys3);
765 pre_ratio = readl(&clk->div_fsys3);
766 break;
767 default:
768 return 0;
769 }
770
771 if (dev_index == 1 || dev_index == 3)
772 shift = 16;
773
774 ratio = (ratio >> shift) & 0xf;
775 pre_ratio = (pre_ratio >> (shift + 8)) & 0xff;
776 uclk = (sclk / (ratio + 1)) / (pre_ratio + 1);
777
778 return uclk;
779}
780
781static unsigned long exynos5_get_mmc_clk(int dev_index)
782{
783 struct exynos5_clock *clk =
784 (struct exynos5_clock *)samsung_get_base_clock();
785 unsigned long uclk, sclk;
786 unsigned int sel, ratio, pre_ratio;
Amare1df6282013-04-27 11:42:56 +0530787 int shift = 0;
Jaehoon Chung8788e062012-12-27 22:30:32 +0000788
789 sel = readl(&clk->src_fsys);
790 sel = (sel >> (dev_index << 2)) & 0xf;
791
792 if (sel == 0x6)
793 sclk = get_pll_clk(MPLL);
794 else if (sel == 0x7)
795 sclk = get_pll_clk(EPLL);
796 else if (sel == 0x8)
797 sclk = get_pll_clk(VPLL);
798 else
799 return 0;
800
801 switch (dev_index) {
802 case 0:
803 case 1:
804 ratio = readl(&clk->div_fsys1);
805 pre_ratio = readl(&clk->div_fsys1);
806 break;
807 case 2:
808 case 3:
809 ratio = readl(&clk->div_fsys2);
810 pre_ratio = readl(&clk->div_fsys2);
811 break;
812 default:
813 return 0;
814 }
815
816 if (dev_index == 1 || dev_index == 3)
817 shift = 16;
818
819 ratio = (ratio >> shift) & 0xf;
820 pre_ratio = (pre_ratio >> (shift + 8)) & 0xff;
821 uclk = (sclk / (ratio + 1)) / (pre_ratio + 1);
822
823 return uclk;
824}
825
Rajeshwari Birjeac892d02013-12-26 09:44:21 +0530826static unsigned long exynos5420_get_mmc_clk(int dev_index)
827{
828 struct exynos5420_clock *clk =
829 (struct exynos5420_clock *)samsung_get_base_clock();
830 unsigned long uclk, sclk;
831 unsigned int sel, ratio;
832
833 /*
834 * CLK_SRC_FSYS
835 * MMC0_SEL [10:8]
836 * MMC1_SEL [14:12]
837 * MMC2_SEL [18:16]
838 * generalised calculation as follows
839 * sel = (sel >> ((dev_index * 4) + 8)) & mask
840 */
841 sel = readl(&clk->src_fsys);
842 sel = (sel >> ((dev_index * 4) + 8)) & 0x7;
843
844 if (sel == 0x3)
845 sclk = get_pll_clk(MPLL);
846 else if (sel == 0x6)
847 sclk = get_pll_clk(EPLL);
848 else
849 return 0;
850
851 /*
852 * CLK_DIV_FSYS1
853 * MMC0_RATIO [9:0]
854 * MMC1_RATIO [19:10]
855 * MMC2_RATIO [29:20]
856 * generalised calculation as follows
857 * ratio = (ratio >> (dev_index * 10)) & mask
858 */
859 ratio = readl(&clk->div_fsys1);
860 ratio = (ratio >> (dev_index * 10)) & 0x3ff;
861
862 uclk = (sclk / (ratio + 1));
863
864 return uclk;
865}
866
Chander Kashyap4131a772011-12-06 23:34:12 +0000867/* exynos4: set the mmc clock */
868static void exynos4_set_mmc_clk(int dev_index, unsigned int div)
Jaehoon Chung9a772212011-05-17 21:19:17 +0000869{
Chander Kashyap4131a772011-12-06 23:34:12 +0000870 struct exynos4_clock *clk =
871 (struct exynos4_clock *)samsung_get_base_clock();
Jaehoon Chungd2c83242014-05-16 13:59:50 +0900872 unsigned int addr, clear_bit, set_bit;
Jaehoon Chung9a772212011-05-17 21:19:17 +0000873
874 /*
875 * CLK_DIV_FSYS1
876 * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24]
877 * CLK_DIV_FSYS2
878 * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24]
Jaehoon Chung29fe8c52012-12-27 22:30:33 +0000879 * CLK_DIV_FSYS3
Jaehoon Chungd2c83242014-05-16 13:59:50 +0900880 * MMC4_RATIO [3:0]
Jaehoon Chung9a772212011-05-17 21:19:17 +0000881 */
882 if (dev_index < 2) {
883 addr = (unsigned int)&clk->div_fsys1;
Jaehoon Chungd2c83242014-05-16 13:59:50 +0900884 clear_bit = MASK_PRE_RATIO(dev_index);
885 set_bit = SET_PRE_RATIO(dev_index, div);
886 } else if (dev_index == 4) {
Jaehoon Chung29fe8c52012-12-27 22:30:33 +0000887 addr = (unsigned int)&clk->div_fsys3;
888 dev_index -= 4;
Jaehoon Chungd2c83242014-05-16 13:59:50 +0900889 /* MMC4 is controlled with the MMC4_RATIO value */
890 clear_bit = MASK_RATIO(dev_index);
891 set_bit = SET_RATIO(dev_index, div);
Jaehoon Chung9a772212011-05-17 21:19:17 +0000892 } else {
893 addr = (unsigned int)&clk->div_fsys2;
894 dev_index -= 2;
Jaehoon Chungd2c83242014-05-16 13:59:50 +0900895 clear_bit = MASK_PRE_RATIO(dev_index);
896 set_bit = SET_PRE_RATIO(dev_index, div);
Jaehoon Chung9a772212011-05-17 21:19:17 +0000897 }
898
Jaehoon Chungd2c83242014-05-16 13:59:50 +0900899 clrsetbits_le32(addr, clear_bit, set_bit);
Jaehoon Chung9a772212011-05-17 21:19:17 +0000900}
901
Chander Kashyap34076a02012-02-05 23:01:46 +0000902/* exynos5: set the mmc clock */
903static void exynos5_set_mmc_clk(int dev_index, unsigned int div)
904{
905 struct exynos5_clock *clk =
906 (struct exynos5_clock *)samsung_get_base_clock();
907 unsigned int addr;
Chander Kashyap34076a02012-02-05 23:01:46 +0000908
909 /*
910 * CLK_DIV_FSYS1
911 * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24]
912 * CLK_DIV_FSYS2
913 * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24]
914 */
915 if (dev_index < 2) {
916 addr = (unsigned int)&clk->div_fsys1;
917 } else {
918 addr = (unsigned int)&clk->div_fsys2;
919 dev_index -= 2;
920 }
921
Inha Song4e558532014-02-06 14:20:12 +0900922 clrsetbits_le32(addr, 0xff << ((dev_index << 4) + 8),
923 (div & 0xff) << ((dev_index << 4) + 8));
Chander Kashyap34076a02012-02-05 23:01:46 +0000924}
925
Rajeshwari Birjeac892d02013-12-26 09:44:21 +0530926/* exynos5: set the mmc clock */
927static void exynos5420_set_mmc_clk(int dev_index, unsigned int div)
928{
929 struct exynos5420_clock *clk =
930 (struct exynos5420_clock *)samsung_get_base_clock();
931 unsigned int addr;
Inha Song4e558532014-02-06 14:20:12 +0900932 unsigned int shift;
Rajeshwari Birjeac892d02013-12-26 09:44:21 +0530933
934 /*
935 * CLK_DIV_FSYS1
936 * MMC0_RATIO [9:0]
937 * MMC1_RATIO [19:10]
938 * MMC2_RATIO [29:20]
939 */
940 addr = (unsigned int)&clk->div_fsys1;
941 shift = dev_index * 10;
942
Inha Song4e558532014-02-06 14:20:12 +0900943 clrsetbits_le32(addr, 0x3ff << shift, (div & 0x3ff) << shift);
Rajeshwari Birjeac892d02013-12-26 09:44:21 +0530944}
945
Donghwa Lee77ba1912012-04-05 19:36:12 +0000946/* get_lcd_clk: return lcd clock frequency */
947static unsigned long exynos4_get_lcd_clk(void)
948{
949 struct exynos4_clock *clk =
950 (struct exynos4_clock *)samsung_get_base_clock();
951 unsigned long pclk, sclk;
952 unsigned int sel;
953 unsigned int ratio;
954
955 /*
956 * CLK_SRC_LCD0
957 * FIMD0_SEL [3:0]
958 */
959 sel = readl(&clk->src_lcd0);
960 sel = sel & 0xf;
961
962 /*
963 * 0x6: SCLK_MPLL
964 * 0x7: SCLK_EPLL
965 * 0x8: SCLK_VPLL
966 */
967 if (sel == 0x6)
968 sclk = get_pll_clk(MPLL);
969 else if (sel == 0x7)
970 sclk = get_pll_clk(EPLL);
971 else if (sel == 0x8)
972 sclk = get_pll_clk(VPLL);
973 else
974 return 0;
975
976 /*
977 * CLK_DIV_LCD0
978 * FIMD0_RATIO [3:0]
979 */
980 ratio = readl(&clk->div_lcd0);
981 ratio = ratio & 0xf;
982
983 pclk = sclk / (ratio + 1);
984
985 return pclk;
986}
987
Donghwa Lee3c9d4532012-07-02 01:15:49 +0000988/* get_lcd_clk: return lcd clock frequency */
989static unsigned long exynos5_get_lcd_clk(void)
990{
991 struct exynos5_clock *clk =
992 (struct exynos5_clock *)samsung_get_base_clock();
993 unsigned long pclk, sclk;
994 unsigned int sel;
995 unsigned int ratio;
996
997 /*
998 * CLK_SRC_LCD0
999 * FIMD0_SEL [3:0]
1000 */
1001 sel = readl(&clk->src_disp1_0);
1002 sel = sel & 0xf;
1003
1004 /*
1005 * 0x6: SCLK_MPLL
1006 * 0x7: SCLK_EPLL
1007 * 0x8: SCLK_VPLL
1008 */
1009 if (sel == 0x6)
1010 sclk = get_pll_clk(MPLL);
1011 else if (sel == 0x7)
1012 sclk = get_pll_clk(EPLL);
1013 else if (sel == 0x8)
1014 sclk = get_pll_clk(VPLL);
1015 else
1016 return 0;
1017
1018 /*
1019 * CLK_DIV_LCD0
1020 * FIMD0_RATIO [3:0]
1021 */
1022 ratio = readl(&clk->div_disp1_0);
1023 ratio = ratio & 0xf;
1024
1025 pclk = sclk / (ratio + 1);
1026
1027 return pclk;
1028}
1029
Donghwa Lee77ba1912012-04-05 19:36:12 +00001030void exynos4_set_lcd_clk(void)
1031{
1032 struct exynos4_clock *clk =
1033 (struct exynos4_clock *)samsung_get_base_clock();
Donghwa Lee77ba1912012-04-05 19:36:12 +00001034
1035 /*
1036 * CLK_GATE_BLOCK
1037 * CLK_CAM [0]
1038 * CLK_TV [1]
1039 * CLK_MFC [2]
1040 * CLK_G3D [3]
1041 * CLK_LCD0 [4]
1042 * CLK_LCD1 [5]
1043 * CLK_GPS [7]
1044 */
Inha Song4e558532014-02-06 14:20:12 +09001045 setbits_le32(&clk->gate_block, 1 << 4);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001046
1047 /*
1048 * CLK_SRC_LCD0
1049 * FIMD0_SEL [3:0]
1050 * MDNIE0_SEL [7:4]
1051 * MDNIE_PWM0_SEL [8:11]
1052 * MIPI0_SEL [12:15]
1053 * set lcd0 src clock 0x6: SCLK_MPLL
1054 */
Inha Song4e558532014-02-06 14:20:12 +09001055 clrsetbits_le32(&clk->src_lcd0, 0xf, 0x6);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001056
1057 /*
1058 * CLK_GATE_IP_LCD0
1059 * CLK_FIMD0 [0]
1060 * CLK_MIE0 [1]
1061 * CLK_MDNIE0 [2]
1062 * CLK_DSIM0 [3]
1063 * CLK_SMMUFIMD0 [4]
1064 * CLK_PPMULCD0 [5]
1065 * Gating all clocks for FIMD0
1066 */
Inha Song4e558532014-02-06 14:20:12 +09001067 setbits_le32(&clk->gate_ip_lcd0, 1 << 0);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001068
1069 /*
1070 * CLK_DIV_LCD0
1071 * FIMD0_RATIO [3:0]
1072 * MDNIE0_RATIO [7:4]
1073 * MDNIE_PWM0_RATIO [11:8]
1074 * MDNIE_PWM_PRE_RATIO [15:12]
1075 * MIPI0_RATIO [19:16]
1076 * MIPI0_PRE_RATIO [23:20]
1077 * set fimd ratio
1078 */
Inha Song4e558532014-02-06 14:20:12 +09001079 clrsetbits_le32(&clk->div_lcd0, 0xf, 0x1);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001080}
1081
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001082void exynos5_set_lcd_clk(void)
1083{
1084 struct exynos5_clock *clk =
1085 (struct exynos5_clock *)samsung_get_base_clock();
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001086
1087 /*
1088 * CLK_GATE_BLOCK
1089 * CLK_CAM [0]
1090 * CLK_TV [1]
1091 * CLK_MFC [2]
1092 * CLK_G3D [3]
1093 * CLK_LCD0 [4]
1094 * CLK_LCD1 [5]
1095 * CLK_GPS [7]
1096 */
Inha Song4e558532014-02-06 14:20:12 +09001097 setbits_le32(&clk->gate_block, 1 << 4);
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001098
1099 /*
1100 * CLK_SRC_LCD0
1101 * FIMD0_SEL [3:0]
1102 * MDNIE0_SEL [7:4]
1103 * MDNIE_PWM0_SEL [8:11]
1104 * MIPI0_SEL [12:15]
1105 * set lcd0 src clock 0x6: SCLK_MPLL
1106 */
Inha Song4e558532014-02-06 14:20:12 +09001107 clrsetbits_le32(&clk->src_disp1_0, 0xf, 0x6);
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001108
1109 /*
1110 * CLK_GATE_IP_LCD0
1111 * CLK_FIMD0 [0]
1112 * CLK_MIE0 [1]
1113 * CLK_MDNIE0 [2]
1114 * CLK_DSIM0 [3]
1115 * CLK_SMMUFIMD0 [4]
1116 * CLK_PPMULCD0 [5]
1117 * Gating all clocks for FIMD0
1118 */
Inha Song4e558532014-02-06 14:20:12 +09001119 setbits_le32(&clk->gate_ip_disp1, 1 << 0);
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001120
1121 /*
1122 * CLK_DIV_LCD0
1123 * FIMD0_RATIO [3:0]
1124 * MDNIE0_RATIO [7:4]
1125 * MDNIE_PWM0_RATIO [11:8]
1126 * MDNIE_PWM_PRE_RATIO [15:12]
1127 * MIPI0_RATIO [19:16]
1128 * MIPI0_PRE_RATIO [23:20]
1129 * set fimd ratio
1130 */
Inha Song4e558532014-02-06 14:20:12 +09001131 clrsetbits_le32(&clk->div_disp1_0, 0xf, 0x0);
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001132}
1133
Donghwa Lee77ba1912012-04-05 19:36:12 +00001134void exynos4_set_mipi_clk(void)
1135{
1136 struct exynos4_clock *clk =
1137 (struct exynos4_clock *)samsung_get_base_clock();
Donghwa Lee77ba1912012-04-05 19:36:12 +00001138
1139 /*
1140 * CLK_SRC_LCD0
1141 * FIMD0_SEL [3:0]
1142 * MDNIE0_SEL [7:4]
1143 * MDNIE_PWM0_SEL [8:11]
1144 * MIPI0_SEL [12:15]
1145 * set mipi0 src clock 0x6: SCLK_MPLL
1146 */
Inha Song4e558532014-02-06 14:20:12 +09001147 clrsetbits_le32(&clk->src_lcd0, 0xf << 12, 0x6 << 12);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001148
1149 /*
1150 * CLK_SRC_MASK_LCD0
1151 * FIMD0_MASK [0]
1152 * MDNIE0_MASK [4]
1153 * MDNIE_PWM0_MASK [8]
1154 * MIPI0_MASK [12]
1155 * set src mask mipi0 0x1: Unmask
1156 */
Inha Song4e558532014-02-06 14:20:12 +09001157 setbits_le32(&clk->src_mask_lcd0, 0x1 << 12);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001158
1159 /*
1160 * CLK_GATE_IP_LCD0
1161 * CLK_FIMD0 [0]
1162 * CLK_MIE0 [1]
1163 * CLK_MDNIE0 [2]
1164 * CLK_DSIM0 [3]
1165 * CLK_SMMUFIMD0 [4]
1166 * CLK_PPMULCD0 [5]
1167 * Gating all clocks for MIPI0
1168 */
Inha Song4e558532014-02-06 14:20:12 +09001169 setbits_le32(&clk->gate_ip_lcd0, 1 << 3);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001170
1171 /*
1172 * CLK_DIV_LCD0
1173 * FIMD0_RATIO [3:0]
1174 * MDNIE0_RATIO [7:4]
1175 * MDNIE_PWM0_RATIO [11:8]
1176 * MDNIE_PWM_PRE_RATIO [15:12]
1177 * MIPI0_RATIO [19:16]
1178 * MIPI0_PRE_RATIO [23:20]
1179 * set mipi ratio
1180 */
Inha Song4e558532014-02-06 14:20:12 +09001181 clrsetbits_le32(&clk->div_lcd0, 0xf << 16, 0x1 << 16);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001182}
1183
Rajeshwari Shinde1c9412a2012-07-23 21:23:48 +00001184/*
1185 * I2C
1186 *
1187 * exynos5: obtaining the I2C clock
1188 */
1189static unsigned long exynos5_get_i2c_clk(void)
1190{
1191 struct exynos5_clock *clk =
1192 (struct exynos5_clock *)samsung_get_base_clock();
1193 unsigned long aclk_66, aclk_66_pre, sclk;
1194 unsigned int ratio;
1195
1196 sclk = get_pll_clk(MPLL);
1197
1198 ratio = (readl(&clk->div_top1)) >> 24;
1199 ratio &= 0x7;
1200 aclk_66_pre = sclk / (ratio + 1);
1201 ratio = readl(&clk->div_top0);
1202 ratio &= 0x7;
1203 aclk_66 = aclk_66_pre / (ratio + 1);
1204 return aclk_66;
1205}
1206
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001207int exynos5_set_epll_clk(unsigned long rate)
1208{
1209 unsigned int epll_con, epll_con_k;
1210 unsigned int i;
1211 unsigned int lockcnt;
1212 unsigned int start;
1213 struct exynos5_clock *clk =
1214 (struct exynos5_clock *)samsung_get_base_clock();
1215
1216 epll_con = readl(&clk->epll_con0);
1217 epll_con &= ~((EPLL_CON0_LOCK_DET_EN_MASK <<
1218 EPLL_CON0_LOCK_DET_EN_SHIFT) |
1219 EPLL_CON0_MDIV_MASK << EPLL_CON0_MDIV_SHIFT |
1220 EPLL_CON0_PDIV_MASK << EPLL_CON0_PDIV_SHIFT |
1221 EPLL_CON0_SDIV_MASK << EPLL_CON0_SDIV_SHIFT);
1222
1223 for (i = 0; i < ARRAY_SIZE(exynos5_epll_div); i++) {
1224 if (exynos5_epll_div[i].freq_out == rate)
1225 break;
1226 }
1227
1228 if (i == ARRAY_SIZE(exynos5_epll_div))
1229 return -1;
1230
1231 epll_con_k = exynos5_epll_div[i].k_dsm << 0;
1232 epll_con |= exynos5_epll_div[i].en_lock_det <<
1233 EPLL_CON0_LOCK_DET_EN_SHIFT;
1234 epll_con |= exynos5_epll_div[i].m_div << EPLL_CON0_MDIV_SHIFT;
1235 epll_con |= exynos5_epll_div[i].p_div << EPLL_CON0_PDIV_SHIFT;
1236 epll_con |= exynos5_epll_div[i].s_div << EPLL_CON0_SDIV_SHIFT;
1237
1238 /*
1239 * Required period ( in cycles) to genarate a stable clock output.
1240 * The maximum clock time can be up to 3000 * PDIV cycles of PLLs
1241 * frequency input (as per spec)
1242 */
1243 lockcnt = 3000 * exynos5_epll_div[i].p_div;
1244
1245 writel(lockcnt, &clk->epll_lock);
1246 writel(epll_con, &clk->epll_con0);
1247 writel(epll_con_k, &clk->epll_con1);
1248
1249 start = get_timer(0);
1250
1251 while (!(readl(&clk->epll_con0) &
1252 (0x1 << EXYNOS5_EPLLCON0_LOCKED_SHIFT))) {
1253 if (get_timer(start) > TIMEOUT_EPLL_LOCK) {
1254 debug("%s: Timeout waiting for EPLL lock\n", __func__);
1255 return -1;
1256 }
1257 }
1258 return 0;
1259}
1260
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301261int exynos5_set_i2s_clk_source(unsigned int i2s_id)
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001262{
1263 struct exynos5_clock *clk =
1264 (struct exynos5_clock *)samsung_get_base_clock();
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301265 unsigned int *audio_ass = (unsigned int *)samsung_get_base_audio_ass();
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001266
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301267 if (i2s_id == 0) {
1268 setbits_le32(&clk->src_top2, CLK_SRC_MOUT_EPLL);
1269 clrsetbits_le32(&clk->src_mau, AUDIO0_SEL_MASK,
1270 (CLK_SRC_SCLK_EPLL));
1271 setbits_le32(audio_ass, AUDIO_CLKMUX_ASS);
1272 } else if (i2s_id == 1) {
1273 clrsetbits_le32(&clk->src_peric1, AUDIO1_SEL_MASK,
1274 (CLK_SRC_SCLK_EPLL));
1275 } else {
1276 return -1;
1277 }
1278 return 0;
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001279}
1280
1281int exynos5_set_i2s_clk_prescaler(unsigned int src_frq,
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301282 unsigned int dst_frq,
1283 unsigned int i2s_id)
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001284{
1285 struct exynos5_clock *clk =
1286 (struct exynos5_clock *)samsung_get_base_clock();
1287 unsigned int div;
1288
1289 if ((dst_frq == 0) || (src_frq == 0)) {
1290 debug("%s: Invalid requency input for prescaler\n", __func__);
1291 debug("src frq = %d des frq = %d ", src_frq, dst_frq);
1292 return -1;
1293 }
1294
1295 div = (src_frq / dst_frq);
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301296 if (i2s_id == 0) {
1297 if (div > AUDIO_0_RATIO_MASK) {
1298 debug("%s: Frequency ratio is out of range\n",
1299 __func__);
1300 debug("src frq = %d des frq = %d ", src_frq, dst_frq);
1301 return -1;
1302 }
1303 clrsetbits_le32(&clk->div_mau, AUDIO_0_RATIO_MASK,
1304 (div & AUDIO_0_RATIO_MASK));
1305 } else if(i2s_id == 1) {
1306 if (div > AUDIO_1_RATIO_MASK) {
1307 debug("%s: Frequency ratio is out of range\n",
1308 __func__);
1309 debug("src frq = %d des frq = %d ", src_frq, dst_frq);
1310 return -1;
1311 }
1312 clrsetbits_le32(&clk->div_peric4, AUDIO_1_RATIO_MASK,
1313 (div & AUDIO_1_RATIO_MASK));
1314 } else {
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001315 return -1;
1316 }
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001317 return 0;
1318}
1319
Hatim RVe6365b62012-11-02 01:15:34 +00001320/**
1321 * Linearly searches for the most accurate main and fine stage clock scalars
1322 * (divisors) for a specified target frequency and scalar bit sizes by checking
1323 * all multiples of main_scalar_bits values. Will always return scalars up to or
1324 * slower than target.
1325 *
1326 * @param main_scalar_bits Number of main scalar bits, must be > 0 and < 32
1327 * @param fine_scalar_bits Number of fine scalar bits, must be > 0 and < 32
1328 * @param input_freq Clock frequency to be scaled in Hz
1329 * @param target_freq Desired clock frequency in Hz
1330 * @param best_fine_scalar Pointer to store the fine stage divisor
1331 *
1332 * @return best_main_scalar Main scalar for desired frequency or -1 if none
1333 * found
1334 */
1335static int clock_calc_best_scalar(unsigned int main_scaler_bits,
1336 unsigned int fine_scalar_bits, unsigned int input_rate,
1337 unsigned int target_rate, unsigned int *best_fine_scalar)
1338{
1339 int i;
1340 int best_main_scalar = -1;
1341 unsigned int best_error = target_rate;
1342 const unsigned int cap = (1 << fine_scalar_bits) - 1;
1343 const unsigned int loops = 1 << main_scaler_bits;
1344
1345 debug("Input Rate is %u, Target is %u, Cap is %u\n", input_rate,
1346 target_rate, cap);
1347
1348 assert(best_fine_scalar != NULL);
1349 assert(main_scaler_bits <= fine_scalar_bits);
1350
1351 *best_fine_scalar = 1;
1352
1353 if (input_rate == 0 || target_rate == 0)
1354 return -1;
1355
1356 if (target_rate >= input_rate)
1357 return 1;
1358
1359 for (i = 1; i <= loops; i++) {
1360 const unsigned int effective_div = max(min(input_rate / i /
1361 target_rate, cap), 1);
1362 const unsigned int effective_rate = input_rate / i /
1363 effective_div;
1364 const int error = target_rate - effective_rate;
1365
1366 debug("%d|effdiv:%u, effrate:%u, error:%d\n", i, effective_div,
1367 effective_rate, error);
1368
1369 if (error >= 0 && error <= best_error) {
1370 best_error = error;
1371 best_main_scalar = i;
1372 *best_fine_scalar = effective_div;
1373 }
1374 }
1375
1376 return best_main_scalar;
1377}
1378
1379static int exynos5_set_spi_clk(enum periph_id periph_id,
1380 unsigned int rate)
1381{
1382 struct exynos5_clock *clk =
1383 (struct exynos5_clock *)samsung_get_base_clock();
1384 int main;
1385 unsigned int fine;
1386 unsigned shift, pre_shift;
1387 unsigned mask = 0xff;
1388 u32 *reg;
1389
1390 main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine);
1391 if (main < 0) {
1392 debug("%s: Cannot set clock rate for periph %d",
1393 __func__, periph_id);
1394 return -1;
1395 }
1396 main = main - 1;
1397 fine = fine - 1;
1398
1399 switch (periph_id) {
1400 case PERIPH_ID_SPI0:
1401 reg = &clk->div_peric1;
1402 shift = 0;
1403 pre_shift = 8;
1404 break;
1405 case PERIPH_ID_SPI1:
1406 reg = &clk->div_peric1;
1407 shift = 16;
1408 pre_shift = 24;
1409 break;
1410 case PERIPH_ID_SPI2:
1411 reg = &clk->div_peric2;
1412 shift = 0;
1413 pre_shift = 8;
1414 break;
1415 case PERIPH_ID_SPI3:
1416 reg = &clk->sclk_div_isp;
1417 shift = 0;
1418 pre_shift = 4;
1419 break;
1420 case PERIPH_ID_SPI4:
1421 reg = &clk->sclk_div_isp;
1422 shift = 12;
1423 pre_shift = 16;
1424 break;
1425 default:
1426 debug("%s: Unsupported peripheral ID %d\n", __func__,
1427 periph_id);
1428 return -1;
1429 }
1430 clrsetbits_le32(reg, mask << shift, (main & mask) << shift);
1431 clrsetbits_le32(reg, mask << pre_shift, (fine & mask) << pre_shift);
1432
1433 return 0;
1434}
1435
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301436static int exynos5420_set_spi_clk(enum periph_id periph_id,
1437 unsigned int rate)
1438{
1439 struct exynos5420_clock *clk =
1440 (struct exynos5420_clock *)samsung_get_base_clock();
1441 int main;
1442 unsigned int fine;
1443 unsigned shift, pre_shift;
1444 unsigned div_mask = 0xf, pre_div_mask = 0xff;
1445 u32 *reg;
1446 u32 *pre_reg;
1447
1448 main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine);
1449 if (main < 0) {
1450 debug("%s: Cannot set clock rate for periph %d",
1451 __func__, periph_id);
1452 return -1;
1453 }
1454 main = main - 1;
1455 fine = fine - 1;
1456
1457 switch (periph_id) {
1458 case PERIPH_ID_SPI0:
1459 reg = &clk->div_peric1;
1460 shift = 20;
1461 pre_reg = &clk->div_peric4;
1462 pre_shift = 8;
1463 break;
1464 case PERIPH_ID_SPI1:
1465 reg = &clk->div_peric1;
1466 shift = 24;
1467 pre_reg = &clk->div_peric4;
1468 pre_shift = 16;
1469 break;
1470 case PERIPH_ID_SPI2:
1471 reg = &clk->div_peric1;
1472 shift = 28;
1473 pre_reg = &clk->div_peric4;
1474 pre_shift = 24;
1475 break;
1476 case PERIPH_ID_SPI3:
1477 reg = &clk->div_isp1;
1478 shift = 16;
1479 pre_reg = &clk->div_isp1;
1480 pre_shift = 0;
1481 break;
1482 case PERIPH_ID_SPI4:
1483 reg = &clk->div_isp1;
1484 shift = 20;
1485 pre_reg = &clk->div_isp1;
1486 pre_shift = 8;
1487 break;
1488 default:
1489 debug("%s: Unsupported peripheral ID %d\n", __func__,
1490 periph_id);
1491 return -1;
1492 }
1493
1494 clrsetbits_le32(reg, div_mask << shift, (main & div_mask) << shift);
1495 clrsetbits_le32(pre_reg, pre_div_mask << pre_shift,
1496 (fine & pre_div_mask) << pre_shift);
1497
1498 return 0;
1499}
1500
Piotr Wilczek01d589f2012-11-20 02:19:02 +00001501static unsigned long exynos4_get_i2c_clk(void)
1502{
1503 struct exynos4_clock *clk =
1504 (struct exynos4_clock *)samsung_get_base_clock();
1505 unsigned long sclk, aclk_100;
1506 unsigned int ratio;
1507
1508 sclk = get_pll_clk(APLL);
1509
1510 ratio = (readl(&clk->div_top)) >> 4;
1511 ratio &= 0xf;
1512 aclk_100 = sclk / (ratio + 1);
1513 return aclk_100;
Minkyu Kangb1b24682011-01-24 15:22:23 +09001514}
1515
1516unsigned long get_pll_clk(int pllreg)
1517{
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301518 if (cpu_is_exynos5()) {
1519 if (proid_is_exynos5420())
1520 return exynos5420_get_pll_clk(pllreg);
Chander Kashyap34076a02012-02-05 23:01:46 +00001521 return exynos5_get_pll_clk(pllreg);
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301522 } else {
Chander Kashyap400ab162012-10-07 01:43:17 +00001523 if (proid_is_exynos4412())
1524 return exynos4x12_get_pll_clk(pllreg);
Chander Kashyap34076a02012-02-05 23:01:46 +00001525 return exynos4_get_pll_clk(pllreg);
Chander Kashyap400ab162012-10-07 01:43:17 +00001526 }
Minkyu Kangb1b24682011-01-24 15:22:23 +09001527}
1528
1529unsigned long get_arm_clk(void)
1530{
Chander Kashyap34076a02012-02-05 23:01:46 +00001531 if (cpu_is_exynos5())
1532 return exynos5_get_arm_clk();
Chander Kashyap400ab162012-10-07 01:43:17 +00001533 else {
1534 if (proid_is_exynos4412())
1535 return exynos4x12_get_arm_clk();
Chander Kashyap34076a02012-02-05 23:01:46 +00001536 return exynos4_get_arm_clk();
Chander Kashyap400ab162012-10-07 01:43:17 +00001537 }
Minkyu Kangb1b24682011-01-24 15:22:23 +09001538}
1539
Rajeshwari Shinde1c9412a2012-07-23 21:23:48 +00001540unsigned long get_i2c_clk(void)
1541{
1542 if (cpu_is_exynos5()) {
1543 return exynos5_get_i2c_clk();
Piotr Wilczek01d589f2012-11-20 02:19:02 +00001544 } else if (cpu_is_exynos4()) {
1545 return exynos4_get_i2c_clk();
Rajeshwari Shinde1c9412a2012-07-23 21:23:48 +00001546 } else {
1547 debug("I2C clock is not set for this CPU\n");
1548 return 0;
1549 }
1550}
1551
Minkyu Kangb1b24682011-01-24 15:22:23 +09001552unsigned long get_pwm_clk(void)
1553{
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301554 if (cpu_is_exynos5()) {
1555 if (proid_is_exynos5420())
1556 return exynos5420_get_pwm_clk();
Padmavathi Vennabb714162013-03-28 04:32:23 +00001557 return clock_get_periph_rate(PERIPH_ID_PWM0);
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301558 } else {
Chander Kashyap400ab162012-10-07 01:43:17 +00001559 if (proid_is_exynos4412())
1560 return exynos4x12_get_pwm_clk();
Chander Kashyap34076a02012-02-05 23:01:46 +00001561 return exynos4_get_pwm_clk();
Chander Kashyap400ab162012-10-07 01:43:17 +00001562 }
Minkyu Kangb1b24682011-01-24 15:22:23 +09001563}
1564
1565unsigned long get_uart_clk(int dev_index)
1566{
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301567 if (cpu_is_exynos5()) {
1568 if (proid_is_exynos5420())
1569 return exynos5420_get_uart_clk(dev_index);
Chander Kashyap34076a02012-02-05 23:01:46 +00001570 return exynos5_get_uart_clk(dev_index);
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301571 } else {
Chander Kashyap400ab162012-10-07 01:43:17 +00001572 if (proid_is_exynos4412())
1573 return exynos4x12_get_uart_clk(dev_index);
Chander Kashyap34076a02012-02-05 23:01:46 +00001574 return exynos4_get_uart_clk(dev_index);
Chander Kashyap400ab162012-10-07 01:43:17 +00001575 }
Minkyu Kangb1b24682011-01-24 15:22:23 +09001576}
Jaehoon Chung9a772212011-05-17 21:19:17 +00001577
Jaehoon Chung8788e062012-12-27 22:30:32 +00001578unsigned long get_mmc_clk(int dev_index)
1579{
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301580 if (cpu_is_exynos5()) {
1581 if (proid_is_exynos5420())
1582 return exynos5420_get_mmc_clk(dev_index);
Jaehoon Chung8788e062012-12-27 22:30:32 +00001583 return exynos5_get_mmc_clk(dev_index);
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301584 } else {
Jaehoon Chung8788e062012-12-27 22:30:32 +00001585 return exynos4_get_mmc_clk(dev_index);
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301586 }
Jaehoon Chung8788e062012-12-27 22:30:32 +00001587}
1588
Jaehoon Chung9a772212011-05-17 21:19:17 +00001589void set_mmc_clk(int dev_index, unsigned int div)
1590{
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301591 if (cpu_is_exynos5()) {
1592 if (proid_is_exynos5420())
1593 exynos5420_set_mmc_clk(dev_index, div);
1594 else
1595 exynos5_set_mmc_clk(dev_index, div);
1596 } else {
Beomho Seo99660cc2014-05-16 13:59:47 +09001597 exynos4_set_mmc_clk(dev_index, div);
Chander Kashyap400ab162012-10-07 01:43:17 +00001598 }
Jaehoon Chung9a772212011-05-17 21:19:17 +00001599}
Donghwa Lee77ba1912012-04-05 19:36:12 +00001600
1601unsigned long get_lcd_clk(void)
1602{
1603 if (cpu_is_exynos4())
1604 return exynos4_get_lcd_clk();
1605 else
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001606 return exynos5_get_lcd_clk();
Donghwa Lee77ba1912012-04-05 19:36:12 +00001607}
1608
1609void set_lcd_clk(void)
1610{
1611 if (cpu_is_exynos4())
1612 exynos4_set_lcd_clk();
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001613 else
1614 exynos5_set_lcd_clk();
Donghwa Lee77ba1912012-04-05 19:36:12 +00001615}
1616
1617void set_mipi_clk(void)
1618{
1619 if (cpu_is_exynos4())
1620 exynos4_set_mipi_clk();
1621}
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001622
Hatim RVe6365b62012-11-02 01:15:34 +00001623int set_spi_clk(int periph_id, unsigned int rate)
1624{
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301625 if (cpu_is_exynos5()) {
1626 if (proid_is_exynos5420())
1627 return exynos5420_set_spi_clk(periph_id, rate);
Hatim RVe6365b62012-11-02 01:15:34 +00001628 return exynos5_set_spi_clk(periph_id, rate);
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301629 } else {
Hatim RVe6365b62012-11-02 01:15:34 +00001630 return 0;
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301631 }
Hatim RVe6365b62012-11-02 01:15:34 +00001632}
1633
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301634int set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq,
1635 unsigned int i2s_id)
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001636{
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001637 if (cpu_is_exynos5())
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301638 return exynos5_set_i2s_clk_prescaler(src_frq, dst_frq, i2s_id);
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001639 else
1640 return 0;
1641}
1642
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301643int set_i2s_clk_source(unsigned int i2s_id)
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001644{
1645 if (cpu_is_exynos5())
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301646 return exynos5_set_i2s_clk_source(i2s_id);
1647 else
1648 return 0;
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001649}
1650
1651int set_epll_clk(unsigned long rate)
1652{
1653 if (cpu_is_exynos5())
1654 return exynos5_set_epll_clk(rate);
1655 else
1656 return 0;
1657}