blob: defa2f6261b8e8c8e301ca324e6e3b41f3a09afc [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>
Ley Foon Tanca40f292017-04-26 02:44:39 +080010#include <asm/arch/clock_manager.h>
11
Marek Vasutec472e02018-05-12 00:09:21 +020012static const struct socfpga_clock_manager *clock_manager_base =
13 (struct socfpga_clock_manager *)SOCFPGA_CLKMGR_ADDRESS;
14
Ley Foon Tanca40f292017-04-26 02:44:39 +080015static u32 eosc1_hz;
16static u32 cb_intosc_hz;
17static u32 f2s_free_hz;
18static u32 cm_l4_main_clk_hz;
19static u32 cm_l4_sp_clk_hz;
20static u32 cm_l4_mp_clk_hz;
21static u32 cm_l4_sys_free_clk_hz;
22
23struct mainpll_cfg {
24 u32 vco0_psrc;
25 u32 vco1_denom;
26 u32 vco1_numer;
27 u32 mpuclk;
28 u32 mpuclk_cnt;
29 u32 mpuclk_src;
30 u32 nocclk;
31 u32 nocclk_cnt;
32 u32 nocclk_src;
33 u32 cntr2clk_cnt;
34 u32 cntr3clk_cnt;
35 u32 cntr4clk_cnt;
36 u32 cntr5clk_cnt;
37 u32 cntr6clk_cnt;
38 u32 cntr7clk_cnt;
39 u32 cntr7clk_src;
40 u32 cntr8clk_cnt;
41 u32 cntr9clk_cnt;
42 u32 cntr9clk_src;
43 u32 cntr15clk_cnt;
44 u32 nocdiv_l4mainclk;
45 u32 nocdiv_l4mpclk;
46 u32 nocdiv_l4spclk;
47 u32 nocdiv_csatclk;
48 u32 nocdiv_cstraceclk;
49 u32 nocdiv_cspdbclk;
50};
51
52struct perpll_cfg {
53 u32 vco0_psrc;
54 u32 vco1_denom;
55 u32 vco1_numer;
56 u32 cntr2clk_cnt;
57 u32 cntr2clk_src;
58 u32 cntr3clk_cnt;
59 u32 cntr3clk_src;
60 u32 cntr4clk_cnt;
61 u32 cntr4clk_src;
62 u32 cntr5clk_cnt;
63 u32 cntr5clk_src;
64 u32 cntr6clk_cnt;
65 u32 cntr6clk_src;
66 u32 cntr7clk_cnt;
67 u32 cntr8clk_cnt;
68 u32 cntr8clk_src;
69 u32 cntr9clk_cnt;
Marek Vasutec472e02018-05-12 00:09:21 +020070 u32 cntr9clk_src;
Ley Foon Tanca40f292017-04-26 02:44:39 +080071 u32 emacctl_emac0sel;
72 u32 emacctl_emac1sel;
73 u32 emacctl_emac2sel;
74 u32 gpiodiv_gpiodbclk;
75};
76
Marek Vasutec472e02018-05-12 00:09:21 +020077struct strtou32 {
78 const char *str;
79 const u32 val;
Ley Foon Tanca40f292017-04-26 02:44:39 +080080};
81
Marek Vasutec472e02018-05-12 00:09:21 +020082static const struct strtou32 mainpll_cfg_tab[] = {
83 { "vco0-psrc", offsetof(struct mainpll_cfg, vco0_psrc) },
84 { "vco1-denom", offsetof(struct mainpll_cfg, vco1_denom) },
85 { "vco1-numer", offsetof(struct mainpll_cfg, vco1_numer) },
86 { "mpuclk-cnt", offsetof(struct mainpll_cfg, mpuclk_cnt) },
87 { "mpuclk-src", offsetof(struct mainpll_cfg, mpuclk_src) },
88 { "nocclk-cnt", offsetof(struct mainpll_cfg, nocclk_cnt) },
89 { "nocclk-src", offsetof(struct mainpll_cfg, nocclk_src) },
90 { "cntr2clk-cnt", offsetof(struct mainpll_cfg, cntr2clk_cnt) },
91 { "cntr3clk-cnt", offsetof(struct mainpll_cfg, cntr3clk_cnt) },
92 { "cntr4clk-cnt", offsetof(struct mainpll_cfg, cntr4clk_cnt) },
93 { "cntr5clk-cnt", offsetof(struct mainpll_cfg, cntr5clk_cnt) },
94 { "cntr6clk-cnt", offsetof(struct mainpll_cfg, cntr6clk_cnt) },
95 { "cntr7clk-cnt", offsetof(struct mainpll_cfg, cntr7clk_cnt) },
96 { "cntr7clk-src", offsetof(struct mainpll_cfg, cntr7clk_src) },
97 { "cntr8clk-cnt", offsetof(struct mainpll_cfg, cntr8clk_cnt) },
98 { "cntr9clk-cnt", offsetof(struct mainpll_cfg, cntr9clk_cnt) },
99 { "cntr9clk-src", offsetof(struct mainpll_cfg, cntr9clk_src) },
100 { "cntr15clk-cnt", offsetof(struct mainpll_cfg, cntr15clk_cnt) },
101 { "nocdiv-l4mainclk", offsetof(struct mainpll_cfg, nocdiv_l4mainclk) },
102 { "nocdiv-l4mpclk", offsetof(struct mainpll_cfg, nocdiv_l4mpclk) },
103 { "nocdiv-l4spclk", offsetof(struct mainpll_cfg, nocdiv_l4spclk) },
104 { "nocdiv-csatclk", offsetof(struct mainpll_cfg, nocdiv_csatclk) },
105 { "nocdiv-cstraceclk", offsetof(struct mainpll_cfg, nocdiv_cstraceclk) },
106 { "nocdiv-cspdbgclk", offsetof(struct mainpll_cfg, nocdiv_cspdbclk) },
107};
Ley Foon Tanca40f292017-04-26 02:44:39 +0800108
Marek Vasutec472e02018-05-12 00:09:21 +0200109static const struct strtou32 perpll_cfg_tab[] = {
110 { "vco0-psrc", offsetof(struct perpll_cfg, vco0_psrc) },
111 { "vco1-denom", offsetof(struct perpll_cfg, vco1_denom) },
112 { "vco1-numer", offsetof(struct perpll_cfg, vco1_numer) },
113 { "cntr2clk-cnt", offsetof(struct perpll_cfg, cntr2clk_cnt) },
114 { "cntr2clk-src", offsetof(struct perpll_cfg, cntr2clk_src) },
115 { "cntr3clk-cnt", offsetof(struct perpll_cfg, cntr3clk_cnt) },
116 { "cntr3clk-src", offsetof(struct perpll_cfg, cntr3clk_src) },
117 { "cntr4clk-cnt", offsetof(struct perpll_cfg, cntr4clk_cnt) },
118 { "cntr4clk-src", offsetof(struct perpll_cfg, cntr4clk_src) },
119 { "cntr5clk-cnt", offsetof(struct perpll_cfg, cntr5clk_cnt) },
120 { "cntr5clk-src", offsetof(struct perpll_cfg, cntr5clk_src) },
121 { "cntr6clk-cnt", offsetof(struct perpll_cfg, cntr6clk_cnt) },
122 { "cntr6clk-src", offsetof(struct perpll_cfg, cntr6clk_src) },
123 { "cntr7clk-cnt", offsetof(struct perpll_cfg, cntr7clk_cnt) },
124 { "cntr8clk-cnt", offsetof(struct perpll_cfg, cntr8clk_cnt) },
125 { "cntr8clk-src", offsetof(struct perpll_cfg, cntr8clk_src) },
126 { "cntr9clk-cnt", offsetof(struct perpll_cfg, cntr9clk_cnt) },
127 { "emacctl-emac0sel", offsetof(struct perpll_cfg, emacctl_emac0sel) },
128 { "emacctl-emac1sel", offsetof(struct perpll_cfg, emacctl_emac1sel) },
129 { "emacctl-emac2sel", offsetof(struct perpll_cfg, emacctl_emac2sel) },
130 { "gpiodiv-gpiodbclk", offsetof(struct perpll_cfg, gpiodiv_gpiodbclk) },
131};
132
133static const struct strtou32 alteragrp_cfg_tab[] = {
134 { "nocclk", offsetof(struct mainpll_cfg, nocclk) },
135 { "mpuclk", offsetof(struct mainpll_cfg, mpuclk) },
136};
137
138struct strtopu32 {
139 const char *str;
140 u32 *p;
141};
142
143const struct strtopu32 dt_to_val[] = {
144 { "/clocks/altera_arria10_hps_eosc1", &eosc1_hz},
145 { "/clocks/altera_arria10_hps_cb_intosc_ls", &cb_intosc_hz},
146 { "/clocks/altera_arria10_hps_f2h_free", &f2s_free_hz},
147};
148
149static int of_to_struct(const void *blob, int node, const struct strtou32 *cfg_tab,
150 int cfg_tab_len, void *cfg)
Ley Foon Tanca40f292017-04-26 02:44:39 +0800151{
Marek Vasutec472e02018-05-12 00:09:21 +0200152 int i;
153 u32 val;
154
155 for (i = 0; i < cfg_tab_len; i++) {
156 if (fdtdec_get_int_array(blob, node, cfg_tab[i].str, &val, 1)) {
157 /* could not find required property */
158 return -EINVAL;
159 }
160 *(u32 *)(cfg + cfg_tab[i].val) = val;
Ley Foon Tanca40f292017-04-26 02:44:39 +0800161 }
162
163 return 0;
164}
165
Marek Vasutec472e02018-05-12 00:09:21 +0200166static void of_get_input_clks(const void *blob)
Ley Foon Tanca40f292017-04-26 02:44:39 +0800167{
Marek Vasutec472e02018-05-12 00:09:21 +0200168 int node, i;
Ley Foon Tanca40f292017-04-26 02:44:39 +0800169
Marek Vasutec472e02018-05-12 00:09:21 +0200170 for (i = 0; i < ARRAY_SIZE(dt_to_val); i++) {
171 node = fdt_path_offset(blob, dt_to_val[i].str);
172
173 if (node < 0)
174 continue;
175
176 fdtdec_get_int_array(blob, node, "clock-frequency",
177 dt_to_val[i].p, 1);
178 }
Ley Foon Tanca40f292017-04-26 02:44:39 +0800179}
180
181static int of_get_clk_cfg(const void *blob, struct mainpll_cfg *main_cfg,
Marek Vasutec472e02018-05-12 00:09:21 +0200182 struct perpll_cfg *per_cfg)
Ley Foon Tanca40f292017-04-26 02:44:39 +0800183{
184 int node, child, len;
185 const char *node_name;
186
Marek Vasutec472e02018-05-12 00:09:21 +0200187 of_get_input_clks(blob);
188
189 node = fdtdec_next_compatible(blob, 0, COMPAT_ALTERA_SOCFPGA_CLK_INIT);
190
Ley Foon Tanca40f292017-04-26 02:44:39 +0800191 if (node < 0)
192 return -EINVAL;
193
194 child = fdt_first_subnode(blob, node);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800195
Ley Foon Tanca40f292017-04-26 02:44:39 +0800196 if (child < 0)
197 return -EINVAL;
198
199 node_name = fdt_get_name(blob, child, &len);
200
201 while (node_name) {
Marek Vasutec472e02018-05-12 00:09:21 +0200202 if (!strcmp(node_name, "mainpll")) {
203 if (of_to_struct(blob, child, mainpll_cfg_tab,
204 ARRAY_SIZE(mainpll_cfg_tab), main_cfg))
Ley Foon Tanca40f292017-04-26 02:44:39 +0800205 return -EINVAL;
Marek Vasutec472e02018-05-12 00:09:21 +0200206 } else if (!strcmp(node_name, "perpll")) {
207 if (of_to_struct(blob, child, perpll_cfg_tab,
208 ARRAY_SIZE(perpll_cfg_tab), per_cfg))
Ley Foon Tanca40f292017-04-26 02:44:39 +0800209 return -EINVAL;
Marek Vasutec472e02018-05-12 00:09:21 +0200210 } else if (!strcmp(node_name, "alteragrp")) {
211 if (of_to_struct(blob, child, alteragrp_cfg_tab,
212 ARRAY_SIZE(alteragrp_cfg_tab), main_cfg))
Ley Foon Tanca40f292017-04-26 02:44:39 +0800213 return -EINVAL;
Ley Foon Tanca40f292017-04-26 02:44:39 +0800214 }
215 child = fdt_next_subnode(blob, child);
216
217 if (child < 0)
218 break;
219
220 node_name = fdt_get_name(blob, child, &len);
221 }
222
223 return 0;
224}
225
226/* calculate the intended main VCO frequency based on handoff */
227static unsigned int cm_calc_handoff_main_vco_clk_hz
228 (struct mainpll_cfg *main_cfg)
229{
230 unsigned int clk_hz;
231
232 /* Check main VCO clock source: eosc, intosc or f2s? */
233 switch (main_cfg->vco0_psrc) {
234 case CLKMGR_MAINPLL_VCO0_PSRC_EOSC:
235 clk_hz = eosc1_hz;
236 break;
237 case CLKMGR_MAINPLL_VCO0_PSRC_E_INTOSC:
238 clk_hz = cb_intosc_hz;
239 break;
240 case CLKMGR_MAINPLL_VCO0_PSRC_F2S:
241 clk_hz = f2s_free_hz;
242 break;
243 default:
244 return 0;
245 }
246
247 /* calculate the VCO frequency */
248 clk_hz /= 1 + main_cfg->vco1_denom;
249 clk_hz *= 1 + main_cfg->vco1_numer;
250
251 return clk_hz;
252}
253
254/* calculate the intended periph VCO frequency based on handoff */
255static unsigned int cm_calc_handoff_periph_vco_clk_hz(
256 struct mainpll_cfg *main_cfg, struct perpll_cfg *per_cfg)
257{
258 unsigned int clk_hz;
259
260 /* Check periph VCO clock source: eosc, intosc, f2s or mainpll? */
261 switch (per_cfg->vco0_psrc) {
262 case CLKMGR_PERPLL_VCO0_PSRC_EOSC:
263 clk_hz = eosc1_hz;
264 break;
265 case CLKMGR_PERPLL_VCO0_PSRC_E_INTOSC:
266 clk_hz = cb_intosc_hz;
267 break;
268 case CLKMGR_PERPLL_VCO0_PSRC_F2S:
269 clk_hz = f2s_free_hz;
270 break;
271 case CLKMGR_PERPLL_VCO0_PSRC_MAIN:
272 clk_hz = cm_calc_handoff_main_vco_clk_hz(main_cfg);
273 clk_hz /= main_cfg->cntr15clk_cnt;
274 break;
275 default:
276 return 0;
277 }
278
279 /* calculate the VCO frequency */
280 clk_hz /= 1 + per_cfg->vco1_denom;
281 clk_hz *= 1 + per_cfg->vco1_numer;
282
283 return clk_hz;
284}
285
286/* calculate the intended MPU clock frequency based on handoff */
287static unsigned int cm_calc_handoff_mpu_clk_hz(struct mainpll_cfg *main_cfg,
288 struct perpll_cfg *per_cfg)
289{
290 unsigned int clk_hz;
291
292 /* Check MPU clock source: main, periph, osc1, intosc or f2s? */
293 switch (main_cfg->mpuclk_src) {
294 case CLKMGR_MAINPLL_MPUCLK_SRC_MAIN:
295 clk_hz = cm_calc_handoff_main_vco_clk_hz(main_cfg);
296 clk_hz /= (main_cfg->mpuclk & CLKMGR_MAINPLL_MPUCLK_CNT_MSK)
297 + 1;
298 break;
299 case CLKMGR_MAINPLL_MPUCLK_SRC_PERI:
300 clk_hz = cm_calc_handoff_periph_vco_clk_hz(main_cfg, per_cfg);
301 clk_hz /= ((main_cfg->mpuclk >>
302 CLKMGR_MAINPLL_MPUCLK_PERICNT_LSB) &
303 CLKMGR_MAINPLL_MPUCLK_CNT_MSK) + 1;
304 break;
305 case CLKMGR_MAINPLL_MPUCLK_SRC_OSC1:
306 clk_hz = eosc1_hz;
307 break;
308 case CLKMGR_MAINPLL_MPUCLK_SRC_INTOSC:
309 clk_hz = cb_intosc_hz;
310 break;
311 case CLKMGR_MAINPLL_MPUCLK_SRC_FPGA:
312 clk_hz = f2s_free_hz;
313 break;
314 default:
315 return 0;
316 }
317
318 clk_hz /= main_cfg->mpuclk_cnt + 1;
319 return clk_hz;
320}
321
322/* calculate the intended NOC clock frequency based on handoff */
323static unsigned int cm_calc_handoff_noc_clk_hz(struct mainpll_cfg *main_cfg,
324 struct perpll_cfg *per_cfg)
325{
326 unsigned int clk_hz;
327
328 /* Check MPU clock source: main, periph, osc1, intosc or f2s? */
329 switch (main_cfg->nocclk_src) {
330 case CLKMGR_MAINPLL_NOCCLK_SRC_MAIN:
331 clk_hz = cm_calc_handoff_main_vco_clk_hz(main_cfg);
332 clk_hz /= (main_cfg->nocclk & CLKMGR_MAINPLL_NOCCLK_CNT_MSK)
333 + 1;
334 break;
335 case CLKMGR_MAINPLL_NOCCLK_SRC_PERI:
336 clk_hz = cm_calc_handoff_periph_vco_clk_hz(main_cfg, per_cfg);
337 clk_hz /= ((main_cfg->nocclk >>
338 CLKMGR_MAINPLL_NOCCLK_PERICNT_LSB) &
339 CLKMGR_MAINPLL_NOCCLK_CNT_MSK) + 1;
340 break;
341 case CLKMGR_MAINPLL_NOCCLK_SRC_OSC1:
342 clk_hz = eosc1_hz;
343 break;
344 case CLKMGR_MAINPLL_NOCCLK_SRC_INTOSC:
345 clk_hz = cb_intosc_hz;
346 break;
347 case CLKMGR_MAINPLL_NOCCLK_SRC_FPGA:
348 clk_hz = f2s_free_hz;
349 break;
350 default:
351 return 0;
352 }
353
354 clk_hz /= main_cfg->nocclk_cnt + 1;
355 return clk_hz;
356}
357
358/* return 1 if PLL ramp is required */
359static int cm_is_pll_ramp_required(int main0periph1,
360 struct mainpll_cfg *main_cfg,
361 struct perpll_cfg *per_cfg)
362{
363 /* Check for main PLL */
364 if (main0periph1 == 0) {
365 /*
366 * PLL ramp is not required if both MPU clock and NOC clock are
367 * not sourced from main PLL
368 */
369 if (main_cfg->mpuclk_src != CLKMGR_MAINPLL_MPUCLK_SRC_MAIN &&
370 main_cfg->nocclk_src != CLKMGR_MAINPLL_NOCCLK_SRC_MAIN)
371 return 0;
372
373 /*
374 * PLL ramp is required if MPU clock is sourced from main PLL
375 * and MPU clock is over 900MHz (as advised by HW team)
376 */
377 if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_MAIN &&
378 (cm_calc_handoff_mpu_clk_hz(main_cfg, per_cfg) >
379 CLKMGR_PLL_RAMP_MPUCLK_THRESHOLD_HZ))
380 return 1;
381
382 /*
383 * PLL ramp is required if NOC clock is sourced from main PLL
384 * and NOC clock is over 300MHz (as advised by HW team)
385 */
386 if (main_cfg->nocclk_src == CLKMGR_MAINPLL_NOCCLK_SRC_MAIN &&
387 (cm_calc_handoff_noc_clk_hz(main_cfg, per_cfg) >
388 CLKMGR_PLL_RAMP_NOCCLK_THRESHOLD_HZ))
389 return 2;
390
391 } else if (main0periph1 == 1) {
392 /*
393 * PLL ramp is not required if both MPU clock and NOC clock are
394 * not sourced from periph PLL
395 */
396 if (main_cfg->mpuclk_src != CLKMGR_MAINPLL_MPUCLK_SRC_PERI &&
397 main_cfg->nocclk_src != CLKMGR_MAINPLL_NOCCLK_SRC_PERI)
398 return 0;
399
400 /*
401 * PLL ramp is required if MPU clock are source from periph PLL
402 * and MPU clock is over 900MHz (as advised by HW team)
403 */
404 if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_PERI &&
405 (cm_calc_handoff_mpu_clk_hz(main_cfg, per_cfg) >
406 CLKMGR_PLL_RAMP_MPUCLK_THRESHOLD_HZ))
407 return 1;
408
409 /*
410 * PLL ramp is required if NOC clock are source from periph PLL
411 * and NOC clock is over 300MHz (as advised by HW team)
412 */
413 if (main_cfg->nocclk_src == CLKMGR_MAINPLL_NOCCLK_SRC_PERI &&
414 (cm_calc_handoff_noc_clk_hz(main_cfg, per_cfg) >
415 CLKMGR_PLL_RAMP_NOCCLK_THRESHOLD_HZ))
416 return 2;
417 }
418
419 return 0;
420}
421
422static u32 cm_calculate_numer(struct mainpll_cfg *main_cfg,
423 struct perpll_cfg *per_cfg,
424 u32 safe_hz, u32 clk_hz)
425{
426 u32 cnt;
427 u32 clk;
428 u32 shift;
429 u32 mask;
430 u32 denom;
431
432 if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_MAIN) {
433 cnt = main_cfg->mpuclk_cnt;
434 clk = main_cfg->mpuclk;
435 shift = 0;
436 mask = CLKMGR_MAINPLL_MPUCLK_CNT_MSK;
437 denom = main_cfg->vco1_denom;
438 } else if (main_cfg->nocclk_src == CLKMGR_MAINPLL_NOCCLK_SRC_MAIN) {
439 cnt = main_cfg->nocclk_cnt;
440 clk = main_cfg->nocclk;
441 shift = 0;
442 mask = CLKMGR_MAINPLL_NOCCLK_CNT_MSK;
443 denom = main_cfg->vco1_denom;
444 } else if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_PERI) {
445 cnt = main_cfg->mpuclk_cnt;
446 clk = main_cfg->mpuclk;
447 shift = CLKMGR_MAINPLL_MPUCLK_PERICNT_LSB;
448 mask = CLKMGR_MAINPLL_MPUCLK_CNT_MSK;
449 denom = per_cfg->vco1_denom;
450 } else if (main_cfg->nocclk_src == CLKMGR_MAINPLL_NOCCLK_SRC_PERI) {
451 cnt = main_cfg->nocclk_cnt;
452 clk = main_cfg->nocclk;
453 shift = CLKMGR_MAINPLL_NOCCLK_PERICNT_LSB;
454 mask = CLKMGR_MAINPLL_NOCCLK_CNT_MSK;
455 denom = per_cfg->vco1_denom;
456 } else {
457 return 0;
458 }
459
460 return (safe_hz / clk_hz) * (cnt + 1) * (((clk >> shift) & mask) + 1) *
461 (1 + denom) - 1;
462}
463
464/*
465 * Calculate the new PLL numerator which is based on existing DTS hand off and
466 * intended safe frequency (safe_hz). Note that PLL ramp is only modifying the
467 * numerator while maintaining denominator as denominator will influence the
468 * jitter condition. Please refer A10 HPS TRM for the jitter guide. Note final
469 * value for numerator is minus with 1 to cater our register value
470 * representation.
471 */
472static unsigned int cm_calc_safe_pll_numer(int main0periph1,
473 struct mainpll_cfg *main_cfg,
474 struct perpll_cfg *per_cfg,
475 unsigned int safe_hz)
476{
477 unsigned int clk_hz = 0;
478
479 /* Check for main PLL */
480 if (main0periph1 == 0) {
481 /* Check main VCO clock source: eosc, intosc or f2s? */
482 switch (main_cfg->vco0_psrc) {
483 case CLKMGR_MAINPLL_VCO0_PSRC_EOSC:
484 clk_hz = eosc1_hz;
485 break;
486 case CLKMGR_MAINPLL_VCO0_PSRC_E_INTOSC:
487 clk_hz = cb_intosc_hz;
488 break;
489 case CLKMGR_MAINPLL_VCO0_PSRC_F2S:
490 clk_hz = f2s_free_hz;
491 break;
492 default:
493 return 0;
494 }
495 } else if (main0periph1 == 1) {
496 /* Check periph VCO clock source: eosc, intosc, f2s, mainpll */
497 switch (per_cfg->vco0_psrc) {
498 case CLKMGR_PERPLL_VCO0_PSRC_EOSC:
499 clk_hz = eosc1_hz;
500 break;
501 case CLKMGR_PERPLL_VCO0_PSRC_E_INTOSC:
502 clk_hz = cb_intosc_hz;
503 break;
504 case CLKMGR_PERPLL_VCO0_PSRC_F2S:
505 clk_hz = f2s_free_hz;
506 break;
507 case CLKMGR_PERPLL_VCO0_PSRC_MAIN:
508 clk_hz = cm_calc_handoff_main_vco_clk_hz(main_cfg);
509 clk_hz /= main_cfg->cntr15clk_cnt;
510 break;
511 default:
512 return 0;
513 }
514 } else {
515 return 0;
516 }
517
518 return cm_calculate_numer(main_cfg, per_cfg, safe_hz, clk_hz);
519}
520
521/* ramping the main PLL to final value */
522static void cm_pll_ramp_main(struct mainpll_cfg *main_cfg,
523 struct perpll_cfg *per_cfg,
524 unsigned int pll_ramp_main_hz)
525{
526 unsigned int clk_hz = 0, clk_incr_hz = 0, clk_final_hz = 0;
527
528 /* find out the increment value */
529 if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_MAIN) {
530 clk_incr_hz = CLKMGR_PLL_RAMP_MPUCLK_INCREMENT_HZ;
531 clk_final_hz = cm_calc_handoff_mpu_clk_hz(main_cfg, per_cfg);
532 } else if (main_cfg->nocclk_src == CLKMGR_MAINPLL_NOCCLK_SRC_MAIN) {
533 clk_incr_hz = CLKMGR_PLL_RAMP_NOCCLK_INCREMENT_HZ;
534 clk_final_hz = cm_calc_handoff_noc_clk_hz(main_cfg, per_cfg);
535 }
536
537 /* execute the ramping here */
538 for (clk_hz = pll_ramp_main_hz + clk_incr_hz;
539 clk_hz < clk_final_hz; clk_hz += clk_incr_hz) {
540 writel((main_cfg->vco1_denom <<
541 CLKMGR_MAINPLL_VCO1_DENOM_LSB) |
542 cm_calc_safe_pll_numer(0, main_cfg, per_cfg, clk_hz),
543 &clock_manager_base->main_pll.vco1);
544 mdelay(1);
545 cm_wait_for_lock(LOCKED_MASK);
546 }
547 writel((main_cfg->vco1_denom << CLKMGR_MAINPLL_VCO1_DENOM_LSB) |
548 main_cfg->vco1_numer, &clock_manager_base->main_pll.vco1);
549 mdelay(1);
550 cm_wait_for_lock(LOCKED_MASK);
551}
552
553/* ramping the periph PLL to final value */
554static void cm_pll_ramp_periph(struct mainpll_cfg *main_cfg,
555 struct perpll_cfg *per_cfg,
556 unsigned int pll_ramp_periph_hz)
557{
558 unsigned int clk_hz = 0, clk_incr_hz = 0, clk_final_hz = 0;
559
560 /* find out the increment value */
561 if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_PERI) {
562 clk_incr_hz = CLKMGR_PLL_RAMP_MPUCLK_INCREMENT_HZ;
563 clk_final_hz = cm_calc_handoff_mpu_clk_hz(main_cfg, per_cfg);
564 } else if (main_cfg->nocclk_src == CLKMGR_MAINPLL_NOCCLK_SRC_PERI) {
565 clk_incr_hz = CLKMGR_PLL_RAMP_NOCCLK_INCREMENT_HZ;
566 clk_final_hz = cm_calc_handoff_noc_clk_hz(main_cfg, per_cfg);
567 }
568 /* execute the ramping here */
569 for (clk_hz = pll_ramp_periph_hz + clk_incr_hz;
570 clk_hz < clk_final_hz; clk_hz += clk_incr_hz) {
571 writel((per_cfg->vco1_denom << CLKMGR_PERPLL_VCO1_DENOM_LSB) |
572 cm_calc_safe_pll_numer(1, main_cfg, per_cfg, clk_hz),
573 &clock_manager_base->per_pll.vco1);
574 mdelay(1);
575 cm_wait_for_lock(LOCKED_MASK);
576 }
577 writel((per_cfg->vco1_denom << CLKMGR_PERPLL_VCO1_DENOM_LSB) |
578 per_cfg->vco1_numer, &clock_manager_base->per_pll.vco1);
579 mdelay(1);
580 cm_wait_for_lock(LOCKED_MASK);
581}
582
583/*
584 * Setup clocks while making no assumptions of the
585 * previous state of the clocks.
586 *
587 * Start by being paranoid and gate all sw managed clocks
588 *
589 * Put all plls in bypass
590 *
591 * Put all plls VCO registers back to reset value (bgpwr dwn).
592 *
593 * Put peripheral and main pll src to reset value to avoid glitch.
594 *
595 * Delay 5 us.
596 *
597 * Deassert bg pwr dn and set numerator and denominator
598 *
599 * Start 7 us timer.
600 *
601 * set internal dividers
602 *
603 * Wait for 7 us timer.
604 *
605 * Enable plls
606 *
607 * Set external dividers while plls are locking
608 *
609 * Wait for pll lock
610 *
611 * Assert/deassert outreset all.
612 *
613 * Take all pll's out of bypass
614 *
615 * Clear safe mode
616 *
617 * set source main and peripheral clocks
618 *
619 * Ungate clocks
620 */
621
622static int cm_full_cfg(struct mainpll_cfg *main_cfg, struct perpll_cfg *per_cfg)
623{
624 unsigned int pll_ramp_main_hz = 0, pll_ramp_periph_hz = 0,
625 ramp_required;
626
627 /* gate off all mainpll clock excpet HW managed clock */
628 writel(CLKMGR_MAINPLL_EN_S2FUSER0CLKEN_SET_MSK |
629 CLKMGR_MAINPLL_EN_HMCPLLREFCLKEN_SET_MSK,
630 &clock_manager_base->main_pll.enr);
631
632 /* now we can gate off the rest of the peripheral clocks */
633 writel(0, &clock_manager_base->per_pll.en);
634
635 /* Put all plls in external bypass */
636 writel(CLKMGR_MAINPLL_BYPASS_RESET,
637 &clock_manager_base->main_pll.bypasss);
638 writel(CLKMGR_PERPLL_BYPASS_RESET,
639 &clock_manager_base->per_pll.bypasss);
640
641 /*
642 * Put all plls VCO registers back to reset value.
643 * Some code might have messed with them. At same time set the
644 * desired clock source
645 */
646 writel(CLKMGR_MAINPLL_VCO0_RESET |
647 CLKMGR_MAINPLL_VCO0_REGEXTSEL_SET_MSK |
648 (main_cfg->vco0_psrc << CLKMGR_MAINPLL_VCO0_PSRC_LSB),
649 &clock_manager_base->main_pll.vco0);
650
651 writel(CLKMGR_PERPLL_VCO0_RESET |
652 CLKMGR_PERPLL_VCO0_REGEXTSEL_SET_MSK |
653 (per_cfg->vco0_psrc << CLKMGR_PERPLL_VCO0_PSRC_LSB),
654 &clock_manager_base->per_pll.vco0);
655
656 writel(CLKMGR_MAINPLL_VCO1_RESET, &clock_manager_base->main_pll.vco1);
657 writel(CLKMGR_PERPLL_VCO1_RESET, &clock_manager_base->per_pll.vco1);
658
659 /* clear the interrupt register status register */
660 writel(CLKMGR_CLKMGR_INTR_MAINPLLLOST_SET_MSK |
661 CLKMGR_CLKMGR_INTR_PERPLLLOST_SET_MSK |
662 CLKMGR_CLKMGR_INTR_MAINPLLRFSLIP_SET_MSK |
663 CLKMGR_CLKMGR_INTR_PERPLLRFSLIP_SET_MSK |
664 CLKMGR_CLKMGR_INTR_MAINPLLFBSLIP_SET_MSK |
665 CLKMGR_CLKMGR_INTR_PERPLLFBSLIP_SET_MSK |
666 CLKMGR_CLKMGR_INTR_MAINPLLACHIEVED_SET_MSK |
667 CLKMGR_CLKMGR_INTR_PERPLLACHIEVED_SET_MSK,
668 &clock_manager_base->intr);
669
670 /* Program VCO Numerator and Denominator for main PLL */
671 ramp_required = cm_is_pll_ramp_required(0, main_cfg, per_cfg);
672 if (ramp_required) {
673 /* set main PLL to safe starting threshold frequency */
674 if (ramp_required == 1)
675 pll_ramp_main_hz = CLKMGR_PLL_RAMP_MPUCLK_THRESHOLD_HZ;
676 else if (ramp_required == 2)
677 pll_ramp_main_hz = CLKMGR_PLL_RAMP_NOCCLK_THRESHOLD_HZ;
678
679 writel((main_cfg->vco1_denom << CLKMGR_MAINPLL_VCO1_DENOM_LSB) |
680 cm_calc_safe_pll_numer(0, main_cfg, per_cfg,
681 pll_ramp_main_hz),
682 &clock_manager_base->main_pll.vco1);
683 } else
684 writel((main_cfg->vco1_denom << CLKMGR_MAINPLL_VCO1_DENOM_LSB) |
685 main_cfg->vco1_numer,
686 &clock_manager_base->main_pll.vco1);
687
688 /* Program VCO Numerator and Denominator for periph PLL */
689 ramp_required = cm_is_pll_ramp_required(1, main_cfg, per_cfg);
690 if (ramp_required) {
691 /* set periph PLL to safe starting threshold frequency */
692 if (ramp_required == 1)
693 pll_ramp_periph_hz =
694 CLKMGR_PLL_RAMP_MPUCLK_THRESHOLD_HZ;
695 else if (ramp_required == 2)
696 pll_ramp_periph_hz =
697 CLKMGR_PLL_RAMP_NOCCLK_THRESHOLD_HZ;
698
699 writel((per_cfg->vco1_denom << CLKMGR_PERPLL_VCO1_DENOM_LSB) |
700 cm_calc_safe_pll_numer(1, main_cfg, per_cfg,
701 pll_ramp_periph_hz),
702 &clock_manager_base->per_pll.vco1);
703 } else
704 writel((per_cfg->vco1_denom << CLKMGR_PERPLL_VCO1_DENOM_LSB) |
705 per_cfg->vco1_numer,
706 &clock_manager_base->per_pll.vco1);
707
708 /* Wait for at least 5 us */
709 udelay(5);
710
711 /* Now deassert BGPWRDN and PWRDN */
712 clrbits_le32(&clock_manager_base->main_pll.vco0,
713 CLKMGR_MAINPLL_VCO0_BGPWRDN_SET_MSK |
714 CLKMGR_MAINPLL_VCO0_PWRDN_SET_MSK);
715 clrbits_le32(&clock_manager_base->per_pll.vco0,
716 CLKMGR_PERPLL_VCO0_BGPWRDN_SET_MSK |
717 CLKMGR_PERPLL_VCO0_PWRDN_SET_MSK);
718
719 /* Wait for at least 7 us */
720 udelay(7);
721
722 /* enable the VCO and disable the external regulator to PLL */
723 writel((readl(&clock_manager_base->main_pll.vco0) &
724 ~CLKMGR_MAINPLL_VCO0_REGEXTSEL_SET_MSK) |
725 CLKMGR_MAINPLL_VCO0_EN_SET_MSK,
726 &clock_manager_base->main_pll.vco0);
727 writel((readl(&clock_manager_base->per_pll.vco0) &
728 ~CLKMGR_PERPLL_VCO0_REGEXTSEL_SET_MSK) |
729 CLKMGR_PERPLL_VCO0_EN_SET_MSK,
730 &clock_manager_base->per_pll.vco0);
731
732 /* setup all the main PLL counter and clock source */
733 writel(main_cfg->nocclk,
734 SOCFPGA_CLKMGR_ADDRESS + CLKMGR_MAINPLL_NOC_CLK_OFFSET);
735 writel(main_cfg->mpuclk,
736 SOCFPGA_CLKMGR_ADDRESS + CLKMGR_ALTERAGRP_MPU_CLK_OFFSET);
737
738 /* main_emaca_clk divider */
739 writel(main_cfg->cntr2clk_cnt, &clock_manager_base->main_pll.cntr2clk);
740 /* main_emacb_clk divider */
741 writel(main_cfg->cntr3clk_cnt, &clock_manager_base->main_pll.cntr3clk);
742 /* main_emac_ptp_clk divider */
743 writel(main_cfg->cntr4clk_cnt, &clock_manager_base->main_pll.cntr4clk);
744 /* main_gpio_db_clk divider */
745 writel(main_cfg->cntr5clk_cnt, &clock_manager_base->main_pll.cntr5clk);
746 /* main_sdmmc_clk divider */
747 writel(main_cfg->cntr6clk_cnt, &clock_manager_base->main_pll.cntr6clk);
748 /* main_s2f_user0_clk divider */
749 writel(main_cfg->cntr7clk_cnt |
750 (main_cfg->cntr7clk_src << CLKMGR_MAINPLL_CNTR7CLK_SRC_LSB),
751 &clock_manager_base->main_pll.cntr7clk);
752 /* main_s2f_user1_clk divider */
753 writel(main_cfg->cntr8clk_cnt, &clock_manager_base->main_pll.cntr8clk);
754 /* main_hmc_pll_clk divider */
755 writel(main_cfg->cntr9clk_cnt |
756 (main_cfg->cntr9clk_src << CLKMGR_MAINPLL_CNTR9CLK_SRC_LSB),
757 &clock_manager_base->main_pll.cntr9clk);
758 /* main_periph_ref_clk divider */
759 writel(main_cfg->cntr15clk_cnt,
760 &clock_manager_base->main_pll.cntr15clk);
761
762 /* setup all the peripheral PLL counter and clock source */
763 /* peri_emaca_clk divider */
764 writel(per_cfg->cntr2clk_cnt |
765 (per_cfg->cntr2clk_src << CLKMGR_PERPLL_CNTR2CLK_SRC_LSB),
766 &clock_manager_base->per_pll.cntr2clk);
767 /* peri_emacb_clk divider */
768 writel(per_cfg->cntr3clk_cnt |
769 (per_cfg->cntr3clk_src << CLKMGR_PERPLL_CNTR3CLK_SRC_LSB),
770 &clock_manager_base->per_pll.cntr3clk);
771 /* peri_emac_ptp_clk divider */
772 writel(per_cfg->cntr4clk_cnt |
773 (per_cfg->cntr4clk_src << CLKMGR_PERPLL_CNTR4CLK_SRC_LSB),
774 &clock_manager_base->per_pll.cntr4clk);
775 /* peri_gpio_db_clk divider */
776 writel(per_cfg->cntr5clk_cnt |
777 (per_cfg->cntr5clk_src << CLKMGR_PERPLL_CNTR5CLK_SRC_LSB),
778 &clock_manager_base->per_pll.cntr5clk);
779 /* peri_sdmmc_clk divider */
780 writel(per_cfg->cntr6clk_cnt |
781 (per_cfg->cntr6clk_src << CLKMGR_PERPLL_CNTR6CLK_SRC_LSB),
782 &clock_manager_base->per_pll.cntr6clk);
783 /* peri_s2f_user0_clk divider */
784 writel(per_cfg->cntr7clk_cnt, &clock_manager_base->per_pll.cntr7clk);
785 /* peri_s2f_user1_clk divider */
786 writel(per_cfg->cntr8clk_cnt |
787 (per_cfg->cntr8clk_src << CLKMGR_PERPLL_CNTR8CLK_SRC_LSB),
788 &clock_manager_base->per_pll.cntr8clk);
789 /* peri_hmc_pll_clk divider */
790 writel(per_cfg->cntr9clk_cnt, &clock_manager_base->per_pll.cntr9clk);
791
792 /* setup all the external PLL counter */
793 /* mpu wrapper / external divider */
794 writel(main_cfg->mpuclk_cnt |
795 (main_cfg->mpuclk_src << CLKMGR_MAINPLL_MPUCLK_SRC_LSB),
796 &clock_manager_base->main_pll.mpuclk);
797 /* NOC wrapper / external divider */
798 writel(main_cfg->nocclk_cnt |
799 (main_cfg->nocclk_src << CLKMGR_MAINPLL_NOCCLK_SRC_LSB),
800 &clock_manager_base->main_pll.nocclk);
801 /* NOC subclock divider such as l4 */
802 writel(main_cfg->nocdiv_l4mainclk |
803 (main_cfg->nocdiv_l4mpclk <<
804 CLKMGR_MAINPLL_NOCDIV_L4MPCLK_LSB) |
805 (main_cfg->nocdiv_l4spclk <<
806 CLKMGR_MAINPLL_NOCDIV_L4SPCLK_LSB) |
807 (main_cfg->nocdiv_csatclk <<
808 CLKMGR_MAINPLL_NOCDIV_CSATCLK_LSB) |
809 (main_cfg->nocdiv_cstraceclk <<
810 CLKMGR_MAINPLL_NOCDIV_CSTRACECLK_LSB) |
811 (main_cfg->nocdiv_cspdbclk <<
812 CLKMGR_MAINPLL_NOCDIV_CSPDBGCLK_LSB),
813 &clock_manager_base->main_pll.nocdiv);
814 /* gpio_db external divider */
815 writel(per_cfg->gpiodiv_gpiodbclk,
816 &clock_manager_base->per_pll.gpiodiv);
817
818 /* setup the EMAC clock mux select */
819 writel((per_cfg->emacctl_emac0sel <<
820 CLKMGR_PERPLL_EMACCTL_EMAC0SEL_LSB) |
821 (per_cfg->emacctl_emac1sel <<
822 CLKMGR_PERPLL_EMACCTL_EMAC1SEL_LSB) |
823 (per_cfg->emacctl_emac2sel <<
824 CLKMGR_PERPLL_EMACCTL_EMAC2SEL_LSB),
825 &clock_manager_base->per_pll.emacctl);
826
827 /* at this stage, check for PLL lock status */
828 cm_wait_for_lock(LOCKED_MASK);
829
830 /*
831 * after locking, but before taking out of bypass,
832 * assert/deassert outresetall
833 */
834 /* assert mainpll outresetall */
835 setbits_le32(&clock_manager_base->main_pll.vco0,
836 CLKMGR_MAINPLL_VCO0_OUTRSTALL_SET_MSK);
837 /* assert perpll outresetall */
838 setbits_le32(&clock_manager_base->per_pll.vco0,
839 CLKMGR_PERPLL_VCO0_OUTRSTALL_SET_MSK);
840 /* de-assert mainpll outresetall */
841 clrbits_le32(&clock_manager_base->main_pll.vco0,
842 CLKMGR_MAINPLL_VCO0_OUTRSTALL_SET_MSK);
843 /* de-assert perpll outresetall */
844 clrbits_le32(&clock_manager_base->per_pll.vco0,
845 CLKMGR_PERPLL_VCO0_OUTRSTALL_SET_MSK);
846
847 /* Take all PLLs out of bypass when boot mode is cleared. */
848 /* release mainpll from bypass */
849 writel(CLKMGR_MAINPLL_BYPASS_RESET,
850 &clock_manager_base->main_pll.bypassr);
851 /* wait till Clock Manager is not busy */
852 cm_wait_for_fsm();
853
854 /* release perpll from bypass */
855 writel(CLKMGR_PERPLL_BYPASS_RESET,
856 &clock_manager_base->per_pll.bypassr);
857 /* wait till Clock Manager is not busy */
858 cm_wait_for_fsm();
859
860 /* clear boot mode */
861 clrbits_le32(&clock_manager_base->ctrl,
862 CLKMGR_CLKMGR_CTL_BOOTMOD_SET_MSK);
863 /* wait till Clock Manager is not busy */
864 cm_wait_for_fsm();
865
866 /* At here, we need to ramp to final value if needed */
867 if (pll_ramp_main_hz != 0)
868 cm_pll_ramp_main(main_cfg, per_cfg, pll_ramp_main_hz);
869 if (pll_ramp_periph_hz != 0)
870 cm_pll_ramp_periph(main_cfg, per_cfg, pll_ramp_periph_hz);
871
872 /* Now ungate non-hw-managed clocks */
873 writel(CLKMGR_MAINPLL_EN_S2FUSER0CLKEN_SET_MSK |
874 CLKMGR_MAINPLL_EN_HMCPLLREFCLKEN_SET_MSK,
875 &clock_manager_base->main_pll.ens);
876 writel(CLKMGR_PERPLL_EN_RESET, &clock_manager_base->per_pll.ens);
877
878 /* Clear the loss lock and slip bits as they might set during
879 clock reconfiguration */
880 writel(CLKMGR_CLKMGR_INTR_MAINPLLLOST_SET_MSK |
881 CLKMGR_CLKMGR_INTR_PERPLLLOST_SET_MSK |
882 CLKMGR_CLKMGR_INTR_MAINPLLRFSLIP_SET_MSK |
883 CLKMGR_CLKMGR_INTR_PERPLLRFSLIP_SET_MSK |
884 CLKMGR_CLKMGR_INTR_MAINPLLFBSLIP_SET_MSK |
885 CLKMGR_CLKMGR_INTR_PERPLLFBSLIP_SET_MSK,
886 &clock_manager_base->intr);
887
888 return 0;
889}
890
891void cm_use_intosc(void)
892{
893 setbits_le32(&clock_manager_base->ctrl,
894 CLKMGR_CLKMGR_CTL_BOOTCLK_INTOSC_SET_MSK);
895}
896
897unsigned int cm_get_noc_clk_hz(void)
898{
899 unsigned int clk_src, divisor, nocclk, src_hz;
900
901 nocclk = readl(&clock_manager_base->main_pll.nocclk);
902 clk_src = (nocclk >> CLKMGR_MAINPLL_NOCCLK_SRC_LSB) &
903 CLKMGR_MAINPLL_NOCCLK_SRC_MSK;
904
905 divisor = 1 + (nocclk & CLKMGR_MAINPLL_NOCDIV_MSK);
906
907 if (clk_src == CLKMGR_PERPLLGRP_SRC_MAIN) {
908 src_hz = cm_get_main_vco_clk_hz();
909 src_hz /= 1 +
910 (readl(SOCFPGA_CLKMGR_ADDRESS + CLKMGR_MAINPLL_NOC_CLK_OFFSET) &
911 CLKMGR_MAINPLL_NOCCLK_CNT_MSK);
912 } else if (clk_src == CLKMGR_PERPLLGRP_SRC_PERI) {
913 src_hz = cm_get_per_vco_clk_hz();
914 src_hz /= 1 +
915 ((readl(SOCFPGA_CLKMGR_ADDRESS +
916 CLKMGR_MAINPLL_NOC_CLK_OFFSET) >>
917 CLKMGR_MAINPLL_NOCCLK_PERICNT_LSB) &
918 CLKMGR_MAINPLL_NOCCLK_CNT_MSK);
919 } else if (clk_src == CLKMGR_PERPLLGRP_SRC_OSC1) {
920 src_hz = eosc1_hz;
921 } else if (clk_src == CLKMGR_PERPLLGRP_SRC_INTOSC) {
922 src_hz = cb_intosc_hz;
923 } else if (clk_src == CLKMGR_PERPLLGRP_SRC_FPGA) {
924 src_hz = f2s_free_hz;
925 } else {
926 src_hz = 0;
927 }
928
929 return src_hz / divisor;
930}
931
932unsigned int cm_get_l4_noc_hz(unsigned int nocdivshift)
933{
934 unsigned int divisor2 = 1 <<
935 ((readl(&clock_manager_base->main_pll.nocdiv) >>
936 nocdivshift) & CLKMGR_MAINPLL_NOCDIV_MSK);
937
938 return cm_get_noc_clk_hz() / divisor2;
939}
940
941int cm_basic_init(const void *blob)
942{
943 struct mainpll_cfg main_cfg;
944 struct perpll_cfg per_cfg;
Ley Foon Tanca40f292017-04-26 02:44:39 +0800945 int rval;
946
947 /* initialize to zero for use case of optional node */
948 memset(&main_cfg, 0, sizeof(main_cfg));
949 memset(&per_cfg, 0, sizeof(per_cfg));
Ley Foon Tanca40f292017-04-26 02:44:39 +0800950
Marek Vasutec472e02018-05-12 00:09:21 +0200951 rval = of_get_clk_cfg(blob, &main_cfg, &per_cfg);
Ley Foon Tanca40f292017-04-26 02:44:39 +0800952 if (rval)
953 return rval;
954
955 rval = cm_full_cfg(&main_cfg, &per_cfg);
956
957 cm_l4_main_clk_hz =
958 cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MAINCLK_LSB);
959
960 cm_l4_mp_clk_hz = cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MPCLK_LSB);
961
962 cm_l4_sp_clk_hz = cm_get_l4_sp_clk_hz();
963
964 cm_l4_sys_free_clk_hz = cm_get_noc_clk_hz() / 4;
965
966 return rval;
967}
968
969unsigned long cm_get_mpu_clk_hz(void)
970{
971 u32 reg, clk_hz;
972 u32 clk_src, mainmpuclk_reg;
973
974 mainmpuclk_reg = readl(&clock_manager_base->main_pll.mpuclk);
975
976 clk_src = (mainmpuclk_reg >> CLKMGR_MAINPLL_MPUCLK_SRC_LSB) &
977 CLKMGR_MAINPLL_MPUCLK_SRC_MSK;
978
979 reg = readl(&clock_manager_base->altera.mpuclk);
980 /* Check MPU clock source: main, periph, osc1, intosc or f2s? */
981 switch (clk_src) {
982 case CLKMGR_MAINPLL_MPUCLK_SRC_MAIN:
983 clk_hz = cm_get_main_vco_clk_hz();
984 clk_hz /= (reg & CLKMGR_MAINPLL_MPUCLK_CNT_MSK) + 1;
985 break;
986 case CLKMGR_MAINPLL_MPUCLK_SRC_PERI:
987 clk_hz = cm_get_per_vco_clk_hz();
988 clk_hz /= (((reg >> CLKMGR_MAINPLL_MPUCLK_PERICNT_LSB) &
989 CLKMGR_MAINPLL_MPUCLK_CNT_MSK) + 1);
990 break;
991 case CLKMGR_MAINPLL_MPUCLK_SRC_OSC1:
992 clk_hz = eosc1_hz;
993 break;
994 case CLKMGR_MAINPLL_MPUCLK_SRC_INTOSC:
995 clk_hz = cb_intosc_hz;
996 break;
997 case CLKMGR_MAINPLL_MPUCLK_SRC_FPGA:
998 clk_hz = f2s_free_hz;
999 break;
1000 default:
1001 printf("cm_get_mpu_clk_hz invalid clk_src %d\n", clk_src);
1002 return 0;
1003 }
1004
1005 clk_hz /= (mainmpuclk_reg & CLKMGR_MAINPLL_MPUCLK_CNT_MSK) + 1;
1006
1007 return clk_hz;
1008}
1009
1010unsigned int cm_get_per_vco_clk_hz(void)
1011{
1012 u32 src_hz = 0;
1013 u32 clk_src = 0;
1014 u32 numer = 0;
1015 u32 denom = 0;
1016 u32 vco = 0;
1017
1018 clk_src = readl(&clock_manager_base->per_pll.vco0);
1019
1020 clk_src = (clk_src >> CLKMGR_PERPLL_VCO0_PSRC_LSB) &
1021 CLKMGR_PERPLL_VCO0_PSRC_MSK;
1022
1023 if (clk_src == CLKMGR_PERPLL_VCO0_PSRC_EOSC) {
1024 src_hz = eosc1_hz;
1025 } else if (clk_src == CLKMGR_PERPLL_VCO0_PSRC_E_INTOSC) {
1026 src_hz = cb_intosc_hz;
1027 } else if (clk_src == CLKMGR_PERPLL_VCO0_PSRC_F2S) {
1028 src_hz = f2s_free_hz;
1029 } else if (clk_src == CLKMGR_PERPLL_VCO0_PSRC_MAIN) {
1030 src_hz = cm_get_main_vco_clk_hz();
1031 src_hz /= (readl(&clock_manager_base->main_pll.cntr15clk) &
1032 CLKMGR_MAINPLL_CNTRCLK_MSK) + 1;
1033 } else {
1034 printf("cm_get_per_vco_clk_hz invalid clk_src %d\n", clk_src);
1035 return 0;
1036 }
1037
1038 vco = readl(&clock_manager_base->per_pll.vco1);
1039
1040 numer = vco & CLKMGR_PERPLL_VCO1_NUMER_MSK;
1041
1042 denom = (vco >> CLKMGR_PERPLL_VCO1_DENOM_LSB) &
1043 CLKMGR_PERPLL_VCO1_DENOM_MSK;
1044
1045 vco = src_hz;
1046 vco /= 1 + denom;
1047 vco *= 1 + numer;
1048
1049 return vco;
1050}
1051
1052unsigned int cm_get_main_vco_clk_hz(void)
1053{
1054 u32 src_hz, numer, denom, vco;
1055
1056 u32 clk_src = readl(&clock_manager_base->main_pll.vco0);
1057
1058 clk_src = (clk_src >> CLKMGR_MAINPLL_VCO0_PSRC_LSB) &
1059 CLKMGR_MAINPLL_VCO0_PSRC_MSK;
1060
1061 if (clk_src == CLKMGR_MAINPLL_VCO0_PSRC_EOSC) {
1062 src_hz = eosc1_hz;
1063 } else if (clk_src == CLKMGR_MAINPLL_VCO0_PSRC_E_INTOSC) {
1064 src_hz = cb_intosc_hz;
1065 } else if (clk_src == CLKMGR_MAINPLL_VCO0_PSRC_F2S) {
1066 src_hz = f2s_free_hz;
1067 } else {
1068 printf("cm_get_main_vco_clk_hz invalid clk_src %d\n", clk_src);
1069 return 0;
1070 }
1071
1072 vco = readl(&clock_manager_base->main_pll.vco1);
1073
1074 numer = vco & CLKMGR_MAINPLL_VCO1_NUMER_MSK;
1075
1076 denom = (vco >> CLKMGR_MAINPLL_VCO1_DENOM_LSB) &
1077 CLKMGR_MAINPLL_VCO1_DENOM_MSK;
1078
1079 vco = src_hz;
1080 vco /= 1 + denom;
1081 vco *= 1 + numer;
1082
1083 return vco;
1084}
1085
1086unsigned int cm_get_l4_sp_clk_hz(void)
1087{
1088 return cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4SPCLK_LSB);
1089}
1090
1091unsigned int cm_get_mmc_controller_clk_hz(void)
1092{
1093 u32 clk_hz = 0;
1094 u32 clk_input = 0;
1095
1096 clk_input = readl(&clock_manager_base->per_pll.cntr6clk);
1097 clk_input = (clk_input >> CLKMGR_PERPLL_CNTR6CLK_SRC_LSB) &
1098 CLKMGR_PERPLLGRP_SRC_MSK;
1099
1100 switch (clk_input) {
1101 case CLKMGR_PERPLLGRP_SRC_MAIN:
1102 clk_hz = cm_get_main_vco_clk_hz();
1103 clk_hz /= 1 + (readl(&clock_manager_base->main_pll.cntr6clk) &
1104 CLKMGR_MAINPLL_CNTRCLK_MSK);
1105 break;
1106
1107 case CLKMGR_PERPLLGRP_SRC_PERI:
1108 clk_hz = cm_get_per_vco_clk_hz();
1109 clk_hz /= 1 + (readl(&clock_manager_base->per_pll.cntr6clk) &
1110 CLKMGR_PERPLL_CNTRCLK_MSK);
1111 break;
1112
1113 case CLKMGR_PERPLLGRP_SRC_OSC1:
1114 clk_hz = eosc1_hz;
1115 break;
1116
1117 case CLKMGR_PERPLLGRP_SRC_INTOSC:
1118 clk_hz = cb_intosc_hz;
1119 break;
1120
1121 case CLKMGR_PERPLLGRP_SRC_FPGA:
1122 clk_hz = f2s_free_hz;
1123 break;
1124 }
1125
1126 return clk_hz / 4;
1127}
1128
1129unsigned int cm_get_spi_controller_clk_hz(void)
1130{
1131 return cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MPCLK_LSB);
1132}
1133
1134unsigned int cm_get_qspi_controller_clk_hz(void)
1135{
1136 return cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MAINCLK_LSB);
1137}
1138
Eugeniy Paltsev74739322017-12-28 15:09:02 +03001139/* Override weak dw_spi_get_clk implementation in designware_spi.c driver */
1140int dw_spi_get_clk(struct udevice *bus, ulong *rate)
1141{
1142 *rate = cm_get_spi_controller_clk_hz();
1143
1144 return 0;
1145}
1146
Ley Foon Tanca40f292017-04-26 02:44:39 +08001147void cm_print_clock_quick_summary(void)
1148{
1149 printf("MPU %10ld kHz\n", cm_get_mpu_clk_hz() / 1000);
1150 printf("MMC %8d kHz\n", cm_get_mmc_controller_clk_hz() / 1000);
1151 printf("QSPI %8d kHz\n", cm_get_qspi_controller_clk_hz() / 1000);
1152 printf("SPI %8d kHz\n", cm_get_spi_controller_clk_hz() / 1000);
1153 printf("EOSC1 %8d kHz\n", eosc1_hz / 1000);
1154 printf("cb_intosc %8d kHz\n", cb_intosc_hz / 1000);
1155 printf("f2s_free %8d kHz\n", f2s_free_hz / 1000);
1156 printf("Main VCO %8d kHz\n", cm_get_main_vco_clk_hz() / 1000);
1157 printf("NOC %8d kHz\n", cm_get_noc_clk_hz() / 1000);
1158 printf("L4 Main %8d kHz\n",
1159 cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MAINCLK_LSB) / 1000);
1160 printf("L4 MP %8d kHz\n",
1161 cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MPCLK_LSB) / 1000);
1162 printf("L4 SP %8d kHz\n", cm_get_l4_sp_clk_hz() / 1000);
1163 printf("L4 sys free %8d kHz\n", cm_l4_sys_free_clk_hz / 1000);
1164}