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