1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2016-2017 Intel Corporation
4 */
5
6#include <common.h>
7#include <fdtdec.h>
8#include <malloc.h>
9#include <asm/io.h>
10#include <dm.h>
11#include <clk.h>
12#include <dm/device-internal.h>
13#include <asm/arch/clock_manager.h>
14#include <linux/delay.h>
15
16#ifdef CONFIG_SPL_BUILD
17
18void sdelay(unsigned long loops);
19u32 wait_on_value(u32 read_bit_mask, u32 match_value, void *read_addr,
20		  u32 bound);
21
22static u32 eosc1_hz;
23static u32 cb_intosc_hz;
24static u32 f2s_free_hz;
25
26struct mainpll_cfg {
27	u32 vco0_psrc;
28	u32 vco1_denom;
29	u32 vco1_numer;
30	u32 mpuclk;
31	u32 mpuclk_cnt;
32	u32 mpuclk_src;
33	u32 nocclk;
34	u32 nocclk_cnt;
35	u32 nocclk_src;
36	u32 cntr2clk_cnt;
37	u32 cntr3clk_cnt;
38	u32 cntr4clk_cnt;
39	u32 cntr5clk_cnt;
40	u32 cntr6clk_cnt;
41	u32 cntr7clk_cnt;
42	u32 cntr7clk_src;
43	u32 cntr8clk_cnt;
44	u32 cntr9clk_cnt;
45	u32 cntr9clk_src;
46	u32 cntr15clk_cnt;
47	u32 nocdiv_l4mainclk;
48	u32 nocdiv_l4mpclk;
49	u32 nocdiv_l4spclk;
50	u32 nocdiv_csatclk;
51	u32 nocdiv_cstraceclk;
52	u32 nocdiv_cspdbclk;
53};
54
55struct perpll_cfg {
56	u32 vco0_psrc;
57	u32 vco1_denom;
58	u32 vco1_numer;
59	u32 cntr2clk_cnt;
60	u32 cntr2clk_src;
61	u32 cntr3clk_cnt;
62	u32 cntr3clk_src;
63	u32 cntr4clk_cnt;
64	u32 cntr4clk_src;
65	u32 cntr5clk_cnt;
66	u32 cntr5clk_src;
67	u32 cntr6clk_cnt;
68	u32 cntr6clk_src;
69	u32 cntr7clk_cnt;
70	u32 cntr8clk_cnt;
71	u32 cntr8clk_src;
72	u32 cntr9clk_cnt;
73	u32 cntr9clk_src;
74	u32 emacctl_emac0sel;
75	u32 emacctl_emac1sel;
76	u32 emacctl_emac2sel;
77	u32 gpiodiv_gpiodbclk;
78};
79
80struct strtou32 {
81	const char *str;
82	const u32 val;
83};
84
85static const struct strtou32 mainpll_cfg_tab[] = {
86	{ "vco0-psrc", offsetof(struct mainpll_cfg, vco0_psrc) },
87	{ "vco1-denom", offsetof(struct mainpll_cfg, vco1_denom) },
88	{ "vco1-numer", offsetof(struct mainpll_cfg, vco1_numer) },
89	{ "mpuclk-cnt", offsetof(struct mainpll_cfg, mpuclk_cnt) },
90	{ "mpuclk-src", offsetof(struct mainpll_cfg, mpuclk_src) },
91	{ "nocclk-cnt", offsetof(struct mainpll_cfg, nocclk_cnt) },
92	{ "nocclk-src", offsetof(struct mainpll_cfg, nocclk_src) },
93	{ "cntr2clk-cnt", offsetof(struct mainpll_cfg, cntr2clk_cnt) },
94	{ "cntr3clk-cnt", offsetof(struct mainpll_cfg, cntr3clk_cnt) },
95	{ "cntr4clk-cnt", offsetof(struct mainpll_cfg, cntr4clk_cnt) },
96	{ "cntr5clk-cnt", offsetof(struct mainpll_cfg, cntr5clk_cnt) },
97	{ "cntr6clk-cnt", offsetof(struct mainpll_cfg, cntr6clk_cnt) },
98	{ "cntr7clk-cnt", offsetof(struct mainpll_cfg, cntr7clk_cnt) },
99	{ "cntr7clk-src", offsetof(struct mainpll_cfg, cntr7clk_src) },
100	{ "cntr8clk-cnt", offsetof(struct mainpll_cfg, cntr8clk_cnt) },
101	{ "cntr9clk-cnt", offsetof(struct mainpll_cfg, cntr9clk_cnt) },
102	{ "cntr9clk-src", offsetof(struct mainpll_cfg, cntr9clk_src) },
103	{ "cntr15clk-cnt", offsetof(struct mainpll_cfg, cntr15clk_cnt) },
104	{ "nocdiv-l4mainclk", offsetof(struct mainpll_cfg, nocdiv_l4mainclk) },
105	{ "nocdiv-l4mpclk", offsetof(struct mainpll_cfg, nocdiv_l4mpclk) },
106	{ "nocdiv-l4spclk", offsetof(struct mainpll_cfg, nocdiv_l4spclk) },
107	{ "nocdiv-csatclk", offsetof(struct mainpll_cfg, nocdiv_csatclk) },
108	{ "nocdiv-cstraceclk", offsetof(struct mainpll_cfg, nocdiv_cstraceclk) },
109	{ "nocdiv-cspdbgclk", offsetof(struct mainpll_cfg, nocdiv_cspdbclk) },
110};
111
112static const struct strtou32 perpll_cfg_tab[] = {
113	{ "vco0-psrc", offsetof(struct perpll_cfg, vco0_psrc) },
114	{ "vco1-denom", offsetof(struct perpll_cfg, vco1_denom) },
115	{ "vco1-numer", offsetof(struct perpll_cfg, vco1_numer) },
116	{ "cntr2clk-cnt", offsetof(struct perpll_cfg, cntr2clk_cnt) },
117	{ "cntr2clk-src", offsetof(struct perpll_cfg, cntr2clk_src) },
118	{ "cntr3clk-cnt", offsetof(struct perpll_cfg, cntr3clk_cnt) },
119	{ "cntr3clk-src", offsetof(struct perpll_cfg, cntr3clk_src) },
120	{ "cntr4clk-cnt", offsetof(struct perpll_cfg, cntr4clk_cnt) },
121	{ "cntr4clk-src", offsetof(struct perpll_cfg, cntr4clk_src) },
122	{ "cntr5clk-cnt", offsetof(struct perpll_cfg, cntr5clk_cnt) },
123	{ "cntr5clk-src", offsetof(struct perpll_cfg, cntr5clk_src) },
124	{ "cntr6clk-cnt", offsetof(struct perpll_cfg, cntr6clk_cnt) },
125	{ "cntr6clk-src", offsetof(struct perpll_cfg, cntr6clk_src) },
126	{ "cntr7clk-cnt", offsetof(struct perpll_cfg, cntr7clk_cnt) },
127	{ "cntr8clk-cnt", offsetof(struct perpll_cfg, cntr8clk_cnt) },
128	{ "cntr8clk-src", offsetof(struct perpll_cfg, cntr8clk_src) },
129	{ "cntr9clk-cnt", offsetof(struct perpll_cfg, cntr9clk_cnt) },
130	{ "emacctl-emac0sel", offsetof(struct perpll_cfg, emacctl_emac0sel) },
131	{ "emacctl-emac1sel", offsetof(struct perpll_cfg, emacctl_emac1sel) },
132	{ "emacctl-emac2sel", offsetof(struct perpll_cfg, emacctl_emac2sel) },
133	{ "gpiodiv-gpiodbclk", offsetof(struct perpll_cfg, gpiodiv_gpiodbclk) },
134};
135
136static const struct strtou32 alteragrp_cfg_tab[] = {
137	{ "nocclk", offsetof(struct mainpll_cfg, nocclk) },
138	{ "mpuclk", offsetof(struct mainpll_cfg, mpuclk) },
139};
140
141struct strtopu32 {
142	const char *str;
143	u32 *p;
144};
145
146const struct strtopu32 dt_to_val[] = {
147	{ "altera_arria10_hps_eosc1", &eosc1_hz },
148	{ "altera_arria10_hps_cb_intosc_ls", &cb_intosc_hz },
149	{ "altera_arria10_hps_f2h_free", &f2s_free_hz },
150};
151
152static int of_to_struct(const void *blob, int node, const struct strtou32 *cfg_tab,
153			int cfg_tab_len, void *cfg)
154{
155	int i;
156	u32 val;
157
158	for (i = 0; i < cfg_tab_len; i++) {
159		if (fdtdec_get_int_array(blob, node, cfg_tab[i].str, &val, 1)) {
160			/* could not find required property */
161			return -EINVAL;
162		}
163		*(u32 *)(cfg + cfg_tab[i].val) = val;
164	}
165
166	return 0;
167}
168
169static int of_get_input_clks(const void *blob)
170{
171	struct udevice *dev;
172	struct clk clk;
173	int i, ret;
174
175	for (i = 0; i < ARRAY_SIZE(dt_to_val); i++) {
176		memset(&clk, 0, sizeof(clk));
177
178		ret = uclass_get_device_by_name(UCLASS_CLK, dt_to_val[i].str,
179						&dev);
180		if (ret)
181			return ret;
182
183		ret = clk_request(dev, &clk);
184		if (ret)
185			return ret;
186
187		*dt_to_val[i].p = clk_get_rate(&clk);
188	}
189
190	return 0;
191}
192
193static int of_get_clk_cfg(const void *blob, struct mainpll_cfg *main_cfg,
194			  struct perpll_cfg *per_cfg)
195{
196	int ret, node, child, len;
197	const char *node_name;
198
199	ret = of_get_input_clks(blob);
200	if (ret)
201		return ret;
202
203	node = fdtdec_next_compatible(blob, 0, COMPAT_ALTERA_SOCFPGA_CLK_INIT);
204
205	if (node < 0)
206		return -EINVAL;
207
208	child = fdt_first_subnode(blob, node);
209
210	if (child < 0)
211		return -EINVAL;
212
213	node_name = fdt_get_name(blob, child, &len);
214
215	while (node_name) {
216		if (!strcmp(node_name, "mainpll")) {
217			if (of_to_struct(blob, child, mainpll_cfg_tab,
218					 ARRAY_SIZE(mainpll_cfg_tab), main_cfg))
219				return -EINVAL;
220		} else if (!strcmp(node_name, "perpll")) {
221			if (of_to_struct(blob, child, perpll_cfg_tab,
222					 ARRAY_SIZE(perpll_cfg_tab), per_cfg))
223				return -EINVAL;
224		} else if (!strcmp(node_name, "alteragrp")) {
225			if (of_to_struct(blob, child, alteragrp_cfg_tab,
226					 ARRAY_SIZE(alteragrp_cfg_tab), main_cfg))
227				return -EINVAL;
228		}
229		child = fdt_next_subnode(blob, child);
230
231		if (child < 0)
232			break;
233
234		node_name = fdt_get_name(blob, child, &len);
235	}
236
237	return 0;
238}
239
240/* calculate the intended main VCO frequency based on handoff */
241static unsigned int cm_calc_handoff_main_vco_clk_hz
242					(struct mainpll_cfg *main_cfg)
243{
244	unsigned int clk_hz;
245
246	/* Check main VCO clock source: eosc, intosc or f2s? */
247	switch (main_cfg->vco0_psrc) {
248	case CLKMGR_MAINPLL_VCO0_PSRC_EOSC:
249		clk_hz = eosc1_hz;
250		break;
251	case CLKMGR_MAINPLL_VCO0_PSRC_E_INTOSC:
252		clk_hz = cb_intosc_hz;
253		break;
254	case CLKMGR_MAINPLL_VCO0_PSRC_F2S:
255		clk_hz = f2s_free_hz;
256		break;
257	default:
258		return 0;
259	}
260
261	/* calculate the VCO frequency */
262	clk_hz /= 1 + main_cfg->vco1_denom;
263	clk_hz *= 1 + main_cfg->vco1_numer;
264
265	return clk_hz;
266}
267
268/* calculate the intended periph VCO frequency based on handoff */
269static unsigned int cm_calc_handoff_periph_vco_clk_hz(
270		struct mainpll_cfg *main_cfg, struct perpll_cfg *per_cfg)
271{
272	unsigned int clk_hz;
273
274	/* Check periph VCO clock source: eosc, intosc, f2s or mainpll? */
275	switch (per_cfg->vco0_psrc) {
276	case CLKMGR_PERPLL_VCO0_PSRC_EOSC:
277		clk_hz = eosc1_hz;
278		break;
279	case CLKMGR_PERPLL_VCO0_PSRC_E_INTOSC:
280		clk_hz = cb_intosc_hz;
281		break;
282	case CLKMGR_PERPLL_VCO0_PSRC_F2S:
283		clk_hz = f2s_free_hz;
284		break;
285	case CLKMGR_PERPLL_VCO0_PSRC_MAIN:
286		clk_hz = cm_calc_handoff_main_vco_clk_hz(main_cfg);
287		clk_hz /= main_cfg->cntr15clk_cnt;
288		break;
289	default:
290		return 0;
291	}
292
293	/* calculate the VCO frequency */
294	clk_hz /= 1 + per_cfg->vco1_denom;
295	clk_hz *= 1 + per_cfg->vco1_numer;
296
297	return clk_hz;
298}
299
300/* calculate the intended MPU clock frequency based on handoff */
301static unsigned int cm_calc_handoff_mpu_clk_hz(struct mainpll_cfg *main_cfg,
302					       struct perpll_cfg *per_cfg)
303{
304	unsigned int clk_hz;
305
306	/* Check MPU clock source: main, periph, osc1, intosc or f2s? */
307	switch (main_cfg->mpuclk_src) {
308	case CLKMGR_MAINPLL_MPUCLK_SRC_MAIN:
309		clk_hz = cm_calc_handoff_main_vco_clk_hz(main_cfg);
310		clk_hz /= (main_cfg->mpuclk & CLKMGR_MAINPLL_MPUCLK_CNT_MSK)
311			   + 1;
312		break;
313	case CLKMGR_MAINPLL_MPUCLK_SRC_PERI:
314		clk_hz = cm_calc_handoff_periph_vco_clk_hz(main_cfg, per_cfg);
315		clk_hz /= ((main_cfg->mpuclk >>
316			   CLKMGR_MAINPLL_MPUCLK_PERICNT_LSB) &
317			   CLKMGR_MAINPLL_MPUCLK_CNT_MSK) + 1;
318		break;
319	case CLKMGR_MAINPLL_MPUCLK_SRC_OSC1:
320		clk_hz = eosc1_hz;
321		break;
322	case CLKMGR_MAINPLL_MPUCLK_SRC_INTOSC:
323		clk_hz = cb_intosc_hz;
324		break;
325	case CLKMGR_MAINPLL_MPUCLK_SRC_FPGA:
326		clk_hz = f2s_free_hz;
327		break;
328	default:
329		return 0;
330	}
331
332	clk_hz /= main_cfg->mpuclk_cnt + 1;
333	return clk_hz;
334}
335
336/* calculate the intended NOC clock frequency based on handoff */
337static unsigned int cm_calc_handoff_noc_clk_hz(struct mainpll_cfg *main_cfg,
338					       struct perpll_cfg *per_cfg)
339{
340	unsigned int clk_hz;
341
342	/* Check MPU clock source: main, periph, osc1, intosc or f2s? */
343	switch (main_cfg->nocclk_src) {
344	case CLKMGR_MAINPLL_NOCCLK_SRC_MAIN:
345		clk_hz = cm_calc_handoff_main_vco_clk_hz(main_cfg);
346		clk_hz /= (main_cfg->nocclk & CLKMGR_MAINPLL_NOCCLK_CNT_MSK)
347			 + 1;
348		break;
349	case CLKMGR_MAINPLL_NOCCLK_SRC_PERI:
350		clk_hz = cm_calc_handoff_periph_vco_clk_hz(main_cfg, per_cfg);
351		clk_hz /= ((main_cfg->nocclk >>
352			   CLKMGR_MAINPLL_NOCCLK_PERICNT_LSB) &
353			   CLKMGR_MAINPLL_NOCCLK_CNT_MSK) + 1;
354		break;
355	case CLKMGR_MAINPLL_NOCCLK_SRC_OSC1:
356		clk_hz = eosc1_hz;
357		break;
358	case CLKMGR_MAINPLL_NOCCLK_SRC_INTOSC:
359		clk_hz = cb_intosc_hz;
360		break;
361	case CLKMGR_MAINPLL_NOCCLK_SRC_FPGA:
362		clk_hz = f2s_free_hz;
363		break;
364	default:
365		return 0;
366	}
367
368	clk_hz /= main_cfg->nocclk_cnt + 1;
369	return clk_hz;
370}
371
372/* return 1 if PLL ramp is required */
373static int cm_is_pll_ramp_required(int main0periph1,
374				   struct mainpll_cfg *main_cfg,
375				   struct perpll_cfg *per_cfg)
376{
377	/* Check for main PLL */
378	if (main0periph1 == 0) {
379		/*
380		 * PLL ramp is not required if both MPU clock and NOC clock are
381		 * not sourced from main PLL
382		 */
383		if (main_cfg->mpuclk_src != CLKMGR_MAINPLL_MPUCLK_SRC_MAIN &&
384		    main_cfg->nocclk_src != CLKMGR_MAINPLL_NOCCLK_SRC_MAIN)
385			return 0;
386
387		/*
388		 * PLL ramp is required if MPU clock is sourced from main PLL
389		 * and MPU clock is over 900MHz (as advised by HW team)
390		 */
391		if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_MAIN &&
392		    (cm_calc_handoff_mpu_clk_hz(main_cfg, per_cfg) >
393		     CLKMGR_PLL_RAMP_MPUCLK_THRESHOLD_HZ))
394			return 1;
395
396		/*
397		 * PLL ramp is required if NOC clock is sourced from main PLL
398		 * and NOC clock is over 300MHz (as advised by HW team)
399		 */
400		if (main_cfg->nocclk_src == CLKMGR_MAINPLL_NOCCLK_SRC_MAIN &&
401		    (cm_calc_handoff_noc_clk_hz(main_cfg, per_cfg) >
402		     CLKMGR_PLL_RAMP_NOCCLK_THRESHOLD_HZ))
403			return 2;
404
405	} else if (main0periph1 == 1) {
406		/*
407		 * PLL ramp is not required if both MPU clock and NOC clock are
408		 * not sourced from periph PLL
409		 */
410		if (main_cfg->mpuclk_src != CLKMGR_MAINPLL_MPUCLK_SRC_PERI &&
411		    main_cfg->nocclk_src != CLKMGR_MAINPLL_NOCCLK_SRC_PERI)
412			return 0;
413
414		/*
415		 * PLL ramp is required if MPU clock are source from periph PLL
416		 * and MPU clock is over 900MHz (as advised by HW team)
417		 */
418		if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_PERI &&
419		    (cm_calc_handoff_mpu_clk_hz(main_cfg, per_cfg) >
420		     CLKMGR_PLL_RAMP_MPUCLK_THRESHOLD_HZ))
421			return 1;
422
423		/*
424		 * PLL ramp is required if NOC clock are source from periph PLL
425		 * and NOC clock is over 300MHz (as advised by HW team)
426		 */
427		if (main_cfg->nocclk_src == CLKMGR_MAINPLL_NOCCLK_SRC_PERI &&
428		    (cm_calc_handoff_noc_clk_hz(main_cfg, per_cfg) >
429		     CLKMGR_PLL_RAMP_NOCCLK_THRESHOLD_HZ))
430			return 2;
431	}
432
433	return 0;
434}
435
436static u32 cm_calculate_numer(struct mainpll_cfg *main_cfg,
437			      struct perpll_cfg *per_cfg,
438			      u32 safe_hz, u32 clk_hz)
439{
440	u32 cnt;
441	u32 clk;
442	u32 shift;
443	u32 mask;
444	u32 denom;
445
446	if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_MAIN) {
447		cnt = main_cfg->mpuclk_cnt;
448		clk = main_cfg->mpuclk;
449		shift = 0;
450		mask = CLKMGR_MAINPLL_MPUCLK_CNT_MSK;
451		denom = main_cfg->vco1_denom;
452	} else if (main_cfg->nocclk_src == CLKMGR_MAINPLL_NOCCLK_SRC_MAIN) {
453		cnt = main_cfg->nocclk_cnt;
454		clk = main_cfg->nocclk;
455		shift = 0;
456		mask = CLKMGR_MAINPLL_NOCCLK_CNT_MSK;
457		denom = main_cfg->vco1_denom;
458	} else if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_PERI) {
459		cnt = main_cfg->mpuclk_cnt;
460		clk = main_cfg->mpuclk;
461		shift = CLKMGR_MAINPLL_MPUCLK_PERICNT_LSB;
462		mask = CLKMGR_MAINPLL_MPUCLK_CNT_MSK;
463		denom = per_cfg->vco1_denom;
464	} else if (main_cfg->nocclk_src == CLKMGR_MAINPLL_NOCCLK_SRC_PERI) {
465		cnt = main_cfg->nocclk_cnt;
466		clk = main_cfg->nocclk;
467		shift = CLKMGR_MAINPLL_NOCCLK_PERICNT_LSB;
468		mask = CLKMGR_MAINPLL_NOCCLK_CNT_MSK;
469		denom = per_cfg->vco1_denom;
470	} else {
471		return 0;
472	}
473
474	return (safe_hz / clk_hz) * (cnt + 1) * (((clk >> shift) & mask) + 1) *
475		(1 + denom) - 1;
476}
477
478/*
479 * Calculate the new PLL numerator which is based on existing DTS hand off and
480 * intended safe frequency (safe_hz). Note that PLL ramp is only modifying the
481 * numerator while maintaining denominator as denominator will influence the
482 * jitter condition. Please refer A10 HPS TRM for the jitter guide. Note final
483 * value for numerator is minus with 1 to cater our register value
484 * representation.
485 */
486static unsigned int cm_calc_safe_pll_numer(int main0periph1,
487					   struct mainpll_cfg *main_cfg,
488					   struct perpll_cfg *per_cfg,
489					   unsigned int safe_hz)
490{
491	unsigned int clk_hz = 0;
492
493	/* Check for main PLL */
494	if (main0periph1 == 0) {
495		/* Check main VCO clock source: eosc, intosc or f2s? */
496		switch (main_cfg->vco0_psrc) {
497		case CLKMGR_MAINPLL_VCO0_PSRC_EOSC:
498			clk_hz = eosc1_hz;
499			break;
500		case CLKMGR_MAINPLL_VCO0_PSRC_E_INTOSC:
501			clk_hz = cb_intosc_hz;
502			break;
503		case CLKMGR_MAINPLL_VCO0_PSRC_F2S:
504			clk_hz = f2s_free_hz;
505			break;
506		default:
507			return 0;
508		}
509	} else if (main0periph1 == 1) {
510		/* Check periph VCO clock source: eosc, intosc, f2s, mainpll */
511		switch (per_cfg->vco0_psrc) {
512		case CLKMGR_PERPLL_VCO0_PSRC_EOSC:
513			clk_hz = eosc1_hz;
514			break;
515		case CLKMGR_PERPLL_VCO0_PSRC_E_INTOSC:
516			clk_hz = cb_intosc_hz;
517			break;
518		case CLKMGR_PERPLL_VCO0_PSRC_F2S:
519			clk_hz = f2s_free_hz;
520			break;
521		case CLKMGR_PERPLL_VCO0_PSRC_MAIN:
522			clk_hz = cm_calc_handoff_main_vco_clk_hz(main_cfg);
523			clk_hz /= main_cfg->cntr15clk_cnt;
524			break;
525		default:
526			return 0;
527		}
528	} else {
529		return 0;
530	}
531
532	return cm_calculate_numer(main_cfg, per_cfg, safe_hz, clk_hz);
533}
534
535/* ramping the main PLL to final value */
536static void cm_pll_ramp_main(struct mainpll_cfg *main_cfg,
537			     struct perpll_cfg *per_cfg,
538			     unsigned int pll_ramp_main_hz)
539{
540	unsigned int clk_hz = 0, clk_incr_hz = 0, clk_final_hz = 0;
541
542	/* find out the increment value */
543	if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_MAIN) {
544		clk_incr_hz = CLKMGR_PLL_RAMP_MPUCLK_INCREMENT_HZ;
545		clk_final_hz = cm_calc_handoff_mpu_clk_hz(main_cfg, per_cfg);
546	} else if (main_cfg->nocclk_src == CLKMGR_MAINPLL_NOCCLK_SRC_MAIN) {
547		clk_incr_hz = CLKMGR_PLL_RAMP_NOCCLK_INCREMENT_HZ;
548		clk_final_hz = cm_calc_handoff_noc_clk_hz(main_cfg, per_cfg);
549	}
550
551	/* execute the ramping here */
552	for (clk_hz = pll_ramp_main_hz + clk_incr_hz;
553	     clk_hz < clk_final_hz; clk_hz += clk_incr_hz) {
554		writel((main_cfg->vco1_denom <<
555			CLKMGR_MAINPLL_VCO1_DENOM_LSB) |
556			cm_calc_safe_pll_numer(0, main_cfg, per_cfg, clk_hz),
557			socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO1);
558		sdelay(1000000); /* 1ms */
559		cm_wait_for_lock(LOCKED_MASK);
560	}
561	writel((main_cfg->vco1_denom << CLKMGR_MAINPLL_VCO1_DENOM_LSB) |
562		main_cfg->vco1_numer,
563		socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO1);
564	sdelay(1000000); /* 1ms */
565	cm_wait_for_lock(LOCKED_MASK);
566}
567
568/* ramping the periph PLL to final value */
569static void cm_pll_ramp_periph(struct mainpll_cfg *main_cfg,
570			       struct perpll_cfg *per_cfg,
571			       unsigned int pll_ramp_periph_hz)
572{
573	unsigned int clk_hz = 0, clk_incr_hz = 0, clk_final_hz = 0;
574
575	/* find out the increment value */
576	if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_PERI) {
577		clk_incr_hz = CLKMGR_PLL_RAMP_MPUCLK_INCREMENT_HZ;
578		clk_final_hz = cm_calc_handoff_mpu_clk_hz(main_cfg, per_cfg);
579	} else if (main_cfg->nocclk_src == CLKMGR_MAINPLL_NOCCLK_SRC_PERI) {
580		clk_incr_hz = CLKMGR_PLL_RAMP_NOCCLK_INCREMENT_HZ;
581		clk_final_hz = cm_calc_handoff_noc_clk_hz(main_cfg, per_cfg);
582	}
583	/* execute the ramping here */
584	for (clk_hz = pll_ramp_periph_hz + clk_incr_hz;
585	     clk_hz < clk_final_hz; clk_hz += clk_incr_hz) {
586		writel((per_cfg->vco1_denom <<
587			      CLKMGR_PERPLL_VCO1_DENOM_LSB) |
588			      cm_calc_safe_pll_numer(1, main_cfg, per_cfg,
589						     clk_hz),
590			      socfpga_get_clkmgr_addr() +
591			      CLKMGR_A10_PERPLL_VCO1);
592		sdelay(1000000); /* 1ms */
593		cm_wait_for_lock(LOCKED_MASK);
594	}
595	writel((per_cfg->vco1_denom << CLKMGR_PERPLL_VCO1_DENOM_LSB) |
596		      per_cfg->vco1_numer,
597		      socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO1);
598	sdelay(1000000); /* 1ms */
599	cm_wait_for_lock(LOCKED_MASK);
600}
601
602/* function to poll in the fsm busy bit */
603static int cm_busy_wait_for_fsm(void)
604{
605	void *reg = (void *)(socfpga_get_clkmgr_addr() + CLKMGR_STAT);
606
607	/* 20s timeout */
608	return wait_on_value(CLKMGR_STAT_BUSY, 0, reg, 100000000);
609}
610
611/*
612 * Setup clocks while making no assumptions of the
613 * previous state of the clocks.
614 *
615 * Start by being paranoid and gate all sw managed clocks
616 *
617 * Put all plls in bypass
618 *
619 * Put all plls VCO registers back to reset value (bgpwr dwn).
620 *
621 * Put peripheral and main pll src to reset value to avoid glitch.
622 *
623 * Delay 5 us.
624 *
625 * Deassert bg pwr dn and set numerator and denominator
626 *
627 * Start 7 us timer.
628 *
629 * set internal dividers
630 *
631 * Wait for 7 us timer.
632 *
633 * Enable plls
634 *
635 * Set external dividers while plls are locking
636 *
637 * Wait for pll lock
638 *
639 * Assert/deassert outreset all.
640 *
641 * Take all pll's out of bypass
642 *
643 * Clear safe mode
644 *
645 * set source main and peripheral clocks
646 *
647 * Ungate clocks
648 */
649
650static int cm_full_cfg(struct mainpll_cfg *main_cfg, struct perpll_cfg *per_cfg)
651{
652	unsigned int pll_ramp_main_hz = 0, pll_ramp_periph_hz = 0,
653		ramp_required;
654
655	/* gate off all mainpll clock excpet HW managed clock */
656	writel(CLKMGR_MAINPLL_EN_S2FUSER0CLKEN_SET_MSK |
657		CLKMGR_MAINPLL_EN_HMCPLLREFCLKEN_SET_MSK,
658		socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_ENR);
659
660	/* now we can gate off the rest of the peripheral clocks */
661	writel(0, socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_EN);
662
663	/* Put all plls in external bypass */
664	writel(CLKMGR_MAINPLL_BYPASS_RESET,
665	       socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_BYPASSS);
666	writel(CLKMGR_PERPLL_BYPASS_RESET,
667	       socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_BYPASSS);
668
669	/*
670	 * Put all plls VCO registers back to reset value.
671	 * Some code might have messed with them. At same time set the
672	 * desired clock source
673	 */
674	writel(CLKMGR_MAINPLL_VCO0_RESET |
675	       CLKMGR_MAINPLL_VCO0_REGEXTSEL_SET_MSK |
676	       (main_cfg->vco0_psrc << CLKMGR_MAINPLL_VCO0_PSRC_LSB),
677	       socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO0);
678
679	writel(CLKMGR_PERPLL_VCO0_RESET |
680	       CLKMGR_PERPLL_VCO0_REGEXTSEL_SET_MSK |
681	       (per_cfg->vco0_psrc << CLKMGR_PERPLL_VCO0_PSRC_LSB),
682	       socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO0);
683
684	writel(CLKMGR_MAINPLL_VCO1_RESET,
685	       socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO1);
686	writel(CLKMGR_PERPLL_VCO1_RESET,
687	       socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO1);
688
689	/* clear the interrupt register status register */
690	writel(CLKMGR_CLKMGR_INTR_MAINPLLLOST_SET_MSK |
691		CLKMGR_CLKMGR_INTR_PERPLLLOST_SET_MSK |
692		CLKMGR_CLKMGR_INTR_MAINPLLRFSLIP_SET_MSK |
693		CLKMGR_CLKMGR_INTR_PERPLLRFSLIP_SET_MSK |
694		CLKMGR_CLKMGR_INTR_MAINPLLFBSLIP_SET_MSK |
695		CLKMGR_CLKMGR_INTR_PERPLLFBSLIP_SET_MSK |
696		CLKMGR_CLKMGR_INTR_MAINPLLACHIEVED_SET_MSK |
697		CLKMGR_CLKMGR_INTR_PERPLLACHIEVED_SET_MSK,
698		socfpga_get_clkmgr_addr() + CLKMGR_A10_INTR);
699
700	/* Program VCO Numerator and Denominator for main PLL */
701	ramp_required = cm_is_pll_ramp_required(0, main_cfg, per_cfg);
702	if (ramp_required) {
703		/* set main PLL to safe starting threshold frequency */
704		if (ramp_required == 1)
705			pll_ramp_main_hz = CLKMGR_PLL_RAMP_MPUCLK_THRESHOLD_HZ;
706		else if (ramp_required == 2)
707			pll_ramp_main_hz = CLKMGR_PLL_RAMP_NOCCLK_THRESHOLD_HZ;
708
709		writel((main_cfg->vco1_denom <<
710			CLKMGR_MAINPLL_VCO1_DENOM_LSB) |
711			cm_calc_safe_pll_numer(0, main_cfg, per_cfg,
712					       pll_ramp_main_hz),
713			socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO1);
714	} else
715		writel((main_cfg->vco1_denom <<
716		       CLKMGR_MAINPLL_VCO1_DENOM_LSB) |
717		       main_cfg->vco1_numer,
718		       socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO1);
719
720	/* Program VCO Numerator and Denominator for periph PLL */
721	ramp_required = cm_is_pll_ramp_required(1, main_cfg, per_cfg);
722	if (ramp_required) {
723		/* set periph PLL to safe starting threshold frequency */
724		if (ramp_required == 1)
725			pll_ramp_periph_hz =
726				CLKMGR_PLL_RAMP_MPUCLK_THRESHOLD_HZ;
727		else if (ramp_required == 2)
728			pll_ramp_periph_hz =
729				CLKMGR_PLL_RAMP_NOCCLK_THRESHOLD_HZ;
730
731		writel((per_cfg->vco1_denom <<
732			CLKMGR_PERPLL_VCO1_DENOM_LSB) |
733			cm_calc_safe_pll_numer(1, main_cfg, per_cfg,
734					       pll_ramp_periph_hz),
735			socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO1);
736	} else
737		writel((per_cfg->vco1_denom <<
738			CLKMGR_PERPLL_VCO1_DENOM_LSB) |
739			per_cfg->vco1_numer,
740			socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO1);
741
742	/* Wait for at least 5 us */
743	sdelay(5000);
744
745	/* Now deassert BGPWRDN and PWRDN */
746	clrbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO0,
747		     CLKMGR_MAINPLL_VCO0_BGPWRDN_SET_MSK |
748		     CLKMGR_MAINPLL_VCO0_PWRDN_SET_MSK);
749	clrbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO0,
750		     CLKMGR_PERPLL_VCO0_BGPWRDN_SET_MSK |
751		     CLKMGR_PERPLL_VCO0_PWRDN_SET_MSK);
752
753	/* Wait for at least 7 us */
754	sdelay(7000);
755
756	/* enable the VCO and disable the external regulator to PLL */
757	writel((readl(socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO0) &
758		~CLKMGR_MAINPLL_VCO0_REGEXTSEL_SET_MSK) |
759		CLKMGR_MAINPLL_VCO0_EN_SET_MSK,
760		socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO0);
761	writel((readl(socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO0) &
762		~CLKMGR_PERPLL_VCO0_REGEXTSEL_SET_MSK) |
763		CLKMGR_PERPLL_VCO0_EN_SET_MSK,
764		socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO0);
765
766	/* setup all the main PLL counter and clock source */
767	writel(main_cfg->nocclk,
768	       socfpga_get_clkmgr_addr() + CLKMGR_A10_ALTR_NOCCLK);
769	writel(main_cfg->mpuclk,
770	       socfpga_get_clkmgr_addr() + CLKMGR_A10_ALTR_MPUCLK);
771
772	/* main_emaca_clk divider */
773	writel(main_cfg->cntr2clk_cnt,
774	       socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_CNTR2CLK);
775	/* main_emacb_clk divider */
776	writel(main_cfg->cntr3clk_cnt,
777	       socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_CNTR3CLK);
778	/* main_emac_ptp_clk divider */
779	writel(main_cfg->cntr4clk_cnt,
780	       socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_CNTR4CLK);
781	/* main_gpio_db_clk divider */
782	writel(main_cfg->cntr5clk_cnt,
783	       socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_CNTR5CLK);
784	/* main_sdmmc_clk divider */
785	writel(main_cfg->cntr6clk_cnt,
786	       socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_CNTR6CLK);
787	/* main_s2f_user0_clk divider */
788	writel(main_cfg->cntr7clk_cnt |
789	       (main_cfg->cntr7clk_src << CLKMGR_MAINPLL_CNTR7CLK_SRC_LSB),
790	       socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_CNTR7CLK);
791	/* main_s2f_user1_clk divider */
792	writel(main_cfg->cntr8clk_cnt,
793	       socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_CNTR8CLK);
794	/* main_hmc_pll_clk divider */
795	writel(main_cfg->cntr9clk_cnt |
796	       (main_cfg->cntr9clk_src << CLKMGR_MAINPLL_CNTR9CLK_SRC_LSB),
797	       socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_CNTR9CLK);
798	/* main_periph_ref_clk divider */
799	writel(main_cfg->cntr15clk_cnt,
800	       socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_CNTR15CLK);
801
802	/* setup all the peripheral PLL counter and clock source */
803	/* peri_emaca_clk divider */
804	writel(per_cfg->cntr2clk_cnt |
805	       (per_cfg->cntr2clk_src << CLKMGR_PERPLL_CNTR2CLK_SRC_LSB),
806	       socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_CNTR2CLK);
807	/* peri_emacb_clk divider */
808	writel(per_cfg->cntr3clk_cnt |
809	       (per_cfg->cntr3clk_src << CLKMGR_PERPLL_CNTR3CLK_SRC_LSB),
810	       socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_CNTR3CLK);
811	/* peri_emac_ptp_clk divider */
812	writel(per_cfg->cntr4clk_cnt |
813	       (per_cfg->cntr4clk_src << CLKMGR_PERPLL_CNTR4CLK_SRC_LSB),
814	       socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_CNTR4CLK);
815	/* peri_gpio_db_clk divider */
816	writel(per_cfg->cntr5clk_cnt |
817	       (per_cfg->cntr5clk_src << CLKMGR_PERPLL_CNTR5CLK_SRC_LSB),
818	       socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_CNTR5CLK);
819	/* peri_sdmmc_clk divider */
820	writel(per_cfg->cntr6clk_cnt |
821	       (per_cfg->cntr6clk_src << CLKMGR_PERPLL_CNTR6CLK_SRC_LSB),
822	       socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_CNTR6CLK);
823	/* peri_s2f_user0_clk divider */
824	writel(per_cfg->cntr7clk_cnt,
825	       socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_CNTR7CLK);
826	/* peri_s2f_user1_clk divider */
827	writel(per_cfg->cntr8clk_cnt |
828	       (per_cfg->cntr8clk_src << CLKMGR_PERPLL_CNTR8CLK_SRC_LSB),
829	       socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_CNTR8CLK);
830	/* peri_hmc_pll_clk divider */
831	writel(per_cfg->cntr9clk_cnt,
832	       socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_CNTR9CLK);
833
834	/* setup all the external PLL counter */
835	/* mpu wrapper / external divider */
836	writel(main_cfg->mpuclk_cnt |
837	       (main_cfg->mpuclk_src << CLKMGR_MAINPLL_MPUCLK_SRC_LSB),
838	       socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_MPUCLK);
839	/* NOC wrapper / external divider */
840	writel(main_cfg->nocclk_cnt |
841	       (main_cfg->nocclk_src << CLKMGR_MAINPLL_NOCCLK_SRC_LSB),
842	       socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_NOCCLK);
843	/* NOC subclock divider such as l4 */
844	writel(main_cfg->nocdiv_l4mainclk |
845	       (main_cfg->nocdiv_l4mpclk <<
846		CLKMGR_MAINPLL_NOCDIV_L4MPCLK_LSB) |
847	       (main_cfg->nocdiv_l4spclk <<
848		CLKMGR_MAINPLL_NOCDIV_L4SPCLK_LSB) |
849	       (main_cfg->nocdiv_csatclk <<
850		CLKMGR_MAINPLL_NOCDIV_CSATCLK_LSB) |
851	       (main_cfg->nocdiv_cstraceclk <<
852		CLKMGR_MAINPLL_NOCDIV_CSTRACECLK_LSB) |
853	       (main_cfg->nocdiv_cspdbclk <<
854		CLKMGR_MAINPLL_NOCDIV_CSPDBGCLK_LSB),
855	       socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_NOCDIV);
856	/* gpio_db external divider */
857	writel(per_cfg->gpiodiv_gpiodbclk,
858	       socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_GPIOFIV);
859
860	/* setup the EMAC clock mux select */
861	writel((per_cfg->emacctl_emac0sel <<
862		CLKMGR_PERPLL_EMACCTL_EMAC0SEL_LSB) |
863	       (per_cfg->emacctl_emac1sel <<
864		CLKMGR_PERPLL_EMACCTL_EMAC1SEL_LSB) |
865	       (per_cfg->emacctl_emac2sel <<
866		CLKMGR_PERPLL_EMACCTL_EMAC2SEL_LSB),
867	       socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_EMACCTL);
868
869	/* at this stage, check for PLL lock status */
870	cm_wait_for_lock(LOCKED_MASK);
871
872	/*
873	 * after locking, but before taking out of bypass,
874	 * assert/deassert outresetall
875	 */
876	/* assert mainpll outresetall */
877	setbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO0,
878		     CLKMGR_MAINPLL_VCO0_OUTRSTALL_SET_MSK);
879	/* assert perpll outresetall */
880	setbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO0,
881		     CLKMGR_PERPLL_VCO0_OUTRSTALL_SET_MSK);
882	/* de-assert mainpll outresetall */
883	clrbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO0,
884		     CLKMGR_MAINPLL_VCO0_OUTRSTALL_SET_MSK);
885	/* de-assert perpll outresetall */
886	clrbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO0,
887		     CLKMGR_PERPLL_VCO0_OUTRSTALL_SET_MSK);
888
889	/* Take all PLLs out of bypass when boot mode is cleared. */
890	/* release mainpll from bypass */
891	writel(CLKMGR_MAINPLL_BYPASS_RESET,
892	       socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_BYPASSR);
893	/* wait till Clock Manager is not busy */
894	cm_busy_wait_for_fsm();
895
896	/* release perpll from bypass */
897	writel(CLKMGR_PERPLL_BYPASS_RESET,
898	       socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_BYPASSR);
899	/* wait till Clock Manager is not busy */
900	cm_busy_wait_for_fsm();
901
902	/* clear boot mode */
903	clrbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_A10_CTRL,
904		     CLKMGR_CLKMGR_CTL_BOOTMOD_SET_MSK);
905	/* wait till Clock Manager is not busy */
906	cm_busy_wait_for_fsm();
907
908	/* At here, we need to ramp to final value if needed */
909	if (pll_ramp_main_hz != 0)
910		cm_pll_ramp_main(main_cfg, per_cfg, pll_ramp_main_hz);
911	if (pll_ramp_periph_hz != 0)
912		cm_pll_ramp_periph(main_cfg, per_cfg, pll_ramp_periph_hz);
913
914	/* Now ungate non-hw-managed clocks */
915	writel(CLKMGR_MAINPLL_EN_S2FUSER0CLKEN_SET_MSK |
916	       CLKMGR_MAINPLL_EN_HMCPLLREFCLKEN_SET_MSK,
917	       socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_ENS);
918	writel(CLKMGR_PERPLL_EN_RESET,
919	       socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_ENS);
920
921	/* Clear the loss lock and slip bits as they might set during
922	clock reconfiguration */
923	writel(CLKMGR_CLKMGR_INTR_MAINPLLLOST_SET_MSK |
924	       CLKMGR_CLKMGR_INTR_PERPLLLOST_SET_MSK |
925	       CLKMGR_CLKMGR_INTR_MAINPLLRFSLIP_SET_MSK |
926	       CLKMGR_CLKMGR_INTR_PERPLLRFSLIP_SET_MSK |
927	       CLKMGR_CLKMGR_INTR_MAINPLLFBSLIP_SET_MSK |
928	       CLKMGR_CLKMGR_INTR_PERPLLFBSLIP_SET_MSK,
929	       socfpga_get_clkmgr_addr() + CLKMGR_A10_INTR);
930
931	return 0;
932}
933
934static void cm_use_intosc(void)
935{
936	setbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_A10_CTRL,
937		     CLKMGR_CLKMGR_CTL_BOOTCLK_INTOSC_SET_MSK);
938}
939
940int cm_basic_init(const void *blob)
941{
942	struct mainpll_cfg main_cfg;
943	struct perpll_cfg per_cfg;
944	int rval;
945
946	/* initialize to zero for use case of optional node */
947	memset(&main_cfg, 0, sizeof(main_cfg));
948	memset(&per_cfg, 0, sizeof(per_cfg));
949
950	rval = of_get_clk_cfg(blob, &main_cfg, &per_cfg);
951	if (rval)
952		return rval;
953
954	cm_use_intosc();
955
956	return cm_full_cfg(&main_cfg, &per_cfg);
957}
958#endif
959
960static u32 cm_get_rate_dm(char *name)
961{
962	struct uclass *uc;
963	struct udevice *dev = NULL;
964	struct clk clk = { 0 };
965	int ret;
966
967	/* Device addresses start at 1 */
968	ret = uclass_get(UCLASS_CLK, &uc);
969	if (ret)
970		return 0;
971
972	ret = uclass_get_device_by_name(UCLASS_CLK, name, &dev);
973	if (ret)
974		return 0;
975
976	ret = device_probe(dev);
977	if (ret)
978		return 0;
979
980	ret = clk_request(dev, &clk);
981	if (ret)
982		return 0;
983
984	return clk_get_rate(&clk);
985}
986
987static u32 cm_get_rate_dm_khz(char *name)
988{
989	return cm_get_rate_dm(name) / 1000;
990}
991
992unsigned long cm_get_mpu_clk_hz(void)
993{
994	return cm_get_rate_dm("main_mpu_base_clk");
995}
996
997unsigned int cm_get_qspi_controller_clk_hz(void)
998{
999	return cm_get_rate_dm("qspi_clk");
1000}
1001
1002unsigned int cm_get_l4_sp_clk_hz(void)
1003{
1004	return cm_get_rate_dm("l4_sp_clk");
1005}
1006
1007void cm_print_clock_quick_summary(void)
1008{
1009	printf("MPU       %10d kHz\n", cm_get_rate_dm_khz("main_mpu_base_clk"));
1010	printf("MMC         %8d kHz\n", cm_get_rate_dm_khz("sdmmc_clk"));
1011	printf("QSPI        %8d kHz\n", cm_get_rate_dm_khz("qspi_clk"));
1012	printf("SPI         %8d kHz\n", cm_get_rate_dm_khz("spi_m_clk"));
1013	printf("EOSC1       %8d kHz\n", cm_get_rate_dm_khz("osc1"));
1014	printf("cb_intosc   %8d kHz\n", cm_get_rate_dm_khz("cb_intosc_ls_clk"));
1015	printf("f2s_free    %8d kHz\n", cm_get_rate_dm_khz("f2s_free_clk"));
1016	printf("Main VCO    %8d kHz\n", cm_get_rate_dm_khz("main_pll@40"));
1017	printf("NOC         %8d kHz\n", cm_get_rate_dm_khz("main_noc_base_clk"));
1018	printf("L4 Main	    %8d kHz\n", cm_get_rate_dm_khz("l4_main_clk"));
1019	printf("L4 MP       %8d kHz\n", cm_get_rate_dm_khz("l4_mp_clk"));
1020	printf("L4 SP       %8d kHz\n", cm_get_rate_dm_khz("l4_sp_clk"));
1021	printf("L4 sys free %8d kHz\n", cm_get_rate_dm_khz("l4_sys_free_clk"));
1022}
1023