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