blob: ee71b95237df6b5a2d3c9e6f023cc602b8aa6b3e [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Minkyu Kangb1b24682011-01-24 15:22:23 +09002/*
3 * Copyright (C) 2010 Samsung Electronics
4 * Minkyu Kang <mk7.kang@samsung.com>
Minkyu Kangb1b24682011-01-24 15:22:23 +09005 */
6
Tom Rini8c70baa2021-12-14 13:36:40 -05007#include <clock_legacy.h>
Simon Glass0f2af882020-05-10 11:40:05 -06008#include <log.h>
Tom Rinidec7ea02024-05-20 13:35:03 -06009#include <time.h>
10#include <mach/cpu.h>
Minkyu Kangb1b24682011-01-24 15:22:23 +090011#include <asm/io.h>
12#include <asm/arch/clock.h>
13#include <asm/arch/clk.h>
Hatim RVe6365b62012-11-02 01:15:34 +000014#include <asm/arch/periph.h>
Minkyu Kangb1b24682011-01-24 15:22:23 +090015
Minkyu Kang368588e2013-07-05 19:08:33 +090016#define PLL_DIV_1024 1024
17#define PLL_DIV_65535 65535
18#define PLL_DIV_65536 65536
Padmavathi Venna37feb7b2013-03-28 04:32:21 +000019/* *
20 * This structure is to store the src bit, div bit and prediv bit
21 * positions of the peripheral clocks of the src and div registers
22 */
23struct clk_bit_info {
Akshay Saraswat3ad7ffc2015-02-04 15:59:59 +053024 enum periph_id id;
Akshay Saraswatd932c362015-02-04 16:00:04 +053025 int32_t src_mask;
26 int32_t div_mask;
27 int32_t prediv_mask;
Padmavathi Venna37feb7b2013-03-28 04:32:21 +000028 int8_t src_bit;
29 int8_t div_bit;
30 int8_t prediv_bit;
31};
32
Akshay Saraswatd5072262015-02-04 16:00:01 +053033static struct clk_bit_info exynos5_bit_info[] = {
Akshay Saraswatd932c362015-02-04 16:00:04 +053034 /* periph id s_mask d_mask p_mask s_bit d_bit p_bit */
35 {PERIPH_ID_UART0, 0xf, 0xf, -1, 0, 0, -1},
36 {PERIPH_ID_UART1, 0xf, 0xf, -1, 4, 4, -1},
37 {PERIPH_ID_UART2, 0xf, 0xf, -1, 8, 8, -1},
38 {PERIPH_ID_UART3, 0xf, 0xf, -1, 12, 12, -1},
39 {PERIPH_ID_I2C0, -1, 0x7, 0x7, -1, 24, 0},
40 {PERIPH_ID_I2C1, -1, 0x7, 0x7, -1, 24, 0},
41 {PERIPH_ID_I2C2, -1, 0x7, 0x7, -1, 24, 0},
42 {PERIPH_ID_I2C3, -1, 0x7, 0x7, -1, 24, 0},
43 {PERIPH_ID_I2C4, -1, 0x7, 0x7, -1, 24, 0},
44 {PERIPH_ID_I2C5, -1, 0x7, 0x7, -1, 24, 0},
45 {PERIPH_ID_I2C6, -1, 0x7, 0x7, -1, 24, 0},
46 {PERIPH_ID_I2C7, -1, 0x7, 0x7, -1, 24, 0},
47 {PERIPH_ID_SPI0, 0xf, 0xf, 0xff, 16, 0, 8},
48 {PERIPH_ID_SPI1, 0xf, 0xf, 0xff, 20, 16, 24},
49 {PERIPH_ID_SPI2, 0xf, 0xf, 0xff, 24, 0, 8},
50 {PERIPH_ID_SDMMC0, 0xf, 0xf, 0xff, 0, 0, 8},
51 {PERIPH_ID_SDMMC1, 0xf, 0xf, 0xff, 4, 16, 24},
52 {PERIPH_ID_SDMMC2, 0xf, 0xf, 0xff, 8, 0, 8},
53 {PERIPH_ID_SDMMC3, 0xf, 0xf, 0xff, 12, 16, 24},
54 {PERIPH_ID_I2S0, 0xf, 0xf, 0xff, 0, 0, 4},
55 {PERIPH_ID_I2S1, 0xf, 0xf, 0xff, 4, 12, 16},
56 {PERIPH_ID_SPI3, 0xf, 0xf, 0xff, 0, 0, 4},
57 {PERIPH_ID_SPI4, 0xf, 0xf, 0xff, 4, 12, 16},
58 {PERIPH_ID_SDMMC4, 0xf, 0xf, 0xff, 16, 0, 8},
59 {PERIPH_ID_PWM0, 0xf, 0xf, -1, 24, 0, -1},
60 {PERIPH_ID_PWM1, 0xf, 0xf, -1, 24, 0, -1},
61 {PERIPH_ID_PWM2, 0xf, 0xf, -1, 24, 0, -1},
62 {PERIPH_ID_PWM3, 0xf, 0xf, -1, 24, 0, -1},
63 {PERIPH_ID_PWM4, 0xf, 0xf, -1, 24, 0, -1},
Akshay Saraswat3ad7ffc2015-02-04 15:59:59 +053064
Akshay Saraswatd932c362015-02-04 16:00:04 +053065 {PERIPH_ID_NONE, -1, -1, -1, -1, -1, -1},
Padmavathi Venna37feb7b2013-03-28 04:32:21 +000066};
67
Akshay Saraswatd5072262015-02-04 16:00:01 +053068static struct clk_bit_info exynos542x_bit_info[] = {
Akshay Saraswatd932c362015-02-04 16:00:04 +053069 /* periph id s_mask d_mask p_mask s_bit d_bit p_bit */
70 {PERIPH_ID_UART0, 0xf, 0xf, -1, 4, 8, -1},
71 {PERIPH_ID_UART1, 0xf, 0xf, -1, 8, 12, -1},
72 {PERIPH_ID_UART2, 0xf, 0xf, -1, 12, 16, -1},
73 {PERIPH_ID_UART3, 0xf, 0xf, -1, 16, 20, -1},
74 {PERIPH_ID_I2C0, -1, 0x3f, -1, -1, 8, -1},
75 {PERIPH_ID_I2C1, -1, 0x3f, -1, -1, 8, -1},
76 {PERIPH_ID_I2C2, -1, 0x3f, -1, -1, 8, -1},
77 {PERIPH_ID_I2C3, -1, 0x3f, -1, -1, 8, -1},
78 {PERIPH_ID_I2C4, -1, 0x3f, -1, -1, 8, -1},
79 {PERIPH_ID_I2C5, -1, 0x3f, -1, -1, 8, -1},
80 {PERIPH_ID_I2C6, -1, 0x3f, -1, -1, 8, -1},
81 {PERIPH_ID_I2C7, -1, 0x3f, -1, -1, 8, -1},
82 {PERIPH_ID_SPI0, 0xf, 0xf, 0xff, 20, 20, 8},
83 {PERIPH_ID_SPI1, 0xf, 0xf, 0xff, 24, 24, 16},
84 {PERIPH_ID_SPI2, 0xf, 0xf, 0xff, 28, 28, 24},
85 {PERIPH_ID_SDMMC0, 0x7, 0x3ff, -1, 8, 0, -1},
86 {PERIPH_ID_SDMMC1, 0x7, 0x3ff, -1, 12, 10, -1},
87 {PERIPH_ID_SDMMC2, 0x7, 0x3ff, -1, 16, 20, -1},
88 {PERIPH_ID_I2C8, -1, 0x3f, -1, -1, 8, -1},
89 {PERIPH_ID_I2C9, -1, 0x3f, -1, -1, 8, -1},
90 {PERIPH_ID_I2S0, 0xf, 0xf, 0xff, 0, 0, 4},
91 {PERIPH_ID_I2S1, 0xf, 0xf, 0xff, 4, 12, 16},
92 {PERIPH_ID_SPI3, 0xf, 0xf, 0xff, 12, 16, 0},
93 {PERIPH_ID_SPI4, 0xf, 0xf, 0xff, 16, 20, 8},
94 {PERIPH_ID_PWM0, 0xf, 0xf, -1, 24, 28, -1},
95 {PERIPH_ID_PWM1, 0xf, 0xf, -1, 24, 28, -1},
96 {PERIPH_ID_PWM2, 0xf, 0xf, -1, 24, 28, -1},
97 {PERIPH_ID_PWM3, 0xf, 0xf, -1, 24, 28, -1},
98 {PERIPH_ID_PWM4, 0xf, 0xf, -1, 24, 28, -1},
99 {PERIPH_ID_I2C10, -1, 0x3f, -1, -1, 8, -1},
Akshay Saraswatd5072262015-02-04 16:00:01 +0530100
Akshay Saraswatd932c362015-02-04 16:00:04 +0530101 {PERIPH_ID_NONE, -1, -1, -1, -1, -1, -1},
Akshay Saraswatd5072262015-02-04 16:00:01 +0530102};
103
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +0000104/* Epll Clock division values to achive different frequency output */
105static struct set_epll_con_val exynos5_epll_div[] = {
106 { 192000000, 0, 48, 3, 1, 0 },
107 { 180000000, 0, 45, 3, 1, 0 },
108 { 73728000, 1, 73, 3, 3, 47710 },
109 { 67737600, 1, 90, 4, 3, 20762 },
110 { 49152000, 0, 49, 3, 3, 9961 },
111 { 45158400, 0, 45, 3, 3, 10381 },
112 { 180633600, 0, 45, 3, 1, 10381 }
113};
114
Minkyu Kang1a055aa2012-10-15 01:58:00 +0000115/* exynos: return pll clock frequency */
116static int exynos_get_pll_clk(int pllreg, unsigned int r, unsigned int k)
Minkyu Kangb1b24682011-01-24 15:22:23 +0900117{
Minkyu Kang1a055aa2012-10-15 01:58:00 +0000118 unsigned long m, p, s = 0, mask, fout;
Minkyu Kang368588e2013-07-05 19:08:33 +0900119 unsigned int div;
Minkyu Kangb1b24682011-01-24 15:22:23 +0900120 unsigned int freq;
Minkyu Kangb1b24682011-01-24 15:22:23 +0900121 /*
122 * APLL_CON: MIDV [25:16]
123 * MPLL_CON: MIDV [25:16]
124 * EPLL_CON: MIDV [24:16]
125 * VPLL_CON: MIDV [24:16]
Minkyu Kang1a055aa2012-10-15 01:58:00 +0000126 * BPLL_CON: MIDV [25:16]: Exynos5
Minkyu Kangb1b24682011-01-24 15:22:23 +0900127 */
Ajay Kumar914af872014-09-05 16:53:32 +0530128 if (pllreg == APLL || pllreg == MPLL || pllreg == BPLL ||
129 pllreg == SPLL)
Minkyu Kangb1b24682011-01-24 15:22:23 +0900130 mask = 0x3ff;
131 else
132 mask = 0x1ff;
133
134 m = (r >> 16) & mask;
135
136 /* PDIV [13:8] */
137 p = (r >> 8) & 0x3f;
138 /* SDIV [2:0] */
139 s = r & 0x7;
140
Tom Rini8c70baa2021-12-14 13:36:40 -0500141 freq = get_board_sys_clk();
Minkyu Kangb1b24682011-01-24 15:22:23 +0900142
Rajeshwari Birjeac892d02013-12-26 09:44:21 +0530143 if (pllreg == EPLL || pllreg == RPLL) {
Minkyu Kangb1b24682011-01-24 15:22:23 +0900144 k = k & 0xffff;
145 /* FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV) */
Minkyu Kang368588e2013-07-05 19:08:33 +0900146 fout = (m + k / PLL_DIV_65536) * (freq / (p * (1 << s)));
Minkyu Kangb1b24682011-01-24 15:22:23 +0900147 } else if (pllreg == VPLL) {
148 k = k & 0xfff;
Minkyu Kang368588e2013-07-05 19:08:33 +0900149
150 /*
151 * Exynos4210
152 * FOUT = (MDIV + K / 1024) * FIN / (PDIV * 2^SDIV)
153 *
154 * Exynos4412
155 * FOUT = (MDIV + K / 65535) * FIN / (PDIV * 2^SDIV)
156 *
157 * Exynos5250
158 * FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV)
159 */
160 if (proid_is_exynos4210())
161 div = PLL_DIV_1024;
162 else if (proid_is_exynos4412())
163 div = PLL_DIV_65535;
Przemyslaw Marczakcefbfe42015-10-27 13:07:57 +0100164 else if (proid_is_exynos5250() || proid_is_exynos5420() ||
165 proid_is_exynos5422())
Minkyu Kang368588e2013-07-05 19:08:33 +0900166 div = PLL_DIV_65536;
167 else
168 return 0;
169
170 fout = (m + k / div) * (freq / (p * (1 << s)));
Minkyu Kangb1b24682011-01-24 15:22:23 +0900171 } else {
Minkyu Kang368588e2013-07-05 19:08:33 +0900172 /*
Łukasz Majewski326c4592013-07-12 19:08:25 +0200173 * Exynos4412 / Exynos5250
Minkyu Kang368588e2013-07-05 19:08:33 +0900174 * FOUT = MDIV * FIN / (PDIV * 2^SDIV)
175 *
Łukasz Majewski326c4592013-07-12 19:08:25 +0200176 * Exynos4210
Minkyu Kang368588e2013-07-05 19:08:33 +0900177 * FOUT = MDIV * FIN / (PDIV * 2^(SDIV-1))
178 */
179 if (proid_is_exynos4210())
Minkyu Kang368588e2013-07-05 19:08:33 +0900180 fout = m * (freq / (p * (1 << (s - 1))));
Łukasz Majewski326c4592013-07-12 19:08:25 +0200181 else
182 fout = m * (freq / (p * (1 << s)));
Minkyu Kangb1b24682011-01-24 15:22:23 +0900183 }
Minkyu Kangb1b24682011-01-24 15:22:23 +0900184 return fout;
185}
186
Minkyu Kang1a055aa2012-10-15 01:58:00 +0000187/* exynos4: return pll clock frequency */
188static unsigned long exynos4_get_pll_clk(int pllreg)
189{
190 struct exynos4_clock *clk =
191 (struct exynos4_clock *)samsung_get_base_clock();
192 unsigned long r, k = 0;
193
194 switch (pllreg) {
195 case APLL:
196 r = readl(&clk->apll_con0);
197 break;
198 case MPLL:
199 r = readl(&clk->mpll_con0);
200 break;
201 case EPLL:
202 r = readl(&clk->epll_con0);
203 k = readl(&clk->epll_con1);
204 break;
205 case VPLL:
206 r = readl(&clk->vpll_con0);
207 k = readl(&clk->vpll_con1);
208 break;
209 default:
210 printf("Unsupported PLL (%d)\n", pllreg);
211 return 0;
212 }
213
214 return exynos_get_pll_clk(pllreg, r, k);
215}
216
Chander Kashyap400ab162012-10-07 01:43:17 +0000217/* exynos4x12: return pll clock frequency */
218static unsigned long exynos4x12_get_pll_clk(int pllreg)
219{
220 struct exynos4x12_clock *clk =
221 (struct exynos4x12_clock *)samsung_get_base_clock();
222 unsigned long r, k = 0;
223
224 switch (pllreg) {
225 case APLL:
226 r = readl(&clk->apll_con0);
227 break;
228 case MPLL:
229 r = readl(&clk->mpll_con0);
230 break;
231 case EPLL:
232 r = readl(&clk->epll_con0);
233 k = readl(&clk->epll_con1);
234 break;
235 case VPLL:
236 r = readl(&clk->vpll_con0);
237 k = readl(&clk->vpll_con1);
238 break;
239 default:
240 printf("Unsupported PLL (%d)\n", pllreg);
241 return 0;
242 }
243
244 return exynos_get_pll_clk(pllreg, r, k);
245}
246
Chander Kashyap34076a02012-02-05 23:01:46 +0000247/* exynos5: return pll clock frequency */
248static unsigned long exynos5_get_pll_clk(int pllreg)
249{
250 struct exynos5_clock *clk =
251 (struct exynos5_clock *)samsung_get_base_clock();
Minkyu Kang1a055aa2012-10-15 01:58:00 +0000252 unsigned long r, k = 0, fout;
253 unsigned int pll_div2_sel, fout_sel;
Chander Kashyap34076a02012-02-05 23:01:46 +0000254
255 switch (pllreg) {
256 case APLL:
257 r = readl(&clk->apll_con0);
258 break;
259 case MPLL:
260 r = readl(&clk->mpll_con0);
261 break;
262 case EPLL:
263 r = readl(&clk->epll_con0);
264 k = readl(&clk->epll_con1);
265 break;
266 case VPLL:
267 r = readl(&clk->vpll_con0);
268 k = readl(&clk->vpll_con1);
269 break;
Rajeshwari Shinde84112862012-07-03 20:02:58 +0000270 case BPLL:
271 r = readl(&clk->bpll_con0);
272 break;
Chander Kashyap34076a02012-02-05 23:01:46 +0000273 default:
274 printf("Unsupported PLL (%d)\n", pllreg);
275 return 0;
276 }
277
Minkyu Kang1a055aa2012-10-15 01:58:00 +0000278 fout = exynos_get_pll_clk(pllreg, r, k);
Chander Kashyap34076a02012-02-05 23:01:46 +0000279
Rajeshwari Shinde84112862012-07-03 20:02:58 +0000280 /* According to the user manual, in EVT1 MPLL and BPLL always gives
Rajeshwari Shinde7b9afce2012-07-03 20:02:57 +0000281 * 1.6GHz clock, so divide by 2 to get 800MHz MPLL clock.*/
Rajeshwari Shinde84112862012-07-03 20:02:58 +0000282 if (pllreg == MPLL || pllreg == BPLL) {
Rajeshwari Shinde7b9afce2012-07-03 20:02:57 +0000283 pll_div2_sel = readl(&clk->pll_div2_sel);
Rajeshwari Shinde84112862012-07-03 20:02:58 +0000284
285 switch (pllreg) {
286 case MPLL:
287 fout_sel = (pll_div2_sel >> MPLL_FOUT_SEL_SHIFT)
288 & MPLL_FOUT_SEL_MASK;
289 break;
290 case BPLL:
291 fout_sel = (pll_div2_sel >> BPLL_FOUT_SEL_SHIFT)
292 & BPLL_FOUT_SEL_MASK;
293 break;
Jaehoon Chung0fc779c2012-07-09 21:20:34 +0000294 default:
295 fout_sel = -1;
296 break;
Rajeshwari Shinde84112862012-07-03 20:02:58 +0000297 }
298
299 if (fout_sel == 0)
Rajeshwari Shinde7b9afce2012-07-03 20:02:57 +0000300 fout /= 2;
301 }
302
Chander Kashyap34076a02012-02-05 23:01:46 +0000303 return fout;
304}
305
Akshay Saraswat1bd40e42015-02-04 16:00:00 +0530306/* exynos542x: return pll clock frequency */
307static unsigned long exynos542x_get_pll_clk(int pllreg)
308{
309 struct exynos5420_clock *clk =
310 (struct exynos5420_clock *)samsung_get_base_clock();
311 unsigned long r, k = 0;
312
313 switch (pllreg) {
314 case APLL:
315 r = readl(&clk->apll_con0);
316 break;
317 case MPLL:
318 r = readl(&clk->mpll_con0);
319 break;
320 case EPLL:
321 r = readl(&clk->epll_con0);
322 k = readl(&clk->epll_con1);
323 break;
324 case VPLL:
325 r = readl(&clk->vpll_con0);
326 k = readl(&clk->vpll_con1);
327 break;
328 case BPLL:
329 r = readl(&clk->bpll_con0);
330 break;
331 case RPLL:
332 r = readl(&clk->rpll_con0);
333 k = readl(&clk->rpll_con1);
334 break;
335 case SPLL:
336 r = readl(&clk->spll_con0);
337 break;
338 default:
339 printf("Unsupported PLL (%d)\n", pllreg);
340 return 0;
341 }
342
343 return exynos_get_pll_clk(pllreg, r, k);
344}
345
Akshay Saraswat3ad7ffc2015-02-04 15:59:59 +0530346static struct clk_bit_info *get_clk_bit_info(int peripheral)
347{
348 int i;
Akshay Saraswatd5072262015-02-04 16:00:01 +0530349 struct clk_bit_info *info;
350
Simon Glass8d451b42018-12-10 10:37:40 -0700351 if (proid_is_exynos542x())
Akshay Saraswatd5072262015-02-04 16:00:01 +0530352 info = exynos542x_bit_info;
353 else
354 info = exynos5_bit_info;
Akshay Saraswat3ad7ffc2015-02-04 15:59:59 +0530355
Akshay Saraswatd5072262015-02-04 16:00:01 +0530356 for (i = 0; info[i].id != PERIPH_ID_NONE; i++) {
357 if (info[i].id == peripheral)
Akshay Saraswat3ad7ffc2015-02-04 15:59:59 +0530358 break;
359 }
360
Akshay Saraswatd5072262015-02-04 16:00:01 +0530361 if (info[i].id == PERIPH_ID_NONE)
Akshay Saraswat3ad7ffc2015-02-04 15:59:59 +0530362 debug("ERROR: Peripheral ID %d not found\n", peripheral);
363
Akshay Saraswatd5072262015-02-04 16:00:01 +0530364 return &info[i];
Akshay Saraswat3ad7ffc2015-02-04 15:59:59 +0530365}
366
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000367static unsigned long exynos5_get_periph_rate(int peripheral)
368{
Akshay Saraswat3ad7ffc2015-02-04 15:59:59 +0530369 struct clk_bit_info *bit_info = get_clk_bit_info(peripheral);
Akshay Saraswate81cb882015-02-04 16:00:05 +0530370 unsigned long sclk = 0;
371 unsigned int src = 0, div = 0, sub_div = 0;
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000372 struct exynos5_clock *clk =
373 (struct exynos5_clock *)samsung_get_base_clock();
374
375 switch (peripheral) {
376 case PERIPH_ID_UART0:
377 case PERIPH_ID_UART1:
378 case PERIPH_ID_UART2:
379 case PERIPH_ID_UART3:
380 src = readl(&clk->src_peric0);
381 div = readl(&clk->div_peric0);
382 break;
383 case PERIPH_ID_PWM0:
384 case PERIPH_ID_PWM1:
385 case PERIPH_ID_PWM2:
386 case PERIPH_ID_PWM3:
387 case PERIPH_ID_PWM4:
388 src = readl(&clk->src_peric0);
389 div = readl(&clk->div_peric3);
390 break;
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +0530391 case PERIPH_ID_I2S0:
392 src = readl(&clk->src_mau);
Akshay Saraswate81cb882015-02-04 16:00:05 +0530393 div = sub_div = readl(&clk->div_mau);
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000394 case PERIPH_ID_SPI0:
395 case PERIPH_ID_SPI1:
396 src = readl(&clk->src_peric1);
Akshay Saraswate81cb882015-02-04 16:00:05 +0530397 div = sub_div = readl(&clk->div_peric1);
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000398 break;
399 case PERIPH_ID_SPI2:
400 src = readl(&clk->src_peric1);
Akshay Saraswate81cb882015-02-04 16:00:05 +0530401 div = sub_div = readl(&clk->div_peric2);
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000402 break;
403 case PERIPH_ID_SPI3:
404 case PERIPH_ID_SPI4:
405 src = readl(&clk->sclk_src_isp);
Akshay Saraswate81cb882015-02-04 16:00:05 +0530406 div = sub_div = readl(&clk->sclk_div_isp);
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000407 break;
408 case PERIPH_ID_SDMMC0:
409 case PERIPH_ID_SDMMC1:
Akshay Saraswatbad6a982015-02-04 16:00:02 +0530410 src = readl(&clk->src_fsys);
Akshay Saraswate81cb882015-02-04 16:00:05 +0530411 div = sub_div = readl(&clk->div_fsys1);
Akshay Saraswatbad6a982015-02-04 16:00:02 +0530412 break;
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000413 case PERIPH_ID_SDMMC2:
414 case PERIPH_ID_SDMMC3:
415 src = readl(&clk->src_fsys);
Akshay Saraswate81cb882015-02-04 16:00:05 +0530416 div = sub_div = readl(&clk->div_fsys2);
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000417 break;
418 case PERIPH_ID_I2C0:
419 case PERIPH_ID_I2C1:
420 case PERIPH_ID_I2C2:
421 case PERIPH_ID_I2C3:
422 case PERIPH_ID_I2C4:
423 case PERIPH_ID_I2C5:
424 case PERIPH_ID_I2C6:
425 case PERIPH_ID_I2C7:
Akshay Saraswate81cb882015-02-04 16:00:05 +0530426 src = EXYNOS_SRC_MPLL;
Guillaume GARDETf87f8ee2015-03-11 10:34:27 +0100427 div = readl(&clk->div_top1);
428 sub_div = readl(&clk->div_top0);
Akshay Saraswate81cb882015-02-04 16:00:05 +0530429 break;
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000430 default:
431 debug("%s: invalid peripheral %d", __func__, peripheral);
432 return -1;
433 };
434
Akshay Saraswatbad6a982015-02-04 16:00:02 +0530435 if (bit_info->src_bit >= 0)
Akshay Saraswatd932c362015-02-04 16:00:04 +0530436 src = (src >> bit_info->src_bit) & bit_info->src_mask;
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000437
438 switch (src) {
439 case EXYNOS_SRC_MPLL:
440 sclk = exynos5_get_pll_clk(MPLL);
441 break;
442 case EXYNOS_SRC_EPLL:
443 sclk = exynos5_get_pll_clk(EPLL);
444 break;
445 case EXYNOS_SRC_VPLL:
446 sclk = exynos5_get_pll_clk(VPLL);
447 break;
448 default:
Akshay Saraswate81cb882015-02-04 16:00:05 +0530449 debug("%s: EXYNOS_SRC %d not supported\n", __func__, src);
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000450 return 0;
451 }
452
Akshay Saraswate81cb882015-02-04 16:00:05 +0530453 /* Clock divider ratio for this peripheral */
454 if (bit_info->div_bit >= 0)
455 div = (div >> bit_info->div_bit) & bit_info->div_mask;
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000456
Akshay Saraswate81cb882015-02-04 16:00:05 +0530457 /* Clock pre-divider ratio for this peripheral */
458 if (bit_info->prediv_bit >= 0)
459 sub_div = (sub_div >> bit_info->prediv_bit)
460 & bit_info->prediv_mask;
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000461
Akshay Saraswate81cb882015-02-04 16:00:05 +0530462 /* Calculate and return required clock rate */
463 return (sclk / (div + 1)) / (sub_div + 1);
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000464}
465
Akshay Saraswatd5072262015-02-04 16:00:01 +0530466static unsigned long exynos542x_get_periph_rate(int peripheral)
467{
468 struct clk_bit_info *bit_info = get_clk_bit_info(peripheral);
Akshay Saraswate81cb882015-02-04 16:00:05 +0530469 unsigned long sclk = 0;
470 unsigned int src = 0, div = 0, sub_div = 0;
Akshay Saraswatd5072262015-02-04 16:00:01 +0530471 struct exynos5420_clock *clk =
472 (struct exynos5420_clock *)samsung_get_base_clock();
473
474 switch (peripheral) {
475 case PERIPH_ID_UART0:
476 case PERIPH_ID_UART1:
477 case PERIPH_ID_UART2:
478 case PERIPH_ID_UART3:
479 case PERIPH_ID_PWM0:
480 case PERIPH_ID_PWM1:
481 case PERIPH_ID_PWM2:
482 case PERIPH_ID_PWM3:
483 case PERIPH_ID_PWM4:
484 src = readl(&clk->src_peric0);
485 div = readl(&clk->div_peric0);
486 break;
487 case PERIPH_ID_SPI0:
488 case PERIPH_ID_SPI1:
489 case PERIPH_ID_SPI2:
490 src = readl(&clk->src_peric1);
491 div = readl(&clk->div_peric1);
492 sub_div = readl(&clk->div_peric4);
493 break;
494 case PERIPH_ID_SPI3:
495 case PERIPH_ID_SPI4:
496 src = readl(&clk->src_isp);
497 div = readl(&clk->div_isp1);
498 sub_div = readl(&clk->div_isp1);
499 break;
500 case PERIPH_ID_SDMMC0:
501 case PERIPH_ID_SDMMC1:
502 case PERIPH_ID_SDMMC2:
503 case PERIPH_ID_SDMMC3:
504 src = readl(&clk->src_fsys);
505 div = readl(&clk->div_fsys1);
506 break;
507 case PERIPH_ID_I2C0:
508 case PERIPH_ID_I2C1:
509 case PERIPH_ID_I2C2:
510 case PERIPH_ID_I2C3:
511 case PERIPH_ID_I2C4:
512 case PERIPH_ID_I2C5:
513 case PERIPH_ID_I2C6:
514 case PERIPH_ID_I2C7:
515 case PERIPH_ID_I2C8:
516 case PERIPH_ID_I2C9:
517 case PERIPH_ID_I2C10:
Akshay Saraswate81cb882015-02-04 16:00:05 +0530518 src = EXYNOS542X_SRC_MPLL;
519 div = readl(&clk->div_top1);
520 break;
Akshay Saraswatd5072262015-02-04 16:00:01 +0530521 default:
522 debug("%s: invalid peripheral %d", __func__, peripheral);
523 return -1;
524 };
525
526 if (bit_info->src_bit >= 0)
Akshay Saraswatd932c362015-02-04 16:00:04 +0530527 src = (src >> bit_info->src_bit) & bit_info->src_mask;
Akshay Saraswatd5072262015-02-04 16:00:01 +0530528
529 switch (src) {
530 case EXYNOS542X_SRC_MPLL:
531 sclk = exynos542x_get_pll_clk(MPLL);
532 break;
533 case EXYNOS542X_SRC_SPLL:
534 sclk = exynos542x_get_pll_clk(SPLL);
535 break;
536 case EXYNOS542X_SRC_EPLL:
537 sclk = exynos542x_get_pll_clk(EPLL);
538 break;
539 case EXYNOS542X_SRC_RPLL:
540 sclk = exynos542x_get_pll_clk(RPLL);
541 break;
542 default:
Akshay Saraswate81cb882015-02-04 16:00:05 +0530543 debug("%s: EXYNOS542X_SRC %d not supported", __func__, src);
Akshay Saraswatd5072262015-02-04 16:00:01 +0530544 return 0;
545 }
546
Akshay Saraswate81cb882015-02-04 16:00:05 +0530547 /* Clock divider ratio for this peripheral */
548 if (bit_info->div_bit >= 0)
Akshay Saraswatd932c362015-02-04 16:00:04 +0530549 div = (div >> bit_info->div_bit) & bit_info->div_mask;
Akshay Saraswatd5072262015-02-04 16:00:01 +0530550
Akshay Saraswate81cb882015-02-04 16:00:05 +0530551 /* Clock pre-divider ratio for this peripheral */
552 if (bit_info->prediv_bit >= 0)
Akshay Saraswatd932c362015-02-04 16:00:04 +0530553 sub_div = (sub_div >> bit_info->prediv_bit)
Akshay Saraswate81cb882015-02-04 16:00:05 +0530554 & bit_info->prediv_mask;
Akshay Saraswatd5072262015-02-04 16:00:01 +0530555
Akshay Saraswate81cb882015-02-04 16:00:05 +0530556 /* Calculate and return required clock rate */
557 return (sclk / (div + 1)) / (sub_div + 1);
Akshay Saraswatd5072262015-02-04 16:00:01 +0530558}
559
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000560unsigned long clock_get_periph_rate(int peripheral)
561{
Akshay Saraswatd5072262015-02-04 16:00:01 +0530562 if (cpu_is_exynos5()) {
Simon Glass8d451b42018-12-10 10:37:40 -0700563 if (proid_is_exynos542x())
Akshay Saraswatd5072262015-02-04 16:00:01 +0530564 return exynos542x_get_periph_rate(peripheral);
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000565 return exynos5_get_periph_rate(peripheral);
Akshay Saraswatd5072262015-02-04 16:00:01 +0530566 } else {
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000567 return 0;
Akshay Saraswatd5072262015-02-04 16:00:01 +0530568 }
Padmavathi Venna37feb7b2013-03-28 04:32:21 +0000569}
570
Chander Kashyap4131a772011-12-06 23:34:12 +0000571/* exynos4: return ARM clock frequency */
572static unsigned long exynos4_get_arm_clk(void)
Minkyu Kangb1b24682011-01-24 15:22:23 +0900573{
Chander Kashyap4131a772011-12-06 23:34:12 +0000574 struct exynos4_clock *clk =
575 (struct exynos4_clock *)samsung_get_base_clock();
Minkyu Kangb1b24682011-01-24 15:22:23 +0900576 unsigned long div;
Chander Kashyap3c7721f2011-12-18 22:56:44 +0000577 unsigned long armclk;
578 unsigned int core_ratio;
579 unsigned int core2_ratio;
Minkyu Kangb1b24682011-01-24 15:22:23 +0900580
581 div = readl(&clk->div_cpu0);
582
Chander Kashyap3c7721f2011-12-18 22:56:44 +0000583 /* CORE_RATIO: [2:0], CORE2_RATIO: [30:28] */
584 core_ratio = (div >> 0) & 0x7;
585 core2_ratio = (div >> 28) & 0x7;
Minkyu Kangb1b24682011-01-24 15:22:23 +0900586
Chander Kashyap3c7721f2011-12-18 22:56:44 +0000587 armclk = get_pll_clk(APLL) / (core_ratio + 1);
588 armclk /= (core2_ratio + 1);
Minkyu Kangb1b24682011-01-24 15:22:23 +0900589
Chander Kashyap3c7721f2011-12-18 22:56:44 +0000590 return armclk;
Minkyu Kangb1b24682011-01-24 15:22:23 +0900591}
592
Chander Kashyap400ab162012-10-07 01:43:17 +0000593/* exynos4x12: return ARM clock frequency */
594static unsigned long exynos4x12_get_arm_clk(void)
595{
596 struct exynos4x12_clock *clk =
597 (struct exynos4x12_clock *)samsung_get_base_clock();
598 unsigned long div;
599 unsigned long armclk;
600 unsigned int core_ratio;
601 unsigned int core2_ratio;
602
603 div = readl(&clk->div_cpu0);
604
605 /* CORE_RATIO: [2:0], CORE2_RATIO: [30:28] */
606 core_ratio = (div >> 0) & 0x7;
607 core2_ratio = (div >> 28) & 0x7;
608
609 armclk = get_pll_clk(APLL) / (core_ratio + 1);
610 armclk /= (core2_ratio + 1);
611
612 return armclk;
613}
614
Chander Kashyap34076a02012-02-05 23:01:46 +0000615/* exynos5: return ARM clock frequency */
616static unsigned long exynos5_get_arm_clk(void)
617{
618 struct exynos5_clock *clk =
619 (struct exynos5_clock *)samsung_get_base_clock();
620 unsigned long div;
621 unsigned long armclk;
622 unsigned int arm_ratio;
623 unsigned int arm2_ratio;
624
625 div = readl(&clk->div_cpu0);
626
627 /* ARM_RATIO: [2:0], ARM2_RATIO: [30:28] */
628 arm_ratio = (div >> 0) & 0x7;
629 arm2_ratio = (div >> 28) & 0x7;
630
631 armclk = get_pll_clk(APLL) / (arm_ratio + 1);
632 armclk /= (arm2_ratio + 1);
633
634 return armclk;
635}
636
Chander Kashyap4131a772011-12-06 23:34:12 +0000637/* exynos4: return pwm clock frequency */
638static unsigned long exynos4_get_pwm_clk(void)
Minkyu Kangb1b24682011-01-24 15:22:23 +0900639{
Chander Kashyap4131a772011-12-06 23:34:12 +0000640 struct exynos4_clock *clk =
641 (struct exynos4_clock *)samsung_get_base_clock();
Minkyu Kangb1b24682011-01-24 15:22:23 +0900642 unsigned long pclk, sclk;
643 unsigned int sel;
644 unsigned int ratio;
645
Minkyu Kang69b28242011-05-18 16:57:55 +0900646 if (s5p_get_cpu_rev() == 0) {
647 /*
648 * CLK_SRC_PERIL0
649 * PWM_SEL [27:24]
650 */
651 sel = readl(&clk->src_peril0);
652 sel = (sel >> 24) & 0xf;
Minkyu Kangb1b24682011-01-24 15:22:23 +0900653
Minkyu Kang69b28242011-05-18 16:57:55 +0900654 if (sel == 0x6)
655 sclk = get_pll_clk(MPLL);
656 else if (sel == 0x7)
657 sclk = get_pll_clk(EPLL);
658 else if (sel == 0x8)
659 sclk = get_pll_clk(VPLL);
660 else
661 return 0;
662
663 /*
664 * CLK_DIV_PERIL3
665 * PWM_RATIO [3:0]
666 */
667 ratio = readl(&clk->div_peril3);
668 ratio = ratio & 0xf;
669 } else if (s5p_get_cpu_rev() == 1) {
Minkyu Kangb1b24682011-01-24 15:22:23 +0900670 sclk = get_pll_clk(MPLL);
Minkyu Kang69b28242011-05-18 16:57:55 +0900671 ratio = 8;
672 } else
Minkyu Kangb1b24682011-01-24 15:22:23 +0900673 return 0;
674
Minkyu Kangb1b24682011-01-24 15:22:23 +0900675 pclk = sclk / (ratio + 1);
676
677 return pclk;
678}
679
Chander Kashyap400ab162012-10-07 01:43:17 +0000680/* exynos4x12: return pwm clock frequency */
681static unsigned long exynos4x12_get_pwm_clk(void)
682{
683 unsigned long pclk, sclk;
684 unsigned int ratio;
685
686 sclk = get_pll_clk(MPLL);
687 ratio = 8;
688
689 pclk = sclk / (ratio + 1);
690
691 return pclk;
692}
693
Chander Kashyap4131a772011-12-06 23:34:12 +0000694/* exynos4: return uart clock frequency */
695static unsigned long exynos4_get_uart_clk(int dev_index)
Minkyu Kangb1b24682011-01-24 15:22:23 +0900696{
Chander Kashyap4131a772011-12-06 23:34:12 +0000697 struct exynos4_clock *clk =
698 (struct exynos4_clock *)samsung_get_base_clock();
Minkyu Kangb1b24682011-01-24 15:22:23 +0900699 unsigned long uclk, sclk;
700 unsigned int sel;
701 unsigned int ratio;
702
703 /*
704 * CLK_SRC_PERIL0
705 * UART0_SEL [3:0]
706 * UART1_SEL [7:4]
707 * UART2_SEL [8:11]
708 * UART3_SEL [12:15]
709 * UART4_SEL [16:19]
710 * UART5_SEL [23:20]
711 */
712 sel = readl(&clk->src_peril0);
713 sel = (sel >> (dev_index << 2)) & 0xf;
714
715 if (sel == 0x6)
716 sclk = get_pll_clk(MPLL);
717 else if (sel == 0x7)
718 sclk = get_pll_clk(EPLL);
719 else if (sel == 0x8)
720 sclk = get_pll_clk(VPLL);
721 else
722 return 0;
723
724 /*
725 * CLK_DIV_PERIL0
726 * UART0_RATIO [3:0]
727 * UART1_RATIO [7:4]
728 * UART2_RATIO [8:11]
729 * UART3_RATIO [12:15]
730 * UART4_RATIO [16:19]
731 * UART5_RATIO [23:20]
732 */
733 ratio = readl(&clk->div_peril0);
734 ratio = (ratio >> (dev_index << 2)) & 0xf;
735
736 uclk = sclk / (ratio + 1);
737
738 return uclk;
739}
740
Chander Kashyap400ab162012-10-07 01:43:17 +0000741/* exynos4x12: return uart clock frequency */
742static unsigned long exynos4x12_get_uart_clk(int dev_index)
743{
744 struct exynos4x12_clock *clk =
745 (struct exynos4x12_clock *)samsung_get_base_clock();
746 unsigned long uclk, sclk;
747 unsigned int sel;
748 unsigned int ratio;
749
750 /*
751 * CLK_SRC_PERIL0
752 * UART0_SEL [3:0]
753 * UART1_SEL [7:4]
754 * UART2_SEL [8:11]
755 * UART3_SEL [12:15]
756 * UART4_SEL [16:19]
757 */
758 sel = readl(&clk->src_peril0);
759 sel = (sel >> (dev_index << 2)) & 0xf;
760
761 if (sel == 0x6)
762 sclk = get_pll_clk(MPLL);
763 else if (sel == 0x7)
764 sclk = get_pll_clk(EPLL);
765 else if (sel == 0x8)
766 sclk = get_pll_clk(VPLL);
767 else
768 return 0;
769
770 /*
771 * CLK_DIV_PERIL0
772 * UART0_RATIO [3:0]
773 * UART1_RATIO [7:4]
774 * UART2_RATIO [8:11]
775 * UART3_RATIO [12:15]
776 * UART4_RATIO [16:19]
777 */
778 ratio = readl(&clk->div_peril0);
779 ratio = (ratio >> (dev_index << 2)) & 0xf;
780
781 uclk = sclk / (ratio + 1);
782
783 return uclk;
784}
785
Jaehoon Chung8788e062012-12-27 22:30:32 +0000786static unsigned long exynos4_get_mmc_clk(int dev_index)
787{
788 struct exynos4_clock *clk =
789 (struct exynos4_clock *)samsung_get_base_clock();
790 unsigned long uclk, sclk;
791 unsigned int sel, ratio, pre_ratio;
Amare1df6282013-04-27 11:42:56 +0530792 int shift = 0;
Jaehoon Chung8788e062012-12-27 22:30:32 +0000793
794 sel = readl(&clk->src_fsys);
795 sel = (sel >> (dev_index << 2)) & 0xf;
796
797 if (sel == 0x6)
798 sclk = get_pll_clk(MPLL);
799 else if (sel == 0x7)
800 sclk = get_pll_clk(EPLL);
801 else if (sel == 0x8)
802 sclk = get_pll_clk(VPLL);
803 else
804 return 0;
805
806 switch (dev_index) {
807 case 0:
808 case 1:
809 ratio = readl(&clk->div_fsys1);
810 pre_ratio = readl(&clk->div_fsys1);
811 break;
812 case 2:
813 case 3:
814 ratio = readl(&clk->div_fsys2);
815 pre_ratio = readl(&clk->div_fsys2);
816 break;
817 case 4:
818 ratio = readl(&clk->div_fsys3);
819 pre_ratio = readl(&clk->div_fsys3);
820 break;
821 default:
822 return 0;
823 }
824
825 if (dev_index == 1 || dev_index == 3)
826 shift = 16;
827
828 ratio = (ratio >> shift) & 0xf;
829 pre_ratio = (pre_ratio >> (shift + 8)) & 0xff;
830 uclk = (sclk / (ratio + 1)) / (pre_ratio + 1);
831
832 return uclk;
833}
834
Chander Kashyap4131a772011-12-06 23:34:12 +0000835/* exynos4: set the mmc clock */
836static void exynos4_set_mmc_clk(int dev_index, unsigned int div)
Jaehoon Chung9a772212011-05-17 21:19:17 +0000837{
Chander Kashyap4131a772011-12-06 23:34:12 +0000838 struct exynos4_clock *clk =
839 (struct exynos4_clock *)samsung_get_base_clock();
Jaehoon Chungd2c83242014-05-16 13:59:50 +0900840 unsigned int addr, clear_bit, set_bit;
Jaehoon Chung9a772212011-05-17 21:19:17 +0000841
842 /*
843 * CLK_DIV_FSYS1
844 * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24]
845 * CLK_DIV_FSYS2
846 * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24]
Jaehoon Chung29fe8c52012-12-27 22:30:33 +0000847 * CLK_DIV_FSYS3
Jaehoon Chungd2c83242014-05-16 13:59:50 +0900848 * MMC4_RATIO [3:0]
Jaehoon Chung9a772212011-05-17 21:19:17 +0000849 */
850 if (dev_index < 2) {
851 addr = (unsigned int)&clk->div_fsys1;
Jaehoon Chungd2c83242014-05-16 13:59:50 +0900852 clear_bit = MASK_PRE_RATIO(dev_index);
853 set_bit = SET_PRE_RATIO(dev_index, div);
854 } else if (dev_index == 4) {
Jaehoon Chung29fe8c52012-12-27 22:30:33 +0000855 addr = (unsigned int)&clk->div_fsys3;
856 dev_index -= 4;
Jaehoon Chungd2c83242014-05-16 13:59:50 +0900857 /* MMC4 is controlled with the MMC4_RATIO value */
858 clear_bit = MASK_RATIO(dev_index);
859 set_bit = SET_RATIO(dev_index, div);
Jaehoon Chung9a772212011-05-17 21:19:17 +0000860 } else {
861 addr = (unsigned int)&clk->div_fsys2;
862 dev_index -= 2;
Jaehoon Chungd2c83242014-05-16 13:59:50 +0900863 clear_bit = MASK_PRE_RATIO(dev_index);
864 set_bit = SET_PRE_RATIO(dev_index, div);
Jaehoon Chung9a772212011-05-17 21:19:17 +0000865 }
866
Jaehoon Chungd2c83242014-05-16 13:59:50 +0900867 clrsetbits_le32(addr, clear_bit, set_bit);
Jaehoon Chung9a772212011-05-17 21:19:17 +0000868}
869
Chander Kashyap34076a02012-02-05 23:01:46 +0000870/* exynos5: set the mmc clock */
871static void exynos5_set_mmc_clk(int dev_index, unsigned int div)
872{
873 struct exynos5_clock *clk =
874 (struct exynos5_clock *)samsung_get_base_clock();
875 unsigned int addr;
Chander Kashyap34076a02012-02-05 23:01:46 +0000876
877 /*
878 * CLK_DIV_FSYS1
879 * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24]
880 * CLK_DIV_FSYS2
881 * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24]
882 */
883 if (dev_index < 2) {
884 addr = (unsigned int)&clk->div_fsys1;
885 } else {
886 addr = (unsigned int)&clk->div_fsys2;
887 dev_index -= 2;
888 }
889
Inha Song4e558532014-02-06 14:20:12 +0900890 clrsetbits_le32(addr, 0xff << ((dev_index << 4) + 8),
891 (div & 0xff) << ((dev_index << 4) + 8));
Chander Kashyap34076a02012-02-05 23:01:46 +0000892}
893
Rajeshwari Birjeac892d02013-12-26 09:44:21 +0530894/* exynos5: set the mmc clock */
895static void exynos5420_set_mmc_clk(int dev_index, unsigned int div)
896{
897 struct exynos5420_clock *clk =
898 (struct exynos5420_clock *)samsung_get_base_clock();
899 unsigned int addr;
Inha Song4e558532014-02-06 14:20:12 +0900900 unsigned int shift;
Rajeshwari Birjeac892d02013-12-26 09:44:21 +0530901
902 /*
903 * CLK_DIV_FSYS1
904 * MMC0_RATIO [9:0]
905 * MMC1_RATIO [19:10]
906 * MMC2_RATIO [29:20]
907 */
908 addr = (unsigned int)&clk->div_fsys1;
909 shift = dev_index * 10;
910
Inha Song4e558532014-02-06 14:20:12 +0900911 clrsetbits_le32(addr, 0x3ff << shift, (div & 0x3ff) << shift);
Rajeshwari Birjeac892d02013-12-26 09:44:21 +0530912}
913
Donghwa Lee77ba1912012-04-05 19:36:12 +0000914/* get_lcd_clk: return lcd clock frequency */
915static unsigned long exynos4_get_lcd_clk(void)
916{
917 struct exynos4_clock *clk =
918 (struct exynos4_clock *)samsung_get_base_clock();
919 unsigned long pclk, sclk;
920 unsigned int sel;
921 unsigned int ratio;
922
923 /*
924 * CLK_SRC_LCD0
925 * FIMD0_SEL [3:0]
926 */
927 sel = readl(&clk->src_lcd0);
928 sel = sel & 0xf;
929
930 /*
931 * 0x6: SCLK_MPLL
932 * 0x7: SCLK_EPLL
933 * 0x8: SCLK_VPLL
934 */
935 if (sel == 0x6)
936 sclk = get_pll_clk(MPLL);
937 else if (sel == 0x7)
938 sclk = get_pll_clk(EPLL);
939 else if (sel == 0x8)
940 sclk = get_pll_clk(VPLL);
941 else
942 return 0;
943
944 /*
945 * CLK_DIV_LCD0
946 * FIMD0_RATIO [3:0]
947 */
948 ratio = readl(&clk->div_lcd0);
949 ratio = ratio & 0xf;
950
951 pclk = sclk / (ratio + 1);
952
953 return pclk;
954}
955
Donghwa Lee3c9d4532012-07-02 01:15:49 +0000956/* get_lcd_clk: return lcd clock frequency */
957static unsigned long exynos5_get_lcd_clk(void)
958{
959 struct exynos5_clock *clk =
960 (struct exynos5_clock *)samsung_get_base_clock();
961 unsigned long pclk, sclk;
962 unsigned int sel;
963 unsigned int ratio;
964
965 /*
966 * CLK_SRC_LCD0
967 * FIMD0_SEL [3:0]
968 */
969 sel = readl(&clk->src_disp1_0);
970 sel = sel & 0xf;
971
972 /*
973 * 0x6: SCLK_MPLL
974 * 0x7: SCLK_EPLL
975 * 0x8: SCLK_VPLL
976 */
977 if (sel == 0x6)
978 sclk = get_pll_clk(MPLL);
979 else if (sel == 0x7)
980 sclk = get_pll_clk(EPLL);
981 else if (sel == 0x8)
982 sclk = get_pll_clk(VPLL);
983 else
984 return 0;
985
986 /*
987 * CLK_DIV_LCD0
988 * FIMD0_RATIO [3:0]
989 */
990 ratio = readl(&clk->div_disp1_0);
991 ratio = ratio & 0xf;
992
993 pclk = sclk / (ratio + 1);
994
995 return pclk;
996}
997
Ajay Kumar914af872014-09-05 16:53:32 +0530998static unsigned long exynos5420_get_lcd_clk(void)
999{
1000 struct exynos5420_clock *clk =
1001 (struct exynos5420_clock *)samsung_get_base_clock();
1002 unsigned long pclk, sclk;
1003 unsigned int sel;
1004 unsigned int ratio;
1005
1006 /*
1007 * CLK_SRC_DISP10
1008 * FIMD1_SEL [4]
1009 * 0: SCLK_RPLL
1010 * 1: SCLK_SPLL
1011 */
1012 sel = readl(&clk->src_disp10);
1013 sel &= (1 << 4);
1014
1015 if (sel)
1016 sclk = get_pll_clk(SPLL);
1017 else
1018 sclk = get_pll_clk(RPLL);
1019
1020 /*
1021 * CLK_DIV_DISP10
1022 * FIMD1_RATIO [3:0]
1023 */
1024 ratio = readl(&clk->div_disp10);
1025 ratio = ratio & 0xf;
1026
1027 pclk = sclk / (ratio + 1);
1028
1029 return pclk;
1030}
1031
Ajay Kumarf0df9582015-03-04 19:05:24 +05301032static unsigned long exynos5800_get_lcd_clk(void)
1033{
1034 struct exynos5420_clock *clk =
1035 (struct exynos5420_clock *)samsung_get_base_clock();
1036 unsigned long sclk;
1037 unsigned int sel;
1038 unsigned int ratio;
1039
1040 /*
1041 * CLK_SRC_DISP10
1042 * CLKMUX_FIMD1 [6:4]
1043 */
1044 sel = (readl(&clk->src_disp10) >> 4) & 0x7;
1045
1046 if (sel) {
1047 /*
1048 * Mapping of CLK_SRC_DISP10 CLKMUX_FIMD1 [6:4] values into
1049 * PLLs. The first element is a placeholder to bypass the
1050 * default settig.
1051 */
1052 const int reg_map[] = {0, CPLL, DPLL, MPLL, SPLL, IPLL, EPLL,
1053 RPLL};
1054 sclk = get_pll_clk(reg_map[sel]);
1055 } else
Tom Rini8c70baa2021-12-14 13:36:40 -05001056 sclk = get_board_sys_clk();
Ajay Kumarf0df9582015-03-04 19:05:24 +05301057 /*
1058 * CLK_DIV_DISP10
1059 * FIMD1_RATIO [3:0]
1060 */
1061 ratio = readl(&clk->div_disp10) & 0xf;
1062
1063 return sclk / (ratio + 1);
1064}
1065
Donghwa Lee77ba1912012-04-05 19:36:12 +00001066void exynos4_set_lcd_clk(void)
1067{
1068 struct exynos4_clock *clk =
1069 (struct exynos4_clock *)samsung_get_base_clock();
Donghwa Lee77ba1912012-04-05 19:36:12 +00001070
1071 /*
1072 * CLK_GATE_BLOCK
1073 * CLK_CAM [0]
1074 * CLK_TV [1]
1075 * CLK_MFC [2]
1076 * CLK_G3D [3]
1077 * CLK_LCD0 [4]
1078 * CLK_LCD1 [5]
1079 * CLK_GPS [7]
1080 */
Inha Song4e558532014-02-06 14:20:12 +09001081 setbits_le32(&clk->gate_block, 1 << 4);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001082
1083 /*
1084 * CLK_SRC_LCD0
1085 * FIMD0_SEL [3:0]
1086 * MDNIE0_SEL [7:4]
1087 * MDNIE_PWM0_SEL [8:11]
1088 * MIPI0_SEL [12:15]
1089 * set lcd0 src clock 0x6: SCLK_MPLL
1090 */
Inha Song4e558532014-02-06 14:20:12 +09001091 clrsetbits_le32(&clk->src_lcd0, 0xf, 0x6);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001092
1093 /*
1094 * CLK_GATE_IP_LCD0
1095 * CLK_FIMD0 [0]
1096 * CLK_MIE0 [1]
1097 * CLK_MDNIE0 [2]
1098 * CLK_DSIM0 [3]
1099 * CLK_SMMUFIMD0 [4]
1100 * CLK_PPMULCD0 [5]
1101 * Gating all clocks for FIMD0
1102 */
Inha Song4e558532014-02-06 14:20:12 +09001103 setbits_le32(&clk->gate_ip_lcd0, 1 << 0);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001104
1105 /*
1106 * CLK_DIV_LCD0
1107 * FIMD0_RATIO [3:0]
1108 * MDNIE0_RATIO [7:4]
1109 * MDNIE_PWM0_RATIO [11:8]
1110 * MDNIE_PWM_PRE_RATIO [15:12]
1111 * MIPI0_RATIO [19:16]
1112 * MIPI0_PRE_RATIO [23:20]
1113 * set fimd ratio
1114 */
Inha Song4e558532014-02-06 14:20:12 +09001115 clrsetbits_le32(&clk->div_lcd0, 0xf, 0x1);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001116}
1117
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001118void exynos5_set_lcd_clk(void)
1119{
1120 struct exynos5_clock *clk =
1121 (struct exynos5_clock *)samsung_get_base_clock();
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001122
1123 /*
1124 * CLK_GATE_BLOCK
1125 * CLK_CAM [0]
1126 * CLK_TV [1]
1127 * CLK_MFC [2]
1128 * CLK_G3D [3]
1129 * CLK_LCD0 [4]
1130 * CLK_LCD1 [5]
1131 * CLK_GPS [7]
1132 */
Inha Song4e558532014-02-06 14:20:12 +09001133 setbits_le32(&clk->gate_block, 1 << 4);
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001134
1135 /*
1136 * CLK_SRC_LCD0
1137 * FIMD0_SEL [3:0]
1138 * MDNIE0_SEL [7:4]
1139 * MDNIE_PWM0_SEL [8:11]
1140 * MIPI0_SEL [12:15]
1141 * set lcd0 src clock 0x6: SCLK_MPLL
1142 */
Inha Song4e558532014-02-06 14:20:12 +09001143 clrsetbits_le32(&clk->src_disp1_0, 0xf, 0x6);
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001144
1145 /*
1146 * CLK_GATE_IP_LCD0
1147 * CLK_FIMD0 [0]
1148 * CLK_MIE0 [1]
1149 * CLK_MDNIE0 [2]
1150 * CLK_DSIM0 [3]
1151 * CLK_SMMUFIMD0 [4]
1152 * CLK_PPMULCD0 [5]
1153 * Gating all clocks for FIMD0
1154 */
Inha Song4e558532014-02-06 14:20:12 +09001155 setbits_le32(&clk->gate_ip_disp1, 1 << 0);
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001156
1157 /*
1158 * CLK_DIV_LCD0
1159 * FIMD0_RATIO [3:0]
1160 * MDNIE0_RATIO [7:4]
1161 * MDNIE_PWM0_RATIO [11:8]
1162 * MDNIE_PWM_PRE_RATIO [15:12]
1163 * MIPI0_RATIO [19:16]
1164 * MIPI0_PRE_RATIO [23:20]
1165 * set fimd ratio
1166 */
Inha Song4e558532014-02-06 14:20:12 +09001167 clrsetbits_le32(&clk->div_disp1_0, 0xf, 0x0);
Donghwa Lee3c9d4532012-07-02 01:15:49 +00001168}
1169
Ajay Kumar914af872014-09-05 16:53:32 +05301170void exynos5420_set_lcd_clk(void)
1171{
1172 struct exynos5420_clock *clk =
1173 (struct exynos5420_clock *)samsung_get_base_clock();
1174 unsigned int cfg;
1175
1176 /*
1177 * CLK_SRC_DISP10
1178 * FIMD1_SEL [4]
1179 * 0: SCLK_RPLL
1180 * 1: SCLK_SPLL
1181 */
1182 cfg = readl(&clk->src_disp10);
1183 cfg &= ~(0x1 << 4);
1184 cfg |= (0 << 4);
1185 writel(cfg, &clk->src_disp10);
1186
1187 /*
1188 * CLK_DIV_DISP10
1189 * FIMD1_RATIO [3:0]
1190 */
1191 cfg = readl(&clk->div_disp10);
1192 cfg &= ~(0xf << 0);
1193 cfg |= (0 << 0);
1194 writel(cfg, &clk->div_disp10);
1195}
1196
Ajay Kumarf0df9582015-03-04 19:05:24 +05301197void exynos5800_set_lcd_clk(void)
1198{
1199 struct exynos5420_clock *clk =
1200 (struct exynos5420_clock *)samsung_get_base_clock();
1201 unsigned int cfg;
1202
1203 /*
1204 * Use RPLL for pixel clock
1205 * CLK_SRC_DISP10 CLKMUX_FIMD1 [6:4]
1206 * ==================
1207 * 111: SCLK_RPLL
1208 */
1209 cfg = readl(&clk->src_disp10) | (0x7 << 4);
1210 writel(cfg, &clk->src_disp10);
1211
1212 /*
1213 * CLK_DIV_DISP10
1214 * FIMD1_RATIO [3:0]
1215 */
1216 clrsetbits_le32(&clk->div_disp10, 0xf << 0, 0x0 << 0);
1217}
1218
Donghwa Lee77ba1912012-04-05 19:36:12 +00001219void exynos4_set_mipi_clk(void)
1220{
1221 struct exynos4_clock *clk =
1222 (struct exynos4_clock *)samsung_get_base_clock();
Donghwa Lee77ba1912012-04-05 19:36:12 +00001223
1224 /*
1225 * CLK_SRC_LCD0
1226 * FIMD0_SEL [3:0]
1227 * MDNIE0_SEL [7:4]
1228 * MDNIE_PWM0_SEL [8:11]
1229 * MIPI0_SEL [12:15]
1230 * set mipi0 src clock 0x6: SCLK_MPLL
1231 */
Inha Song4e558532014-02-06 14:20:12 +09001232 clrsetbits_le32(&clk->src_lcd0, 0xf << 12, 0x6 << 12);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001233
1234 /*
1235 * CLK_SRC_MASK_LCD0
1236 * FIMD0_MASK [0]
1237 * MDNIE0_MASK [4]
1238 * MDNIE_PWM0_MASK [8]
1239 * MIPI0_MASK [12]
1240 * set src mask mipi0 0x1: Unmask
1241 */
Inha Song4e558532014-02-06 14:20:12 +09001242 setbits_le32(&clk->src_mask_lcd0, 0x1 << 12);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001243
1244 /*
1245 * CLK_GATE_IP_LCD0
1246 * CLK_FIMD0 [0]
1247 * CLK_MIE0 [1]
1248 * CLK_MDNIE0 [2]
1249 * CLK_DSIM0 [3]
1250 * CLK_SMMUFIMD0 [4]
1251 * CLK_PPMULCD0 [5]
1252 * Gating all clocks for MIPI0
1253 */
Inha Song4e558532014-02-06 14:20:12 +09001254 setbits_le32(&clk->gate_ip_lcd0, 1 << 3);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001255
1256 /*
1257 * CLK_DIV_LCD0
1258 * FIMD0_RATIO [3:0]
1259 * MDNIE0_RATIO [7:4]
1260 * MDNIE_PWM0_RATIO [11:8]
1261 * MDNIE_PWM_PRE_RATIO [15:12]
1262 * MIPI0_RATIO [19:16]
1263 * MIPI0_PRE_RATIO [23:20]
1264 * set mipi ratio
1265 */
Inha Song4e558532014-02-06 14:20:12 +09001266 clrsetbits_le32(&clk->div_lcd0, 0xf << 16, 0x1 << 16);
Donghwa Lee77ba1912012-04-05 19:36:12 +00001267}
1268
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001269int exynos5_set_epll_clk(unsigned long rate)
1270{
1271 unsigned int epll_con, epll_con_k;
1272 unsigned int i;
1273 unsigned int lockcnt;
1274 unsigned int start;
1275 struct exynos5_clock *clk =
1276 (struct exynos5_clock *)samsung_get_base_clock();
1277
1278 epll_con = readl(&clk->epll_con0);
1279 epll_con &= ~((EPLL_CON0_LOCK_DET_EN_MASK <<
1280 EPLL_CON0_LOCK_DET_EN_SHIFT) |
1281 EPLL_CON0_MDIV_MASK << EPLL_CON0_MDIV_SHIFT |
1282 EPLL_CON0_PDIV_MASK << EPLL_CON0_PDIV_SHIFT |
1283 EPLL_CON0_SDIV_MASK << EPLL_CON0_SDIV_SHIFT);
1284
1285 for (i = 0; i < ARRAY_SIZE(exynos5_epll_div); i++) {
1286 if (exynos5_epll_div[i].freq_out == rate)
1287 break;
1288 }
1289
1290 if (i == ARRAY_SIZE(exynos5_epll_div))
1291 return -1;
1292
1293 epll_con_k = exynos5_epll_div[i].k_dsm << 0;
1294 epll_con |= exynos5_epll_div[i].en_lock_det <<
1295 EPLL_CON0_LOCK_DET_EN_SHIFT;
1296 epll_con |= exynos5_epll_div[i].m_div << EPLL_CON0_MDIV_SHIFT;
1297 epll_con |= exynos5_epll_div[i].p_div << EPLL_CON0_PDIV_SHIFT;
1298 epll_con |= exynos5_epll_div[i].s_div << EPLL_CON0_SDIV_SHIFT;
1299
1300 /*
1301 * Required period ( in cycles) to genarate a stable clock output.
1302 * The maximum clock time can be up to 3000 * PDIV cycles of PLLs
1303 * frequency input (as per spec)
1304 */
1305 lockcnt = 3000 * exynos5_epll_div[i].p_div;
1306
1307 writel(lockcnt, &clk->epll_lock);
1308 writel(epll_con, &clk->epll_con0);
1309 writel(epll_con_k, &clk->epll_con1);
1310
1311 start = get_timer(0);
1312
1313 while (!(readl(&clk->epll_con0) &
1314 (0x1 << EXYNOS5_EPLLCON0_LOCKED_SHIFT))) {
1315 if (get_timer(start) > TIMEOUT_EPLL_LOCK) {
1316 debug("%s: Timeout waiting for EPLL lock\n", __func__);
1317 return -1;
1318 }
1319 }
1320 return 0;
1321}
1322
Simon Glass12d70f42018-12-10 10:37:41 -07001323static int exynos5420_set_i2s_clk_source(void)
1324{
1325 struct exynos5420_clock *clk =
1326 (struct exynos5420_clock *)samsung_get_base_clock();
1327
1328 setbits_le32(&clk->src_top6, EXYNOS5420_CLK_SRC_MOUT_EPLL);
1329 clrsetbits_le32(&clk->src_mau, EXYNOS5420_AUDIO0_SEL_MASK,
1330 (EXYNOS5420_CLK_SRC_SCLK_EPLL));
1331 setbits_le32(EXYNOS5_AUDIOSS_BASE, 1 << 0);
1332
1333 return 0;
1334}
1335
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301336int exynos5_set_i2s_clk_source(unsigned int i2s_id)
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001337{
1338 struct exynos5_clock *clk =
1339 (struct exynos5_clock *)samsung_get_base_clock();
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301340 unsigned int *audio_ass = (unsigned int *)samsung_get_base_audio_ass();
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001341
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301342 if (i2s_id == 0) {
1343 setbits_le32(&clk->src_top2, CLK_SRC_MOUT_EPLL);
1344 clrsetbits_le32(&clk->src_mau, AUDIO0_SEL_MASK,
1345 (CLK_SRC_SCLK_EPLL));
1346 setbits_le32(audio_ass, AUDIO_CLKMUX_ASS);
1347 } else if (i2s_id == 1) {
1348 clrsetbits_le32(&clk->src_peric1, AUDIO1_SEL_MASK,
1349 (CLK_SRC_SCLK_EPLL));
1350 } else {
1351 return -1;
1352 }
1353 return 0;
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001354}
1355
1356int exynos5_set_i2s_clk_prescaler(unsigned int src_frq,
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301357 unsigned int dst_frq,
1358 unsigned int i2s_id)
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001359{
1360 struct exynos5_clock *clk =
1361 (struct exynos5_clock *)samsung_get_base_clock();
1362 unsigned int div;
1363
1364 if ((dst_frq == 0) || (src_frq == 0)) {
1365 debug("%s: Invalid requency input for prescaler\n", __func__);
1366 debug("src frq = %d des frq = %d ", src_frq, dst_frq);
1367 return -1;
1368 }
1369
1370 div = (src_frq / dst_frq);
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301371 if (i2s_id == 0) {
1372 if (div > AUDIO_0_RATIO_MASK) {
1373 debug("%s: Frequency ratio is out of range\n",
1374 __func__);
1375 debug("src frq = %d des frq = %d ", src_frq, dst_frq);
1376 return -1;
1377 }
1378 clrsetbits_le32(&clk->div_mau, AUDIO_0_RATIO_MASK,
1379 (div & AUDIO_0_RATIO_MASK));
Minkyu Kang86253d42015-05-11 16:27:07 +09001380 } else if (i2s_id == 1) {
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301381 if (div > AUDIO_1_RATIO_MASK) {
1382 debug("%s: Frequency ratio is out of range\n",
1383 __func__);
1384 debug("src frq = %d des frq = %d ", src_frq, dst_frq);
1385 return -1;
1386 }
1387 clrsetbits_le32(&clk->div_peric4, AUDIO_1_RATIO_MASK,
1388 (div & AUDIO_1_RATIO_MASK));
1389 } else {
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001390 return -1;
1391 }
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001392 return 0;
1393}
1394
Hatim RVe6365b62012-11-02 01:15:34 +00001395/**
1396 * Linearly searches for the most accurate main and fine stage clock scalars
1397 * (divisors) for a specified target frequency and scalar bit sizes by checking
1398 * all multiples of main_scalar_bits values. Will always return scalars up to or
1399 * slower than target.
1400 *
1401 * @param main_scalar_bits Number of main scalar bits, must be > 0 and < 32
1402 * @param fine_scalar_bits Number of fine scalar bits, must be > 0 and < 32
1403 * @param input_freq Clock frequency to be scaled in Hz
1404 * @param target_freq Desired clock frequency in Hz
1405 * @param best_fine_scalar Pointer to store the fine stage divisor
1406 *
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +01001407 * Return: best_main_scalar Main scalar for desired frequency or -1 if none
Hatim RVe6365b62012-11-02 01:15:34 +00001408 * found
1409 */
1410static int clock_calc_best_scalar(unsigned int main_scaler_bits,
1411 unsigned int fine_scalar_bits, unsigned int input_rate,
1412 unsigned int target_rate, unsigned int *best_fine_scalar)
1413{
1414 int i;
1415 int best_main_scalar = -1;
1416 unsigned int best_error = target_rate;
1417 const unsigned int cap = (1 << fine_scalar_bits) - 1;
1418 const unsigned int loops = 1 << main_scaler_bits;
1419
1420 debug("Input Rate is %u, Target is %u, Cap is %u\n", input_rate,
1421 target_rate, cap);
1422
1423 assert(best_fine_scalar != NULL);
1424 assert(main_scaler_bits <= fine_scalar_bits);
1425
1426 *best_fine_scalar = 1;
1427
1428 if (input_rate == 0 || target_rate == 0)
1429 return -1;
1430
1431 if (target_rate >= input_rate)
1432 return 1;
1433
1434 for (i = 1; i <= loops; i++) {
Masahiro Yamadadb204642014-11-07 03:03:31 +09001435 const unsigned int effective_div =
1436 max(min(input_rate / i / target_rate, cap), 1U);
Hatim RVe6365b62012-11-02 01:15:34 +00001437 const unsigned int effective_rate = input_rate / i /
1438 effective_div;
1439 const int error = target_rate - effective_rate;
1440
1441 debug("%d|effdiv:%u, effrate:%u, error:%d\n", i, effective_div,
1442 effective_rate, error);
1443
1444 if (error >= 0 && error <= best_error) {
1445 best_error = error;
1446 best_main_scalar = i;
1447 *best_fine_scalar = effective_div;
1448 }
1449 }
1450
1451 return best_main_scalar;
1452}
1453
1454static int exynos5_set_spi_clk(enum periph_id periph_id,
1455 unsigned int rate)
1456{
1457 struct exynos5_clock *clk =
1458 (struct exynos5_clock *)samsung_get_base_clock();
1459 int main;
1460 unsigned int fine;
1461 unsigned shift, pre_shift;
1462 unsigned mask = 0xff;
1463 u32 *reg;
1464
1465 main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine);
1466 if (main < 0) {
1467 debug("%s: Cannot set clock rate for periph %d",
1468 __func__, periph_id);
1469 return -1;
1470 }
1471 main = main - 1;
1472 fine = fine - 1;
1473
1474 switch (periph_id) {
1475 case PERIPH_ID_SPI0:
1476 reg = &clk->div_peric1;
1477 shift = 0;
1478 pre_shift = 8;
1479 break;
1480 case PERIPH_ID_SPI1:
1481 reg = &clk->div_peric1;
1482 shift = 16;
1483 pre_shift = 24;
1484 break;
1485 case PERIPH_ID_SPI2:
1486 reg = &clk->div_peric2;
1487 shift = 0;
1488 pre_shift = 8;
1489 break;
1490 case PERIPH_ID_SPI3:
1491 reg = &clk->sclk_div_isp;
1492 shift = 0;
1493 pre_shift = 4;
1494 break;
1495 case PERIPH_ID_SPI4:
1496 reg = &clk->sclk_div_isp;
1497 shift = 12;
1498 pre_shift = 16;
1499 break;
1500 default:
1501 debug("%s: Unsupported peripheral ID %d\n", __func__,
1502 periph_id);
1503 return -1;
1504 }
1505 clrsetbits_le32(reg, mask << shift, (main & mask) << shift);
1506 clrsetbits_le32(reg, mask << pre_shift, (fine & mask) << pre_shift);
1507
1508 return 0;
1509}
1510
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301511static int exynos5420_set_spi_clk(enum periph_id periph_id,
1512 unsigned int rate)
1513{
1514 struct exynos5420_clock *clk =
1515 (struct exynos5420_clock *)samsung_get_base_clock();
1516 int main;
1517 unsigned int fine;
1518 unsigned shift, pre_shift;
1519 unsigned div_mask = 0xf, pre_div_mask = 0xff;
1520 u32 *reg;
1521 u32 *pre_reg;
1522
1523 main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine);
1524 if (main < 0) {
1525 debug("%s: Cannot set clock rate for periph %d",
1526 __func__, periph_id);
1527 return -1;
1528 }
1529 main = main - 1;
1530 fine = fine - 1;
1531
1532 switch (periph_id) {
1533 case PERIPH_ID_SPI0:
1534 reg = &clk->div_peric1;
1535 shift = 20;
1536 pre_reg = &clk->div_peric4;
1537 pre_shift = 8;
1538 break;
1539 case PERIPH_ID_SPI1:
1540 reg = &clk->div_peric1;
1541 shift = 24;
1542 pre_reg = &clk->div_peric4;
1543 pre_shift = 16;
1544 break;
1545 case PERIPH_ID_SPI2:
1546 reg = &clk->div_peric1;
1547 shift = 28;
1548 pre_reg = &clk->div_peric4;
1549 pre_shift = 24;
1550 break;
1551 case PERIPH_ID_SPI3:
1552 reg = &clk->div_isp1;
1553 shift = 16;
1554 pre_reg = &clk->div_isp1;
1555 pre_shift = 0;
1556 break;
1557 case PERIPH_ID_SPI4:
1558 reg = &clk->div_isp1;
1559 shift = 20;
1560 pre_reg = &clk->div_isp1;
1561 pre_shift = 8;
1562 break;
1563 default:
1564 debug("%s: Unsupported peripheral ID %d\n", __func__,
1565 periph_id);
1566 return -1;
1567 }
1568
1569 clrsetbits_le32(reg, div_mask << shift, (main & div_mask) << shift);
1570 clrsetbits_le32(pre_reg, pre_div_mask << pre_shift,
1571 (fine & pre_div_mask) << pre_shift);
1572
1573 return 0;
1574}
1575
Piotr Wilczek01d589f2012-11-20 02:19:02 +00001576static unsigned long exynos4_get_i2c_clk(void)
1577{
1578 struct exynos4_clock *clk =
1579 (struct exynos4_clock *)samsung_get_base_clock();
1580 unsigned long sclk, aclk_100;
1581 unsigned int ratio;
1582
1583 sclk = get_pll_clk(APLL);
1584
1585 ratio = (readl(&clk->div_top)) >> 4;
1586 ratio &= 0xf;
1587 aclk_100 = sclk / (ratio + 1);
1588 return aclk_100;
Rajeshwari Shinde1c9412a2012-07-23 21:23:48 +00001589}
1590
Minkyu Kangb1b24682011-01-24 15:22:23 +09001591unsigned long get_pll_clk(int pllreg)
1592{
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301593 if (cpu_is_exynos5()) {
Simon Glass8d451b42018-12-10 10:37:40 -07001594 if (proid_is_exynos542x())
Akshay Saraswat1bd40e42015-02-04 16:00:00 +05301595 return exynos542x_get_pll_clk(pllreg);
Chander Kashyap34076a02012-02-05 23:01:46 +00001596 return exynos5_get_pll_clk(pllreg);
Minkyu Kang86253d42015-05-11 16:27:07 +09001597 } else if (cpu_is_exynos4()) {
Chander Kashyap400ab162012-10-07 01:43:17 +00001598 if (proid_is_exynos4412())
1599 return exynos4x12_get_pll_clk(pllreg);
Chander Kashyap34076a02012-02-05 23:01:46 +00001600 return exynos4_get_pll_clk(pllreg);
Chander Kashyap400ab162012-10-07 01:43:17 +00001601 }
Minkyu Kang86253d42015-05-11 16:27:07 +09001602
1603 return 0;
Minkyu Kangb1b24682011-01-24 15:22:23 +09001604}
1605
1606unsigned long get_arm_clk(void)
1607{
Minkyu Kang86253d42015-05-11 16:27:07 +09001608 if (cpu_is_exynos5()) {
Chander Kashyap34076a02012-02-05 23:01:46 +00001609 return exynos5_get_arm_clk();
Minkyu Kang86253d42015-05-11 16:27:07 +09001610 } else if (cpu_is_exynos4()) {
Chander Kashyap400ab162012-10-07 01:43:17 +00001611 if (proid_is_exynos4412())
1612 return exynos4x12_get_arm_clk();
Chander Kashyap34076a02012-02-05 23:01:46 +00001613 return exynos4_get_arm_clk();
Chander Kashyap400ab162012-10-07 01:43:17 +00001614 }
Minkyu Kang86253d42015-05-11 16:27:07 +09001615
1616 return 0;
Minkyu Kangb1b24682011-01-24 15:22:23 +09001617}
1618
Rajeshwari Shinde1c9412a2012-07-23 21:23:48 +00001619unsigned long get_i2c_clk(void)
1620{
Minkyu Kang86253d42015-05-11 16:27:07 +09001621 if (cpu_is_exynos5())
Akshay Saraswat348bc5f2015-02-04 16:00:03 +05301622 return clock_get_periph_rate(PERIPH_ID_I2C0);
Minkyu Kang86253d42015-05-11 16:27:07 +09001623 else if (cpu_is_exynos4())
Piotr Wilczek01d589f2012-11-20 02:19:02 +00001624 return exynos4_get_i2c_clk();
Minkyu Kang86253d42015-05-11 16:27:07 +09001625
1626 return 0;
Rajeshwari Shinde1c9412a2012-07-23 21:23:48 +00001627}
1628
Minkyu Kangb1b24682011-01-24 15:22:23 +09001629unsigned long get_pwm_clk(void)
1630{
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301631 if (cpu_is_exynos5()) {
Padmavathi Vennabb714162013-03-28 04:32:23 +00001632 return clock_get_periph_rate(PERIPH_ID_PWM0);
Minkyu Kang86253d42015-05-11 16:27:07 +09001633 } else if (cpu_is_exynos4()) {
Chander Kashyap400ab162012-10-07 01:43:17 +00001634 if (proid_is_exynos4412())
1635 return exynos4x12_get_pwm_clk();
Chander Kashyap34076a02012-02-05 23:01:46 +00001636 return exynos4_get_pwm_clk();
Chander Kashyap400ab162012-10-07 01:43:17 +00001637 }
Minkyu Kang86253d42015-05-11 16:27:07 +09001638
1639 return 0;
Minkyu Kangb1b24682011-01-24 15:22:23 +09001640}
1641
1642unsigned long get_uart_clk(int dev_index)
1643{
Akshay Saraswat348bc5f2015-02-04 16:00:03 +05301644 enum periph_id id;
1645
1646 switch (dev_index) {
1647 case 0:
1648 id = PERIPH_ID_UART0;
1649 break;
1650 case 1:
1651 id = PERIPH_ID_UART1;
1652 break;
1653 case 2:
1654 id = PERIPH_ID_UART2;
1655 break;
1656 case 3:
1657 id = PERIPH_ID_UART3;
1658 break;
1659 default:
1660 debug("%s: invalid UART index %d", __func__, dev_index);
1661 return -1;
1662 }
1663
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301664 if (cpu_is_exynos5()) {
Akshay Saraswat348bc5f2015-02-04 16:00:03 +05301665 return clock_get_periph_rate(id);
Minkyu Kang86253d42015-05-11 16:27:07 +09001666 } else if (cpu_is_exynos4()) {
Chander Kashyap400ab162012-10-07 01:43:17 +00001667 if (proid_is_exynos4412())
1668 return exynos4x12_get_uart_clk(dev_index);
Chander Kashyap34076a02012-02-05 23:01:46 +00001669 return exynos4_get_uart_clk(dev_index);
Chander Kashyap400ab162012-10-07 01:43:17 +00001670 }
Minkyu Kang86253d42015-05-11 16:27:07 +09001671
1672 return 0;
Minkyu Kangb1b24682011-01-24 15:22:23 +09001673}
Jaehoon Chung9a772212011-05-17 21:19:17 +00001674
Jaehoon Chung8788e062012-12-27 22:30:32 +00001675unsigned long get_mmc_clk(int dev_index)
1676{
Akshay Saraswat348bc5f2015-02-04 16:00:03 +05301677 enum periph_id id;
1678
Przemyslaw Marczakccae0d42015-09-30 13:14:52 +02001679 if (cpu_is_exynos4())
1680 return exynos4_get_mmc_clk(dev_index);
1681
Akshay Saraswat348bc5f2015-02-04 16:00:03 +05301682 switch (dev_index) {
1683 case 0:
1684 id = PERIPH_ID_SDMMC0;
1685 break;
1686 case 1:
1687 id = PERIPH_ID_SDMMC1;
1688 break;
1689 case 2:
1690 id = PERIPH_ID_SDMMC2;
1691 break;
1692 case 3:
1693 id = PERIPH_ID_SDMMC3;
1694 break;
1695 default:
1696 debug("%s: invalid MMC index %d", __func__, dev_index);
1697 return -1;
1698 }
1699
Przemyslaw Marczakccae0d42015-09-30 13:14:52 +02001700 return clock_get_periph_rate(id);
Jaehoon Chung8788e062012-12-27 22:30:32 +00001701}
1702
Jaehoon Chung9a772212011-05-17 21:19:17 +00001703void set_mmc_clk(int dev_index, unsigned int div)
1704{
Jaehoon Chung15cd6b52015-01-08 16:50:21 +09001705 /* If want to set correct value, it needs to substract one from div.*/
1706 if (div > 0)
1707 div -= 1;
1708
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301709 if (cpu_is_exynos5()) {
Simon Glass8d451b42018-12-10 10:37:40 -07001710 if (proid_is_exynos542x())
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301711 exynos5420_set_mmc_clk(dev_index, div);
1712 else
1713 exynos5_set_mmc_clk(dev_index, div);
Minkyu Kang86253d42015-05-11 16:27:07 +09001714 } else if (cpu_is_exynos4()) {
Beomho Seo99660cc2014-05-16 13:59:47 +09001715 exynos4_set_mmc_clk(dev_index, div);
Chander Kashyap400ab162012-10-07 01:43:17 +00001716 }
Jaehoon Chung9a772212011-05-17 21:19:17 +00001717}
Donghwa Lee77ba1912012-04-05 19:36:12 +00001718
1719unsigned long get_lcd_clk(void)
1720{
Minkyu Kang86253d42015-05-11 16:27:07 +09001721 if (cpu_is_exynos4()) {
Donghwa Lee77ba1912012-04-05 19:36:12 +00001722 return exynos4_get_lcd_clk();
Minkyu Kang86253d42015-05-11 16:27:07 +09001723 } else if (cpu_is_exynos5()) {
Ajay Kumarf0df9582015-03-04 19:05:24 +05301724 if (proid_is_exynos5420())
Ajay Kumar914af872014-09-05 16:53:32 +05301725 return exynos5420_get_lcd_clk();
Przemyslaw Marczakcefbfe42015-10-27 13:07:57 +01001726 else if (proid_is_exynos5422())
Ajay Kumarf0df9582015-03-04 19:05:24 +05301727 return exynos5800_get_lcd_clk();
Ajay Kumar914af872014-09-05 16:53:32 +05301728 else
1729 return exynos5_get_lcd_clk();
1730 }
Minkyu Kang86253d42015-05-11 16:27:07 +09001731
1732 return 0;
Donghwa Lee77ba1912012-04-05 19:36:12 +00001733}
1734
1735void set_lcd_clk(void)
1736{
Minkyu Kang86253d42015-05-11 16:27:07 +09001737 if (cpu_is_exynos4()) {
Donghwa Lee77ba1912012-04-05 19:36:12 +00001738 exynos4_set_lcd_clk();
Minkyu Kang86253d42015-05-11 16:27:07 +09001739 } else if (cpu_is_exynos5()) {
Ajay Kumar914af872014-09-05 16:53:32 +05301740 if (proid_is_exynos5250())
1741 exynos5_set_lcd_clk();
Ajay Kumarf0df9582015-03-04 19:05:24 +05301742 else if (proid_is_exynos5420())
Ajay Kumar914af872014-09-05 16:53:32 +05301743 exynos5420_set_lcd_clk();
Ajay Kumarf0df9582015-03-04 19:05:24 +05301744 else
1745 exynos5800_set_lcd_clk();
Ajay Kumar914af872014-09-05 16:53:32 +05301746 }
Donghwa Lee77ba1912012-04-05 19:36:12 +00001747}
1748
1749void set_mipi_clk(void)
1750{
1751 if (cpu_is_exynos4())
1752 exynos4_set_mipi_clk();
1753}
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001754
Hatim RVe6365b62012-11-02 01:15:34 +00001755int set_spi_clk(int periph_id, unsigned int rate)
1756{
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301757 if (cpu_is_exynos5()) {
Simon Glass8d451b42018-12-10 10:37:40 -07001758 if (proid_is_exynos542x())
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301759 return exynos5420_set_spi_clk(periph_id, rate);
Hatim RVe6365b62012-11-02 01:15:34 +00001760 return exynos5_set_spi_clk(periph_id, rate);
Rajeshwari Birjeac892d02013-12-26 09:44:21 +05301761 }
Minkyu Kang86253d42015-05-11 16:27:07 +09001762
1763 return 0;
Hatim RVe6365b62012-11-02 01:15:34 +00001764}
1765
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301766int set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq,
1767 unsigned int i2s_id)
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001768{
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001769 if (cpu_is_exynos5())
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301770 return exynos5_set_i2s_clk_prescaler(src_frq, dst_frq, i2s_id);
Minkyu Kang86253d42015-05-11 16:27:07 +09001771
1772 return 0;
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001773}
1774
Dani Krishna Mohan65c7ee62013-09-11 16:38:48 +05301775int set_i2s_clk_source(unsigned int i2s_id)
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001776{
Simon Glass12d70f42018-12-10 10:37:41 -07001777 if (cpu_is_exynos5()) {
1778 if (proid_is_exynos542x())
1779 return exynos5420_set_i2s_clk_source();
1780 else
1781 return exynos5_set_i2s_clk_source(i2s_id);
1782 }
Minkyu Kang86253d42015-05-11 16:27:07 +09001783
1784 return 0;
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001785}
1786
1787int set_epll_clk(unsigned long rate)
1788{
1789 if (cpu_is_exynos5())
1790 return exynos5_set_epll_clk(rate);
Minkyu Kang86253d42015-05-11 16:27:07 +09001791
1792 return 0;
Rajeshwari Shinde392a73a2012-10-25 19:49:29 +00001793}