blob: cadb090387a4591b3fe0fa79b1a152b84170e412 [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
6#include <common.h>
7#include <fdtdec.h>
8#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>
13
Marek Vasutec472e02018-05-12 00:09:21 +020014static const struct socfpga_clock_manager *clock_manager_base =
15 (struct socfpga_clock_manager *)SOCFPGA_CLKMGR_ADDRESS;
16
Ley Foon Tanca40f292017-04-26 02:44:39 +080017static u32 eosc1_hz;
18static u32 cb_intosc_hz;
19static u32 f2s_free_hz;
20static u32 cm_l4_main_clk_hz;
21static u32 cm_l4_sp_clk_hz;
22static u32 cm_l4_mp_clk_hz;
23static u32 cm_l4_sys_free_clk_hz;
24
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),
556 &clock_manager_base->main_pll.vco1);
557 mdelay(1);
558 cm_wait_for_lock(LOCKED_MASK);
559 }
560 writel((main_cfg->vco1_denom << CLKMGR_MAINPLL_VCO1_DENOM_LSB) |
561 main_cfg->vco1_numer, &clock_manager_base->main_pll.vco1);
562 mdelay(1);
563 cm_wait_for_lock(LOCKED_MASK);
564}
565
566/* ramping the periph PLL to final value */
567static void cm_pll_ramp_periph(struct mainpll_cfg *main_cfg,
568 struct perpll_cfg *per_cfg,
569 unsigned int pll_ramp_periph_hz)
570{
571 unsigned int clk_hz = 0, clk_incr_hz = 0, clk_final_hz = 0;
572
573 /* find out the increment value */
574 if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_PERI) {
575 clk_incr_hz = CLKMGR_PLL_RAMP_MPUCLK_INCREMENT_HZ;
576 clk_final_hz = cm_calc_handoff_mpu_clk_hz(main_cfg, per_cfg);
577 } else if (main_cfg->nocclk_src == CLKMGR_MAINPLL_NOCCLK_SRC_PERI) {
578 clk_incr_hz = CLKMGR_PLL_RAMP_NOCCLK_INCREMENT_HZ;
579 clk_final_hz = cm_calc_handoff_noc_clk_hz(main_cfg, per_cfg);
580 }
581 /* execute the ramping here */
582 for (clk_hz = pll_ramp_periph_hz + clk_incr_hz;
583 clk_hz < clk_final_hz; clk_hz += clk_incr_hz) {
584 writel((per_cfg->vco1_denom << CLKMGR_PERPLL_VCO1_DENOM_LSB) |
585 cm_calc_safe_pll_numer(1, main_cfg, per_cfg, clk_hz),
586 &clock_manager_base->per_pll.vco1);
587 mdelay(1);
588 cm_wait_for_lock(LOCKED_MASK);
589 }
590 writel((per_cfg->vco1_denom << CLKMGR_PERPLL_VCO1_DENOM_LSB) |
591 per_cfg->vco1_numer, &clock_manager_base->per_pll.vco1);
592 mdelay(1);
593 cm_wait_for_lock(LOCKED_MASK);
594}
595
596/*
597 * Setup clocks while making no assumptions of the
598 * previous state of the clocks.
599 *
600 * Start by being paranoid and gate all sw managed clocks
601 *
602 * Put all plls in bypass
603 *
604 * Put all plls VCO registers back to reset value (bgpwr dwn).
605 *
606 * Put peripheral and main pll src to reset value to avoid glitch.
607 *
608 * Delay 5 us.
609 *
610 * Deassert bg pwr dn and set numerator and denominator
611 *
612 * Start 7 us timer.
613 *
614 * set internal dividers
615 *
616 * Wait for 7 us timer.
617 *
618 * Enable plls
619 *
620 * Set external dividers while plls are locking
621 *
622 * Wait for pll lock
623 *
624 * Assert/deassert outreset all.
625 *
626 * Take all pll's out of bypass
627 *
628 * Clear safe mode
629 *
630 * set source main and peripheral clocks
631 *
632 * Ungate clocks
633 */
634
635static int cm_full_cfg(struct mainpll_cfg *main_cfg, struct perpll_cfg *per_cfg)
636{
637 unsigned int pll_ramp_main_hz = 0, pll_ramp_periph_hz = 0,
638 ramp_required;
639
640 /* gate off all mainpll clock excpet HW managed clock */
641 writel(CLKMGR_MAINPLL_EN_S2FUSER0CLKEN_SET_MSK |
642 CLKMGR_MAINPLL_EN_HMCPLLREFCLKEN_SET_MSK,
643 &clock_manager_base->main_pll.enr);
644
645 /* now we can gate off the rest of the peripheral clocks */
646 writel(0, &clock_manager_base->per_pll.en);
647
648 /* Put all plls in external bypass */
649 writel(CLKMGR_MAINPLL_BYPASS_RESET,
650 &clock_manager_base->main_pll.bypasss);
651 writel(CLKMGR_PERPLL_BYPASS_RESET,
652 &clock_manager_base->per_pll.bypasss);
653
654 /*
655 * Put all plls VCO registers back to reset value.
656 * Some code might have messed with them. At same time set the
657 * desired clock source
658 */
659 writel(CLKMGR_MAINPLL_VCO0_RESET |
660 CLKMGR_MAINPLL_VCO0_REGEXTSEL_SET_MSK |
661 (main_cfg->vco0_psrc << CLKMGR_MAINPLL_VCO0_PSRC_LSB),
662 &clock_manager_base->main_pll.vco0);
663
664 writel(CLKMGR_PERPLL_VCO0_RESET |
665 CLKMGR_PERPLL_VCO0_REGEXTSEL_SET_MSK |
666 (per_cfg->vco0_psrc << CLKMGR_PERPLL_VCO0_PSRC_LSB),
667 &clock_manager_base->per_pll.vco0);
668
669 writel(CLKMGR_MAINPLL_VCO1_RESET, &clock_manager_base->main_pll.vco1);
670 writel(CLKMGR_PERPLL_VCO1_RESET, &clock_manager_base->per_pll.vco1);
671
672 /* clear the interrupt register status register */
673 writel(CLKMGR_CLKMGR_INTR_MAINPLLLOST_SET_MSK |
674 CLKMGR_CLKMGR_INTR_PERPLLLOST_SET_MSK |
675 CLKMGR_CLKMGR_INTR_MAINPLLRFSLIP_SET_MSK |
676 CLKMGR_CLKMGR_INTR_PERPLLRFSLIP_SET_MSK |
677 CLKMGR_CLKMGR_INTR_MAINPLLFBSLIP_SET_MSK |
678 CLKMGR_CLKMGR_INTR_PERPLLFBSLIP_SET_MSK |
679 CLKMGR_CLKMGR_INTR_MAINPLLACHIEVED_SET_MSK |
680 CLKMGR_CLKMGR_INTR_PERPLLACHIEVED_SET_MSK,
681 &clock_manager_base->intr);
682
683 /* Program VCO Numerator and Denominator for main PLL */
684 ramp_required = cm_is_pll_ramp_required(0, main_cfg, per_cfg);
685 if (ramp_required) {
686 /* set main PLL to safe starting threshold frequency */
687 if (ramp_required == 1)
688 pll_ramp_main_hz = CLKMGR_PLL_RAMP_MPUCLK_THRESHOLD_HZ;
689 else if (ramp_required == 2)
690 pll_ramp_main_hz = CLKMGR_PLL_RAMP_NOCCLK_THRESHOLD_HZ;
691
692 writel((main_cfg->vco1_denom << CLKMGR_MAINPLL_VCO1_DENOM_LSB) |
693 cm_calc_safe_pll_numer(0, main_cfg, per_cfg,
694 pll_ramp_main_hz),
695 &clock_manager_base->main_pll.vco1);
696 } else
697 writel((main_cfg->vco1_denom << CLKMGR_MAINPLL_VCO1_DENOM_LSB) |
698 main_cfg->vco1_numer,
699 &clock_manager_base->main_pll.vco1);
700
701 /* Program VCO Numerator and Denominator for periph PLL */
702 ramp_required = cm_is_pll_ramp_required(1, main_cfg, per_cfg);
703 if (ramp_required) {
704 /* set periph PLL to safe starting threshold frequency */
705 if (ramp_required == 1)
706 pll_ramp_periph_hz =
707 CLKMGR_PLL_RAMP_MPUCLK_THRESHOLD_HZ;
708 else if (ramp_required == 2)
709 pll_ramp_periph_hz =
710 CLKMGR_PLL_RAMP_NOCCLK_THRESHOLD_HZ;
711
712 writel((per_cfg->vco1_denom << CLKMGR_PERPLL_VCO1_DENOM_LSB) |
713 cm_calc_safe_pll_numer(1, main_cfg, per_cfg,
714 pll_ramp_periph_hz),
715 &clock_manager_base->per_pll.vco1);
716 } else
717 writel((per_cfg->vco1_denom << CLKMGR_PERPLL_VCO1_DENOM_LSB) |
718 per_cfg->vco1_numer,
719 &clock_manager_base->per_pll.vco1);
720
721 /* Wait for at least 5 us */
722 udelay(5);
723
724 /* Now deassert BGPWRDN and PWRDN */
725 clrbits_le32(&clock_manager_base->main_pll.vco0,
726 CLKMGR_MAINPLL_VCO0_BGPWRDN_SET_MSK |
727 CLKMGR_MAINPLL_VCO0_PWRDN_SET_MSK);
728 clrbits_le32(&clock_manager_base->per_pll.vco0,
729 CLKMGR_PERPLL_VCO0_BGPWRDN_SET_MSK |
730 CLKMGR_PERPLL_VCO0_PWRDN_SET_MSK);
731
732 /* Wait for at least 7 us */
733 udelay(7);
734
735 /* enable the VCO and disable the external regulator to PLL */
736 writel((readl(&clock_manager_base->main_pll.vco0) &
737 ~CLKMGR_MAINPLL_VCO0_REGEXTSEL_SET_MSK) |
738 CLKMGR_MAINPLL_VCO0_EN_SET_MSK,
739 &clock_manager_base->main_pll.vco0);
740 writel((readl(&clock_manager_base->per_pll.vco0) &
741 ~CLKMGR_PERPLL_VCO0_REGEXTSEL_SET_MSK) |
742 CLKMGR_PERPLL_VCO0_EN_SET_MSK,
743 &clock_manager_base->per_pll.vco0);
744
745 /* setup all the main PLL counter and clock source */
746 writel(main_cfg->nocclk,
747 SOCFPGA_CLKMGR_ADDRESS + CLKMGR_MAINPLL_NOC_CLK_OFFSET);
748 writel(main_cfg->mpuclk,
749 SOCFPGA_CLKMGR_ADDRESS + CLKMGR_ALTERAGRP_MPU_CLK_OFFSET);
750
751 /* main_emaca_clk divider */
752 writel(main_cfg->cntr2clk_cnt, &clock_manager_base->main_pll.cntr2clk);
753 /* main_emacb_clk divider */
754 writel(main_cfg->cntr3clk_cnt, &clock_manager_base->main_pll.cntr3clk);
755 /* main_emac_ptp_clk divider */
756 writel(main_cfg->cntr4clk_cnt, &clock_manager_base->main_pll.cntr4clk);
757 /* main_gpio_db_clk divider */
758 writel(main_cfg->cntr5clk_cnt, &clock_manager_base->main_pll.cntr5clk);
759 /* main_sdmmc_clk divider */
760 writel(main_cfg->cntr6clk_cnt, &clock_manager_base->main_pll.cntr6clk);
761 /* main_s2f_user0_clk divider */
762 writel(main_cfg->cntr7clk_cnt |
763 (main_cfg->cntr7clk_src << CLKMGR_MAINPLL_CNTR7CLK_SRC_LSB),
764 &clock_manager_base->main_pll.cntr7clk);
765 /* main_s2f_user1_clk divider */
766 writel(main_cfg->cntr8clk_cnt, &clock_manager_base->main_pll.cntr8clk);
767 /* main_hmc_pll_clk divider */
768 writel(main_cfg->cntr9clk_cnt |
769 (main_cfg->cntr9clk_src << CLKMGR_MAINPLL_CNTR9CLK_SRC_LSB),
770 &clock_manager_base->main_pll.cntr9clk);
771 /* main_periph_ref_clk divider */
772 writel(main_cfg->cntr15clk_cnt,
773 &clock_manager_base->main_pll.cntr15clk);
774
775 /* setup all the peripheral PLL counter and clock source */
776 /* peri_emaca_clk divider */
777 writel(per_cfg->cntr2clk_cnt |
778 (per_cfg->cntr2clk_src << CLKMGR_PERPLL_CNTR2CLK_SRC_LSB),
779 &clock_manager_base->per_pll.cntr2clk);
780 /* peri_emacb_clk divider */
781 writel(per_cfg->cntr3clk_cnt |
782 (per_cfg->cntr3clk_src << CLKMGR_PERPLL_CNTR3CLK_SRC_LSB),
783 &clock_manager_base->per_pll.cntr3clk);
784 /* peri_emac_ptp_clk divider */
785 writel(per_cfg->cntr4clk_cnt |
786 (per_cfg->cntr4clk_src << CLKMGR_PERPLL_CNTR4CLK_SRC_LSB),
787 &clock_manager_base->per_pll.cntr4clk);
788 /* peri_gpio_db_clk divider */
789 writel(per_cfg->cntr5clk_cnt |
790 (per_cfg->cntr5clk_src << CLKMGR_PERPLL_CNTR5CLK_SRC_LSB),
791 &clock_manager_base->per_pll.cntr5clk);
792 /* peri_sdmmc_clk divider */
793 writel(per_cfg->cntr6clk_cnt |
794 (per_cfg->cntr6clk_src << CLKMGR_PERPLL_CNTR6CLK_SRC_LSB),
795 &clock_manager_base->per_pll.cntr6clk);
796 /* peri_s2f_user0_clk divider */
797 writel(per_cfg->cntr7clk_cnt, &clock_manager_base->per_pll.cntr7clk);
798 /* peri_s2f_user1_clk divider */
799 writel(per_cfg->cntr8clk_cnt |
800 (per_cfg->cntr8clk_src << CLKMGR_PERPLL_CNTR8CLK_SRC_LSB),
801 &clock_manager_base->per_pll.cntr8clk);
802 /* peri_hmc_pll_clk divider */
803 writel(per_cfg->cntr9clk_cnt, &clock_manager_base->per_pll.cntr9clk);
804
805 /* setup all the external PLL counter */
806 /* mpu wrapper / external divider */
807 writel(main_cfg->mpuclk_cnt |
808 (main_cfg->mpuclk_src << CLKMGR_MAINPLL_MPUCLK_SRC_LSB),
809 &clock_manager_base->main_pll.mpuclk);
810 /* NOC wrapper / external divider */
811 writel(main_cfg->nocclk_cnt |
812 (main_cfg->nocclk_src << CLKMGR_MAINPLL_NOCCLK_SRC_LSB),
813 &clock_manager_base->main_pll.nocclk);
814 /* NOC subclock divider such as l4 */
815 writel(main_cfg->nocdiv_l4mainclk |
816 (main_cfg->nocdiv_l4mpclk <<
817 CLKMGR_MAINPLL_NOCDIV_L4MPCLK_LSB) |
818 (main_cfg->nocdiv_l4spclk <<
819 CLKMGR_MAINPLL_NOCDIV_L4SPCLK_LSB) |
820 (main_cfg->nocdiv_csatclk <<
821 CLKMGR_MAINPLL_NOCDIV_CSATCLK_LSB) |
822 (main_cfg->nocdiv_cstraceclk <<
823 CLKMGR_MAINPLL_NOCDIV_CSTRACECLK_LSB) |
824 (main_cfg->nocdiv_cspdbclk <<
825 CLKMGR_MAINPLL_NOCDIV_CSPDBGCLK_LSB),
826 &clock_manager_base->main_pll.nocdiv);
827 /* gpio_db external divider */
828 writel(per_cfg->gpiodiv_gpiodbclk,
829 &clock_manager_base->per_pll.gpiodiv);
830
831 /* setup the EMAC clock mux select */
832 writel((per_cfg->emacctl_emac0sel <<
833 CLKMGR_PERPLL_EMACCTL_EMAC0SEL_LSB) |
834 (per_cfg->emacctl_emac1sel <<
835 CLKMGR_PERPLL_EMACCTL_EMAC1SEL_LSB) |
836 (per_cfg->emacctl_emac2sel <<
837 CLKMGR_PERPLL_EMACCTL_EMAC2SEL_LSB),
838 &clock_manager_base->per_pll.emacctl);
839
840 /* at this stage, check for PLL lock status */
841 cm_wait_for_lock(LOCKED_MASK);
842
843 /*
844 * after locking, but before taking out of bypass,
845 * assert/deassert outresetall
846 */
847 /* assert mainpll outresetall */
848 setbits_le32(&clock_manager_base->main_pll.vco0,
849 CLKMGR_MAINPLL_VCO0_OUTRSTALL_SET_MSK);
850 /* assert perpll outresetall */
851 setbits_le32(&clock_manager_base->per_pll.vco0,
852 CLKMGR_PERPLL_VCO0_OUTRSTALL_SET_MSK);
853 /* de-assert mainpll outresetall */
854 clrbits_le32(&clock_manager_base->main_pll.vco0,
855 CLKMGR_MAINPLL_VCO0_OUTRSTALL_SET_MSK);
856 /* de-assert perpll outresetall */
857 clrbits_le32(&clock_manager_base->per_pll.vco0,
858 CLKMGR_PERPLL_VCO0_OUTRSTALL_SET_MSK);
859
860 /* Take all PLLs out of bypass when boot mode is cleared. */
861 /* release mainpll from bypass */
862 writel(CLKMGR_MAINPLL_BYPASS_RESET,
863 &clock_manager_base->main_pll.bypassr);
864 /* wait till Clock Manager is not busy */
865 cm_wait_for_fsm();
866
867 /* release perpll from bypass */
868 writel(CLKMGR_PERPLL_BYPASS_RESET,
869 &clock_manager_base->per_pll.bypassr);
870 /* wait till Clock Manager is not busy */
871 cm_wait_for_fsm();
872
873 /* clear boot mode */
874 clrbits_le32(&clock_manager_base->ctrl,
875 CLKMGR_CLKMGR_CTL_BOOTMOD_SET_MSK);
876 /* wait till Clock Manager is not busy */
877 cm_wait_for_fsm();
878
879 /* At here, we need to ramp to final value if needed */
880 if (pll_ramp_main_hz != 0)
881 cm_pll_ramp_main(main_cfg, per_cfg, pll_ramp_main_hz);
882 if (pll_ramp_periph_hz != 0)
883 cm_pll_ramp_periph(main_cfg, per_cfg, pll_ramp_periph_hz);
884
885 /* Now ungate non-hw-managed clocks */
886 writel(CLKMGR_MAINPLL_EN_S2FUSER0CLKEN_SET_MSK |
887 CLKMGR_MAINPLL_EN_HMCPLLREFCLKEN_SET_MSK,
888 &clock_manager_base->main_pll.ens);
889 writel(CLKMGR_PERPLL_EN_RESET, &clock_manager_base->per_pll.ens);
890
891 /* Clear the loss lock and slip bits as they might set during
892 clock reconfiguration */
893 writel(CLKMGR_CLKMGR_INTR_MAINPLLLOST_SET_MSK |
894 CLKMGR_CLKMGR_INTR_PERPLLLOST_SET_MSK |
895 CLKMGR_CLKMGR_INTR_MAINPLLRFSLIP_SET_MSK |
896 CLKMGR_CLKMGR_INTR_PERPLLRFSLIP_SET_MSK |
897 CLKMGR_CLKMGR_INTR_MAINPLLFBSLIP_SET_MSK |
898 CLKMGR_CLKMGR_INTR_PERPLLFBSLIP_SET_MSK,
899 &clock_manager_base->intr);
900
901 return 0;
902}
903
904void cm_use_intosc(void)
905{
906 setbits_le32(&clock_manager_base->ctrl,
907 CLKMGR_CLKMGR_CTL_BOOTCLK_INTOSC_SET_MSK);
908}
909
910unsigned int cm_get_noc_clk_hz(void)
911{
912 unsigned int clk_src, divisor, nocclk, src_hz;
913
914 nocclk = readl(&clock_manager_base->main_pll.nocclk);
915 clk_src = (nocclk >> CLKMGR_MAINPLL_NOCCLK_SRC_LSB) &
916 CLKMGR_MAINPLL_NOCCLK_SRC_MSK;
917
918 divisor = 1 + (nocclk & CLKMGR_MAINPLL_NOCDIV_MSK);
919
920 if (clk_src == CLKMGR_PERPLLGRP_SRC_MAIN) {
921 src_hz = cm_get_main_vco_clk_hz();
922 src_hz /= 1 +
923 (readl(SOCFPGA_CLKMGR_ADDRESS + CLKMGR_MAINPLL_NOC_CLK_OFFSET) &
924 CLKMGR_MAINPLL_NOCCLK_CNT_MSK);
925 } else if (clk_src == CLKMGR_PERPLLGRP_SRC_PERI) {
926 src_hz = cm_get_per_vco_clk_hz();
927 src_hz /= 1 +
928 ((readl(SOCFPGA_CLKMGR_ADDRESS +
929 CLKMGR_MAINPLL_NOC_CLK_OFFSET) >>
930 CLKMGR_MAINPLL_NOCCLK_PERICNT_LSB) &
931 CLKMGR_MAINPLL_NOCCLK_CNT_MSK);
932 } else if (clk_src == CLKMGR_PERPLLGRP_SRC_OSC1) {
933 src_hz = eosc1_hz;
934 } else if (clk_src == CLKMGR_PERPLLGRP_SRC_INTOSC) {
935 src_hz = cb_intosc_hz;
936 } else if (clk_src == CLKMGR_PERPLLGRP_SRC_FPGA) {
937 src_hz = f2s_free_hz;
938 } else {
939 src_hz = 0;
940 }
941
942 return src_hz / divisor;
943}
944
945unsigned int cm_get_l4_noc_hz(unsigned int nocdivshift)
946{
947 unsigned int divisor2 = 1 <<
948 ((readl(&clock_manager_base->main_pll.nocdiv) >>
949 nocdivshift) & CLKMGR_MAINPLL_NOCDIV_MSK);
950
951 return cm_get_noc_clk_hz() / divisor2;
952}
953
954int cm_basic_init(const void *blob)
955{
956 struct mainpll_cfg main_cfg;
957 struct perpll_cfg per_cfg;
Ley Foon Tanca40f292017-04-26 02:44:39 +0800958 int rval;
959
960 /* initialize to zero for use case of optional node */
961 memset(&main_cfg, 0, sizeof(main_cfg));
962 memset(&per_cfg, 0, sizeof(per_cfg));
Ley Foon Tanca40f292017-04-26 02:44:39 +0800963
Marek Vasutec472e02018-05-12 00:09:21 +0200964 rval = of_get_clk_cfg(blob, &main_cfg, &per_cfg);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800965 if (rval)
966 return rval;
967
968 rval = cm_full_cfg(&main_cfg, &per_cfg);
969
970 cm_l4_main_clk_hz =
971 cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MAINCLK_LSB);
972
973 cm_l4_mp_clk_hz = cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MPCLK_LSB);
974
975 cm_l4_sp_clk_hz = cm_get_l4_sp_clk_hz();
976
977 cm_l4_sys_free_clk_hz = cm_get_noc_clk_hz() / 4;
978
979 return rval;
980}
981
982unsigned long cm_get_mpu_clk_hz(void)
983{
984 u32 reg, clk_hz;
985 u32 clk_src, mainmpuclk_reg;
986
987 mainmpuclk_reg = readl(&clock_manager_base->main_pll.mpuclk);
988
989 clk_src = (mainmpuclk_reg >> CLKMGR_MAINPLL_MPUCLK_SRC_LSB) &
990 CLKMGR_MAINPLL_MPUCLK_SRC_MSK;
991
992 reg = readl(&clock_manager_base->altera.mpuclk);
993 /* Check MPU clock source: main, periph, osc1, intosc or f2s? */
994 switch (clk_src) {
995 case CLKMGR_MAINPLL_MPUCLK_SRC_MAIN:
996 clk_hz = cm_get_main_vco_clk_hz();
997 clk_hz /= (reg & CLKMGR_MAINPLL_MPUCLK_CNT_MSK) + 1;
998 break;
999 case CLKMGR_MAINPLL_MPUCLK_SRC_PERI:
1000 clk_hz = cm_get_per_vco_clk_hz();
1001 clk_hz /= (((reg >> CLKMGR_MAINPLL_MPUCLK_PERICNT_LSB) &
1002 CLKMGR_MAINPLL_MPUCLK_CNT_MSK) + 1);
1003 break;
1004 case CLKMGR_MAINPLL_MPUCLK_SRC_OSC1:
1005 clk_hz = eosc1_hz;
1006 break;
1007 case CLKMGR_MAINPLL_MPUCLK_SRC_INTOSC:
1008 clk_hz = cb_intosc_hz;
1009 break;
1010 case CLKMGR_MAINPLL_MPUCLK_SRC_FPGA:
1011 clk_hz = f2s_free_hz;
1012 break;
1013 default:
1014 printf("cm_get_mpu_clk_hz invalid clk_src %d\n", clk_src);
1015 return 0;
1016 }
1017
1018 clk_hz /= (mainmpuclk_reg & CLKMGR_MAINPLL_MPUCLK_CNT_MSK) + 1;
1019
1020 return clk_hz;
1021}
1022
1023unsigned int cm_get_per_vco_clk_hz(void)
1024{
1025 u32 src_hz = 0;
1026 u32 clk_src = 0;
1027 u32 numer = 0;
1028 u32 denom = 0;
1029 u32 vco = 0;
1030
1031 clk_src = readl(&clock_manager_base->per_pll.vco0);
1032
1033 clk_src = (clk_src >> CLKMGR_PERPLL_VCO0_PSRC_LSB) &
1034 CLKMGR_PERPLL_VCO0_PSRC_MSK;
1035
1036 if (clk_src == CLKMGR_PERPLL_VCO0_PSRC_EOSC) {
1037 src_hz = eosc1_hz;
1038 } else if (clk_src == CLKMGR_PERPLL_VCO0_PSRC_E_INTOSC) {
1039 src_hz = cb_intosc_hz;
1040 } else if (clk_src == CLKMGR_PERPLL_VCO0_PSRC_F2S) {
1041 src_hz = f2s_free_hz;
1042 } else if (clk_src == CLKMGR_PERPLL_VCO0_PSRC_MAIN) {
1043 src_hz = cm_get_main_vco_clk_hz();
1044 src_hz /= (readl(&clock_manager_base->main_pll.cntr15clk) &
1045 CLKMGR_MAINPLL_CNTRCLK_MSK) + 1;
1046 } else {
1047 printf("cm_get_per_vco_clk_hz invalid clk_src %d\n", clk_src);
1048 return 0;
1049 }
1050
1051 vco = readl(&clock_manager_base->per_pll.vco1);
1052
1053 numer = vco & CLKMGR_PERPLL_VCO1_NUMER_MSK;
1054
1055 denom = (vco >> CLKMGR_PERPLL_VCO1_DENOM_LSB) &
1056 CLKMGR_PERPLL_VCO1_DENOM_MSK;
1057
1058 vco = src_hz;
1059 vco /= 1 + denom;
1060 vco *= 1 + numer;
1061
1062 return vco;
1063}
1064
1065unsigned int cm_get_main_vco_clk_hz(void)
1066{
1067 u32 src_hz, numer, denom, vco;
1068
1069 u32 clk_src = readl(&clock_manager_base->main_pll.vco0);
1070
1071 clk_src = (clk_src >> CLKMGR_MAINPLL_VCO0_PSRC_LSB) &
1072 CLKMGR_MAINPLL_VCO0_PSRC_MSK;
1073
1074 if (clk_src == CLKMGR_MAINPLL_VCO0_PSRC_EOSC) {
1075 src_hz = eosc1_hz;
1076 } else if (clk_src == CLKMGR_MAINPLL_VCO0_PSRC_E_INTOSC) {
1077 src_hz = cb_intosc_hz;
1078 } else if (clk_src == CLKMGR_MAINPLL_VCO0_PSRC_F2S) {
1079 src_hz = f2s_free_hz;
1080 } else {
1081 printf("cm_get_main_vco_clk_hz invalid clk_src %d\n", clk_src);
1082 return 0;
1083 }
1084
1085 vco = readl(&clock_manager_base->main_pll.vco1);
1086
1087 numer = vco & CLKMGR_MAINPLL_VCO1_NUMER_MSK;
1088
1089 denom = (vco >> CLKMGR_MAINPLL_VCO1_DENOM_LSB) &
1090 CLKMGR_MAINPLL_VCO1_DENOM_MSK;
1091
1092 vco = src_hz;
1093 vco /= 1 + denom;
1094 vco *= 1 + numer;
1095
1096 return vco;
1097}
1098
1099unsigned int cm_get_l4_sp_clk_hz(void)
1100{
1101 return cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4SPCLK_LSB);
1102}
1103
1104unsigned int cm_get_mmc_controller_clk_hz(void)
1105{
1106 u32 clk_hz = 0;
1107 u32 clk_input = 0;
1108
1109 clk_input = readl(&clock_manager_base->per_pll.cntr6clk);
1110 clk_input = (clk_input >> CLKMGR_PERPLL_CNTR6CLK_SRC_LSB) &
1111 CLKMGR_PERPLLGRP_SRC_MSK;
1112
1113 switch (clk_input) {
1114 case CLKMGR_PERPLLGRP_SRC_MAIN:
1115 clk_hz = cm_get_main_vco_clk_hz();
1116 clk_hz /= 1 + (readl(&clock_manager_base->main_pll.cntr6clk) &
1117 CLKMGR_MAINPLL_CNTRCLK_MSK);
1118 break;
1119
1120 case CLKMGR_PERPLLGRP_SRC_PERI:
1121 clk_hz = cm_get_per_vco_clk_hz();
1122 clk_hz /= 1 + (readl(&clock_manager_base->per_pll.cntr6clk) &
1123 CLKMGR_PERPLL_CNTRCLK_MSK);
1124 break;
1125
1126 case CLKMGR_PERPLLGRP_SRC_OSC1:
1127 clk_hz = eosc1_hz;
1128 break;
1129
1130 case CLKMGR_PERPLLGRP_SRC_INTOSC:
1131 clk_hz = cb_intosc_hz;
1132 break;
1133
1134 case CLKMGR_PERPLLGRP_SRC_FPGA:
1135 clk_hz = f2s_free_hz;
1136 break;
1137 }
1138
1139 return clk_hz / 4;
1140}
1141
1142unsigned int cm_get_spi_controller_clk_hz(void)
1143{
1144 return cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MPCLK_LSB);
1145}
1146
1147unsigned int cm_get_qspi_controller_clk_hz(void)
1148{
1149 return cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MAINCLK_LSB);
1150}
1151
Eugeniy Paltsev74739322017-12-28 15:09:02 +03001152/* Override weak dw_spi_get_clk implementation in designware_spi.c driver */
1153int dw_spi_get_clk(struct udevice *bus, ulong *rate)
1154{
1155 *rate = cm_get_spi_controller_clk_hz();
1156
1157 return 0;
1158}
1159
Ley Foon Tanca40f292017-04-26 02:44:39 +08001160void cm_print_clock_quick_summary(void)
1161{
1162 printf("MPU %10ld kHz\n", cm_get_mpu_clk_hz() / 1000);
1163 printf("MMC %8d kHz\n", cm_get_mmc_controller_clk_hz() / 1000);
1164 printf("QSPI %8d kHz\n", cm_get_qspi_controller_clk_hz() / 1000);
1165 printf("SPI %8d kHz\n", cm_get_spi_controller_clk_hz() / 1000);
1166 printf("EOSC1 %8d kHz\n", eosc1_hz / 1000);
1167 printf("cb_intosc %8d kHz\n", cb_intosc_hz / 1000);
1168 printf("f2s_free %8d kHz\n", f2s_free_hz / 1000);
1169 printf("Main VCO %8d kHz\n", cm_get_main_vco_clk_hz() / 1000);
1170 printf("NOC %8d kHz\n", cm_get_noc_clk_hz() / 1000);
1171 printf("L4 Main %8d kHz\n",
1172 cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MAINCLK_LSB) / 1000);
1173 printf("L4 MP %8d kHz\n",
1174 cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MPCLK_LSB) / 1000);
1175 printf("L4 SP %8d kHz\n", cm_get_l4_sp_clk_hz() / 1000);
1176 printf("L4 sys free %8d kHz\n", cm_l4_sys_free_clk_hz / 1000);
1177}