blob: 84a50470aaff265837d00099566bdb36d2d0cd86 [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 */
29static struct clk_bit_info clk_bit_info[PERIPH_ID_COUNT] = {
30 {0, 0, -1},
31 {4, 4, -1},
32 {8, 8, -1},
33 {12, 12, -1},
34 {0, 0, 8},
35 {4, 16, 24},
36 {8, 0, 8},
37 {12, 16, 24},
38 {-1, -1, -1},
39 {16, 0, 8},
40 {20, 16, 24},
41 {24, 0, 8},
42 {0, 0, 4},
43 {4, 12, 16},
44 {-1, -1, -1},
45 {-1, -1, -1},
46 {-1, 24, 0},
47 {-1, 24, 0},
48 {-1, 24, 0},
49 {-1, 24, 0},
50 {-1, 24, 0},
51 {-1, 24, 0},
52 {-1, 24, 0},
53 {-1, 24, 0},
54 {24, 0, -1},
55 {24, 0, -1},
56 {24, 0, -1},
57 {24, 0, -1},
58 {24, 0, -1},
59};
60
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
99 if (pllreg == EPLL) {
100 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;
120 else if (proid_is_exynos5250())
121 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
Chander Kashyap4131a772011-12-06 23:34:12 +0000365/* exynos4: return ARM clock frequency */
366static unsigned long exynos4_get_arm_clk(void)
Minkyu Kangb1b24682011-01-24 15:22:23 +0900367{
Chander Kashyap4131a772011-12-06 23:34:12 +0000368 struct exynos4_clock *clk =
369 (struct exynos4_clock *)samsung_get_base_clock();
Minkyu Kangb1b24682011-01-24 15:22:23 +0900370 unsigned long div;
Chander Kashyap3c7721f2011-12-18 22:56:44 +0000371 unsigned long armclk;
372 unsigned int core_ratio;
373 unsigned int core2_ratio;
Minkyu Kangb1b24682011-01-24 15:22:23 +0900374
375 div = readl(&clk->div_cpu0);
376
Chander Kashyap3c7721f2011-12-18 22:56:44 +0000377 /* CORE_RATIO: [2:0], CORE2_RATIO: [30:28] */
378 core_ratio = (div >> 0) & 0x7;
379 core2_ratio = (div >> 28) & 0x7;
Minkyu Kangb1b24682011-01-24 15:22:23 +0900380
Chander Kashyap3c7721f2011-12-18 22:56:44 +0000381 armclk = get_pll_clk(APLL) / (core_ratio + 1);
382 armclk /= (core2_ratio + 1);
Minkyu Kangb1b24682011-01-24 15:22:23 +0900383
Chander Kashyap3c7721f2011-12-18 22:56:44 +0000384 return armclk;
Minkyu Kangb1b24682011-01-24 15:22:23 +0900385}
386
Chander Kashyap400ab162012-10-07 01:43:17 +0000387/* exynos4x12: return ARM clock frequency */
388static unsigned long exynos4x12_get_arm_clk(void)
389{
390 struct exynos4x12_clock *clk =
391 (struct exynos4x12_clock *)samsung_get_base_clock();
392 unsigned long div;
393 unsigned long armclk;
394 unsigned int core_ratio;
395 unsigned int core2_ratio;
396
397 div = readl(&clk->div_cpu0);
398
399 /* CORE_RATIO: [2:0], CORE2_RATIO: [30:28] */
400 core_ratio = (div >> 0) & 0x7;
401 core2_ratio = (div >> 28) & 0x7;
402
403 armclk = get_pll_clk(APLL) / (core_ratio + 1);
404 armclk /= (core2_ratio + 1);
405
406 return armclk;
407}
408
Chander Kashyap34076a02012-02-05 23:01:46 +0000409/* exynos5: return ARM clock frequency */
410static unsigned long exynos5_get_arm_clk(void)
411{
412 struct exynos5_clock *clk =
413 (struct exynos5_clock *)samsung_get_base_clock();
414 unsigned long div;
415 unsigned long armclk;
416 unsigned int arm_ratio;
417 unsigned int arm2_ratio;
418
419 div = readl(&clk->div_cpu0);
420
421 /* ARM_RATIO: [2:0], ARM2_RATIO: [30:28] */
422 arm_ratio = (div >> 0) & 0x7;
423 arm2_ratio = (div >> 28) & 0x7;
424
425 armclk = get_pll_clk(APLL) / (arm_ratio + 1);
426 armclk /= (arm2_ratio + 1);
427
428 return armclk;
429}
430
Chander Kashyap4131a772011-12-06 23:34:12 +0000431/* exynos4: return pwm clock frequency */
432static unsigned long exynos4_get_pwm_clk(void)
Minkyu Kangb1b24682011-01-24 15:22:23 +0900433{
Chander Kashyap4131a772011-12-06 23:34:12 +0000434 struct exynos4_clock *clk =
435 (struct exynos4_clock *)samsung_get_base_clock();
Minkyu Kangb1b24682011-01-24 15:22:23 +0900436 unsigned long pclk, sclk;
437 unsigned int sel;
438 unsigned int ratio;
439
Minkyu Kang69b28242011-05-18 16:57:55 +0900440 if (s5p_get_cpu_rev() == 0) {
441 /*
442 * CLK_SRC_PERIL0
443 * PWM_SEL [27:24]
444 */
445 sel = readl(&clk->src_peril0);
446 sel = (sel >> 24) & 0xf;
Minkyu Kangb1b24682011-01-24 15:22:23 +0900447
Minkyu Kang69b28242011-05-18 16:57:55 +0900448 if (sel == 0x6)
449 sclk = get_pll_clk(MPLL);
450 else if (sel == 0x7)
451 sclk = get_pll_clk(EPLL);
452 else if (sel == 0x8)
453 sclk = get_pll_clk(VPLL);
454 else
455 return 0;
456
457 /*
458 * CLK_DIV_PERIL3
459 * PWM_RATIO [3:0]
460 */
461 ratio = readl(&clk->div_peril3);
462 ratio = ratio & 0xf;
463 } else if (s5p_get_cpu_rev() == 1) {
Minkyu Kangb1b24682011-01-24 15:22:23 +0900464 sclk = get_pll_clk(MPLL);
Minkyu Kang69b28242011-05-18 16:57:55 +0900465 ratio = 8;
466 } else
Minkyu Kangb1b24682011-01-24 15:22:23 +0900467 return 0;
468
Minkyu Kangb1b24682011-01-24 15:22:23 +0900469 pclk = sclk / (ratio + 1);
470
471 return pclk;
472}
473
Chander Kashyap400ab162012-10-07 01:43:17 +0000474/* exynos4x12: return pwm clock frequency */
475static unsigned long exynos4x12_get_pwm_clk(void)
476{
477 unsigned long pclk, sclk;
478 unsigned int ratio;
479
480 sclk = get_pll_clk(MPLL);
481 ratio = 8;
482
483 pclk = sclk / (ratio + 1);
484
485 return pclk;
486}
487
Chander Kashyap4131a772011-12-06 23:34:12 +0000488/* exynos4: return uart clock frequency */
489static unsigned long exynos4_get_uart_clk(int dev_index)
Minkyu Kangb1b24682011-01-24 15:22:23 +0900490{
Chander Kashyap4131a772011-12-06 23:34:12 +0000491 struct exynos4_clock *clk =
492 (struct exynos4_clock *)samsung_get_base_clock();
Minkyu Kangb1b24682011-01-24 15:22:23 +0900493 unsigned long uclk, sclk;
494 unsigned int sel;
495 unsigned int ratio;
496
497 /*
498 * CLK_SRC_PERIL0
499 * UART0_SEL [3:0]
500 * UART1_SEL [7:4]
501 * UART2_SEL [8:11]
502 * UART3_SEL [12:15]
503 * UART4_SEL [16:19]
504 * UART5_SEL [23:20]
505 */
506 sel = readl(&clk->src_peril0);
507 sel = (sel >> (dev_index << 2)) & 0xf;
508
509 if (sel == 0x6)
510 sclk = get_pll_clk(MPLL);
511 else if (sel == 0x7)
512 sclk = get_pll_clk(EPLL);
513 else if (sel == 0x8)
514 sclk = get_pll_clk(VPLL);
515 else
516 return 0;
517
518 /*
519 * CLK_DIV_PERIL0
520 * UART0_RATIO [3:0]
521 * UART1_RATIO [7:4]
522 * UART2_RATIO [8:11]
523 * UART3_RATIO [12:15]
524 * UART4_RATIO [16:19]
525 * UART5_RATIO [23:20]
526 */
527 ratio = readl(&clk->div_peril0);
528 ratio = (ratio >> (dev_index << 2)) & 0xf;
529
530 uclk = sclk / (ratio + 1);
531
532 return uclk;
533}
534
Chander Kashyap400ab162012-10-07 01:43:17 +0000535/* exynos4x12: return uart clock frequency */
536static unsigned long exynos4x12_get_uart_clk(int dev_index)
537{
538 struct exynos4x12_clock *clk =
539 (struct exynos4x12_clock *)samsung_get_base_clock();
540 unsigned long uclk, sclk;
541 unsigned int sel;
542 unsigned int ratio;
543
544 /*
545 * CLK_SRC_PERIL0
546 * UART0_SEL [3:0]
547 * UART1_SEL [7:4]
548 * UART2_SEL [8:11]
549 * UART3_SEL [12:15]
550 * UART4_SEL [16:19]
551 */
552 sel = readl(&clk->src_peril0);
553 sel = (sel >> (dev_index << 2)) & 0xf;
554
555 if (sel == 0x6)
556 sclk = get_pll_clk(MPLL);
557 else if (sel == 0x7)
558 sclk = get_pll_clk(EPLL);
559 else if (sel == 0x8)
560 sclk = get_pll_clk(VPLL);
561 else
562 return 0;
563
564 /*
565 * CLK_DIV_PERIL0
566 * UART0_RATIO [3:0]
567 * UART1_RATIO [7:4]
568 * UART2_RATIO [8:11]
569 * UART3_RATIO [12:15]
570 * UART4_RATIO [16:19]
571 */
572 ratio = readl(&clk->div_peril0);
573 ratio = (ratio >> (dev_index << 2)) & 0xf;
574
575 uclk = sclk / (ratio + 1);
576
577 return uclk;
578}
579
Chander Kashyap34076a02012-02-05 23:01:46 +0000580/* exynos5: return uart clock frequency */
581static unsigned long exynos5_get_uart_clk(int dev_index)
582{
583 struct exynos5_clock *clk =
584 (struct exynos5_clock *)samsung_get_base_clock();
585 unsigned long uclk, sclk;
586 unsigned int sel;
587 unsigned int ratio;
588
589 /*
590 * CLK_SRC_PERIC0
591 * UART0_SEL [3:0]
592 * UART1_SEL [7:4]
593 * UART2_SEL [8:11]
594 * UART3_SEL [12:15]
595 * UART4_SEL [16:19]
596 * UART5_SEL [23:20]
597 */
598 sel = readl(&clk->src_peric0);
599 sel = (sel >> (dev_index << 2)) & 0xf;
600
601 if (sel == 0x6)
602 sclk = get_pll_clk(MPLL);
603 else if (sel == 0x7)
604 sclk = get_pll_clk(EPLL);
605 else if (sel == 0x8)
606 sclk = get_pll_clk(VPLL);
607 else
608 return 0;
609
610 /*
611 * CLK_DIV_PERIC0
612 * UART0_RATIO [3:0]
613 * UART1_RATIO [7:4]
614 * UART2_RATIO [8:11]
615 * UART3_RATIO [12:15]
616 * UART4_RATIO [16:19]
617 * UART5_RATIO [23:20]
618 */
619 ratio = readl(&clk->div_peric0);
620 ratio = (ratio >> (dev_index << 2)) & 0xf;
621
622 uclk = sclk / (ratio + 1);
623
624 return uclk;
625}
626
Jaehoon Chung8788e062012-12-27 22:30:32 +0000627static unsigned long exynos4_get_mmc_clk(int dev_index)
628{
629 struct exynos4_clock *clk =
630 (struct exynos4_clock *)samsung_get_base_clock();
631 unsigned long uclk, sclk;
632 unsigned int sel, ratio, pre_ratio;
Amare1df6282013-04-27 11:42:56 +0530633 int shift = 0;
Jaehoon Chung8788e062012-12-27 22:30:32 +0000634
635 sel = readl(&clk->src_fsys);
636 sel = (sel >> (dev_index << 2)) & 0xf;
637
638 if (sel == 0x6)
639 sclk = get_pll_clk(MPLL);
640 else if (sel == 0x7)
641 sclk = get_pll_clk(EPLL);
642 else if (sel == 0x8)
643 sclk = get_pll_clk(VPLL);
644 else
645 return 0;
646
647 switch (dev_index) {
648 case 0:
649 case 1:
650 ratio = readl(&clk->div_fsys1);
651 pre_ratio = readl(&clk->div_fsys1);
652 break;
653 case 2:
654 case 3:
655 ratio = readl(&clk->div_fsys2);
656 pre_ratio = readl(&clk->div_fsys2);
657 break;
658 case 4:
659 ratio = readl(&clk->div_fsys3);
660 pre_ratio = readl(&clk->div_fsys3);
661 break;
662 default:
663 return 0;
664 }
665
666 if (dev_index == 1 || dev_index == 3)
667 shift = 16;
668
669 ratio = (ratio >> shift) & 0xf;
670 pre_ratio = (pre_ratio >> (shift + 8)) & 0xff;
671 uclk = (sclk / (ratio + 1)) / (pre_ratio + 1);
672
673 return uclk;
674}
675
676static unsigned long exynos5_get_mmc_clk(int dev_index)
677{
678 struct exynos5_clock *clk =
679 (struct exynos5_clock *)samsung_get_base_clock();
680 unsigned long uclk, sclk;
681 unsigned int sel, ratio, pre_ratio;
Amare1df6282013-04-27 11:42:56 +0530682 int shift = 0;
Jaehoon Chung8788e062012-12-27 22:30:32 +0000683
684 sel = readl(&clk->src_fsys);
685 sel = (sel >> (dev_index << 2)) & 0xf;
686
687 if (sel == 0x6)
688 sclk = get_pll_clk(MPLL);
689 else if (sel == 0x7)
690 sclk = get_pll_clk(EPLL);
691 else if (sel == 0x8)
692 sclk = get_pll_clk(VPLL);
693 else
694 return 0;
695
696 switch (dev_index) {
697 case 0:
698 case 1:
699 ratio = readl(&clk->div_fsys1);
700 pre_ratio = readl(&clk->div_fsys1);
701 break;
702 case 2:
703 case 3:
704 ratio = readl(&clk->div_fsys2);
705 pre_ratio = readl(&clk->div_fsys2);
706 break;
707 default:
708 return 0;
709 }
710
711 if (dev_index == 1 || dev_index == 3)
712 shift = 16;
713
714 ratio = (ratio >> shift) & 0xf;
715 pre_ratio = (pre_ratio >> (shift + 8)) & 0xff;
716 uclk = (sclk / (ratio + 1)) / (pre_ratio + 1);
717
718 return uclk;
719}
720
Chander Kashyap4131a772011-12-06 23:34:12 +0000721/* exynos4: set the mmc clock */
722static void exynos4_set_mmc_clk(int dev_index, unsigned int div)
Jaehoon Chung9a772212011-05-17 21:19:17 +0000723{
Chander Kashyap4131a772011-12-06 23:34:12 +0000724 struct exynos4_clock *clk =
725 (struct exynos4_clock *)samsung_get_base_clock();
Jaehoon Chung9a772212011-05-17 21:19:17 +0000726 unsigned int addr;
727 unsigned int val;
728
729 /*
730 * CLK_DIV_FSYS1
731 * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24]
732 * CLK_DIV_FSYS2
733 * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24]
Jaehoon Chung29fe8c52012-12-27 22:30:33 +0000734 * CLK_DIV_FSYS3
735 * MMC4_PRE_RATIO [15:8]
Jaehoon Chung9a772212011-05-17 21:19:17 +0000736 */
737 if (dev_index < 2) {
738 addr = (unsigned int)&clk->div_fsys1;
Jaehoon Chung29fe8c52012-12-27 22:30:33 +0000739 } else if (dev_index == 4) {
740 addr = (unsigned int)&clk->div_fsys3;
741 dev_index -= 4;
Jaehoon Chung9a772212011-05-17 21:19:17 +0000742 } else {
743 addr = (unsigned int)&clk->div_fsys2;
744 dev_index -= 2;
745 }
746
747 val = readl(addr);
748 val &= ~(0xff << ((dev_index << 4) + 8));
749 val |= (div & 0xff) << ((dev_index << 4) + 8);
750 writel(val, addr);
751}
752
Chander Kashyap400ab162012-10-07 01:43:17 +0000753/* exynos4x12: set the mmc clock */
754static void exynos4x12_set_mmc_clk(int dev_index, unsigned int div)
755{
756 struct exynos4x12_clock *clk =
757 (struct exynos4x12_clock *)samsung_get_base_clock();
758 unsigned int addr;
759 unsigned int val;
760
761 /*
762 * CLK_DIV_FSYS1
763 * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24]
764 * CLK_DIV_FSYS2
765 * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24]
766 */
767 if (dev_index < 2) {
768 addr = (unsigned int)&clk->div_fsys1;
769 } else {
770 addr = (unsigned int)&clk->div_fsys2;
771 dev_index -= 2;
772 }
773
774 val = readl(addr);
775 val &= ~(0xff << ((dev_index << 4) + 8));
776 val |= (div & 0xff) << ((dev_index << 4) + 8);
777 writel(val, addr);
778}
779
Chander Kashyap34076a02012-02-05 23:01:46 +0000780/* exynos5: set the mmc clock */
781static void exynos5_set_mmc_clk(int dev_index, unsigned int div)
782{
783 struct exynos5_clock *clk =
784 (struct exynos5_clock *)samsung_get_base_clock();
785 unsigned int addr;
786 unsigned int val;
787
788 /*
789 * CLK_DIV_FSYS1
790 * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24]
791 * CLK_DIV_FSYS2
792 * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24]
793 */
794 if (dev_index < 2) {
795 addr = (unsigned int)&clk->div_fsys1;
796 } else {
797 addr = (unsigned int)&clk->div_fsys2;
798 dev_index -= 2;
799 }
800
801 val = readl(addr);
802 val &= ~(0xff << ((dev_index << 4) + 8));
803 val |= (div & 0xff) << ((dev_index << 4) + 8);
804 writel(val, addr);
805}
806
Donghwa Lee77ba1912012-04-05 19:36:12 +0000807/* get_lcd_clk: return lcd clock frequency */
808static unsigned long exynos4_get_lcd_clk(void)
809{
810 struct exynos4_clock *clk =
811 (struct exynos4_clock *)samsung_get_base_clock();
812 unsigned long pclk, sclk;
813 unsigned int sel;
814 unsigned int ratio;
815
816 /*
817 * CLK_SRC_LCD0
818 * FIMD0_SEL [3:0]
819 */
820 sel = readl(&clk->src_lcd0);
821 sel = sel & 0xf;
822
823 /*
824 * 0x6: SCLK_MPLL
825 * 0x7: SCLK_EPLL
826 * 0x8: SCLK_VPLL
827 */
828 if (sel == 0x6)
829 sclk = get_pll_clk(MPLL);
830 else if (sel == 0x7)
831 sclk = get_pll_clk(EPLL);
832 else if (sel == 0x8)
833 sclk = get_pll_clk(VPLL);
834 else
835 return 0;
836
837 /*
838 * CLK_DIV_LCD0
839 * FIMD0_RATIO [3:0]
840 */
841 ratio = readl(&clk->div_lcd0);
842 ratio = ratio & 0xf;
843
844 pclk = sclk / (ratio + 1);
845
846 return pclk;
847}
848
Donghwa Lee3c9d4532012-07-02 01:15:49 +0000849/* get_lcd_clk: return lcd clock frequency */
850static unsigned long exynos5_get_lcd_clk(void)
851{
852 struct exynos5_clock *clk =
853 (struct exynos5_clock *)samsung_get_base_clock();
854 unsigned long pclk, sclk;
855 unsigned int sel;
856 unsigned int ratio;
857
858 /*
859 * CLK_SRC_LCD0
860 * FIMD0_SEL [3:0]
861 */
862 sel = readl(&clk->src_disp1_0);
863 sel = sel & 0xf;
864
865 /*
866 * 0x6: SCLK_MPLL
867 * 0x7: SCLK_EPLL
868 * 0x8: SCLK_VPLL
869 */
870 if (sel == 0x6)
871 sclk = get_pll_clk(MPLL);
872 else if (sel == 0x7)
873 sclk = get_pll_clk(EPLL);
874 else if (sel == 0x8)
875 sclk = get_pll_clk(VPLL);
876 else
877 return 0;
878
879 /*
880 * CLK_DIV_LCD0
881 * FIMD0_RATIO [3:0]
882 */
883 ratio = readl(&clk->div_disp1_0);
884 ratio = ratio & 0xf;
885
886 pclk = sclk / (ratio + 1);
887
888 return pclk;
889}
890
Donghwa Lee77ba1912012-04-05 19:36:12 +0000891void exynos4_set_lcd_clk(void)
892{
893 struct exynos4_clock *clk =
894 (struct exynos4_clock *)samsung_get_base_clock();
895 unsigned int cfg = 0;
896
897 /*
898 * CLK_GATE_BLOCK
899 * CLK_CAM [0]
900 * CLK_TV [1]
901 * CLK_MFC [2]
902 * CLK_G3D [3]
903 * CLK_LCD0 [4]
904 * CLK_LCD1 [5]
905 * CLK_GPS [7]
906 */
907 cfg = readl(&clk->gate_block);
908 cfg |= 1 << 4;
909 writel(cfg, &clk->gate_block);
910
911 /*
912 * CLK_SRC_LCD0
913 * FIMD0_SEL [3:0]
914 * MDNIE0_SEL [7:4]
915 * MDNIE_PWM0_SEL [8:11]
916 * MIPI0_SEL [12:15]
917 * set lcd0 src clock 0x6: SCLK_MPLL
918 */
919 cfg = readl(&clk->src_lcd0);
920 cfg &= ~(0xf);
921 cfg |= 0x6;
922 writel(cfg, &clk->src_lcd0);
923
924 /*
925 * CLK_GATE_IP_LCD0
926 * CLK_FIMD0 [0]
927 * CLK_MIE0 [1]
928 * CLK_MDNIE0 [2]
929 * CLK_DSIM0 [3]
930 * CLK_SMMUFIMD0 [4]
931 * CLK_PPMULCD0 [5]
932 * Gating all clocks for FIMD0
933 */
934 cfg = readl(&clk->gate_ip_lcd0);
935 cfg |= 1 << 0;
936 writel(cfg, &clk->gate_ip_lcd0);
937
938 /*
939 * CLK_DIV_LCD0
940 * FIMD0_RATIO [3:0]
941 * MDNIE0_RATIO [7:4]
942 * MDNIE_PWM0_RATIO [11:8]
943 * MDNIE_PWM_PRE_RATIO [15:12]
944 * MIPI0_RATIO [19:16]
945 * MIPI0_PRE_RATIO [23:20]
946 * set fimd ratio
947 */
948 cfg &= ~(0xf);
949 cfg |= 0x1;
950 writel(cfg, &clk->div_lcd0);
951}
952
Donghwa Lee3c9d4532012-07-02 01:15:49 +0000953void exynos5_set_lcd_clk(void)
954{
955 struct exynos5_clock *clk =
956 (struct exynos5_clock *)samsung_get_base_clock();
957 unsigned int cfg = 0;
958
959 /*
960 * CLK_GATE_BLOCK
961 * CLK_CAM [0]
962 * CLK_TV [1]
963 * CLK_MFC [2]
964 * CLK_G3D [3]
965 * CLK_LCD0 [4]
966 * CLK_LCD1 [5]
967 * CLK_GPS [7]
968 */
969 cfg = readl(&clk->gate_block);
970 cfg |= 1 << 4;
971 writel(cfg, &clk->gate_block);
972
973 /*
974 * CLK_SRC_LCD0
975 * FIMD0_SEL [3:0]
976 * MDNIE0_SEL [7:4]
977 * MDNIE_PWM0_SEL [8:11]
978 * MIPI0_SEL [12:15]
979 * set lcd0 src clock 0x6: SCLK_MPLL
980 */
981 cfg = readl(&clk->src_disp1_0);
982 cfg &= ~(0xf);
Ajay Kumar17dd8562013-01-08 20:42:23 +0000983 cfg |= 0x6;
Donghwa Lee3c9d4532012-07-02 01:15:49 +0000984 writel(cfg, &clk->src_disp1_0);
985
986 /*
987 * CLK_GATE_IP_LCD0
988 * CLK_FIMD0 [0]
989 * CLK_MIE0 [1]
990 * CLK_MDNIE0 [2]
991 * CLK_DSIM0 [3]
992 * CLK_SMMUFIMD0 [4]
993 * CLK_PPMULCD0 [5]
994 * Gating all clocks for FIMD0
995 */
996 cfg = readl(&clk->gate_ip_disp1);
997 cfg |= 1 << 0;
998 writel(cfg, &clk->gate_ip_disp1);
999
1000 /*
1001 * CLK_DIV_LCD0
1002 * FIMD0_RATIO [3:0]
1003 * MDNIE0_RATIO [7:4]
1004 * MDNIE_PWM0_RATIO [11:8]
1005 * MDNIE_PWM_PRE_RATIO [15:12]
1006 * MIPI0_RATIO [19:16]
1007 * MIPI0_PRE_RATIO [23:20]
1008 * set fimd ratio
1009 */
1010 cfg &= ~(0xf);
1011 cfg |= 0x0;
1012 writel(cfg, &clk->div_disp1_0);
1013}
1014
Donghwa Lee77ba1912012-04-05 19:36:12 +00001015void exynos4_set_mipi_clk(void)
1016{
1017 struct exynos4_clock *clk =
1018 (struct exynos4_clock *)samsung_get_base_clock();
1019 unsigned int cfg = 0;
1020
1021 /*
1022 * CLK_SRC_LCD0
1023 * FIMD0_SEL [3:0]
1024 * MDNIE0_SEL [7:4]
1025 * MDNIE_PWM0_SEL [8:11]
1026 * MIPI0_SEL [12:15]
1027 * set mipi0 src clock 0x6: SCLK_MPLL
1028 */
1029 cfg = readl(&clk->src_lcd0);
1030 cfg &= ~(0xf << 12);
1031 cfg |= (0x6 << 12);
1032 writel(cfg, &clk->src_lcd0);
1033
1034 /*
1035 * CLK_SRC_MASK_LCD0
1036 * FIMD0_MASK [0]
1037 * MDNIE0_MASK [4]
1038 * MDNIE_PWM0_MASK [8]
1039 * MIPI0_MASK [12]
1040 * set src mask mipi0 0x1: Unmask
1041 */
1042 cfg = readl(&clk->src_mask_lcd0);
1043 cfg |= (0x1 << 12);
1044 writel(cfg, &clk->src_mask_lcd0);
1045
1046 /*
1047 * CLK_GATE_IP_LCD0
1048 * CLK_FIMD0 [0]
1049 * CLK_MIE0 [1]
1050 * CLK_MDNIE0 [2]
1051 * CLK_DSIM0 [3]
1052 * CLK_SMMUFIMD0 [4]
1053 * CLK_PPMULCD0 [5]
1054 * Gating all clocks for MIPI0
1055 */
1056 cfg = readl(&clk->gate_ip_lcd0);
1057 cfg |= 1 << 3;
1058 writel(cfg, &clk->gate_ip_lcd0);
1059
1060 /*
1061 * CLK_DIV_LCD0
1062 * FIMD0_RATIO [3:0]
1063 * MDNIE0_RATIO [7:4]
1064 * MDNIE_PWM0_RATIO [11:8]
1065 * MDNIE_PWM_PRE_RATIO [15:12]
1066 * MIPI0_RATIO [19:16]
1067 * MIPI0_PRE_RATIO [23:20]
1068 * set mipi ratio
1069 */
1070 cfg &= ~(0xf << 16);
1071 cfg |= (0x1 << 16);
1072 writel(cfg, &clk->div_lcd0);
1073}
1074
Rajeshwari Shinde1c9412a2012-07-23 21:23:48 +00001075/*
1076 * I2C
1077 *
1078 * exynos5: obtaining the I2C clock
1079 */
1080static unsigned long exynos5_get_i2c_clk(void)
1081{
1082 struct exynos5_clock *clk =
1083 (struct exynos5_clock *)samsung_get_base_clock();
1084 unsigned long aclk_66, aclk_66_pre, sclk;
1085 unsigned int ratio;
1086
1087 sclk = get_pll_clk(MPLL);
1088
1089 ratio = (readl(&clk->div_top1)) >> 24;
1090 ratio &= 0x7;
1091 aclk_66_pre = sclk / (ratio + 1);
1092 ratio = readl(&clk->div_top0);
1093 ratio &= 0x7;
1094 aclk_66 = aclk_66_pre / (ratio + 1);
1095 return aclk_66;
1096}
1097
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001098int exynos5_set_epll_clk(unsigned long rate)
1099{
1100 unsigned int epll_con, epll_con_k;
1101 unsigned int i;
1102 unsigned int lockcnt;
1103 unsigned int start;
1104 struct exynos5_clock *clk =
1105 (struct exynos5_clock *)samsung_get_base_clock();
1106
1107 epll_con = readl(&clk->epll_con0);
1108 epll_con &= ~((EPLL_CON0_LOCK_DET_EN_MASK <<
1109 EPLL_CON0_LOCK_DET_EN_SHIFT) |
1110 EPLL_CON0_MDIV_MASK << EPLL_CON0_MDIV_SHIFT |
1111 EPLL_CON0_PDIV_MASK << EPLL_CON0_PDIV_SHIFT |
1112 EPLL_CON0_SDIV_MASK << EPLL_CON0_SDIV_SHIFT);
1113
1114 for (i = 0; i < ARRAY_SIZE(exynos5_epll_div); i++) {
1115 if (exynos5_epll_div[i].freq_out == rate)
1116 break;
1117 }
1118
1119 if (i == ARRAY_SIZE(exynos5_epll_div))
1120 return -1;
1121
1122 epll_con_k = exynos5_epll_div[i].k_dsm << 0;
1123 epll_con |= exynos5_epll_div[i].en_lock_det <<
1124 EPLL_CON0_LOCK_DET_EN_SHIFT;
1125 epll_con |= exynos5_epll_div[i].m_div << EPLL_CON0_MDIV_SHIFT;
1126 epll_con |= exynos5_epll_div[i].p_div << EPLL_CON0_PDIV_SHIFT;
1127 epll_con |= exynos5_epll_div[i].s_div << EPLL_CON0_SDIV_SHIFT;
1128
1129 /*
1130 * Required period ( in cycles) to genarate a stable clock output.
1131 * The maximum clock time can be up to 3000 * PDIV cycles of PLLs
1132 * frequency input (as per spec)
1133 */
1134 lockcnt = 3000 * exynos5_epll_div[i].p_div;
1135
1136 writel(lockcnt, &clk->epll_lock);
1137 writel(epll_con, &clk->epll_con0);
1138 writel(epll_con_k, &clk->epll_con1);
1139
1140 start = get_timer(0);
1141
1142 while (!(readl(&clk->epll_con0) &
1143 (0x1 << EXYNOS5_EPLLCON0_LOCKED_SHIFT))) {
1144 if (get_timer(start) > TIMEOUT_EPLL_LOCK) {
1145 debug("%s: Timeout waiting for EPLL lock\n", __func__);
1146 return -1;
1147 }
1148 }
1149 return 0;
1150}
1151
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301152int exynos5_set_i2s_clk_source(unsigned int i2s_id)
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001153{
1154 struct exynos5_clock *clk =
1155 (struct exynos5_clock *)samsung_get_base_clock();
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301156 unsigned int *audio_ass = (unsigned int *)samsung_get_base_audio_ass();
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001157
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301158 if (i2s_id == 0) {
1159 setbits_le32(&clk->src_top2, CLK_SRC_MOUT_EPLL);
1160 clrsetbits_le32(&clk->src_mau, AUDIO0_SEL_MASK,
1161 (CLK_SRC_SCLK_EPLL));
1162 setbits_le32(audio_ass, AUDIO_CLKMUX_ASS);
1163 } else if (i2s_id == 1) {
1164 clrsetbits_le32(&clk->src_peric1, AUDIO1_SEL_MASK,
1165 (CLK_SRC_SCLK_EPLL));
1166 } else {
1167 return -1;
1168 }
1169 return 0;
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001170}
1171
1172int exynos5_set_i2s_clk_prescaler(unsigned int src_frq,
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301173 unsigned int dst_frq,
1174 unsigned int i2s_id)
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001175{
1176 struct exynos5_clock *clk =
1177 (struct exynos5_clock *)samsung_get_base_clock();
1178 unsigned int div;
1179
1180 if ((dst_frq == 0) || (src_frq == 0)) {
1181 debug("%s: Invalid requency input for prescaler\n", __func__);
1182 debug("src frq = %d des frq = %d ", src_frq, dst_frq);
1183 return -1;
1184 }
1185
1186 div = (src_frq / dst_frq);
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301187 if (i2s_id == 0) {
1188 if (div > AUDIO_0_RATIO_MASK) {
1189 debug("%s: Frequency ratio is out of range\n",
1190 __func__);
1191 debug("src frq = %d des frq = %d ", src_frq, dst_frq);
1192 return -1;
1193 }
1194 clrsetbits_le32(&clk->div_mau, AUDIO_0_RATIO_MASK,
1195 (div & AUDIO_0_RATIO_MASK));
1196 } else if(i2s_id == 1) {
1197 if (div > AUDIO_1_RATIO_MASK) {
1198 debug("%s: Frequency ratio is out of range\n",
1199 __func__);
1200 debug("src frq = %d des frq = %d ", src_frq, dst_frq);
1201 return -1;
1202 }
1203 clrsetbits_le32(&clk->div_peric4, AUDIO_1_RATIO_MASK,
1204 (div & AUDIO_1_RATIO_MASK));
1205 } else {
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001206 return -1;
1207 }
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001208 return 0;
1209}
1210
Hatim RVe6365b62012-11-02 01:15:34 +00001211/**
1212 * Linearly searches for the most accurate main and fine stage clock scalars
1213 * (divisors) for a specified target frequency and scalar bit sizes by checking
1214 * all multiples of main_scalar_bits values. Will always return scalars up to or
1215 * slower than target.
1216 *
1217 * @param main_scalar_bits Number of main scalar bits, must be > 0 and < 32
1218 * @param fine_scalar_bits Number of fine scalar bits, must be > 0 and < 32
1219 * @param input_freq Clock frequency to be scaled in Hz
1220 * @param target_freq Desired clock frequency in Hz
1221 * @param best_fine_scalar Pointer to store the fine stage divisor
1222 *
1223 * @return best_main_scalar Main scalar for desired frequency or -1 if none
1224 * found
1225 */
1226static int clock_calc_best_scalar(unsigned int main_scaler_bits,
1227 unsigned int fine_scalar_bits, unsigned int input_rate,
1228 unsigned int target_rate, unsigned int *best_fine_scalar)
1229{
1230 int i;
1231 int best_main_scalar = -1;
1232 unsigned int best_error = target_rate;
1233 const unsigned int cap = (1 << fine_scalar_bits) - 1;
1234 const unsigned int loops = 1 << main_scaler_bits;
1235
1236 debug("Input Rate is %u, Target is %u, Cap is %u\n", input_rate,
1237 target_rate, cap);
1238
1239 assert(best_fine_scalar != NULL);
1240 assert(main_scaler_bits <= fine_scalar_bits);
1241
1242 *best_fine_scalar = 1;
1243
1244 if (input_rate == 0 || target_rate == 0)
1245 return -1;
1246
1247 if (target_rate >= input_rate)
1248 return 1;
1249
1250 for (i = 1; i <= loops; i++) {
1251 const unsigned int effective_div = max(min(input_rate / i /
1252 target_rate, cap), 1);
1253 const unsigned int effective_rate = input_rate / i /
1254 effective_div;
1255 const int error = target_rate - effective_rate;
1256
1257 debug("%d|effdiv:%u, effrate:%u, error:%d\n", i, effective_div,
1258 effective_rate, error);
1259
1260 if (error >= 0 && error <= best_error) {
1261 best_error = error;
1262 best_main_scalar = i;
1263 *best_fine_scalar = effective_div;
1264 }
1265 }
1266
1267 return best_main_scalar;
1268}
1269
1270static int exynos5_set_spi_clk(enum periph_id periph_id,
1271 unsigned int rate)
1272{
1273 struct exynos5_clock *clk =
1274 (struct exynos5_clock *)samsung_get_base_clock();
1275 int main;
1276 unsigned int fine;
1277 unsigned shift, pre_shift;
1278 unsigned mask = 0xff;
1279 u32 *reg;
1280
1281 main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine);
1282 if (main < 0) {
1283 debug("%s: Cannot set clock rate for periph %d",
1284 __func__, periph_id);
1285 return -1;
1286 }
1287 main = main - 1;
1288 fine = fine - 1;
1289
1290 switch (periph_id) {
1291 case PERIPH_ID_SPI0:
1292 reg = &clk->div_peric1;
1293 shift = 0;
1294 pre_shift = 8;
1295 break;
1296 case PERIPH_ID_SPI1:
1297 reg = &clk->div_peric1;
1298 shift = 16;
1299 pre_shift = 24;
1300 break;
1301 case PERIPH_ID_SPI2:
1302 reg = &clk->div_peric2;
1303 shift = 0;
1304 pre_shift = 8;
1305 break;
1306 case PERIPH_ID_SPI3:
1307 reg = &clk->sclk_div_isp;
1308 shift = 0;
1309 pre_shift = 4;
1310 break;
1311 case PERIPH_ID_SPI4:
1312 reg = &clk->sclk_div_isp;
1313 shift = 12;
1314 pre_shift = 16;
1315 break;
1316 default:
1317 debug("%s: Unsupported peripheral ID %d\n", __func__,
1318 periph_id);
1319 return -1;
1320 }
1321 clrsetbits_le32(reg, mask << shift, (main & mask) << shift);
1322 clrsetbits_le32(reg, mask << pre_shift, (fine & mask) << pre_shift);
1323
1324 return 0;
1325}
1326
Piotr Wilczek01d589f2012-11-20 02:19:02 +00001327static unsigned long exynos4_get_i2c_clk(void)
1328{
1329 struct exynos4_clock *clk =
1330 (struct exynos4_clock *)samsung_get_base_clock();
1331 unsigned long sclk, aclk_100;
1332 unsigned int ratio;
1333
1334 sclk = get_pll_clk(APLL);
1335
1336 ratio = (readl(&clk->div_top)) >> 4;
1337 ratio &= 0xf;
1338 aclk_100 = sclk / (ratio + 1);
1339 return aclk_100;
Minkyu Kangb1b24682011-01-24 15:22:23 +09001340}
1341
1342unsigned long get_pll_clk(int pllreg)
1343{
Chander Kashyap34076a02012-02-05 23:01:46 +00001344 if (cpu_is_exynos5())
1345 return exynos5_get_pll_clk(pllreg);
Chander Kashyap400ab162012-10-07 01:43:17 +00001346 else {
1347 if (proid_is_exynos4412())
1348 return exynos4x12_get_pll_clk(pllreg);
Chander Kashyap34076a02012-02-05 23:01:46 +00001349 return exynos4_get_pll_clk(pllreg);
Chander Kashyap400ab162012-10-07 01:43:17 +00001350 }
Minkyu Kangb1b24682011-01-24 15:22:23 +09001351}
1352
1353unsigned long get_arm_clk(void)
1354{
Chander Kashyap34076a02012-02-05 23:01:46 +00001355 if (cpu_is_exynos5())
1356 return exynos5_get_arm_clk();
Chander Kashyap400ab162012-10-07 01:43:17 +00001357 else {
1358 if (proid_is_exynos4412())
1359 return exynos4x12_get_arm_clk();
Chander Kashyap34076a02012-02-05 23:01:46 +00001360 return exynos4_get_arm_clk();
Chander Kashyap400ab162012-10-07 01:43:17 +00001361 }
Minkyu Kangb1b24682011-01-24 15:22:23 +09001362}
1363
Rajeshwari Shinde1c9412a2012-07-23 21:23:48 +00001364unsigned long get_i2c_clk(void)
1365{
1366 if (cpu_is_exynos5()) {
1367 return exynos5_get_i2c_clk();
Piotr Wilczek01d589f2012-11-20 02:19:02 +00001368 } else if (cpu_is_exynos4()) {
1369 return exynos4_get_i2c_clk();
Rajeshwari Shinde1c9412a2012-07-23 21:23:48 +00001370 } else {
1371 debug("I2C clock is not set for this CPU\n");
1372 return 0;
1373 }
1374}
1375
Minkyu Kangb1b24682011-01-24 15:22:23 +09001376unsigned long get_pwm_clk(void)
1377{
Chander Kashyap34076a02012-02-05 23:01:46 +00001378 if (cpu_is_exynos5())
Padmavathi Vennabb714162013-03-28 04:32:23 +00001379 return clock_get_periph_rate(PERIPH_ID_PWM0);
Chander Kashyap400ab162012-10-07 01:43:17 +00001380 else {
1381 if (proid_is_exynos4412())
1382 return exynos4x12_get_pwm_clk();
Chander Kashyap34076a02012-02-05 23:01:46 +00001383 return exynos4_get_pwm_clk();
Chander Kashyap400ab162012-10-07 01:43:17 +00001384 }
Minkyu Kangb1b24682011-01-24 15:22:23 +09001385}
1386
1387unsigned long get_uart_clk(int dev_index)
1388{
Chander Kashyap34076a02012-02-05 23:01:46 +00001389 if (cpu_is_exynos5())
1390 return exynos5_get_uart_clk(dev_index);
Chander Kashyap400ab162012-10-07 01:43:17 +00001391 else {
1392 if (proid_is_exynos4412())
1393 return exynos4x12_get_uart_clk(dev_index);
Chander Kashyap34076a02012-02-05 23:01:46 +00001394 return exynos4_get_uart_clk(dev_index);
Chander Kashyap400ab162012-10-07 01:43:17 +00001395 }
Minkyu Kangb1b24682011-01-24 15:22:23 +09001396}
Jaehoon Chung9a772212011-05-17 21:19:17 +00001397
Jaehoon Chung8788e062012-12-27 22:30:32 +00001398unsigned long get_mmc_clk(int dev_index)
1399{
1400 if (cpu_is_exynos5())
1401 return exynos5_get_mmc_clk(dev_index);
1402 else
1403 return exynos4_get_mmc_clk(dev_index);
1404}
1405
Jaehoon Chung9a772212011-05-17 21:19:17 +00001406void set_mmc_clk(int dev_index, unsigned int div)
1407{
Chander Kashyap34076a02012-02-05 23:01:46 +00001408 if (cpu_is_exynos5())
1409 exynos5_set_mmc_clk(dev_index, div);
Chander Kashyap400ab162012-10-07 01:43:17 +00001410 else {
1411 if (proid_is_exynos4412())
1412 exynos4x12_set_mmc_clk(dev_index, div);
Jaehoon Chungda914742013-12-02 14:25:33 +09001413 else
1414 exynos4_set_mmc_clk(dev_index, div);
Chander Kashyap400ab162012-10-07 01:43:17 +00001415 }
Jaehoon Chung9a772212011-05-17 21:19:17 +00001416}
Donghwa Lee77ba1912012-04-05 19:36:12 +00001417
1418unsigned long get_lcd_clk(void)
1419{
1420 if (cpu_is_exynos4())
1421 return exynos4_get_lcd_clk();
1422 else
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001423 return exynos5_get_lcd_clk();
Donghwa Lee77ba1912012-04-05 19:36:12 +00001424}
1425
1426void set_lcd_clk(void)
1427{
1428 if (cpu_is_exynos4())
1429 exynos4_set_lcd_clk();
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001430 else
1431 exynos5_set_lcd_clk();
Donghwa Lee77ba1912012-04-05 19:36:12 +00001432}
1433
1434void set_mipi_clk(void)
1435{
1436 if (cpu_is_exynos4())
1437 exynos4_set_mipi_clk();
1438}
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001439
Hatim RVe6365b62012-11-02 01:15:34 +00001440int set_spi_clk(int periph_id, unsigned int rate)
1441{
1442 if (cpu_is_exynos5())
1443 return exynos5_set_spi_clk(periph_id, rate);
1444 else
1445 return 0;
1446}
1447
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301448int set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq,
1449 unsigned int i2s_id)
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001450{
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001451 if (cpu_is_exynos5())
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301452 return exynos5_set_i2s_clk_prescaler(src_frq, dst_frq, i2s_id);
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001453 else
1454 return 0;
1455}
1456
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301457int set_i2s_clk_source(unsigned int i2s_id)
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001458{
1459 if (cpu_is_exynos5())
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301460 return exynos5_set_i2s_clk_source(i2s_id);
1461 else
1462 return 0;
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001463}
1464
1465int set_epll_clk(unsigned long rate)
1466{
1467 if (cpu_is_exynos5())
1468 return exynos5_set_epll_clk(rate);
1469 else
1470 return 0;
1471}