1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2021 Fuzhou Rockchip Electronics Co., Ltd
4 * Author: Elaine Zhang <zhangqing@rock-chips.com>
5 */
6
7#include <common.h>
8#include <bitfield.h>
9#include <clk-uclass.h>
10#include <dm.h>
11#include <errno.h>
12#include <scmi_protocols.h>
13#include <syscon.h>
14#include <asm/arch-rockchip/cru_rk3588.h>
15#include <asm/arch-rockchip/clock.h>
16#include <asm/arch-rockchip/hardware.h>
17#include <dm/device-internal.h>
18#include <dm/lists.h>
19#include <dt-bindings/clock/rockchip,rk3588-cru.h>
20
21DECLARE_GLOBAL_DATA_PTR;
22
23#define DIV_TO_RATE(input_rate, div)	((input_rate) / ((div) + 1))
24
25static struct rockchip_pll_rate_table rk3588_pll_rates[] = {
26	/* _mhz, _p, _m, _s, _k */
27	RK3588_PLL_RATE(1500000000, 2, 250, 1, 0),
28	RK3588_PLL_RATE(1200000000, 2, 200, 1, 0),
29	RK3588_PLL_RATE(1188000000, 2, 198, 1, 0),
30	RK3588_PLL_RATE(1100000000, 3, 550, 2, 0),
31	RK3588_PLL_RATE(1008000000, 2, 336, 2, 0),
32	RK3588_PLL_RATE(1000000000, 3, 500, 2, 0),
33	RK3588_PLL_RATE(900000000, 2, 300, 2, 0),
34	RK3588_PLL_RATE(850000000, 3, 425, 2, 0),
35	RK3588_PLL_RATE(816000000, 2, 272, 2, 0),
36	RK3588_PLL_RATE(786432000, 2, 262, 2, 9437),
37	RK3588_PLL_RATE(786000000, 1, 131, 2, 0),
38	RK3588_PLL_RATE(742500000, 4, 495, 2, 0),
39	RK3588_PLL_RATE(722534400, 8, 963, 2, 24850),
40	RK3588_PLL_RATE(702000000, 3, 351, 2, 0),
41	RK3588_PLL_RATE(600000000, 2, 200, 2, 0),
42	RK3588_PLL_RATE(594000000, 2, 198, 2, 0),
43	RK3588_PLL_RATE(200000000, 3, 400, 4, 0),
44	RK3588_PLL_RATE(100000000, 3, 400, 5, 0),
45	{ /* sentinel */ },
46};
47
48static struct rockchip_pll_clock rk3588_pll_clks[] = {
49	[B0PLL] = PLL(pll_rk3588, PLL_B0PLL, RK3588_B0_PLL_CON(0),
50		      RK3588_B0_PLL_MODE_CON, 0, 15, 0,
51		      rk3588_pll_rates),
52	[B1PLL] = PLL(pll_rk3588, PLL_B1PLL, RK3588_B1_PLL_CON(8),
53		      RK3588_B1_PLL_MODE_CON, 0, 15, 0,
54		      rk3588_pll_rates),
55	[LPLL] = PLL(pll_rk3588, PLL_LPLL, RK3588_LPLL_CON(16),
56		     RK3588_LPLL_MODE_CON, 0, 15, 0, rk3588_pll_rates),
57	[V0PLL] = PLL(pll_rk3588, PLL_V0PLL, RK3588_PLL_CON(88),
58		      RK3588_MODE_CON0, 4, 15, 0, rk3588_pll_rates),
59	[AUPLL] = PLL(pll_rk3588, PLL_AUPLL, RK3588_PLL_CON(96),
60		      RK3588_MODE_CON0, 6, 15, 0, rk3588_pll_rates),
61	[CPLL] = PLL(pll_rk3588, PLL_CPLL, RK3588_PLL_CON(104),
62		     RK3588_MODE_CON0, 8, 15, 0, rk3588_pll_rates),
63	[GPLL] = PLL(pll_rk3588, PLL_GPLL, RK3588_PLL_CON(112),
64		     RK3588_MODE_CON0, 2, 15, 0, rk3588_pll_rates),
65	[NPLL] = PLL(pll_rk3588, PLL_NPLL, RK3588_PLL_CON(120),
66		     RK3588_MODE_CON0, 0, 15, 0, rk3588_pll_rates),
67	[PPLL] = PLL(pll_rk3588, PLL_PPLL, RK3588_PMU_PLL_CON(128),
68		     RK3588_MODE_CON0, 10, 15, 0, rk3588_pll_rates),
69#ifdef CONFIG_SPL_BUILD
70	/*
71	 * The SPLL is part of the SBUSCRU, not the main CRU and as
72	 * such only directly accessible during the SPL stage.
73	 */
74	[SPLL] = PLL(pll_rk3588, 0, RK3588_SBUSCRU_SPLL_CON(0),
75		     RK3588_SBUSCRU_MODE_CON0, 0, 15, 0, rk3588_pll_rates),
76#endif
77
78};
79
80#ifndef CONFIG_SPL_BUILD
81/*
82 *
83 * rational_best_approximation(31415, 10000,
84 *		(1 << 8) - 1, (1 << 5) - 1, &n, &d);
85 *
86 * you may look at given_numerator as a fixed point number,
87 * with the fractional part size described in given_denominator.
88 *
89 * for theoretical background, see:
90 * http://en.wikipedia.org/wiki/Continued_fraction
91 */
92static void rational_best_approximation(unsigned long given_numerator,
93					unsigned long given_denominator,
94					unsigned long max_numerator,
95					unsigned long max_denominator,
96					unsigned long *best_numerator,
97					unsigned long *best_denominator)
98{
99	unsigned long n, d, n0, d0, n1, d1;
100
101	n = given_numerator;
102	d = given_denominator;
103	n0 = 0;
104	d1 = 0;
105	n1 = 1;
106	d0 = 1;
107	for (;;) {
108		unsigned long t, a;
109
110		if (n1 > max_numerator || d1 > max_denominator) {
111			n1 = n0;
112			d1 = d0;
113			break;
114		}
115		if (d == 0)
116			break;
117		t = d;
118		a = n / d;
119		d = n % d;
120		n = t;
121		t = n0 + a * n1;
122		n0 = n1;
123		n1 = t;
124		t = d0 + a * d1;
125		d0 = d1;
126		d1 = t;
127	}
128	*best_numerator = n1;
129	*best_denominator = d1;
130}
131#endif
132
133static ulong rk3588_center_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
134{
135	struct rk3588_cru *cru = priv->cru;
136	u32 con, sel, rate;
137
138	switch (clk_id) {
139	case ACLK_CENTER_ROOT:
140		con = readl(&cru->clksel_con[165]);
141		sel = (con & ACLK_CENTER_ROOT_SEL_MASK) >>
142		      ACLK_CENTER_ROOT_SEL_SHIFT;
143		if (sel == ACLK_CENTER_ROOT_SEL_700M)
144			rate = 702 * MHz;
145		else if (sel == ACLK_CENTER_ROOT_SEL_400M)
146			rate = 396 * MHz;
147		else if (sel == ACLK_CENTER_ROOT_SEL_200M)
148			rate = 200 * MHz;
149		else
150			rate = OSC_HZ;
151		break;
152	case ACLK_CENTER_LOW_ROOT:
153		con = readl(&cru->clksel_con[165]);
154		sel = (con & ACLK_CENTER_LOW_ROOT_SEL_MASK) >>
155		      ACLK_CENTER_LOW_ROOT_SEL_SHIFT;
156		if (sel == ACLK_CENTER_LOW_ROOT_SEL_500M)
157			rate = 500 * MHz;
158		else if (sel == ACLK_CENTER_LOW_ROOT_SEL_250M)
159			rate = 250 * MHz;
160		else if (sel == ACLK_CENTER_LOW_ROOT_SEL_100M)
161			rate = 100 * MHz;
162		else
163			rate = OSC_HZ;
164		break;
165	case HCLK_CENTER_ROOT:
166		con = readl(&cru->clksel_con[165]);
167		sel = (con & HCLK_CENTER_ROOT_SEL_MASK) >>
168		      HCLK_CENTER_ROOT_SEL_SHIFT;
169		if (sel == HCLK_CENTER_ROOT_SEL_400M)
170			rate = 396 * MHz;
171		else if (sel == HCLK_CENTER_ROOT_SEL_200M)
172			rate = 200 * MHz;
173		else if (sel == HCLK_CENTER_ROOT_SEL_100M)
174			rate = 100 * MHz;
175		else
176			rate = OSC_HZ;
177		break;
178	case PCLK_CENTER_ROOT:
179		con = readl(&cru->clksel_con[165]);
180		sel = (con & PCLK_CENTER_ROOT_SEL_MASK) >>
181		      PCLK_CENTER_ROOT_SEL_SHIFT;
182		if (sel == PCLK_CENTER_ROOT_SEL_200M)
183			rate = 200 * MHz;
184		else if (sel == PCLK_CENTER_ROOT_SEL_100M)
185			rate = 100 * MHz;
186		else if (sel == PCLK_CENTER_ROOT_SEL_50M)
187			rate = 50 * MHz;
188		else
189			rate = OSC_HZ;
190		break;
191	default:
192		return -ENOENT;
193	}
194
195	return rate;
196}
197
198static ulong rk3588_center_set_clk(struct rk3588_clk_priv *priv,
199				   ulong clk_id, ulong rate)
200{
201	struct rk3588_cru *cru = priv->cru;
202	int src_clk;
203
204	switch (clk_id) {
205	case ACLK_CENTER_ROOT:
206		if (rate >= 700 * MHz)
207			src_clk = ACLK_CENTER_ROOT_SEL_700M;
208		else if (rate >= 396 * MHz)
209			src_clk = ACLK_CENTER_ROOT_SEL_400M;
210		else if (rate >= 200 * MHz)
211			src_clk = ACLK_CENTER_ROOT_SEL_200M;
212		else
213			src_clk = ACLK_CENTER_ROOT_SEL_24M;
214		rk_clrsetreg(&cru->clksel_con[165],
215			     ACLK_CENTER_ROOT_SEL_MASK,
216			     src_clk << ACLK_CENTER_ROOT_SEL_SHIFT);
217		break;
218	case ACLK_CENTER_LOW_ROOT:
219		if (rate >= 500 * MHz)
220			src_clk = ACLK_CENTER_LOW_ROOT_SEL_500M;
221		else if (rate >= 250 * MHz)
222			src_clk = ACLK_CENTER_LOW_ROOT_SEL_250M;
223		else if (rate >= 99 * MHz)
224			src_clk = ACLK_CENTER_LOW_ROOT_SEL_100M;
225		else
226			src_clk = ACLK_CENTER_LOW_ROOT_SEL_24M;
227		rk_clrsetreg(&cru->clksel_con[165],
228			     ACLK_CENTER_LOW_ROOT_SEL_MASK,
229			     src_clk << ACLK_CENTER_LOW_ROOT_SEL_SHIFT);
230		break;
231	case HCLK_CENTER_ROOT:
232		if (rate >= 396 * MHz)
233			src_clk = HCLK_CENTER_ROOT_SEL_400M;
234		else if (rate >= 198 * MHz)
235			src_clk = HCLK_CENTER_ROOT_SEL_200M;
236		else if (rate >= 99 * MHz)
237			src_clk = HCLK_CENTER_ROOT_SEL_100M;
238		else
239			src_clk = HCLK_CENTER_ROOT_SEL_24M;
240		rk_clrsetreg(&cru->clksel_con[165],
241			     HCLK_CENTER_ROOT_SEL_MASK,
242			     src_clk << HCLK_CENTER_ROOT_SEL_SHIFT);
243		break;
244	case PCLK_CENTER_ROOT:
245		if (rate >= 198 * MHz)
246			src_clk = PCLK_CENTER_ROOT_SEL_200M;
247		else if (rate >= 99 * MHz)
248			src_clk = PCLK_CENTER_ROOT_SEL_100M;
249		else if (rate >= 50 * MHz)
250			src_clk = PCLK_CENTER_ROOT_SEL_50M;
251		else
252			src_clk = PCLK_CENTER_ROOT_SEL_24M;
253		rk_clrsetreg(&cru->clksel_con[165],
254			     PCLK_CENTER_ROOT_SEL_MASK,
255			     src_clk << PCLK_CENTER_ROOT_SEL_SHIFT);
256		break;
257	default:
258		printf("do not support this center freq\n");
259		return -EINVAL;
260	}
261
262	return rk3588_center_get_clk(priv, clk_id);
263}
264
265static ulong rk3588_top_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
266{
267	struct rk3588_cru *cru = priv->cru;
268	u32 con, sel, div, rate, prate;
269
270	switch (clk_id) {
271	case ACLK_TOP_ROOT:
272		con = readl(&cru->clksel_con[8]);
273		div = (con & ACLK_TOP_ROOT_DIV_MASK) >>
274		      ACLK_TOP_ROOT_DIV_SHIFT;
275		sel = (con & ACLK_TOP_ROOT_SRC_SEL_MASK) >>
276		      ACLK_TOP_ROOT_SRC_SEL_SHIFT;
277		if (sel == ACLK_TOP_ROOT_SRC_SEL_CPLL)
278			prate = priv->cpll_hz;
279		else
280			prate = priv->gpll_hz;
281		return DIV_TO_RATE(prate, div);
282	case ACLK_LOW_TOP_ROOT:
283		con = readl(&cru->clksel_con[8]);
284		div = (con & ACLK_LOW_TOP_ROOT_DIV_MASK) >>
285		      ACLK_LOW_TOP_ROOT_DIV_SHIFT;
286		sel = (con & ACLK_LOW_TOP_ROOT_SRC_SEL_MASK) >>
287		      ACLK_LOW_TOP_ROOT_SRC_SEL_SHIFT;
288		if (sel == ACLK_LOW_TOP_ROOT_SRC_SEL_CPLL)
289			prate = priv->cpll_hz;
290		else
291			prate = priv->gpll_hz;
292		return DIV_TO_RATE(prate, div);
293	case PCLK_TOP_ROOT:
294		con = readl(&cru->clksel_con[8]);
295		sel = (con & PCLK_TOP_ROOT_SEL_MASK) >> PCLK_TOP_ROOT_SEL_SHIFT;
296		if (sel == PCLK_TOP_ROOT_SEL_100M)
297			rate = 100 * MHz;
298		else if (sel == PCLK_TOP_ROOT_SEL_50M)
299			rate = 50 * MHz;
300		else
301			rate = OSC_HZ;
302		break;
303	default:
304		return -ENOENT;
305	}
306
307	return rate;
308}
309
310static ulong rk3588_top_set_clk(struct rk3588_clk_priv *priv,
311				ulong clk_id, ulong rate)
312{
313	struct rk3588_cru *cru = priv->cru;
314	int src_clk, src_clk_div;
315
316	switch (clk_id) {
317	case ACLK_TOP_ROOT:
318		if (!(priv->cpll_hz % rate)) {
319			src_clk = ACLK_TOP_ROOT_SRC_SEL_CPLL;
320			src_clk_div = DIV_ROUND_UP(priv->cpll_hz, rate);
321		} else {
322			src_clk = ACLK_TOP_ROOT_SRC_SEL_GPLL;
323			src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
324		}
325		assert(src_clk_div - 1 <= 31);
326		rk_clrsetreg(&cru->clksel_con[8],
327			     ACLK_TOP_ROOT_DIV_MASK |
328			     ACLK_TOP_ROOT_SRC_SEL_MASK,
329			     (src_clk <<
330			      ACLK_TOP_ROOT_SRC_SEL_SHIFT) |
331			     (src_clk_div - 1) << ACLK_TOP_ROOT_DIV_SHIFT);
332		break;
333	case ACLK_LOW_TOP_ROOT:
334		src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
335		assert(src_clk_div - 1 <= 31);
336		rk_clrsetreg(&cru->clksel_con[8],
337			     ACLK_LOW_TOP_ROOT_DIV_MASK |
338			     ACLK_LOW_TOP_ROOT_SRC_SEL_MASK,
339			     (ACLK_LOW_TOP_ROOT_SRC_SEL_GPLL <<
340			      ACLK_LOW_TOP_ROOT_SRC_SEL_SHIFT) |
341			     (src_clk_div - 1) << ACLK_LOW_TOP_ROOT_DIV_SHIFT);
342		break;
343	case PCLK_TOP_ROOT:
344		if (rate == 100 * MHz)
345			src_clk = PCLK_TOP_ROOT_SEL_100M;
346		else if (rate == 50 * MHz)
347			src_clk = PCLK_TOP_ROOT_SEL_50M;
348		else
349			src_clk = PCLK_TOP_ROOT_SEL_24M;
350		rk_clrsetreg(&cru->clksel_con[8],
351			     PCLK_TOP_ROOT_SEL_MASK,
352			     src_clk << PCLK_TOP_ROOT_SEL_SHIFT);
353		break;
354	default:
355		printf("do not support this top freq\n");
356		return -EINVAL;
357	}
358
359	return rk3588_top_get_clk(priv, clk_id);
360}
361
362static ulong rk3588_i2c_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
363{
364	struct rk3588_cru *cru = priv->cru;
365	u32 sel, con;
366	ulong rate;
367
368	switch (clk_id) {
369	case CLK_I2C0:
370		con = readl(&cru->pmuclksel_con[3]);
371		sel = (con & CLK_I2C0_SEL_MASK) >> CLK_I2C0_SEL_SHIFT;
372		break;
373	case CLK_I2C1:
374		con = readl(&cru->clksel_con[38]);
375		sel = (con & CLK_I2C1_SEL_MASK) >> CLK_I2C1_SEL_SHIFT;
376		break;
377	case CLK_I2C2:
378		con = readl(&cru->clksel_con[38]);
379		sel = (con & CLK_I2C2_SEL_MASK) >> CLK_I2C2_SEL_SHIFT;
380		break;
381	case CLK_I2C3:
382		con = readl(&cru->clksel_con[38]);
383		sel = (con & CLK_I2C3_SEL_MASK) >> CLK_I2C3_SEL_SHIFT;
384		break;
385	case CLK_I2C4:
386		con = readl(&cru->clksel_con[38]);
387		sel = (con & CLK_I2C4_SEL_MASK) >> CLK_I2C4_SEL_SHIFT;
388		break;
389	case CLK_I2C5:
390		con = readl(&cru->clksel_con[38]);
391		sel = (con & CLK_I2C5_SEL_MASK) >> CLK_I2C5_SEL_SHIFT;
392		break;
393	case CLK_I2C6:
394		con = readl(&cru->clksel_con[38]);
395		sel = (con & CLK_I2C6_SEL_MASK) >> CLK_I2C6_SEL_SHIFT;
396		break;
397	case CLK_I2C7:
398		con = readl(&cru->clksel_con[38]);
399		sel = (con & CLK_I2C7_SEL_MASK) >> CLK_I2C7_SEL_SHIFT;
400		break;
401	case CLK_I2C8:
402		con = readl(&cru->clksel_con[38]);
403		sel = (con & CLK_I2C8_SEL_MASK) >> CLK_I2C8_SEL_SHIFT;
404		break;
405	default:
406		return -ENOENT;
407	}
408	if (sel == CLK_I2C_SEL_200M)
409		rate = 200 * MHz;
410	else
411		rate = 100 * MHz;
412
413	return rate;
414}
415
416static ulong rk3588_i2c_set_clk(struct rk3588_clk_priv *priv, ulong clk_id,
417				ulong rate)
418{
419	struct rk3588_cru *cru = priv->cru;
420	int src_clk;
421
422	if (rate >= 198 * MHz)
423		src_clk = CLK_I2C_SEL_200M;
424	else
425		src_clk = CLK_I2C_SEL_100M;
426
427	switch (clk_id) {
428	case CLK_I2C0:
429		rk_clrsetreg(&cru->pmuclksel_con[3], CLK_I2C0_SEL_MASK,
430			     src_clk << CLK_I2C0_SEL_SHIFT);
431		break;
432	case CLK_I2C1:
433		rk_clrsetreg(&cru->clksel_con[38], CLK_I2C1_SEL_MASK,
434			     src_clk << CLK_I2C1_SEL_SHIFT);
435		break;
436	case CLK_I2C2:
437		rk_clrsetreg(&cru->clksel_con[38], CLK_I2C2_SEL_MASK,
438			     src_clk << CLK_I2C2_SEL_SHIFT);
439		break;
440	case CLK_I2C3:
441		rk_clrsetreg(&cru->clksel_con[38], CLK_I2C3_SEL_MASK,
442			     src_clk << CLK_I2C3_SEL_SHIFT);
443		break;
444	case CLK_I2C4:
445		rk_clrsetreg(&cru->clksel_con[38], CLK_I2C4_SEL_MASK,
446			     src_clk << CLK_I2C4_SEL_SHIFT);
447		break;
448	case CLK_I2C5:
449		rk_clrsetreg(&cru->clksel_con[38], CLK_I2C5_SEL_MASK,
450			     src_clk << CLK_I2C5_SEL_SHIFT);
451		break;
452	case CLK_I2C6:
453		rk_clrsetreg(&cru->clksel_con[38], CLK_I2C6_SEL_MASK,
454			     src_clk << CLK_I2C6_SEL_SHIFT);
455		break;
456	case CLK_I2C7:
457		rk_clrsetreg(&cru->clksel_con[38], CLK_I2C7_SEL_MASK,
458			     src_clk << CLK_I2C7_SEL_SHIFT);
459		break;
460	case CLK_I2C8:
461		rk_clrsetreg(&cru->clksel_con[38], CLK_I2C8_SEL_MASK,
462			     src_clk << CLK_I2C8_SEL_SHIFT);
463		break;
464	default:
465		return -ENOENT;
466	}
467
468	return rk3588_i2c_get_clk(priv, clk_id);
469}
470
471static ulong rk3588_spi_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
472{
473	struct rk3588_cru *cru = priv->cru;
474	u32 sel, con;
475
476	con = readl(&cru->clksel_con[59]);
477
478	switch (clk_id) {
479	case CLK_SPI0:
480		sel = (con & CLK_SPI0_SEL_MASK) >> CLK_SPI0_SEL_SHIFT;
481		break;
482	case CLK_SPI1:
483		sel = (con & CLK_SPI1_SEL_MASK) >> CLK_SPI1_SEL_SHIFT;
484		break;
485	case CLK_SPI2:
486		sel = (con & CLK_SPI2_SEL_MASK) >> CLK_SPI2_SEL_SHIFT;
487		break;
488	case CLK_SPI3:
489		sel = (con & CLK_SPI3_SEL_MASK) >> CLK_SPI3_SEL_SHIFT;
490		break;
491	case CLK_SPI4:
492		sel = (con & CLK_SPI4_SEL_MASK) >> CLK_SPI4_SEL_SHIFT;
493		break;
494	default:
495		return -ENOENT;
496	}
497
498	switch (sel) {
499	case CLK_SPI_SEL_200M:
500		return 200 * MHz;
501	case CLK_SPI_SEL_150M:
502		return 150 * MHz;
503	case CLK_SPI_SEL_24M:
504		return OSC_HZ;
505	default:
506		return -ENOENT;
507	}
508}
509
510static ulong rk3588_spi_set_clk(struct rk3588_clk_priv *priv,
511				ulong clk_id, ulong rate)
512{
513	struct rk3588_cru *cru = priv->cru;
514	int src_clk;
515
516	if (rate >= 198 * MHz)
517		src_clk = CLK_SPI_SEL_200M;
518	else if (rate >= 140 * MHz)
519		src_clk = CLK_SPI_SEL_150M;
520	else
521		src_clk = CLK_SPI_SEL_24M;
522
523	switch (clk_id) {
524	case CLK_SPI0:
525		rk_clrsetreg(&cru->clksel_con[59],
526			     CLK_SPI0_SEL_MASK,
527			     src_clk << CLK_SPI0_SEL_SHIFT);
528		break;
529	case CLK_SPI1:
530		rk_clrsetreg(&cru->clksel_con[59],
531			     CLK_SPI1_SEL_MASK,
532			     src_clk << CLK_SPI1_SEL_SHIFT);
533		break;
534	case CLK_SPI2:
535		rk_clrsetreg(&cru->clksel_con[59],
536			     CLK_SPI2_SEL_MASK,
537			     src_clk << CLK_SPI2_SEL_SHIFT);
538		break;
539	case CLK_SPI3:
540		rk_clrsetreg(&cru->clksel_con[59],
541			     CLK_SPI3_SEL_MASK,
542			     src_clk << CLK_SPI3_SEL_SHIFT);
543		break;
544	case CLK_SPI4:
545		rk_clrsetreg(&cru->clksel_con[59],
546			     CLK_SPI4_SEL_MASK,
547			     src_clk << CLK_SPI4_SEL_SHIFT);
548		break;
549	default:
550		return -ENOENT;
551	}
552
553	return rk3588_spi_get_clk(priv, clk_id);
554}
555
556static ulong rk3588_pwm_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
557{
558	struct rk3588_cru *cru = priv->cru;
559	u32 sel, con;
560
561	switch (clk_id) {
562	case CLK_PWM1:
563		con = readl(&cru->clksel_con[59]);
564		sel = (con & CLK_PWM1_SEL_MASK) >> CLK_PWM1_SEL_SHIFT;
565		break;
566	case CLK_PWM2:
567		con = readl(&cru->clksel_con[59]);
568		sel = (con & CLK_PWM2_SEL_MASK) >> CLK_PWM2_SEL_SHIFT;
569		break;
570	case CLK_PWM3:
571		con = readl(&cru->clksel_con[60]);
572		sel = (con & CLK_PWM3_SEL_MASK) >> CLK_PWM3_SEL_SHIFT;
573		break;
574	case CLK_PMU1PWM:
575		con = readl(&cru->pmuclksel_con[2]);
576		sel = (con & CLK_PMU1PWM_SEL_MASK) >> CLK_PMU1PWM_SEL_SHIFT;
577		break;
578	default:
579		return -ENOENT;
580	}
581
582	switch (sel) {
583	case CLK_PWM_SEL_100M:
584		return 100 * MHz;
585	case CLK_PWM_SEL_50M:
586		return 50 * MHz;
587	case CLK_PWM_SEL_24M:
588		return OSC_HZ;
589	default:
590		return -ENOENT;
591	}
592}
593
594static ulong rk3588_pwm_set_clk(struct rk3588_clk_priv *priv,
595				ulong clk_id, ulong rate)
596{
597	struct rk3588_cru *cru = priv->cru;
598	int src_clk;
599
600	if (rate >= 99 * MHz)
601		src_clk = CLK_PWM_SEL_100M;
602	else if (rate >= 50 * MHz)
603		src_clk = CLK_PWM_SEL_50M;
604	else
605		src_clk = CLK_PWM_SEL_24M;
606
607	switch (clk_id) {
608	case CLK_PWM1:
609		rk_clrsetreg(&cru->clksel_con[59],
610			     CLK_PWM1_SEL_MASK,
611			     src_clk << CLK_PWM1_SEL_SHIFT);
612		break;
613	case CLK_PWM2:
614		rk_clrsetreg(&cru->clksel_con[59],
615			     CLK_PWM2_SEL_MASK,
616			     src_clk << CLK_PWM2_SEL_SHIFT);
617		break;
618	case CLK_PWM3:
619		rk_clrsetreg(&cru->clksel_con[60],
620			     CLK_PWM3_SEL_MASK,
621			     src_clk << CLK_PWM3_SEL_SHIFT);
622		break;
623	case CLK_PMU1PWM:
624		rk_clrsetreg(&cru->pmuclksel_con[2],
625			     CLK_PMU1PWM_SEL_MASK,
626			     src_clk << CLK_PMU1PWM_SEL_SHIFT);
627		break;
628	default:
629		return -ENOENT;
630	}
631
632	return rk3588_pwm_get_clk(priv, clk_id);
633}
634
635static ulong rk3588_adc_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
636{
637	struct rk3588_cru *cru = priv->cru;
638	u32 div, sel, con, prate;
639
640	switch (clk_id) {
641	case CLK_SARADC:
642		con = readl(&cru->clksel_con[40]);
643		div = (con & CLK_SARADC_DIV_MASK) >> CLK_SARADC_DIV_SHIFT;
644		sel = (con & CLK_SARADC_SEL_MASK) >>
645		      CLK_SARADC_SEL_SHIFT;
646		if (sel == CLK_SARADC_SEL_24M)
647			prate = OSC_HZ;
648		else
649			prate = priv->gpll_hz;
650		return DIV_TO_RATE(prate, div);
651	case CLK_TSADC:
652		con = readl(&cru->clksel_con[41]);
653		div = (con & CLK_TSADC_DIV_MASK) >>
654		      CLK_TSADC_DIV_SHIFT;
655		sel = (con & CLK_TSADC_SEL_MASK) >>
656		      CLK_TSADC_SEL_SHIFT;
657		if (sel == CLK_TSADC_SEL_24M)
658			prate = OSC_HZ;
659		else
660			prate = 100 * MHz;
661		return DIV_TO_RATE(prate, div);
662	default:
663		return -ENOENT;
664	}
665}
666
667static ulong rk3588_adc_set_clk(struct rk3588_clk_priv *priv,
668				ulong clk_id, ulong rate)
669{
670	struct rk3588_cru *cru = priv->cru;
671	int src_clk_div;
672
673	switch (clk_id) {
674	case CLK_SARADC:
675		if (!(OSC_HZ % rate)) {
676			src_clk_div = DIV_ROUND_UP(OSC_HZ, rate);
677			assert(src_clk_div - 1 <= 255);
678			rk_clrsetreg(&cru->clksel_con[40],
679				     CLK_SARADC_SEL_MASK |
680				     CLK_SARADC_DIV_MASK,
681				     (CLK_SARADC_SEL_24M <<
682				      CLK_SARADC_SEL_SHIFT) |
683				     (src_clk_div - 1) <<
684				     CLK_SARADC_DIV_SHIFT);
685		} else {
686			src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
687			assert(src_clk_div - 1 <= 255);
688			rk_clrsetreg(&cru->clksel_con[40],
689				     CLK_SARADC_SEL_MASK |
690				     CLK_SARADC_DIV_MASK,
691				     (CLK_SARADC_SEL_GPLL <<
692				      CLK_SARADC_SEL_SHIFT) |
693				     (src_clk_div - 1) <<
694				     CLK_SARADC_DIV_SHIFT);
695		}
696		break;
697	case CLK_TSADC:
698		if (!(OSC_HZ % rate)) {
699			src_clk_div = DIV_ROUND_UP(OSC_HZ, rate);
700			assert(src_clk_div - 1 <= 255);
701			rk_clrsetreg(&cru->clksel_con[41],
702				     CLK_TSADC_SEL_MASK |
703				     CLK_TSADC_DIV_MASK,
704				     (CLK_TSADC_SEL_24M <<
705				      CLK_TSADC_SEL_SHIFT) |
706				     (src_clk_div - 1) <<
707				     CLK_TSADC_DIV_SHIFT);
708		} else {
709			src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
710			assert(src_clk_div - 1 <= 7);
711			rk_clrsetreg(&cru->clksel_con[41],
712				     CLK_TSADC_SEL_MASK |
713				     CLK_TSADC_DIV_MASK,
714				     (CLK_TSADC_SEL_GPLL <<
715				      CLK_TSADC_SEL_SHIFT) |
716				     (src_clk_div - 1) <<
717				     CLK_TSADC_DIV_SHIFT);
718		}
719		break;
720	default:
721		return -ENOENT;
722	}
723	return rk3588_adc_get_clk(priv, clk_id);
724}
725
726static ulong rk3588_mmc_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
727{
728	struct rk3588_cru *cru = priv->cru;
729	u32 sel, con, div, prate;
730
731	switch (clk_id) {
732	case CCLK_SRC_SDIO:
733		con = readl(&cru->clksel_con[172]);
734		div = (con & CCLK_SDIO_SRC_DIV_MASK) >> CCLK_SDIO_SRC_DIV_SHIFT;
735		sel = (con & CCLK_SDIO_SRC_SEL_MASK) >>
736		      CCLK_SDIO_SRC_SEL_SHIFT;
737		if (sel == CCLK_SDIO_SRC_SEL_GPLL)
738			prate = priv->gpll_hz;
739		else if (sel == CCLK_SDIO_SRC_SEL_CPLL)
740			prate = priv->cpll_hz;
741		else
742			prate = OSC_HZ;
743		return DIV_TO_RATE(prate, div);
744	case CCLK_EMMC:
745		con = readl(&cru->clksel_con[77]);
746		div = (con & CCLK_EMMC_DIV_MASK) >> CCLK_EMMC_DIV_SHIFT;
747		sel = (con & CCLK_EMMC_SEL_MASK) >>
748		      CCLK_EMMC_SEL_SHIFT;
749		if (sel == CCLK_EMMC_SEL_GPLL)
750			prate = priv->gpll_hz;
751		else if (sel == CCLK_EMMC_SEL_CPLL)
752			prate = priv->cpll_hz;
753		else
754			prate = OSC_HZ;
755		return DIV_TO_RATE(prate, div);
756	case BCLK_EMMC:
757		con = readl(&cru->clksel_con[78]);
758		div = (con & BCLK_EMMC_DIV_MASK) >> BCLK_EMMC_DIV_SHIFT;
759		sel = (con & BCLK_EMMC_SEL_MASK) >>
760		      BCLK_EMMC_SEL_SHIFT;
761		if (sel == CCLK_EMMC_SEL_CPLL)
762			prate = priv->cpll_hz;
763		else
764			prate = priv->gpll_hz;
765		return DIV_TO_RATE(prate, div);
766	case SCLK_SFC:
767		con = readl(&cru->clksel_con[78]);
768		div = (con & SCLK_SFC_DIV_MASK) >> SCLK_SFC_DIV_SHIFT;
769		sel = (con & SCLK_SFC_SEL_MASK) >>
770		      SCLK_SFC_SEL_SHIFT;
771		if (sel == SCLK_SFC_SEL_GPLL)
772			prate = priv->gpll_hz;
773		else if (sel == SCLK_SFC_SEL_CPLL)
774			prate = priv->cpll_hz;
775		else
776			prate = OSC_HZ;
777		return DIV_TO_RATE(prate, div);
778	case DCLK_DECOM:
779		con = readl(&cru->clksel_con[62]);
780		div = (con & DCLK_DECOM_DIV_MASK) >> DCLK_DECOM_DIV_SHIFT;
781		sel = (con & DCLK_DECOM_SEL_MASK) >>
782		      DCLK_DECOM_SEL_SHIFT;
783		if (sel == DCLK_DECOM_SEL_SPLL)
784			prate = 702 * MHz;
785		else
786			prate = priv->gpll_hz;
787		return DIV_TO_RATE(prate, div);
788	default:
789		return -ENOENT;
790	}
791}
792
793static ulong rk3588_mmc_set_clk(struct rk3588_clk_priv *priv,
794				ulong clk_id, ulong rate)
795{
796	struct rk3588_cru *cru = priv->cru;
797	int src_clk, div;
798
799	switch (clk_id) {
800	case CCLK_SRC_SDIO:
801	case CCLK_EMMC:
802	case SCLK_SFC:
803		if (!(OSC_HZ % rate)) {
804			src_clk = SCLK_SFC_SEL_24M;
805			div = DIV_ROUND_UP(OSC_HZ, rate);
806		} else if (!(priv->cpll_hz % rate)) {
807			src_clk = SCLK_SFC_SEL_CPLL;
808			div = DIV_ROUND_UP(priv->cpll_hz, rate);
809		} else {
810			src_clk = SCLK_SFC_SEL_GPLL;
811			div = DIV_ROUND_UP(priv->gpll_hz, rate);
812		}
813		break;
814	case BCLK_EMMC:
815		if (!(priv->cpll_hz % rate)) {
816			src_clk = CCLK_EMMC_SEL_CPLL;
817			div = DIV_ROUND_UP(priv->cpll_hz, rate);
818		} else {
819			src_clk = CCLK_EMMC_SEL_GPLL;
820			div = DIV_ROUND_UP(priv->gpll_hz, rate);
821		}
822		break;
823	case DCLK_DECOM:
824		if (!(702 * MHz % rate)) {
825			src_clk = DCLK_DECOM_SEL_SPLL;
826			div = DIV_ROUND_UP(702 * MHz, rate);
827		} else {
828			src_clk = DCLK_DECOM_SEL_GPLL;
829			div = DIV_ROUND_UP(priv->gpll_hz, rate);
830		}
831		break;
832	default:
833		return -ENOENT;
834	}
835
836	switch (clk_id) {
837	case CCLK_SRC_SDIO:
838		rk_clrsetreg(&cru->clksel_con[172],
839			     CCLK_SDIO_SRC_SEL_MASK |
840			     CCLK_SDIO_SRC_DIV_MASK,
841			     (src_clk << CCLK_SDIO_SRC_SEL_SHIFT) |
842			     (div - 1) << CCLK_SDIO_SRC_DIV_SHIFT);
843		break;
844	case CCLK_EMMC:
845		rk_clrsetreg(&cru->clksel_con[77],
846			     CCLK_EMMC_SEL_MASK |
847			     CCLK_EMMC_DIV_MASK,
848			     (src_clk << CCLK_EMMC_SEL_SHIFT) |
849			     (div - 1) << CCLK_EMMC_DIV_SHIFT);
850		break;
851	case BCLK_EMMC:
852		rk_clrsetreg(&cru->clksel_con[78],
853			     BCLK_EMMC_DIV_MASK |
854			     BCLK_EMMC_SEL_MASK,
855			     (src_clk << BCLK_EMMC_SEL_SHIFT) |
856			     (div - 1) << BCLK_EMMC_DIV_SHIFT);
857		break;
858	case SCLK_SFC:
859		rk_clrsetreg(&cru->clksel_con[78],
860			     SCLK_SFC_DIV_MASK |
861			     SCLK_SFC_SEL_MASK,
862			     (src_clk << SCLK_SFC_SEL_SHIFT) |
863			     (div - 1) << SCLK_SFC_DIV_SHIFT);
864		break;
865	case DCLK_DECOM:
866		rk_clrsetreg(&cru->clksel_con[62],
867			     DCLK_DECOM_DIV_MASK |
868			     DCLK_DECOM_SEL_MASK,
869			     (src_clk << DCLK_DECOM_SEL_SHIFT) |
870			     (div - 1) << DCLK_DECOM_DIV_SHIFT);
871		break;
872	default:
873		return -ENOENT;
874	}
875
876	return rk3588_mmc_get_clk(priv, clk_id);
877}
878
879#ifndef CONFIG_SPL_BUILD
880static ulong rk3588_aux16m_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
881{
882	struct rk3588_cru *cru = priv->cru;
883	u32 div, con, parent;
884
885	parent = priv->gpll_hz;
886	con = readl(&cru->clksel_con[117]);
887
888	switch (clk_id) {
889	case CLK_AUX16M_0:
890		div = (con & CLK_AUX16MHZ_0_DIV_MASK) >> CLK_AUX16MHZ_0_DIV_SHIFT;
891		return DIV_TO_RATE(parent, div);
892	case CLK_AUX16M_1:
893		div = (con & CLK_AUX16MHZ_1_DIV_MASK) >> CLK_AUX16MHZ_1_DIV_SHIFT;
894		return DIV_TO_RATE(parent, div);
895	default:
896		return -ENOENT;
897	}
898}
899
900static ulong rk3588_aux16m_set_clk(struct rk3588_clk_priv *priv,
901				   ulong clk_id, ulong rate)
902{
903	struct rk3588_cru *cru = priv->cru;
904	u32 div;
905
906	if (!priv->gpll_hz) {
907		printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
908		return -ENOENT;
909	}
910
911	div = DIV_ROUND_UP(priv->gpll_hz, rate);
912
913	switch (clk_id) {
914	case CLK_AUX16M_0:
915		rk_clrsetreg(&cru->clksel_con[117], CLK_AUX16MHZ_0_DIV_MASK,
916			     (div - 1) << CLK_AUX16MHZ_0_DIV_SHIFT);
917		break;
918	case CLK_AUX16M_1:
919		rk_clrsetreg(&cru->clksel_con[117], CLK_AUX16MHZ_1_DIV_MASK,
920			     (div - 1) << CLK_AUX16MHZ_1_DIV_SHIFT);
921		break;
922	default:
923		return -ENOENT;
924	}
925
926	return rk3588_aux16m_get_clk(priv, clk_id);
927}
928
929static ulong rk3588_aclk_vop_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
930{
931	struct rk3588_cru *cru = priv->cru;
932	u32 div, sel, con, parent;
933
934	switch (clk_id) {
935	case ACLK_VOP_ROOT:
936	case ACLK_VOP:
937		con = readl(&cru->clksel_con[110]);
938		div = (con & ACLK_VOP_ROOT_DIV_MASK) >> ACLK_VOP_ROOT_DIV_SHIFT;
939		sel = (con & ACLK_VOP_ROOT_SEL_MASK) >> ACLK_VOP_ROOT_SEL_SHIFT;
940		if (sel == ACLK_VOP_ROOT_SEL_GPLL)
941			parent = priv->gpll_hz;
942		else if (sel == ACLK_VOP_ROOT_SEL_CPLL)
943			parent = priv->cpll_hz;
944		else if (sel == ACLK_VOP_ROOT_SEL_AUPLL)
945			parent = priv->aupll_hz;
946		else if (sel == ACLK_VOP_ROOT_SEL_NPLL)
947			parent = priv->npll_hz;
948		else
949			parent = 702 * MHz;
950		return DIV_TO_RATE(parent, div);
951	case ACLK_VOP_LOW_ROOT:
952		con = readl(&cru->clksel_con[110]);
953		sel = (con & ACLK_VOP_LOW_ROOT_SEL_MASK) >>
954		      ACLK_VOP_LOW_ROOT_SEL_SHIFT;
955		if (sel == ACLK_VOP_LOW_ROOT_SEL_400M)
956			return 396 * MHz;
957		else if (sel == ACLK_VOP_LOW_ROOT_SEL_200M)
958			return 200 * MHz;
959		else if (sel == ACLK_VOP_LOW_ROOT_SEL_100M)
960			return 100 * MHz;
961		else
962			return OSC_HZ;
963	case HCLK_VOP_ROOT:
964		con = readl(&cru->clksel_con[110]);
965		sel = (con & HCLK_VOP_ROOT_SEL_MASK) >> HCLK_VOP_ROOT_SEL_SHIFT;
966		if (sel == HCLK_VOP_ROOT_SEL_200M)
967			return 200 * MHz;
968		else if (sel == HCLK_VOP_ROOT_SEL_100M)
969			return 100 * MHz;
970		else if (sel == HCLK_VOP_ROOT_SEL_50M)
971			return 50 * MHz;
972		else
973			return OSC_HZ;
974	default:
975		return -ENOENT;
976	}
977}
978
979static ulong rk3588_aclk_vop_set_clk(struct rk3588_clk_priv *priv,
980				     ulong clk_id, ulong rate)
981{
982	struct rk3588_cru *cru = priv->cru;
983	int src_clk, div;
984
985	switch (clk_id) {
986	case ACLK_VOP_ROOT:
987	case ACLK_VOP:
988		if (rate >= 850 * MHz) {
989			src_clk = ACLK_VOP_ROOT_SEL_NPLL;
990			div = 1;
991		} else if (rate >= 750 * MHz) {
992			src_clk = ACLK_VOP_ROOT_SEL_CPLL;
993			div = 2;
994		} else if (rate >= 700 * MHz) {
995			src_clk = ACLK_VOP_ROOT_SEL_SPLL;
996			div = 1;
997		} else if (!(priv->cpll_hz % rate)) {
998			src_clk = ACLK_VOP_ROOT_SEL_CPLL;
999			div = DIV_ROUND_UP(priv->cpll_hz, rate);
1000		} else {
1001			src_clk = ACLK_VOP_ROOT_SEL_GPLL;
1002			div = DIV_ROUND_UP(priv->gpll_hz, rate);
1003		}
1004		rk_clrsetreg(&cru->clksel_con[110],
1005			     ACLK_VOP_ROOT_DIV_MASK |
1006			     ACLK_VOP_ROOT_SEL_MASK,
1007			     (src_clk << ACLK_VOP_ROOT_SEL_SHIFT) |
1008			     (div - 1) << ACLK_VOP_ROOT_DIV_SHIFT);
1009		break;
1010	case ACLK_VOP_LOW_ROOT:
1011		if (rate == 400 * MHz || rate == 396 * MHz)
1012			src_clk = ACLK_VOP_LOW_ROOT_SEL_400M;
1013		else if (rate == 200 * MHz)
1014			src_clk = ACLK_VOP_LOW_ROOT_SEL_200M;
1015		else if (rate == 100 * MHz)
1016			src_clk = ACLK_VOP_LOW_ROOT_SEL_100M;
1017		else
1018			src_clk = ACLK_VOP_LOW_ROOT_SEL_24M;
1019		rk_clrsetreg(&cru->clksel_con[110],
1020			     ACLK_VOP_LOW_ROOT_SEL_MASK,
1021			     src_clk << ACLK_VOP_LOW_ROOT_SEL_SHIFT);
1022		break;
1023	case HCLK_VOP_ROOT:
1024		if (rate == 200 * MHz)
1025			src_clk = HCLK_VOP_ROOT_SEL_200M;
1026		else if (rate == 100 * MHz)
1027			src_clk = HCLK_VOP_ROOT_SEL_100M;
1028		else if (rate == 50 * MHz)
1029			src_clk = HCLK_VOP_ROOT_SEL_50M;
1030		else
1031			src_clk = HCLK_VOP_ROOT_SEL_24M;
1032		rk_clrsetreg(&cru->clksel_con[110],
1033			     HCLK_VOP_ROOT_SEL_MASK,
1034			     src_clk << HCLK_VOP_ROOT_SEL_SHIFT);
1035		break;
1036	default:
1037		return -ENOENT;
1038	}
1039
1040	return rk3588_aclk_vop_get_clk(priv, clk_id);
1041}
1042
1043static ulong rk3588_dclk_vop_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
1044{
1045	struct rk3588_cru *cru = priv->cru;
1046	u32 div, sel, con, parent;
1047
1048	switch (clk_id) {
1049	case DCLK_VOP0:
1050	case DCLK_VOP0_SRC:
1051		con = readl(&cru->clksel_con[111]);
1052		div = (con & DCLK0_VOP_SRC_DIV_MASK) >> DCLK0_VOP_SRC_DIV_SHIFT;
1053		sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
1054		break;
1055	case DCLK_VOP1:
1056	case DCLK_VOP1_SRC:
1057		con = readl(&cru->clksel_con[111]);
1058		div = (con & DCLK1_VOP_SRC_DIV_MASK) >> DCLK1_VOP_SRC_DIV_SHIFT;
1059		sel = (con & DCLK1_VOP_SRC_SEL_MASK) >> DCLK1_VOP_SRC_SEL_SHIFT;
1060		break;
1061	case DCLK_VOP2:
1062	case DCLK_VOP2_SRC:
1063		con = readl(&cru->clksel_con[112]);
1064		div = (con & DCLK2_VOP_SRC_DIV_MASK) >> DCLK2_VOP_SRC_DIV_SHIFT;
1065		sel = (con & DCLK2_VOP_SRC_SEL_MASK) >> DCLK2_VOP_SRC_SEL_SHIFT;
1066		break;
1067	case DCLK_VOP3:
1068		con = readl(&cru->clksel_con[113]);
1069		div = (con & DCLK3_VOP_SRC_DIV_MASK) >> DCLK3_VOP_SRC_DIV_SHIFT;
1070		sel = (con & DCLK3_VOP_SRC_SEL_MASK) >> DCLK3_VOP_SRC_SEL_SHIFT;
1071		break;
1072	default:
1073		return -ENOENT;
1074	}
1075
1076	if (sel == DCLK_VOP_SRC_SEL_AUPLL)
1077		parent = priv->aupll_hz;
1078	else if (sel == DCLK_VOP_SRC_SEL_V0PLL)
1079		parent = rockchip_pll_get_rate(&rk3588_pll_clks[V0PLL],
1080					       priv->cru, V0PLL);
1081	else if (sel == DCLK_VOP_SRC_SEL_GPLL)
1082		parent = priv->gpll_hz;
1083	else if (sel == DCLK_VOP_SRC_SEL_CPLL)
1084		parent = priv->cpll_hz;
1085	else
1086		return -ENOENT;
1087
1088	return DIV_TO_RATE(parent, div);
1089}
1090
1091#define RK3588_VOP_PLL_LIMIT_FREQ 600000000
1092
1093static ulong rk3588_dclk_vop_set_clk(struct rk3588_clk_priv *priv,
1094				     ulong clk_id, ulong rate)
1095{
1096	struct rk3588_cru *cru = priv->cru;
1097	ulong pll_rate, now, best_rate = 0;
1098	u32 i, conid, con, sel, div, best_div = 0, best_sel = 0;
1099	u32 mask, div_shift, sel_shift;
1100
1101	switch (clk_id) {
1102	case DCLK_VOP0:
1103	case DCLK_VOP0_SRC:
1104		conid = 111;
1105		con = readl(&cru->clksel_con[111]);
1106		sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
1107		mask = DCLK0_VOP_SRC_SEL_MASK | DCLK0_VOP_SRC_DIV_MASK;
1108		div_shift = DCLK0_VOP_SRC_DIV_SHIFT;
1109		sel_shift = DCLK0_VOP_SRC_SEL_SHIFT;
1110		break;
1111	case DCLK_VOP1:
1112	case DCLK_VOP1_SRC:
1113		conid = 111;
1114		con = readl(&cru->clksel_con[111]);
1115		sel = (con & DCLK1_VOP_SRC_SEL_MASK) >> DCLK1_VOP_SRC_SEL_SHIFT;
1116		mask = DCLK1_VOP_SRC_SEL_MASK | DCLK1_VOP_SRC_DIV_MASK;
1117		div_shift = DCLK1_VOP_SRC_DIV_SHIFT;
1118		sel_shift = DCLK1_VOP_SRC_SEL_SHIFT;
1119		break;
1120	case DCLK_VOP2:
1121	case DCLK_VOP2_SRC:
1122		conid = 112;
1123		con = readl(&cru->clksel_con[112]);
1124		sel = (con & DCLK2_VOP_SRC_SEL_MASK) >> DCLK2_VOP_SRC_SEL_SHIFT;
1125		mask = DCLK2_VOP_SRC_SEL_MASK | DCLK2_VOP_SRC_DIV_MASK;
1126		div_shift = DCLK2_VOP_SRC_DIV_SHIFT;
1127		sel_shift = DCLK2_VOP_SRC_SEL_SHIFT;
1128		break;
1129	case DCLK_VOP3:
1130		conid = 113;
1131		con = readl(&cru->clksel_con[113]);
1132		sel = (con & DCLK3_VOP_SRC_SEL_MASK) >> DCLK3_VOP_SRC_SEL_SHIFT;
1133		mask = DCLK3_VOP_SRC_SEL_MASK | DCLK3_VOP_SRC_DIV_MASK;
1134		div_shift = DCLK3_VOP_SRC_DIV_SHIFT;
1135		sel_shift = DCLK3_VOP_SRC_SEL_SHIFT;
1136		break;
1137	default:
1138		return -ENOENT;
1139	}
1140
1141	if (sel == DCLK_VOP_SRC_SEL_V0PLL) {
1142		pll_rate = rockchip_pll_get_rate(&rk3588_pll_clks[V0PLL],
1143						 priv->cru, V0PLL);
1144		if (pll_rate >= RK3588_VOP_PLL_LIMIT_FREQ && pll_rate % rate == 0) {
1145			div = DIV_ROUND_UP(pll_rate, rate);
1146			rk_clrsetreg(&cru->clksel_con[conid],
1147				     mask,
1148				     DCLK_VOP_SRC_SEL_V0PLL << sel_shift |
1149				     ((div - 1) << div_shift));
1150		} else {
1151			div = DIV_ROUND_UP(RK3588_VOP_PLL_LIMIT_FREQ, rate);
1152			rk_clrsetreg(&cru->clksel_con[conid],
1153				     mask,
1154				     DCLK_VOP_SRC_SEL_V0PLL << sel_shift |
1155				     ((div - 1) << div_shift));
1156			rockchip_pll_set_rate(&rk3588_pll_clks[V0PLL],
1157					      priv->cru, V0PLL, div * rate);
1158		}
1159	} else {
1160		for (i = 0; i <= DCLK_VOP_SRC_SEL_AUPLL; i++) {
1161			switch (i) {
1162			case DCLK_VOP_SRC_SEL_GPLL:
1163				pll_rate = priv->gpll_hz;
1164				break;
1165			case DCLK_VOP_SRC_SEL_CPLL:
1166				pll_rate = priv->cpll_hz;
1167				break;
1168			case DCLK_VOP_SRC_SEL_AUPLL:
1169				pll_rate = priv->aupll_hz;
1170				break;
1171			case DCLK_VOP_SRC_SEL_V0PLL:
1172				pll_rate = 0;
1173				break;
1174			default:
1175				printf("do not support this vop pll sel\n");
1176				return -EINVAL;
1177			}
1178
1179			div = DIV_ROUND_UP(pll_rate, rate);
1180			if (div > 255)
1181				continue;
1182			now = pll_rate / div;
1183			if (abs(rate - now) < abs(rate - best_rate)) {
1184				best_rate = now;
1185				best_div = div;
1186				best_sel = i;
1187			}
1188			debug("p_rate=%lu, best_rate=%lu, div=%u, sel=%u\n",
1189			      pll_rate, best_rate, best_div, best_sel);
1190		}
1191
1192		if (best_rate) {
1193			rk_clrsetreg(&cru->clksel_con[conid],
1194				     mask,
1195				     best_sel << sel_shift |
1196				     (best_div - 1) << div_shift);
1197		} else {
1198			printf("do not support this vop freq %lu\n", rate);
1199			return -EINVAL;
1200		}
1201	}
1202	return rk3588_dclk_vop_get_clk(priv, clk_id);
1203}
1204
1205static ulong rk3588_gmac_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
1206{
1207	struct rk3588_cru *cru = priv->cru;
1208	u32 con, div;
1209
1210	switch (clk_id) {
1211	case CLK_GMAC0_PTP_REF:
1212		con = readl(&cru->clksel_con[81]);
1213		div = (con & CLK_GMAC0_PTP_DIV_MASK) >> CLK_GMAC0_PTP_DIV_SHIFT;
1214		return DIV_TO_RATE(priv->cpll_hz, div);
1215	case CLK_GMAC1_PTP_REF:
1216		con = readl(&cru->clksel_con[81]);
1217		div = (con & CLK_GMAC1_PTP_DIV_MASK) >> CLK_GMAC1_PTP_DIV_SHIFT;
1218		return DIV_TO_RATE(priv->cpll_hz, div);
1219	case CLK_GMAC_125M:
1220		con = readl(&cru->clksel_con[83]);
1221		div = (con & CLK_GMAC_125M_DIV_MASK) >> CLK_GMAC_125M_DIV_SHIFT;
1222		return DIV_TO_RATE(priv->cpll_hz, div);
1223	case CLK_GMAC_50M:
1224		con = readl(&cru->clksel_con[84]);
1225		div = (con & CLK_GMAC_50M_DIV_MASK) >> CLK_GMAC_50M_DIV_SHIFT;
1226		return DIV_TO_RATE(priv->cpll_hz, div);
1227	default:
1228		return -ENOENT;
1229	}
1230}
1231
1232static ulong rk3588_gmac_set_clk(struct rk3588_clk_priv *priv,
1233				 ulong clk_id, ulong rate)
1234{
1235	struct rk3588_cru *cru = priv->cru;
1236	int div;
1237
1238	div = DIV_ROUND_UP(priv->cpll_hz, rate);
1239
1240	switch (clk_id) {
1241	case CLK_GMAC0_PTP_REF:
1242		rk_clrsetreg(&cru->clksel_con[81],
1243			     CLK_GMAC0_PTP_DIV_MASK | CLK_GMAC0_PTP_SEL_MASK,
1244			     CLK_GMAC0_PTP_SEL_CPLL << CLK_GMAC0_PTP_SEL_SHIFT |
1245			     (div - 1) << CLK_GMAC0_PTP_DIV_SHIFT);
1246		break;
1247	case CLK_GMAC1_PTP_REF:
1248		rk_clrsetreg(&cru->clksel_con[81],
1249			     CLK_GMAC1_PTP_DIV_MASK | CLK_GMAC1_PTP_SEL_MASK,
1250			     CLK_GMAC1_PTP_SEL_CPLL << CLK_GMAC1_PTP_SEL_SHIFT |
1251			     (div - 1) << CLK_GMAC1_PTP_DIV_SHIFT);
1252		break;
1253
1254	case CLK_GMAC_125M:
1255		rk_clrsetreg(&cru->clksel_con[83],
1256			     CLK_GMAC_125M_DIV_MASK | CLK_GMAC_125M_SEL_MASK,
1257			     CLK_GMAC_125M_SEL_CPLL << CLK_GMAC_125M_SEL_SHIFT |
1258			     (div - 1) << CLK_GMAC_125M_DIV_SHIFT);
1259		break;
1260	case CLK_GMAC_50M:
1261		rk_clrsetreg(&cru->clksel_con[84],
1262			     CLK_GMAC_50M_DIV_MASK | CLK_GMAC_50M_SEL_MASK,
1263			     CLK_GMAC_50M_SEL_CPLL << CLK_GMAC_50M_SEL_SHIFT |
1264			     (div - 1) << CLK_GMAC_50M_DIV_SHIFT);
1265		break;
1266	default:
1267		return -ENOENT;
1268	}
1269
1270	return rk3588_gmac_get_clk(priv, clk_id);
1271}
1272
1273static ulong rk3588_uart_get_rate(struct rk3588_clk_priv *priv, ulong clk_id)
1274{
1275	struct rk3588_cru *cru = priv->cru;
1276	u32 reg, con, fracdiv, div, src, p_src, p_rate;
1277	unsigned long m, n;
1278
1279	switch (clk_id) {
1280	case SCLK_UART1:
1281		reg = 41;
1282		break;
1283	case SCLK_UART2:
1284		reg = 43;
1285		break;
1286	case SCLK_UART3:
1287		reg = 45;
1288		break;
1289	case SCLK_UART4:
1290		reg = 47;
1291		break;
1292	case SCLK_UART5:
1293		reg = 49;
1294		break;
1295	case SCLK_UART6:
1296		reg = 51;
1297		break;
1298	case SCLK_UART7:
1299		reg = 53;
1300		break;
1301	case SCLK_UART8:
1302		reg = 55;
1303		break;
1304	case SCLK_UART9:
1305		reg = 57;
1306		break;
1307	default:
1308		return -ENOENT;
1309	}
1310	con = readl(&cru->clksel_con[reg + 2]);
1311	src = (con & CLK_UART_SEL_MASK) >> CLK_UART_SEL_SHIFT;
1312	con = readl(&cru->clksel_con[reg]);
1313	div = (con & CLK_UART_SRC_DIV_MASK) >> CLK_UART_SRC_DIV_SHIFT;
1314	p_src = (con & CLK_UART_SRC_SEL_MASK) >> CLK_UART_SRC_SEL_SHIFT;
1315	if (p_src == CLK_UART_SRC_SEL_GPLL)
1316		p_rate = priv->gpll_hz;
1317	else
1318		p_rate = priv->cpll_hz;
1319
1320	if (src == CLK_UART_SEL_SRC) {
1321		return DIV_TO_RATE(p_rate, div);
1322	} else if (src == CLK_UART_SEL_FRAC) {
1323		fracdiv = readl(&cru->clksel_con[reg + 1]);
1324		n = fracdiv & CLK_UART_FRAC_NUMERATOR_MASK;
1325		n >>= CLK_UART_FRAC_NUMERATOR_SHIFT;
1326		m = fracdiv & CLK_UART_FRAC_DENOMINATOR_MASK;
1327		m >>= CLK_UART_FRAC_DENOMINATOR_SHIFT;
1328		return DIV_TO_RATE(p_rate, div) * n / m;
1329	} else {
1330		return OSC_HZ;
1331	}
1332}
1333
1334static ulong rk3588_uart_set_rate(struct rk3588_clk_priv *priv,
1335				  ulong clk_id, ulong rate)
1336{
1337	struct rk3588_cru *cru = priv->cru;
1338	u32 reg, clk_src, uart_src, div;
1339	unsigned long m = 0, n = 0, val;
1340
1341	if (priv->gpll_hz % rate == 0) {
1342		clk_src = CLK_UART_SRC_SEL_GPLL;
1343		uart_src = CLK_UART_SEL_SRC;
1344		div = DIV_ROUND_UP(priv->gpll_hz, rate);
1345	} else if (priv->cpll_hz % rate == 0) {
1346		clk_src = CLK_UART_SRC_SEL_CPLL;
1347		uart_src = CLK_UART_SEL_SRC;
1348		div = DIV_ROUND_UP(priv->gpll_hz, rate);
1349	} else if (rate == OSC_HZ) {
1350		clk_src = CLK_UART_SRC_SEL_GPLL;
1351		uart_src = CLK_UART_SEL_XIN24M;
1352		div = 2;
1353	} else {
1354		clk_src = CLK_UART_SRC_SEL_GPLL;
1355		uart_src = CLK_UART_SEL_FRAC;
1356		div = 2;
1357		rational_best_approximation(rate, priv->gpll_hz / div,
1358					    GENMASK(16 - 1, 0),
1359					    GENMASK(16 - 1, 0),
1360					    &m, &n);
1361	}
1362
1363	switch (clk_id) {
1364	case SCLK_UART1:
1365		reg = 41;
1366		break;
1367	case SCLK_UART2:
1368		reg = 43;
1369		break;
1370	case SCLK_UART3:
1371		reg = 45;
1372		break;
1373	case SCLK_UART4:
1374		reg = 47;
1375		break;
1376	case SCLK_UART5:
1377		reg = 49;
1378		break;
1379	case SCLK_UART6:
1380		reg = 51;
1381		break;
1382	case SCLK_UART7:
1383		reg = 53;
1384		break;
1385	case SCLK_UART8:
1386		reg = 55;
1387		break;
1388	case SCLK_UART9:
1389		reg = 57;
1390		break;
1391	default:
1392		return -ENOENT;
1393	}
1394	rk_clrsetreg(&cru->clksel_con[reg],
1395		     CLK_UART_SRC_SEL_MASK |
1396		     CLK_UART_SRC_DIV_MASK,
1397		     (clk_src << CLK_UART_SRC_SEL_SHIFT) |
1398		     ((div - 1) << CLK_UART_SRC_DIV_SHIFT));
1399	rk_clrsetreg(&cru->clksel_con[reg + 2],
1400		     CLK_UART_SEL_MASK,
1401		     (uart_src << CLK_UART_SEL_SHIFT));
1402	if (m && n) {
1403		val = m << CLK_UART_FRAC_NUMERATOR_SHIFT | n;
1404		writel(val, &cru->clksel_con[reg + 1]);
1405	}
1406
1407	return rk3588_uart_get_rate(priv, clk_id);
1408}
1409
1410static ulong rk3588_pciephy_get_rate(struct rk3588_clk_priv *priv, ulong clk_id)
1411{
1412	struct rk3588_cru *cru = priv->cru;
1413	u32 con, div, src;
1414
1415	switch (clk_id) {
1416	case CLK_REF_PIPE_PHY0:
1417		con = readl(&cru->clksel_con[177]);
1418		src = (con & CLK_PCIE_PHY0_REF_SEL_MASK) >> CLK_PCIE_PHY0_REF_SEL_SHIFT;
1419		con = readl(&cru->clksel_con[176]);
1420		div = (con & CLK_PCIE_PHY0_PLL_DIV_MASK) >> CLK_PCIE_PHY0_PLL_DIV_SHIFT;
1421		break;
1422	case CLK_REF_PIPE_PHY1:
1423		con = readl(&cru->clksel_con[177]);
1424		src = (con & CLK_PCIE_PHY1_REF_SEL_MASK) >> CLK_PCIE_PHY1_REF_SEL_SHIFT;
1425		con = readl(&cru->clksel_con[176]);
1426		div = (con & CLK_PCIE_PHY1_PLL_DIV_MASK) >> CLK_PCIE_PHY1_PLL_DIV_SHIFT;
1427		break;
1428	case CLK_REF_PIPE_PHY2:
1429		con = readl(&cru->clksel_con[177]);
1430		src = (con & CLK_PCIE_PHY2_REF_SEL_MASK) >> CLK_PCIE_PHY2_REF_SEL_SHIFT;
1431		div = (con & CLK_PCIE_PHY2_PLL_DIV_MASK) >> CLK_PCIE_PHY2_PLL_DIV_SHIFT;
1432		break;
1433	default:
1434		return -ENOENT;
1435	}
1436
1437	if (src == CLK_PCIE_PHY_REF_SEL_PPLL)
1438		return DIV_TO_RATE(priv->ppll_hz, div);
1439	else
1440		return OSC_HZ;
1441}
1442
1443static ulong rk3588_pciephy_set_rate(struct rk3588_clk_priv *priv,
1444				     ulong clk_id, ulong rate)
1445{
1446	struct rk3588_cru *cru = priv->cru;
1447	u32 clk_src, div;
1448
1449	if (rate == OSC_HZ) {
1450		clk_src = CLK_PCIE_PHY_REF_SEL_24M;
1451		div = 1;
1452	} else {
1453		clk_src = CLK_PCIE_PHY_REF_SEL_PPLL;
1454		div = DIV_ROUND_UP(priv->ppll_hz, rate);
1455	}
1456
1457	switch (clk_id) {
1458	case CLK_REF_PIPE_PHY0:
1459		rk_clrsetreg(&cru->clksel_con[177], CLK_PCIE_PHY0_REF_SEL_MASK,
1460			     (clk_src << CLK_PCIE_PHY0_REF_SEL_SHIFT));
1461		rk_clrsetreg(&cru->clksel_con[176], CLK_PCIE_PHY0_PLL_DIV_MASK,
1462			     ((div - 1) << CLK_PCIE_PHY0_PLL_DIV_SHIFT));
1463		break;
1464	case CLK_REF_PIPE_PHY1:
1465		rk_clrsetreg(&cru->clksel_con[177], CLK_PCIE_PHY1_REF_SEL_MASK,
1466			     (clk_src << CLK_PCIE_PHY1_REF_SEL_SHIFT));
1467		rk_clrsetreg(&cru->clksel_con[176], CLK_PCIE_PHY1_PLL_DIV_MASK,
1468			     ((div - 1) << CLK_PCIE_PHY1_PLL_DIV_SHIFT));
1469		break;
1470	case CLK_REF_PIPE_PHY2:
1471		rk_clrsetreg(&cru->clksel_con[177], CLK_PCIE_PHY2_REF_SEL_MASK |
1472			     CLK_PCIE_PHY2_PLL_DIV_MASK,
1473			     (clk_src << CLK_PCIE_PHY2_REF_SEL_SHIFT) |
1474			     ((div - 1) << CLK_PCIE_PHY2_PLL_DIV_SHIFT));
1475		break;
1476	default:
1477		return -ENOENT;
1478	}
1479
1480	return rk3588_pciephy_get_rate(priv, clk_id);
1481}
1482#endif
1483
1484static ulong rk3588_clk_get_rate(struct clk *clk)
1485{
1486	struct rk3588_clk_priv *priv = dev_get_priv(clk->dev);
1487	ulong rate = 0;
1488
1489	if (!priv->gpll_hz) {
1490		printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
1491		return -ENOENT;
1492	}
1493
1494	if (!priv->ppll_hz) {
1495		priv->ppll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[PPLL],
1496						      priv->cru, PPLL);
1497	}
1498
1499	switch (clk->id) {
1500	case PLL_LPLL:
1501		rate = rockchip_pll_get_rate(&rk3588_pll_clks[LPLL], priv->cru,
1502					     LPLL);
1503		break;
1504	case PLL_B0PLL:
1505		rate = rockchip_pll_get_rate(&rk3588_pll_clks[B0PLL], priv->cru,
1506					     B0PLL);
1507		break;
1508	case PLL_B1PLL:
1509		rate = rockchip_pll_get_rate(&rk3588_pll_clks[B1PLL], priv->cru,
1510					     B1PLL);
1511		break;
1512	case PLL_GPLL:
1513		rate = rockchip_pll_get_rate(&rk3588_pll_clks[GPLL], priv->cru,
1514					     GPLL);
1515		break;
1516	case PLL_CPLL:
1517		rate = rockchip_pll_get_rate(&rk3588_pll_clks[CPLL], priv->cru,
1518					     CPLL);
1519		break;
1520	case PLL_NPLL:
1521		rate = rockchip_pll_get_rate(&rk3588_pll_clks[NPLL], priv->cru,
1522					     NPLL);
1523		break;
1524	case PLL_V0PLL:
1525		rate = rockchip_pll_get_rate(&rk3588_pll_clks[V0PLL], priv->cru,
1526					     V0PLL);
1527		break;
1528	case PLL_AUPLL:
1529		rate = rockchip_pll_get_rate(&rk3588_pll_clks[AUPLL], priv->cru,
1530					     AUPLL);
1531		break;
1532	case PLL_PPLL:
1533		rate = rockchip_pll_get_rate(&rk3588_pll_clks[PPLL], priv->cru,
1534					     PPLL);
1535		break;
1536	case ACLK_CENTER_ROOT:
1537	case PCLK_CENTER_ROOT:
1538	case HCLK_CENTER_ROOT:
1539	case ACLK_CENTER_LOW_ROOT:
1540		rate = rk3588_center_get_clk(priv, clk->id);
1541		break;
1542	case ACLK_TOP_ROOT:
1543	case PCLK_TOP_ROOT:
1544	case ACLK_LOW_TOP_ROOT:
1545		rate = rk3588_top_get_clk(priv, clk->id);
1546		break;
1547	case CLK_I2C0:
1548	case CLK_I2C1:
1549	case CLK_I2C2:
1550	case CLK_I2C3:
1551	case CLK_I2C4:
1552	case CLK_I2C5:
1553	case CLK_I2C6:
1554	case CLK_I2C7:
1555	case CLK_I2C8:
1556		rate = rk3588_i2c_get_clk(priv, clk->id);
1557		break;
1558	case CLK_SPI0:
1559	case CLK_SPI1:
1560	case CLK_SPI2:
1561	case CLK_SPI3:
1562	case CLK_SPI4:
1563		rate = rk3588_spi_get_clk(priv, clk->id);
1564		break;
1565	case CLK_PWM1:
1566	case CLK_PWM2:
1567	case CLK_PWM3:
1568	case CLK_PMU1PWM:
1569		rate = rk3588_pwm_get_clk(priv, clk->id);
1570		break;
1571	case CLK_SARADC:
1572	case CLK_TSADC:
1573		rate = rk3588_adc_get_clk(priv, clk->id);
1574		break;
1575	case CCLK_SRC_SDIO:
1576	case CCLK_EMMC:
1577	case BCLK_EMMC:
1578	case SCLK_SFC:
1579	case DCLK_DECOM:
1580		rate = rk3588_mmc_get_clk(priv, clk->id);
1581		break;
1582	case REF_CLK_USB3OTG0:
1583	case REF_CLK_USB3OTG1:
1584	case REF_CLK_USB3OTG2:
1585	case TMCLK_EMMC:
1586	case TCLK_WDT0:
1587		rate = OSC_HZ;
1588		break;
1589	case PCLK_PMU0_ROOT:
1590		rate = 100000000;
1591		break;
1592	case HCLK_PMU_CM0_ROOT:
1593		rate = 200000000;
1594		break;
1595	case ACLK_BUS_ROOT:
1596		rate = 375000000;
1597		break;
1598	case CLK_150M_SRC:
1599		rate = 150000000;
1600		break;
1601	case CLK_GPU:
1602		rate = 200000000;
1603		break;
1604#ifndef CONFIG_SPL_BUILD
1605	case CLK_AUX16M_0:
1606	case CLK_AUX16M_1:
1607		rate = rk3588_aux16m_get_clk(priv, clk->id);
1608		break;
1609	case ACLK_VOP_ROOT:
1610	case ACLK_VOP:
1611	case ACLK_VOP_LOW_ROOT:
1612	case HCLK_VOP_ROOT:
1613		rate = rk3588_aclk_vop_get_clk(priv, clk->id);
1614		break;
1615	case DCLK_VOP0:
1616	case DCLK_VOP0_SRC:
1617	case DCLK_VOP1:
1618	case DCLK_VOP1_SRC:
1619	case DCLK_VOP2:
1620	case DCLK_VOP2_SRC:
1621	case DCLK_VOP3:
1622		rate = rk3588_dclk_vop_get_clk(priv, clk->id);
1623		break;
1624	case CLK_GMAC0_PTP_REF:
1625	case CLK_GMAC1_PTP_REF:
1626	case CLK_GMAC_125M:
1627	case CLK_GMAC_50M:
1628		rate = rk3588_gmac_get_clk(priv, clk->id);
1629		break;
1630	case SCLK_UART1:
1631	case SCLK_UART2:
1632	case SCLK_UART3:
1633	case SCLK_UART4:
1634	case SCLK_UART5:
1635	case SCLK_UART6:
1636	case SCLK_UART7:
1637	case SCLK_UART8:
1638	case SCLK_UART9:
1639		rate = rk3588_uart_get_rate(priv, clk->id);
1640		break;
1641	case CLK_REF_PIPE_PHY0:
1642	case CLK_REF_PIPE_PHY1:
1643	case CLK_REF_PIPE_PHY2:
1644		rate = rk3588_pciephy_get_rate(priv, clk->id);
1645		break;
1646#endif
1647	default:
1648		return -ENOENT;
1649	}
1650
1651	return rate;
1652};
1653
1654static ulong rk3588_clk_set_rate(struct clk *clk, ulong rate)
1655{
1656	struct rk3588_clk_priv *priv = dev_get_priv(clk->dev);
1657	ulong ret = 0;
1658
1659	if (!priv->gpll_hz) {
1660		printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
1661		return -ENOENT;
1662	}
1663
1664	if (!priv->ppll_hz) {
1665		priv->ppll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[PPLL],
1666						      priv->cru, PPLL);
1667	}
1668
1669	switch (clk->id) {
1670	case PLL_CPLL:
1671		ret = rockchip_pll_set_rate(&rk3588_pll_clks[CPLL], priv->cru,
1672					    CPLL, rate);
1673		priv->cpll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[CPLL],
1674						      priv->cru, CPLL);
1675		break;
1676	case PLL_GPLL:
1677		ret = rockchip_pll_set_rate(&rk3588_pll_clks[GPLL], priv->cru,
1678					    GPLL, rate);
1679		priv->gpll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[GPLL],
1680						      priv->cru, GPLL);
1681		break;
1682	case PLL_NPLL:
1683		ret = rockchip_pll_set_rate(&rk3588_pll_clks[NPLL], priv->cru,
1684					    NPLL, rate);
1685		break;
1686	case PLL_V0PLL:
1687		ret = rockchip_pll_set_rate(&rk3588_pll_clks[V0PLL], priv->cru,
1688					    V0PLL, rate);
1689		priv->v0pll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[V0PLL],
1690						       priv->cru, V0PLL);
1691		break;
1692	case PLL_AUPLL:
1693		ret = rockchip_pll_set_rate(&rk3588_pll_clks[AUPLL], priv->cru,
1694					    AUPLL, rate);
1695		priv->aupll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[AUPLL],
1696						       priv->cru, AUPLL);
1697		break;
1698	case PLL_PPLL:
1699		ret = rockchip_pll_set_rate(&rk3588_pll_clks[PPLL], priv->cru,
1700					    PPLL, rate);
1701		priv->ppll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[PPLL],
1702						      priv->cru, PPLL);
1703		break;
1704	case ACLK_CENTER_ROOT:
1705	case PCLK_CENTER_ROOT:
1706	case HCLK_CENTER_ROOT:
1707	case ACLK_CENTER_LOW_ROOT:
1708		ret = rk3588_center_set_clk(priv, clk->id, rate);
1709		break;
1710	case ACLK_TOP_ROOT:
1711	case PCLK_TOP_ROOT:
1712	case ACLK_LOW_TOP_ROOT:
1713		ret = rk3588_top_set_clk(priv, clk->id, rate);
1714		break;
1715	case CLK_I2C0:
1716	case CLK_I2C1:
1717	case CLK_I2C2:
1718	case CLK_I2C3:
1719	case CLK_I2C4:
1720	case CLK_I2C5:
1721	case CLK_I2C6:
1722	case CLK_I2C7:
1723	case CLK_I2C8:
1724		ret = rk3588_i2c_set_clk(priv, clk->id, rate);
1725		break;
1726	case CLK_SPI0:
1727	case CLK_SPI1:
1728	case CLK_SPI2:
1729	case CLK_SPI3:
1730	case CLK_SPI4:
1731		ret = rk3588_spi_set_clk(priv, clk->id, rate);
1732		break;
1733	case CLK_PWM1:
1734	case CLK_PWM2:
1735	case CLK_PWM3:
1736	case CLK_PMU1PWM:
1737		ret = rk3588_pwm_set_clk(priv, clk->id, rate);
1738		break;
1739	case CLK_SARADC:
1740	case CLK_TSADC:
1741		ret = rk3588_adc_set_clk(priv, clk->id, rate);
1742		break;
1743	case CCLK_SRC_SDIO:
1744	case CCLK_EMMC:
1745	case BCLK_EMMC:
1746	case SCLK_SFC:
1747	case DCLK_DECOM:
1748		ret = rk3588_mmc_set_clk(priv, clk->id, rate);
1749		break;
1750	case REF_CLK_USB3OTG0:
1751	case REF_CLK_USB3OTG1:
1752	case REF_CLK_USB3OTG2:
1753	case TMCLK_EMMC:
1754	case TCLK_WDT0:
1755		ret = OSC_HZ;
1756		break;
1757	case PCLK_PMU0_ROOT:
1758	case CLK_GPU:
1759	case HCLK_PMU_CM0_ROOT:
1760	case ACLK_BUS_ROOT:
1761	case CLK_150M_SRC:
1762		ret = 0;
1763		break;
1764#ifndef CONFIG_SPL_BUILD
1765	case CLK_AUX16M_0:
1766	case CLK_AUX16M_1:
1767		ret = rk3588_aux16m_set_clk(priv, clk->id, rate);
1768		break;
1769	case ACLK_VOP_ROOT:
1770	case ACLK_VOP:
1771	case ACLK_VOP_LOW_ROOT:
1772	case HCLK_VOP_ROOT:
1773		ret = rk3588_aclk_vop_set_clk(priv, clk->id, rate);
1774		break;
1775	case DCLK_VOP0:
1776	case DCLK_VOP0_SRC:
1777	case DCLK_VOP1:
1778	case DCLK_VOP1_SRC:
1779	case DCLK_VOP2:
1780	case DCLK_VOP2_SRC:
1781	case DCLK_VOP3:
1782		ret = rk3588_dclk_vop_set_clk(priv, clk->id, rate);
1783		break;
1784	case CLK_GMAC0_PTP_REF:
1785	case CLK_GMAC1_PTP_REF:
1786	case CLK_GMAC_125M:
1787	case CLK_GMAC_50M:
1788		ret = rk3588_gmac_set_clk(priv, clk->id, rate);
1789		break;
1790	case SCLK_UART1:
1791	case SCLK_UART2:
1792	case SCLK_UART3:
1793	case SCLK_UART4:
1794	case SCLK_UART5:
1795	case SCLK_UART6:
1796	case SCLK_UART7:
1797	case SCLK_UART8:
1798	case SCLK_UART9:
1799		ret = rk3588_uart_set_rate(priv, clk->id, rate);
1800		break;
1801	case CLK_REF_PIPE_PHY0:
1802	case CLK_REF_PIPE_PHY1:
1803	case CLK_REF_PIPE_PHY2:
1804		ret = rk3588_pciephy_set_rate(priv, clk->id, rate);
1805		break;
1806#endif
1807	default:
1808		return -ENOENT;
1809	}
1810
1811	return ret;
1812};
1813
1814#define ROCKCHIP_MMC_DELAY_SEL		BIT(10)
1815#define ROCKCHIP_MMC_DEGREE_MASK	0x3
1816#define ROCKCHIP_MMC_DELAYNUM_OFFSET	2
1817#define ROCKCHIP_MMC_DELAYNUM_MASK	(0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
1818
1819#define PSECS_PER_SEC 1000000000000LL
1820/*
1821 * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
1822 * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
1823 */
1824#define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
1825
1826#if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA))
1827static int __maybe_unused rk3588_dclk_vop_set_parent(struct clk *clk,
1828						     struct clk *parent)
1829{
1830	struct rk3588_clk_priv *priv = dev_get_priv(clk->dev);
1831	struct rk3588_cru *cru = priv->cru;
1832	u32 sel;
1833	const char *clock_dev_name = parent->dev->name;
1834
1835	if (parent->id == PLL_V0PLL)
1836		sel = 2;
1837	else if (parent->id == PLL_GPLL)
1838		sel = 0;
1839	else if (parent->id == PLL_CPLL)
1840		sel = 1;
1841	else
1842		sel = 3;
1843
1844	switch (clk->id) {
1845	case DCLK_VOP0_SRC:
1846		rk_clrsetreg(&cru->clksel_con[111], DCLK0_VOP_SRC_SEL_MASK,
1847			     sel << DCLK0_VOP_SRC_SEL_SHIFT);
1848		break;
1849	case DCLK_VOP1_SRC:
1850		rk_clrsetreg(&cru->clksel_con[111], DCLK1_VOP_SRC_SEL_MASK,
1851			     sel << DCLK1_VOP_SRC_SEL_SHIFT);
1852		break;
1853	case DCLK_VOP2_SRC:
1854		rk_clrsetreg(&cru->clksel_con[112], DCLK2_VOP_SRC_SEL_MASK,
1855			     sel << DCLK2_VOP_SRC_SEL_SHIFT);
1856		break;
1857	case DCLK_VOP3:
1858		rk_clrsetreg(&cru->clksel_con[113], DCLK3_VOP_SRC_SEL_MASK,
1859			     sel << DCLK3_VOP_SRC_SEL_SHIFT);
1860		break;
1861	case DCLK_VOP0:
1862		if (!strcmp(clock_dev_name, "hdmiphypll_clk0"))
1863			sel = 1;
1864		else if (!strcmp(clock_dev_name, "hdmiphypll_clk1"))
1865			sel = 2;
1866		else
1867			sel = 0;
1868		rk_clrsetreg(&cru->clksel_con[112], DCLK0_VOP_SEL_MASK,
1869			     sel << DCLK0_VOP_SEL_SHIFT);
1870		break;
1871	case DCLK_VOP1:
1872		if (!strcmp(clock_dev_name, "hdmiphypll_clk0"))
1873			sel = 1;
1874		else if (!strcmp(clock_dev_name, "hdmiphypll_clk1"))
1875			sel = 2;
1876		else
1877			sel = 0;
1878		rk_clrsetreg(&cru->clksel_con[112], DCLK1_VOP_SEL_MASK,
1879			     sel << DCLK1_VOP_SEL_SHIFT);
1880		break;
1881	case DCLK_VOP2:
1882		if (!strcmp(clock_dev_name, "hdmiphypll_clk0"))
1883			sel = 1;
1884		else if (!strcmp(clock_dev_name, "hdmiphypll_clk1"))
1885			sel = 2;
1886		else
1887			sel = 0;
1888		rk_clrsetreg(&cru->clksel_con[112], DCLK2_VOP_SEL_MASK,
1889			     sel << DCLK2_VOP_SEL_SHIFT);
1890		break;
1891	default:
1892		return -EINVAL;
1893	}
1894	return 0;
1895}
1896
1897static int rk3588_clk_set_parent(struct clk *clk, struct clk *parent)
1898{
1899	switch (clk->id) {
1900	case DCLK_VOP0_SRC:
1901	case DCLK_VOP1_SRC:
1902	case DCLK_VOP2_SRC:
1903	case DCLK_VOP0:
1904	case DCLK_VOP1:
1905	case DCLK_VOP2:
1906	case DCLK_VOP3:
1907		return rk3588_dclk_vop_set_parent(clk, parent);
1908	default:
1909		return -ENOENT;
1910	}
1911
1912	return 0;
1913}
1914#endif
1915
1916static struct clk_ops rk3588_clk_ops = {
1917	.get_rate = rk3588_clk_get_rate,
1918	.set_rate = rk3588_clk_set_rate,
1919#if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA))
1920	.set_parent = rk3588_clk_set_parent,
1921#endif
1922};
1923
1924static void rk3588_clk_init(struct rk3588_clk_priv *priv)
1925{
1926	int ret, div;
1927
1928	div = DIV_ROUND_UP(GPLL_HZ, 300 * MHz);
1929	rk_clrsetreg(&priv->cru->clksel_con[38],
1930		     ACLK_BUS_ROOT_SEL_MASK |
1931		     ACLK_BUS_ROOT_DIV_MASK,
1932		     div << ACLK_BUS_ROOT_DIV_SHIFT);
1933
1934	if (priv->cpll_hz != CPLL_HZ) {
1935		ret = rockchip_pll_set_rate(&rk3588_pll_clks[CPLL], priv->cru,
1936					    CPLL, CPLL_HZ);
1937		if (!ret)
1938			priv->cpll_hz = CPLL_HZ;
1939	}
1940	if (priv->gpll_hz != GPLL_HZ) {
1941		ret = rockchip_pll_set_rate(&rk3588_pll_clks[GPLL], priv->cru,
1942					    GPLL, GPLL_HZ);
1943		if (!ret)
1944			priv->gpll_hz = GPLL_HZ;
1945	}
1946
1947#ifdef CONFIG_PCI
1948	if (priv->ppll_hz != PPLL_HZ) {
1949		ret = rockchip_pll_set_rate(&rk3588_pll_clks[PPLL], priv->cru,
1950					    PPLL, PPLL_HZ);
1951		priv->ppll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[PPLL],
1952						      priv->cru, PPLL);
1953	}
1954#endif
1955	rk_clrsetreg(&priv->cru->clksel_con[9],
1956		     ACLK_TOP_S400_SEL_MASK |
1957		     ACLK_TOP_S200_SEL_MASK,
1958		     (ACLK_TOP_S400_SEL_400M << ACLK_TOP_S400_SEL_SHIFT) |
1959		     (ACLK_TOP_S200_SEL_200M << ACLK_TOP_S200_SEL_SHIFT));
1960}
1961
1962static int rk3588_clk_probe(struct udevice *dev)
1963{
1964	struct rk3588_clk_priv *priv = dev_get_priv(dev);
1965	int ret;
1966
1967	priv->sync_kernel = false;
1968
1969#ifdef CONFIG_SPL_BUILD
1970	rockchip_pll_set_rate(&rk3588_pll_clks[B0PLL], priv->cru,
1971			      B0PLL, LPLL_HZ);
1972	rockchip_pll_set_rate(&rk3588_pll_clks[B1PLL], priv->cru,
1973			      B1PLL, LPLL_HZ);
1974	if (!priv->armclk_enter_hz) {
1975		ret = rockchip_pll_set_rate(&rk3588_pll_clks[LPLL], priv->cru,
1976					    LPLL, LPLL_HZ);
1977		priv->armclk_enter_hz =
1978			rockchip_pll_get_rate(&rk3588_pll_clks[LPLL],
1979					      priv->cru, LPLL);
1980		priv->armclk_init_hz = priv->armclk_enter_hz;
1981	}
1982#endif
1983
1984	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
1985	if (IS_ERR(priv->grf))
1986		return PTR_ERR(priv->grf);
1987
1988	rk3588_clk_init(priv);
1989
1990	/* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
1991	ret = clk_set_defaults(dev, 1);
1992	if (ret)
1993		debug("%s clk_set_defaults failed %d\n", __func__, ret);
1994	else
1995		priv->sync_kernel = true;
1996
1997	return 0;
1998}
1999
2000static int rk3588_clk_ofdata_to_platdata(struct udevice *dev)
2001{
2002	struct rk3588_clk_priv *priv = dev_get_priv(dev);
2003
2004	priv->cru = dev_read_addr_ptr(dev);
2005
2006	return 0;
2007}
2008
2009static int rk3588_clk_bind(struct udevice *dev)
2010{
2011	int ret;
2012	struct udevice *sys_child;
2013	struct sysreset_reg *priv;
2014
2015	/* The reset driver does not have a device node, so bind it here */
2016	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
2017				 &sys_child);
2018	if (ret) {
2019		debug("Warning: No sysreset driver: ret=%d\n", ret);
2020	} else {
2021		priv = malloc(sizeof(struct sysreset_reg));
2022		priv->glb_srst_fst_value = offsetof(struct rk3588_cru,
2023						    glb_srst_fst);
2024		priv->glb_srst_snd_value = offsetof(struct rk3588_cru,
2025						    glb_srsr_snd);
2026		dev_set_priv(sys_child, priv);
2027	}
2028
2029#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
2030	ret = offsetof(struct rk3588_cru, softrst_con[0]);
2031	ret = rk3588_reset_bind_lut(dev, ret, 49158);
2032	if (ret)
2033		debug("Warning: software reset driver bind failed\n");
2034#endif
2035
2036	return 0;
2037}
2038
2039static const struct udevice_id rk3588_clk_ids[] = {
2040	{ .compatible = "rockchip,rk3588-cru" },
2041	{ }
2042};
2043
2044U_BOOT_DRIVER(rockchip_rk3588_cru) = {
2045	.name		= "rockchip_rk3588_cru",
2046	.id		= UCLASS_CLK,
2047	.of_match	= rk3588_clk_ids,
2048	.priv_auto	= sizeof(struct rk3588_clk_priv),
2049	.of_to_plat	= rk3588_clk_ofdata_to_platdata,
2050	.ops		= &rk3588_clk_ops,
2051	.bind		= rk3588_clk_bind,
2052	.probe		= rk3588_clk_probe,
2053};
2054
2055#ifdef CONFIG_SPL_BUILD
2056#define SCRU_BASE			0xfd7d0000
2057#define SBUSCRU_BASE			0xfd7d8000
2058
2059static ulong rk3588_scru_clk_get_rate(struct clk *clk)
2060{
2061	u32 con, div, sel, parent;
2062
2063	switch (clk->id) {
2064	case SCMI_CCLK_SD:
2065		con = readl(SCRU_BASE + RK3588_CLKSEL_CON(3));
2066		sel = (con & SCMI_CCLK_SD_SEL_MASK) >> SCMI_CCLK_SD_SEL_SHIFT;
2067		div = (con & SCMI_CCLK_SD_DIV_MASK) >> SCMI_CCLK_SD_DIV_SHIFT;
2068		if (sel == SCMI_CCLK_SD_SEL_GPLL)
2069			parent = GPLL_HZ;
2070		else if (sel == SCMI_CCLK_SD_SEL_SPLL)
2071			parent = SPLL_HZ;
2072		else
2073			parent = OSC_HZ;
2074		return DIV_TO_RATE(parent, div);
2075	case SCMI_HCLK_SD:
2076		con = readl(SCRU_BASE + RK3588_CLKSEL_CON(1));
2077		sel = (con & SCMI_HCLK_SD_SEL_MASK) >> SCMI_HCLK_SD_SEL_SHIFT;
2078		if (sel == SCMI_HCLK_SD_SEL_150M)
2079			return 150 * MHz;
2080		else if (sel == SCMI_HCLK_SD_SEL_100M)
2081			return 100 * MHz;
2082		else if (sel == SCMI_HCLK_SD_SEL_50M)
2083			return 50 * MHz;
2084		else
2085			return OSC_HZ;
2086	default:
2087		return -ENOENT;
2088	}
2089}
2090
2091static ulong rk3588_scru_clk_set_rate(struct clk *clk, ulong rate)
2092{
2093	u32 div, sel;
2094
2095	switch (clk->id) {
2096	case SCMI_CCLK_SD:
2097		if ((OSC_HZ % rate) == 0) {
2098			sel = SCMI_CCLK_SD_SEL_24M;
2099			div = DIV_ROUND_UP(OSC_HZ, rate);
2100		} else if ((SPLL_HZ % rate) == 0) {
2101			sel = SCMI_CCLK_SD_SEL_SPLL;
2102			div = DIV_ROUND_UP(SPLL_HZ, rate);
2103		} else {
2104			sel = SCMI_CCLK_SD_SEL_GPLL;
2105			div = DIV_ROUND_UP(GPLL_HZ, rate);
2106		}
2107		rk_clrsetreg(SCRU_BASE + RK3588_CLKSEL_CON(3),
2108			     SCMI_CCLK_SD_SEL_MASK | SCMI_CCLK_SD_DIV_MASK,
2109			     sel << SCMI_CCLK_SD_SEL_SHIFT |
2110			     (div - 1) << SCMI_CCLK_SD_DIV_SHIFT);
2111		break;
2112	case SCMI_HCLK_SD:
2113		if (rate >= 150 * MHz)
2114			sel = SCMI_HCLK_SD_SEL_150M;
2115		else if (rate >= 100 * MHz)
2116			sel = SCMI_HCLK_SD_SEL_100M;
2117		else if (rate >= 50 * MHz)
2118			sel = SCMI_HCLK_SD_SEL_50M;
2119		else
2120			sel = SCMI_HCLK_SD_SEL_24M;
2121		rk_clrsetreg(SCRU_BASE + RK3588_CLKSEL_CON(1),
2122			     SCMI_HCLK_SD_SEL_MASK,
2123			     sel << SCMI_HCLK_SD_SEL_SHIFT);
2124		break;
2125	default:
2126		return -ENOENT;
2127	}
2128
2129	return rk3588_scru_clk_get_rate(clk);
2130}
2131
2132static int rk3588_scru_clk_probe(struct udevice *dev)
2133{
2134	int ret;
2135
2136	ret = rockchip_pll_set_rate(&rk3588_pll_clks[SPLL],
2137				    (void *)SBUSCRU_BASE, SPLL, SPLL_HZ);
2138	if (ret)
2139		debug("%s setting spll rate failed %d\n", __func__, ret);
2140
2141	return 0;
2142}
2143
2144static const struct clk_ops rk3588_scru_clk_ops = {
2145	.get_rate = rk3588_scru_clk_get_rate,
2146	.set_rate = rk3588_scru_clk_set_rate,
2147};
2148
2149U_BOOT_DRIVER(rockchip_rk3588_scru) = {
2150	.name	= "rockchip_rk3588_scru",
2151	.id	= UCLASS_CLK,
2152	.ops	= &rk3588_scru_clk_ops,
2153	.probe	= rk3588_scru_clk_probe,
2154};
2155
2156static int rk3588_scmi_spl_glue_bind(struct udevice *dev)
2157{
2158	ofnode node;
2159	u32 protocol_id;
2160	const char *name;
2161
2162	dev_for_each_subnode(node, dev) {
2163		if (!ofnode_is_enabled(node))
2164			continue;
2165
2166		if (ofnode_read_u32(node, "reg", &protocol_id))
2167			continue;
2168
2169		if (protocol_id != SCMI_PROTOCOL_ID_CLOCK)
2170			continue;
2171
2172		name = ofnode_get_name(node);
2173		return device_bind_driver_to_node(dev, "rockchip_rk3588_scru",
2174						  name, node, NULL);
2175	}
2176
2177	return -ENOENT;
2178}
2179
2180static const struct udevice_id rk3588_scmi_spl_glue_ids[] = {
2181	{ .compatible = "arm,scmi-smc" },
2182	{ }
2183};
2184
2185U_BOOT_DRIVER(rk3588_scmi_spl_glue) = {
2186	.name		= "rk3588_scmi_spl_glue",
2187	.id		= UCLASS_NOP,
2188	.of_match	= rk3588_scmi_spl_glue_ids,
2189	.bind		= rk3588_scmi_spl_glue_bind,
2190};
2191#endif
2192