blob: 59d7dc87bdd4ea78d8ac03ccc655d9d4480fb05c [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 {
Akshay Saraswat3ad7ffc2015-02-04 15:59:59 +053023 enum periph_id id;
Padmavathi Venna37feb7b2013-03-28 04:32:21 +000024 int8_t src_bit;
25 int8_t div_bit;
26 int8_t prediv_bit;
27};
28
Akshay Saraswat3ad7ffc2015-02-04 15:59:59 +053029/* periph_id src_bit div_bit prediv_bit */
Akshay Saraswatd5072262015-02-04 16:00:01 +053030static struct clk_bit_info exynos5_bit_info[] = {
Akshay Saraswat3ad7ffc2015-02-04 15:59:59 +053031 {PERIPH_ID_UART0, 0, 0, -1},
32 {PERIPH_ID_UART1, 4, 4, -1},
33 {PERIPH_ID_UART2, 8, 8, -1},
34 {PERIPH_ID_UART3, 12, 12, -1},
35 {PERIPH_ID_I2C0, -1, 24, 0},
36 {PERIPH_ID_I2C1, -1, 24, 0},
37 {PERIPH_ID_I2C2, -1, 24, 0},
38 {PERIPH_ID_I2C3, -1, 24, 0},
39 {PERIPH_ID_I2C4, -1, 24, 0},
40 {PERIPH_ID_I2C5, -1, 24, 0},
41 {PERIPH_ID_I2C6, -1, 24, 0},
42 {PERIPH_ID_I2C7, -1, 24, 0},
43 {PERIPH_ID_SPI0, 16, 0, 8},
44 {PERIPH_ID_SPI1, 20, 16, 24},
45 {PERIPH_ID_SPI2, 24, 0, 8},
46 {PERIPH_ID_SDMMC0, 0, 0, 8},
47 {PERIPH_ID_SDMMC1, 4, 16, 24},
48 {PERIPH_ID_SDMMC2, 8, 0, 8},
49 {PERIPH_ID_SDMMC3, 12, 16, 24},
50 {PERIPH_ID_I2S0, 0, 0, 4},
51 {PERIPH_ID_I2S1, 4, 12, 16},
52 {PERIPH_ID_SPI3, 0, 0, 4},
53 {PERIPH_ID_SPI4, 4, 12, 16},
54 {PERIPH_ID_SDMMC4, 16, 0, 8},
55 {PERIPH_ID_PWM0, 24, 0, -1},
56 {PERIPH_ID_PWM1, 24, 0, -1},
57 {PERIPH_ID_PWM2, 24, 0, -1},
58 {PERIPH_ID_PWM3, 24, 0, -1},
59 {PERIPH_ID_PWM4, 24, 0, -1},
60
61 {PERIPH_ID_NONE, -1, -1, -1},
Padmavathi Venna37feb7b2013-03-28 04:32:21 +000062};
63
Akshay Saraswatd5072262015-02-04 16:00:01 +053064static struct clk_bit_info exynos542x_bit_info[] = {
65 {PERIPH_ID_UART0, 4, 8, -1},
66 {PERIPH_ID_UART1, 8, 12, -1},
67 {PERIPH_ID_UART2, 12, 16, -1},
68 {PERIPH_ID_UART3, 16, 20, -1},
69 {PERIPH_ID_I2C0, -1, 8, -1},
70 {PERIPH_ID_I2C1, -1, 8, -1},
71 {PERIPH_ID_I2C2, -1, 8, -1},
72 {PERIPH_ID_I2C3, -1, 8, -1},
73 {PERIPH_ID_I2C4, -1, 8, -1},
74 {PERIPH_ID_I2C5, -1, 8, -1},
75 {PERIPH_ID_I2C6, -1, 8, -1},
76 {PERIPH_ID_I2C7, -1, 8, -1},
77 {PERIPH_ID_SPI0, 20, 20, 8},
78 {PERIPH_ID_SPI1, 24, 24, 16},
79 {PERIPH_ID_SPI2, 28, 28, 24},
80 {PERIPH_ID_SDMMC0, 8, 0, -1},
81 {PERIPH_ID_SDMMC1, 12, 10, -1},
82 {PERIPH_ID_SDMMC2, 16, 20, -1},
83 {PERIPH_ID_I2C8, -1, 8, -1},
84 {PERIPH_ID_I2C9, -1, 8, -1},
85 {PERIPH_ID_I2S0, 0, 0, 4},
86 {PERIPH_ID_I2S1, 4, 12, 16},
87 {PERIPH_ID_SPI3, 12, 16, 0},
88 {PERIPH_ID_SPI4, 16, 20, 8},
89 {PERIPH_ID_PWM0, 24, 28, -1},
90 {PERIPH_ID_PWM1, 24, 28, -1},
91 {PERIPH_ID_PWM2, 24, 28, -1},
92 {PERIPH_ID_PWM3, 24, 28, -1},
93 {PERIPH_ID_PWM4, 24, 28, -1},
94 {PERIPH_ID_I2C10, -1, 8, -1},
95
96 {PERIPH_ID_NONE, -1, -1, -1},
97};
98
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +000099/* Epll Clock division values to achive different frequency output */
100static struct set_epll_con_val exynos5_epll_div[] = {
101 { 192000000, 0, 48, 3, 1, 0 },
102 { 180000000, 0, 45, 3, 1, 0 },
103 { 73728000, 1, 73, 3, 3, 47710 },
104 { 67737600, 1, 90, 4, 3, 20762 },
105 { 49152000, 0, 49, 3, 3, 9961 },
106 { 45158400, 0, 45, 3, 3, 10381 },
107 { 180633600, 0, 45, 3, 1, 10381 }
108};
109
Minkyu Kang1a055aa2012-10-15 01:58:00 +0000110/* exynos: return pll clock frequency */
111static int exynos_get_pll_clk(int pllreg, unsigned int r, unsigned int k)
Minkyu Kangb1b24682011-01-24 15:22:23 +0900112{
Minkyu Kang1a055aa2012-10-15 01:58:00 +0000113 unsigned long m, p, s = 0, mask, fout;
Minkyu Kang368588e2013-07-05 19:08:33 +0900114 unsigned int div;
Minkyu Kangb1b24682011-01-24 15:22:23 +0900115 unsigned int freq;
Minkyu Kangb1b24682011-01-24 15:22:23 +0900116 /*
117 * APLL_CON: MIDV [25:16]
118 * MPLL_CON: MIDV [25:16]
119 * EPLL_CON: MIDV [24:16]
120 * VPLL_CON: MIDV [24:16]
Minkyu Kang1a055aa2012-10-15 01:58:00 +0000121 * BPLL_CON: MIDV [25:16]: Exynos5
Minkyu Kangb1b24682011-01-24 15:22:23 +0900122 */
Ajay Kumar914af872014-09-05 16:53:32 +0530123 if (pllreg == APLL || pllreg == MPLL || pllreg == BPLL ||
124 pllreg == SPLL)
Minkyu Kangb1b24682011-01-24 15:22:23 +0900125 mask = 0x3ff;
126 else
127 mask = 0x1ff;
128
129 m = (r >> 16) & mask;
130
131 /* PDIV [13:8] */
132 p = (r >> 8) & 0x3f;
133 /* SDIV [2:0] */
134 s = r & 0x7;
135
Chander Kashyap6a870e12012-02-05 23:01:45 +0000136 freq = CONFIG_SYS_CLK_FREQ;
Minkyu Kangb1b24682011-01-24 15:22:23 +0900137
Rajeshwari Birjeac892d02013-12-26 09:44:21 +0530138 if (pllreg == EPLL || pllreg == RPLL) {
Minkyu Kangb1b24682011-01-24 15:22:23 +0900139 k = k & 0xffff;
140 /* FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV) */
Minkyu Kang368588e2013-07-05 19:08:33 +0900141 fout = (m + k / PLL_DIV_65536) * (freq / (p * (1 << s)));
Minkyu Kangb1b24682011-01-24 15:22:23 +0900142 } else if (pllreg == VPLL) {
143 k = k & 0xfff;
Minkyu Kang368588e2013-07-05 19:08:33 +0900144
145 /*
146 * Exynos4210
147 * FOUT = (MDIV + K / 1024) * FIN / (PDIV * 2^SDIV)
148 *
149 * Exynos4412
150 * FOUT = (MDIV + K / 65535) * FIN / (PDIV * 2^SDIV)
151 *
152 * Exynos5250
153 * FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV)
154 */
155 if (proid_is_exynos4210())
156 div = PLL_DIV_1024;
157 else if (proid_is_exynos4412())
158 div = PLL_DIV_65535;
Akshay Saraswat9fba7b42014-11-13 22:38:15 +0530159 else if (proid_is_exynos5250() || proid_is_exynos5420()
160 || proid_is_exynos5800())
Minkyu Kang368588e2013-07-05 19:08:33 +0900161 div = PLL_DIV_65536;
162 else
163 return 0;
164
165 fout = (m + k / div) * (freq / (p * (1 << s)));
Minkyu Kangb1b24682011-01-24 15:22:23 +0900166 } else {
Minkyu Kang368588e2013-07-05 19:08:33 +0900167 /*
Łukasz Majewski326c4592013-07-12 19:08:25 +0200168 * Exynos4412 / Exynos5250
Minkyu Kang368588e2013-07-05 19:08:33 +0900169 * FOUT = MDIV * FIN / (PDIV * 2^SDIV)
170 *
Łukasz Majewski326c4592013-07-12 19:08:25 +0200171 * Exynos4210
Minkyu Kang368588e2013-07-05 19:08:33 +0900172 * FOUT = MDIV * FIN / (PDIV * 2^(SDIV-1))
173 */
174 if (proid_is_exynos4210())
Minkyu Kang368588e2013-07-05 19:08:33 +0900175 fout = m * (freq / (p * (1 << (s - 1))));
Łukasz Majewski326c4592013-07-12 19:08:25 +0200176 else
177 fout = m * (freq / (p * (1 << s)));
Minkyu Kangb1b24682011-01-24 15:22:23 +0900178 }
Minkyu Kangb1b24682011-01-24 15:22:23 +0900179 return fout;
180}
181
Minkyu Kang1a055aa2012-10-15 01:58:00 +0000182/* exynos4: return pll clock frequency */
183static unsigned long exynos4_get_pll_clk(int pllreg)
184{
185 struct exynos4_clock *clk =
186 (struct exynos4_clock *)samsung_get_base_clock();
187 unsigned long r, k = 0;
188
189 switch (pllreg) {
190 case APLL:
191 r = readl(&clk->apll_con0);
192 break;
193 case MPLL:
194 r = readl(&clk->mpll_con0);
195 break;
196 case EPLL:
197 r = readl(&clk->epll_con0);
198 k = readl(&clk->epll_con1);
199 break;
200 case VPLL:
201 r = readl(&clk->vpll_con0);
202 k = readl(&clk->vpll_con1);
203 break;
204 default:
205 printf("Unsupported PLL (%d)\n", pllreg);
206 return 0;
207 }
208
209 return exynos_get_pll_clk(pllreg, r, k);
210}
211
Chander Kashyap400ab162012-10-07 01:43:17 +0000212/* exynos4x12: return pll clock frequency */
213static unsigned long exynos4x12_get_pll_clk(int pllreg)
214{
215 struct exynos4x12_clock *clk =
216 (struct exynos4x12_clock *)samsung_get_base_clock();
217 unsigned long r, k = 0;
218
219 switch (pllreg) {
220 case APLL:
221 r = readl(&clk->apll_con0);
222 break;
223 case MPLL:
224 r = readl(&clk->mpll_con0);
225 break;
226 case EPLL:
227 r = readl(&clk->epll_con0);
228 k = readl(&clk->epll_con1);
229 break;
230 case VPLL:
231 r = readl(&clk->vpll_con0);
232 k = readl(&clk->vpll_con1);
233 break;
234 default:
235 printf("Unsupported PLL (%d)\n", pllreg);
236 return 0;
237 }
238
239 return exynos_get_pll_clk(pllreg, r, k);
240}
241
Chander Kashyap34076a02012-02-05 23:01:46 +0000242/* exynos5: return pll clock frequency */
243static unsigned long exynos5_get_pll_clk(int pllreg)
244{
245 struct exynos5_clock *clk =
246 (struct exynos5_clock *)samsung_get_base_clock();
Minkyu Kang1a055aa2012-10-15 01:58:00 +0000247 unsigned long r, k = 0, fout;
248 unsigned int pll_div2_sel, fout_sel;
Chander Kashyap34076a02012-02-05 23:01:46 +0000249
250 switch (pllreg) {
251 case APLL:
252 r = readl(&clk->apll_con0);
253 break;
254 case MPLL:
255 r = readl(&clk->mpll_con0);
256 break;
257 case EPLL:
258 r = readl(&clk->epll_con0);
259 k = readl(&clk->epll_con1);
260 break;
261 case VPLL:
262 r = readl(&clk->vpll_con0);
263 k = readl(&clk->vpll_con1);
264 break;
Rajeshwari Shinde84112862012-07-03 20:02:58 +0000265 case BPLL:
266 r = readl(&clk->bpll_con0);
267 break;
Chander Kashyap34076a02012-02-05 23:01:46 +0000268 default:
269 printf("Unsupported PLL (%d)\n", pllreg);
270 return 0;
271 }
272
Minkyu Kang1a055aa2012-10-15 01:58:00 +0000273 fout = exynos_get_pll_clk(pllreg, r, k);
Chander Kashyap34076a02012-02-05 23:01:46 +0000274
Rajeshwari Shinde84112862012-07-03 20:02:58 +0000275 /* According to the user manual, in EVT1 MPLL and BPLL always gives
Rajeshwari Shinde7b9afce2012-07-03 20:02:57 +0000276 * 1.6GHz clock, so divide by 2 to get 800MHz MPLL clock.*/
Rajeshwari Shinde84112862012-07-03 20:02:58 +0000277 if (pllreg == MPLL || pllreg == BPLL) {
Rajeshwari Shinde7b9afce2012-07-03 20:02:57 +0000278 pll_div2_sel = readl(&clk->pll_div2_sel);
Rajeshwari Shinde84112862012-07-03 20:02:58 +0000279
280 switch (pllreg) {
281 case MPLL:
282 fout_sel = (pll_div2_sel >> MPLL_FOUT_SEL_SHIFT)
283 & MPLL_FOUT_SEL_MASK;
284 break;
285 case BPLL:
286 fout_sel = (pll_div2_sel >> BPLL_FOUT_SEL_SHIFT)
287 & BPLL_FOUT_SEL_MASK;
288 break;
Jaehoon Chung0fc779c2012-07-09 21:20:34 +0000289 default:
290 fout_sel = -1;
291 break;
Rajeshwari Shinde84112862012-07-03 20:02:58 +0000292 }
293
294 if (fout_sel == 0)
Rajeshwari Shinde7b9afce2012-07-03 20:02:57 +0000295 fout /= 2;
296 }
297
Chander Kashyap34076a02012-02-05 23:01:46 +0000298 return fout;
299}
300
Akshay Saraswat1bd40e42015-02-04 16:00:00 +0530301/* exynos542x: return pll clock frequency */
302static unsigned long exynos542x_get_pll_clk(int pllreg)
303{
304 struct exynos5420_clock *clk =
305 (struct exynos5420_clock *)samsung_get_base_clock();
306 unsigned long r, k = 0;
307
308 switch (pllreg) {
309 case APLL:
310 r = readl(&clk->apll_con0);
311 break;
312 case MPLL:
313 r = readl(&clk->mpll_con0);
314 break;
315 case EPLL:
316 r = readl(&clk->epll_con0);
317 k = readl(&clk->epll_con1);
318 break;
319 case VPLL:
320 r = readl(&clk->vpll_con0);
321 k = readl(&clk->vpll_con1);
322 break;
323 case BPLL:
324 r = readl(&clk->bpll_con0);
325 break;
326 case RPLL:
327 r = readl(&clk->rpll_con0);
328 k = readl(&clk->rpll_con1);
329 break;
330 case SPLL:
331 r = readl(&clk->spll_con0);
332 break;
333 default:
334 printf("Unsupported PLL (%d)\n", pllreg);
335 return 0;
336 }
337
338 return exynos_get_pll_clk(pllreg, r, k);
339}
340
Akshay Saraswat3ad7ffc2015-02-04 15:59:59 +0530341static struct clk_bit_info *get_clk_bit_info(int peripheral)
342{
343 int i;
Akshay Saraswatd5072262015-02-04 16:00:01 +0530344 struct clk_bit_info *info;
345
346 if (proid_is_exynos5420() || proid_is_exynos5800())
347 info = exynos542x_bit_info;
348 else
349 info = exynos5_bit_info;
Akshay Saraswat3ad7ffc2015-02-04 15:59:59 +0530350
Akshay Saraswatd5072262015-02-04 16:00:01 +0530351 for (i = 0; info[i].id != PERIPH_ID_NONE; i++) {
352 if (info[i].id == peripheral)
Akshay Saraswat3ad7ffc2015-02-04 15:59:59 +0530353 break;
354 }
355
Akshay Saraswatd5072262015-02-04 16:00:01 +0530356 if (info[i].id == PERIPH_ID_NONE)
Akshay Saraswat3ad7ffc2015-02-04 15:59:59 +0530357 debug("ERROR: Peripheral ID %d not found\n", peripheral);
358
Akshay Saraswatd5072262015-02-04 16:00:01 +0530359 return &info[i];
Akshay Saraswat3ad7ffc2015-02-04 15:59:59 +0530360}
361
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000362static unsigned long exynos5_get_periph_rate(int peripheral)
363{
Akshay Saraswat3ad7ffc2015-02-04 15:59:59 +0530364 struct clk_bit_info *bit_info = get_clk_bit_info(peripheral);
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000365 unsigned long sclk, sub_clk;
366 unsigned int src, div, sub_div;
367 struct exynos5_clock *clk =
368 (struct exynos5_clock *)samsung_get_base_clock();
369
370 switch (peripheral) {
371 case PERIPH_ID_UART0:
372 case PERIPH_ID_UART1:
373 case PERIPH_ID_UART2:
374 case PERIPH_ID_UART3:
375 src = readl(&clk->src_peric0);
376 div = readl(&clk->div_peric0);
377 break;
378 case PERIPH_ID_PWM0:
379 case PERIPH_ID_PWM1:
380 case PERIPH_ID_PWM2:
381 case PERIPH_ID_PWM3:
382 case PERIPH_ID_PWM4:
383 src = readl(&clk->src_peric0);
384 div = readl(&clk->div_peric3);
385 break;
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +0530386 case PERIPH_ID_I2S0:
387 src = readl(&clk->src_mau);
388 div = readl(&clk->div_mau);
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000389 case PERIPH_ID_SPI0:
390 case PERIPH_ID_SPI1:
391 src = readl(&clk->src_peric1);
392 div = readl(&clk->div_peric1);
393 break;
394 case PERIPH_ID_SPI2:
395 src = readl(&clk->src_peric1);
396 div = readl(&clk->div_peric2);
397 break;
398 case PERIPH_ID_SPI3:
399 case PERIPH_ID_SPI4:
400 src = readl(&clk->sclk_src_isp);
401 div = readl(&clk->sclk_div_isp);
402 break;
403 case PERIPH_ID_SDMMC0:
404 case PERIPH_ID_SDMMC1:
405 case PERIPH_ID_SDMMC2:
406 case PERIPH_ID_SDMMC3:
407 src = readl(&clk->src_fsys);
408 div = readl(&clk->div_fsys1);
409 break;
410 case PERIPH_ID_I2C0:
411 case PERIPH_ID_I2C1:
412 case PERIPH_ID_I2C2:
413 case PERIPH_ID_I2C3:
414 case PERIPH_ID_I2C4:
415 case PERIPH_ID_I2C5:
416 case PERIPH_ID_I2C6:
417 case PERIPH_ID_I2C7:
418 sclk = exynos5_get_pll_clk(MPLL);
419 sub_div = ((readl(&clk->div_top1) >> bit_info->div_bit)
420 & 0x7) + 1;
421 div = ((readl(&clk->div_top0) >> bit_info->prediv_bit)
422 & 0x7) + 1;
423 return (sclk / sub_div) / div;
424 default:
425 debug("%s: invalid peripheral %d", __func__, peripheral);
426 return -1;
427 };
428
429 src = (src >> bit_info->src_bit) & 0xf;
430
431 switch (src) {
432 case EXYNOS_SRC_MPLL:
433 sclk = exynos5_get_pll_clk(MPLL);
434 break;
435 case EXYNOS_SRC_EPLL:
436 sclk = exynos5_get_pll_clk(EPLL);
437 break;
438 case EXYNOS_SRC_VPLL:
439 sclk = exynos5_get_pll_clk(VPLL);
440 break;
441 default:
442 return 0;
443 }
444
445 /* Ratio clock division for this peripheral */
446 sub_div = (div >> bit_info->div_bit) & 0xf;
447 sub_clk = sclk / (sub_div + 1);
448
449 /* Pre-ratio clock division for SDMMC0 and 2 */
450 if (peripheral == PERIPH_ID_SDMMC0 || peripheral == PERIPH_ID_SDMMC2) {
451 div = (div >> bit_info->prediv_bit) & 0xff;
452 return sub_clk / (div + 1);
453 }
454
455 return sub_clk;
456}
457
Akshay Saraswatd5072262015-02-04 16:00:01 +0530458static unsigned long exynos542x_get_periph_rate(int peripheral)
459{
460 struct clk_bit_info *bit_info = get_clk_bit_info(peripheral);
461 unsigned long sclk, sub_clk = 0;
462 unsigned int src, div, sub_div = 0;
463 struct exynos5420_clock *clk =
464 (struct exynos5420_clock *)samsung_get_base_clock();
465
466 switch (peripheral) {
467 case PERIPH_ID_UART0:
468 case PERIPH_ID_UART1:
469 case PERIPH_ID_UART2:
470 case PERIPH_ID_UART3:
471 case PERIPH_ID_PWM0:
472 case PERIPH_ID_PWM1:
473 case PERIPH_ID_PWM2:
474 case PERIPH_ID_PWM3:
475 case PERIPH_ID_PWM4:
476 src = readl(&clk->src_peric0);
477 div = readl(&clk->div_peric0);
478 break;
479 case PERIPH_ID_SPI0:
480 case PERIPH_ID_SPI1:
481 case PERIPH_ID_SPI2:
482 src = readl(&clk->src_peric1);
483 div = readl(&clk->div_peric1);
484 sub_div = readl(&clk->div_peric4);
485 break;
486 case PERIPH_ID_SPI3:
487 case PERIPH_ID_SPI4:
488 src = readl(&clk->src_isp);
489 div = readl(&clk->div_isp1);
490 sub_div = readl(&clk->div_isp1);
491 break;
492 case PERIPH_ID_SDMMC0:
493 case PERIPH_ID_SDMMC1:
494 case PERIPH_ID_SDMMC2:
495 case PERIPH_ID_SDMMC3:
496 src = readl(&clk->src_fsys);
497 div = readl(&clk->div_fsys1);
498 break;
499 case PERIPH_ID_I2C0:
500 case PERIPH_ID_I2C1:
501 case PERIPH_ID_I2C2:
502 case PERIPH_ID_I2C3:
503 case PERIPH_ID_I2C4:
504 case PERIPH_ID_I2C5:
505 case PERIPH_ID_I2C6:
506 case PERIPH_ID_I2C7:
507 case PERIPH_ID_I2C8:
508 case PERIPH_ID_I2C9:
509 case PERIPH_ID_I2C10:
510 sclk = exynos542x_get_pll_clk(MPLL);
511 sub_div = ((readl(&clk->div_top1) >> bit_info->div_bit)
512 & 0x7) + 1;
513 return sclk / sub_div;
514 default:
515 debug("%s: invalid peripheral %d", __func__, peripheral);
516 return -1;
517 };
518
519 if (bit_info->src_bit >= 0)
520 src = (src >> bit_info->src_bit) & 0xf;
521
522 switch (src) {
523 case EXYNOS542X_SRC_MPLL:
524 sclk = exynos542x_get_pll_clk(MPLL);
525 break;
526 case EXYNOS542X_SRC_SPLL:
527 sclk = exynos542x_get_pll_clk(SPLL);
528 break;
529 case EXYNOS542X_SRC_EPLL:
530 sclk = exynos542x_get_pll_clk(EPLL);
531 break;
532 case EXYNOS542X_SRC_RPLL:
533 sclk = exynos542x_get_pll_clk(RPLL);
534 break;
535 default:
536 return 0;
537 }
538
539 /* Ratio clock division for this peripheral */
540 if (bit_info->div_bit >= 0) {
541 div = (div >> bit_info->div_bit) & 0xf;
542 sub_clk = sclk / (div + 1);
543 }
544
545 if (bit_info->prediv_bit >= 0) {
546 sub_div = (sub_div >> bit_info->prediv_bit) & 0xff;
547 return sub_clk / (sub_div + 1);
548 }
549
550 return sub_clk;
551}
552
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000553unsigned long clock_get_periph_rate(int peripheral)
554{
Akshay Saraswatd5072262015-02-04 16:00:01 +0530555 if (cpu_is_exynos5()) {
556 if (proid_is_exynos5420() || proid_is_exynos5800())
557 return exynos542x_get_periph_rate(peripheral);
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000558 return exynos5_get_periph_rate(peripheral);
Akshay Saraswatd5072262015-02-04 16:00:01 +0530559 } else {
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000560 return 0;
Akshay Saraswatd5072262015-02-04 16:00:01 +0530561 }
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000562}
563
Chander Kashyap4131a772011-12-06 23:34:12 +0000564/* exynos4: return ARM clock frequency */
565static unsigned long exynos4_get_arm_clk(void)
Minkyu Kangb1b24682011-01-24 15:22:23 +0900566{
Chander Kashyap4131a772011-12-06 23:34:12 +0000567 struct exynos4_clock *clk =
568 (struct exynos4_clock *)samsung_get_base_clock();
Minkyu Kangb1b24682011-01-24 15:22:23 +0900569 unsigned long div;
Chander Kashyap3c7721f2011-12-18 22:56:44 +0000570 unsigned long armclk;
571 unsigned int core_ratio;
572 unsigned int core2_ratio;
Minkyu Kangb1b24682011-01-24 15:22:23 +0900573
574 div = readl(&clk->div_cpu0);
575
Chander Kashyap3c7721f2011-12-18 22:56:44 +0000576 /* CORE_RATIO: [2:0], CORE2_RATIO: [30:28] */
577 core_ratio = (div >> 0) & 0x7;
578 core2_ratio = (div >> 28) & 0x7;
Minkyu Kangb1b24682011-01-24 15:22:23 +0900579
Chander Kashyap3c7721f2011-12-18 22:56:44 +0000580 armclk = get_pll_clk(APLL) / (core_ratio + 1);
581 armclk /= (core2_ratio + 1);
Minkyu Kangb1b24682011-01-24 15:22:23 +0900582
Chander Kashyap3c7721f2011-12-18 22:56:44 +0000583 return armclk;
Minkyu Kangb1b24682011-01-24 15:22:23 +0900584}
585
Chander Kashyap400ab162012-10-07 01:43:17 +0000586/* exynos4x12: return ARM clock frequency */
587static unsigned long exynos4x12_get_arm_clk(void)
588{
589 struct exynos4x12_clock *clk =
590 (struct exynos4x12_clock *)samsung_get_base_clock();
591 unsigned long div;
592 unsigned long armclk;
593 unsigned int core_ratio;
594 unsigned int core2_ratio;
595
596 div = readl(&clk->div_cpu0);
597
598 /* CORE_RATIO: [2:0], CORE2_RATIO: [30:28] */
599 core_ratio = (div >> 0) & 0x7;
600 core2_ratio = (div >> 28) & 0x7;
601
602 armclk = get_pll_clk(APLL) / (core_ratio + 1);
603 armclk /= (core2_ratio + 1);
604
605 return armclk;
606}
607
Chander Kashyap34076a02012-02-05 23:01:46 +0000608/* exynos5: return ARM clock frequency */
609static unsigned long exynos5_get_arm_clk(void)
610{
611 struct exynos5_clock *clk =
612 (struct exynos5_clock *)samsung_get_base_clock();
613 unsigned long div;
614 unsigned long armclk;
615 unsigned int arm_ratio;
616 unsigned int arm2_ratio;
617
618 div = readl(&clk->div_cpu0);
619
620 /* ARM_RATIO: [2:0], ARM2_RATIO: [30:28] */
621 arm_ratio = (div >> 0) & 0x7;
622 arm2_ratio = (div >> 28) & 0x7;
623
624 armclk = get_pll_clk(APLL) / (arm_ratio + 1);
625 armclk /= (arm2_ratio + 1);
626
627 return armclk;
628}
629
Chander Kashyap4131a772011-12-06 23:34:12 +0000630/* exynos4: return pwm clock frequency */
631static unsigned long exynos4_get_pwm_clk(void)
Minkyu Kangb1b24682011-01-24 15:22:23 +0900632{
Chander Kashyap4131a772011-12-06 23:34:12 +0000633 struct exynos4_clock *clk =
634 (struct exynos4_clock *)samsung_get_base_clock();
Minkyu Kangb1b24682011-01-24 15:22:23 +0900635 unsigned long pclk, sclk;
636 unsigned int sel;
637 unsigned int ratio;
638
Minkyu Kang69b28242011-05-18 16:57:55 +0900639 if (s5p_get_cpu_rev() == 0) {
640 /*
641 * CLK_SRC_PERIL0
642 * PWM_SEL [27:24]
643 */
644 sel = readl(&clk->src_peril0);
645 sel = (sel >> 24) & 0xf;
Minkyu Kangb1b24682011-01-24 15:22:23 +0900646
Minkyu Kang69b28242011-05-18 16:57:55 +0900647 if (sel == 0x6)
648 sclk = get_pll_clk(MPLL);
649 else if (sel == 0x7)
650 sclk = get_pll_clk(EPLL);
651 else if (sel == 0x8)
652 sclk = get_pll_clk(VPLL);
653 else
654 return 0;
655
656 /*
657 * CLK_DIV_PERIL3
658 * PWM_RATIO [3:0]
659 */
660 ratio = readl(&clk->div_peril3);
661 ratio = ratio & 0xf;
662 } else if (s5p_get_cpu_rev() == 1) {
Minkyu Kangb1b24682011-01-24 15:22:23 +0900663 sclk = get_pll_clk(MPLL);
Minkyu Kang69b28242011-05-18 16:57:55 +0900664 ratio = 8;
665 } else
Minkyu Kangb1b24682011-01-24 15:22:23 +0900666 return 0;
667
Minkyu Kangb1b24682011-01-24 15:22:23 +0900668 pclk = sclk / (ratio + 1);
669
670 return pclk;
671}
672
Chander Kashyap400ab162012-10-07 01:43:17 +0000673/* exynos4x12: return pwm clock frequency */
674static unsigned long exynos4x12_get_pwm_clk(void)
675{
676 unsigned long pclk, sclk;
677 unsigned int ratio;
678
679 sclk = get_pll_clk(MPLL);
680 ratio = 8;
681
682 pclk = sclk / (ratio + 1);
683
684 return pclk;
685}
686
Rajeshwari Birjeac892d02013-12-26 09:44:21 +0530687/* exynos5420: return pwm clock frequency */
688static unsigned long exynos5420_get_pwm_clk(void)
689{
690 struct exynos5420_clock *clk =
691 (struct exynos5420_clock *)samsung_get_base_clock();
692 unsigned long pclk, sclk;
693 unsigned int ratio;
694
695 /*
696 * CLK_DIV_PERIC0
697 * PWM_RATIO [31:28]
698 */
699 ratio = readl(&clk->div_peric0);
700 ratio = (ratio >> 28) & 0xf;
701 sclk = get_pll_clk(MPLL);
702
703 pclk = sclk / (ratio + 1);
704
705 return pclk;
706}
707
Chander Kashyap4131a772011-12-06 23:34:12 +0000708/* exynos4: return uart clock frequency */
709static unsigned long exynos4_get_uart_clk(int dev_index)
Minkyu Kangb1b24682011-01-24 15:22:23 +0900710{
Chander Kashyap4131a772011-12-06 23:34:12 +0000711 struct exynos4_clock *clk =
712 (struct exynos4_clock *)samsung_get_base_clock();
Minkyu Kangb1b24682011-01-24 15:22:23 +0900713 unsigned long uclk, sclk;
714 unsigned int sel;
715 unsigned int ratio;
716
717 /*
718 * CLK_SRC_PERIL0
719 * UART0_SEL [3:0]
720 * UART1_SEL [7:4]
721 * UART2_SEL [8:11]
722 * UART3_SEL [12:15]
723 * UART4_SEL [16:19]
724 * UART5_SEL [23:20]
725 */
726 sel = readl(&clk->src_peril0);
727 sel = (sel >> (dev_index << 2)) & 0xf;
728
729 if (sel == 0x6)
730 sclk = get_pll_clk(MPLL);
731 else if (sel == 0x7)
732 sclk = get_pll_clk(EPLL);
733 else if (sel == 0x8)
734 sclk = get_pll_clk(VPLL);
735 else
736 return 0;
737
738 /*
739 * CLK_DIV_PERIL0
740 * UART0_RATIO [3:0]
741 * UART1_RATIO [7:4]
742 * UART2_RATIO [8:11]
743 * UART3_RATIO [12:15]
744 * UART4_RATIO [16:19]
745 * UART5_RATIO [23:20]
746 */
747 ratio = readl(&clk->div_peril0);
748 ratio = (ratio >> (dev_index << 2)) & 0xf;
749
750 uclk = sclk / (ratio + 1);
751
752 return uclk;
753}
754
Chander Kashyap400ab162012-10-07 01:43:17 +0000755/* exynos4x12: return uart clock frequency */
756static unsigned long exynos4x12_get_uart_clk(int dev_index)
757{
758 struct exynos4x12_clock *clk =
759 (struct exynos4x12_clock *)samsung_get_base_clock();
760 unsigned long uclk, sclk;
761 unsigned int sel;
762 unsigned int ratio;
763
764 /*
765 * CLK_SRC_PERIL0
766 * UART0_SEL [3:0]
767 * UART1_SEL [7:4]
768 * UART2_SEL [8:11]
769 * UART3_SEL [12:15]
770 * UART4_SEL [16:19]
771 */
772 sel = readl(&clk->src_peril0);
773 sel = (sel >> (dev_index << 2)) & 0xf;
774
775 if (sel == 0x6)
776 sclk = get_pll_clk(MPLL);
777 else if (sel == 0x7)
778 sclk = get_pll_clk(EPLL);
779 else if (sel == 0x8)
780 sclk = get_pll_clk(VPLL);
781 else
782 return 0;
783
784 /*
785 * CLK_DIV_PERIL0
786 * UART0_RATIO [3:0]
787 * UART1_RATIO [7:4]
788 * UART2_RATIO [8:11]
789 * UART3_RATIO [12:15]
790 * UART4_RATIO [16:19]
791 */
792 ratio = readl(&clk->div_peril0);
793 ratio = (ratio >> (dev_index << 2)) & 0xf;
794
795 uclk = sclk / (ratio + 1);
796
797 return uclk;
798}
799
Chander Kashyap34076a02012-02-05 23:01:46 +0000800/* exynos5: return uart clock frequency */
801static unsigned long exynos5_get_uart_clk(int dev_index)
802{
803 struct exynos5_clock *clk =
804 (struct exynos5_clock *)samsung_get_base_clock();
805 unsigned long uclk, sclk;
806 unsigned int sel;
807 unsigned int ratio;
808
809 /*
810 * CLK_SRC_PERIC0
811 * UART0_SEL [3:0]
812 * UART1_SEL [7:4]
813 * UART2_SEL [8:11]
814 * UART3_SEL [12:15]
815 * UART4_SEL [16:19]
816 * UART5_SEL [23:20]
817 */
818 sel = readl(&clk->src_peric0);
819 sel = (sel >> (dev_index << 2)) & 0xf;
820
821 if (sel == 0x6)
822 sclk = get_pll_clk(MPLL);
823 else if (sel == 0x7)
824 sclk = get_pll_clk(EPLL);
825 else if (sel == 0x8)
826 sclk = get_pll_clk(VPLL);
827 else
828 return 0;
829
830 /*
831 * CLK_DIV_PERIC0
832 * UART0_RATIO [3:0]
833 * UART1_RATIO [7:4]
834 * UART2_RATIO [8:11]
835 * UART3_RATIO [12:15]
836 * UART4_RATIO [16:19]
837 * UART5_RATIO [23:20]
838 */
839 ratio = readl(&clk->div_peric0);
840 ratio = (ratio >> (dev_index << 2)) & 0xf;
841
842 uclk = sclk / (ratio + 1);
843
844 return uclk;
845}
846
Rajeshwari Birjeac892d02013-12-26 09:44:21 +0530847/* exynos5420: return uart clock frequency */
848static unsigned long exynos5420_get_uart_clk(int dev_index)
849{
850 struct exynos5420_clock *clk =
851 (struct exynos5420_clock *)samsung_get_base_clock();
852 unsigned long uclk, sclk;
853 unsigned int sel;
854 unsigned int ratio;
855
856 /*
857 * CLK_SRC_PERIC0
858 * UART0_SEL [6:4]
859 * UART1_SEL [10:8]
860 * UART2_SEL [14:12]
861 * UART3_SEL [18:16]
862 * generalised calculation as follows
863 * sel = (sel >> ((dev_index * 4) + 4)) & mask;
864 */
865 sel = readl(&clk->src_peric0);
866 sel = (sel >> ((dev_index * 4) + 4)) & 0x7;
867
868 if (sel == 0x3)
869 sclk = get_pll_clk(MPLL);
870 else if (sel == 0x6)
871 sclk = get_pll_clk(EPLL);
872 else if (sel == 0x7)
873 sclk = get_pll_clk(RPLL);
874 else
875 return 0;
876
877 /*
878 * CLK_DIV_PERIC0
879 * UART0_RATIO [11:8]
880 * UART1_RATIO [15:12]
881 * UART2_RATIO [19:16]
882 * UART3_RATIO [23:20]
883 * generalised calculation as follows
884 * ratio = (ratio >> ((dev_index * 4) + 8)) & mask;
885 */
886 ratio = readl(&clk->div_peric0);
887 ratio = (ratio >> ((dev_index * 4) + 8)) & 0xf;
888
889 uclk = sclk / (ratio + 1);
890
891 return uclk;
892}
893
Jaehoon Chung8788e062012-12-27 22:30:32 +0000894static unsigned long exynos4_get_mmc_clk(int dev_index)
895{
896 struct exynos4_clock *clk =
897 (struct exynos4_clock *)samsung_get_base_clock();
898 unsigned long uclk, sclk;
899 unsigned int sel, ratio, pre_ratio;
Amare1df6282013-04-27 11:42:56 +0530900 int shift = 0;
Jaehoon Chung8788e062012-12-27 22:30:32 +0000901
902 sel = readl(&clk->src_fsys);
903 sel = (sel >> (dev_index << 2)) & 0xf;
904
905 if (sel == 0x6)
906 sclk = get_pll_clk(MPLL);
907 else if (sel == 0x7)
908 sclk = get_pll_clk(EPLL);
909 else if (sel == 0x8)
910 sclk = get_pll_clk(VPLL);
911 else
912 return 0;
913
914 switch (dev_index) {
915 case 0:
916 case 1:
917 ratio = readl(&clk->div_fsys1);
918 pre_ratio = readl(&clk->div_fsys1);
919 break;
920 case 2:
921 case 3:
922 ratio = readl(&clk->div_fsys2);
923 pre_ratio = readl(&clk->div_fsys2);
924 break;
925 case 4:
926 ratio = readl(&clk->div_fsys3);
927 pre_ratio = readl(&clk->div_fsys3);
928 break;
929 default:
930 return 0;
931 }
932
933 if (dev_index == 1 || dev_index == 3)
934 shift = 16;
935
936 ratio = (ratio >> shift) & 0xf;
937 pre_ratio = (pre_ratio >> (shift + 8)) & 0xff;
938 uclk = (sclk / (ratio + 1)) / (pre_ratio + 1);
939
940 return uclk;
941}
942
943static unsigned long exynos5_get_mmc_clk(int dev_index)
944{
945 struct exynos5_clock *clk =
946 (struct exynos5_clock *)samsung_get_base_clock();
947 unsigned long uclk, sclk;
948 unsigned int sel, ratio, pre_ratio;
Amare1df6282013-04-27 11:42:56 +0530949 int shift = 0;
Jaehoon Chung8788e062012-12-27 22:30:32 +0000950
951 sel = readl(&clk->src_fsys);
952 sel = (sel >> (dev_index << 2)) & 0xf;
953
954 if (sel == 0x6)
955 sclk = get_pll_clk(MPLL);
956 else if (sel == 0x7)
957 sclk = get_pll_clk(EPLL);
958 else if (sel == 0x8)
959 sclk = get_pll_clk(VPLL);
960 else
961 return 0;
962
963 switch (dev_index) {
964 case 0:
965 case 1:
966 ratio = readl(&clk->div_fsys1);
967 pre_ratio = readl(&clk->div_fsys1);
968 break;
969 case 2:
970 case 3:
971 ratio = readl(&clk->div_fsys2);
972 pre_ratio = readl(&clk->div_fsys2);
973 break;
974 default:
975 return 0;
976 }
977
978 if (dev_index == 1 || dev_index == 3)
979 shift = 16;
980
981 ratio = (ratio >> shift) & 0xf;
982 pre_ratio = (pre_ratio >> (shift + 8)) & 0xff;
983 uclk = (sclk / (ratio + 1)) / (pre_ratio + 1);
984
985 return uclk;
986}
987
Rajeshwari Birjeac892d02013-12-26 09:44:21 +0530988static unsigned long exynos5420_get_mmc_clk(int dev_index)
989{
990 struct exynos5420_clock *clk =
991 (struct exynos5420_clock *)samsung_get_base_clock();
992 unsigned long uclk, sclk;
993 unsigned int sel, ratio;
994
995 /*
996 * CLK_SRC_FSYS
997 * MMC0_SEL [10:8]
998 * MMC1_SEL [14:12]
999 * MMC2_SEL [18:16]
1000 * generalised calculation as follows
1001 * sel = (sel >> ((dev_index * 4) + 8)) & mask
1002 */
1003 sel = readl(&clk->src_fsys);
1004 sel = (sel >> ((dev_index * 4) + 8)) & 0x7;
1005
1006 if (sel == 0x3)
1007 sclk = get_pll_clk(MPLL);
Joonyoung Shim615e1482014-12-22 19:46:30 +09001008 else if (sel == 0x4)
1009 sclk = get_pll_clk(SPLL);
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301010 else if (sel == 0x6)
1011 sclk = get_pll_clk(EPLL);
1012 else
1013 return 0;
1014
1015 /*
1016 * CLK_DIV_FSYS1
1017 * MMC0_RATIO [9:0]
1018 * MMC1_RATIO [19:10]
1019 * MMC2_RATIO [29:20]
1020 * generalised calculation as follows
1021 * ratio = (ratio >> (dev_index * 10)) & mask
1022 */
1023 ratio = readl(&clk->div_fsys1);
1024 ratio = (ratio >> (dev_index * 10)) & 0x3ff;
1025
1026 uclk = (sclk / (ratio + 1));
1027
1028 return uclk;
1029}
1030
Chander Kashyap4131a772011-12-06 23:34:12 +00001031/* exynos4: set the mmc clock */
1032static void exynos4_set_mmc_clk(int dev_index, unsigned int div)
Jaehoon Chung9a772212011-05-17 21:19:17 +00001033{
Chander Kashyap4131a772011-12-06 23:34:12 +00001034 struct exynos4_clock *clk =
1035 (struct exynos4_clock *)samsung_get_base_clock();
Jaehoon Chungd2c83242014-05-16 13:59:50 +09001036 unsigned int addr, clear_bit, set_bit;
Jaehoon Chung9a772212011-05-17 21:19:17 +00001037
1038 /*
1039 * CLK_DIV_FSYS1
1040 * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24]
1041 * CLK_DIV_FSYS2
1042 * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24]
Jaehoon Chung29fe8c52012-12-27 22:30:33 +00001043 * CLK_DIV_FSYS3
Jaehoon Chungd2c83242014-05-16 13:59:50 +09001044 * MMC4_RATIO [3:0]
Jaehoon Chung9a772212011-05-17 21:19:17 +00001045 */
1046 if (dev_index < 2) {
1047 addr = (unsigned int)&clk->div_fsys1;
Jaehoon Chungd2c83242014-05-16 13:59:50 +09001048 clear_bit = MASK_PRE_RATIO(dev_index);
1049 set_bit = SET_PRE_RATIO(dev_index, div);
1050 } else if (dev_index == 4) {
Jaehoon Chung29fe8c52012-12-27 22:30:33 +00001051 addr = (unsigned int)&clk->div_fsys3;
1052 dev_index -= 4;
Jaehoon Chungd2c83242014-05-16 13:59:50 +09001053 /* MMC4 is controlled with the MMC4_RATIO value */
1054 clear_bit = MASK_RATIO(dev_index);
1055 set_bit = SET_RATIO(dev_index, div);
Jaehoon Chung9a772212011-05-17 21:19:17 +00001056 } else {
1057 addr = (unsigned int)&clk->div_fsys2;
1058 dev_index -= 2;
Jaehoon Chungd2c83242014-05-16 13:59:50 +09001059 clear_bit = MASK_PRE_RATIO(dev_index);
1060 set_bit = SET_PRE_RATIO(dev_index, div);
Jaehoon Chung9a772212011-05-17 21:19:17 +00001061 }
1062
Jaehoon Chungd2c83242014-05-16 13:59:50 +09001063 clrsetbits_le32(addr, clear_bit, set_bit);
Jaehoon Chung9a772212011-05-17 21:19:17 +00001064}
1065
Chander Kashyap34076a02012-02-05 23:01:46 +00001066/* exynos5: set the mmc clock */
1067static void exynos5_set_mmc_clk(int dev_index, unsigned int div)
1068{
1069 struct exynos5_clock *clk =
1070 (struct exynos5_clock *)samsung_get_base_clock();
1071 unsigned int addr;
Chander Kashyap34076a02012-02-05 23:01:46 +00001072
1073 /*
1074 * CLK_DIV_FSYS1
1075 * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24]
1076 * CLK_DIV_FSYS2
1077 * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24]
1078 */
1079 if (dev_index < 2) {
1080 addr = (unsigned int)&clk->div_fsys1;
1081 } else {
1082 addr = (unsigned int)&clk->div_fsys2;
1083 dev_index -= 2;
1084 }
1085
Inha Song4e558532014-02-06 14:20:12 +09001086 clrsetbits_le32(addr, 0xff << ((dev_index << 4) + 8),
1087 (div & 0xff) << ((dev_index << 4) + 8));
Chander Kashyap34076a02012-02-05 23:01:46 +00001088}
1089
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301090/* exynos5: set the mmc clock */
1091static void exynos5420_set_mmc_clk(int dev_index, unsigned int div)
1092{
1093 struct exynos5420_clock *clk =
1094 (struct exynos5420_clock *)samsung_get_base_clock();
1095 unsigned int addr;
Inha Song4e558532014-02-06 14:20:12 +09001096 unsigned int shift;
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301097
1098 /*
1099 * CLK_DIV_FSYS1
1100 * MMC0_RATIO [9:0]
1101 * MMC1_RATIO [19:10]
1102 * MMC2_RATIO [29:20]
1103 */
1104 addr = (unsigned int)&clk->div_fsys1;
1105 shift = dev_index * 10;
1106
Inha Song4e558532014-02-06 14:20:12 +09001107 clrsetbits_le32(addr, 0x3ff << shift, (div & 0x3ff) << shift);
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301108}
1109
Donghwa Lee77ba1912012-04-05 19:36:12 +00001110/* get_lcd_clk: return lcd clock frequency */
1111static unsigned long exynos4_get_lcd_clk(void)
1112{
1113 struct exynos4_clock *clk =
1114 (struct exynos4_clock *)samsung_get_base_clock();
1115 unsigned long pclk, sclk;
1116 unsigned int sel;
1117 unsigned int ratio;
1118
1119 /*
1120 * CLK_SRC_LCD0
1121 * FIMD0_SEL [3:0]
1122 */
1123 sel = readl(&clk->src_lcd0);
1124 sel = sel & 0xf;
1125
1126 /*
1127 * 0x6: SCLK_MPLL
1128 * 0x7: SCLK_EPLL
1129 * 0x8: SCLK_VPLL
1130 */
1131 if (sel == 0x6)
1132 sclk = get_pll_clk(MPLL);
1133 else if (sel == 0x7)
1134 sclk = get_pll_clk(EPLL);
1135 else if (sel == 0x8)
1136 sclk = get_pll_clk(VPLL);
1137 else
1138 return 0;
1139
1140 /*
1141 * CLK_DIV_LCD0
1142 * FIMD0_RATIO [3:0]
1143 */
1144 ratio = readl(&clk->div_lcd0);
1145 ratio = ratio & 0xf;
1146
1147 pclk = sclk / (ratio + 1);
1148
1149 return pclk;
1150}
1151
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001152/* get_lcd_clk: return lcd clock frequency */
1153static unsigned long exynos5_get_lcd_clk(void)
1154{
1155 struct exynos5_clock *clk =
1156 (struct exynos5_clock *)samsung_get_base_clock();
1157 unsigned long pclk, sclk;
1158 unsigned int sel;
1159 unsigned int ratio;
1160
1161 /*
1162 * CLK_SRC_LCD0
1163 * FIMD0_SEL [3:0]
1164 */
1165 sel = readl(&clk->src_disp1_0);
1166 sel = sel & 0xf;
1167
1168 /*
1169 * 0x6: SCLK_MPLL
1170 * 0x7: SCLK_EPLL
1171 * 0x8: SCLK_VPLL
1172 */
1173 if (sel == 0x6)
1174 sclk = get_pll_clk(MPLL);
1175 else if (sel == 0x7)
1176 sclk = get_pll_clk(EPLL);
1177 else if (sel == 0x8)
1178 sclk = get_pll_clk(VPLL);
1179 else
1180 return 0;
1181
1182 /*
1183 * CLK_DIV_LCD0
1184 * FIMD0_RATIO [3:0]
1185 */
1186 ratio = readl(&clk->div_disp1_0);
1187 ratio = ratio & 0xf;
1188
1189 pclk = sclk / (ratio + 1);
1190
1191 return pclk;
1192}
1193
Ajay Kumar914af872014-09-05 16:53:32 +05301194static unsigned long exynos5420_get_lcd_clk(void)
1195{
1196 struct exynos5420_clock *clk =
1197 (struct exynos5420_clock *)samsung_get_base_clock();
1198 unsigned long pclk, sclk;
1199 unsigned int sel;
1200 unsigned int ratio;
1201
1202 /*
1203 * CLK_SRC_DISP10
1204 * FIMD1_SEL [4]
1205 * 0: SCLK_RPLL
1206 * 1: SCLK_SPLL
1207 */
1208 sel = readl(&clk->src_disp10);
1209 sel &= (1 << 4);
1210
1211 if (sel)
1212 sclk = get_pll_clk(SPLL);
1213 else
1214 sclk = get_pll_clk(RPLL);
1215
1216 /*
1217 * CLK_DIV_DISP10
1218 * FIMD1_RATIO [3:0]
1219 */
1220 ratio = readl(&clk->div_disp10);
1221 ratio = ratio & 0xf;
1222
1223 pclk = sclk / (ratio + 1);
1224
1225 return pclk;
1226}
1227
Donghwa Lee77ba1912012-04-05 19:36:12 +00001228void exynos4_set_lcd_clk(void)
1229{
1230 struct exynos4_clock *clk =
1231 (struct exynos4_clock *)samsung_get_base_clock();
Donghwa Lee77ba1912012-04-05 19:36:12 +00001232
1233 /*
1234 * CLK_GATE_BLOCK
1235 * CLK_CAM [0]
1236 * CLK_TV [1]
1237 * CLK_MFC [2]
1238 * CLK_G3D [3]
1239 * CLK_LCD0 [4]
1240 * CLK_LCD1 [5]
1241 * CLK_GPS [7]
1242 */
Inha Song4e558532014-02-06 14:20:12 +09001243 setbits_le32(&clk->gate_block, 1 << 4);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001244
1245 /*
1246 * CLK_SRC_LCD0
1247 * FIMD0_SEL [3:0]
1248 * MDNIE0_SEL [7:4]
1249 * MDNIE_PWM0_SEL [8:11]
1250 * MIPI0_SEL [12:15]
1251 * set lcd0 src clock 0x6: SCLK_MPLL
1252 */
Inha Song4e558532014-02-06 14:20:12 +09001253 clrsetbits_le32(&clk->src_lcd0, 0xf, 0x6);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001254
1255 /*
1256 * CLK_GATE_IP_LCD0
1257 * CLK_FIMD0 [0]
1258 * CLK_MIE0 [1]
1259 * CLK_MDNIE0 [2]
1260 * CLK_DSIM0 [3]
1261 * CLK_SMMUFIMD0 [4]
1262 * CLK_PPMULCD0 [5]
1263 * Gating all clocks for FIMD0
1264 */
Inha Song4e558532014-02-06 14:20:12 +09001265 setbits_le32(&clk->gate_ip_lcd0, 1 << 0);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001266
1267 /*
1268 * CLK_DIV_LCD0
1269 * FIMD0_RATIO [3:0]
1270 * MDNIE0_RATIO [7:4]
1271 * MDNIE_PWM0_RATIO [11:8]
1272 * MDNIE_PWM_PRE_RATIO [15:12]
1273 * MIPI0_RATIO [19:16]
1274 * MIPI0_PRE_RATIO [23:20]
1275 * set fimd ratio
1276 */
Inha Song4e558532014-02-06 14:20:12 +09001277 clrsetbits_le32(&clk->div_lcd0, 0xf, 0x1);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001278}
1279
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001280void exynos5_set_lcd_clk(void)
1281{
1282 struct exynos5_clock *clk =
1283 (struct exynos5_clock *)samsung_get_base_clock();
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001284
1285 /*
1286 * CLK_GATE_BLOCK
1287 * CLK_CAM [0]
1288 * CLK_TV [1]
1289 * CLK_MFC [2]
1290 * CLK_G3D [3]
1291 * CLK_LCD0 [4]
1292 * CLK_LCD1 [5]
1293 * CLK_GPS [7]
1294 */
Inha Song4e558532014-02-06 14:20:12 +09001295 setbits_le32(&clk->gate_block, 1 << 4);
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001296
1297 /*
1298 * CLK_SRC_LCD0
1299 * FIMD0_SEL [3:0]
1300 * MDNIE0_SEL [7:4]
1301 * MDNIE_PWM0_SEL [8:11]
1302 * MIPI0_SEL [12:15]
1303 * set lcd0 src clock 0x6: SCLK_MPLL
1304 */
Inha Song4e558532014-02-06 14:20:12 +09001305 clrsetbits_le32(&clk->src_disp1_0, 0xf, 0x6);
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001306
1307 /*
1308 * CLK_GATE_IP_LCD0
1309 * CLK_FIMD0 [0]
1310 * CLK_MIE0 [1]
1311 * CLK_MDNIE0 [2]
1312 * CLK_DSIM0 [3]
1313 * CLK_SMMUFIMD0 [4]
1314 * CLK_PPMULCD0 [5]
1315 * Gating all clocks for FIMD0
1316 */
Inha Song4e558532014-02-06 14:20:12 +09001317 setbits_le32(&clk->gate_ip_disp1, 1 << 0);
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001318
1319 /*
1320 * CLK_DIV_LCD0
1321 * FIMD0_RATIO [3:0]
1322 * MDNIE0_RATIO [7:4]
1323 * MDNIE_PWM0_RATIO [11:8]
1324 * MDNIE_PWM_PRE_RATIO [15:12]
1325 * MIPI0_RATIO [19:16]
1326 * MIPI0_PRE_RATIO [23:20]
1327 * set fimd ratio
1328 */
Inha Song4e558532014-02-06 14:20:12 +09001329 clrsetbits_le32(&clk->div_disp1_0, 0xf, 0x0);
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001330}
1331
Ajay Kumar914af872014-09-05 16:53:32 +05301332void exynos5420_set_lcd_clk(void)
1333{
1334 struct exynos5420_clock *clk =
1335 (struct exynos5420_clock *)samsung_get_base_clock();
1336 unsigned int cfg;
1337
1338 /*
1339 * CLK_SRC_DISP10
1340 * FIMD1_SEL [4]
1341 * 0: SCLK_RPLL
1342 * 1: SCLK_SPLL
1343 */
1344 cfg = readl(&clk->src_disp10);
1345 cfg &= ~(0x1 << 4);
1346 cfg |= (0 << 4);
1347 writel(cfg, &clk->src_disp10);
1348
1349 /*
1350 * CLK_DIV_DISP10
1351 * FIMD1_RATIO [3:0]
1352 */
1353 cfg = readl(&clk->div_disp10);
1354 cfg &= ~(0xf << 0);
1355 cfg |= (0 << 0);
1356 writel(cfg, &clk->div_disp10);
1357}
1358
Donghwa Lee77ba1912012-04-05 19:36:12 +00001359void exynos4_set_mipi_clk(void)
1360{
1361 struct exynos4_clock *clk =
1362 (struct exynos4_clock *)samsung_get_base_clock();
Donghwa Lee77ba1912012-04-05 19:36:12 +00001363
1364 /*
1365 * CLK_SRC_LCD0
1366 * FIMD0_SEL [3:0]
1367 * MDNIE0_SEL [7:4]
1368 * MDNIE_PWM0_SEL [8:11]
1369 * MIPI0_SEL [12:15]
1370 * set mipi0 src clock 0x6: SCLK_MPLL
1371 */
Inha Song4e558532014-02-06 14:20:12 +09001372 clrsetbits_le32(&clk->src_lcd0, 0xf << 12, 0x6 << 12);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001373
1374 /*
1375 * CLK_SRC_MASK_LCD0
1376 * FIMD0_MASK [0]
1377 * MDNIE0_MASK [4]
1378 * MDNIE_PWM0_MASK [8]
1379 * MIPI0_MASK [12]
1380 * set src mask mipi0 0x1: Unmask
1381 */
Inha Song4e558532014-02-06 14:20:12 +09001382 setbits_le32(&clk->src_mask_lcd0, 0x1 << 12);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001383
1384 /*
1385 * CLK_GATE_IP_LCD0
1386 * CLK_FIMD0 [0]
1387 * CLK_MIE0 [1]
1388 * CLK_MDNIE0 [2]
1389 * CLK_DSIM0 [3]
1390 * CLK_SMMUFIMD0 [4]
1391 * CLK_PPMULCD0 [5]
1392 * Gating all clocks for MIPI0
1393 */
Inha Song4e558532014-02-06 14:20:12 +09001394 setbits_le32(&clk->gate_ip_lcd0, 1 << 3);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001395
1396 /*
1397 * CLK_DIV_LCD0
1398 * FIMD0_RATIO [3:0]
1399 * MDNIE0_RATIO [7:4]
1400 * MDNIE_PWM0_RATIO [11:8]
1401 * MDNIE_PWM_PRE_RATIO [15:12]
1402 * MIPI0_RATIO [19:16]
1403 * MIPI0_PRE_RATIO [23:20]
1404 * set mipi ratio
1405 */
Inha Song4e558532014-02-06 14:20:12 +09001406 clrsetbits_le32(&clk->div_lcd0, 0xf << 16, 0x1 << 16);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001407}
1408
Rajeshwari Shinde1c9412a2012-07-23 21:23:48 +00001409/*
1410 * I2C
1411 *
1412 * exynos5: obtaining the I2C clock
1413 */
1414static unsigned long exynos5_get_i2c_clk(void)
1415{
1416 struct exynos5_clock *clk =
1417 (struct exynos5_clock *)samsung_get_base_clock();
1418 unsigned long aclk_66, aclk_66_pre, sclk;
1419 unsigned int ratio;
1420
1421 sclk = get_pll_clk(MPLL);
1422
1423 ratio = (readl(&clk->div_top1)) >> 24;
1424 ratio &= 0x7;
1425 aclk_66_pre = sclk / (ratio + 1);
1426 ratio = readl(&clk->div_top0);
1427 ratio &= 0x7;
1428 aclk_66 = aclk_66_pre / (ratio + 1);
1429 return aclk_66;
1430}
1431
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001432int exynos5_set_epll_clk(unsigned long rate)
1433{
1434 unsigned int epll_con, epll_con_k;
1435 unsigned int i;
1436 unsigned int lockcnt;
1437 unsigned int start;
1438 struct exynos5_clock *clk =
1439 (struct exynos5_clock *)samsung_get_base_clock();
1440
1441 epll_con = readl(&clk->epll_con0);
1442 epll_con &= ~((EPLL_CON0_LOCK_DET_EN_MASK <<
1443 EPLL_CON0_LOCK_DET_EN_SHIFT) |
1444 EPLL_CON0_MDIV_MASK << EPLL_CON0_MDIV_SHIFT |
1445 EPLL_CON0_PDIV_MASK << EPLL_CON0_PDIV_SHIFT |
1446 EPLL_CON0_SDIV_MASK << EPLL_CON0_SDIV_SHIFT);
1447
1448 for (i = 0; i < ARRAY_SIZE(exynos5_epll_div); i++) {
1449 if (exynos5_epll_div[i].freq_out == rate)
1450 break;
1451 }
1452
1453 if (i == ARRAY_SIZE(exynos5_epll_div))
1454 return -1;
1455
1456 epll_con_k = exynos5_epll_div[i].k_dsm << 0;
1457 epll_con |= exynos5_epll_div[i].en_lock_det <<
1458 EPLL_CON0_LOCK_DET_EN_SHIFT;
1459 epll_con |= exynos5_epll_div[i].m_div << EPLL_CON0_MDIV_SHIFT;
1460 epll_con |= exynos5_epll_div[i].p_div << EPLL_CON0_PDIV_SHIFT;
1461 epll_con |= exynos5_epll_div[i].s_div << EPLL_CON0_SDIV_SHIFT;
1462
1463 /*
1464 * Required period ( in cycles) to genarate a stable clock output.
1465 * The maximum clock time can be up to 3000 * PDIV cycles of PLLs
1466 * frequency input (as per spec)
1467 */
1468 lockcnt = 3000 * exynos5_epll_div[i].p_div;
1469
1470 writel(lockcnt, &clk->epll_lock);
1471 writel(epll_con, &clk->epll_con0);
1472 writel(epll_con_k, &clk->epll_con1);
1473
1474 start = get_timer(0);
1475
1476 while (!(readl(&clk->epll_con0) &
1477 (0x1 << EXYNOS5_EPLLCON0_LOCKED_SHIFT))) {
1478 if (get_timer(start) > TIMEOUT_EPLL_LOCK) {
1479 debug("%s: Timeout waiting for EPLL lock\n", __func__);
1480 return -1;
1481 }
1482 }
1483 return 0;
1484}
1485
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301486int exynos5_set_i2s_clk_source(unsigned int i2s_id)
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001487{
1488 struct exynos5_clock *clk =
1489 (struct exynos5_clock *)samsung_get_base_clock();
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301490 unsigned int *audio_ass = (unsigned int *)samsung_get_base_audio_ass();
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001491
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301492 if (i2s_id == 0) {
1493 setbits_le32(&clk->src_top2, CLK_SRC_MOUT_EPLL);
1494 clrsetbits_le32(&clk->src_mau, AUDIO0_SEL_MASK,
1495 (CLK_SRC_SCLK_EPLL));
1496 setbits_le32(audio_ass, AUDIO_CLKMUX_ASS);
1497 } else if (i2s_id == 1) {
1498 clrsetbits_le32(&clk->src_peric1, AUDIO1_SEL_MASK,
1499 (CLK_SRC_SCLK_EPLL));
1500 } else {
1501 return -1;
1502 }
1503 return 0;
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001504}
1505
1506int exynos5_set_i2s_clk_prescaler(unsigned int src_frq,
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301507 unsigned int dst_frq,
1508 unsigned int i2s_id)
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001509{
1510 struct exynos5_clock *clk =
1511 (struct exynos5_clock *)samsung_get_base_clock();
1512 unsigned int div;
1513
1514 if ((dst_frq == 0) || (src_frq == 0)) {
1515 debug("%s: Invalid requency input for prescaler\n", __func__);
1516 debug("src frq = %d des frq = %d ", src_frq, dst_frq);
1517 return -1;
1518 }
1519
1520 div = (src_frq / dst_frq);
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301521 if (i2s_id == 0) {
1522 if (div > AUDIO_0_RATIO_MASK) {
1523 debug("%s: Frequency ratio is out of range\n",
1524 __func__);
1525 debug("src frq = %d des frq = %d ", src_frq, dst_frq);
1526 return -1;
1527 }
1528 clrsetbits_le32(&clk->div_mau, AUDIO_0_RATIO_MASK,
1529 (div & AUDIO_0_RATIO_MASK));
1530 } else if(i2s_id == 1) {
1531 if (div > AUDIO_1_RATIO_MASK) {
1532 debug("%s: Frequency ratio is out of range\n",
1533 __func__);
1534 debug("src frq = %d des frq = %d ", src_frq, dst_frq);
1535 return -1;
1536 }
1537 clrsetbits_le32(&clk->div_peric4, AUDIO_1_RATIO_MASK,
1538 (div & AUDIO_1_RATIO_MASK));
1539 } else {
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001540 return -1;
1541 }
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001542 return 0;
1543}
1544
Hatim RVe6365b62012-11-02 01:15:34 +00001545/**
1546 * Linearly searches for the most accurate main and fine stage clock scalars
1547 * (divisors) for a specified target frequency and scalar bit sizes by checking
1548 * all multiples of main_scalar_bits values. Will always return scalars up to or
1549 * slower than target.
1550 *
1551 * @param main_scalar_bits Number of main scalar bits, must be > 0 and < 32
1552 * @param fine_scalar_bits Number of fine scalar bits, must be > 0 and < 32
1553 * @param input_freq Clock frequency to be scaled in Hz
1554 * @param target_freq Desired clock frequency in Hz
1555 * @param best_fine_scalar Pointer to store the fine stage divisor
1556 *
1557 * @return best_main_scalar Main scalar for desired frequency or -1 if none
1558 * found
1559 */
1560static int clock_calc_best_scalar(unsigned int main_scaler_bits,
1561 unsigned int fine_scalar_bits, unsigned int input_rate,
1562 unsigned int target_rate, unsigned int *best_fine_scalar)
1563{
1564 int i;
1565 int best_main_scalar = -1;
1566 unsigned int best_error = target_rate;
1567 const unsigned int cap = (1 << fine_scalar_bits) - 1;
1568 const unsigned int loops = 1 << main_scaler_bits;
1569
1570 debug("Input Rate is %u, Target is %u, Cap is %u\n", input_rate,
1571 target_rate, cap);
1572
1573 assert(best_fine_scalar != NULL);
1574 assert(main_scaler_bits <= fine_scalar_bits);
1575
1576 *best_fine_scalar = 1;
1577
1578 if (input_rate == 0 || target_rate == 0)
1579 return -1;
1580
1581 if (target_rate >= input_rate)
1582 return 1;
1583
1584 for (i = 1; i <= loops; i++) {
Masahiro Yamadadb204642014-11-07 03:03:31 +09001585 const unsigned int effective_div =
1586 max(min(input_rate / i / target_rate, cap), 1U);
Hatim RVe6365b62012-11-02 01:15:34 +00001587 const unsigned int effective_rate = input_rate / i /
1588 effective_div;
1589 const int error = target_rate - effective_rate;
1590
1591 debug("%d|effdiv:%u, effrate:%u, error:%d\n", i, effective_div,
1592 effective_rate, error);
1593
1594 if (error >= 0 && error <= best_error) {
1595 best_error = error;
1596 best_main_scalar = i;
1597 *best_fine_scalar = effective_div;
1598 }
1599 }
1600
1601 return best_main_scalar;
1602}
1603
1604static int exynos5_set_spi_clk(enum periph_id periph_id,
1605 unsigned int rate)
1606{
1607 struct exynos5_clock *clk =
1608 (struct exynos5_clock *)samsung_get_base_clock();
1609 int main;
1610 unsigned int fine;
1611 unsigned shift, pre_shift;
1612 unsigned mask = 0xff;
1613 u32 *reg;
1614
1615 main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine);
1616 if (main < 0) {
1617 debug("%s: Cannot set clock rate for periph %d",
1618 __func__, periph_id);
1619 return -1;
1620 }
1621 main = main - 1;
1622 fine = fine - 1;
1623
1624 switch (periph_id) {
1625 case PERIPH_ID_SPI0:
1626 reg = &clk->div_peric1;
1627 shift = 0;
1628 pre_shift = 8;
1629 break;
1630 case PERIPH_ID_SPI1:
1631 reg = &clk->div_peric1;
1632 shift = 16;
1633 pre_shift = 24;
1634 break;
1635 case PERIPH_ID_SPI2:
1636 reg = &clk->div_peric2;
1637 shift = 0;
1638 pre_shift = 8;
1639 break;
1640 case PERIPH_ID_SPI3:
1641 reg = &clk->sclk_div_isp;
1642 shift = 0;
1643 pre_shift = 4;
1644 break;
1645 case PERIPH_ID_SPI4:
1646 reg = &clk->sclk_div_isp;
1647 shift = 12;
1648 pre_shift = 16;
1649 break;
1650 default:
1651 debug("%s: Unsupported peripheral ID %d\n", __func__,
1652 periph_id);
1653 return -1;
1654 }
1655 clrsetbits_le32(reg, mask << shift, (main & mask) << shift);
1656 clrsetbits_le32(reg, mask << pre_shift, (fine & mask) << pre_shift);
1657
1658 return 0;
1659}
1660
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301661static int exynos5420_set_spi_clk(enum periph_id periph_id,
1662 unsigned int rate)
1663{
1664 struct exynos5420_clock *clk =
1665 (struct exynos5420_clock *)samsung_get_base_clock();
1666 int main;
1667 unsigned int fine;
1668 unsigned shift, pre_shift;
1669 unsigned div_mask = 0xf, pre_div_mask = 0xff;
1670 u32 *reg;
1671 u32 *pre_reg;
1672
1673 main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine);
1674 if (main < 0) {
1675 debug("%s: Cannot set clock rate for periph %d",
1676 __func__, periph_id);
1677 return -1;
1678 }
1679 main = main - 1;
1680 fine = fine - 1;
1681
1682 switch (periph_id) {
1683 case PERIPH_ID_SPI0:
1684 reg = &clk->div_peric1;
1685 shift = 20;
1686 pre_reg = &clk->div_peric4;
1687 pre_shift = 8;
1688 break;
1689 case PERIPH_ID_SPI1:
1690 reg = &clk->div_peric1;
1691 shift = 24;
1692 pre_reg = &clk->div_peric4;
1693 pre_shift = 16;
1694 break;
1695 case PERIPH_ID_SPI2:
1696 reg = &clk->div_peric1;
1697 shift = 28;
1698 pre_reg = &clk->div_peric4;
1699 pre_shift = 24;
1700 break;
1701 case PERIPH_ID_SPI3:
1702 reg = &clk->div_isp1;
1703 shift = 16;
1704 pre_reg = &clk->div_isp1;
1705 pre_shift = 0;
1706 break;
1707 case PERIPH_ID_SPI4:
1708 reg = &clk->div_isp1;
1709 shift = 20;
1710 pre_reg = &clk->div_isp1;
1711 pre_shift = 8;
1712 break;
1713 default:
1714 debug("%s: Unsupported peripheral ID %d\n", __func__,
1715 periph_id);
1716 return -1;
1717 }
1718
1719 clrsetbits_le32(reg, div_mask << shift, (main & div_mask) << shift);
1720 clrsetbits_le32(pre_reg, pre_div_mask << pre_shift,
1721 (fine & pre_div_mask) << pre_shift);
1722
1723 return 0;
1724}
1725
Piotr Wilczek01d589f2012-11-20 02:19:02 +00001726static unsigned long exynos4_get_i2c_clk(void)
1727{
1728 struct exynos4_clock *clk =
1729 (struct exynos4_clock *)samsung_get_base_clock();
1730 unsigned long sclk, aclk_100;
1731 unsigned int ratio;
1732
1733 sclk = get_pll_clk(APLL);
1734
1735 ratio = (readl(&clk->div_top)) >> 4;
1736 ratio &= 0xf;
1737 aclk_100 = sclk / (ratio + 1);
1738 return aclk_100;
Minkyu Kangb1b24682011-01-24 15:22:23 +09001739}
1740
1741unsigned long get_pll_clk(int pllreg)
1742{
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301743 if (cpu_is_exynos5()) {
Akshay Saraswat9fba7b42014-11-13 22:38:15 +05301744 if (proid_is_exynos5420() || proid_is_exynos5800())
Akshay Saraswat1bd40e42015-02-04 16:00:00 +05301745 return exynos542x_get_pll_clk(pllreg);
Chander Kashyap34076a02012-02-05 23:01:46 +00001746 return exynos5_get_pll_clk(pllreg);
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301747 } else {
Chander Kashyap400ab162012-10-07 01:43:17 +00001748 if (proid_is_exynos4412())
1749 return exynos4x12_get_pll_clk(pllreg);
Chander Kashyap34076a02012-02-05 23:01:46 +00001750 return exynos4_get_pll_clk(pllreg);
Chander Kashyap400ab162012-10-07 01:43:17 +00001751 }
Minkyu Kangb1b24682011-01-24 15:22:23 +09001752}
1753
1754unsigned long get_arm_clk(void)
1755{
Chander Kashyap34076a02012-02-05 23:01:46 +00001756 if (cpu_is_exynos5())
1757 return exynos5_get_arm_clk();
Chander Kashyap400ab162012-10-07 01:43:17 +00001758 else {
1759 if (proid_is_exynos4412())
1760 return exynos4x12_get_arm_clk();
Chander Kashyap34076a02012-02-05 23:01:46 +00001761 return exynos4_get_arm_clk();
Chander Kashyap400ab162012-10-07 01:43:17 +00001762 }
Minkyu Kangb1b24682011-01-24 15:22:23 +09001763}
1764
Rajeshwari Shinde1c9412a2012-07-23 21:23:48 +00001765unsigned long get_i2c_clk(void)
1766{
1767 if (cpu_is_exynos5()) {
1768 return exynos5_get_i2c_clk();
Piotr Wilczek01d589f2012-11-20 02:19:02 +00001769 } else if (cpu_is_exynos4()) {
1770 return exynos4_get_i2c_clk();
Rajeshwari Shinde1c9412a2012-07-23 21:23:48 +00001771 } else {
1772 debug("I2C clock is not set for this CPU\n");
1773 return 0;
1774 }
1775}
1776
Minkyu Kangb1b24682011-01-24 15:22:23 +09001777unsigned long get_pwm_clk(void)
1778{
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301779 if (cpu_is_exynos5()) {
Akshay Saraswat9fba7b42014-11-13 22:38:15 +05301780 if (proid_is_exynos5420() || proid_is_exynos5800())
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301781 return exynos5420_get_pwm_clk();
Padmavathi Vennabb714162013-03-28 04:32:23 +00001782 return clock_get_periph_rate(PERIPH_ID_PWM0);
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301783 } else {
Chander Kashyap400ab162012-10-07 01:43:17 +00001784 if (proid_is_exynos4412())
1785 return exynos4x12_get_pwm_clk();
Chander Kashyap34076a02012-02-05 23:01:46 +00001786 return exynos4_get_pwm_clk();
Chander Kashyap400ab162012-10-07 01:43:17 +00001787 }
Minkyu Kangb1b24682011-01-24 15:22:23 +09001788}
1789
1790unsigned long get_uart_clk(int dev_index)
1791{
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301792 if (cpu_is_exynos5()) {
Akshay Saraswat9fba7b42014-11-13 22:38:15 +05301793 if (proid_is_exynos5420() || proid_is_exynos5800())
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301794 return exynos5420_get_uart_clk(dev_index);
Chander Kashyap34076a02012-02-05 23:01:46 +00001795 return exynos5_get_uart_clk(dev_index);
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301796 } else {
Chander Kashyap400ab162012-10-07 01:43:17 +00001797 if (proid_is_exynos4412())
1798 return exynos4x12_get_uart_clk(dev_index);
Chander Kashyap34076a02012-02-05 23:01:46 +00001799 return exynos4_get_uart_clk(dev_index);
Chander Kashyap400ab162012-10-07 01:43:17 +00001800 }
Minkyu Kangb1b24682011-01-24 15:22:23 +09001801}
Jaehoon Chung9a772212011-05-17 21:19:17 +00001802
Jaehoon Chung8788e062012-12-27 22:30:32 +00001803unsigned long get_mmc_clk(int dev_index)
1804{
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301805 if (cpu_is_exynos5()) {
Akshay Saraswat9fba7b42014-11-13 22:38:15 +05301806 if (proid_is_exynos5420() || proid_is_exynos5800())
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301807 return exynos5420_get_mmc_clk(dev_index);
Jaehoon Chung8788e062012-12-27 22:30:32 +00001808 return exynos5_get_mmc_clk(dev_index);
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301809 } else {
Jaehoon Chung8788e062012-12-27 22:30:32 +00001810 return exynos4_get_mmc_clk(dev_index);
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301811 }
Jaehoon Chung8788e062012-12-27 22:30:32 +00001812}
1813
Jaehoon Chung9a772212011-05-17 21:19:17 +00001814void set_mmc_clk(int dev_index, unsigned int div)
1815{
Jaehoon Chung15cd6b52015-01-08 16:50:21 +09001816 /* If want to set correct value, it needs to substract one from div.*/
1817 if (div > 0)
1818 div -= 1;
1819
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301820 if (cpu_is_exynos5()) {
Akshay Saraswat9fba7b42014-11-13 22:38:15 +05301821 if (proid_is_exynos5420() || proid_is_exynos5800())
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301822 exynos5420_set_mmc_clk(dev_index, div);
1823 else
1824 exynos5_set_mmc_clk(dev_index, div);
1825 } else {
Beomho Seo99660cc2014-05-16 13:59:47 +09001826 exynos4_set_mmc_clk(dev_index, div);
Chander Kashyap400ab162012-10-07 01:43:17 +00001827 }
Jaehoon Chung9a772212011-05-17 21:19:17 +00001828}
Donghwa Lee77ba1912012-04-05 19:36:12 +00001829
1830unsigned long get_lcd_clk(void)
1831{
1832 if (cpu_is_exynos4())
1833 return exynos4_get_lcd_clk();
Ajay Kumar914af872014-09-05 16:53:32 +05301834 else {
Akshay Saraswat9fba7b42014-11-13 22:38:15 +05301835 if (proid_is_exynos5420() || proid_is_exynos5800())
Ajay Kumar914af872014-09-05 16:53:32 +05301836 return exynos5420_get_lcd_clk();
1837 else
1838 return exynos5_get_lcd_clk();
1839 }
Donghwa Lee77ba1912012-04-05 19:36:12 +00001840}
1841
1842void set_lcd_clk(void)
1843{
1844 if (cpu_is_exynos4())
1845 exynos4_set_lcd_clk();
Ajay Kumar914af872014-09-05 16:53:32 +05301846 else {
1847 if (proid_is_exynos5250())
1848 exynos5_set_lcd_clk();
Akshay Saraswat9fba7b42014-11-13 22:38:15 +05301849 else if (proid_is_exynos5420() || proid_is_exynos5800())
Ajay Kumar914af872014-09-05 16:53:32 +05301850 exynos5420_set_lcd_clk();
1851 }
Donghwa Lee77ba1912012-04-05 19:36:12 +00001852}
1853
1854void set_mipi_clk(void)
1855{
1856 if (cpu_is_exynos4())
1857 exynos4_set_mipi_clk();
1858}
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001859
Hatim RVe6365b62012-11-02 01:15:34 +00001860int set_spi_clk(int periph_id, unsigned int rate)
1861{
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301862 if (cpu_is_exynos5()) {
Akshay Saraswat9fba7b42014-11-13 22:38:15 +05301863 if (proid_is_exynos5420() || proid_is_exynos5800())
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301864 return exynos5420_set_spi_clk(periph_id, rate);
Hatim RVe6365b62012-11-02 01:15:34 +00001865 return exynos5_set_spi_clk(periph_id, rate);
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301866 } else {
Hatim RVe6365b62012-11-02 01:15:34 +00001867 return 0;
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301868 }
Hatim RVe6365b62012-11-02 01:15:34 +00001869}
1870
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301871int set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq,
1872 unsigned int i2s_id)
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001873{
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001874 if (cpu_is_exynos5())
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301875 return exynos5_set_i2s_clk_prescaler(src_frq, dst_frq, i2s_id);
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001876 else
1877 return 0;
1878}
1879
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301880int set_i2s_clk_source(unsigned int i2s_id)
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001881{
1882 if (cpu_is_exynos5())
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301883 return exynos5_set_i2s_clk_source(i2s_id);
1884 else
1885 return 0;
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001886}
1887
1888int set_epll_clk(unsigned long rate)
1889{
1890 if (cpu_is_exynos5())
1891 return exynos5_set_epll_clk(rate);
1892 else
1893 return 0;
1894}