blob: 0153314b45e5f16e87e2c71a5a876a4c0ea40e60 [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);
Akshay Saraswatbad6a982015-02-04 16:00:02 +0530365 unsigned long sclk, sub_clk = 0;
366 unsigned int src, div, sub_div = 0;
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000367 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:
Akshay Saraswatbad6a982015-02-04 16:00:02 +0530405 src = readl(&clk->src_fsys);
406 div = readl(&clk->div_fsys1);
407 break;
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000408 case PERIPH_ID_SDMMC2:
409 case PERIPH_ID_SDMMC3:
410 src = readl(&clk->src_fsys);
Akshay Saraswatbad6a982015-02-04 16:00:02 +0530411 div = readl(&clk->div_fsys2);
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000412 break;
413 case PERIPH_ID_I2C0:
414 case PERIPH_ID_I2C1:
415 case PERIPH_ID_I2C2:
416 case PERIPH_ID_I2C3:
417 case PERIPH_ID_I2C4:
418 case PERIPH_ID_I2C5:
419 case PERIPH_ID_I2C6:
420 case PERIPH_ID_I2C7:
421 sclk = exynos5_get_pll_clk(MPLL);
422 sub_div = ((readl(&clk->div_top1) >> bit_info->div_bit)
423 & 0x7) + 1;
424 div = ((readl(&clk->div_top0) >> bit_info->prediv_bit)
425 & 0x7) + 1;
426 return (sclk / sub_div) / div;
427 default:
428 debug("%s: invalid peripheral %d", __func__, peripheral);
429 return -1;
430 };
431
Akshay Saraswatbad6a982015-02-04 16:00:02 +0530432 if (bit_info->src_bit >= 0)
433 src = (src >> bit_info->src_bit) & 0xf;
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000434
435 switch (src) {
436 case EXYNOS_SRC_MPLL:
437 sclk = exynos5_get_pll_clk(MPLL);
438 break;
439 case EXYNOS_SRC_EPLL:
440 sclk = exynos5_get_pll_clk(EPLL);
441 break;
442 case EXYNOS_SRC_VPLL:
443 sclk = exynos5_get_pll_clk(VPLL);
444 break;
445 default:
446 return 0;
447 }
448
449 /* Ratio clock division for this peripheral */
Akshay Saraswatbad6a982015-02-04 16:00:02 +0530450 if (bit_info->div_bit >= 0) {
451 sub_div = (div >> bit_info->div_bit) & 0xf;
452 sub_clk = sclk / (sub_div + 1);
453 }
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000454
Akshay Saraswatbad6a982015-02-04 16:00:02 +0530455 if (bit_info->prediv_bit >= 0) {
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000456 div = (div >> bit_info->prediv_bit) & 0xff;
457 return sub_clk / (div + 1);
458 }
459
460 return sub_clk;
461}
462
Akshay Saraswatd5072262015-02-04 16:00:01 +0530463static unsigned long exynos542x_get_periph_rate(int peripheral)
464{
465 struct clk_bit_info *bit_info = get_clk_bit_info(peripheral);
466 unsigned long sclk, sub_clk = 0;
467 unsigned int src, div, sub_div = 0;
468 struct exynos5420_clock *clk =
469 (struct exynos5420_clock *)samsung_get_base_clock();
470
471 switch (peripheral) {
472 case PERIPH_ID_UART0:
473 case PERIPH_ID_UART1:
474 case PERIPH_ID_UART2:
475 case PERIPH_ID_UART3:
476 case PERIPH_ID_PWM0:
477 case PERIPH_ID_PWM1:
478 case PERIPH_ID_PWM2:
479 case PERIPH_ID_PWM3:
480 case PERIPH_ID_PWM4:
481 src = readl(&clk->src_peric0);
482 div = readl(&clk->div_peric0);
483 break;
484 case PERIPH_ID_SPI0:
485 case PERIPH_ID_SPI1:
486 case PERIPH_ID_SPI2:
487 src = readl(&clk->src_peric1);
488 div = readl(&clk->div_peric1);
489 sub_div = readl(&clk->div_peric4);
490 break;
491 case PERIPH_ID_SPI3:
492 case PERIPH_ID_SPI4:
493 src = readl(&clk->src_isp);
494 div = readl(&clk->div_isp1);
495 sub_div = readl(&clk->div_isp1);
496 break;
497 case PERIPH_ID_SDMMC0:
498 case PERIPH_ID_SDMMC1:
499 case PERIPH_ID_SDMMC2:
500 case PERIPH_ID_SDMMC3:
501 src = readl(&clk->src_fsys);
502 div = readl(&clk->div_fsys1);
503 break;
504 case PERIPH_ID_I2C0:
505 case PERIPH_ID_I2C1:
506 case PERIPH_ID_I2C2:
507 case PERIPH_ID_I2C3:
508 case PERIPH_ID_I2C4:
509 case PERIPH_ID_I2C5:
510 case PERIPH_ID_I2C6:
511 case PERIPH_ID_I2C7:
512 case PERIPH_ID_I2C8:
513 case PERIPH_ID_I2C9:
514 case PERIPH_ID_I2C10:
515 sclk = exynos542x_get_pll_clk(MPLL);
516 sub_div = ((readl(&clk->div_top1) >> bit_info->div_bit)
517 & 0x7) + 1;
518 return sclk / sub_div;
519 default:
520 debug("%s: invalid peripheral %d", __func__, peripheral);
521 return -1;
522 };
523
524 if (bit_info->src_bit >= 0)
525 src = (src >> bit_info->src_bit) & 0xf;
526
527 switch (src) {
528 case EXYNOS542X_SRC_MPLL:
529 sclk = exynos542x_get_pll_clk(MPLL);
530 break;
531 case EXYNOS542X_SRC_SPLL:
532 sclk = exynos542x_get_pll_clk(SPLL);
533 break;
534 case EXYNOS542X_SRC_EPLL:
535 sclk = exynos542x_get_pll_clk(EPLL);
536 break;
537 case EXYNOS542X_SRC_RPLL:
538 sclk = exynos542x_get_pll_clk(RPLL);
539 break;
540 default:
541 return 0;
542 }
543
544 /* Ratio clock division for this peripheral */
545 if (bit_info->div_bit >= 0) {
546 div = (div >> bit_info->div_bit) & 0xf;
547 sub_clk = sclk / (div + 1);
548 }
549
550 if (bit_info->prediv_bit >= 0) {
551 sub_div = (sub_div >> bit_info->prediv_bit) & 0xff;
552 return sub_clk / (sub_div + 1);
553 }
554
555 return sub_clk;
556}
557
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000558unsigned long clock_get_periph_rate(int peripheral)
559{
Akshay Saraswatd5072262015-02-04 16:00:01 +0530560 if (cpu_is_exynos5()) {
561 if (proid_is_exynos5420() || proid_is_exynos5800())
562 return exynos542x_get_periph_rate(peripheral);
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000563 return exynos5_get_periph_rate(peripheral);
Akshay Saraswatd5072262015-02-04 16:00:01 +0530564 } else {
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000565 return 0;
Akshay Saraswatd5072262015-02-04 16:00:01 +0530566 }
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000567}
568
Chander Kashyap4131a772011-12-06 23:34:12 +0000569/* exynos4: return ARM clock frequency */
570static unsigned long exynos4_get_arm_clk(void)
Minkyu Kangb1b24682011-01-24 15:22:23 +0900571{
Chander Kashyap4131a772011-12-06 23:34:12 +0000572 struct exynos4_clock *clk =
573 (struct exynos4_clock *)samsung_get_base_clock();
Minkyu Kangb1b24682011-01-24 15:22:23 +0900574 unsigned long div;
Chander Kashyap3c7721f2011-12-18 22:56:44 +0000575 unsigned long armclk;
576 unsigned int core_ratio;
577 unsigned int core2_ratio;
Minkyu Kangb1b24682011-01-24 15:22:23 +0900578
579 div = readl(&clk->div_cpu0);
580
Chander Kashyap3c7721f2011-12-18 22:56:44 +0000581 /* CORE_RATIO: [2:0], CORE2_RATIO: [30:28] */
582 core_ratio = (div >> 0) & 0x7;
583 core2_ratio = (div >> 28) & 0x7;
Minkyu Kangb1b24682011-01-24 15:22:23 +0900584
Chander Kashyap3c7721f2011-12-18 22:56:44 +0000585 armclk = get_pll_clk(APLL) / (core_ratio + 1);
586 armclk /= (core2_ratio + 1);
Minkyu Kangb1b24682011-01-24 15:22:23 +0900587
Chander Kashyap3c7721f2011-12-18 22:56:44 +0000588 return armclk;
Minkyu Kangb1b24682011-01-24 15:22:23 +0900589}
590
Chander Kashyap400ab162012-10-07 01:43:17 +0000591/* exynos4x12: return ARM clock frequency */
592static unsigned long exynos4x12_get_arm_clk(void)
593{
594 struct exynos4x12_clock *clk =
595 (struct exynos4x12_clock *)samsung_get_base_clock();
596 unsigned long div;
597 unsigned long armclk;
598 unsigned int core_ratio;
599 unsigned int core2_ratio;
600
601 div = readl(&clk->div_cpu0);
602
603 /* CORE_RATIO: [2:0], CORE2_RATIO: [30:28] */
604 core_ratio = (div >> 0) & 0x7;
605 core2_ratio = (div >> 28) & 0x7;
606
607 armclk = get_pll_clk(APLL) / (core_ratio + 1);
608 armclk /= (core2_ratio + 1);
609
610 return armclk;
611}
612
Chander Kashyap34076a02012-02-05 23:01:46 +0000613/* exynos5: return ARM clock frequency */
614static unsigned long exynos5_get_arm_clk(void)
615{
616 struct exynos5_clock *clk =
617 (struct exynos5_clock *)samsung_get_base_clock();
618 unsigned long div;
619 unsigned long armclk;
620 unsigned int arm_ratio;
621 unsigned int arm2_ratio;
622
623 div = readl(&clk->div_cpu0);
624
625 /* ARM_RATIO: [2:0], ARM2_RATIO: [30:28] */
626 arm_ratio = (div >> 0) & 0x7;
627 arm2_ratio = (div >> 28) & 0x7;
628
629 armclk = get_pll_clk(APLL) / (arm_ratio + 1);
630 armclk /= (arm2_ratio + 1);
631
632 return armclk;
633}
634
Chander Kashyap4131a772011-12-06 23:34:12 +0000635/* exynos4: return pwm clock frequency */
636static unsigned long exynos4_get_pwm_clk(void)
Minkyu Kangb1b24682011-01-24 15:22:23 +0900637{
Chander Kashyap4131a772011-12-06 23:34:12 +0000638 struct exynos4_clock *clk =
639 (struct exynos4_clock *)samsung_get_base_clock();
Minkyu Kangb1b24682011-01-24 15:22:23 +0900640 unsigned long pclk, sclk;
641 unsigned int sel;
642 unsigned int ratio;
643
Minkyu Kang69b28242011-05-18 16:57:55 +0900644 if (s5p_get_cpu_rev() == 0) {
645 /*
646 * CLK_SRC_PERIL0
647 * PWM_SEL [27:24]
648 */
649 sel = readl(&clk->src_peril0);
650 sel = (sel >> 24) & 0xf;
Minkyu Kangb1b24682011-01-24 15:22:23 +0900651
Minkyu Kang69b28242011-05-18 16:57:55 +0900652 if (sel == 0x6)
653 sclk = get_pll_clk(MPLL);
654 else if (sel == 0x7)
655 sclk = get_pll_clk(EPLL);
656 else if (sel == 0x8)
657 sclk = get_pll_clk(VPLL);
658 else
659 return 0;
660
661 /*
662 * CLK_DIV_PERIL3
663 * PWM_RATIO [3:0]
664 */
665 ratio = readl(&clk->div_peril3);
666 ratio = ratio & 0xf;
667 } else if (s5p_get_cpu_rev() == 1) {
Minkyu Kangb1b24682011-01-24 15:22:23 +0900668 sclk = get_pll_clk(MPLL);
Minkyu Kang69b28242011-05-18 16:57:55 +0900669 ratio = 8;
670 } else
Minkyu Kangb1b24682011-01-24 15:22:23 +0900671 return 0;
672
Minkyu Kangb1b24682011-01-24 15:22:23 +0900673 pclk = sclk / (ratio + 1);
674
675 return pclk;
676}
677
Chander Kashyap400ab162012-10-07 01:43:17 +0000678/* exynos4x12: return pwm clock frequency */
679static unsigned long exynos4x12_get_pwm_clk(void)
680{
681 unsigned long pclk, sclk;
682 unsigned int ratio;
683
684 sclk = get_pll_clk(MPLL);
685 ratio = 8;
686
687 pclk = sclk / (ratio + 1);
688
689 return pclk;
690}
691
Rajeshwari Birjeac892d02013-12-26 09:44:21 +0530692/* exynos5420: return pwm clock frequency */
693static unsigned long exynos5420_get_pwm_clk(void)
694{
695 struct exynos5420_clock *clk =
696 (struct exynos5420_clock *)samsung_get_base_clock();
697 unsigned long pclk, sclk;
698 unsigned int ratio;
699
700 /*
701 * CLK_DIV_PERIC0
702 * PWM_RATIO [31:28]
703 */
704 ratio = readl(&clk->div_peric0);
705 ratio = (ratio >> 28) & 0xf;
706 sclk = get_pll_clk(MPLL);
707
708 pclk = sclk / (ratio + 1);
709
710 return pclk;
711}
712
Chander Kashyap4131a772011-12-06 23:34:12 +0000713/* exynos4: return uart clock frequency */
714static unsigned long exynos4_get_uart_clk(int dev_index)
Minkyu Kangb1b24682011-01-24 15:22:23 +0900715{
Chander Kashyap4131a772011-12-06 23:34:12 +0000716 struct exynos4_clock *clk =
717 (struct exynos4_clock *)samsung_get_base_clock();
Minkyu Kangb1b24682011-01-24 15:22:23 +0900718 unsigned long uclk, sclk;
719 unsigned int sel;
720 unsigned int ratio;
721
722 /*
723 * CLK_SRC_PERIL0
724 * UART0_SEL [3:0]
725 * UART1_SEL [7:4]
726 * UART2_SEL [8:11]
727 * UART3_SEL [12:15]
728 * UART4_SEL [16:19]
729 * UART5_SEL [23:20]
730 */
731 sel = readl(&clk->src_peril0);
732 sel = (sel >> (dev_index << 2)) & 0xf;
733
734 if (sel == 0x6)
735 sclk = get_pll_clk(MPLL);
736 else if (sel == 0x7)
737 sclk = get_pll_clk(EPLL);
738 else if (sel == 0x8)
739 sclk = get_pll_clk(VPLL);
740 else
741 return 0;
742
743 /*
744 * CLK_DIV_PERIL0
745 * UART0_RATIO [3:0]
746 * UART1_RATIO [7:4]
747 * UART2_RATIO [8:11]
748 * UART3_RATIO [12:15]
749 * UART4_RATIO [16:19]
750 * UART5_RATIO [23:20]
751 */
752 ratio = readl(&clk->div_peril0);
753 ratio = (ratio >> (dev_index << 2)) & 0xf;
754
755 uclk = sclk / (ratio + 1);
756
757 return uclk;
758}
759
Chander Kashyap400ab162012-10-07 01:43:17 +0000760/* exynos4x12: return uart clock frequency */
761static unsigned long exynos4x12_get_uart_clk(int dev_index)
762{
763 struct exynos4x12_clock *clk =
764 (struct exynos4x12_clock *)samsung_get_base_clock();
765 unsigned long uclk, sclk;
766 unsigned int sel;
767 unsigned int ratio;
768
769 /*
770 * CLK_SRC_PERIL0
771 * UART0_SEL [3:0]
772 * UART1_SEL [7:4]
773 * UART2_SEL [8:11]
774 * UART3_SEL [12:15]
775 * UART4_SEL [16:19]
776 */
777 sel = readl(&clk->src_peril0);
778 sel = (sel >> (dev_index << 2)) & 0xf;
779
780 if (sel == 0x6)
781 sclk = get_pll_clk(MPLL);
782 else if (sel == 0x7)
783 sclk = get_pll_clk(EPLL);
784 else if (sel == 0x8)
785 sclk = get_pll_clk(VPLL);
786 else
787 return 0;
788
789 /*
790 * CLK_DIV_PERIL0
791 * UART0_RATIO [3:0]
792 * UART1_RATIO [7:4]
793 * UART2_RATIO [8:11]
794 * UART3_RATIO [12:15]
795 * UART4_RATIO [16:19]
796 */
797 ratio = readl(&clk->div_peril0);
798 ratio = (ratio >> (dev_index << 2)) & 0xf;
799
800 uclk = sclk / (ratio + 1);
801
802 return uclk;
803}
804
Chander Kashyap34076a02012-02-05 23:01:46 +0000805/* exynos5: return uart clock frequency */
806static unsigned long exynos5_get_uart_clk(int dev_index)
807{
808 struct exynos5_clock *clk =
809 (struct exynos5_clock *)samsung_get_base_clock();
810 unsigned long uclk, sclk;
811 unsigned int sel;
812 unsigned int ratio;
813
814 /*
815 * CLK_SRC_PERIC0
816 * UART0_SEL [3:0]
817 * UART1_SEL [7:4]
818 * UART2_SEL [8:11]
819 * UART3_SEL [12:15]
820 * UART4_SEL [16:19]
821 * UART5_SEL [23:20]
822 */
823 sel = readl(&clk->src_peric0);
824 sel = (sel >> (dev_index << 2)) & 0xf;
825
826 if (sel == 0x6)
827 sclk = get_pll_clk(MPLL);
828 else if (sel == 0x7)
829 sclk = get_pll_clk(EPLL);
830 else if (sel == 0x8)
831 sclk = get_pll_clk(VPLL);
832 else
833 return 0;
834
835 /*
836 * CLK_DIV_PERIC0
837 * UART0_RATIO [3:0]
838 * UART1_RATIO [7:4]
839 * UART2_RATIO [8:11]
840 * UART3_RATIO [12:15]
841 * UART4_RATIO [16:19]
842 * UART5_RATIO [23:20]
843 */
844 ratio = readl(&clk->div_peric0);
845 ratio = (ratio >> (dev_index << 2)) & 0xf;
846
847 uclk = sclk / (ratio + 1);
848
849 return uclk;
850}
851
Rajeshwari Birjeac892d02013-12-26 09:44:21 +0530852/* exynos5420: return uart clock frequency */
853static unsigned long exynos5420_get_uart_clk(int dev_index)
854{
855 struct exynos5420_clock *clk =
856 (struct exynos5420_clock *)samsung_get_base_clock();
857 unsigned long uclk, sclk;
858 unsigned int sel;
859 unsigned int ratio;
860
861 /*
862 * CLK_SRC_PERIC0
863 * UART0_SEL [6:4]
864 * UART1_SEL [10:8]
865 * UART2_SEL [14:12]
866 * UART3_SEL [18:16]
867 * generalised calculation as follows
868 * sel = (sel >> ((dev_index * 4) + 4)) & mask;
869 */
870 sel = readl(&clk->src_peric0);
871 sel = (sel >> ((dev_index * 4) + 4)) & 0x7;
872
873 if (sel == 0x3)
874 sclk = get_pll_clk(MPLL);
875 else if (sel == 0x6)
876 sclk = get_pll_clk(EPLL);
877 else if (sel == 0x7)
878 sclk = get_pll_clk(RPLL);
879 else
880 return 0;
881
882 /*
883 * CLK_DIV_PERIC0
884 * UART0_RATIO [11:8]
885 * UART1_RATIO [15:12]
886 * UART2_RATIO [19:16]
887 * UART3_RATIO [23:20]
888 * generalised calculation as follows
889 * ratio = (ratio >> ((dev_index * 4) + 8)) & mask;
890 */
891 ratio = readl(&clk->div_peric0);
892 ratio = (ratio >> ((dev_index * 4) + 8)) & 0xf;
893
894 uclk = sclk / (ratio + 1);
895
896 return uclk;
897}
898
Jaehoon Chung8788e062012-12-27 22:30:32 +0000899static unsigned long exynos4_get_mmc_clk(int dev_index)
900{
901 struct exynos4_clock *clk =
902 (struct exynos4_clock *)samsung_get_base_clock();
903 unsigned long uclk, sclk;
904 unsigned int sel, ratio, pre_ratio;
Amare1df6282013-04-27 11:42:56 +0530905 int shift = 0;
Jaehoon Chung8788e062012-12-27 22:30:32 +0000906
907 sel = readl(&clk->src_fsys);
908 sel = (sel >> (dev_index << 2)) & 0xf;
909
910 if (sel == 0x6)
911 sclk = get_pll_clk(MPLL);
912 else if (sel == 0x7)
913 sclk = get_pll_clk(EPLL);
914 else if (sel == 0x8)
915 sclk = get_pll_clk(VPLL);
916 else
917 return 0;
918
919 switch (dev_index) {
920 case 0:
921 case 1:
922 ratio = readl(&clk->div_fsys1);
923 pre_ratio = readl(&clk->div_fsys1);
924 break;
925 case 2:
926 case 3:
927 ratio = readl(&clk->div_fsys2);
928 pre_ratio = readl(&clk->div_fsys2);
929 break;
930 case 4:
931 ratio = readl(&clk->div_fsys3);
932 pre_ratio = readl(&clk->div_fsys3);
933 break;
934 default:
935 return 0;
936 }
937
938 if (dev_index == 1 || dev_index == 3)
939 shift = 16;
940
941 ratio = (ratio >> shift) & 0xf;
942 pre_ratio = (pre_ratio >> (shift + 8)) & 0xff;
943 uclk = (sclk / (ratio + 1)) / (pre_ratio + 1);
944
945 return uclk;
946}
947
948static unsigned long exynos5_get_mmc_clk(int dev_index)
949{
950 struct exynos5_clock *clk =
951 (struct exynos5_clock *)samsung_get_base_clock();
952 unsigned long uclk, sclk;
953 unsigned int sel, ratio, pre_ratio;
Amare1df6282013-04-27 11:42:56 +0530954 int shift = 0;
Jaehoon Chung8788e062012-12-27 22:30:32 +0000955
956 sel = readl(&clk->src_fsys);
957 sel = (sel >> (dev_index << 2)) & 0xf;
958
959 if (sel == 0x6)
960 sclk = get_pll_clk(MPLL);
961 else if (sel == 0x7)
962 sclk = get_pll_clk(EPLL);
963 else if (sel == 0x8)
964 sclk = get_pll_clk(VPLL);
965 else
966 return 0;
967
968 switch (dev_index) {
969 case 0:
970 case 1:
971 ratio = readl(&clk->div_fsys1);
972 pre_ratio = readl(&clk->div_fsys1);
973 break;
974 case 2:
975 case 3:
976 ratio = readl(&clk->div_fsys2);
977 pre_ratio = readl(&clk->div_fsys2);
978 break;
979 default:
980 return 0;
981 }
982
983 if (dev_index == 1 || dev_index == 3)
984 shift = 16;
985
986 ratio = (ratio >> shift) & 0xf;
987 pre_ratio = (pre_ratio >> (shift + 8)) & 0xff;
988 uclk = (sclk / (ratio + 1)) / (pre_ratio + 1);
989
990 return uclk;
991}
992
Rajeshwari Birjeac892d02013-12-26 09:44:21 +0530993static unsigned long exynos5420_get_mmc_clk(int dev_index)
994{
995 struct exynos5420_clock *clk =
996 (struct exynos5420_clock *)samsung_get_base_clock();
997 unsigned long uclk, sclk;
998 unsigned int sel, ratio;
999
1000 /*
1001 * CLK_SRC_FSYS
1002 * MMC0_SEL [10:8]
1003 * MMC1_SEL [14:12]
1004 * MMC2_SEL [18:16]
1005 * generalised calculation as follows
1006 * sel = (sel >> ((dev_index * 4) + 8)) & mask
1007 */
1008 sel = readl(&clk->src_fsys);
1009 sel = (sel >> ((dev_index * 4) + 8)) & 0x7;
1010
1011 if (sel == 0x3)
1012 sclk = get_pll_clk(MPLL);
Joonyoung Shim615e1482014-12-22 19:46:30 +09001013 else if (sel == 0x4)
1014 sclk = get_pll_clk(SPLL);
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301015 else if (sel == 0x6)
1016 sclk = get_pll_clk(EPLL);
1017 else
1018 return 0;
1019
1020 /*
1021 * CLK_DIV_FSYS1
1022 * MMC0_RATIO [9:0]
1023 * MMC1_RATIO [19:10]
1024 * MMC2_RATIO [29:20]
1025 * generalised calculation as follows
1026 * ratio = (ratio >> (dev_index * 10)) & mask
1027 */
1028 ratio = readl(&clk->div_fsys1);
1029 ratio = (ratio >> (dev_index * 10)) & 0x3ff;
1030
1031 uclk = (sclk / (ratio + 1));
1032
1033 return uclk;
1034}
1035
Chander Kashyap4131a772011-12-06 23:34:12 +00001036/* exynos4: set the mmc clock */
1037static void exynos4_set_mmc_clk(int dev_index, unsigned int div)
Jaehoon Chung9a772212011-05-17 21:19:17 +00001038{
Chander Kashyap4131a772011-12-06 23:34:12 +00001039 struct exynos4_clock *clk =
1040 (struct exynos4_clock *)samsung_get_base_clock();
Jaehoon Chungd2c83242014-05-16 13:59:50 +09001041 unsigned int addr, clear_bit, set_bit;
Jaehoon Chung9a772212011-05-17 21:19:17 +00001042
1043 /*
1044 * CLK_DIV_FSYS1
1045 * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24]
1046 * CLK_DIV_FSYS2
1047 * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24]
Jaehoon Chung29fe8c52012-12-27 22:30:33 +00001048 * CLK_DIV_FSYS3
Jaehoon Chungd2c83242014-05-16 13:59:50 +09001049 * MMC4_RATIO [3:0]
Jaehoon Chung9a772212011-05-17 21:19:17 +00001050 */
1051 if (dev_index < 2) {
1052 addr = (unsigned int)&clk->div_fsys1;
Jaehoon Chungd2c83242014-05-16 13:59:50 +09001053 clear_bit = MASK_PRE_RATIO(dev_index);
1054 set_bit = SET_PRE_RATIO(dev_index, div);
1055 } else if (dev_index == 4) {
Jaehoon Chung29fe8c52012-12-27 22:30:33 +00001056 addr = (unsigned int)&clk->div_fsys3;
1057 dev_index -= 4;
Jaehoon Chungd2c83242014-05-16 13:59:50 +09001058 /* MMC4 is controlled with the MMC4_RATIO value */
1059 clear_bit = MASK_RATIO(dev_index);
1060 set_bit = SET_RATIO(dev_index, div);
Jaehoon Chung9a772212011-05-17 21:19:17 +00001061 } else {
1062 addr = (unsigned int)&clk->div_fsys2;
1063 dev_index -= 2;
Jaehoon Chungd2c83242014-05-16 13:59:50 +09001064 clear_bit = MASK_PRE_RATIO(dev_index);
1065 set_bit = SET_PRE_RATIO(dev_index, div);
Jaehoon Chung9a772212011-05-17 21:19:17 +00001066 }
1067
Jaehoon Chungd2c83242014-05-16 13:59:50 +09001068 clrsetbits_le32(addr, clear_bit, set_bit);
Jaehoon Chung9a772212011-05-17 21:19:17 +00001069}
1070
Chander Kashyap34076a02012-02-05 23:01:46 +00001071/* exynos5: set the mmc clock */
1072static void exynos5_set_mmc_clk(int dev_index, unsigned int div)
1073{
1074 struct exynos5_clock *clk =
1075 (struct exynos5_clock *)samsung_get_base_clock();
1076 unsigned int addr;
Chander Kashyap34076a02012-02-05 23:01:46 +00001077
1078 /*
1079 * CLK_DIV_FSYS1
1080 * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24]
1081 * CLK_DIV_FSYS2
1082 * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24]
1083 */
1084 if (dev_index < 2) {
1085 addr = (unsigned int)&clk->div_fsys1;
1086 } else {
1087 addr = (unsigned int)&clk->div_fsys2;
1088 dev_index -= 2;
1089 }
1090
Inha Song4e558532014-02-06 14:20:12 +09001091 clrsetbits_le32(addr, 0xff << ((dev_index << 4) + 8),
1092 (div & 0xff) << ((dev_index << 4) + 8));
Chander Kashyap34076a02012-02-05 23:01:46 +00001093}
1094
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301095/* exynos5: set the mmc clock */
1096static void exynos5420_set_mmc_clk(int dev_index, unsigned int div)
1097{
1098 struct exynos5420_clock *clk =
1099 (struct exynos5420_clock *)samsung_get_base_clock();
1100 unsigned int addr;
Inha Song4e558532014-02-06 14:20:12 +09001101 unsigned int shift;
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301102
1103 /*
1104 * CLK_DIV_FSYS1
1105 * MMC0_RATIO [9:0]
1106 * MMC1_RATIO [19:10]
1107 * MMC2_RATIO [29:20]
1108 */
1109 addr = (unsigned int)&clk->div_fsys1;
1110 shift = dev_index * 10;
1111
Inha Song4e558532014-02-06 14:20:12 +09001112 clrsetbits_le32(addr, 0x3ff << shift, (div & 0x3ff) << shift);
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301113}
1114
Donghwa Lee77ba1912012-04-05 19:36:12 +00001115/* get_lcd_clk: return lcd clock frequency */
1116static unsigned long exynos4_get_lcd_clk(void)
1117{
1118 struct exynos4_clock *clk =
1119 (struct exynos4_clock *)samsung_get_base_clock();
1120 unsigned long pclk, sclk;
1121 unsigned int sel;
1122 unsigned int ratio;
1123
1124 /*
1125 * CLK_SRC_LCD0
1126 * FIMD0_SEL [3:0]
1127 */
1128 sel = readl(&clk->src_lcd0);
1129 sel = sel & 0xf;
1130
1131 /*
1132 * 0x6: SCLK_MPLL
1133 * 0x7: SCLK_EPLL
1134 * 0x8: SCLK_VPLL
1135 */
1136 if (sel == 0x6)
1137 sclk = get_pll_clk(MPLL);
1138 else if (sel == 0x7)
1139 sclk = get_pll_clk(EPLL);
1140 else if (sel == 0x8)
1141 sclk = get_pll_clk(VPLL);
1142 else
1143 return 0;
1144
1145 /*
1146 * CLK_DIV_LCD0
1147 * FIMD0_RATIO [3:0]
1148 */
1149 ratio = readl(&clk->div_lcd0);
1150 ratio = ratio & 0xf;
1151
1152 pclk = sclk / (ratio + 1);
1153
1154 return pclk;
1155}
1156
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001157/* get_lcd_clk: return lcd clock frequency */
1158static unsigned long exynos5_get_lcd_clk(void)
1159{
1160 struct exynos5_clock *clk =
1161 (struct exynos5_clock *)samsung_get_base_clock();
1162 unsigned long pclk, sclk;
1163 unsigned int sel;
1164 unsigned int ratio;
1165
1166 /*
1167 * CLK_SRC_LCD0
1168 * FIMD0_SEL [3:0]
1169 */
1170 sel = readl(&clk->src_disp1_0);
1171 sel = sel & 0xf;
1172
1173 /*
1174 * 0x6: SCLK_MPLL
1175 * 0x7: SCLK_EPLL
1176 * 0x8: SCLK_VPLL
1177 */
1178 if (sel == 0x6)
1179 sclk = get_pll_clk(MPLL);
1180 else if (sel == 0x7)
1181 sclk = get_pll_clk(EPLL);
1182 else if (sel == 0x8)
1183 sclk = get_pll_clk(VPLL);
1184 else
1185 return 0;
1186
1187 /*
1188 * CLK_DIV_LCD0
1189 * FIMD0_RATIO [3:0]
1190 */
1191 ratio = readl(&clk->div_disp1_0);
1192 ratio = ratio & 0xf;
1193
1194 pclk = sclk / (ratio + 1);
1195
1196 return pclk;
1197}
1198
Ajay Kumar914af872014-09-05 16:53:32 +05301199static unsigned long exynos5420_get_lcd_clk(void)
1200{
1201 struct exynos5420_clock *clk =
1202 (struct exynos5420_clock *)samsung_get_base_clock();
1203 unsigned long pclk, sclk;
1204 unsigned int sel;
1205 unsigned int ratio;
1206
1207 /*
1208 * CLK_SRC_DISP10
1209 * FIMD1_SEL [4]
1210 * 0: SCLK_RPLL
1211 * 1: SCLK_SPLL
1212 */
1213 sel = readl(&clk->src_disp10);
1214 sel &= (1 << 4);
1215
1216 if (sel)
1217 sclk = get_pll_clk(SPLL);
1218 else
1219 sclk = get_pll_clk(RPLL);
1220
1221 /*
1222 * CLK_DIV_DISP10
1223 * FIMD1_RATIO [3:0]
1224 */
1225 ratio = readl(&clk->div_disp10);
1226 ratio = ratio & 0xf;
1227
1228 pclk = sclk / (ratio + 1);
1229
1230 return pclk;
1231}
1232
Donghwa Lee77ba1912012-04-05 19:36:12 +00001233void exynos4_set_lcd_clk(void)
1234{
1235 struct exynos4_clock *clk =
1236 (struct exynos4_clock *)samsung_get_base_clock();
Donghwa Lee77ba1912012-04-05 19:36:12 +00001237
1238 /*
1239 * CLK_GATE_BLOCK
1240 * CLK_CAM [0]
1241 * CLK_TV [1]
1242 * CLK_MFC [2]
1243 * CLK_G3D [3]
1244 * CLK_LCD0 [4]
1245 * CLK_LCD1 [5]
1246 * CLK_GPS [7]
1247 */
Inha Song4e558532014-02-06 14:20:12 +09001248 setbits_le32(&clk->gate_block, 1 << 4);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001249
1250 /*
1251 * CLK_SRC_LCD0
1252 * FIMD0_SEL [3:0]
1253 * MDNIE0_SEL [7:4]
1254 * MDNIE_PWM0_SEL [8:11]
1255 * MIPI0_SEL [12:15]
1256 * set lcd0 src clock 0x6: SCLK_MPLL
1257 */
Inha Song4e558532014-02-06 14:20:12 +09001258 clrsetbits_le32(&clk->src_lcd0, 0xf, 0x6);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001259
1260 /*
1261 * CLK_GATE_IP_LCD0
1262 * CLK_FIMD0 [0]
1263 * CLK_MIE0 [1]
1264 * CLK_MDNIE0 [2]
1265 * CLK_DSIM0 [3]
1266 * CLK_SMMUFIMD0 [4]
1267 * CLK_PPMULCD0 [5]
1268 * Gating all clocks for FIMD0
1269 */
Inha Song4e558532014-02-06 14:20:12 +09001270 setbits_le32(&clk->gate_ip_lcd0, 1 << 0);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001271
1272 /*
1273 * CLK_DIV_LCD0
1274 * FIMD0_RATIO [3:0]
1275 * MDNIE0_RATIO [7:4]
1276 * MDNIE_PWM0_RATIO [11:8]
1277 * MDNIE_PWM_PRE_RATIO [15:12]
1278 * MIPI0_RATIO [19:16]
1279 * MIPI0_PRE_RATIO [23:20]
1280 * set fimd ratio
1281 */
Inha Song4e558532014-02-06 14:20:12 +09001282 clrsetbits_le32(&clk->div_lcd0, 0xf, 0x1);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001283}
1284
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001285void exynos5_set_lcd_clk(void)
1286{
1287 struct exynos5_clock *clk =
1288 (struct exynos5_clock *)samsung_get_base_clock();
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001289
1290 /*
1291 * CLK_GATE_BLOCK
1292 * CLK_CAM [0]
1293 * CLK_TV [1]
1294 * CLK_MFC [2]
1295 * CLK_G3D [3]
1296 * CLK_LCD0 [4]
1297 * CLK_LCD1 [5]
1298 * CLK_GPS [7]
1299 */
Inha Song4e558532014-02-06 14:20:12 +09001300 setbits_le32(&clk->gate_block, 1 << 4);
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001301
1302 /*
1303 * CLK_SRC_LCD0
1304 * FIMD0_SEL [3:0]
1305 * MDNIE0_SEL [7:4]
1306 * MDNIE_PWM0_SEL [8:11]
1307 * MIPI0_SEL [12:15]
1308 * set lcd0 src clock 0x6: SCLK_MPLL
1309 */
Inha Song4e558532014-02-06 14:20:12 +09001310 clrsetbits_le32(&clk->src_disp1_0, 0xf, 0x6);
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001311
1312 /*
1313 * CLK_GATE_IP_LCD0
1314 * CLK_FIMD0 [0]
1315 * CLK_MIE0 [1]
1316 * CLK_MDNIE0 [2]
1317 * CLK_DSIM0 [3]
1318 * CLK_SMMUFIMD0 [4]
1319 * CLK_PPMULCD0 [5]
1320 * Gating all clocks for FIMD0
1321 */
Inha Song4e558532014-02-06 14:20:12 +09001322 setbits_le32(&clk->gate_ip_disp1, 1 << 0);
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001323
1324 /*
1325 * CLK_DIV_LCD0
1326 * FIMD0_RATIO [3:0]
1327 * MDNIE0_RATIO [7:4]
1328 * MDNIE_PWM0_RATIO [11:8]
1329 * MDNIE_PWM_PRE_RATIO [15:12]
1330 * MIPI0_RATIO [19:16]
1331 * MIPI0_PRE_RATIO [23:20]
1332 * set fimd ratio
1333 */
Inha Song4e558532014-02-06 14:20:12 +09001334 clrsetbits_le32(&clk->div_disp1_0, 0xf, 0x0);
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001335}
1336
Ajay Kumar914af872014-09-05 16:53:32 +05301337void exynos5420_set_lcd_clk(void)
1338{
1339 struct exynos5420_clock *clk =
1340 (struct exynos5420_clock *)samsung_get_base_clock();
1341 unsigned int cfg;
1342
1343 /*
1344 * CLK_SRC_DISP10
1345 * FIMD1_SEL [4]
1346 * 0: SCLK_RPLL
1347 * 1: SCLK_SPLL
1348 */
1349 cfg = readl(&clk->src_disp10);
1350 cfg &= ~(0x1 << 4);
1351 cfg |= (0 << 4);
1352 writel(cfg, &clk->src_disp10);
1353
1354 /*
1355 * CLK_DIV_DISP10
1356 * FIMD1_RATIO [3:0]
1357 */
1358 cfg = readl(&clk->div_disp10);
1359 cfg &= ~(0xf << 0);
1360 cfg |= (0 << 0);
1361 writel(cfg, &clk->div_disp10);
1362}
1363
Donghwa Lee77ba1912012-04-05 19:36:12 +00001364void exynos4_set_mipi_clk(void)
1365{
1366 struct exynos4_clock *clk =
1367 (struct exynos4_clock *)samsung_get_base_clock();
Donghwa Lee77ba1912012-04-05 19:36:12 +00001368
1369 /*
1370 * CLK_SRC_LCD0
1371 * FIMD0_SEL [3:0]
1372 * MDNIE0_SEL [7:4]
1373 * MDNIE_PWM0_SEL [8:11]
1374 * MIPI0_SEL [12:15]
1375 * set mipi0 src clock 0x6: SCLK_MPLL
1376 */
Inha Song4e558532014-02-06 14:20:12 +09001377 clrsetbits_le32(&clk->src_lcd0, 0xf << 12, 0x6 << 12);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001378
1379 /*
1380 * CLK_SRC_MASK_LCD0
1381 * FIMD0_MASK [0]
1382 * MDNIE0_MASK [4]
1383 * MDNIE_PWM0_MASK [8]
1384 * MIPI0_MASK [12]
1385 * set src mask mipi0 0x1: Unmask
1386 */
Inha Song4e558532014-02-06 14:20:12 +09001387 setbits_le32(&clk->src_mask_lcd0, 0x1 << 12);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001388
1389 /*
1390 * CLK_GATE_IP_LCD0
1391 * CLK_FIMD0 [0]
1392 * CLK_MIE0 [1]
1393 * CLK_MDNIE0 [2]
1394 * CLK_DSIM0 [3]
1395 * CLK_SMMUFIMD0 [4]
1396 * CLK_PPMULCD0 [5]
1397 * Gating all clocks for MIPI0
1398 */
Inha Song4e558532014-02-06 14:20:12 +09001399 setbits_le32(&clk->gate_ip_lcd0, 1 << 3);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001400
1401 /*
1402 * CLK_DIV_LCD0
1403 * FIMD0_RATIO [3:0]
1404 * MDNIE0_RATIO [7:4]
1405 * MDNIE_PWM0_RATIO [11:8]
1406 * MDNIE_PWM_PRE_RATIO [15:12]
1407 * MIPI0_RATIO [19:16]
1408 * MIPI0_PRE_RATIO [23:20]
1409 * set mipi ratio
1410 */
Inha Song4e558532014-02-06 14:20:12 +09001411 clrsetbits_le32(&clk->div_lcd0, 0xf << 16, 0x1 << 16);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001412}
1413
Rajeshwari Shinde1c9412a2012-07-23 21:23:48 +00001414/*
1415 * I2C
1416 *
1417 * exynos5: obtaining the I2C clock
1418 */
1419static unsigned long exynos5_get_i2c_clk(void)
1420{
1421 struct exynos5_clock *clk =
1422 (struct exynos5_clock *)samsung_get_base_clock();
1423 unsigned long aclk_66, aclk_66_pre, sclk;
1424 unsigned int ratio;
1425
1426 sclk = get_pll_clk(MPLL);
1427
1428 ratio = (readl(&clk->div_top1)) >> 24;
1429 ratio &= 0x7;
1430 aclk_66_pre = sclk / (ratio + 1);
1431 ratio = readl(&clk->div_top0);
1432 ratio &= 0x7;
1433 aclk_66 = aclk_66_pre / (ratio + 1);
1434 return aclk_66;
1435}
1436
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001437int exynos5_set_epll_clk(unsigned long rate)
1438{
1439 unsigned int epll_con, epll_con_k;
1440 unsigned int i;
1441 unsigned int lockcnt;
1442 unsigned int start;
1443 struct exynos5_clock *clk =
1444 (struct exynos5_clock *)samsung_get_base_clock();
1445
1446 epll_con = readl(&clk->epll_con0);
1447 epll_con &= ~((EPLL_CON0_LOCK_DET_EN_MASK <<
1448 EPLL_CON0_LOCK_DET_EN_SHIFT) |
1449 EPLL_CON0_MDIV_MASK << EPLL_CON0_MDIV_SHIFT |
1450 EPLL_CON0_PDIV_MASK << EPLL_CON0_PDIV_SHIFT |
1451 EPLL_CON0_SDIV_MASK << EPLL_CON0_SDIV_SHIFT);
1452
1453 for (i = 0; i < ARRAY_SIZE(exynos5_epll_div); i++) {
1454 if (exynos5_epll_div[i].freq_out == rate)
1455 break;
1456 }
1457
1458 if (i == ARRAY_SIZE(exynos5_epll_div))
1459 return -1;
1460
1461 epll_con_k = exynos5_epll_div[i].k_dsm << 0;
1462 epll_con |= exynos5_epll_div[i].en_lock_det <<
1463 EPLL_CON0_LOCK_DET_EN_SHIFT;
1464 epll_con |= exynos5_epll_div[i].m_div << EPLL_CON0_MDIV_SHIFT;
1465 epll_con |= exynos5_epll_div[i].p_div << EPLL_CON0_PDIV_SHIFT;
1466 epll_con |= exynos5_epll_div[i].s_div << EPLL_CON0_SDIV_SHIFT;
1467
1468 /*
1469 * Required period ( in cycles) to genarate a stable clock output.
1470 * The maximum clock time can be up to 3000 * PDIV cycles of PLLs
1471 * frequency input (as per spec)
1472 */
1473 lockcnt = 3000 * exynos5_epll_div[i].p_div;
1474
1475 writel(lockcnt, &clk->epll_lock);
1476 writel(epll_con, &clk->epll_con0);
1477 writel(epll_con_k, &clk->epll_con1);
1478
1479 start = get_timer(0);
1480
1481 while (!(readl(&clk->epll_con0) &
1482 (0x1 << EXYNOS5_EPLLCON0_LOCKED_SHIFT))) {
1483 if (get_timer(start) > TIMEOUT_EPLL_LOCK) {
1484 debug("%s: Timeout waiting for EPLL lock\n", __func__);
1485 return -1;
1486 }
1487 }
1488 return 0;
1489}
1490
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301491int exynos5_set_i2s_clk_source(unsigned int i2s_id)
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001492{
1493 struct exynos5_clock *clk =
1494 (struct exynos5_clock *)samsung_get_base_clock();
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301495 unsigned int *audio_ass = (unsigned int *)samsung_get_base_audio_ass();
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001496
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301497 if (i2s_id == 0) {
1498 setbits_le32(&clk->src_top2, CLK_SRC_MOUT_EPLL);
1499 clrsetbits_le32(&clk->src_mau, AUDIO0_SEL_MASK,
1500 (CLK_SRC_SCLK_EPLL));
1501 setbits_le32(audio_ass, AUDIO_CLKMUX_ASS);
1502 } else if (i2s_id == 1) {
1503 clrsetbits_le32(&clk->src_peric1, AUDIO1_SEL_MASK,
1504 (CLK_SRC_SCLK_EPLL));
1505 } else {
1506 return -1;
1507 }
1508 return 0;
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001509}
1510
1511int exynos5_set_i2s_clk_prescaler(unsigned int src_frq,
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301512 unsigned int dst_frq,
1513 unsigned int i2s_id)
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001514{
1515 struct exynos5_clock *clk =
1516 (struct exynos5_clock *)samsung_get_base_clock();
1517 unsigned int div;
1518
1519 if ((dst_frq == 0) || (src_frq == 0)) {
1520 debug("%s: Invalid requency input for prescaler\n", __func__);
1521 debug("src frq = %d des frq = %d ", src_frq, dst_frq);
1522 return -1;
1523 }
1524
1525 div = (src_frq / dst_frq);
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301526 if (i2s_id == 0) {
1527 if (div > AUDIO_0_RATIO_MASK) {
1528 debug("%s: Frequency ratio is out of range\n",
1529 __func__);
1530 debug("src frq = %d des frq = %d ", src_frq, dst_frq);
1531 return -1;
1532 }
1533 clrsetbits_le32(&clk->div_mau, AUDIO_0_RATIO_MASK,
1534 (div & AUDIO_0_RATIO_MASK));
1535 } else if(i2s_id == 1) {
1536 if (div > AUDIO_1_RATIO_MASK) {
1537 debug("%s: Frequency ratio is out of range\n",
1538 __func__);
1539 debug("src frq = %d des frq = %d ", src_frq, dst_frq);
1540 return -1;
1541 }
1542 clrsetbits_le32(&clk->div_peric4, AUDIO_1_RATIO_MASK,
1543 (div & AUDIO_1_RATIO_MASK));
1544 } else {
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001545 return -1;
1546 }
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001547 return 0;
1548}
1549
Hatim RVe6365b62012-11-02 01:15:34 +00001550/**
1551 * Linearly searches for the most accurate main and fine stage clock scalars
1552 * (divisors) for a specified target frequency and scalar bit sizes by checking
1553 * all multiples of main_scalar_bits values. Will always return scalars up to or
1554 * slower than target.
1555 *
1556 * @param main_scalar_bits Number of main scalar bits, must be > 0 and < 32
1557 * @param fine_scalar_bits Number of fine scalar bits, must be > 0 and < 32
1558 * @param input_freq Clock frequency to be scaled in Hz
1559 * @param target_freq Desired clock frequency in Hz
1560 * @param best_fine_scalar Pointer to store the fine stage divisor
1561 *
1562 * @return best_main_scalar Main scalar for desired frequency or -1 if none
1563 * found
1564 */
1565static int clock_calc_best_scalar(unsigned int main_scaler_bits,
1566 unsigned int fine_scalar_bits, unsigned int input_rate,
1567 unsigned int target_rate, unsigned int *best_fine_scalar)
1568{
1569 int i;
1570 int best_main_scalar = -1;
1571 unsigned int best_error = target_rate;
1572 const unsigned int cap = (1 << fine_scalar_bits) - 1;
1573 const unsigned int loops = 1 << main_scaler_bits;
1574
1575 debug("Input Rate is %u, Target is %u, Cap is %u\n", input_rate,
1576 target_rate, cap);
1577
1578 assert(best_fine_scalar != NULL);
1579 assert(main_scaler_bits <= fine_scalar_bits);
1580
1581 *best_fine_scalar = 1;
1582
1583 if (input_rate == 0 || target_rate == 0)
1584 return -1;
1585
1586 if (target_rate >= input_rate)
1587 return 1;
1588
1589 for (i = 1; i <= loops; i++) {
Masahiro Yamadadb204642014-11-07 03:03:31 +09001590 const unsigned int effective_div =
1591 max(min(input_rate / i / target_rate, cap), 1U);
Hatim RVe6365b62012-11-02 01:15:34 +00001592 const unsigned int effective_rate = input_rate / i /
1593 effective_div;
1594 const int error = target_rate - effective_rate;
1595
1596 debug("%d|effdiv:%u, effrate:%u, error:%d\n", i, effective_div,
1597 effective_rate, error);
1598
1599 if (error >= 0 && error <= best_error) {
1600 best_error = error;
1601 best_main_scalar = i;
1602 *best_fine_scalar = effective_div;
1603 }
1604 }
1605
1606 return best_main_scalar;
1607}
1608
1609static int exynos5_set_spi_clk(enum periph_id periph_id,
1610 unsigned int rate)
1611{
1612 struct exynos5_clock *clk =
1613 (struct exynos5_clock *)samsung_get_base_clock();
1614 int main;
1615 unsigned int fine;
1616 unsigned shift, pre_shift;
1617 unsigned mask = 0xff;
1618 u32 *reg;
1619
1620 main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine);
1621 if (main < 0) {
1622 debug("%s: Cannot set clock rate for periph %d",
1623 __func__, periph_id);
1624 return -1;
1625 }
1626 main = main - 1;
1627 fine = fine - 1;
1628
1629 switch (periph_id) {
1630 case PERIPH_ID_SPI0:
1631 reg = &clk->div_peric1;
1632 shift = 0;
1633 pre_shift = 8;
1634 break;
1635 case PERIPH_ID_SPI1:
1636 reg = &clk->div_peric1;
1637 shift = 16;
1638 pre_shift = 24;
1639 break;
1640 case PERIPH_ID_SPI2:
1641 reg = &clk->div_peric2;
1642 shift = 0;
1643 pre_shift = 8;
1644 break;
1645 case PERIPH_ID_SPI3:
1646 reg = &clk->sclk_div_isp;
1647 shift = 0;
1648 pre_shift = 4;
1649 break;
1650 case PERIPH_ID_SPI4:
1651 reg = &clk->sclk_div_isp;
1652 shift = 12;
1653 pre_shift = 16;
1654 break;
1655 default:
1656 debug("%s: Unsupported peripheral ID %d\n", __func__,
1657 periph_id);
1658 return -1;
1659 }
1660 clrsetbits_le32(reg, mask << shift, (main & mask) << shift);
1661 clrsetbits_le32(reg, mask << pre_shift, (fine & mask) << pre_shift);
1662
1663 return 0;
1664}
1665
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301666static int exynos5420_set_spi_clk(enum periph_id periph_id,
1667 unsigned int rate)
1668{
1669 struct exynos5420_clock *clk =
1670 (struct exynos5420_clock *)samsung_get_base_clock();
1671 int main;
1672 unsigned int fine;
1673 unsigned shift, pre_shift;
1674 unsigned div_mask = 0xf, pre_div_mask = 0xff;
1675 u32 *reg;
1676 u32 *pre_reg;
1677
1678 main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine);
1679 if (main < 0) {
1680 debug("%s: Cannot set clock rate for periph %d",
1681 __func__, periph_id);
1682 return -1;
1683 }
1684 main = main - 1;
1685 fine = fine - 1;
1686
1687 switch (periph_id) {
1688 case PERIPH_ID_SPI0:
1689 reg = &clk->div_peric1;
1690 shift = 20;
1691 pre_reg = &clk->div_peric4;
1692 pre_shift = 8;
1693 break;
1694 case PERIPH_ID_SPI1:
1695 reg = &clk->div_peric1;
1696 shift = 24;
1697 pre_reg = &clk->div_peric4;
1698 pre_shift = 16;
1699 break;
1700 case PERIPH_ID_SPI2:
1701 reg = &clk->div_peric1;
1702 shift = 28;
1703 pre_reg = &clk->div_peric4;
1704 pre_shift = 24;
1705 break;
1706 case PERIPH_ID_SPI3:
1707 reg = &clk->div_isp1;
1708 shift = 16;
1709 pre_reg = &clk->div_isp1;
1710 pre_shift = 0;
1711 break;
1712 case PERIPH_ID_SPI4:
1713 reg = &clk->div_isp1;
1714 shift = 20;
1715 pre_reg = &clk->div_isp1;
1716 pre_shift = 8;
1717 break;
1718 default:
1719 debug("%s: Unsupported peripheral ID %d\n", __func__,
1720 periph_id);
1721 return -1;
1722 }
1723
1724 clrsetbits_le32(reg, div_mask << shift, (main & div_mask) << shift);
1725 clrsetbits_le32(pre_reg, pre_div_mask << pre_shift,
1726 (fine & pre_div_mask) << pre_shift);
1727
1728 return 0;
1729}
1730
Piotr Wilczek01d589f2012-11-20 02:19:02 +00001731static unsigned long exynos4_get_i2c_clk(void)
1732{
1733 struct exynos4_clock *clk =
1734 (struct exynos4_clock *)samsung_get_base_clock();
1735 unsigned long sclk, aclk_100;
1736 unsigned int ratio;
1737
1738 sclk = get_pll_clk(APLL);
1739
1740 ratio = (readl(&clk->div_top)) >> 4;
1741 ratio &= 0xf;
1742 aclk_100 = sclk / (ratio + 1);
1743 return aclk_100;
Minkyu Kangb1b24682011-01-24 15:22:23 +09001744}
1745
1746unsigned long get_pll_clk(int pllreg)
1747{
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301748 if (cpu_is_exynos5()) {
Akshay Saraswat9fba7b42014-11-13 22:38:15 +05301749 if (proid_is_exynos5420() || proid_is_exynos5800())
Akshay Saraswat1bd40e42015-02-04 16:00:00 +05301750 return exynos542x_get_pll_clk(pllreg);
Chander Kashyap34076a02012-02-05 23:01:46 +00001751 return exynos5_get_pll_clk(pllreg);
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301752 } else {
Chander Kashyap400ab162012-10-07 01:43:17 +00001753 if (proid_is_exynos4412())
1754 return exynos4x12_get_pll_clk(pllreg);
Chander Kashyap34076a02012-02-05 23:01:46 +00001755 return exynos4_get_pll_clk(pllreg);
Chander Kashyap400ab162012-10-07 01:43:17 +00001756 }
Minkyu Kangb1b24682011-01-24 15:22:23 +09001757}
1758
1759unsigned long get_arm_clk(void)
1760{
Chander Kashyap34076a02012-02-05 23:01:46 +00001761 if (cpu_is_exynos5())
1762 return exynos5_get_arm_clk();
Chander Kashyap400ab162012-10-07 01:43:17 +00001763 else {
1764 if (proid_is_exynos4412())
1765 return exynos4x12_get_arm_clk();
Chander Kashyap34076a02012-02-05 23:01:46 +00001766 return exynos4_get_arm_clk();
Chander Kashyap400ab162012-10-07 01:43:17 +00001767 }
Minkyu Kangb1b24682011-01-24 15:22:23 +09001768}
1769
Rajeshwari Shinde1c9412a2012-07-23 21:23:48 +00001770unsigned long get_i2c_clk(void)
1771{
1772 if (cpu_is_exynos5()) {
1773 return exynos5_get_i2c_clk();
Piotr Wilczek01d589f2012-11-20 02:19:02 +00001774 } else if (cpu_is_exynos4()) {
1775 return exynos4_get_i2c_clk();
Rajeshwari Shinde1c9412a2012-07-23 21:23:48 +00001776 } else {
1777 debug("I2C clock is not set for this CPU\n");
1778 return 0;
1779 }
1780}
1781
Minkyu Kangb1b24682011-01-24 15:22:23 +09001782unsigned long get_pwm_clk(void)
1783{
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301784 if (cpu_is_exynos5()) {
Akshay Saraswat9fba7b42014-11-13 22:38:15 +05301785 if (proid_is_exynos5420() || proid_is_exynos5800())
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301786 return exynos5420_get_pwm_clk();
Padmavathi Vennabb714162013-03-28 04:32:23 +00001787 return clock_get_periph_rate(PERIPH_ID_PWM0);
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301788 } else {
Chander Kashyap400ab162012-10-07 01:43:17 +00001789 if (proid_is_exynos4412())
1790 return exynos4x12_get_pwm_clk();
Chander Kashyap34076a02012-02-05 23:01:46 +00001791 return exynos4_get_pwm_clk();
Chander Kashyap400ab162012-10-07 01:43:17 +00001792 }
Minkyu Kangb1b24682011-01-24 15:22:23 +09001793}
1794
1795unsigned long get_uart_clk(int dev_index)
1796{
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301797 if (cpu_is_exynos5()) {
Akshay Saraswat9fba7b42014-11-13 22:38:15 +05301798 if (proid_is_exynos5420() || proid_is_exynos5800())
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301799 return exynos5420_get_uart_clk(dev_index);
Chander Kashyap34076a02012-02-05 23:01:46 +00001800 return exynos5_get_uart_clk(dev_index);
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301801 } else {
Chander Kashyap400ab162012-10-07 01:43:17 +00001802 if (proid_is_exynos4412())
1803 return exynos4x12_get_uart_clk(dev_index);
Chander Kashyap34076a02012-02-05 23:01:46 +00001804 return exynos4_get_uart_clk(dev_index);
Chander Kashyap400ab162012-10-07 01:43:17 +00001805 }
Minkyu Kangb1b24682011-01-24 15:22:23 +09001806}
Jaehoon Chung9a772212011-05-17 21:19:17 +00001807
Jaehoon Chung8788e062012-12-27 22:30:32 +00001808unsigned long get_mmc_clk(int dev_index)
1809{
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301810 if (cpu_is_exynos5()) {
Akshay Saraswat9fba7b42014-11-13 22:38:15 +05301811 if (proid_is_exynos5420() || proid_is_exynos5800())
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301812 return exynos5420_get_mmc_clk(dev_index);
Jaehoon Chung8788e062012-12-27 22:30:32 +00001813 return exynos5_get_mmc_clk(dev_index);
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301814 } else {
Jaehoon Chung8788e062012-12-27 22:30:32 +00001815 return exynos4_get_mmc_clk(dev_index);
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301816 }
Jaehoon Chung8788e062012-12-27 22:30:32 +00001817}
1818
Jaehoon Chung9a772212011-05-17 21:19:17 +00001819void set_mmc_clk(int dev_index, unsigned int div)
1820{
Jaehoon Chung15cd6b52015-01-08 16:50:21 +09001821 /* If want to set correct value, it needs to substract one from div.*/
1822 if (div > 0)
1823 div -= 1;
1824
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301825 if (cpu_is_exynos5()) {
Akshay Saraswat9fba7b42014-11-13 22:38:15 +05301826 if (proid_is_exynos5420() || proid_is_exynos5800())
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301827 exynos5420_set_mmc_clk(dev_index, div);
1828 else
1829 exynos5_set_mmc_clk(dev_index, div);
1830 } else {
Beomho Seo99660cc2014-05-16 13:59:47 +09001831 exynos4_set_mmc_clk(dev_index, div);
Chander Kashyap400ab162012-10-07 01:43:17 +00001832 }
Jaehoon Chung9a772212011-05-17 21:19:17 +00001833}
Donghwa Lee77ba1912012-04-05 19:36:12 +00001834
1835unsigned long get_lcd_clk(void)
1836{
1837 if (cpu_is_exynos4())
1838 return exynos4_get_lcd_clk();
Ajay Kumar914af872014-09-05 16:53:32 +05301839 else {
Akshay Saraswat9fba7b42014-11-13 22:38:15 +05301840 if (proid_is_exynos5420() || proid_is_exynos5800())
Ajay Kumar914af872014-09-05 16:53:32 +05301841 return exynos5420_get_lcd_clk();
1842 else
1843 return exynos5_get_lcd_clk();
1844 }
Donghwa Lee77ba1912012-04-05 19:36:12 +00001845}
1846
1847void set_lcd_clk(void)
1848{
1849 if (cpu_is_exynos4())
1850 exynos4_set_lcd_clk();
Ajay Kumar914af872014-09-05 16:53:32 +05301851 else {
1852 if (proid_is_exynos5250())
1853 exynos5_set_lcd_clk();
Akshay Saraswat9fba7b42014-11-13 22:38:15 +05301854 else if (proid_is_exynos5420() || proid_is_exynos5800())
Ajay Kumar914af872014-09-05 16:53:32 +05301855 exynos5420_set_lcd_clk();
1856 }
Donghwa Lee77ba1912012-04-05 19:36:12 +00001857}
1858
1859void set_mipi_clk(void)
1860{
1861 if (cpu_is_exynos4())
1862 exynos4_set_mipi_clk();
1863}
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001864
Hatim RVe6365b62012-11-02 01:15:34 +00001865int set_spi_clk(int periph_id, unsigned int rate)
1866{
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301867 if (cpu_is_exynos5()) {
Akshay Saraswat9fba7b42014-11-13 22:38:15 +05301868 if (proid_is_exynos5420() || proid_is_exynos5800())
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301869 return exynos5420_set_spi_clk(periph_id, rate);
Hatim RVe6365b62012-11-02 01:15:34 +00001870 return exynos5_set_spi_clk(periph_id, rate);
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301871 } else {
Hatim RVe6365b62012-11-02 01:15:34 +00001872 return 0;
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301873 }
Hatim RVe6365b62012-11-02 01:15:34 +00001874}
1875
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301876int set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq,
1877 unsigned int i2s_id)
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001878{
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001879 if (cpu_is_exynos5())
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301880 return exynos5_set_i2s_clk_prescaler(src_frq, dst_frq, i2s_id);
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001881 else
1882 return 0;
1883}
1884
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301885int set_i2s_clk_source(unsigned int i2s_id)
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001886{
1887 if (cpu_is_exynos5())
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301888 return exynos5_set_i2s_clk_source(i2s_id);
1889 else
1890 return 0;
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001891}
1892
1893int set_epll_clk(unsigned long rate)
1894{
1895 if (cpu_is_exynos5())
1896 return exynos5_set_epll_clk(rate);
1897 else
1898 return 0;
1899}