blob: 18eadf545fa94926a324b53637e5e96d23e2e702 [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
Padmavathi Venna37feb7b2013-03-28 04:32:21 +000017/* *
18 * This structure is to store the src bit, div bit and prediv bit
19 * positions of the peripheral clocks of the src and div registers
20 */
21struct clk_bit_info {
Akshay Saraswat3ad7ffc2015-02-04 15:59:59 +053022 enum periph_id id;
Akshay Saraswatd932c362015-02-04 16:00:04 +053023 int32_t src_mask;
24 int32_t div_mask;
25 int32_t prediv_mask;
Padmavathi Venna37feb7b2013-03-28 04:32:21 +000026 int8_t src_bit;
27 int8_t div_bit;
28 int8_t prediv_bit;
29};
30
Akshay Saraswatd5072262015-02-04 16:00:01 +053031static struct clk_bit_info exynos5_bit_info[] = {
Akshay Saraswatd932c362015-02-04 16:00:04 +053032 /* periph id s_mask d_mask p_mask s_bit d_bit p_bit */
33 {PERIPH_ID_UART0, 0xf, 0xf, -1, 0, 0, -1},
34 {PERIPH_ID_UART1, 0xf, 0xf, -1, 4, 4, -1},
35 {PERIPH_ID_UART2, 0xf, 0xf, -1, 8, 8, -1},
36 {PERIPH_ID_UART3, 0xf, 0xf, -1, 12, 12, -1},
37 {PERIPH_ID_I2C0, -1, 0x7, 0x7, -1, 24, 0},
38 {PERIPH_ID_I2C1, -1, 0x7, 0x7, -1, 24, 0},
39 {PERIPH_ID_I2C2, -1, 0x7, 0x7, -1, 24, 0},
40 {PERIPH_ID_I2C3, -1, 0x7, 0x7, -1, 24, 0},
41 {PERIPH_ID_I2C4, -1, 0x7, 0x7, -1, 24, 0},
42 {PERIPH_ID_I2C5, -1, 0x7, 0x7, -1, 24, 0},
43 {PERIPH_ID_I2C6, -1, 0x7, 0x7, -1, 24, 0},
44 {PERIPH_ID_I2C7, -1, 0x7, 0x7, -1, 24, 0},
45 {PERIPH_ID_SPI0, 0xf, 0xf, 0xff, 16, 0, 8},
46 {PERIPH_ID_SPI1, 0xf, 0xf, 0xff, 20, 16, 24},
47 {PERIPH_ID_SPI2, 0xf, 0xf, 0xff, 24, 0, 8},
48 {PERIPH_ID_SDMMC0, 0xf, 0xf, 0xff, 0, 0, 8},
49 {PERIPH_ID_SDMMC1, 0xf, 0xf, 0xff, 4, 16, 24},
50 {PERIPH_ID_SDMMC2, 0xf, 0xf, 0xff, 8, 0, 8},
51 {PERIPH_ID_SDMMC3, 0xf, 0xf, 0xff, 12, 16, 24},
52 {PERIPH_ID_I2S0, 0xf, 0xf, 0xff, 0, 0, 4},
53 {PERIPH_ID_I2S1, 0xf, 0xf, 0xff, 4, 12, 16},
54 {PERIPH_ID_SPI3, 0xf, 0xf, 0xff, 0, 0, 4},
55 {PERIPH_ID_SPI4, 0xf, 0xf, 0xff, 4, 12, 16},
56 {PERIPH_ID_SDMMC4, 0xf, 0xf, 0xff, 16, 0, 8},
57 {PERIPH_ID_PWM0, 0xf, 0xf, -1, 24, 0, -1},
58 {PERIPH_ID_PWM1, 0xf, 0xf, -1, 24, 0, -1},
59 {PERIPH_ID_PWM2, 0xf, 0xf, -1, 24, 0, -1},
60 {PERIPH_ID_PWM3, 0xf, 0xf, -1, 24, 0, -1},
61 {PERIPH_ID_PWM4, 0xf, 0xf, -1, 24, 0, -1},
Akshay Saraswat3ad7ffc2015-02-04 15:59:59 +053062
Akshay Saraswatd932c362015-02-04 16:00:04 +053063 {PERIPH_ID_NONE, -1, -1, -1, -1, -1, -1},
Padmavathi Venna37feb7b2013-03-28 04:32:21 +000064};
65
Akshay Saraswatd5072262015-02-04 16:00:01 +053066static struct clk_bit_info exynos542x_bit_info[] = {
Akshay Saraswatd932c362015-02-04 16:00:04 +053067 /* periph id s_mask d_mask p_mask s_bit d_bit p_bit */
68 {PERIPH_ID_UART0, 0xf, 0xf, -1, 4, 8, -1},
69 {PERIPH_ID_UART1, 0xf, 0xf, -1, 8, 12, -1},
70 {PERIPH_ID_UART2, 0xf, 0xf, -1, 12, 16, -1},
71 {PERIPH_ID_UART3, 0xf, 0xf, -1, 16, 20, -1},
72 {PERIPH_ID_I2C0, -1, 0x3f, -1, -1, 8, -1},
73 {PERIPH_ID_I2C1, -1, 0x3f, -1, -1, 8, -1},
74 {PERIPH_ID_I2C2, -1, 0x3f, -1, -1, 8, -1},
75 {PERIPH_ID_I2C3, -1, 0x3f, -1, -1, 8, -1},
76 {PERIPH_ID_I2C4, -1, 0x3f, -1, -1, 8, -1},
77 {PERIPH_ID_I2C5, -1, 0x3f, -1, -1, 8, -1},
78 {PERIPH_ID_I2C6, -1, 0x3f, -1, -1, 8, -1},
79 {PERIPH_ID_I2C7, -1, 0x3f, -1, -1, 8, -1},
80 {PERIPH_ID_SPI0, 0xf, 0xf, 0xff, 20, 20, 8},
81 {PERIPH_ID_SPI1, 0xf, 0xf, 0xff, 24, 24, 16},
82 {PERIPH_ID_SPI2, 0xf, 0xf, 0xff, 28, 28, 24},
83 {PERIPH_ID_SDMMC0, 0x7, 0x3ff, -1, 8, 0, -1},
84 {PERIPH_ID_SDMMC1, 0x7, 0x3ff, -1, 12, 10, -1},
85 {PERIPH_ID_SDMMC2, 0x7, 0x3ff, -1, 16, 20, -1},
86 {PERIPH_ID_I2C8, -1, 0x3f, -1, -1, 8, -1},
87 {PERIPH_ID_I2C9, -1, 0x3f, -1, -1, 8, -1},
88 {PERIPH_ID_I2S0, 0xf, 0xf, 0xff, 0, 0, 4},
89 {PERIPH_ID_I2S1, 0xf, 0xf, 0xff, 4, 12, 16},
90 {PERIPH_ID_SPI3, 0xf, 0xf, 0xff, 12, 16, 0},
91 {PERIPH_ID_SPI4, 0xf, 0xf, 0xff, 16, 20, 8},
92 {PERIPH_ID_PWM0, 0xf, 0xf, -1, 24, 28, -1},
93 {PERIPH_ID_PWM1, 0xf, 0xf, -1, 24, 28, -1},
94 {PERIPH_ID_PWM2, 0xf, 0xf, -1, 24, 28, -1},
95 {PERIPH_ID_PWM3, 0xf, 0xf, -1, 24, 28, -1},
96 {PERIPH_ID_PWM4, 0xf, 0xf, -1, 24, 28, -1},
97 {PERIPH_ID_I2C10, -1, 0x3f, -1, -1, 8, -1},
Akshay Saraswatd5072262015-02-04 16:00:01 +053098
Akshay Saraswatd932c362015-02-04 16:00:04 +053099 {PERIPH_ID_NONE, -1, -1, -1, -1, -1, -1},
Akshay Saraswatd5072262015-02-04 16:00:01 +0530100};
101
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +0000102/* Epll Clock division values to achive different frequency output */
103static struct set_epll_con_val exynos5_epll_div[] = {
104 { 192000000, 0, 48, 3, 1, 0 },
105 { 180000000, 0, 45, 3, 1, 0 },
106 { 73728000, 1, 73, 3, 3, 47710 },
107 { 67737600, 1, 90, 4, 3, 20762 },
108 { 49152000, 0, 49, 3, 3, 9961 },
109 { 45158400, 0, 45, 3, 3, 10381 },
110 { 180633600, 0, 45, 3, 1, 10381 }
111};
112
Minkyu Kang1a055aa2012-10-15 01:58:00 +0000113/* exynos: return pll clock frequency */
114static int exynos_get_pll_clk(int pllreg, unsigned int r, unsigned int k)
Minkyu Kangb1b24682011-01-24 15:22:23 +0900115{
Minkyu Kang1a055aa2012-10-15 01:58:00 +0000116 unsigned long m, p, s = 0, mask, fout;
Minkyu Kang368588e2013-07-05 19:08:33 +0900117 unsigned int div;
Minkyu Kangb1b24682011-01-24 15:22:23 +0900118 unsigned int freq;
Minkyu Kangb1b24682011-01-24 15:22:23 +0900119 /*
120 * APLL_CON: MIDV [25:16]
121 * MPLL_CON: MIDV [25:16]
122 * EPLL_CON: MIDV [24:16]
123 * VPLL_CON: MIDV [24:16]
Minkyu Kang1a055aa2012-10-15 01:58:00 +0000124 * BPLL_CON: MIDV [25:16]: Exynos5
Minkyu Kangb1b24682011-01-24 15:22:23 +0900125 */
Ajay Kumar914af872014-09-05 16:53:32 +0530126 if (pllreg == APLL || pllreg == MPLL || pllreg == BPLL ||
127 pllreg == SPLL)
Minkyu Kangb1b24682011-01-24 15:22:23 +0900128 mask = 0x3ff;
129 else
130 mask = 0x1ff;
131
132 m = (r >> 16) & mask;
133
134 /* PDIV [13:8] */
135 p = (r >> 8) & 0x3f;
136 /* SDIV [2:0] */
137 s = r & 0x7;
138
Chander Kashyap6a870e12012-02-05 23:01:45 +0000139 freq = CONFIG_SYS_CLK_FREQ;
Minkyu Kangb1b24682011-01-24 15:22:23 +0900140
Rajeshwari Birjeac892d02013-12-26 09:44:21 +0530141 if (pllreg == EPLL || pllreg == RPLL) {
Minkyu Kangb1b24682011-01-24 15:22:23 +0900142 k = k & 0xffff;
143 /* FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV) */
Minkyu Kang368588e2013-07-05 19:08:33 +0900144 fout = (m + k / PLL_DIV_65536) * (freq / (p * (1 << s)));
Minkyu Kangb1b24682011-01-24 15:22:23 +0900145 } else if (pllreg == VPLL) {
146 k = k & 0xfff;
Minkyu Kang368588e2013-07-05 19:08:33 +0900147
148 /*
149 * Exynos4210
150 * FOUT = (MDIV + K / 1024) * FIN / (PDIV * 2^SDIV)
151 *
152 * Exynos4412
153 * FOUT = (MDIV + K / 65535) * FIN / (PDIV * 2^SDIV)
154 *
155 * Exynos5250
156 * FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV)
157 */
158 if (proid_is_exynos4210())
159 div = PLL_DIV_1024;
160 else if (proid_is_exynos4412())
161 div = PLL_DIV_65535;
Akshay Saraswat9fba7b42014-11-13 22:38:15 +0530162 else if (proid_is_exynos5250() || proid_is_exynos5420()
163 || proid_is_exynos5800())
Minkyu Kang368588e2013-07-05 19:08:33 +0900164 div = PLL_DIV_65536;
165 else
166 return 0;
167
168 fout = (m + k / div) * (freq / (p * (1 << s)));
Minkyu Kangb1b24682011-01-24 15:22:23 +0900169 } else {
Minkyu Kang368588e2013-07-05 19:08:33 +0900170 /*
Łukasz Majewski326c4592013-07-12 19:08:25 +0200171 * Exynos4412 / Exynos5250
Minkyu Kang368588e2013-07-05 19:08:33 +0900172 * FOUT = MDIV * FIN / (PDIV * 2^SDIV)
173 *
Łukasz Majewski326c4592013-07-12 19:08:25 +0200174 * Exynos4210
Minkyu Kang368588e2013-07-05 19:08:33 +0900175 * FOUT = MDIV * FIN / (PDIV * 2^(SDIV-1))
176 */
177 if (proid_is_exynos4210())
Minkyu Kang368588e2013-07-05 19:08:33 +0900178 fout = m * (freq / (p * (1 << (s - 1))));
Łukasz Majewski326c4592013-07-12 19:08:25 +0200179 else
180 fout = m * (freq / (p * (1 << s)));
Minkyu Kangb1b24682011-01-24 15:22:23 +0900181 }
Minkyu Kangb1b24682011-01-24 15:22:23 +0900182 return fout;
183}
184
Minkyu Kang1a055aa2012-10-15 01:58:00 +0000185/* exynos4: return pll clock frequency */
186static unsigned long exynos4_get_pll_clk(int pllreg)
187{
188 struct exynos4_clock *clk =
189 (struct exynos4_clock *)samsung_get_base_clock();
190 unsigned long r, k = 0;
191
192 switch (pllreg) {
193 case APLL:
194 r = readl(&clk->apll_con0);
195 break;
196 case MPLL:
197 r = readl(&clk->mpll_con0);
198 break;
199 case EPLL:
200 r = readl(&clk->epll_con0);
201 k = readl(&clk->epll_con1);
202 break;
203 case VPLL:
204 r = readl(&clk->vpll_con0);
205 k = readl(&clk->vpll_con1);
206 break;
207 default:
208 printf("Unsupported PLL (%d)\n", pllreg);
209 return 0;
210 }
211
212 return exynos_get_pll_clk(pllreg, r, k);
213}
214
Chander Kashyap400ab162012-10-07 01:43:17 +0000215/* exynos4x12: return pll clock frequency */
216static unsigned long exynos4x12_get_pll_clk(int pllreg)
217{
218 struct exynos4x12_clock *clk =
219 (struct exynos4x12_clock *)samsung_get_base_clock();
220 unsigned long r, k = 0;
221
222 switch (pllreg) {
223 case APLL:
224 r = readl(&clk->apll_con0);
225 break;
226 case MPLL:
227 r = readl(&clk->mpll_con0);
228 break;
229 case EPLL:
230 r = readl(&clk->epll_con0);
231 k = readl(&clk->epll_con1);
232 break;
233 case VPLL:
234 r = readl(&clk->vpll_con0);
235 k = readl(&clk->vpll_con1);
236 break;
237 default:
238 printf("Unsupported PLL (%d)\n", pllreg);
239 return 0;
240 }
241
242 return exynos_get_pll_clk(pllreg, r, k);
243}
244
Chander Kashyap34076a02012-02-05 23:01:46 +0000245/* exynos5: return pll clock frequency */
246static unsigned long exynos5_get_pll_clk(int pllreg)
247{
248 struct exynos5_clock *clk =
249 (struct exynos5_clock *)samsung_get_base_clock();
Minkyu Kang1a055aa2012-10-15 01:58:00 +0000250 unsigned long r, k = 0, fout;
251 unsigned int pll_div2_sel, fout_sel;
Chander Kashyap34076a02012-02-05 23:01:46 +0000252
253 switch (pllreg) {
254 case APLL:
255 r = readl(&clk->apll_con0);
256 break;
257 case MPLL:
258 r = readl(&clk->mpll_con0);
259 break;
260 case EPLL:
261 r = readl(&clk->epll_con0);
262 k = readl(&clk->epll_con1);
263 break;
264 case VPLL:
265 r = readl(&clk->vpll_con0);
266 k = readl(&clk->vpll_con1);
267 break;
Rajeshwari Shinde84112862012-07-03 20:02:58 +0000268 case BPLL:
269 r = readl(&clk->bpll_con0);
270 break;
Chander Kashyap34076a02012-02-05 23:01:46 +0000271 default:
272 printf("Unsupported PLL (%d)\n", pllreg);
273 return 0;
274 }
275
Minkyu Kang1a055aa2012-10-15 01:58:00 +0000276 fout = exynos_get_pll_clk(pllreg, r, k);
Chander Kashyap34076a02012-02-05 23:01:46 +0000277
Rajeshwari Shinde84112862012-07-03 20:02:58 +0000278 /* According to the user manual, in EVT1 MPLL and BPLL always gives
Rajeshwari Shinde7b9afce2012-07-03 20:02:57 +0000279 * 1.6GHz clock, so divide by 2 to get 800MHz MPLL clock.*/
Rajeshwari Shinde84112862012-07-03 20:02:58 +0000280 if (pllreg == MPLL || pllreg == BPLL) {
Rajeshwari Shinde7b9afce2012-07-03 20:02:57 +0000281 pll_div2_sel = readl(&clk->pll_div2_sel);
Rajeshwari Shinde84112862012-07-03 20:02:58 +0000282
283 switch (pllreg) {
284 case MPLL:
285 fout_sel = (pll_div2_sel >> MPLL_FOUT_SEL_SHIFT)
286 & MPLL_FOUT_SEL_MASK;
287 break;
288 case BPLL:
289 fout_sel = (pll_div2_sel >> BPLL_FOUT_SEL_SHIFT)
290 & BPLL_FOUT_SEL_MASK;
291 break;
Jaehoon Chung0fc779c2012-07-09 21:20:34 +0000292 default:
293 fout_sel = -1;
294 break;
Rajeshwari Shinde84112862012-07-03 20:02:58 +0000295 }
296
297 if (fout_sel == 0)
Rajeshwari Shinde7b9afce2012-07-03 20:02:57 +0000298 fout /= 2;
299 }
300
Chander Kashyap34076a02012-02-05 23:01:46 +0000301 return fout;
302}
303
Akshay Saraswat1bd40e42015-02-04 16:00:00 +0530304/* exynos542x: return pll clock frequency */
305static unsigned long exynos542x_get_pll_clk(int pllreg)
306{
307 struct exynos5420_clock *clk =
308 (struct exynos5420_clock *)samsung_get_base_clock();
309 unsigned long r, k = 0;
310
311 switch (pllreg) {
312 case APLL:
313 r = readl(&clk->apll_con0);
314 break;
315 case MPLL:
316 r = readl(&clk->mpll_con0);
317 break;
318 case EPLL:
319 r = readl(&clk->epll_con0);
320 k = readl(&clk->epll_con1);
321 break;
322 case VPLL:
323 r = readl(&clk->vpll_con0);
324 k = readl(&clk->vpll_con1);
325 break;
326 case BPLL:
327 r = readl(&clk->bpll_con0);
328 break;
329 case RPLL:
330 r = readl(&clk->rpll_con0);
331 k = readl(&clk->rpll_con1);
332 break;
333 case SPLL:
334 r = readl(&clk->spll_con0);
335 break;
336 default:
337 printf("Unsupported PLL (%d)\n", pllreg);
338 return 0;
339 }
340
341 return exynos_get_pll_clk(pllreg, r, k);
342}
343
Akshay Saraswat3ad7ffc2015-02-04 15:59:59 +0530344static struct clk_bit_info *get_clk_bit_info(int peripheral)
345{
346 int i;
Akshay Saraswatd5072262015-02-04 16:00:01 +0530347 struct clk_bit_info *info;
348
349 if (proid_is_exynos5420() || proid_is_exynos5800())
350 info = exynos542x_bit_info;
351 else
352 info = exynos5_bit_info;
Akshay Saraswat3ad7ffc2015-02-04 15:59:59 +0530353
Akshay Saraswatd5072262015-02-04 16:00:01 +0530354 for (i = 0; info[i].id != PERIPH_ID_NONE; i++) {
355 if (info[i].id == peripheral)
Akshay Saraswat3ad7ffc2015-02-04 15:59:59 +0530356 break;
357 }
358
Akshay Saraswatd5072262015-02-04 16:00:01 +0530359 if (info[i].id == PERIPH_ID_NONE)
Akshay Saraswat3ad7ffc2015-02-04 15:59:59 +0530360 debug("ERROR: Peripheral ID %d not found\n", peripheral);
361
Akshay Saraswatd5072262015-02-04 16:00:01 +0530362 return &info[i];
Akshay Saraswat3ad7ffc2015-02-04 15:59:59 +0530363}
364
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000365static unsigned long exynos5_get_periph_rate(int peripheral)
366{
Akshay Saraswat3ad7ffc2015-02-04 15:59:59 +0530367 struct clk_bit_info *bit_info = get_clk_bit_info(peripheral);
Akshay Saraswate81cb882015-02-04 16:00:05 +0530368 unsigned long sclk = 0;
369 unsigned int src = 0, div = 0, sub_div = 0;
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000370 struct exynos5_clock *clk =
371 (struct exynos5_clock *)samsung_get_base_clock();
372
373 switch (peripheral) {
374 case PERIPH_ID_UART0:
375 case PERIPH_ID_UART1:
376 case PERIPH_ID_UART2:
377 case PERIPH_ID_UART3:
378 src = readl(&clk->src_peric0);
379 div = readl(&clk->div_peric0);
380 break;
381 case PERIPH_ID_PWM0:
382 case PERIPH_ID_PWM1:
383 case PERIPH_ID_PWM2:
384 case PERIPH_ID_PWM3:
385 case PERIPH_ID_PWM4:
386 src = readl(&clk->src_peric0);
387 div = readl(&clk->div_peric3);
388 break;
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +0530389 case PERIPH_ID_I2S0:
390 src = readl(&clk->src_mau);
Akshay Saraswate81cb882015-02-04 16:00:05 +0530391 div = sub_div = readl(&clk->div_mau);
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000392 case PERIPH_ID_SPI0:
393 case PERIPH_ID_SPI1:
394 src = readl(&clk->src_peric1);
Akshay Saraswate81cb882015-02-04 16:00:05 +0530395 div = sub_div = readl(&clk->div_peric1);
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000396 break;
397 case PERIPH_ID_SPI2:
398 src = readl(&clk->src_peric1);
Akshay Saraswate81cb882015-02-04 16:00:05 +0530399 div = sub_div = readl(&clk->div_peric2);
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000400 break;
401 case PERIPH_ID_SPI3:
402 case PERIPH_ID_SPI4:
403 src = readl(&clk->sclk_src_isp);
Akshay Saraswate81cb882015-02-04 16:00:05 +0530404 div = sub_div = readl(&clk->sclk_div_isp);
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000405 break;
406 case PERIPH_ID_SDMMC0:
407 case PERIPH_ID_SDMMC1:
Akshay Saraswatbad6a982015-02-04 16:00:02 +0530408 src = readl(&clk->src_fsys);
Akshay Saraswate81cb882015-02-04 16:00:05 +0530409 div = sub_div = readl(&clk->div_fsys1);
Akshay Saraswatbad6a982015-02-04 16:00:02 +0530410 break;
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000411 case PERIPH_ID_SDMMC2:
412 case PERIPH_ID_SDMMC3:
413 src = readl(&clk->src_fsys);
Akshay Saraswate81cb882015-02-04 16:00:05 +0530414 div = sub_div = readl(&clk->div_fsys2);
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000415 break;
416 case PERIPH_ID_I2C0:
417 case PERIPH_ID_I2C1:
418 case PERIPH_ID_I2C2:
419 case PERIPH_ID_I2C3:
420 case PERIPH_ID_I2C4:
421 case PERIPH_ID_I2C5:
422 case PERIPH_ID_I2C6:
423 case PERIPH_ID_I2C7:
Akshay Saraswate81cb882015-02-04 16:00:05 +0530424 src = EXYNOS_SRC_MPLL;
Guillaume GARDETf87f8ee2015-03-11 10:34:27 +0100425 div = readl(&clk->div_top1);
426 sub_div = readl(&clk->div_top0);
Akshay Saraswate81cb882015-02-04 16:00:05 +0530427 break;
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000428 default:
429 debug("%s: invalid peripheral %d", __func__, peripheral);
430 return -1;
431 };
432
Akshay Saraswatbad6a982015-02-04 16:00:02 +0530433 if (bit_info->src_bit >= 0)
Akshay Saraswatd932c362015-02-04 16:00:04 +0530434 src = (src >> bit_info->src_bit) & bit_info->src_mask;
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000435
436 switch (src) {
437 case EXYNOS_SRC_MPLL:
438 sclk = exynos5_get_pll_clk(MPLL);
439 break;
440 case EXYNOS_SRC_EPLL:
441 sclk = exynos5_get_pll_clk(EPLL);
442 break;
443 case EXYNOS_SRC_VPLL:
444 sclk = exynos5_get_pll_clk(VPLL);
445 break;
446 default:
Akshay Saraswate81cb882015-02-04 16:00:05 +0530447 debug("%s: EXYNOS_SRC %d not supported\n", __func__, src);
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000448 return 0;
449 }
450
Akshay Saraswate81cb882015-02-04 16:00:05 +0530451 /* Clock divider ratio for this peripheral */
452 if (bit_info->div_bit >= 0)
453 div = (div >> bit_info->div_bit) & bit_info->div_mask;
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000454
Akshay Saraswate81cb882015-02-04 16:00:05 +0530455 /* Clock pre-divider ratio for this peripheral */
456 if (bit_info->prediv_bit >= 0)
457 sub_div = (sub_div >> bit_info->prediv_bit)
458 & bit_info->prediv_mask;
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000459
Akshay Saraswate81cb882015-02-04 16:00:05 +0530460 /* Calculate and return required clock rate */
461 return (sclk / (div + 1)) / (sub_div + 1);
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000462}
463
Akshay Saraswatd5072262015-02-04 16:00:01 +0530464static unsigned long exynos542x_get_periph_rate(int peripheral)
465{
466 struct clk_bit_info *bit_info = get_clk_bit_info(peripheral);
Akshay Saraswate81cb882015-02-04 16:00:05 +0530467 unsigned long sclk = 0;
468 unsigned int src = 0, div = 0, sub_div = 0;
Akshay Saraswatd5072262015-02-04 16:00:01 +0530469 struct exynos5420_clock *clk =
470 (struct exynos5420_clock *)samsung_get_base_clock();
471
472 switch (peripheral) {
473 case PERIPH_ID_UART0:
474 case PERIPH_ID_UART1:
475 case PERIPH_ID_UART2:
476 case PERIPH_ID_UART3:
477 case PERIPH_ID_PWM0:
478 case PERIPH_ID_PWM1:
479 case PERIPH_ID_PWM2:
480 case PERIPH_ID_PWM3:
481 case PERIPH_ID_PWM4:
482 src = readl(&clk->src_peric0);
483 div = readl(&clk->div_peric0);
484 break;
485 case PERIPH_ID_SPI0:
486 case PERIPH_ID_SPI1:
487 case PERIPH_ID_SPI2:
488 src = readl(&clk->src_peric1);
489 div = readl(&clk->div_peric1);
490 sub_div = readl(&clk->div_peric4);
491 break;
492 case PERIPH_ID_SPI3:
493 case PERIPH_ID_SPI4:
494 src = readl(&clk->src_isp);
495 div = readl(&clk->div_isp1);
496 sub_div = readl(&clk->div_isp1);
497 break;
498 case PERIPH_ID_SDMMC0:
499 case PERIPH_ID_SDMMC1:
500 case PERIPH_ID_SDMMC2:
501 case PERIPH_ID_SDMMC3:
502 src = readl(&clk->src_fsys);
503 div = readl(&clk->div_fsys1);
504 break;
505 case PERIPH_ID_I2C0:
506 case PERIPH_ID_I2C1:
507 case PERIPH_ID_I2C2:
508 case PERIPH_ID_I2C3:
509 case PERIPH_ID_I2C4:
510 case PERIPH_ID_I2C5:
511 case PERIPH_ID_I2C6:
512 case PERIPH_ID_I2C7:
513 case PERIPH_ID_I2C8:
514 case PERIPH_ID_I2C9:
515 case PERIPH_ID_I2C10:
Akshay Saraswate81cb882015-02-04 16:00:05 +0530516 src = EXYNOS542X_SRC_MPLL;
517 div = readl(&clk->div_top1);
518 break;
Akshay Saraswatd5072262015-02-04 16:00:01 +0530519 default:
520 debug("%s: invalid peripheral %d", __func__, peripheral);
521 return -1;
522 };
523
524 if (bit_info->src_bit >= 0)
Akshay Saraswatd932c362015-02-04 16:00:04 +0530525 src = (src >> bit_info->src_bit) & bit_info->src_mask;
Akshay Saraswatd5072262015-02-04 16:00:01 +0530526
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:
Akshay Saraswate81cb882015-02-04 16:00:05 +0530541 debug("%s: EXYNOS542X_SRC %d not supported", __func__, src);
Akshay Saraswatd5072262015-02-04 16:00:01 +0530542 return 0;
543 }
544
Akshay Saraswate81cb882015-02-04 16:00:05 +0530545 /* Clock divider ratio for this peripheral */
546 if (bit_info->div_bit >= 0)
Akshay Saraswatd932c362015-02-04 16:00:04 +0530547 div = (div >> bit_info->div_bit) & bit_info->div_mask;
Akshay Saraswatd5072262015-02-04 16:00:01 +0530548
Akshay Saraswate81cb882015-02-04 16:00:05 +0530549 /* Clock pre-divider ratio for this peripheral */
550 if (bit_info->prediv_bit >= 0)
Akshay Saraswatd932c362015-02-04 16:00:04 +0530551 sub_div = (sub_div >> bit_info->prediv_bit)
Akshay Saraswate81cb882015-02-04 16:00:05 +0530552 & bit_info->prediv_mask;
Akshay Saraswatd5072262015-02-04 16:00:01 +0530553
Akshay Saraswate81cb882015-02-04 16:00:05 +0530554 /* Calculate and return required clock rate */
555 return (sclk / (div + 1)) / (sub_div + 1);
Akshay Saraswatd5072262015-02-04 16:00:01 +0530556}
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
Chander Kashyap4131a772011-12-06 23:34:12 +0000692/* exynos4: return uart clock frequency */
693static unsigned long exynos4_get_uart_clk(int dev_index)
Minkyu Kangb1b24682011-01-24 15:22:23 +0900694{
Chander Kashyap4131a772011-12-06 23:34:12 +0000695 struct exynos4_clock *clk =
696 (struct exynos4_clock *)samsung_get_base_clock();
Minkyu Kangb1b24682011-01-24 15:22:23 +0900697 unsigned long uclk, sclk;
698 unsigned int sel;
699 unsigned int ratio;
700
701 /*
702 * CLK_SRC_PERIL0
703 * UART0_SEL [3:0]
704 * UART1_SEL [7:4]
705 * UART2_SEL [8:11]
706 * UART3_SEL [12:15]
707 * UART4_SEL [16:19]
708 * UART5_SEL [23:20]
709 */
710 sel = readl(&clk->src_peril0);
711 sel = (sel >> (dev_index << 2)) & 0xf;
712
713 if (sel == 0x6)
714 sclk = get_pll_clk(MPLL);
715 else if (sel == 0x7)
716 sclk = get_pll_clk(EPLL);
717 else if (sel == 0x8)
718 sclk = get_pll_clk(VPLL);
719 else
720 return 0;
721
722 /*
723 * CLK_DIV_PERIL0
724 * UART0_RATIO [3:0]
725 * UART1_RATIO [7:4]
726 * UART2_RATIO [8:11]
727 * UART3_RATIO [12:15]
728 * UART4_RATIO [16:19]
729 * UART5_RATIO [23:20]
730 */
731 ratio = readl(&clk->div_peril0);
732 ratio = (ratio >> (dev_index << 2)) & 0xf;
733
734 uclk = sclk / (ratio + 1);
735
736 return uclk;
737}
738
Chander Kashyap400ab162012-10-07 01:43:17 +0000739/* exynos4x12: return uart clock frequency */
740static unsigned long exynos4x12_get_uart_clk(int dev_index)
741{
742 struct exynos4x12_clock *clk =
743 (struct exynos4x12_clock *)samsung_get_base_clock();
744 unsigned long uclk, sclk;
745 unsigned int sel;
746 unsigned int ratio;
747
748 /*
749 * CLK_SRC_PERIL0
750 * UART0_SEL [3:0]
751 * UART1_SEL [7:4]
752 * UART2_SEL [8:11]
753 * UART3_SEL [12:15]
754 * UART4_SEL [16:19]
755 */
756 sel = readl(&clk->src_peril0);
757 sel = (sel >> (dev_index << 2)) & 0xf;
758
759 if (sel == 0x6)
760 sclk = get_pll_clk(MPLL);
761 else if (sel == 0x7)
762 sclk = get_pll_clk(EPLL);
763 else if (sel == 0x8)
764 sclk = get_pll_clk(VPLL);
765 else
766 return 0;
767
768 /*
769 * CLK_DIV_PERIL0
770 * UART0_RATIO [3:0]
771 * UART1_RATIO [7:4]
772 * UART2_RATIO [8:11]
773 * UART3_RATIO [12:15]
774 * UART4_RATIO [16:19]
775 */
776 ratio = readl(&clk->div_peril0);
777 ratio = (ratio >> (dev_index << 2)) & 0xf;
778
779 uclk = sclk / (ratio + 1);
780
781 return uclk;
782}
783
Jaehoon Chung8788e062012-12-27 22:30:32 +0000784static unsigned long exynos4_get_mmc_clk(int dev_index)
785{
786 struct exynos4_clock *clk =
787 (struct exynos4_clock *)samsung_get_base_clock();
788 unsigned long uclk, sclk;
789 unsigned int sel, ratio, pre_ratio;
Amare1df6282013-04-27 11:42:56 +0530790 int shift = 0;
Jaehoon Chung8788e062012-12-27 22:30:32 +0000791
792 sel = readl(&clk->src_fsys);
793 sel = (sel >> (dev_index << 2)) & 0xf;
794
795 if (sel == 0x6)
796 sclk = get_pll_clk(MPLL);
797 else if (sel == 0x7)
798 sclk = get_pll_clk(EPLL);
799 else if (sel == 0x8)
800 sclk = get_pll_clk(VPLL);
801 else
802 return 0;
803
804 switch (dev_index) {
805 case 0:
806 case 1:
807 ratio = readl(&clk->div_fsys1);
808 pre_ratio = readl(&clk->div_fsys1);
809 break;
810 case 2:
811 case 3:
812 ratio = readl(&clk->div_fsys2);
813 pre_ratio = readl(&clk->div_fsys2);
814 break;
815 case 4:
816 ratio = readl(&clk->div_fsys3);
817 pre_ratio = readl(&clk->div_fsys3);
818 break;
819 default:
820 return 0;
821 }
822
823 if (dev_index == 1 || dev_index == 3)
824 shift = 16;
825
826 ratio = (ratio >> shift) & 0xf;
827 pre_ratio = (pre_ratio >> (shift + 8)) & 0xff;
828 uclk = (sclk / (ratio + 1)) / (pre_ratio + 1);
829
830 return uclk;
831}
832
Chander Kashyap4131a772011-12-06 23:34:12 +0000833/* exynos4: set the mmc clock */
834static void exynos4_set_mmc_clk(int dev_index, unsigned int div)
Jaehoon Chung9a772212011-05-17 21:19:17 +0000835{
Chander Kashyap4131a772011-12-06 23:34:12 +0000836 struct exynos4_clock *clk =
837 (struct exynos4_clock *)samsung_get_base_clock();
Jaehoon Chungd2c83242014-05-16 13:59:50 +0900838 unsigned int addr, clear_bit, set_bit;
Jaehoon Chung9a772212011-05-17 21:19:17 +0000839
840 /*
841 * CLK_DIV_FSYS1
842 * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24]
843 * CLK_DIV_FSYS2
844 * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24]
Jaehoon Chung29fe8c52012-12-27 22:30:33 +0000845 * CLK_DIV_FSYS3
Jaehoon Chungd2c83242014-05-16 13:59:50 +0900846 * MMC4_RATIO [3:0]
Jaehoon Chung9a772212011-05-17 21:19:17 +0000847 */
848 if (dev_index < 2) {
849 addr = (unsigned int)&clk->div_fsys1;
Jaehoon Chungd2c83242014-05-16 13:59:50 +0900850 clear_bit = MASK_PRE_RATIO(dev_index);
851 set_bit = SET_PRE_RATIO(dev_index, div);
852 } else if (dev_index == 4) {
Jaehoon Chung29fe8c52012-12-27 22:30:33 +0000853 addr = (unsigned int)&clk->div_fsys3;
854 dev_index -= 4;
Jaehoon Chungd2c83242014-05-16 13:59:50 +0900855 /* MMC4 is controlled with the MMC4_RATIO value */
856 clear_bit = MASK_RATIO(dev_index);
857 set_bit = SET_RATIO(dev_index, div);
Jaehoon Chung9a772212011-05-17 21:19:17 +0000858 } else {
859 addr = (unsigned int)&clk->div_fsys2;
860 dev_index -= 2;
Jaehoon Chungd2c83242014-05-16 13:59:50 +0900861 clear_bit = MASK_PRE_RATIO(dev_index);
862 set_bit = SET_PRE_RATIO(dev_index, div);
Jaehoon Chung9a772212011-05-17 21:19:17 +0000863 }
864
Jaehoon Chungd2c83242014-05-16 13:59:50 +0900865 clrsetbits_le32(addr, clear_bit, set_bit);
Jaehoon Chung9a772212011-05-17 21:19:17 +0000866}
867
Chander Kashyap34076a02012-02-05 23:01:46 +0000868/* exynos5: set the mmc clock */
869static void exynos5_set_mmc_clk(int dev_index, unsigned int div)
870{
871 struct exynos5_clock *clk =
872 (struct exynos5_clock *)samsung_get_base_clock();
873 unsigned int addr;
Chander Kashyap34076a02012-02-05 23:01:46 +0000874
875 /*
876 * CLK_DIV_FSYS1
877 * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24]
878 * CLK_DIV_FSYS2
879 * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24]
880 */
881 if (dev_index < 2) {
882 addr = (unsigned int)&clk->div_fsys1;
883 } else {
884 addr = (unsigned int)&clk->div_fsys2;
885 dev_index -= 2;
886 }
887
Inha Song4e558532014-02-06 14:20:12 +0900888 clrsetbits_le32(addr, 0xff << ((dev_index << 4) + 8),
889 (div & 0xff) << ((dev_index << 4) + 8));
Chander Kashyap34076a02012-02-05 23:01:46 +0000890}
891
Rajeshwari Birjeac892d02013-12-26 09:44:21 +0530892/* exynos5: set the mmc clock */
893static void exynos5420_set_mmc_clk(int dev_index, unsigned int div)
894{
895 struct exynos5420_clock *clk =
896 (struct exynos5420_clock *)samsung_get_base_clock();
897 unsigned int addr;
Inha Song4e558532014-02-06 14:20:12 +0900898 unsigned int shift;
Rajeshwari Birjeac892d02013-12-26 09:44:21 +0530899
900 /*
901 * CLK_DIV_FSYS1
902 * MMC0_RATIO [9:0]
903 * MMC1_RATIO [19:10]
904 * MMC2_RATIO [29:20]
905 */
906 addr = (unsigned int)&clk->div_fsys1;
907 shift = dev_index * 10;
908
Inha Song4e558532014-02-06 14:20:12 +0900909 clrsetbits_le32(addr, 0x3ff << shift, (div & 0x3ff) << shift);
Rajeshwari Birjeac892d02013-12-26 09:44:21 +0530910}
911
Donghwa Lee77ba1912012-04-05 19:36:12 +0000912/* get_lcd_clk: return lcd clock frequency */
913static unsigned long exynos4_get_lcd_clk(void)
914{
915 struct exynos4_clock *clk =
916 (struct exynos4_clock *)samsung_get_base_clock();
917 unsigned long pclk, sclk;
918 unsigned int sel;
919 unsigned int ratio;
920
921 /*
922 * CLK_SRC_LCD0
923 * FIMD0_SEL [3:0]
924 */
925 sel = readl(&clk->src_lcd0);
926 sel = sel & 0xf;
927
928 /*
929 * 0x6: SCLK_MPLL
930 * 0x7: SCLK_EPLL
931 * 0x8: SCLK_VPLL
932 */
933 if (sel == 0x6)
934 sclk = get_pll_clk(MPLL);
935 else if (sel == 0x7)
936 sclk = get_pll_clk(EPLL);
937 else if (sel == 0x8)
938 sclk = get_pll_clk(VPLL);
939 else
940 return 0;
941
942 /*
943 * CLK_DIV_LCD0
944 * FIMD0_RATIO [3:0]
945 */
946 ratio = readl(&clk->div_lcd0);
947 ratio = ratio & 0xf;
948
949 pclk = sclk / (ratio + 1);
950
951 return pclk;
952}
953
Donghwa Lee3c9d4532012-07-02 01:15:49 +0000954/* get_lcd_clk: return lcd clock frequency */
955static unsigned long exynos5_get_lcd_clk(void)
956{
957 struct exynos5_clock *clk =
958 (struct exynos5_clock *)samsung_get_base_clock();
959 unsigned long pclk, sclk;
960 unsigned int sel;
961 unsigned int ratio;
962
963 /*
964 * CLK_SRC_LCD0
965 * FIMD0_SEL [3:0]
966 */
967 sel = readl(&clk->src_disp1_0);
968 sel = sel & 0xf;
969
970 /*
971 * 0x6: SCLK_MPLL
972 * 0x7: SCLK_EPLL
973 * 0x8: SCLK_VPLL
974 */
975 if (sel == 0x6)
976 sclk = get_pll_clk(MPLL);
977 else if (sel == 0x7)
978 sclk = get_pll_clk(EPLL);
979 else if (sel == 0x8)
980 sclk = get_pll_clk(VPLL);
981 else
982 return 0;
983
984 /*
985 * CLK_DIV_LCD0
986 * FIMD0_RATIO [3:0]
987 */
988 ratio = readl(&clk->div_disp1_0);
989 ratio = ratio & 0xf;
990
991 pclk = sclk / (ratio + 1);
992
993 return pclk;
994}
995
Ajay Kumar914af872014-09-05 16:53:32 +0530996static unsigned long exynos5420_get_lcd_clk(void)
997{
998 struct exynos5420_clock *clk =
999 (struct exynos5420_clock *)samsung_get_base_clock();
1000 unsigned long pclk, sclk;
1001 unsigned int sel;
1002 unsigned int ratio;
1003
1004 /*
1005 * CLK_SRC_DISP10
1006 * FIMD1_SEL [4]
1007 * 0: SCLK_RPLL
1008 * 1: SCLK_SPLL
1009 */
1010 sel = readl(&clk->src_disp10);
1011 sel &= (1 << 4);
1012
1013 if (sel)
1014 sclk = get_pll_clk(SPLL);
1015 else
1016 sclk = get_pll_clk(RPLL);
1017
1018 /*
1019 * CLK_DIV_DISP10
1020 * FIMD1_RATIO [3:0]
1021 */
1022 ratio = readl(&clk->div_disp10);
1023 ratio = ratio & 0xf;
1024
1025 pclk = sclk / (ratio + 1);
1026
1027 return pclk;
1028}
1029
Ajay Kumarf0df9582015-03-04 19:05:24 +05301030static unsigned long exynos5800_get_lcd_clk(void)
1031{
1032 struct exynos5420_clock *clk =
1033 (struct exynos5420_clock *)samsung_get_base_clock();
1034 unsigned long sclk;
1035 unsigned int sel;
1036 unsigned int ratio;
1037
1038 /*
1039 * CLK_SRC_DISP10
1040 * CLKMUX_FIMD1 [6:4]
1041 */
1042 sel = (readl(&clk->src_disp10) >> 4) & 0x7;
1043
1044 if (sel) {
1045 /*
1046 * Mapping of CLK_SRC_DISP10 CLKMUX_FIMD1 [6:4] values into
1047 * PLLs. The first element is a placeholder to bypass the
1048 * default settig.
1049 */
1050 const int reg_map[] = {0, CPLL, DPLL, MPLL, SPLL, IPLL, EPLL,
1051 RPLL};
1052 sclk = get_pll_clk(reg_map[sel]);
1053 } else
1054 sclk = CONFIG_SYS_CLK_FREQ;
1055 /*
1056 * CLK_DIV_DISP10
1057 * FIMD1_RATIO [3:0]
1058 */
1059 ratio = readl(&clk->div_disp10) & 0xf;
1060
1061 return sclk / (ratio + 1);
1062}
1063
Donghwa Lee77ba1912012-04-05 19:36:12 +00001064void exynos4_set_lcd_clk(void)
1065{
1066 struct exynos4_clock *clk =
1067 (struct exynos4_clock *)samsung_get_base_clock();
Donghwa Lee77ba1912012-04-05 19:36:12 +00001068
1069 /*
1070 * CLK_GATE_BLOCK
1071 * CLK_CAM [0]
1072 * CLK_TV [1]
1073 * CLK_MFC [2]
1074 * CLK_G3D [3]
1075 * CLK_LCD0 [4]
1076 * CLK_LCD1 [5]
1077 * CLK_GPS [7]
1078 */
Inha Song4e558532014-02-06 14:20:12 +09001079 setbits_le32(&clk->gate_block, 1 << 4);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001080
1081 /*
1082 * CLK_SRC_LCD0
1083 * FIMD0_SEL [3:0]
1084 * MDNIE0_SEL [7:4]
1085 * MDNIE_PWM0_SEL [8:11]
1086 * MIPI0_SEL [12:15]
1087 * set lcd0 src clock 0x6: SCLK_MPLL
1088 */
Inha Song4e558532014-02-06 14:20:12 +09001089 clrsetbits_le32(&clk->src_lcd0, 0xf, 0x6);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001090
1091 /*
1092 * CLK_GATE_IP_LCD0
1093 * CLK_FIMD0 [0]
1094 * CLK_MIE0 [1]
1095 * CLK_MDNIE0 [2]
1096 * CLK_DSIM0 [3]
1097 * CLK_SMMUFIMD0 [4]
1098 * CLK_PPMULCD0 [5]
1099 * Gating all clocks for FIMD0
1100 */
Inha Song4e558532014-02-06 14:20:12 +09001101 setbits_le32(&clk->gate_ip_lcd0, 1 << 0);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001102
1103 /*
1104 * CLK_DIV_LCD0
1105 * FIMD0_RATIO [3:0]
1106 * MDNIE0_RATIO [7:4]
1107 * MDNIE_PWM0_RATIO [11:8]
1108 * MDNIE_PWM_PRE_RATIO [15:12]
1109 * MIPI0_RATIO [19:16]
1110 * MIPI0_PRE_RATIO [23:20]
1111 * set fimd ratio
1112 */
Inha Song4e558532014-02-06 14:20:12 +09001113 clrsetbits_le32(&clk->div_lcd0, 0xf, 0x1);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001114}
1115
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001116void exynos5_set_lcd_clk(void)
1117{
1118 struct exynos5_clock *clk =
1119 (struct exynos5_clock *)samsung_get_base_clock();
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001120
1121 /*
1122 * CLK_GATE_BLOCK
1123 * CLK_CAM [0]
1124 * CLK_TV [1]
1125 * CLK_MFC [2]
1126 * CLK_G3D [3]
1127 * CLK_LCD0 [4]
1128 * CLK_LCD1 [5]
1129 * CLK_GPS [7]
1130 */
Inha Song4e558532014-02-06 14:20:12 +09001131 setbits_le32(&clk->gate_block, 1 << 4);
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001132
1133 /*
1134 * CLK_SRC_LCD0
1135 * FIMD0_SEL [3:0]
1136 * MDNIE0_SEL [7:4]
1137 * MDNIE_PWM0_SEL [8:11]
1138 * MIPI0_SEL [12:15]
1139 * set lcd0 src clock 0x6: SCLK_MPLL
1140 */
Inha Song4e558532014-02-06 14:20:12 +09001141 clrsetbits_le32(&clk->src_disp1_0, 0xf, 0x6);
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001142
1143 /*
1144 * CLK_GATE_IP_LCD0
1145 * CLK_FIMD0 [0]
1146 * CLK_MIE0 [1]
1147 * CLK_MDNIE0 [2]
1148 * CLK_DSIM0 [3]
1149 * CLK_SMMUFIMD0 [4]
1150 * CLK_PPMULCD0 [5]
1151 * Gating all clocks for FIMD0
1152 */
Inha Song4e558532014-02-06 14:20:12 +09001153 setbits_le32(&clk->gate_ip_disp1, 1 << 0);
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001154
1155 /*
1156 * CLK_DIV_LCD0
1157 * FIMD0_RATIO [3:0]
1158 * MDNIE0_RATIO [7:4]
1159 * MDNIE_PWM0_RATIO [11:8]
1160 * MDNIE_PWM_PRE_RATIO [15:12]
1161 * MIPI0_RATIO [19:16]
1162 * MIPI0_PRE_RATIO [23:20]
1163 * set fimd ratio
1164 */
Inha Song4e558532014-02-06 14:20:12 +09001165 clrsetbits_le32(&clk->div_disp1_0, 0xf, 0x0);
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001166}
1167
Ajay Kumar914af872014-09-05 16:53:32 +05301168void exynos5420_set_lcd_clk(void)
1169{
1170 struct exynos5420_clock *clk =
1171 (struct exynos5420_clock *)samsung_get_base_clock();
1172 unsigned int cfg;
1173
1174 /*
1175 * CLK_SRC_DISP10
1176 * FIMD1_SEL [4]
1177 * 0: SCLK_RPLL
1178 * 1: SCLK_SPLL
1179 */
1180 cfg = readl(&clk->src_disp10);
1181 cfg &= ~(0x1 << 4);
1182 cfg |= (0 << 4);
1183 writel(cfg, &clk->src_disp10);
1184
1185 /*
1186 * CLK_DIV_DISP10
1187 * FIMD1_RATIO [3:0]
1188 */
1189 cfg = readl(&clk->div_disp10);
1190 cfg &= ~(0xf << 0);
1191 cfg |= (0 << 0);
1192 writel(cfg, &clk->div_disp10);
1193}
1194
Ajay Kumarf0df9582015-03-04 19:05:24 +05301195void exynos5800_set_lcd_clk(void)
1196{
1197 struct exynos5420_clock *clk =
1198 (struct exynos5420_clock *)samsung_get_base_clock();
1199 unsigned int cfg;
1200
1201 /*
1202 * Use RPLL for pixel clock
1203 * CLK_SRC_DISP10 CLKMUX_FIMD1 [6:4]
1204 * ==================
1205 * 111: SCLK_RPLL
1206 */
1207 cfg = readl(&clk->src_disp10) | (0x7 << 4);
1208 writel(cfg, &clk->src_disp10);
1209
1210 /*
1211 * CLK_DIV_DISP10
1212 * FIMD1_RATIO [3:0]
1213 */
1214 clrsetbits_le32(&clk->div_disp10, 0xf << 0, 0x0 << 0);
1215}
1216
Donghwa Lee77ba1912012-04-05 19:36:12 +00001217void exynos4_set_mipi_clk(void)
1218{
1219 struct exynos4_clock *clk =
1220 (struct exynos4_clock *)samsung_get_base_clock();
Donghwa Lee77ba1912012-04-05 19:36:12 +00001221
1222 /*
1223 * CLK_SRC_LCD0
1224 * FIMD0_SEL [3:0]
1225 * MDNIE0_SEL [7:4]
1226 * MDNIE_PWM0_SEL [8:11]
1227 * MIPI0_SEL [12:15]
1228 * set mipi0 src clock 0x6: SCLK_MPLL
1229 */
Inha Song4e558532014-02-06 14:20:12 +09001230 clrsetbits_le32(&clk->src_lcd0, 0xf << 12, 0x6 << 12);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001231
1232 /*
1233 * CLK_SRC_MASK_LCD0
1234 * FIMD0_MASK [0]
1235 * MDNIE0_MASK [4]
1236 * MDNIE_PWM0_MASK [8]
1237 * MIPI0_MASK [12]
1238 * set src mask mipi0 0x1: Unmask
1239 */
Inha Song4e558532014-02-06 14:20:12 +09001240 setbits_le32(&clk->src_mask_lcd0, 0x1 << 12);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001241
1242 /*
1243 * CLK_GATE_IP_LCD0
1244 * CLK_FIMD0 [0]
1245 * CLK_MIE0 [1]
1246 * CLK_MDNIE0 [2]
1247 * CLK_DSIM0 [3]
1248 * CLK_SMMUFIMD0 [4]
1249 * CLK_PPMULCD0 [5]
1250 * Gating all clocks for MIPI0
1251 */
Inha Song4e558532014-02-06 14:20:12 +09001252 setbits_le32(&clk->gate_ip_lcd0, 1 << 3);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001253
1254 /*
1255 * CLK_DIV_LCD0
1256 * FIMD0_RATIO [3:0]
1257 * MDNIE0_RATIO [7:4]
1258 * MDNIE_PWM0_RATIO [11:8]
1259 * MDNIE_PWM_PRE_RATIO [15:12]
1260 * MIPI0_RATIO [19:16]
1261 * MIPI0_PRE_RATIO [23:20]
1262 * set mipi ratio
1263 */
Inha Song4e558532014-02-06 14:20:12 +09001264 clrsetbits_le32(&clk->div_lcd0, 0xf << 16, 0x1 << 16);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001265}
1266
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001267int exynos5_set_epll_clk(unsigned long rate)
1268{
1269 unsigned int epll_con, epll_con_k;
1270 unsigned int i;
1271 unsigned int lockcnt;
1272 unsigned int start;
1273 struct exynos5_clock *clk =
1274 (struct exynos5_clock *)samsung_get_base_clock();
1275
1276 epll_con = readl(&clk->epll_con0);
1277 epll_con &= ~((EPLL_CON0_LOCK_DET_EN_MASK <<
1278 EPLL_CON0_LOCK_DET_EN_SHIFT) |
1279 EPLL_CON0_MDIV_MASK << EPLL_CON0_MDIV_SHIFT |
1280 EPLL_CON0_PDIV_MASK << EPLL_CON0_PDIV_SHIFT |
1281 EPLL_CON0_SDIV_MASK << EPLL_CON0_SDIV_SHIFT);
1282
1283 for (i = 0; i < ARRAY_SIZE(exynos5_epll_div); i++) {
1284 if (exynos5_epll_div[i].freq_out == rate)
1285 break;
1286 }
1287
1288 if (i == ARRAY_SIZE(exynos5_epll_div))
1289 return -1;
1290
1291 epll_con_k = exynos5_epll_div[i].k_dsm << 0;
1292 epll_con |= exynos5_epll_div[i].en_lock_det <<
1293 EPLL_CON0_LOCK_DET_EN_SHIFT;
1294 epll_con |= exynos5_epll_div[i].m_div << EPLL_CON0_MDIV_SHIFT;
1295 epll_con |= exynos5_epll_div[i].p_div << EPLL_CON0_PDIV_SHIFT;
1296 epll_con |= exynos5_epll_div[i].s_div << EPLL_CON0_SDIV_SHIFT;
1297
1298 /*
1299 * Required period ( in cycles) to genarate a stable clock output.
1300 * The maximum clock time can be up to 3000 * PDIV cycles of PLLs
1301 * frequency input (as per spec)
1302 */
1303 lockcnt = 3000 * exynos5_epll_div[i].p_div;
1304
1305 writel(lockcnt, &clk->epll_lock);
1306 writel(epll_con, &clk->epll_con0);
1307 writel(epll_con_k, &clk->epll_con1);
1308
1309 start = get_timer(0);
1310
1311 while (!(readl(&clk->epll_con0) &
1312 (0x1 << EXYNOS5_EPLLCON0_LOCKED_SHIFT))) {
1313 if (get_timer(start) > TIMEOUT_EPLL_LOCK) {
1314 debug("%s: Timeout waiting for EPLL lock\n", __func__);
1315 return -1;
1316 }
1317 }
1318 return 0;
1319}
1320
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301321int exynos5_set_i2s_clk_source(unsigned int i2s_id)
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001322{
1323 struct exynos5_clock *clk =
1324 (struct exynos5_clock *)samsung_get_base_clock();
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301325 unsigned int *audio_ass = (unsigned int *)samsung_get_base_audio_ass();
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001326
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301327 if (i2s_id == 0) {
1328 setbits_le32(&clk->src_top2, CLK_SRC_MOUT_EPLL);
1329 clrsetbits_le32(&clk->src_mau, AUDIO0_SEL_MASK,
1330 (CLK_SRC_SCLK_EPLL));
1331 setbits_le32(audio_ass, AUDIO_CLKMUX_ASS);
1332 } else if (i2s_id == 1) {
1333 clrsetbits_le32(&clk->src_peric1, AUDIO1_SEL_MASK,
1334 (CLK_SRC_SCLK_EPLL));
1335 } else {
1336 return -1;
1337 }
1338 return 0;
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001339}
1340
1341int exynos5_set_i2s_clk_prescaler(unsigned int src_frq,
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301342 unsigned int dst_frq,
1343 unsigned int i2s_id)
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001344{
1345 struct exynos5_clock *clk =
1346 (struct exynos5_clock *)samsung_get_base_clock();
1347 unsigned int div;
1348
1349 if ((dst_frq == 0) || (src_frq == 0)) {
1350 debug("%s: Invalid requency input for prescaler\n", __func__);
1351 debug("src frq = %d des frq = %d ", src_frq, dst_frq);
1352 return -1;
1353 }
1354
1355 div = (src_frq / dst_frq);
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301356 if (i2s_id == 0) {
1357 if (div > AUDIO_0_RATIO_MASK) {
1358 debug("%s: Frequency ratio is out of range\n",
1359 __func__);
1360 debug("src frq = %d des frq = %d ", src_frq, dst_frq);
1361 return -1;
1362 }
1363 clrsetbits_le32(&clk->div_mau, AUDIO_0_RATIO_MASK,
1364 (div & AUDIO_0_RATIO_MASK));
Minkyu Kang86253d42015-05-11 16:27:07 +09001365 } else if (i2s_id == 1) {
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301366 if (div > AUDIO_1_RATIO_MASK) {
1367 debug("%s: Frequency ratio is out of range\n",
1368 __func__);
1369 debug("src frq = %d des frq = %d ", src_frq, dst_frq);
1370 return -1;
1371 }
1372 clrsetbits_le32(&clk->div_peric4, AUDIO_1_RATIO_MASK,
1373 (div & AUDIO_1_RATIO_MASK));
1374 } else {
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001375 return -1;
1376 }
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001377 return 0;
1378}
1379
Hatim RVe6365b62012-11-02 01:15:34 +00001380/**
1381 * Linearly searches for the most accurate main and fine stage clock scalars
1382 * (divisors) for a specified target frequency and scalar bit sizes by checking
1383 * all multiples of main_scalar_bits values. Will always return scalars up to or
1384 * slower than target.
1385 *
1386 * @param main_scalar_bits Number of main scalar bits, must be > 0 and < 32
1387 * @param fine_scalar_bits Number of fine scalar bits, must be > 0 and < 32
1388 * @param input_freq Clock frequency to be scaled in Hz
1389 * @param target_freq Desired clock frequency in Hz
1390 * @param best_fine_scalar Pointer to store the fine stage divisor
1391 *
1392 * @return best_main_scalar Main scalar for desired frequency or -1 if none
1393 * found
1394 */
1395static int clock_calc_best_scalar(unsigned int main_scaler_bits,
1396 unsigned int fine_scalar_bits, unsigned int input_rate,
1397 unsigned int target_rate, unsigned int *best_fine_scalar)
1398{
1399 int i;
1400 int best_main_scalar = -1;
1401 unsigned int best_error = target_rate;
1402 const unsigned int cap = (1 << fine_scalar_bits) - 1;
1403 const unsigned int loops = 1 << main_scaler_bits;
1404
1405 debug("Input Rate is %u, Target is %u, Cap is %u\n", input_rate,
1406 target_rate, cap);
1407
1408 assert(best_fine_scalar != NULL);
1409 assert(main_scaler_bits <= fine_scalar_bits);
1410
1411 *best_fine_scalar = 1;
1412
1413 if (input_rate == 0 || target_rate == 0)
1414 return -1;
1415
1416 if (target_rate >= input_rate)
1417 return 1;
1418
1419 for (i = 1; i <= loops; i++) {
Masahiro Yamadadb204642014-11-07 03:03:31 +09001420 const unsigned int effective_div =
1421 max(min(input_rate / i / target_rate, cap), 1U);
Hatim RVe6365b62012-11-02 01:15:34 +00001422 const unsigned int effective_rate = input_rate / i /
1423 effective_div;
1424 const int error = target_rate - effective_rate;
1425
1426 debug("%d|effdiv:%u, effrate:%u, error:%d\n", i, effective_div,
1427 effective_rate, error);
1428
1429 if (error >= 0 && error <= best_error) {
1430 best_error = error;
1431 best_main_scalar = i;
1432 *best_fine_scalar = effective_div;
1433 }
1434 }
1435
1436 return best_main_scalar;
1437}
1438
1439static int exynos5_set_spi_clk(enum periph_id periph_id,
1440 unsigned int rate)
1441{
1442 struct exynos5_clock *clk =
1443 (struct exynos5_clock *)samsung_get_base_clock();
1444 int main;
1445 unsigned int fine;
1446 unsigned shift, pre_shift;
1447 unsigned mask = 0xff;
1448 u32 *reg;
1449
1450 main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine);
1451 if (main < 0) {
1452 debug("%s: Cannot set clock rate for periph %d",
1453 __func__, periph_id);
1454 return -1;
1455 }
1456 main = main - 1;
1457 fine = fine - 1;
1458
1459 switch (periph_id) {
1460 case PERIPH_ID_SPI0:
1461 reg = &clk->div_peric1;
1462 shift = 0;
1463 pre_shift = 8;
1464 break;
1465 case PERIPH_ID_SPI1:
1466 reg = &clk->div_peric1;
1467 shift = 16;
1468 pre_shift = 24;
1469 break;
1470 case PERIPH_ID_SPI2:
1471 reg = &clk->div_peric2;
1472 shift = 0;
1473 pre_shift = 8;
1474 break;
1475 case PERIPH_ID_SPI3:
1476 reg = &clk->sclk_div_isp;
1477 shift = 0;
1478 pre_shift = 4;
1479 break;
1480 case PERIPH_ID_SPI4:
1481 reg = &clk->sclk_div_isp;
1482 shift = 12;
1483 pre_shift = 16;
1484 break;
1485 default:
1486 debug("%s: Unsupported peripheral ID %d\n", __func__,
1487 periph_id);
1488 return -1;
1489 }
1490 clrsetbits_le32(reg, mask << shift, (main & mask) << shift);
1491 clrsetbits_le32(reg, mask << pre_shift, (fine & mask) << pre_shift);
1492
1493 return 0;
1494}
1495
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301496static int exynos5420_set_spi_clk(enum periph_id periph_id,
1497 unsigned int rate)
1498{
1499 struct exynos5420_clock *clk =
1500 (struct exynos5420_clock *)samsung_get_base_clock();
1501 int main;
1502 unsigned int fine;
1503 unsigned shift, pre_shift;
1504 unsigned div_mask = 0xf, pre_div_mask = 0xff;
1505 u32 *reg;
1506 u32 *pre_reg;
1507
1508 main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine);
1509 if (main < 0) {
1510 debug("%s: Cannot set clock rate for periph %d",
1511 __func__, periph_id);
1512 return -1;
1513 }
1514 main = main - 1;
1515 fine = fine - 1;
1516
1517 switch (periph_id) {
1518 case PERIPH_ID_SPI0:
1519 reg = &clk->div_peric1;
1520 shift = 20;
1521 pre_reg = &clk->div_peric4;
1522 pre_shift = 8;
1523 break;
1524 case PERIPH_ID_SPI1:
1525 reg = &clk->div_peric1;
1526 shift = 24;
1527 pre_reg = &clk->div_peric4;
1528 pre_shift = 16;
1529 break;
1530 case PERIPH_ID_SPI2:
1531 reg = &clk->div_peric1;
1532 shift = 28;
1533 pre_reg = &clk->div_peric4;
1534 pre_shift = 24;
1535 break;
1536 case PERIPH_ID_SPI3:
1537 reg = &clk->div_isp1;
1538 shift = 16;
1539 pre_reg = &clk->div_isp1;
1540 pre_shift = 0;
1541 break;
1542 case PERIPH_ID_SPI4:
1543 reg = &clk->div_isp1;
1544 shift = 20;
1545 pre_reg = &clk->div_isp1;
1546 pre_shift = 8;
1547 break;
1548 default:
1549 debug("%s: Unsupported peripheral ID %d\n", __func__,
1550 periph_id);
1551 return -1;
1552 }
1553
1554 clrsetbits_le32(reg, div_mask << shift, (main & div_mask) << shift);
1555 clrsetbits_le32(pre_reg, pre_div_mask << pre_shift,
1556 (fine & pre_div_mask) << pre_shift);
1557
1558 return 0;
1559}
1560
Piotr Wilczek01d589f2012-11-20 02:19:02 +00001561static unsigned long exynos4_get_i2c_clk(void)
1562{
1563 struct exynos4_clock *clk =
1564 (struct exynos4_clock *)samsung_get_base_clock();
1565 unsigned long sclk, aclk_100;
1566 unsigned int ratio;
1567
1568 sclk = get_pll_clk(APLL);
1569
1570 ratio = (readl(&clk->div_top)) >> 4;
1571 ratio &= 0xf;
1572 aclk_100 = sclk / (ratio + 1);
1573 return aclk_100;
Rajeshwari Shinde1c9412a2012-07-23 21:23:48 +00001574}
1575
Minkyu Kangb1b24682011-01-24 15:22:23 +09001576unsigned long get_pll_clk(int pllreg)
1577{
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301578 if (cpu_is_exynos5()) {
Akshay Saraswat9fba7b42014-11-13 22:38:15 +05301579 if (proid_is_exynos5420() || proid_is_exynos5800())
Akshay Saraswat1bd40e42015-02-04 16:00:00 +05301580 return exynos542x_get_pll_clk(pllreg);
Chander Kashyap34076a02012-02-05 23:01:46 +00001581 return exynos5_get_pll_clk(pllreg);
Minkyu Kang86253d42015-05-11 16:27:07 +09001582 } else if (cpu_is_exynos4()) {
Chander Kashyap400ab162012-10-07 01:43:17 +00001583 if (proid_is_exynos4412())
1584 return exynos4x12_get_pll_clk(pllreg);
Chander Kashyap34076a02012-02-05 23:01:46 +00001585 return exynos4_get_pll_clk(pllreg);
Chander Kashyap400ab162012-10-07 01:43:17 +00001586 }
Minkyu Kang86253d42015-05-11 16:27:07 +09001587
1588 return 0;
Minkyu Kangb1b24682011-01-24 15:22:23 +09001589}
1590
1591unsigned long get_arm_clk(void)
1592{
Minkyu Kang86253d42015-05-11 16:27:07 +09001593 if (cpu_is_exynos5()) {
Chander Kashyap34076a02012-02-05 23:01:46 +00001594 return exynos5_get_arm_clk();
Minkyu Kang86253d42015-05-11 16:27:07 +09001595 } else if (cpu_is_exynos4()) {
Chander Kashyap400ab162012-10-07 01:43:17 +00001596 if (proid_is_exynos4412())
1597 return exynos4x12_get_arm_clk();
Chander Kashyap34076a02012-02-05 23:01:46 +00001598 return exynos4_get_arm_clk();
Chander Kashyap400ab162012-10-07 01:43:17 +00001599 }
Minkyu Kang86253d42015-05-11 16:27:07 +09001600
1601 return 0;
Minkyu Kangb1b24682011-01-24 15:22:23 +09001602}
1603
Rajeshwari Shinde1c9412a2012-07-23 21:23:48 +00001604unsigned long get_i2c_clk(void)
1605{
Minkyu Kang86253d42015-05-11 16:27:07 +09001606 if (cpu_is_exynos5())
Akshay Saraswat348bc5f2015-02-04 16:00:03 +05301607 return clock_get_periph_rate(PERIPH_ID_I2C0);
Minkyu Kang86253d42015-05-11 16:27:07 +09001608 else if (cpu_is_exynos4())
Piotr Wilczek01d589f2012-11-20 02:19:02 +00001609 return exynos4_get_i2c_clk();
Minkyu Kang86253d42015-05-11 16:27:07 +09001610
1611 return 0;
Rajeshwari Shinde1c9412a2012-07-23 21:23:48 +00001612}
1613
Minkyu Kangb1b24682011-01-24 15:22:23 +09001614unsigned long get_pwm_clk(void)
1615{
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301616 if (cpu_is_exynos5()) {
Padmavathi Vennabb714162013-03-28 04:32:23 +00001617 return clock_get_periph_rate(PERIPH_ID_PWM0);
Minkyu Kang86253d42015-05-11 16:27:07 +09001618 } else if (cpu_is_exynos4()) {
Chander Kashyap400ab162012-10-07 01:43:17 +00001619 if (proid_is_exynos4412())
1620 return exynos4x12_get_pwm_clk();
Chander Kashyap34076a02012-02-05 23:01:46 +00001621 return exynos4_get_pwm_clk();
Chander Kashyap400ab162012-10-07 01:43:17 +00001622 }
Minkyu Kang86253d42015-05-11 16:27:07 +09001623
1624 return 0;
Minkyu Kangb1b24682011-01-24 15:22:23 +09001625}
1626
1627unsigned long get_uart_clk(int dev_index)
1628{
Akshay Saraswat348bc5f2015-02-04 16:00:03 +05301629 enum periph_id id;
1630
1631 switch (dev_index) {
1632 case 0:
1633 id = PERIPH_ID_UART0;
1634 break;
1635 case 1:
1636 id = PERIPH_ID_UART1;
1637 break;
1638 case 2:
1639 id = PERIPH_ID_UART2;
1640 break;
1641 case 3:
1642 id = PERIPH_ID_UART3;
1643 break;
1644 default:
1645 debug("%s: invalid UART index %d", __func__, dev_index);
1646 return -1;
1647 }
1648
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301649 if (cpu_is_exynos5()) {
Akshay Saraswat348bc5f2015-02-04 16:00:03 +05301650 return clock_get_periph_rate(id);
Minkyu Kang86253d42015-05-11 16:27:07 +09001651 } else if (cpu_is_exynos4()) {
Chander Kashyap400ab162012-10-07 01:43:17 +00001652 if (proid_is_exynos4412())
1653 return exynos4x12_get_uart_clk(dev_index);
Chander Kashyap34076a02012-02-05 23:01:46 +00001654 return exynos4_get_uart_clk(dev_index);
Chander Kashyap400ab162012-10-07 01:43:17 +00001655 }
Minkyu Kang86253d42015-05-11 16:27:07 +09001656
1657 return 0;
Minkyu Kangb1b24682011-01-24 15:22:23 +09001658}
Jaehoon Chung9a772212011-05-17 21:19:17 +00001659
Jaehoon Chung8788e062012-12-27 22:30:32 +00001660unsigned long get_mmc_clk(int dev_index)
1661{
Akshay Saraswat348bc5f2015-02-04 16:00:03 +05301662 enum periph_id id;
1663
Przemyslaw Marczakccae0d42015-09-30 13:14:52 +02001664 if (cpu_is_exynos4())
1665 return exynos4_get_mmc_clk(dev_index);
1666
Akshay Saraswat348bc5f2015-02-04 16:00:03 +05301667 switch (dev_index) {
1668 case 0:
1669 id = PERIPH_ID_SDMMC0;
1670 break;
1671 case 1:
1672 id = PERIPH_ID_SDMMC1;
1673 break;
1674 case 2:
1675 id = PERIPH_ID_SDMMC2;
1676 break;
1677 case 3:
1678 id = PERIPH_ID_SDMMC3;
1679 break;
1680 default:
1681 debug("%s: invalid MMC index %d", __func__, dev_index);
1682 return -1;
1683 }
1684
Przemyslaw Marczakccae0d42015-09-30 13:14:52 +02001685 return clock_get_periph_rate(id);
Jaehoon Chung8788e062012-12-27 22:30:32 +00001686}
1687
Jaehoon Chung9a772212011-05-17 21:19:17 +00001688void set_mmc_clk(int dev_index, unsigned int div)
1689{
Jaehoon Chung15cd6b52015-01-08 16:50:21 +09001690 /* If want to set correct value, it needs to substract one from div.*/
1691 if (div > 0)
1692 div -= 1;
1693
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301694 if (cpu_is_exynos5()) {
Akshay Saraswat9fba7b42014-11-13 22:38:15 +05301695 if (proid_is_exynos5420() || proid_is_exynos5800())
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301696 exynos5420_set_mmc_clk(dev_index, div);
1697 else
1698 exynos5_set_mmc_clk(dev_index, div);
Minkyu Kang86253d42015-05-11 16:27:07 +09001699 } else if (cpu_is_exynos4()) {
Beomho Seo99660cc2014-05-16 13:59:47 +09001700 exynos4_set_mmc_clk(dev_index, div);
Chander Kashyap400ab162012-10-07 01:43:17 +00001701 }
Jaehoon Chung9a772212011-05-17 21:19:17 +00001702}
Donghwa Lee77ba1912012-04-05 19:36:12 +00001703
1704unsigned long get_lcd_clk(void)
1705{
Minkyu Kang86253d42015-05-11 16:27:07 +09001706 if (cpu_is_exynos4()) {
Donghwa Lee77ba1912012-04-05 19:36:12 +00001707 return exynos4_get_lcd_clk();
Minkyu Kang86253d42015-05-11 16:27:07 +09001708 } else if (cpu_is_exynos5()) {
Ajay Kumarf0df9582015-03-04 19:05:24 +05301709 if (proid_is_exynos5420())
Ajay Kumar914af872014-09-05 16:53:32 +05301710 return exynos5420_get_lcd_clk();
Ajay Kumarf0df9582015-03-04 19:05:24 +05301711 else if (proid_is_exynos5800())
1712 return exynos5800_get_lcd_clk();
Ajay Kumar914af872014-09-05 16:53:32 +05301713 else
1714 return exynos5_get_lcd_clk();
1715 }
Minkyu Kang86253d42015-05-11 16:27:07 +09001716
1717 return 0;
Donghwa Lee77ba1912012-04-05 19:36:12 +00001718}
1719
1720void set_lcd_clk(void)
1721{
Minkyu Kang86253d42015-05-11 16:27:07 +09001722 if (cpu_is_exynos4()) {
Donghwa Lee77ba1912012-04-05 19:36:12 +00001723 exynos4_set_lcd_clk();
Minkyu Kang86253d42015-05-11 16:27:07 +09001724 } else if (cpu_is_exynos5()) {
Ajay Kumar914af872014-09-05 16:53:32 +05301725 if (proid_is_exynos5250())
1726 exynos5_set_lcd_clk();
Ajay Kumarf0df9582015-03-04 19:05:24 +05301727 else if (proid_is_exynos5420())
Ajay Kumar914af872014-09-05 16:53:32 +05301728 exynos5420_set_lcd_clk();
Ajay Kumarf0df9582015-03-04 19:05:24 +05301729 else
1730 exynos5800_set_lcd_clk();
Ajay Kumar914af872014-09-05 16:53:32 +05301731 }
Donghwa Lee77ba1912012-04-05 19:36:12 +00001732}
1733
1734void set_mipi_clk(void)
1735{
1736 if (cpu_is_exynos4())
1737 exynos4_set_mipi_clk();
1738}
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001739
Hatim RVe6365b62012-11-02 01:15:34 +00001740int set_spi_clk(int periph_id, unsigned int rate)
1741{
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301742 if (cpu_is_exynos5()) {
Akshay Saraswat9fba7b42014-11-13 22:38:15 +05301743 if (proid_is_exynos5420() || proid_is_exynos5800())
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301744 return exynos5420_set_spi_clk(periph_id, rate);
Hatim RVe6365b62012-11-02 01:15:34 +00001745 return exynos5_set_spi_clk(periph_id, rate);
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301746 }
Minkyu Kang86253d42015-05-11 16:27:07 +09001747
1748 return 0;
Hatim RVe6365b62012-11-02 01:15:34 +00001749}
1750
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301751int set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq,
1752 unsigned int i2s_id)
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001753{
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001754 if (cpu_is_exynos5())
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301755 return exynos5_set_i2s_clk_prescaler(src_frq, dst_frq, i2s_id);
Minkyu Kang86253d42015-05-11 16:27:07 +09001756
1757 return 0;
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001758}
1759
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301760int set_i2s_clk_source(unsigned int i2s_id)
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001761{
1762 if (cpu_is_exynos5())
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301763 return exynos5_set_i2s_clk_source(i2s_id);
Minkyu Kang86253d42015-05-11 16:27:07 +09001764
1765 return 0;
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001766}
1767
1768int set_epll_clk(unsigned long rate)
1769{
1770 if (cpu_is_exynos5())
1771 return exynos5_set_epll_clk(rate);
Minkyu Kang86253d42015-05-11 16:27:07 +09001772
1773 return 0;
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001774}