blob: 9809b2003edb680487b95185c1f7d751d20986a8 [file] [log] [blame]
Angel Pons1ddb8942020-04-04 18:51:26 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Gabe Black607c0b62013-05-16 05:45:57 -07002
Kyösti Mälkki13f66502019-03-03 08:01:05 +02003#include <device/mmio.h>
Julius Wernerfa938c72013-08-29 14:17:36 -07004#include <assert.h>
Julius Werner80af4422014-10-20 13:18:56 -07005#include <console/console.h>
6#include <soc/clk.h>
7#include <soc/periph.h>
Gabe Black713853a2013-07-31 22:48:20 -07008#include <timer.h>
Gabe Black607c0b62013-05-16 05:45:57 -07009
10/* input clock of PLL: SMDK5420 has 24MHz input clock */
Elyes HAOUAS251514d2019-01-23 11:36:44 +010011#define CONF_SYS_CLK_FREQ 24000000
Gabe Black607c0b62013-05-16 05:45:57 -070012
Martin Roth1fc2ba52014-12-07 14:59:11 -070013/* Epll Clock division values to achieve different frequency output */
Gabe Black607c0b62013-05-16 05:45:57 -070014static struct st_epll_con_val epll_div[] = {
15 { 192000000, 0, 48, 3, 1, 0 },
16 { 180000000, 0, 45, 3, 1, 0 },
17 { 73728000, 1, 73, 3, 3, 47710 },
18 { 67737600, 1, 90, 4, 3, 20762 },
19 { 49152000, 0, 49, 3, 3, 9961 },
20 { 45158400, 0, 45, 3, 3, 10381 },
21 { 180633600, 0, 45, 3, 1, 10381 }
22};
23
24/* exynos5: return pll clock frequency */
25unsigned long get_pll_clk(int pllreg)
26{
Gabe Black607c0b62013-05-16 05:45:57 -070027 unsigned long r, m, p, s, k = 0, mask, fout;
28 unsigned int freq;
29
30 switch (pllreg) {
31 case APLL:
Julius Werner2f37bd62015-02-19 14:51:15 -080032 r = read32(&exynos_clock->apll_con0);
Gabe Black607c0b62013-05-16 05:45:57 -070033 break;
Gabe Black607c0b62013-05-16 05:45:57 -070034 case MPLL:
Julius Werner2f37bd62015-02-19 14:51:15 -080035 r = read32(&exynos_clock->mpll_con0);
Gabe Black607c0b62013-05-16 05:45:57 -070036 break;
37 case EPLL:
Julius Werner2f37bd62015-02-19 14:51:15 -080038 r = read32(&exynos_clock->epll_con0);
39 k = read32(&exynos_clock->epll_con1);
Gabe Black607c0b62013-05-16 05:45:57 -070040 break;
41 case VPLL:
Julius Werner2f37bd62015-02-19 14:51:15 -080042 r = read32(&exynos_clock->vpll_con0);
43 k = read32(&exynos_clock->vpll_con1);
Gabe Black607c0b62013-05-16 05:45:57 -070044 break;
Gabe Black5420e092013-05-17 11:29:22 -070045 case BPLL:
Julius Werner2f37bd62015-02-19 14:51:15 -080046 r = read32(&exynos_clock->bpll_con0);
Gabe Black5420e092013-05-17 11:29:22 -070047 break;
48 case RPLL:
Julius Werner2f37bd62015-02-19 14:51:15 -080049 r = read32(&exynos_clock->rpll_con0);
50 k = read32(&exynos_clock->rpll_con1);
Gabe Black5420e092013-05-17 11:29:22 -070051 break;
52 case SPLL:
Julius Werner2f37bd62015-02-19 14:51:15 -080053 r = read32(&exynos_clock->spll_con0);
Gabe Black5420e092013-05-17 11:29:22 -070054 break;
David Hendricks5f6ffba2013-08-08 16:16:40 -070055 case CPLL:
Julius Werner2f37bd62015-02-19 14:51:15 -080056 r = read32(&exynos_clock->cpll_con0);
David Hendricks5f6ffba2013-08-08 16:16:40 -070057 break;
58 case DPLL:
Julius Werner2f37bd62015-02-19 14:51:15 -080059 r = read32(&exynos_clock->dpll_con0);
David Hendricks5f6ffba2013-08-08 16:16:40 -070060 break;
Gabe Black607c0b62013-05-16 05:45:57 -070061 default:
62 printk(BIOS_DEBUG, "Unsupported PLL (%d)\n", pllreg);
63 return 0;
64 }
65
66 /*
67 * APLL_CON: MIDV [25:16]
68 * MPLL_CON: MIDV [25:16]
69 * EPLL_CON: MIDV [24:16]
70 * VPLL_CON: MIDV [24:16]
71 */
Gabe Black5420e092013-05-17 11:29:22 -070072 if (pllreg == APLL || pllreg == BPLL || pllreg == MPLL ||
73 pllreg == SPLL)
Gabe Black607c0b62013-05-16 05:45:57 -070074 mask = 0x3ff;
75 else
76 mask = 0x1ff;
77
78 m = (r >> 16) & mask;
79
80 /* PDIV [13:8] */
81 p = (r >> 8) & 0x3f;
82 /* SDIV [2:0] */
83 s = r & 0x7;
84
Elyes HAOUAS251514d2019-01-23 11:36:44 +010085 freq = CONF_SYS_CLK_FREQ;
Gabe Black607c0b62013-05-16 05:45:57 -070086
Gabe Black5420e092013-05-17 11:29:22 -070087 if (pllreg == EPLL || pllreg == RPLL) {
Gabe Black607c0b62013-05-16 05:45:57 -070088 k = k & 0xffff;
89 /* FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV) */
90 fout = (m + k / 65536) * (freq / (p * (1 << s)));
91 } else if (pllreg == VPLL) {
92 k = k & 0xfff;
93 /* FOUT = (MDIV + K / 1024) * FIN / (PDIV * 2^SDIV) */
94 fout = (m + k / 1024) * (freq / (p * (1 << s)));
95 } else {
96 /* FOUT = MDIV * FIN / (PDIV * 2^SDIV) */
97 fout = m * (freq / (p * (1 << s)));
98 }
99
100 return fout;
101}
102
David Hendricksefd4b9e2013-08-08 19:03:03 -0700103enum peripheral_clock_select {
104 PERIPH_SRC_CPLL = 1,
105 PERIPH_SRC_DPLL = 2,
106 PERIPH_SRC_MPLL = 3,
107 PERIPH_SRC_SPLL = 4,
108 PERIPH_SRC_IPLL = 5,
109 PERIPH_SRC_EPLL = 6,
110 PERIPH_SRC_RPLL = 7,
111};
112
113static int clock_select_to_pll(enum peripheral_clock_select sel)
114{
115 int pll;
116
117 switch (sel) {
118 case PERIPH_SRC_CPLL:
119 pll = CPLL;
120 break;
121 case PERIPH_SRC_DPLL:
122 pll = DPLL;
123 break;
124 case PERIPH_SRC_MPLL:
125 pll = MPLL;
126 break;
127 case PERIPH_SRC_SPLL:
128 pll = SPLL;
129 break;
130 case PERIPH_SRC_IPLL:
131 pll = IPLL;
132 break;
133 case PERIPH_SRC_EPLL:
134 pll = EPLL;
135 break;
136 case PERIPH_SRC_RPLL:
137 pll = RPLL;
138 break;
139 default:
140 pll = -1;
141 break;
142 }
143
144 return pll;
145}
146
Gabe Black607c0b62013-05-16 05:45:57 -0700147unsigned long clock_get_periph_rate(enum periph_id peripheral)
148{
David Hendricks401da252013-08-08 20:45:53 -0700149 unsigned long sclk;
Patrick Georgi74add8b2016-12-15 15:51:13 +0100150 unsigned int div;
151 int src;
Gabe Black607c0b62013-05-16 05:45:57 -0700152
153 switch (peripheral) {
154 case PERIPH_ID_UART0:
Julius Werner2f37bd62015-02-19 14:51:15 -0800155 src = (read32(&exynos_clock->clk_src_peric0) >> 4) & 0x7;
156 div = (read32(&exynos_clock->clk_div_peric0) >> 8) & 0xf;
David Hendricks401da252013-08-08 20:45:53 -0700157 break;
Gabe Black607c0b62013-05-16 05:45:57 -0700158 case PERIPH_ID_UART1:
Julius Werner2f37bd62015-02-19 14:51:15 -0800159 src = (read32(&exynos_clock->clk_src_peric0) >> 8) & 0x7;
160 div = (read32(&exynos_clock->clk_div_peric0) >> 12) & 0xf;
David Hendricks401da252013-08-08 20:45:53 -0700161 break;
Gabe Black607c0b62013-05-16 05:45:57 -0700162 case PERIPH_ID_UART2:
Julius Werner2f37bd62015-02-19 14:51:15 -0800163 src = (read32(&exynos_clock->clk_src_peric0) >> 12) & 0x7;
164 div = (read32(&exynos_clock->clk_div_peric0) >> 16) & 0xf;
David Hendricks401da252013-08-08 20:45:53 -0700165 break;
Gabe Black607c0b62013-05-16 05:45:57 -0700166 case PERIPH_ID_UART3:
Julius Werner2f37bd62015-02-19 14:51:15 -0800167 src = (read32(&exynos_clock->clk_src_peric0) >> 16) & 0x7;
168 div = (read32(&exynos_clock->clk_div_peric0) >> 20) & 0xf;
Gabe Black607c0b62013-05-16 05:45:57 -0700169 break;
170 case PERIPH_ID_PWM0:
171 case PERIPH_ID_PWM1:
172 case PERIPH_ID_PWM2:
173 case PERIPH_ID_PWM3:
174 case PERIPH_ID_PWM4:
Julius Werner2f37bd62015-02-19 14:51:15 -0800175 src = (read32(&exynos_clock->clk_src_peric0) >> 24) & 0x7;
176 div = (read32(&exynos_clock->clk_div_peric0) >> 28) & 0x7;
Gabe Black607c0b62013-05-16 05:45:57 -0700177 break;
178 case PERIPH_ID_SPI0:
Julius Werner2f37bd62015-02-19 14:51:15 -0800179 src = (read32(&exynos_clock->clk_src_peric1) >> 20) & 0x7;
180 div = (read32(&exynos_clock->clk_div_peric1) >> 20) & 0xf;
Gabe Black607c0b62013-05-16 05:45:57 -0700181 break;
David Hendricks401da252013-08-08 20:45:53 -0700182 case PERIPH_ID_SPI1:
Julius Werner2f37bd62015-02-19 14:51:15 -0800183 src = (read32(&exynos_clock->clk_src_peric1) >> 24) & 0x7;
184 div = (read32(&exynos_clock->clk_div_peric1) >> 24) & 0xf;
David Hendricks401da252013-08-08 20:45:53 -0700185 break;
186 case PERIPH_ID_SPI2:
Julius Werner2f37bd62015-02-19 14:51:15 -0800187 src = (read32(&exynos_clock->clk_src_peric1) >> 28) & 0x7;
188 div = (read32(&exynos_clock->clk_div_peric1) >> 28) & 0xf;
David Hendricks401da252013-08-08 20:45:53 -0700189 break;
190 case PERIPH_ID_SPI3: /* aka SPI0_ISP */
Julius Werner2f37bd62015-02-19 14:51:15 -0800191 src = (read32(&exynos_clock->clk_src_isp) >> 16) & 0x7;
192 div = (read32(&exynos_clock->clk_div_isp0) >> 0) & 0x7;
David Hendricks401da252013-08-08 20:45:53 -0700193 break;
194 case PERIPH_ID_SPI4: /* aka SPI1_ISP */
Julius Werner2f37bd62015-02-19 14:51:15 -0800195 src = (read32(&exynos_clock->clk_src_isp) >> 12) & 0x7;
196 div = (read32(&exynos_clock->clk_div_isp1) >> 4) & 0x7;
Gabe Black607c0b62013-05-16 05:45:57 -0700197 break;
Gabe Black607c0b62013-05-16 05:45:57 -0700198 case PERIPH_ID_I2C0:
199 case PERIPH_ID_I2C1:
200 case PERIPH_ID_I2C2:
201 case PERIPH_ID_I2C3:
202 case PERIPH_ID_I2C4:
203 case PERIPH_ID_I2C5:
204 case PERIPH_ID_I2C6:
205 case PERIPH_ID_I2C7:
David Hendrickseb9517c2013-06-15 19:22:06 -0700206 case PERIPH_ID_I2C8:
207 case PERIPH_ID_I2C9:
208 case PERIPH_ID_I2C10:
David Hendricks7f35bbb2013-08-12 13:24:24 -0700209 /*
210 * I2C block parent clock selection is different from other
211 * peripherals, so we handle it all here.
212 * TODO: Add a helper function like with the peripheral clock
213 * select fields?
214 */
Julius Werner2f37bd62015-02-19 14:51:15 -0800215 src = (read32(&exynos_clock->clk_src_top1) >> 8) & 0x3;
David Hendricks7f35bbb2013-08-12 13:24:24 -0700216 if (src == 0x0)
217 src = CPLL;
218 else if (src == 0x1)
219 src = DPLL;
220 else if (src == 0x2)
221 src = MPLL;
222 else
223 return -1;
224
225 sclk = get_pll_clk(src);
Julius Werner2f37bd62015-02-19 14:51:15 -0800226 div = ((read32(&exynos_clock->clk_div_top1) >> 8) & 0x3f) + 1;
Gabe Blackcf7509cf2013-06-22 19:43:40 -0700227 return sclk / div;
Gabe Black607c0b62013-05-16 05:45:57 -0700228 default:
David Hendricks401da252013-08-08 20:45:53 -0700229 printk(BIOS_DEBUG, "%s: invalid peripheral %d",
230 __func__, peripheral);
Gabe Black607c0b62013-05-16 05:45:57 -0700231 return -1;
232 };
233
David Hendricksefd4b9e2013-08-08 19:03:03 -0700234 src = clock_select_to_pll(src);
235 if (src < 0) {
236 printk(BIOS_DEBUG, "%s: cannot determine source PLL", __func__);
237 return -1;
Gabe Black607c0b62013-05-16 05:45:57 -0700238 }
239
David Hendricksefd4b9e2013-08-08 19:03:03 -0700240 sclk = get_pll_clk(src);
241
David Hendricks401da252013-08-08 20:45:53 -0700242 return sclk / (div + 1);
Gabe Black607c0b62013-05-16 05:45:57 -0700243}
244
245/* exynos5: return ARM clock frequency */
246unsigned long get_arm_clk(void)
247{
Gabe Black607c0b62013-05-16 05:45:57 -0700248 unsigned long div;
249 unsigned long armclk;
250 unsigned int arm_ratio;
251 unsigned int arm2_ratio;
252
Julius Werner2f37bd62015-02-19 14:51:15 -0800253 div = read32(&exynos_clock->clk_div_cpu0);
Gabe Black607c0b62013-05-16 05:45:57 -0700254
255 /* ARM_RATIO: [2:0], ARM2_RATIO: [30:28] */
256 arm_ratio = (div >> 0) & 0x7;
257 arm2_ratio = (div >> 28) & 0x7;
258
259 armclk = get_pll_clk(APLL) / (arm_ratio + 1);
260 armclk /= (arm2_ratio + 1);
261
262 return armclk;
263}
264
Hung-Te Linf6d6e622013-07-03 19:07:21 +0800265/* exynos5: get the mmc clock */
266static unsigned long get_mmc_clk(int dev_index)
267{
Hung-Te Linf6d6e622013-07-03 19:07:21 +0800268 unsigned long uclk, sclk;
269 unsigned int sel, ratio;
270 int shift = 0;
271
Julius Werner2f37bd62015-02-19 14:51:15 -0800272 sel = read32(&exynos_clock->clk_src_fsys);
Hung-Te Linf6d6e622013-07-03 19:07:21 +0800273 sel = (sel >> ((dev_index * 4) + 8)) & 0x7;
274
275 if (sel == 0x3)
276 sclk = get_pll_clk(MPLL);
277 else if (sel == 0x6)
278 sclk = get_pll_clk(EPLL);
279 else
280 return 0;
281
Julius Werner2f37bd62015-02-19 14:51:15 -0800282 ratio = read32(&exynos_clock->clk_div_fsys1);
Hung-Te Linf6d6e622013-07-03 19:07:21 +0800283
284 shift = dev_index * 10;
285
286 ratio = (ratio >> shift) & 0x3ff;
287 uclk = (sclk / (ratio + 1));
288 printk(BIOS_DEBUG, "%s(%d): %lu\n", __func__, dev_index, uclk);
289
290 return uclk;
291}
292
Gabe Black607c0b62013-05-16 05:45:57 -0700293/* exynos5: set the mmc clock */
294void set_mmc_clk(int dev_index, unsigned int div)
295{
Gabe Black5420e092013-05-17 11:29:22 -0700296 void *addr;
297 unsigned int val, shift;
Gabe Black607c0b62013-05-16 05:45:57 -0700298
Julius Wernerfa938c72013-08-29 14:17:36 -0700299 addr = &exynos_clock->clk_div_fsys1;
Gabe Black5420e092013-05-17 11:29:22 -0700300 shift = dev_index * 10;
Gabe Black607c0b62013-05-16 05:45:57 -0700301
Julius Werner2f37bd62015-02-19 14:51:15 -0800302 val = read32(addr);
Gabe Black5420e092013-05-17 11:29:22 -0700303 val &= ~(0x3ff << shift);
304 val |= (div & 0x3ff) << shift;
Julius Werner2f37bd62015-02-19 14:51:15 -0800305 write32(addr, val);
Gabe Black607c0b62013-05-16 05:45:57 -0700306}
307
Hung-Te Linf6d6e622013-07-03 19:07:21 +0800308/* Set DW MMC Controller clock */
309int clock_set_dwmci(enum periph_id peripheral)
310{
311 /* Request MMC clock value to 52MHz. */
312 const unsigned long freq = 52000000;
Hung-Te Linf2c42412013-08-22 23:56:35 +0800313 unsigned long sdclkin, cclkin;
Hung-Te Linf6d6e622013-07-03 19:07:21 +0800314 int device_index = (int)peripheral - (int)PERIPH_ID_SDMMC0;
315
316 ASSERT(device_index >= 0 && device_index < 4);
Hung-Te Linf2c42412013-08-22 23:56:35 +0800317 sdclkin = get_mmc_clk(device_index);
318 if (!sdclkin) {
Hung-Te Linf6d6e622013-07-03 19:07:21 +0800319 return -1;
320 }
Hung-Te Linf2c42412013-08-22 23:56:35 +0800321
Martin Roth1fc2ba52014-12-07 14:59:11 -0700322 /* The SDCLKIN is divided inside the controller by the DIVRATIO field in
Hung-Te Linf2c42412013-08-22 23:56:35 +0800323 * CLKSEL register, so we must calculate clock value as
324 * cclk_in = SDCLKIN / (DIVRATIO + 1)
325 * Currently the RIVRATIO must be 3 for MMC0 and MMC2 on Exynos5420
326 * (and must be configured in payload).
327 */
328 if (device_index == 0 || device_index == 2){
329 int divratio = 3;
330 sdclkin /= (divratio + 1);
331 }
332 printk(BIOS_DEBUG, "%s(%d): sdclkin: %ld\n", __func__, device_index, sdclkin);
333
Elyes HAOUAS6df3b642018-11-26 22:53:49 +0100334 cclkin = DIV_ROUND_UP(sdclkin, freq);
Hung-Te Linf2c42412013-08-22 23:56:35 +0800335 set_mmc_clk(device_index, cclkin);
Hung-Te Linf6d6e622013-07-03 19:07:21 +0800336 return 0;
337}
338
Martin Roth57e89092019-10-23 21:45:23 -0600339void clock_ll_set_pre_ratio(enum periph_id periph_id, unsigned int divisor)
Gabe Black607c0b62013-05-16 05:45:57 -0700340{
Martin Roth57e89092019-10-23 21:45:23 -0600341 unsigned int shift;
342 unsigned int mask = 0xff;
Gabe Black607c0b62013-05-16 05:45:57 -0700343 u32 *reg;
344
345 /*
Martin Roth1fc2ba52014-12-07 14:59:11 -0700346 * For now we only handle a very small subset of peripherals here.
Gabe Black607c0b62013-05-16 05:45:57 -0700347 * Others will need to (and do) mangle the clock registers
348 * themselves, At some point it is hoped that this function can work
349 * from a table or calculated register offset / mask. For now this
350 * is at least better than spreading clock control code around
351 * U-Boot.
352 */
353 switch (periph_id) {
354 case PERIPH_ID_SPI0:
Julius Wernerfa938c72013-08-29 14:17:36 -0700355 reg = &exynos_clock->clk_div_peric4;
Gabe Black607c0b62013-05-16 05:45:57 -0700356 shift = 8;
357 break;
358 case PERIPH_ID_SPI1:
Julius Wernerfa938c72013-08-29 14:17:36 -0700359 reg = &exynos_clock->clk_div_peric4;
Gabe Blackc883fdc2013-06-18 06:08:42 -0700360 shift = 16;
Gabe Black607c0b62013-05-16 05:45:57 -0700361 break;
362 case PERIPH_ID_SPI2:
Julius Wernerfa938c72013-08-29 14:17:36 -0700363 reg = &exynos_clock->clk_div_peric4;
Gabe Blackc883fdc2013-06-18 06:08:42 -0700364 shift = 24;
Gabe Black607c0b62013-05-16 05:45:57 -0700365 break;
366 case PERIPH_ID_SPI3:
Julius Wernerfa938c72013-08-29 14:17:36 -0700367 reg = &exynos_clock->clk_div_isp1;
Gabe Blackc883fdc2013-06-18 06:08:42 -0700368 shift = 0;
Gabe Black607c0b62013-05-16 05:45:57 -0700369 break;
370 case PERIPH_ID_SPI4:
Julius Wernerfa938c72013-08-29 14:17:36 -0700371 reg = &exynos_clock->clk_div_isp1;
Gabe Blackc883fdc2013-06-18 06:08:42 -0700372 shift = 8;
Gabe Black607c0b62013-05-16 05:45:57 -0700373 break;
374 default:
375 printk(BIOS_DEBUG, "%s: Unsupported peripheral ID %d\n", __func__,
376 periph_id);
377 return;
378 }
Julius Werner55009af2019-12-02 22:03:27 -0800379 clrsetbits32(reg, mask << shift, (divisor & mask) << shift);
Gabe Black607c0b62013-05-16 05:45:57 -0700380}
381
Martin Roth57e89092019-10-23 21:45:23 -0600382void clock_ll_set_ratio(enum periph_id periph_id, unsigned int divisor)
Gabe Black607c0b62013-05-16 05:45:57 -0700383{
Martin Roth57e89092019-10-23 21:45:23 -0600384 unsigned int shift;
385 unsigned int mask = 0xf;
Gabe Black607c0b62013-05-16 05:45:57 -0700386 u32 *reg;
387
388 switch (periph_id) {
389 case PERIPH_ID_SPI0:
Julius Wernerfa938c72013-08-29 14:17:36 -0700390 reg = &exynos_clock->clk_div_peric1;
Gabe Blackc883fdc2013-06-18 06:08:42 -0700391 shift = 20;
Gabe Black607c0b62013-05-16 05:45:57 -0700392 break;
393 case PERIPH_ID_SPI1:
Julius Wernerfa938c72013-08-29 14:17:36 -0700394 reg = &exynos_clock->clk_div_peric1;
Gabe Blackc883fdc2013-06-18 06:08:42 -0700395 shift = 24;
Gabe Black607c0b62013-05-16 05:45:57 -0700396 break;
397 case PERIPH_ID_SPI2:
Julius Wernerfa938c72013-08-29 14:17:36 -0700398 reg = &exynos_clock->clk_div_peric1;
Gabe Blackc883fdc2013-06-18 06:08:42 -0700399 shift = 28;
Gabe Black607c0b62013-05-16 05:45:57 -0700400 break;
401 case PERIPH_ID_SPI3:
Julius Wernerfa938c72013-08-29 14:17:36 -0700402 reg = &exynos_clock->clk_div_isp1;
Gabe Blackc883fdc2013-06-18 06:08:42 -0700403 shift = 16;
Gabe Black607c0b62013-05-16 05:45:57 -0700404 break;
405 case PERIPH_ID_SPI4:
Julius Wernerfa938c72013-08-29 14:17:36 -0700406 reg = &exynos_clock->clk_div_isp1;
Gabe Blackc883fdc2013-06-18 06:08:42 -0700407 shift = 20;
Gabe Black607c0b62013-05-16 05:45:57 -0700408 break;
409 default:
410 printk(BIOS_DEBUG, "%s: Unsupported peripheral ID %d\n", __func__,
411 periph_id);
412 return;
413 }
Julius Werner55009af2019-12-02 22:03:27 -0800414 clrsetbits32(reg, mask << shift, (divisor & mask) << shift);
Gabe Black607c0b62013-05-16 05:45:57 -0700415}
416
417/**
418 * Linearly searches for the most accurate main and fine stage clock scalars
419 * (divisors) for a specified target frequency and scalar bit sizes by checking
420 * all multiples of main_scalar_bits values. Will always return scalars up to or
421 * slower than target.
422 *
423 * @param main_scalar_bits Number of main scalar bits, must be > 0 and < 32
424 * @param fine_scalar_bits Number of fine scalar bits, must be > 0 and < 32
Martin Roth32bc6b62015-01-04 16:54:35 -0700425 * @param input_rate Clock frequency to be scaled in Hz
426 * @param target_rate Desired clock frequency in Hz
Gabe Black607c0b62013-05-16 05:45:57 -0700427 * @param best_fine_scalar Pointer to store the fine stage divisor
428 *
429 * @return best_main_scalar Main scalar for desired frequency or -1 if none
430 * found
431 */
432static int clock_calc_best_scalar(unsigned int main_scaler_bits,
433 unsigned int fine_scalar_bits, unsigned int input_rate,
434 unsigned int target_rate, unsigned int *best_fine_scalar)
435{
436 int i;
437 int best_main_scalar = -1;
438 unsigned int best_error = target_rate;
439 const unsigned int cap = (1 << fine_scalar_bits) - 1;
440 const unsigned int loops = 1 << main_scaler_bits;
441
442 printk(BIOS_DEBUG, "Input Rate is %u, Target is %u, Cap is %u\n", input_rate,
443 target_rate, cap);
444
445 ASSERT(best_fine_scalar != NULL);
446 ASSERT(main_scaler_bits <= fine_scalar_bits);
447
448 *best_fine_scalar = 1;
449
450 if (input_rate == 0 || target_rate == 0)
451 return -1;
452
453 if (target_rate >= input_rate)
454 return 1;
455
456 for (i = 1; i <= loops; i++) {
457 const unsigned int effective_div = MAX(MIN(input_rate / i /
458 target_rate, cap), 1);
459 const unsigned int effective_rate = input_rate / i /
460 effective_div;
461 const int error = target_rate - effective_rate;
462
463 printk(BIOS_DEBUG, "%d|effdiv:%u, effrate:%u, error:%d\n", i, effective_div,
464 effective_rate, error);
465
466 if (error >= 0 && error <= best_error) {
467 best_error = error;
468 best_main_scalar = i;
469 *best_fine_scalar = effective_div;
470 }
471 }
472
473 return best_main_scalar;
474}
475
476int clock_set_rate(enum periph_id periph_id, unsigned int rate)
477{
Patrick Georgi905e6f22014-08-14 20:23:51 +0200478 int main_scalar;
Gabe Black607c0b62013-05-16 05:45:57 -0700479 unsigned int fine;
480
481 switch (periph_id) {
482 case PERIPH_ID_SPI0:
483 case PERIPH_ID_SPI1:
484 case PERIPH_ID_SPI2:
485 case PERIPH_ID_SPI3:
486 case PERIPH_ID_SPI4:
Patrick Georgi905e6f22014-08-14 20:23:51 +0200487 main_scalar = clock_calc_best_scalar(4, 8, 400000000, rate, &fine);
488 if (main_scalar < 0) {
Gabe Black607c0b62013-05-16 05:45:57 -0700489 printk(BIOS_DEBUG, "%s: Cannot set clock rate for periph %d",
490 __func__, periph_id);
491 return -1;
492 }
Patrick Georgi905e6f22014-08-14 20:23:51 +0200493 clock_ll_set_ratio(periph_id, main_scalar - 1);
Gabe Black607c0b62013-05-16 05:45:57 -0700494 clock_ll_set_pre_ratio(periph_id, fine - 1);
495 break;
496 default:
497 printk(BIOS_DEBUG, "%s: Unsupported peripheral ID %d\n", __func__,
498 periph_id);
499 return -1;
500 }
501
502 return 0;
503}
504
505int clock_set_mshci(enum periph_id peripheral)
506{
Gabe Black607c0b62013-05-16 05:45:57 -0700507 u32 *addr;
508 unsigned int clock;
509 unsigned int tmp;
510 unsigned int i;
511
512 /* get mpll clock */
513 clock = get_pll_clk(MPLL) / 1000000;
514
515 /*
516 * CLK_DIV_FSYS1
517 * MMC0_PRE_RATIO [15:8], MMC0_RATIO [3:0]
518 * CLK_DIV_FSYS2
519 * MMC2_PRE_RATIO [15:8], MMC2_RATIO [3:0]
520 */
521 switch (peripheral) {
522 case PERIPH_ID_SDMMC0:
Julius Wernerfa938c72013-08-29 14:17:36 -0700523 addr = &exynos_clock->clk_div_fsys1;
Gabe Black607c0b62013-05-16 05:45:57 -0700524 break;
525 case PERIPH_ID_SDMMC2:
Julius Wernerfa938c72013-08-29 14:17:36 -0700526 addr = &exynos_clock->clk_div_fsys2;
Gabe Black607c0b62013-05-16 05:45:57 -0700527 break;
528 default:
529 printk(BIOS_DEBUG, "invalid peripheral\n");
530 return -1;
531 }
Julius Werner2f37bd62015-02-19 14:51:15 -0800532 tmp = read32(addr) & ~0xff0f;
Gabe Black607c0b62013-05-16 05:45:57 -0700533 for (i = 0; i <= 0xf; i++) {
534 if ((clock / (i + 1)) <= 400) {
Julius Werner2f37bd62015-02-19 14:51:15 -0800535 write32(addr, tmp | i << 0);
Gabe Black607c0b62013-05-16 05:45:57 -0700536 break;
537 }
538 }
539 return 0;
540}
541
542int clock_epll_set_rate(unsigned long rate)
543{
544 unsigned int epll_con, epll_con_k;
545 unsigned int i;
546 unsigned int lockcnt;
Aaron Durbin43933462014-09-24 10:27:29 -0500547 struct stopwatch sw;
Gabe Black607c0b62013-05-16 05:45:57 -0700548
Julius Werner2f37bd62015-02-19 14:51:15 -0800549 epll_con = read32(&exynos_clock->epll_con0);
Gabe Black607c0b62013-05-16 05:45:57 -0700550 epll_con &= ~((EPLL_CON0_LOCK_DET_EN_MASK <<
551 EPLL_CON0_LOCK_DET_EN_SHIFT) |
552 EPLL_CON0_MDIV_MASK << EPLL_CON0_MDIV_SHIFT |
553 EPLL_CON0_PDIV_MASK << EPLL_CON0_PDIV_SHIFT |
554 EPLL_CON0_SDIV_MASK << EPLL_CON0_SDIV_SHIFT);
555
556 for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
557 if (epll_div[i].freq_out == rate)
558 break;
559 }
560
561 if (i == ARRAY_SIZE(epll_div))
562 return -1;
563
564 epll_con_k = epll_div[i].k_dsm << 0;
565 epll_con |= epll_div[i].en_lock_det << EPLL_CON0_LOCK_DET_EN_SHIFT;
566 epll_con |= epll_div[i].m_div << EPLL_CON0_MDIV_SHIFT;
567 epll_con |= epll_div[i].p_div << EPLL_CON0_PDIV_SHIFT;
568 epll_con |= epll_div[i].s_div << EPLL_CON0_SDIV_SHIFT;
569
570 /*
Elyes HAOUASa342f392018-10-17 10:56:26 +0200571 * Required period (in cycles) to generate a stable clock output.
Gabe Black607c0b62013-05-16 05:45:57 -0700572 * The maximum clock time can be up to 3000 * PDIV cycles of PLLs
573 * frequency input (as per spec)
574 */
575 lockcnt = 3000 * epll_div[i].p_div;
576
Julius Werner2f37bd62015-02-19 14:51:15 -0800577 write32(&exynos_clock->epll_lock, lockcnt);
578 write32(&exynos_clock->epll_con0, epll_con);
579 write32(&exynos_clock->epll_con1, epll_con_k);
Gabe Black607c0b62013-05-16 05:45:57 -0700580
Aaron Durbin43933462014-09-24 10:27:29 -0500581 stopwatch_init_msecs_expire(&sw, TIMEOUT_EPLL_LOCK);
Gabe Black607c0b62013-05-16 05:45:57 -0700582
Julius Werner2f37bd62015-02-19 14:51:15 -0800583 while (!(read32(&exynos_clock->epll_con0) &
Gabe Black607c0b62013-05-16 05:45:57 -0700584 (0x1 << EXYNOS5_EPLLCON0_LOCKED_SHIFT))) {
Aaron Durbin43933462014-09-24 10:27:29 -0500585 if (stopwatch_expired(&sw)) {
Gabe Black607c0b62013-05-16 05:45:57 -0700586 printk(BIOS_DEBUG, "%s: Timeout waiting for EPLL lock\n", __func__);
587 return -1;
588 }
589 }
590
591 return 0;
592}
593
594void clock_select_i2s_clk_source(void)
595{
Julius Werner55009af2019-12-02 22:03:27 -0800596 clrsetbits32(&exynos_clock->clk_src_peric1, AUDIO1_SEL_MASK,
Gabe Black607c0b62013-05-16 05:45:57 -0700597 (CLK_SRC_SCLK_EPLL));
598}
599
600int clock_set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq)
601{
Elyes Haouas108b99b2023-08-13 12:53:34 +0200602 unsigned int div;
Gabe Black607c0b62013-05-16 05:45:57 -0700603
604 if ((dst_frq == 0) || (src_frq == 0)) {
Martin Roth1fc2ba52014-12-07 14:59:11 -0700605 printk(BIOS_DEBUG, "%s: Invalid frequency input for prescaler\n", __func__);
Gabe Black607c0b62013-05-16 05:45:57 -0700606 printk(BIOS_DEBUG, "src frq = %d des frq = %d ", src_frq, dst_frq);
607 return -1;
608 }
609
610 div = (src_frq / dst_frq);
611 if (div > AUDIO_1_RATIO_MASK) {
612 printk(BIOS_DEBUG, "%s: Frequency ratio is out of range\n", __func__);
613 printk(BIOS_DEBUG, "src frq = %d des frq = %d ", src_frq, dst_frq);
614 return -1;
615 }
Julius Werner55009af2019-12-02 22:03:27 -0800616 clrsetbits32(&exynos_clock->clk_div_peric4, AUDIO_1_RATIO_MASK,
Gabe Black607c0b62013-05-16 05:45:57 -0700617 (div & AUDIO_1_RATIO_MASK));
618 return 0;
619}