blob: 58b9321131a90d4da4a4d5bb069fa2802bce2636 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Ley Foon Tanca40f292017-04-26 02:44:39 +08002/*
3 * Copyright (C) 2016-2017 Intel Corporation
Ley Foon Tanca40f292017-04-26 02:44:39 +08004 */
5
Ley Foon Tanca40f292017-04-26 02:44:39 +08006#include <fdtdec.h>
Simon Glass9bc15642020-02-03 07:36:16 -07007#include <malloc.h>
Ley Foon Tanca40f292017-04-26 02:44:39 +08008#include <asm/io.h>
Eugeniy Paltsev74739322017-12-28 15:09:02 +03009#include <dm.h>
Marek Vasute1dcd622018-07-30 15:56:19 +020010#include <clk.h>
11#include <dm/device-internal.h>
Ley Foon Tanca40f292017-04-26 02:44:39 +080012#include <asm/arch/clock_manager.h>
Simon Glassdbd79542020-05-10 11:40:11 -060013#include <linux/delay.h>
Ley Foon Tanca40f292017-04-26 02:44:39 +080014
Marek Vasut8fdb4192018-08-18 19:11:52 +020015#ifdef CONFIG_SPL_BUILD
Marek Vasutec472e02018-05-12 00:09:21 +020016
Paweł Anikiel3dad5752022-06-17 12:47:23 +020017void sdelay(unsigned long loops);
18u32 wait_on_value(u32 read_bit_mask, u32 match_value, void *read_addr,
19 u32 bound);
20
Ley Foon Tanca40f292017-04-26 02:44:39 +080021static u32 eosc1_hz;
22static u32 cb_intosc_hz;
23static u32 f2s_free_hz;
Ley Foon Tanca40f292017-04-26 02:44:39 +080024
25struct mainpll_cfg {
26 u32 vco0_psrc;
27 u32 vco1_denom;
28 u32 vco1_numer;
29 u32 mpuclk;
30 u32 mpuclk_cnt;
31 u32 mpuclk_src;
32 u32 nocclk;
33 u32 nocclk_cnt;
34 u32 nocclk_src;
35 u32 cntr2clk_cnt;
36 u32 cntr3clk_cnt;
37 u32 cntr4clk_cnt;
38 u32 cntr5clk_cnt;
39 u32 cntr6clk_cnt;
40 u32 cntr7clk_cnt;
41 u32 cntr7clk_src;
42 u32 cntr8clk_cnt;
43 u32 cntr9clk_cnt;
44 u32 cntr9clk_src;
45 u32 cntr15clk_cnt;
46 u32 nocdiv_l4mainclk;
47 u32 nocdiv_l4mpclk;
48 u32 nocdiv_l4spclk;
49 u32 nocdiv_csatclk;
50 u32 nocdiv_cstraceclk;
51 u32 nocdiv_cspdbclk;
52};
53
54struct perpll_cfg {
55 u32 vco0_psrc;
56 u32 vco1_denom;
57 u32 vco1_numer;
58 u32 cntr2clk_cnt;
59 u32 cntr2clk_src;
60 u32 cntr3clk_cnt;
61 u32 cntr3clk_src;
62 u32 cntr4clk_cnt;
63 u32 cntr4clk_src;
64 u32 cntr5clk_cnt;
65 u32 cntr5clk_src;
66 u32 cntr6clk_cnt;
67 u32 cntr6clk_src;
68 u32 cntr7clk_cnt;
69 u32 cntr8clk_cnt;
70 u32 cntr8clk_src;
71 u32 cntr9clk_cnt;
Marek Vasutec472e02018-05-12 00:09:21 +020072 u32 cntr9clk_src;
Ley Foon Tanca40f292017-04-26 02:44:39 +080073 u32 emacctl_emac0sel;
74 u32 emacctl_emac1sel;
75 u32 emacctl_emac2sel;
76 u32 gpiodiv_gpiodbclk;
77};
78
Marek Vasutec472e02018-05-12 00:09:21 +020079struct strtou32 {
80 const char *str;
81 const u32 val;
Ley Foon Tanca40f292017-04-26 02:44:39 +080082};
83
Marek Vasutec472e02018-05-12 00:09:21 +020084static const struct strtou32 mainpll_cfg_tab[] = {
85 { "vco0-psrc", offsetof(struct mainpll_cfg, vco0_psrc) },
86 { "vco1-denom", offsetof(struct mainpll_cfg, vco1_denom) },
87 { "vco1-numer", offsetof(struct mainpll_cfg, vco1_numer) },
88 { "mpuclk-cnt", offsetof(struct mainpll_cfg, mpuclk_cnt) },
89 { "mpuclk-src", offsetof(struct mainpll_cfg, mpuclk_src) },
90 { "nocclk-cnt", offsetof(struct mainpll_cfg, nocclk_cnt) },
91 { "nocclk-src", offsetof(struct mainpll_cfg, nocclk_src) },
92 { "cntr2clk-cnt", offsetof(struct mainpll_cfg, cntr2clk_cnt) },
93 { "cntr3clk-cnt", offsetof(struct mainpll_cfg, cntr3clk_cnt) },
94 { "cntr4clk-cnt", offsetof(struct mainpll_cfg, cntr4clk_cnt) },
95 { "cntr5clk-cnt", offsetof(struct mainpll_cfg, cntr5clk_cnt) },
96 { "cntr6clk-cnt", offsetof(struct mainpll_cfg, cntr6clk_cnt) },
97 { "cntr7clk-cnt", offsetof(struct mainpll_cfg, cntr7clk_cnt) },
98 { "cntr7clk-src", offsetof(struct mainpll_cfg, cntr7clk_src) },
99 { "cntr8clk-cnt", offsetof(struct mainpll_cfg, cntr8clk_cnt) },
100 { "cntr9clk-cnt", offsetof(struct mainpll_cfg, cntr9clk_cnt) },
101 { "cntr9clk-src", offsetof(struct mainpll_cfg, cntr9clk_src) },
102 { "cntr15clk-cnt", offsetof(struct mainpll_cfg, cntr15clk_cnt) },
103 { "nocdiv-l4mainclk", offsetof(struct mainpll_cfg, nocdiv_l4mainclk) },
104 { "nocdiv-l4mpclk", offsetof(struct mainpll_cfg, nocdiv_l4mpclk) },
105 { "nocdiv-l4spclk", offsetof(struct mainpll_cfg, nocdiv_l4spclk) },
106 { "nocdiv-csatclk", offsetof(struct mainpll_cfg, nocdiv_csatclk) },
107 { "nocdiv-cstraceclk", offsetof(struct mainpll_cfg, nocdiv_cstraceclk) },
108 { "nocdiv-cspdbgclk", offsetof(struct mainpll_cfg, nocdiv_cspdbclk) },
109};
Ley Foon Tanca40f292017-04-26 02:44:39 +0800110
Marek Vasutec472e02018-05-12 00:09:21 +0200111static const struct strtou32 perpll_cfg_tab[] = {
112 { "vco0-psrc", offsetof(struct perpll_cfg, vco0_psrc) },
113 { "vco1-denom", offsetof(struct perpll_cfg, vco1_denom) },
114 { "vco1-numer", offsetof(struct perpll_cfg, vco1_numer) },
115 { "cntr2clk-cnt", offsetof(struct perpll_cfg, cntr2clk_cnt) },
116 { "cntr2clk-src", offsetof(struct perpll_cfg, cntr2clk_src) },
117 { "cntr3clk-cnt", offsetof(struct perpll_cfg, cntr3clk_cnt) },
118 { "cntr3clk-src", offsetof(struct perpll_cfg, cntr3clk_src) },
119 { "cntr4clk-cnt", offsetof(struct perpll_cfg, cntr4clk_cnt) },
120 { "cntr4clk-src", offsetof(struct perpll_cfg, cntr4clk_src) },
121 { "cntr5clk-cnt", offsetof(struct perpll_cfg, cntr5clk_cnt) },
122 { "cntr5clk-src", offsetof(struct perpll_cfg, cntr5clk_src) },
123 { "cntr6clk-cnt", offsetof(struct perpll_cfg, cntr6clk_cnt) },
124 { "cntr6clk-src", offsetof(struct perpll_cfg, cntr6clk_src) },
125 { "cntr7clk-cnt", offsetof(struct perpll_cfg, cntr7clk_cnt) },
126 { "cntr8clk-cnt", offsetof(struct perpll_cfg, cntr8clk_cnt) },
127 { "cntr8clk-src", offsetof(struct perpll_cfg, cntr8clk_src) },
128 { "cntr9clk-cnt", offsetof(struct perpll_cfg, cntr9clk_cnt) },
129 { "emacctl-emac0sel", offsetof(struct perpll_cfg, emacctl_emac0sel) },
130 { "emacctl-emac1sel", offsetof(struct perpll_cfg, emacctl_emac1sel) },
131 { "emacctl-emac2sel", offsetof(struct perpll_cfg, emacctl_emac2sel) },
132 { "gpiodiv-gpiodbclk", offsetof(struct perpll_cfg, gpiodiv_gpiodbclk) },
133};
134
135static const struct strtou32 alteragrp_cfg_tab[] = {
136 { "nocclk", offsetof(struct mainpll_cfg, nocclk) },
137 { "mpuclk", offsetof(struct mainpll_cfg, mpuclk) },
138};
139
140struct strtopu32 {
141 const char *str;
142 u32 *p;
143};
144
145const struct strtopu32 dt_to_val[] = {
Marek Vasute1dcd622018-07-30 15:56:19 +0200146 { "altera_arria10_hps_eosc1", &eosc1_hz },
147 { "altera_arria10_hps_cb_intosc_ls", &cb_intosc_hz },
148 { "altera_arria10_hps_f2h_free", &f2s_free_hz },
Marek Vasutec472e02018-05-12 00:09:21 +0200149};
150
151static int of_to_struct(const void *blob, int node, const struct strtou32 *cfg_tab,
152 int cfg_tab_len, void *cfg)
Ley Foon Tanca40f292017-04-26 02:44:39 +0800153{
Marek Vasutec472e02018-05-12 00:09:21 +0200154 int i;
155 u32 val;
156
157 for (i = 0; i < cfg_tab_len; i++) {
158 if (fdtdec_get_int_array(blob, node, cfg_tab[i].str, &val, 1)) {
159 /* could not find required property */
160 return -EINVAL;
161 }
162 *(u32 *)(cfg + cfg_tab[i].val) = val;
Ley Foon Tanca40f292017-04-26 02:44:39 +0800163 }
164
165 return 0;
166}
167
Marek Vasute1dcd622018-07-30 15:56:19 +0200168static int of_get_input_clks(const void *blob)
Ley Foon Tanca40f292017-04-26 02:44:39 +0800169{
Marek Vasute1dcd622018-07-30 15:56:19 +0200170 struct udevice *dev;
171 struct clk clk;
172 int i, ret;
Ley Foon Tanca40f292017-04-26 02:44:39 +0800173
Marek Vasutec472e02018-05-12 00:09:21 +0200174 for (i = 0; i < ARRAY_SIZE(dt_to_val); i++) {
Marek Vasute1dcd622018-07-30 15:56:19 +0200175 memset(&clk, 0, sizeof(clk));
Marek Vasutec472e02018-05-12 00:09:21 +0200176
Marek Vasute1dcd622018-07-30 15:56:19 +0200177 ret = uclass_get_device_by_name(UCLASS_CLK, dt_to_val[i].str,
178 &dev);
179 if (ret)
180 return ret;
Marek Vasutec472e02018-05-12 00:09:21 +0200181
Marek Vasute1dcd622018-07-30 15:56:19 +0200182 ret = clk_request(dev, &clk);
183 if (ret)
184 return ret;
185
186 *dt_to_val[i].p = clk_get_rate(&clk);
Marek Vasutec472e02018-05-12 00:09:21 +0200187 }
Marek Vasute1dcd622018-07-30 15:56:19 +0200188
189 return 0;
Ley Foon Tanca40f292017-04-26 02:44:39 +0800190}
191
192static int of_get_clk_cfg(const void *blob, struct mainpll_cfg *main_cfg,
Marek Vasutec472e02018-05-12 00:09:21 +0200193 struct perpll_cfg *per_cfg)
Ley Foon Tanca40f292017-04-26 02:44:39 +0800194{
Marek Vasute1dcd622018-07-30 15:56:19 +0200195 int ret, node, child, len;
Ley Foon Tanca40f292017-04-26 02:44:39 +0800196 const char *node_name;
197
Marek Vasute1dcd622018-07-30 15:56:19 +0200198 ret = of_get_input_clks(blob);
199 if (ret)
200 return ret;
Marek Vasutec472e02018-05-12 00:09:21 +0200201
202 node = fdtdec_next_compatible(blob, 0, COMPAT_ALTERA_SOCFPGA_CLK_INIT);
203
Ley Foon Tanca40f292017-04-26 02:44:39 +0800204 if (node < 0)
205 return -EINVAL;
206
207 child = fdt_first_subnode(blob, node);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800208
Ley Foon Tanca40f292017-04-26 02:44:39 +0800209 if (child < 0)
210 return -EINVAL;
211
212 node_name = fdt_get_name(blob, child, &len);
213
214 while (node_name) {
Marek Vasutec472e02018-05-12 00:09:21 +0200215 if (!strcmp(node_name, "mainpll")) {
216 if (of_to_struct(blob, child, mainpll_cfg_tab,
217 ARRAY_SIZE(mainpll_cfg_tab), main_cfg))
Ley Foon Tanca40f292017-04-26 02:44:39 +0800218 return -EINVAL;
Marek Vasutec472e02018-05-12 00:09:21 +0200219 } else if (!strcmp(node_name, "perpll")) {
220 if (of_to_struct(blob, child, perpll_cfg_tab,
221 ARRAY_SIZE(perpll_cfg_tab), per_cfg))
Ley Foon Tanca40f292017-04-26 02:44:39 +0800222 return -EINVAL;
Marek Vasutec472e02018-05-12 00:09:21 +0200223 } else if (!strcmp(node_name, "alteragrp")) {
224 if (of_to_struct(blob, child, alteragrp_cfg_tab,
225 ARRAY_SIZE(alteragrp_cfg_tab), main_cfg))
Ley Foon Tanca40f292017-04-26 02:44:39 +0800226 return -EINVAL;
Ley Foon Tanca40f292017-04-26 02:44:39 +0800227 }
228 child = fdt_next_subnode(blob, child);
229
230 if (child < 0)
231 break;
232
233 node_name = fdt_get_name(blob, child, &len);
234 }
235
236 return 0;
237}
238
239/* calculate the intended main VCO frequency based on handoff */
240static unsigned int cm_calc_handoff_main_vco_clk_hz
241 (struct mainpll_cfg *main_cfg)
242{
243 unsigned int clk_hz;
244
245 /* Check main VCO clock source: eosc, intosc or f2s? */
246 switch (main_cfg->vco0_psrc) {
247 case CLKMGR_MAINPLL_VCO0_PSRC_EOSC:
248 clk_hz = eosc1_hz;
249 break;
250 case CLKMGR_MAINPLL_VCO0_PSRC_E_INTOSC:
251 clk_hz = cb_intosc_hz;
252 break;
253 case CLKMGR_MAINPLL_VCO0_PSRC_F2S:
254 clk_hz = f2s_free_hz;
255 break;
256 default:
257 return 0;
258 }
259
260 /* calculate the VCO frequency */
261 clk_hz /= 1 + main_cfg->vco1_denom;
262 clk_hz *= 1 + main_cfg->vco1_numer;
263
264 return clk_hz;
265}
266
267/* calculate the intended periph VCO frequency based on handoff */
268static unsigned int cm_calc_handoff_periph_vco_clk_hz(
269 struct mainpll_cfg *main_cfg, struct perpll_cfg *per_cfg)
270{
271 unsigned int clk_hz;
272
273 /* Check periph VCO clock source: eosc, intosc, f2s or mainpll? */
274 switch (per_cfg->vco0_psrc) {
275 case CLKMGR_PERPLL_VCO0_PSRC_EOSC:
276 clk_hz = eosc1_hz;
277 break;
278 case CLKMGR_PERPLL_VCO0_PSRC_E_INTOSC:
279 clk_hz = cb_intosc_hz;
280 break;
281 case CLKMGR_PERPLL_VCO0_PSRC_F2S:
282 clk_hz = f2s_free_hz;
283 break;
284 case CLKMGR_PERPLL_VCO0_PSRC_MAIN:
285 clk_hz = cm_calc_handoff_main_vco_clk_hz(main_cfg);
286 clk_hz /= main_cfg->cntr15clk_cnt;
287 break;
288 default:
289 return 0;
290 }
291
292 /* calculate the VCO frequency */
293 clk_hz /= 1 + per_cfg->vco1_denom;
294 clk_hz *= 1 + per_cfg->vco1_numer;
295
296 return clk_hz;
297}
298
299/* calculate the intended MPU clock frequency based on handoff */
300static unsigned int cm_calc_handoff_mpu_clk_hz(struct mainpll_cfg *main_cfg,
301 struct perpll_cfg *per_cfg)
302{
303 unsigned int clk_hz;
304
305 /* Check MPU clock source: main, periph, osc1, intosc or f2s? */
306 switch (main_cfg->mpuclk_src) {
307 case CLKMGR_MAINPLL_MPUCLK_SRC_MAIN:
308 clk_hz = cm_calc_handoff_main_vco_clk_hz(main_cfg);
309 clk_hz /= (main_cfg->mpuclk & CLKMGR_MAINPLL_MPUCLK_CNT_MSK)
310 + 1;
311 break;
312 case CLKMGR_MAINPLL_MPUCLK_SRC_PERI:
313 clk_hz = cm_calc_handoff_periph_vco_clk_hz(main_cfg, per_cfg);
314 clk_hz /= ((main_cfg->mpuclk >>
315 CLKMGR_MAINPLL_MPUCLK_PERICNT_LSB) &
316 CLKMGR_MAINPLL_MPUCLK_CNT_MSK) + 1;
317 break;
318 case CLKMGR_MAINPLL_MPUCLK_SRC_OSC1:
319 clk_hz = eosc1_hz;
320 break;
321 case CLKMGR_MAINPLL_MPUCLK_SRC_INTOSC:
322 clk_hz = cb_intosc_hz;
323 break;
324 case CLKMGR_MAINPLL_MPUCLK_SRC_FPGA:
325 clk_hz = f2s_free_hz;
326 break;
327 default:
328 return 0;
329 }
330
331 clk_hz /= main_cfg->mpuclk_cnt + 1;
332 return clk_hz;
333}
334
335/* calculate the intended NOC clock frequency based on handoff */
336static unsigned int cm_calc_handoff_noc_clk_hz(struct mainpll_cfg *main_cfg,
337 struct perpll_cfg *per_cfg)
338{
339 unsigned int clk_hz;
340
341 /* Check MPU clock source: main, periph, osc1, intosc or f2s? */
342 switch (main_cfg->nocclk_src) {
343 case CLKMGR_MAINPLL_NOCCLK_SRC_MAIN:
344 clk_hz = cm_calc_handoff_main_vco_clk_hz(main_cfg);
345 clk_hz /= (main_cfg->nocclk & CLKMGR_MAINPLL_NOCCLK_CNT_MSK)
346 + 1;
347 break;
348 case CLKMGR_MAINPLL_NOCCLK_SRC_PERI:
349 clk_hz = cm_calc_handoff_periph_vco_clk_hz(main_cfg, per_cfg);
350 clk_hz /= ((main_cfg->nocclk >>
351 CLKMGR_MAINPLL_NOCCLK_PERICNT_LSB) &
352 CLKMGR_MAINPLL_NOCCLK_CNT_MSK) + 1;
353 break;
354 case CLKMGR_MAINPLL_NOCCLK_SRC_OSC1:
355 clk_hz = eosc1_hz;
356 break;
357 case CLKMGR_MAINPLL_NOCCLK_SRC_INTOSC:
358 clk_hz = cb_intosc_hz;
359 break;
360 case CLKMGR_MAINPLL_NOCCLK_SRC_FPGA:
361 clk_hz = f2s_free_hz;
362 break;
363 default:
364 return 0;
365 }
366
367 clk_hz /= main_cfg->nocclk_cnt + 1;
368 return clk_hz;
369}
370
371/* return 1 if PLL ramp is required */
372static int cm_is_pll_ramp_required(int main0periph1,
373 struct mainpll_cfg *main_cfg,
374 struct perpll_cfg *per_cfg)
375{
376 /* Check for main PLL */
377 if (main0periph1 == 0) {
378 /*
379 * PLL ramp is not required if both MPU clock and NOC clock are
380 * not sourced from main PLL
381 */
382 if (main_cfg->mpuclk_src != CLKMGR_MAINPLL_MPUCLK_SRC_MAIN &&
383 main_cfg->nocclk_src != CLKMGR_MAINPLL_NOCCLK_SRC_MAIN)
384 return 0;
385
386 /*
387 * PLL ramp is required if MPU clock is sourced from main PLL
388 * and MPU clock is over 900MHz (as advised by HW team)
389 */
390 if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_MAIN &&
391 (cm_calc_handoff_mpu_clk_hz(main_cfg, per_cfg) >
392 CLKMGR_PLL_RAMP_MPUCLK_THRESHOLD_HZ))
393 return 1;
394
395 /*
396 * PLL ramp is required if NOC clock is sourced from main PLL
397 * and NOC clock is over 300MHz (as advised by HW team)
398 */
399 if (main_cfg->nocclk_src == CLKMGR_MAINPLL_NOCCLK_SRC_MAIN &&
400 (cm_calc_handoff_noc_clk_hz(main_cfg, per_cfg) >
401 CLKMGR_PLL_RAMP_NOCCLK_THRESHOLD_HZ))
402 return 2;
403
404 } else if (main0periph1 == 1) {
405 /*
406 * PLL ramp is not required if both MPU clock and NOC clock are
407 * not sourced from periph PLL
408 */
409 if (main_cfg->mpuclk_src != CLKMGR_MAINPLL_MPUCLK_SRC_PERI &&
410 main_cfg->nocclk_src != CLKMGR_MAINPLL_NOCCLK_SRC_PERI)
411 return 0;
412
413 /*
414 * PLL ramp is required if MPU clock are source from periph PLL
415 * and MPU clock is over 900MHz (as advised by HW team)
416 */
417 if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_PERI &&
418 (cm_calc_handoff_mpu_clk_hz(main_cfg, per_cfg) >
419 CLKMGR_PLL_RAMP_MPUCLK_THRESHOLD_HZ))
420 return 1;
421
422 /*
423 * PLL ramp is required if NOC clock are source from periph PLL
424 * and NOC clock is over 300MHz (as advised by HW team)
425 */
426 if (main_cfg->nocclk_src == CLKMGR_MAINPLL_NOCCLK_SRC_PERI &&
427 (cm_calc_handoff_noc_clk_hz(main_cfg, per_cfg) >
428 CLKMGR_PLL_RAMP_NOCCLK_THRESHOLD_HZ))
429 return 2;
430 }
431
432 return 0;
433}
434
435static u32 cm_calculate_numer(struct mainpll_cfg *main_cfg,
436 struct perpll_cfg *per_cfg,
437 u32 safe_hz, u32 clk_hz)
438{
439 u32 cnt;
440 u32 clk;
441 u32 shift;
442 u32 mask;
443 u32 denom;
444
445 if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_MAIN) {
446 cnt = main_cfg->mpuclk_cnt;
447 clk = main_cfg->mpuclk;
448 shift = 0;
449 mask = CLKMGR_MAINPLL_MPUCLK_CNT_MSK;
450 denom = main_cfg->vco1_denom;
451 } else if (main_cfg->nocclk_src == CLKMGR_MAINPLL_NOCCLK_SRC_MAIN) {
452 cnt = main_cfg->nocclk_cnt;
453 clk = main_cfg->nocclk;
454 shift = 0;
455 mask = CLKMGR_MAINPLL_NOCCLK_CNT_MSK;
456 denom = main_cfg->vco1_denom;
457 } else if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_PERI) {
458 cnt = main_cfg->mpuclk_cnt;
459 clk = main_cfg->mpuclk;
460 shift = CLKMGR_MAINPLL_MPUCLK_PERICNT_LSB;
461 mask = CLKMGR_MAINPLL_MPUCLK_CNT_MSK;
462 denom = per_cfg->vco1_denom;
463 } else if (main_cfg->nocclk_src == CLKMGR_MAINPLL_NOCCLK_SRC_PERI) {
464 cnt = main_cfg->nocclk_cnt;
465 clk = main_cfg->nocclk;
466 shift = CLKMGR_MAINPLL_NOCCLK_PERICNT_LSB;
467 mask = CLKMGR_MAINPLL_NOCCLK_CNT_MSK;
468 denom = per_cfg->vco1_denom;
469 } else {
470 return 0;
471 }
472
473 return (safe_hz / clk_hz) * (cnt + 1) * (((clk >> shift) & mask) + 1) *
474 (1 + denom) - 1;
475}
476
477/*
478 * Calculate the new PLL numerator which is based on existing DTS hand off and
479 * intended safe frequency (safe_hz). Note that PLL ramp is only modifying the
480 * numerator while maintaining denominator as denominator will influence the
481 * jitter condition. Please refer A10 HPS TRM for the jitter guide. Note final
482 * value for numerator is minus with 1 to cater our register value
483 * representation.
484 */
485static unsigned int cm_calc_safe_pll_numer(int main0periph1,
486 struct mainpll_cfg *main_cfg,
487 struct perpll_cfg *per_cfg,
488 unsigned int safe_hz)
489{
490 unsigned int clk_hz = 0;
491
492 /* Check for main PLL */
493 if (main0periph1 == 0) {
494 /* Check main VCO clock source: eosc, intosc or f2s? */
495 switch (main_cfg->vco0_psrc) {
496 case CLKMGR_MAINPLL_VCO0_PSRC_EOSC:
497 clk_hz = eosc1_hz;
498 break;
499 case CLKMGR_MAINPLL_VCO0_PSRC_E_INTOSC:
500 clk_hz = cb_intosc_hz;
501 break;
502 case CLKMGR_MAINPLL_VCO0_PSRC_F2S:
503 clk_hz = f2s_free_hz;
504 break;
505 default:
506 return 0;
507 }
508 } else if (main0periph1 == 1) {
509 /* Check periph VCO clock source: eosc, intosc, f2s, mainpll */
510 switch (per_cfg->vco0_psrc) {
511 case CLKMGR_PERPLL_VCO0_PSRC_EOSC:
512 clk_hz = eosc1_hz;
513 break;
514 case CLKMGR_PERPLL_VCO0_PSRC_E_INTOSC:
515 clk_hz = cb_intosc_hz;
516 break;
517 case CLKMGR_PERPLL_VCO0_PSRC_F2S:
518 clk_hz = f2s_free_hz;
519 break;
520 case CLKMGR_PERPLL_VCO0_PSRC_MAIN:
521 clk_hz = cm_calc_handoff_main_vco_clk_hz(main_cfg);
522 clk_hz /= main_cfg->cntr15clk_cnt;
523 break;
524 default:
525 return 0;
526 }
527 } else {
528 return 0;
529 }
530
531 return cm_calculate_numer(main_cfg, per_cfg, safe_hz, clk_hz);
532}
533
534/* ramping the main PLL to final value */
535static void cm_pll_ramp_main(struct mainpll_cfg *main_cfg,
536 struct perpll_cfg *per_cfg,
537 unsigned int pll_ramp_main_hz)
538{
539 unsigned int clk_hz = 0, clk_incr_hz = 0, clk_final_hz = 0;
540
541 /* find out the increment value */
542 if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_MAIN) {
543 clk_incr_hz = CLKMGR_PLL_RAMP_MPUCLK_INCREMENT_HZ;
544 clk_final_hz = cm_calc_handoff_mpu_clk_hz(main_cfg, per_cfg);
545 } else if (main_cfg->nocclk_src == CLKMGR_MAINPLL_NOCCLK_SRC_MAIN) {
546 clk_incr_hz = CLKMGR_PLL_RAMP_NOCCLK_INCREMENT_HZ;
547 clk_final_hz = cm_calc_handoff_noc_clk_hz(main_cfg, per_cfg);
548 }
549
550 /* execute the ramping here */
551 for (clk_hz = pll_ramp_main_hz + clk_incr_hz;
552 clk_hz < clk_final_hz; clk_hz += clk_incr_hz) {
553 writel((main_cfg->vco1_denom <<
554 CLKMGR_MAINPLL_VCO1_DENOM_LSB) |
555 cm_calc_safe_pll_numer(0, main_cfg, per_cfg, clk_hz),
Ley Foon Tan26695912019-11-08 10:38:21 +0800556 socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO1);
Paweł Anikiel3dad5752022-06-17 12:47:23 +0200557 sdelay(1000000); /* 1ms */
Ley Foon Tanca40f292017-04-26 02:44:39 +0800558 cm_wait_for_lock(LOCKED_MASK);
559 }
560 writel((main_cfg->vco1_denom << CLKMGR_MAINPLL_VCO1_DENOM_LSB) |
Ley Foon Tan26695912019-11-08 10:38:21 +0800561 main_cfg->vco1_numer,
562 socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO1);
Paweł Anikiel3dad5752022-06-17 12:47:23 +0200563 sdelay(1000000); /* 1ms */
Ley Foon Tanca40f292017-04-26 02:44:39 +0800564 cm_wait_for_lock(LOCKED_MASK);
565}
566
567/* ramping the periph PLL to final value */
568static void cm_pll_ramp_periph(struct mainpll_cfg *main_cfg,
569 struct perpll_cfg *per_cfg,
570 unsigned int pll_ramp_periph_hz)
571{
572 unsigned int clk_hz = 0, clk_incr_hz = 0, clk_final_hz = 0;
573
574 /* find out the increment value */
575 if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_PERI) {
576 clk_incr_hz = CLKMGR_PLL_RAMP_MPUCLK_INCREMENT_HZ;
577 clk_final_hz = cm_calc_handoff_mpu_clk_hz(main_cfg, per_cfg);
578 } else if (main_cfg->nocclk_src == CLKMGR_MAINPLL_NOCCLK_SRC_PERI) {
579 clk_incr_hz = CLKMGR_PLL_RAMP_NOCCLK_INCREMENT_HZ;
580 clk_final_hz = cm_calc_handoff_noc_clk_hz(main_cfg, per_cfg);
581 }
582 /* execute the ramping here */
583 for (clk_hz = pll_ramp_periph_hz + clk_incr_hz;
584 clk_hz < clk_final_hz; clk_hz += clk_incr_hz) {
Ley Foon Tan26695912019-11-08 10:38:21 +0800585 writel((per_cfg->vco1_denom <<
586 CLKMGR_PERPLL_VCO1_DENOM_LSB) |
587 cm_calc_safe_pll_numer(1, main_cfg, per_cfg,
588 clk_hz),
589 socfpga_get_clkmgr_addr() +
590 CLKMGR_A10_PERPLL_VCO1);
Paweł Anikiel3dad5752022-06-17 12:47:23 +0200591 sdelay(1000000); /* 1ms */
Ley Foon Tanca40f292017-04-26 02:44:39 +0800592 cm_wait_for_lock(LOCKED_MASK);
593 }
594 writel((per_cfg->vco1_denom << CLKMGR_PERPLL_VCO1_DENOM_LSB) |
Ley Foon Tan26695912019-11-08 10:38:21 +0800595 per_cfg->vco1_numer,
596 socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO1);
Paweł Anikiel3dad5752022-06-17 12:47:23 +0200597 sdelay(1000000); /* 1ms */
Ley Foon Tanca40f292017-04-26 02:44:39 +0800598 cm_wait_for_lock(LOCKED_MASK);
599}
600
Paweł Anikiel3dad5752022-06-17 12:47:23 +0200601/* function to poll in the fsm busy bit */
602static int cm_busy_wait_for_fsm(void)
603{
604 void *reg = (void *)(socfpga_get_clkmgr_addr() + CLKMGR_STAT);
605
606 /* 20s timeout */
607 return wait_on_value(CLKMGR_STAT_BUSY, 0, reg, 100000000);
608}
609
Ley Foon Tanca40f292017-04-26 02:44:39 +0800610/*
611 * Setup clocks while making no assumptions of the
612 * previous state of the clocks.
613 *
614 * Start by being paranoid and gate all sw managed clocks
615 *
616 * Put all plls in bypass
617 *
618 * Put all plls VCO registers back to reset value (bgpwr dwn).
619 *
620 * Put peripheral and main pll src to reset value to avoid glitch.
621 *
622 * Delay 5 us.
623 *
624 * Deassert bg pwr dn and set numerator and denominator
625 *
626 * Start 7 us timer.
627 *
628 * set internal dividers
629 *
630 * Wait for 7 us timer.
631 *
632 * Enable plls
633 *
634 * Set external dividers while plls are locking
635 *
636 * Wait for pll lock
637 *
638 * Assert/deassert outreset all.
639 *
640 * Take all pll's out of bypass
641 *
642 * Clear safe mode
643 *
644 * set source main and peripheral clocks
645 *
646 * Ungate clocks
647 */
648
649static int cm_full_cfg(struct mainpll_cfg *main_cfg, struct perpll_cfg *per_cfg)
650{
651 unsigned int pll_ramp_main_hz = 0, pll_ramp_periph_hz = 0,
652 ramp_required;
653
654 /* gate off all mainpll clock excpet HW managed clock */
655 writel(CLKMGR_MAINPLL_EN_S2FUSER0CLKEN_SET_MSK |
656 CLKMGR_MAINPLL_EN_HMCPLLREFCLKEN_SET_MSK,
Ley Foon Tan26695912019-11-08 10:38:21 +0800657 socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_ENR);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800658
659 /* now we can gate off the rest of the peripheral clocks */
Ley Foon Tan26695912019-11-08 10:38:21 +0800660 writel(0, socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_EN);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800661
662 /* Put all plls in external bypass */
663 writel(CLKMGR_MAINPLL_BYPASS_RESET,
Ley Foon Tan26695912019-11-08 10:38:21 +0800664 socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_BYPASSS);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800665 writel(CLKMGR_PERPLL_BYPASS_RESET,
Ley Foon Tan26695912019-11-08 10:38:21 +0800666 socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_BYPASSS);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800667
668 /*
669 * Put all plls VCO registers back to reset value.
670 * Some code might have messed with them. At same time set the
671 * desired clock source
672 */
673 writel(CLKMGR_MAINPLL_VCO0_RESET |
674 CLKMGR_MAINPLL_VCO0_REGEXTSEL_SET_MSK |
675 (main_cfg->vco0_psrc << CLKMGR_MAINPLL_VCO0_PSRC_LSB),
Ley Foon Tan26695912019-11-08 10:38:21 +0800676 socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO0);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800677
678 writel(CLKMGR_PERPLL_VCO0_RESET |
679 CLKMGR_PERPLL_VCO0_REGEXTSEL_SET_MSK |
680 (per_cfg->vco0_psrc << CLKMGR_PERPLL_VCO0_PSRC_LSB),
Ley Foon Tan26695912019-11-08 10:38:21 +0800681 socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO0);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800682
Ley Foon Tan26695912019-11-08 10:38:21 +0800683 writel(CLKMGR_MAINPLL_VCO1_RESET,
684 socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO1);
685 writel(CLKMGR_PERPLL_VCO1_RESET,
686 socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO1);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800687
688 /* clear the interrupt register status register */
689 writel(CLKMGR_CLKMGR_INTR_MAINPLLLOST_SET_MSK |
690 CLKMGR_CLKMGR_INTR_PERPLLLOST_SET_MSK |
691 CLKMGR_CLKMGR_INTR_MAINPLLRFSLIP_SET_MSK |
692 CLKMGR_CLKMGR_INTR_PERPLLRFSLIP_SET_MSK |
693 CLKMGR_CLKMGR_INTR_MAINPLLFBSLIP_SET_MSK |
694 CLKMGR_CLKMGR_INTR_PERPLLFBSLIP_SET_MSK |
695 CLKMGR_CLKMGR_INTR_MAINPLLACHIEVED_SET_MSK |
696 CLKMGR_CLKMGR_INTR_PERPLLACHIEVED_SET_MSK,
Ley Foon Tan26695912019-11-08 10:38:21 +0800697 socfpga_get_clkmgr_addr() + CLKMGR_A10_INTR);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800698
699 /* Program VCO Numerator and Denominator for main PLL */
700 ramp_required = cm_is_pll_ramp_required(0, main_cfg, per_cfg);
701 if (ramp_required) {
702 /* set main PLL to safe starting threshold frequency */
703 if (ramp_required == 1)
704 pll_ramp_main_hz = CLKMGR_PLL_RAMP_MPUCLK_THRESHOLD_HZ;
705 else if (ramp_required == 2)
706 pll_ramp_main_hz = CLKMGR_PLL_RAMP_NOCCLK_THRESHOLD_HZ;
707
Ley Foon Tan26695912019-11-08 10:38:21 +0800708 writel((main_cfg->vco1_denom <<
709 CLKMGR_MAINPLL_VCO1_DENOM_LSB) |
Ley Foon Tanca40f292017-04-26 02:44:39 +0800710 cm_calc_safe_pll_numer(0, main_cfg, per_cfg,
711 pll_ramp_main_hz),
Ley Foon Tan26695912019-11-08 10:38:21 +0800712 socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO1);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800713 } else
Ley Foon Tan26695912019-11-08 10:38:21 +0800714 writel((main_cfg->vco1_denom <<
715 CLKMGR_MAINPLL_VCO1_DENOM_LSB) |
716 main_cfg->vco1_numer,
717 socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO1);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800718
719 /* Program VCO Numerator and Denominator for periph PLL */
720 ramp_required = cm_is_pll_ramp_required(1, main_cfg, per_cfg);
721 if (ramp_required) {
722 /* set periph PLL to safe starting threshold frequency */
723 if (ramp_required == 1)
724 pll_ramp_periph_hz =
725 CLKMGR_PLL_RAMP_MPUCLK_THRESHOLD_HZ;
726 else if (ramp_required == 2)
727 pll_ramp_periph_hz =
728 CLKMGR_PLL_RAMP_NOCCLK_THRESHOLD_HZ;
729
Ley Foon Tan26695912019-11-08 10:38:21 +0800730 writel((per_cfg->vco1_denom <<
731 CLKMGR_PERPLL_VCO1_DENOM_LSB) |
Ley Foon Tanca40f292017-04-26 02:44:39 +0800732 cm_calc_safe_pll_numer(1, main_cfg, per_cfg,
733 pll_ramp_periph_hz),
Ley Foon Tan26695912019-11-08 10:38:21 +0800734 socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO1);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800735 } else
Ley Foon Tan26695912019-11-08 10:38:21 +0800736 writel((per_cfg->vco1_denom <<
737 CLKMGR_PERPLL_VCO1_DENOM_LSB) |
Ley Foon Tanca40f292017-04-26 02:44:39 +0800738 per_cfg->vco1_numer,
Ley Foon Tan26695912019-11-08 10:38:21 +0800739 socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO1);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800740
741 /* Wait for at least 5 us */
Paweł Anikiel3dad5752022-06-17 12:47:23 +0200742 sdelay(5000);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800743
744 /* Now deassert BGPWRDN and PWRDN */
Ley Foon Tan26695912019-11-08 10:38:21 +0800745 clrbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO0,
Ley Foon Tanca40f292017-04-26 02:44:39 +0800746 CLKMGR_MAINPLL_VCO0_BGPWRDN_SET_MSK |
747 CLKMGR_MAINPLL_VCO0_PWRDN_SET_MSK);
Ley Foon Tan26695912019-11-08 10:38:21 +0800748 clrbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO0,
Ley Foon Tanca40f292017-04-26 02:44:39 +0800749 CLKMGR_PERPLL_VCO0_BGPWRDN_SET_MSK |
750 CLKMGR_PERPLL_VCO0_PWRDN_SET_MSK);
751
752 /* Wait for at least 7 us */
Paweł Anikiel3dad5752022-06-17 12:47:23 +0200753 sdelay(7000);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800754
755 /* enable the VCO and disable the external regulator to PLL */
Ley Foon Tan26695912019-11-08 10:38:21 +0800756 writel((readl(socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO0) &
Ley Foon Tanca40f292017-04-26 02:44:39 +0800757 ~CLKMGR_MAINPLL_VCO0_REGEXTSEL_SET_MSK) |
758 CLKMGR_MAINPLL_VCO0_EN_SET_MSK,
Ley Foon Tan26695912019-11-08 10:38:21 +0800759 socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO0);
760 writel((readl(socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO0) &
Ley Foon Tanca40f292017-04-26 02:44:39 +0800761 ~CLKMGR_PERPLL_VCO0_REGEXTSEL_SET_MSK) |
762 CLKMGR_PERPLL_VCO0_EN_SET_MSK,
Ley Foon Tan26695912019-11-08 10:38:21 +0800763 socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO0);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800764
765 /* setup all the main PLL counter and clock source */
766 writel(main_cfg->nocclk,
Ley Foon Tan26695912019-11-08 10:38:21 +0800767 socfpga_get_clkmgr_addr() + CLKMGR_A10_ALTR_NOCCLK);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800768 writel(main_cfg->mpuclk,
Ley Foon Tan26695912019-11-08 10:38:21 +0800769 socfpga_get_clkmgr_addr() + CLKMGR_A10_ALTR_MPUCLK);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800770
771 /* main_emaca_clk divider */
Ley Foon Tan26695912019-11-08 10:38:21 +0800772 writel(main_cfg->cntr2clk_cnt,
773 socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_CNTR2CLK);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800774 /* main_emacb_clk divider */
Ley Foon Tan26695912019-11-08 10:38:21 +0800775 writel(main_cfg->cntr3clk_cnt,
776 socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_CNTR3CLK);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800777 /* main_emac_ptp_clk divider */
Ley Foon Tan26695912019-11-08 10:38:21 +0800778 writel(main_cfg->cntr4clk_cnt,
779 socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_CNTR4CLK);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800780 /* main_gpio_db_clk divider */
Ley Foon Tan26695912019-11-08 10:38:21 +0800781 writel(main_cfg->cntr5clk_cnt,
782 socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_CNTR5CLK);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800783 /* main_sdmmc_clk divider */
Ley Foon Tan26695912019-11-08 10:38:21 +0800784 writel(main_cfg->cntr6clk_cnt,
785 socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_CNTR6CLK);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800786 /* main_s2f_user0_clk divider */
787 writel(main_cfg->cntr7clk_cnt |
788 (main_cfg->cntr7clk_src << CLKMGR_MAINPLL_CNTR7CLK_SRC_LSB),
Ley Foon Tan26695912019-11-08 10:38:21 +0800789 socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_CNTR7CLK);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800790 /* main_s2f_user1_clk divider */
Ley Foon Tan26695912019-11-08 10:38:21 +0800791 writel(main_cfg->cntr8clk_cnt,
792 socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_CNTR8CLK);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800793 /* main_hmc_pll_clk divider */
794 writel(main_cfg->cntr9clk_cnt |
795 (main_cfg->cntr9clk_src << CLKMGR_MAINPLL_CNTR9CLK_SRC_LSB),
Ley Foon Tan26695912019-11-08 10:38:21 +0800796 socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_CNTR9CLK);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800797 /* main_periph_ref_clk divider */
798 writel(main_cfg->cntr15clk_cnt,
Ley Foon Tan26695912019-11-08 10:38:21 +0800799 socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_CNTR15CLK);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800800
801 /* setup all the peripheral PLL counter and clock source */
802 /* peri_emaca_clk divider */
803 writel(per_cfg->cntr2clk_cnt |
804 (per_cfg->cntr2clk_src << CLKMGR_PERPLL_CNTR2CLK_SRC_LSB),
Ley Foon Tan26695912019-11-08 10:38:21 +0800805 socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_CNTR2CLK);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800806 /* peri_emacb_clk divider */
807 writel(per_cfg->cntr3clk_cnt |
808 (per_cfg->cntr3clk_src << CLKMGR_PERPLL_CNTR3CLK_SRC_LSB),
Ley Foon Tan26695912019-11-08 10:38:21 +0800809 socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_CNTR3CLK);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800810 /* peri_emac_ptp_clk divider */
811 writel(per_cfg->cntr4clk_cnt |
812 (per_cfg->cntr4clk_src << CLKMGR_PERPLL_CNTR4CLK_SRC_LSB),
Ley Foon Tan26695912019-11-08 10:38:21 +0800813 socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_CNTR4CLK);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800814 /* peri_gpio_db_clk divider */
815 writel(per_cfg->cntr5clk_cnt |
816 (per_cfg->cntr5clk_src << CLKMGR_PERPLL_CNTR5CLK_SRC_LSB),
Ley Foon Tan26695912019-11-08 10:38:21 +0800817 socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_CNTR5CLK);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800818 /* peri_sdmmc_clk divider */
819 writel(per_cfg->cntr6clk_cnt |
820 (per_cfg->cntr6clk_src << CLKMGR_PERPLL_CNTR6CLK_SRC_LSB),
Ley Foon Tan26695912019-11-08 10:38:21 +0800821 socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_CNTR6CLK);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800822 /* peri_s2f_user0_clk divider */
Ley Foon Tan26695912019-11-08 10:38:21 +0800823 writel(per_cfg->cntr7clk_cnt,
824 socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_CNTR7CLK);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800825 /* peri_s2f_user1_clk divider */
826 writel(per_cfg->cntr8clk_cnt |
827 (per_cfg->cntr8clk_src << CLKMGR_PERPLL_CNTR8CLK_SRC_LSB),
Ley Foon Tan26695912019-11-08 10:38:21 +0800828 socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_CNTR8CLK);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800829 /* peri_hmc_pll_clk divider */
Ley Foon Tan26695912019-11-08 10:38:21 +0800830 writel(per_cfg->cntr9clk_cnt,
831 socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_CNTR9CLK);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800832
833 /* setup all the external PLL counter */
834 /* mpu wrapper / external divider */
835 writel(main_cfg->mpuclk_cnt |
836 (main_cfg->mpuclk_src << CLKMGR_MAINPLL_MPUCLK_SRC_LSB),
Ley Foon Tan26695912019-11-08 10:38:21 +0800837 socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_MPUCLK);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800838 /* NOC wrapper / external divider */
839 writel(main_cfg->nocclk_cnt |
840 (main_cfg->nocclk_src << CLKMGR_MAINPLL_NOCCLK_SRC_LSB),
Ley Foon Tan26695912019-11-08 10:38:21 +0800841 socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_NOCCLK);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800842 /* NOC subclock divider such as l4 */
843 writel(main_cfg->nocdiv_l4mainclk |
844 (main_cfg->nocdiv_l4mpclk <<
845 CLKMGR_MAINPLL_NOCDIV_L4MPCLK_LSB) |
846 (main_cfg->nocdiv_l4spclk <<
847 CLKMGR_MAINPLL_NOCDIV_L4SPCLK_LSB) |
848 (main_cfg->nocdiv_csatclk <<
849 CLKMGR_MAINPLL_NOCDIV_CSATCLK_LSB) |
850 (main_cfg->nocdiv_cstraceclk <<
851 CLKMGR_MAINPLL_NOCDIV_CSTRACECLK_LSB) |
852 (main_cfg->nocdiv_cspdbclk <<
853 CLKMGR_MAINPLL_NOCDIV_CSPDBGCLK_LSB),
Ley Foon Tan26695912019-11-08 10:38:21 +0800854 socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_NOCDIV);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800855 /* gpio_db external divider */
856 writel(per_cfg->gpiodiv_gpiodbclk,
Ley Foon Tan26695912019-11-08 10:38:21 +0800857 socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_GPIOFIV);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800858
859 /* setup the EMAC clock mux select */
860 writel((per_cfg->emacctl_emac0sel <<
861 CLKMGR_PERPLL_EMACCTL_EMAC0SEL_LSB) |
862 (per_cfg->emacctl_emac1sel <<
863 CLKMGR_PERPLL_EMACCTL_EMAC1SEL_LSB) |
864 (per_cfg->emacctl_emac2sel <<
865 CLKMGR_PERPLL_EMACCTL_EMAC2SEL_LSB),
Ley Foon Tan26695912019-11-08 10:38:21 +0800866 socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_EMACCTL);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800867
868 /* at this stage, check for PLL lock status */
869 cm_wait_for_lock(LOCKED_MASK);
870
871 /*
872 * after locking, but before taking out of bypass,
873 * assert/deassert outresetall
874 */
875 /* assert mainpll outresetall */
Ley Foon Tan26695912019-11-08 10:38:21 +0800876 setbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO0,
Ley Foon Tanca40f292017-04-26 02:44:39 +0800877 CLKMGR_MAINPLL_VCO0_OUTRSTALL_SET_MSK);
878 /* assert perpll outresetall */
Ley Foon Tan26695912019-11-08 10:38:21 +0800879 setbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO0,
Ley Foon Tanca40f292017-04-26 02:44:39 +0800880 CLKMGR_PERPLL_VCO0_OUTRSTALL_SET_MSK);
881 /* de-assert mainpll outresetall */
Ley Foon Tan26695912019-11-08 10:38:21 +0800882 clrbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO0,
Ley Foon Tanca40f292017-04-26 02:44:39 +0800883 CLKMGR_MAINPLL_VCO0_OUTRSTALL_SET_MSK);
884 /* de-assert perpll outresetall */
Ley Foon Tan26695912019-11-08 10:38:21 +0800885 clrbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO0,
Ley Foon Tanca40f292017-04-26 02:44:39 +0800886 CLKMGR_PERPLL_VCO0_OUTRSTALL_SET_MSK);
887
888 /* Take all PLLs out of bypass when boot mode is cleared. */
889 /* release mainpll from bypass */
890 writel(CLKMGR_MAINPLL_BYPASS_RESET,
Ley Foon Tan26695912019-11-08 10:38:21 +0800891 socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_BYPASSR);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800892 /* wait till Clock Manager is not busy */
Paweł Anikiel3dad5752022-06-17 12:47:23 +0200893 cm_busy_wait_for_fsm();
Ley Foon Tanca40f292017-04-26 02:44:39 +0800894
895 /* release perpll from bypass */
896 writel(CLKMGR_PERPLL_BYPASS_RESET,
Ley Foon Tan26695912019-11-08 10:38:21 +0800897 socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_BYPASSR);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800898 /* wait till Clock Manager is not busy */
Paweł Anikiel3dad5752022-06-17 12:47:23 +0200899 cm_busy_wait_for_fsm();
Ley Foon Tanca40f292017-04-26 02:44:39 +0800900
901 /* clear boot mode */
Ley Foon Tan26695912019-11-08 10:38:21 +0800902 clrbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_A10_CTRL,
Ley Foon Tanca40f292017-04-26 02:44:39 +0800903 CLKMGR_CLKMGR_CTL_BOOTMOD_SET_MSK);
904 /* wait till Clock Manager is not busy */
Paweł Anikiel3dad5752022-06-17 12:47:23 +0200905 cm_busy_wait_for_fsm();
Ley Foon Tanca40f292017-04-26 02:44:39 +0800906
907 /* At here, we need to ramp to final value if needed */
908 if (pll_ramp_main_hz != 0)
909 cm_pll_ramp_main(main_cfg, per_cfg, pll_ramp_main_hz);
910 if (pll_ramp_periph_hz != 0)
911 cm_pll_ramp_periph(main_cfg, per_cfg, pll_ramp_periph_hz);
912
913 /* Now ungate non-hw-managed clocks */
914 writel(CLKMGR_MAINPLL_EN_S2FUSER0CLKEN_SET_MSK |
Ley Foon Tan26695912019-11-08 10:38:21 +0800915 CLKMGR_MAINPLL_EN_HMCPLLREFCLKEN_SET_MSK,
916 socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_ENS);
917 writel(CLKMGR_PERPLL_EN_RESET,
918 socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_ENS);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800919
920 /* Clear the loss lock and slip bits as they might set during
921 clock reconfiguration */
922 writel(CLKMGR_CLKMGR_INTR_MAINPLLLOST_SET_MSK |
923 CLKMGR_CLKMGR_INTR_PERPLLLOST_SET_MSK |
924 CLKMGR_CLKMGR_INTR_MAINPLLRFSLIP_SET_MSK |
925 CLKMGR_CLKMGR_INTR_PERPLLRFSLIP_SET_MSK |
926 CLKMGR_CLKMGR_INTR_MAINPLLFBSLIP_SET_MSK |
927 CLKMGR_CLKMGR_INTR_PERPLLFBSLIP_SET_MSK,
Ley Foon Tan26695912019-11-08 10:38:21 +0800928 socfpga_get_clkmgr_addr() + CLKMGR_A10_INTR);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800929
930 return 0;
931}
932
Marek Vasut8fdb4192018-08-18 19:11:52 +0200933static void cm_use_intosc(void)
Ley Foon Tanca40f292017-04-26 02:44:39 +0800934{
Ley Foon Tan26695912019-11-08 10:38:21 +0800935 setbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_A10_CTRL,
Ley Foon Tanca40f292017-04-26 02:44:39 +0800936 CLKMGR_CLKMGR_CTL_BOOTCLK_INTOSC_SET_MSK);
937}
938
Ley Foon Tanca40f292017-04-26 02:44:39 +0800939int cm_basic_init(const void *blob)
940{
941 struct mainpll_cfg main_cfg;
942 struct perpll_cfg per_cfg;
Ley Foon Tanca40f292017-04-26 02:44:39 +0800943 int rval;
944
945 /* initialize to zero for use case of optional node */
946 memset(&main_cfg, 0, sizeof(main_cfg));
947 memset(&per_cfg, 0, sizeof(per_cfg));
Ley Foon Tanca40f292017-04-26 02:44:39 +0800948
Marek Vasutec472e02018-05-12 00:09:21 +0200949 rval = of_get_clk_cfg(blob, &main_cfg, &per_cfg);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800950 if (rval)
951 return rval;
952
Marek Vasut8fdb4192018-08-18 19:11:52 +0200953 cm_use_intosc();
954
Marek Vasutfd6bcb52018-07-31 17:33:42 +0200955 return cm_full_cfg(&main_cfg, &per_cfg);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800956}
Marek Vasut8fdb4192018-08-18 19:11:52 +0200957#endif
Ley Foon Tanca40f292017-04-26 02:44:39 +0800958
Marek Vasut71b16372018-08-06 21:42:05 +0200959static u32 cm_get_rate_dm(char *name)
Ley Foon Tanca40f292017-04-26 02:44:39 +0800960{
Marek Vasut71b16372018-08-06 21:42:05 +0200961 struct uclass *uc;
962 struct udevice *dev = NULL;
963 struct clk clk = { 0 };
Marek Vasut71b16372018-08-06 21:42:05 +0200964 int ret;
Ley Foon Tanca40f292017-04-26 02:44:39 +0800965
Marek Vasut71b16372018-08-06 21:42:05 +0200966 /* Device addresses start at 1 */
967 ret = uclass_get(UCLASS_CLK, &uc);
968 if (ret)
Ley Foon Tanca40f292017-04-26 02:44:39 +0800969 return 0;
Ley Foon Tanca40f292017-04-26 02:44:39 +0800970
Marek Vasut71b16372018-08-06 21:42:05 +0200971 ret = uclass_get_device_by_name(UCLASS_CLK, name, &dev);
972 if (ret)
Ley Foon Tanca40f292017-04-26 02:44:39 +0800973 return 0;
Ley Foon Tanca40f292017-04-26 02:44:39 +0800974
Marek Vasut71b16372018-08-06 21:42:05 +0200975 ret = device_probe(dev);
976 if (ret)
Ley Foon Tanca40f292017-04-26 02:44:39 +0800977 return 0;
Ley Foon Tanca40f292017-04-26 02:44:39 +0800978
Marek Vasut71b16372018-08-06 21:42:05 +0200979 ret = clk_request(dev, &clk);
980 if (ret)
981 return 0;
Ley Foon Tanca40f292017-04-26 02:44:39 +0800982
Sean Andersond318eb32023-12-16 14:38:42 -0500983 return clk_get_rate(&clk);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800984}
985
Marek Vasut71b16372018-08-06 21:42:05 +0200986static u32 cm_get_rate_dm_khz(char *name)
Ley Foon Tanca40f292017-04-26 02:44:39 +0800987{
Marek Vasut71b16372018-08-06 21:42:05 +0200988 return cm_get_rate_dm(name) / 1000;
Ley Foon Tanca40f292017-04-26 02:44:39 +0800989}
990
Marek Vasut71b16372018-08-06 21:42:05 +0200991unsigned long cm_get_mpu_clk_hz(void)
Ley Foon Tanca40f292017-04-26 02:44:39 +0800992{
Marek Vasut71b16372018-08-06 21:42:05 +0200993 return cm_get_rate_dm("main_mpu_base_clk");
Ley Foon Tanca40f292017-04-26 02:44:39 +0800994}
995
996unsigned int cm_get_qspi_controller_clk_hz(void)
997{
Marek Vasut71b16372018-08-06 21:42:05 +0200998 return cm_get_rate_dm("qspi_clk");
Ley Foon Tanca40f292017-04-26 02:44:39 +0800999}
1000
Marek Vasut71b16372018-08-06 21:42:05 +02001001unsigned int cm_get_l4_sp_clk_hz(void)
Eugeniy Paltsev74739322017-12-28 15:09:02 +03001002{
Marek Vasut71b16372018-08-06 21:42:05 +02001003 return cm_get_rate_dm("l4_sp_clk");
Eugeniy Paltsev74739322017-12-28 15:09:02 +03001004}
1005
Ley Foon Tanca40f292017-04-26 02:44:39 +08001006void cm_print_clock_quick_summary(void)
1007{
Marek Vasut71b16372018-08-06 21:42:05 +02001008 printf("MPU %10d kHz\n", cm_get_rate_dm_khz("main_mpu_base_clk"));
1009 printf("MMC %8d kHz\n", cm_get_rate_dm_khz("sdmmc_clk"));
1010 printf("QSPI %8d kHz\n", cm_get_rate_dm_khz("qspi_clk"));
1011 printf("SPI %8d kHz\n", cm_get_rate_dm_khz("spi_m_clk"));
1012 printf("EOSC1 %8d kHz\n", cm_get_rate_dm_khz("osc1"));
1013 printf("cb_intosc %8d kHz\n", cm_get_rate_dm_khz("cb_intosc_ls_clk"));
1014 printf("f2s_free %8d kHz\n", cm_get_rate_dm_khz("f2s_free_clk"));
1015 printf("Main VCO %8d kHz\n", cm_get_rate_dm_khz("main_pll@40"));
1016 printf("NOC %8d kHz\n", cm_get_rate_dm_khz("main_noc_base_clk"));
1017 printf("L4 Main %8d kHz\n", cm_get_rate_dm_khz("l4_main_clk"));
1018 printf("L4 MP %8d kHz\n", cm_get_rate_dm_khz("l4_mp_clk"));
1019 printf("L4 SP %8d kHz\n", cm_get_rate_dm_khz("l4_sp_clk"));
1020 printf("L4 sys free %8d kHz\n", cm_get_rate_dm_khz("l4_sys_free_clk"));
Ley Foon Tanca40f292017-04-26 02:44:39 +08001021}