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