xref: /rk3399_rockchip-uboot/drivers/clk/rockchip/clk_rk3588.c (revision ee62ba3d7027ae2160a7c33410306d15eb26fe20)
128d0997cSElaine Zhang // SPDX-License-Identifier: GPL-2.0
228d0997cSElaine Zhang /*
328d0997cSElaine Zhang  * Copyright (c) 2021 Fuzhou Rockchip Electronics Co., Ltd
428d0997cSElaine Zhang  * Author: Elaine Zhang <zhangqing@rock-chips.com>
528d0997cSElaine Zhang  */
628d0997cSElaine Zhang 
728d0997cSElaine Zhang #include <common.h>
828d0997cSElaine Zhang #include <bitfield.h>
928d0997cSElaine Zhang #include <clk-uclass.h>
1028d0997cSElaine Zhang #include <dm.h>
1128d0997cSElaine Zhang #include <errno.h>
1228d0997cSElaine Zhang #include <syscon.h>
1328d0997cSElaine Zhang #include <asm/arch/clock.h>
1428d0997cSElaine Zhang #include <asm/arch/cru_rk3588.h>
1528d0997cSElaine Zhang #include <asm/arch/hardware.h>
1628d0997cSElaine Zhang #include <asm/io.h>
1728d0997cSElaine Zhang #include <dm/lists.h>
1828d0997cSElaine Zhang #include <dt-bindings/clock/rk3588-cru.h>
1928d0997cSElaine Zhang 
2028d0997cSElaine Zhang DECLARE_GLOBAL_DATA_PTR;
2128d0997cSElaine Zhang 
2228d0997cSElaine Zhang #define DIV_TO_RATE(input_rate, div)	((input_rate) / ((div) + 1))
2328d0997cSElaine Zhang 
2428d0997cSElaine Zhang static struct rockchip_pll_rate_table rk3588_pll_rates[] = {
2528d0997cSElaine Zhang 	/* _mhz, _p, _m, _s, _k */
2628d0997cSElaine Zhang 	RK3588_PLL_RATE(1500000000, 2, 250, 1, 0),
2728d0997cSElaine Zhang 	RK3588_PLL_RATE(1200000000, 2, 200, 1, 0),
2828d0997cSElaine Zhang 	RK3588_PLL_RATE(1188000000, 2, 198, 1, 0),
29*ee62ba3dSElaine Zhang 	RK3588_PLL_RATE(1150000000, 3, 575, 2, 0),
302909d91bSKever Yang 	RK3588_PLL_RATE(1100000000, 3, 550, 2, 0),
3128d0997cSElaine Zhang 	RK3588_PLL_RATE(1008000000, 2, 336, 2, 0),
3228d0997cSElaine Zhang 	RK3588_PLL_RATE(1000000000, 3, 500, 2, 0),
3328d0997cSElaine Zhang 	RK3588_PLL_RATE(900000000, 2, 300, 2, 0),
3428d0997cSElaine Zhang 	RK3588_PLL_RATE(850000000, 3, 425, 2, 0),
3528d0997cSElaine Zhang 	RK3588_PLL_RATE(816000000, 2, 272, 2, 0),
364892004aSElaine Zhang 	RK3588_PLL_RATE(786432000, 2, 262, 2, 9437),
375eb3ca63SElaine Zhang 	RK3588_PLL_RATE(786000000, 1, 131, 2, 0),
381a40445eSGuochun Huang 	RK3588_PLL_RATE(742500000, 4, 495, 2, 0),
394892004aSElaine Zhang 	RK3588_PLL_RATE(722534400, 8, 963, 2, 24850),
4028d0997cSElaine Zhang 	RK3588_PLL_RATE(600000000, 2, 200, 2, 0),
4128d0997cSElaine Zhang 	RK3588_PLL_RATE(594000000, 2, 198, 2, 0),
4228d0997cSElaine Zhang 	RK3588_PLL_RATE(200000000, 3, 400, 4, 0),
4328d0997cSElaine Zhang 	RK3588_PLL_RATE(100000000, 3, 400, 5, 0),
4428d0997cSElaine Zhang 	{ /* sentinel */ },
4528d0997cSElaine Zhang };
4628d0997cSElaine Zhang 
4728d0997cSElaine Zhang static struct rockchip_pll_clock rk3588_pll_clks[] = {
4828d0997cSElaine Zhang 	[B0PLL] = PLL(pll_rk3588, PLL_B0PLL, RK3588_B0_PLL_CON(0),
4928d0997cSElaine Zhang 		      RK3588_B0_PLL_MODE_CON, 0, 15, 0,
5028d0997cSElaine Zhang 		      rk3588_pll_rates),
5128d0997cSElaine Zhang 	[B1PLL] = PLL(pll_rk3588, PLL_B1PLL, RK3588_B1_PLL_CON(8),
5228d0997cSElaine Zhang 		      RK3588_B1_PLL_MODE_CON, 0, 15, 0,
5328d0997cSElaine Zhang 		      rk3588_pll_rates),
5428d0997cSElaine Zhang 	[LPLL] = PLL(pll_rk3588, PLL_LPLL, RK3588_LPLL_CON(16),
5528d0997cSElaine Zhang 		     RK3588_LPLL_MODE_CON, 0, 15, 0, rk3588_pll_rates),
5628d0997cSElaine Zhang 	[V0PLL] = PLL(pll_rk3588, PLL_V0PLL, RK3588_PLL_CON(88),
5728d0997cSElaine Zhang 		      RK3588_MODE_CON0, 4, 15, 0, rk3588_pll_rates),
5828d0997cSElaine Zhang 	[AUPLL] = PLL(pll_rk3588, PLL_AUPLL, RK3588_PLL_CON(96),
5928d0997cSElaine Zhang 		      RK3588_MODE_CON0, 6, 15, 0, rk3588_pll_rates),
6028d0997cSElaine Zhang 	[CPLL] = PLL(pll_rk3588, PLL_CPLL, RK3588_PLL_CON(104),
6128d0997cSElaine Zhang 		     RK3588_MODE_CON0, 8, 15, 0, rk3588_pll_rates),
6228d0997cSElaine Zhang 	[GPLL] = PLL(pll_rk3588, PLL_GPLL, RK3588_PLL_CON(112),
6328d0997cSElaine Zhang 		     RK3588_MODE_CON0, 2, 15, 0, rk3588_pll_rates),
6428d0997cSElaine Zhang 	[NPLL] = PLL(pll_rk3588, PLL_NPLL, RK3588_PLL_CON(120),
6528d0997cSElaine Zhang 		     RK3588_MODE_CON0, 0, 15, 0, rk3588_pll_rates),
6628d0997cSElaine Zhang 	[PPLL] = PLL(pll_rk3588, PLL_PPLL, RK3588_PMU_PLL_CON(128),
6728d0997cSElaine Zhang 		     RK3588_MODE_CON0, 10, 15, 0, rk3588_pll_rates),
6828d0997cSElaine Zhang };
6928d0997cSElaine Zhang 
7028d0997cSElaine Zhang #ifndef CONFIG_SPL_BUILD
7128d0997cSElaine Zhang #define RK3588_CLK_DUMP(_id, _name, _iscru)	\
7228d0997cSElaine Zhang {						\
7328d0997cSElaine Zhang 	.id = _id,				\
7428d0997cSElaine Zhang 	.name = _name,				\
7528d0997cSElaine Zhang 	.is_cru = _iscru,			\
7628d0997cSElaine Zhang }
7728d0997cSElaine Zhang 
7828d0997cSElaine Zhang static const struct rk3588_clk_info clks_dump[] = {
7928d0997cSElaine Zhang 	RK3588_CLK_DUMP(PLL_B0PLL, "b0pll", true),
8028d0997cSElaine Zhang 	RK3588_CLK_DUMP(PLL_B1PLL, "b1pll", true),
8128d0997cSElaine Zhang 	RK3588_CLK_DUMP(PLL_LPLL, "lpll", true),
8228d0997cSElaine Zhang 	RK3588_CLK_DUMP(PLL_V0PLL, "v0pll", true),
8328d0997cSElaine Zhang 	RK3588_CLK_DUMP(PLL_AUPLL, "aupll", true),
8428d0997cSElaine Zhang 	RK3588_CLK_DUMP(PLL_CPLL, "cpll", true),
8528d0997cSElaine Zhang 	RK3588_CLK_DUMP(PLL_GPLL, "gpll", true),
8628d0997cSElaine Zhang 	RK3588_CLK_DUMP(PLL_NPLL, "npll", true),
8728d0997cSElaine Zhang 	RK3588_CLK_DUMP(PLL_PPLL, "ppll", true),
8828d0997cSElaine Zhang 	RK3588_CLK_DUMP(ACLK_CENTER_ROOT, "aclk_center_root", true),
8928d0997cSElaine Zhang 	RK3588_CLK_DUMP(PCLK_CENTER_ROOT, "pclk_center_root", true),
9028d0997cSElaine Zhang 	RK3588_CLK_DUMP(HCLK_CENTER_ROOT, "hclk_center_root", true),
9128d0997cSElaine Zhang 	RK3588_CLK_DUMP(ACLK_CENTER_LOW_ROOT, "aclk_center_low_root", true),
9228d0997cSElaine Zhang 	RK3588_CLK_DUMP(ACLK_TOP_ROOT, "aclk_top_root", true),
9328d0997cSElaine Zhang 	RK3588_CLK_DUMP(PCLK_TOP_ROOT, "pclk_top_root", true),
9428d0997cSElaine Zhang 	RK3588_CLK_DUMP(ACLK_LOW_TOP_ROOT, "aclk_low_top_root", true),
9528d0997cSElaine Zhang };
9628d0997cSElaine Zhang #endif
9728d0997cSElaine Zhang 
9828d0997cSElaine Zhang #ifndef CONFIG_SPL_BUILD
9928d0997cSElaine Zhang /*
10028d0997cSElaine Zhang  *
10128d0997cSElaine Zhang  * rational_best_approximation(31415, 10000,
10228d0997cSElaine Zhang  *		(1 << 8) - 1, (1 << 5) - 1, &n, &d);
10328d0997cSElaine Zhang  *
10428d0997cSElaine Zhang  * you may look at given_numerator as a fixed point number,
10528d0997cSElaine Zhang  * with the fractional part size described in given_denominator.
10628d0997cSElaine Zhang  *
10728d0997cSElaine Zhang  * for theoretical background, see:
10828d0997cSElaine Zhang  * http://en.wikipedia.org/wiki/Continued_fraction
10928d0997cSElaine Zhang  */
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)11028d0997cSElaine Zhang static void rational_best_approximation(unsigned long given_numerator,
11128d0997cSElaine Zhang 					unsigned long given_denominator,
11228d0997cSElaine Zhang 					unsigned long max_numerator,
11328d0997cSElaine Zhang 					unsigned long max_denominator,
11428d0997cSElaine Zhang 					unsigned long *best_numerator,
11528d0997cSElaine Zhang 					unsigned long *best_denominator)
11628d0997cSElaine Zhang {
11728d0997cSElaine Zhang 	unsigned long n, d, n0, d0, n1, d1;
11828d0997cSElaine Zhang 
11928d0997cSElaine Zhang 	n = given_numerator;
12028d0997cSElaine Zhang 	d = given_denominator;
12128d0997cSElaine Zhang 	n0 = 0;
12228d0997cSElaine Zhang 	d1 = 0;
12328d0997cSElaine Zhang 	n1 = 1;
12428d0997cSElaine Zhang 	d0 = 1;
12528d0997cSElaine Zhang 	for (;;) {
12628d0997cSElaine Zhang 		unsigned long t, a;
12728d0997cSElaine Zhang 
12828d0997cSElaine Zhang 		if (n1 > max_numerator || d1 > max_denominator) {
12928d0997cSElaine Zhang 			n1 = n0;
13028d0997cSElaine Zhang 			d1 = d0;
13128d0997cSElaine Zhang 			break;
13228d0997cSElaine Zhang 		}
13328d0997cSElaine Zhang 		if (d == 0)
13428d0997cSElaine Zhang 			break;
13528d0997cSElaine Zhang 		t = d;
13628d0997cSElaine Zhang 		a = n / d;
13728d0997cSElaine Zhang 		d = n % d;
13828d0997cSElaine Zhang 		n = t;
13928d0997cSElaine Zhang 		t = n0 + a * n1;
14028d0997cSElaine Zhang 		n0 = n1;
14128d0997cSElaine Zhang 		n1 = t;
14228d0997cSElaine Zhang 		t = d0 + a * d1;
14328d0997cSElaine Zhang 		d0 = d1;
14428d0997cSElaine Zhang 		d1 = t;
14528d0997cSElaine Zhang 	}
14628d0997cSElaine Zhang 	*best_numerator = n1;
14728d0997cSElaine Zhang 	*best_denominator = d1;
14828d0997cSElaine Zhang }
14928d0997cSElaine Zhang #endif
15028d0997cSElaine Zhang 
rk3588_center_get_clk(struct rk3588_clk_priv * priv,ulong clk_id)15128d0997cSElaine Zhang static ulong rk3588_center_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
15228d0997cSElaine Zhang {
15328d0997cSElaine Zhang 	struct rk3588_cru *cru = priv->cru;
15428d0997cSElaine Zhang 	u32 con, sel, rate;
15528d0997cSElaine Zhang 
15628d0997cSElaine Zhang 	switch (clk_id) {
15728d0997cSElaine Zhang 	case ACLK_CENTER_ROOT:
15828d0997cSElaine Zhang 		con = readl(&cru->clksel_con[165]);
15928d0997cSElaine Zhang 		sel = (con & ACLK_CENTER_ROOT_SEL_MASK) >>
16028d0997cSElaine Zhang 		      ACLK_CENTER_ROOT_SEL_SHIFT;
16128d0997cSElaine Zhang 		if (sel == ACLK_CENTER_ROOT_SEL_700M)
16228d0997cSElaine Zhang 			rate = 702 * MHz;
16328d0997cSElaine Zhang 		else if (sel == ACLK_CENTER_ROOT_SEL_400M)
16428d0997cSElaine Zhang 			rate = 396 * MHz;
16528d0997cSElaine Zhang 		else if (sel == ACLK_CENTER_ROOT_SEL_200M)
16628d0997cSElaine Zhang 			rate = 200 * MHz;
16728d0997cSElaine Zhang 		else
16828d0997cSElaine Zhang 			rate = OSC_HZ;
16928d0997cSElaine Zhang 		break;
17028d0997cSElaine Zhang 	case ACLK_CENTER_LOW_ROOT:
17128d0997cSElaine Zhang 		con = readl(&cru->clksel_con[165]);
17228d0997cSElaine Zhang 		sel = (con & ACLK_CENTER_LOW_ROOT_SEL_MASK) >>
17328d0997cSElaine Zhang 		      ACLK_CENTER_LOW_ROOT_SEL_SHIFT;
17428d0997cSElaine Zhang 		if (sel == ACLK_CENTER_LOW_ROOT_SEL_500M)
17528d0997cSElaine Zhang 			rate = 500 * MHz;
17628d0997cSElaine Zhang 		else if (sel == ACLK_CENTER_LOW_ROOT_SEL_250M)
17728d0997cSElaine Zhang 			rate = 250 * MHz;
17828d0997cSElaine Zhang 		else if (sel == ACLK_CENTER_LOW_ROOT_SEL_100M)
17928d0997cSElaine Zhang 			rate = 100 * MHz;
18028d0997cSElaine Zhang 		else
18128d0997cSElaine Zhang 			rate = OSC_HZ;
18228d0997cSElaine Zhang 		break;
18328d0997cSElaine Zhang 	case HCLK_CENTER_ROOT:
18428d0997cSElaine Zhang 		con = readl(&cru->clksel_con[165]);
18528d0997cSElaine Zhang 		sel = (con & HCLK_CENTER_ROOT_SEL_MASK) >>
18628d0997cSElaine Zhang 		      HCLK_CENTER_ROOT_SEL_SHIFT;
18728d0997cSElaine Zhang 		if (sel == HCLK_CENTER_ROOT_SEL_400M)
18828d0997cSElaine Zhang 			rate = 396 * MHz;
18928d0997cSElaine Zhang 		else if (sel == HCLK_CENTER_ROOT_SEL_200M)
19028d0997cSElaine Zhang 			rate = 200 * MHz;
19128d0997cSElaine Zhang 		else if (sel == HCLK_CENTER_ROOT_SEL_100M)
19228d0997cSElaine Zhang 			rate = 100 * MHz;
19328d0997cSElaine Zhang 		else
19428d0997cSElaine Zhang 			rate = OSC_HZ;
19528d0997cSElaine Zhang 		break;
19628d0997cSElaine Zhang 	case PCLK_CENTER_ROOT:
19728d0997cSElaine Zhang 		con = readl(&cru->clksel_con[165]);
19828d0997cSElaine Zhang 		sel = (con & PCLK_CENTER_ROOT_SEL_MASK) >>
19928d0997cSElaine Zhang 		      PCLK_CENTER_ROOT_SEL_SHIFT;
20028d0997cSElaine Zhang 		if (sel == PCLK_CENTER_ROOT_SEL_200M)
20128d0997cSElaine Zhang 			rate = 200 * MHz;
20228d0997cSElaine Zhang 		else if (sel == PCLK_CENTER_ROOT_SEL_100M)
20328d0997cSElaine Zhang 			rate = 100 * MHz;
20428d0997cSElaine Zhang 		else if (sel == PCLK_CENTER_ROOT_SEL_50M)
20528d0997cSElaine Zhang 			rate = 50 * MHz;
20628d0997cSElaine Zhang 		else
20728d0997cSElaine Zhang 			rate = OSC_HZ;
20828d0997cSElaine Zhang 		break;
20928d0997cSElaine Zhang 	default:
21028d0997cSElaine Zhang 		return -ENOENT;
21128d0997cSElaine Zhang 	}
21228d0997cSElaine Zhang 
21328d0997cSElaine Zhang 	return rate;
21428d0997cSElaine Zhang }
21528d0997cSElaine Zhang 
rk3588_center_set_clk(struct rk3588_clk_priv * priv,ulong clk_id,ulong rate)21628d0997cSElaine Zhang static ulong rk3588_center_set_clk(struct rk3588_clk_priv *priv,
21728d0997cSElaine Zhang 				   ulong clk_id, ulong rate)
21828d0997cSElaine Zhang {
21928d0997cSElaine Zhang 	struct rk3588_cru *cru = priv->cru;
22028d0997cSElaine Zhang 	int src_clk;
22128d0997cSElaine Zhang 
22228d0997cSElaine Zhang 	switch (clk_id) {
22328d0997cSElaine Zhang 	case ACLK_CENTER_ROOT:
22428d0997cSElaine Zhang 		if (rate >= 700 * MHz)
22528d0997cSElaine Zhang 			src_clk = ACLK_CENTER_ROOT_SEL_700M;
22628d0997cSElaine Zhang 		else if (rate >= 396 * MHz)
22728d0997cSElaine Zhang 			src_clk = ACLK_CENTER_ROOT_SEL_400M;
22828d0997cSElaine Zhang 		else if (rate >= 200 * MHz)
22928d0997cSElaine Zhang 			src_clk = ACLK_CENTER_ROOT_SEL_200M;
23028d0997cSElaine Zhang 		else
23128d0997cSElaine Zhang 			src_clk = ACLK_CENTER_ROOT_SEL_24M;
23228d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[165],
23328d0997cSElaine Zhang 			     ACLK_CENTER_ROOT_SEL_MASK,
23428d0997cSElaine Zhang 			     src_clk << ACLK_CENTER_ROOT_SEL_SHIFT);
23528d0997cSElaine Zhang 		break;
23628d0997cSElaine Zhang 	case ACLK_CENTER_LOW_ROOT:
23728d0997cSElaine Zhang 		if (rate >= 500 * MHz)
23828d0997cSElaine Zhang 			src_clk = ACLK_CENTER_LOW_ROOT_SEL_500M;
23928d0997cSElaine Zhang 		else if (rate >= 250 * MHz)
24028d0997cSElaine Zhang 			src_clk = ACLK_CENTER_LOW_ROOT_SEL_250M;
24128d0997cSElaine Zhang 		else if (rate >= 99 * MHz)
24228d0997cSElaine Zhang 			src_clk = ACLK_CENTER_LOW_ROOT_SEL_100M;
24328d0997cSElaine Zhang 		else
24428d0997cSElaine Zhang 			src_clk = ACLK_CENTER_LOW_ROOT_SEL_24M;
24528d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[165],
24628d0997cSElaine Zhang 			     ACLK_CENTER_LOW_ROOT_SEL_MASK,
24728d0997cSElaine Zhang 			     src_clk << ACLK_CENTER_LOW_ROOT_SEL_SHIFT);
24828d0997cSElaine Zhang 		break;
24928d0997cSElaine Zhang 	case HCLK_CENTER_ROOT:
25028d0997cSElaine Zhang 		if (rate >= 396 * MHz)
25128d0997cSElaine Zhang 			src_clk = HCLK_CENTER_ROOT_SEL_400M;
25228d0997cSElaine Zhang 		else if (rate >= 198 * MHz)
25328d0997cSElaine Zhang 			src_clk = HCLK_CENTER_ROOT_SEL_200M;
25428d0997cSElaine Zhang 		else if (rate >= 99 * MHz)
25528d0997cSElaine Zhang 			src_clk = HCLK_CENTER_ROOT_SEL_100M;
25628d0997cSElaine Zhang 		else
25728d0997cSElaine Zhang 			src_clk = HCLK_CENTER_ROOT_SEL_24M;
25828d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[165],
25928d0997cSElaine Zhang 			     HCLK_CENTER_ROOT_SEL_MASK,
26028d0997cSElaine Zhang 			     src_clk << HCLK_CENTER_ROOT_SEL_SHIFT);
26128d0997cSElaine Zhang 		break;
26228d0997cSElaine Zhang 	case PCLK_CENTER_ROOT:
26328d0997cSElaine Zhang 		if (rate >= 198 * MHz)
26428d0997cSElaine Zhang 			src_clk = PCLK_CENTER_ROOT_SEL_200M;
26528d0997cSElaine Zhang 		else if (rate >= 99 * MHz)
26628d0997cSElaine Zhang 			src_clk = PCLK_CENTER_ROOT_SEL_100M;
26728d0997cSElaine Zhang 		else if (rate >= 50 * MHz)
26828d0997cSElaine Zhang 			src_clk = PCLK_CENTER_ROOT_SEL_50M;
26928d0997cSElaine Zhang 		else
27028d0997cSElaine Zhang 			src_clk = PCLK_CENTER_ROOT_SEL_24M;
27128d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[165],
27228d0997cSElaine Zhang 			     PCLK_CENTER_ROOT_SEL_MASK,
27328d0997cSElaine Zhang 			     src_clk << PCLK_CENTER_ROOT_SEL_SHIFT);
27428d0997cSElaine Zhang 		break;
27528d0997cSElaine Zhang 	default:
27628d0997cSElaine Zhang 		printf("do not support this center freq\n");
27728d0997cSElaine Zhang 		return -EINVAL;
27828d0997cSElaine Zhang 	}
27928d0997cSElaine Zhang 
28028d0997cSElaine Zhang 	return rk3588_center_get_clk(priv, clk_id);
28128d0997cSElaine Zhang }
28228d0997cSElaine Zhang 
rk3588_top_get_clk(struct rk3588_clk_priv * priv,ulong clk_id)28328d0997cSElaine Zhang static ulong rk3588_top_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
28428d0997cSElaine Zhang {
28528d0997cSElaine Zhang 	struct rk3588_cru *cru = priv->cru;
28628d0997cSElaine Zhang 	u32 con, sel, div, rate, prate;
28728d0997cSElaine Zhang 
28828d0997cSElaine Zhang 	switch (clk_id) {
28928d0997cSElaine Zhang 	case ACLK_TOP_ROOT:
29028d0997cSElaine Zhang 		con = readl(&cru->clksel_con[8]);
29128d0997cSElaine Zhang 		div = (con & ACLK_TOP_ROOT_DIV_MASK) >>
29228d0997cSElaine Zhang 		      ACLK_TOP_ROOT_DIV_SHIFT;
29328d0997cSElaine Zhang 		sel = (con & ACLK_TOP_ROOT_SRC_SEL_MASK) >>
29428d0997cSElaine Zhang 		      ACLK_TOP_ROOT_SRC_SEL_SHIFT;
29528d0997cSElaine Zhang 		if (sel == ACLK_TOP_ROOT_SRC_SEL_CPLL)
29628d0997cSElaine Zhang 			prate = priv->cpll_hz;
29728d0997cSElaine Zhang 		else
298770d6e81SJianqun Xu 			prate = priv->gpll_hz;
29928d0997cSElaine Zhang 		return DIV_TO_RATE(prate, div);
30028d0997cSElaine Zhang 	case ACLK_LOW_TOP_ROOT:
30128d0997cSElaine Zhang 		con = readl(&cru->clksel_con[8]);
30228d0997cSElaine Zhang 		div = (con & ACLK_LOW_TOP_ROOT_DIV_MASK) >>
30328d0997cSElaine Zhang 		      ACLK_LOW_TOP_ROOT_DIV_SHIFT;
30428d0997cSElaine Zhang 		sel = (con & ACLK_LOW_TOP_ROOT_SRC_SEL_MASK) >>
30528d0997cSElaine Zhang 		      ACLK_LOW_TOP_ROOT_SRC_SEL_SHIFT;
30628d0997cSElaine Zhang 		if (sel == ACLK_LOW_TOP_ROOT_SRC_SEL_CPLL)
30728d0997cSElaine Zhang 			prate = priv->cpll_hz;
30828d0997cSElaine Zhang 		else
30928d0997cSElaine Zhang 			prate = priv->gpll_hz;
31028d0997cSElaine Zhang 		return DIV_TO_RATE(prate, div);
31128d0997cSElaine Zhang 	case PCLK_TOP_ROOT:
31228d0997cSElaine Zhang 		con = readl(&cru->clksel_con[8]);
31328d0997cSElaine Zhang 		sel = (con & PCLK_TOP_ROOT_SEL_MASK) >> PCLK_TOP_ROOT_SEL_SHIFT;
31428d0997cSElaine Zhang 		if (sel == PCLK_TOP_ROOT_SEL_100M)
31528d0997cSElaine Zhang 			rate = 100 * MHz;
31628d0997cSElaine Zhang 		else if (sel == PCLK_TOP_ROOT_SEL_50M)
31728d0997cSElaine Zhang 			rate = 50 * MHz;
31828d0997cSElaine Zhang 		else
31928d0997cSElaine Zhang 			rate = OSC_HZ;
32028d0997cSElaine Zhang 		break;
32128d0997cSElaine Zhang 	default:
32228d0997cSElaine Zhang 		return -ENOENT;
32328d0997cSElaine Zhang 	}
32428d0997cSElaine Zhang 
32528d0997cSElaine Zhang 	return rate;
32628d0997cSElaine Zhang }
32728d0997cSElaine Zhang 
rk3588_top_set_clk(struct rk3588_clk_priv * priv,ulong clk_id,ulong rate)32828d0997cSElaine Zhang static ulong rk3588_top_set_clk(struct rk3588_clk_priv *priv,
32928d0997cSElaine Zhang 				ulong clk_id, ulong rate)
33028d0997cSElaine Zhang {
33128d0997cSElaine Zhang 	struct rk3588_cru *cru = priv->cru;
33228d0997cSElaine Zhang 	int src_clk, src_clk_div;
33328d0997cSElaine Zhang 
33428d0997cSElaine Zhang 	switch (clk_id) {
33528d0997cSElaine Zhang 	case ACLK_TOP_ROOT:
336548224a1SElaine Zhang 		if (!(priv->cpll_hz % rate)) {
337548224a1SElaine Zhang 			src_clk = ACLK_TOP_ROOT_SRC_SEL_CPLL;
338548224a1SElaine Zhang 			src_clk_div = DIV_ROUND_UP(priv->cpll_hz, rate);
339548224a1SElaine Zhang 		} else {
340548224a1SElaine Zhang 			src_clk = ACLK_TOP_ROOT_SRC_SEL_GPLL;
34128d0997cSElaine Zhang 			src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
342548224a1SElaine Zhang 		}
34328d0997cSElaine Zhang 		assert(src_clk_div - 1 <= 31);
34428d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[8],
34528d0997cSElaine Zhang 			     ACLK_TOP_ROOT_DIV_MASK |
34628d0997cSElaine Zhang 			     ACLK_TOP_ROOT_SRC_SEL_MASK,
347548224a1SElaine Zhang 			     (src_clk <<
34828d0997cSElaine Zhang 			      ACLK_TOP_ROOT_SRC_SEL_SHIFT) |
34928d0997cSElaine Zhang 			     (src_clk_div - 1) << ACLK_TOP_ROOT_DIV_SHIFT);
35028d0997cSElaine Zhang 		break;
35128d0997cSElaine Zhang 	case ACLK_LOW_TOP_ROOT:
35228d0997cSElaine Zhang 		src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
35328d0997cSElaine Zhang 		assert(src_clk_div - 1 <= 31);
35428d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[8],
35528d0997cSElaine Zhang 			     ACLK_LOW_TOP_ROOT_DIV_MASK |
35628d0997cSElaine Zhang 			     ACLK_LOW_TOP_ROOT_SRC_SEL_MASK,
35728d0997cSElaine Zhang 			     (ACLK_LOW_TOP_ROOT_SRC_SEL_GPLL <<
35828d0997cSElaine Zhang 			      ACLK_LOW_TOP_ROOT_SRC_SEL_SHIFT) |
35928d0997cSElaine Zhang 			     (src_clk_div - 1) << ACLK_LOW_TOP_ROOT_DIV_SHIFT);
36028d0997cSElaine Zhang 		break;
36128d0997cSElaine Zhang 	case PCLK_TOP_ROOT:
36228d0997cSElaine Zhang 		if (rate == 100 * MHz)
36328d0997cSElaine Zhang 			src_clk = PCLK_TOP_ROOT_SEL_100M;
36428d0997cSElaine Zhang 		else if (rate == 50 * MHz)
36528d0997cSElaine Zhang 			src_clk = PCLK_TOP_ROOT_SEL_50M;
36628d0997cSElaine Zhang 		else
36728d0997cSElaine Zhang 			src_clk = PCLK_TOP_ROOT_SEL_24M;
36828d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[8],
36928d0997cSElaine Zhang 			     PCLK_TOP_ROOT_SEL_MASK,
37028d0997cSElaine Zhang 			     src_clk << PCLK_TOP_ROOT_SEL_SHIFT);
37128d0997cSElaine Zhang 		break;
37228d0997cSElaine Zhang 	default:
37328d0997cSElaine Zhang 		printf("do not support this top freq\n");
37428d0997cSElaine Zhang 		return -EINVAL;
37528d0997cSElaine Zhang 	}
37628d0997cSElaine Zhang 
37728d0997cSElaine Zhang 	return rk3588_top_get_clk(priv, clk_id);
37828d0997cSElaine Zhang }
37928d0997cSElaine Zhang 
rk3588_i2c_get_clk(struct rk3588_clk_priv * priv,ulong clk_id)38028d0997cSElaine Zhang static ulong rk3588_i2c_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
38128d0997cSElaine Zhang {
38228d0997cSElaine Zhang 	struct rk3588_cru *cru = priv->cru;
38328d0997cSElaine Zhang 	u32 sel, con;
38428d0997cSElaine Zhang 	ulong rate;
38528d0997cSElaine Zhang 
38628d0997cSElaine Zhang 	switch (clk_id) {
38728d0997cSElaine Zhang 	case CLK_I2C0:
38828d0997cSElaine Zhang 		con = readl(&cru->pmuclksel_con[3]);
38928d0997cSElaine Zhang 		sel = (con & CLK_I2C0_SEL_MASK) >> CLK_I2C0_SEL_SHIFT;
39028d0997cSElaine Zhang 		break;
39128d0997cSElaine Zhang 	case CLK_I2C1:
39228d0997cSElaine Zhang 		con = readl(&cru->clksel_con[38]);
39328d0997cSElaine Zhang 		sel = (con & CLK_I2C1_SEL_MASK) >> CLK_I2C1_SEL_SHIFT;
39428d0997cSElaine Zhang 		break;
39528d0997cSElaine Zhang 	case CLK_I2C2:
39628d0997cSElaine Zhang 		con = readl(&cru->clksel_con[38]);
39728d0997cSElaine Zhang 		sel = (con & CLK_I2C2_SEL_MASK) >> CLK_I2C2_SEL_SHIFT;
39828d0997cSElaine Zhang 		break;
39928d0997cSElaine Zhang 	case CLK_I2C3:
40028d0997cSElaine Zhang 		con = readl(&cru->clksel_con[38]);
40128d0997cSElaine Zhang 		sel = (con & CLK_I2C3_SEL_MASK) >> CLK_I2C3_SEL_SHIFT;
40228d0997cSElaine Zhang 		break;
40328d0997cSElaine Zhang 	case CLK_I2C4:
40428d0997cSElaine Zhang 		con = readl(&cru->clksel_con[38]);
40528d0997cSElaine Zhang 		sel = (con & CLK_I2C4_SEL_MASK) >> CLK_I2C4_SEL_SHIFT;
40628d0997cSElaine Zhang 		break;
40728d0997cSElaine Zhang 	case CLK_I2C5:
40828d0997cSElaine Zhang 		con = readl(&cru->clksel_con[38]);
40928d0997cSElaine Zhang 		sel = (con & CLK_I2C5_SEL_MASK) >> CLK_I2C5_SEL_SHIFT;
41028d0997cSElaine Zhang 		break;
41128d0997cSElaine Zhang 	case CLK_I2C6:
41228d0997cSElaine Zhang 		con = readl(&cru->clksel_con[38]);
41328d0997cSElaine Zhang 		sel = (con & CLK_I2C6_SEL_MASK) >> CLK_I2C6_SEL_SHIFT;
41428d0997cSElaine Zhang 		break;
41528d0997cSElaine Zhang 	case CLK_I2C7:
41628d0997cSElaine Zhang 		con = readl(&cru->clksel_con[38]);
41728d0997cSElaine Zhang 		sel = (con & CLK_I2C7_SEL_MASK) >> CLK_I2C7_SEL_SHIFT;
41828d0997cSElaine Zhang 		break;
41928d0997cSElaine Zhang 	case CLK_I2C8:
42028d0997cSElaine Zhang 		con = readl(&cru->clksel_con[38]);
42128d0997cSElaine Zhang 		sel = (con & CLK_I2C8_SEL_MASK) >> CLK_I2C8_SEL_SHIFT;
42228d0997cSElaine Zhang 		break;
42328d0997cSElaine Zhang 	default:
42428d0997cSElaine Zhang 		return -ENOENT;
42528d0997cSElaine Zhang 	}
42628d0997cSElaine Zhang 	if (sel == CLK_I2C_SEL_200M)
42728d0997cSElaine Zhang 		rate = 200 * MHz;
42828d0997cSElaine Zhang 	else
42928d0997cSElaine Zhang 		rate = 100 * MHz;
43028d0997cSElaine Zhang 
43128d0997cSElaine Zhang 	return rate;
43228d0997cSElaine Zhang }
43328d0997cSElaine Zhang 
rk3588_i2c_set_clk(struct rk3588_clk_priv * priv,ulong clk_id,ulong rate)43428d0997cSElaine Zhang static ulong rk3588_i2c_set_clk(struct rk3588_clk_priv *priv, ulong clk_id,
43528d0997cSElaine Zhang 				ulong rate)
43628d0997cSElaine Zhang {
43728d0997cSElaine Zhang 	struct rk3588_cru *cru = priv->cru;
43828d0997cSElaine Zhang 	int src_clk;
43928d0997cSElaine Zhang 
44028d0997cSElaine Zhang 	if (rate >= 198 * MHz)
44128d0997cSElaine Zhang 		src_clk = CLK_I2C_SEL_200M;
44228d0997cSElaine Zhang 	else
44328d0997cSElaine Zhang 		src_clk = CLK_I2C_SEL_100M;
44428d0997cSElaine Zhang 
44528d0997cSElaine Zhang 	switch (clk_id) {
44628d0997cSElaine Zhang 	case CLK_I2C0:
44728d0997cSElaine Zhang 		rk_clrsetreg(&cru->pmuclksel_con[3], CLK_I2C0_SEL_MASK,
44828d0997cSElaine Zhang 			     src_clk << CLK_I2C0_SEL_SHIFT);
44928d0997cSElaine Zhang 		break;
45028d0997cSElaine Zhang 	case CLK_I2C1:
45128d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[38], CLK_I2C1_SEL_MASK,
45228d0997cSElaine Zhang 			     src_clk << CLK_I2C1_SEL_SHIFT);
45328d0997cSElaine Zhang 		break;
45428d0997cSElaine Zhang 	case CLK_I2C2:
45528d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[38], CLK_I2C2_SEL_MASK,
45628d0997cSElaine Zhang 			     src_clk << CLK_I2C2_SEL_SHIFT);
45728d0997cSElaine Zhang 		break;
45828d0997cSElaine Zhang 	case CLK_I2C3:
45928d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[38], CLK_I2C3_SEL_MASK,
46028d0997cSElaine Zhang 			     src_clk << CLK_I2C3_SEL_SHIFT);
46128d0997cSElaine Zhang 		break;
46228d0997cSElaine Zhang 	case CLK_I2C4:
46328d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[38], CLK_I2C4_SEL_MASK,
46428d0997cSElaine Zhang 			     src_clk << CLK_I2C4_SEL_SHIFT);
46528d0997cSElaine Zhang 		break;
46628d0997cSElaine Zhang 	case CLK_I2C5:
46728d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[38], CLK_I2C5_SEL_MASK,
46828d0997cSElaine Zhang 			     src_clk << CLK_I2C5_SEL_SHIFT);
46928d0997cSElaine Zhang 		break;
47028d0997cSElaine Zhang 	case CLK_I2C6:
47128d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[38], CLK_I2C6_SEL_MASK,
47228d0997cSElaine Zhang 			     src_clk << CLK_I2C6_SEL_SHIFT);
47328d0997cSElaine Zhang 		break;
47428d0997cSElaine Zhang 	case CLK_I2C7:
47528d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[38], CLK_I2C7_SEL_MASK,
47628d0997cSElaine Zhang 			     src_clk << CLK_I2C7_SEL_SHIFT);
47728d0997cSElaine Zhang 		break;
47828d0997cSElaine Zhang 	case CLK_I2C8:
47928d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[38], CLK_I2C8_SEL_MASK,
48028d0997cSElaine Zhang 			     src_clk << CLK_I2C8_SEL_SHIFT);
48128d0997cSElaine Zhang 		break;
48228d0997cSElaine Zhang 	default:
48328d0997cSElaine Zhang 		return -ENOENT;
48428d0997cSElaine Zhang 	}
48528d0997cSElaine Zhang 
48628d0997cSElaine Zhang 	return rk3588_i2c_get_clk(priv, clk_id);
48728d0997cSElaine Zhang }
48828d0997cSElaine Zhang 
rk3588_spi_get_clk(struct rk3588_clk_priv * priv,ulong clk_id)48928d0997cSElaine Zhang static ulong rk3588_spi_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
49028d0997cSElaine Zhang {
49128d0997cSElaine Zhang 	struct rk3588_cru *cru = priv->cru;
49228d0997cSElaine Zhang 	u32 sel, con;
49328d0997cSElaine Zhang 
49428d0997cSElaine Zhang 	con = readl(&cru->clksel_con[59]);
49528d0997cSElaine Zhang 
49628d0997cSElaine Zhang 	switch (clk_id) {
49728d0997cSElaine Zhang 	case CLK_SPI0:
49828d0997cSElaine Zhang 		sel = (con & CLK_SPI0_SEL_MASK) >> CLK_SPI0_SEL_SHIFT;
49928d0997cSElaine Zhang 		break;
50028d0997cSElaine Zhang 	case CLK_SPI1:
50128d0997cSElaine Zhang 		sel = (con & CLK_SPI1_SEL_MASK) >> CLK_SPI1_SEL_SHIFT;
50228d0997cSElaine Zhang 		break;
50328d0997cSElaine Zhang 	case CLK_SPI2:
50428d0997cSElaine Zhang 		sel = (con & CLK_SPI2_SEL_MASK) >> CLK_SPI2_SEL_SHIFT;
50528d0997cSElaine Zhang 		break;
50628d0997cSElaine Zhang 	case CLK_SPI3:
50728d0997cSElaine Zhang 		sel = (con & CLK_SPI3_SEL_MASK) >> CLK_SPI3_SEL_SHIFT;
50828d0997cSElaine Zhang 		break;
50928d0997cSElaine Zhang 	case CLK_SPI4:
51028d0997cSElaine Zhang 		sel = (con & CLK_SPI4_SEL_MASK) >> CLK_SPI4_SEL_SHIFT;
51128d0997cSElaine Zhang 		break;
51228d0997cSElaine Zhang 	default:
51328d0997cSElaine Zhang 		return -ENOENT;
51428d0997cSElaine Zhang 	}
51528d0997cSElaine Zhang 
51628d0997cSElaine Zhang 	switch (sel) {
51728d0997cSElaine Zhang 	case CLK_SPI_SEL_200M:
51828d0997cSElaine Zhang 		return 200 * MHz;
51928d0997cSElaine Zhang 	case CLK_SPI_SEL_150M:
52028d0997cSElaine Zhang 		return 150 * MHz;
52128d0997cSElaine Zhang 	case CLK_SPI_SEL_24M:
52228d0997cSElaine Zhang 		return OSC_HZ;
52328d0997cSElaine Zhang 	default:
52428d0997cSElaine Zhang 		return -ENOENT;
52528d0997cSElaine Zhang 	}
52628d0997cSElaine Zhang }
52728d0997cSElaine Zhang 
rk3588_spi_set_clk(struct rk3588_clk_priv * priv,ulong clk_id,ulong rate)52828d0997cSElaine Zhang static ulong rk3588_spi_set_clk(struct rk3588_clk_priv *priv,
52928d0997cSElaine Zhang 				ulong clk_id, ulong rate)
53028d0997cSElaine Zhang {
53128d0997cSElaine Zhang 	struct rk3588_cru *cru = priv->cru;
53228d0997cSElaine Zhang 	int src_clk;
53328d0997cSElaine Zhang 
53428d0997cSElaine Zhang 	if (rate >= 198 * MHz)
53528d0997cSElaine Zhang 		src_clk = CLK_SPI_SEL_200M;
53628d0997cSElaine Zhang 	else if (rate >= 140 * MHz)
53728d0997cSElaine Zhang 		src_clk = CLK_SPI_SEL_150M;
53828d0997cSElaine Zhang 	else
53928d0997cSElaine Zhang 		src_clk = CLK_SPI_SEL_24M;
54028d0997cSElaine Zhang 
54128d0997cSElaine Zhang 	switch (clk_id) {
54228d0997cSElaine Zhang 	case CLK_SPI0:
54328d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[59],
54428d0997cSElaine Zhang 			     CLK_SPI0_SEL_MASK,
54528d0997cSElaine Zhang 			     src_clk << CLK_SPI0_SEL_SHIFT);
54628d0997cSElaine Zhang 		break;
54728d0997cSElaine Zhang 	case CLK_SPI1:
54828d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[59],
54928d0997cSElaine Zhang 			     CLK_SPI1_SEL_MASK,
55028d0997cSElaine Zhang 			     src_clk << CLK_SPI1_SEL_SHIFT);
55128d0997cSElaine Zhang 		break;
55228d0997cSElaine Zhang 	case CLK_SPI2:
55328d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[59],
55428d0997cSElaine Zhang 			     CLK_SPI2_SEL_MASK,
55528d0997cSElaine Zhang 			     src_clk << CLK_SPI2_SEL_SHIFT);
55628d0997cSElaine Zhang 		break;
55728d0997cSElaine Zhang 	case CLK_SPI3:
55828d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[59],
55928d0997cSElaine Zhang 			     CLK_SPI3_SEL_MASK,
56028d0997cSElaine Zhang 			     src_clk << CLK_SPI3_SEL_SHIFT);
56128d0997cSElaine Zhang 		break;
56228d0997cSElaine Zhang 	case CLK_SPI4:
56328d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[59],
56428d0997cSElaine Zhang 			     CLK_SPI4_SEL_MASK,
56528d0997cSElaine Zhang 			     src_clk << CLK_SPI4_SEL_SHIFT);
56628d0997cSElaine Zhang 		break;
56728d0997cSElaine Zhang 	default:
56828d0997cSElaine Zhang 		return -ENOENT;
56928d0997cSElaine Zhang 	}
57028d0997cSElaine Zhang 
57128d0997cSElaine Zhang 	return rk3588_spi_get_clk(priv, clk_id);
57228d0997cSElaine Zhang }
57328d0997cSElaine Zhang 
rk3588_pwm_get_clk(struct rk3588_clk_priv * priv,ulong clk_id)57428d0997cSElaine Zhang static ulong rk3588_pwm_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
57528d0997cSElaine Zhang {
57628d0997cSElaine Zhang 	struct rk3588_cru *cru = priv->cru;
57728d0997cSElaine Zhang 	u32 sel, con;
57828d0997cSElaine Zhang 
57928d0997cSElaine Zhang 	switch (clk_id) {
58028d0997cSElaine Zhang 	case CLK_PWM1:
58128d0997cSElaine Zhang 		con = readl(&cru->clksel_con[59]);
582a8b73cd2SDamon Ding 		sel = (con & CLK_PWM1_SEL_MASK) >> CLK_PWM1_SEL_SHIFT;
58328d0997cSElaine Zhang 		break;
58428d0997cSElaine Zhang 	case CLK_PWM2:
58528d0997cSElaine Zhang 		con = readl(&cru->clksel_con[59]);
58628d0997cSElaine Zhang 		sel = (con & CLK_PWM2_SEL_MASK) >> CLK_PWM2_SEL_SHIFT;
58728d0997cSElaine Zhang 		break;
58828d0997cSElaine Zhang 	case CLK_PWM3:
58928d0997cSElaine Zhang 		con = readl(&cru->clksel_con[60]);
59028d0997cSElaine Zhang 		sel = (con & CLK_PWM3_SEL_MASK) >> CLK_PWM3_SEL_SHIFT;
59128d0997cSElaine Zhang 		break;
5926fe01683SElaine Zhang 	case CLK_PMU1PWM:
5936fe01683SElaine Zhang 		con = readl(&cru->pmuclksel_con[2]);
5946fe01683SElaine Zhang 		sel = (con & CLK_PMU1PWM_SEL_MASK) >> CLK_PMU1PWM_SEL_SHIFT;
5956fe01683SElaine Zhang 		break;
59628d0997cSElaine Zhang 	default:
59728d0997cSElaine Zhang 		return -ENOENT;
59828d0997cSElaine Zhang 	}
59928d0997cSElaine Zhang 
60028d0997cSElaine Zhang 	switch (sel) {
60128d0997cSElaine Zhang 	case CLK_PWM_SEL_100M:
60228d0997cSElaine Zhang 		return 100 * MHz;
60328d0997cSElaine Zhang 	case CLK_PWM_SEL_50M:
60428d0997cSElaine Zhang 		return 50 * MHz;
60528d0997cSElaine Zhang 	case CLK_PWM_SEL_24M:
60628d0997cSElaine Zhang 		return OSC_HZ;
60728d0997cSElaine Zhang 	default:
60828d0997cSElaine Zhang 		return -ENOENT;
60928d0997cSElaine Zhang 	}
61028d0997cSElaine Zhang }
61128d0997cSElaine Zhang 
rk3588_pwm_set_clk(struct rk3588_clk_priv * priv,ulong clk_id,ulong rate)61228d0997cSElaine Zhang static ulong rk3588_pwm_set_clk(struct rk3588_clk_priv *priv,
61328d0997cSElaine Zhang 				ulong clk_id, ulong rate)
61428d0997cSElaine Zhang {
61528d0997cSElaine Zhang 	struct rk3588_cru *cru = priv->cru;
61628d0997cSElaine Zhang 	int src_clk;
61728d0997cSElaine Zhang 
61828d0997cSElaine Zhang 	if (rate >= 99 * MHz)
61928d0997cSElaine Zhang 		src_clk = CLK_PWM_SEL_100M;
62028d0997cSElaine Zhang 	else if (rate >= 50 * MHz)
62128d0997cSElaine Zhang 		src_clk = CLK_PWM_SEL_50M;
62228d0997cSElaine Zhang 	else
62328d0997cSElaine Zhang 		src_clk = CLK_PWM_SEL_24M;
62428d0997cSElaine Zhang 
62528d0997cSElaine Zhang 	switch (clk_id) {
62628d0997cSElaine Zhang 	case CLK_PWM1:
62728d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[59],
62828d0997cSElaine Zhang 			     CLK_PWM1_SEL_MASK,
62928d0997cSElaine Zhang 			     src_clk << CLK_PWM1_SEL_SHIFT);
63028d0997cSElaine Zhang 		break;
63128d0997cSElaine Zhang 	case CLK_PWM2:
63228d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[59],
63328d0997cSElaine Zhang 			     CLK_PWM2_SEL_MASK,
63428d0997cSElaine Zhang 			     src_clk << CLK_PWM2_SEL_SHIFT);
63528d0997cSElaine Zhang 		break;
63628d0997cSElaine Zhang 	case CLK_PWM3:
63728d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[60],
63828d0997cSElaine Zhang 			     CLK_PWM3_SEL_MASK,
63928d0997cSElaine Zhang 			     src_clk << CLK_PWM3_SEL_SHIFT);
64028d0997cSElaine Zhang 		break;
6416fe01683SElaine Zhang 	case CLK_PMU1PWM:
6426fe01683SElaine Zhang 		rk_clrsetreg(&cru->pmuclksel_con[2],
6436fe01683SElaine Zhang 			     CLK_PMU1PWM_SEL_MASK,
6446fe01683SElaine Zhang 			     src_clk << CLK_PMU1PWM_SEL_SHIFT);
6456fe01683SElaine Zhang 		break;
64628d0997cSElaine Zhang 	default:
64728d0997cSElaine Zhang 		return -ENOENT;
64828d0997cSElaine Zhang 	}
64928d0997cSElaine Zhang 
65028d0997cSElaine Zhang 	return rk3588_pwm_get_clk(priv, clk_id);
65128d0997cSElaine Zhang }
65228d0997cSElaine Zhang 
rk3588_adc_get_clk(struct rk3588_clk_priv * priv,ulong clk_id)65328d0997cSElaine Zhang static ulong rk3588_adc_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
65428d0997cSElaine Zhang {
65528d0997cSElaine Zhang 	struct rk3588_cru *cru = priv->cru;
65628d0997cSElaine Zhang 	u32 div, sel, con, prate;
65728d0997cSElaine Zhang 
65828d0997cSElaine Zhang 	switch (clk_id) {
65928d0997cSElaine Zhang 	case CLK_SARADC:
66028d0997cSElaine Zhang 		con = readl(&cru->clksel_con[40]);
66128d0997cSElaine Zhang 		div = (con & CLK_SARADC_DIV_MASK) >> CLK_SARADC_DIV_SHIFT;
66228d0997cSElaine Zhang 		sel = (con & CLK_SARADC_SEL_MASK) >>
66328d0997cSElaine Zhang 		      CLK_SARADC_SEL_SHIFT;
66428d0997cSElaine Zhang 		if (sel == CLK_SARADC_SEL_24M)
66528d0997cSElaine Zhang 			prate = OSC_HZ;
66628d0997cSElaine Zhang 		else
66728d0997cSElaine Zhang 			prate = priv->gpll_hz;
66828d0997cSElaine Zhang 		return DIV_TO_RATE(prate, div);
66928d0997cSElaine Zhang 	case CLK_TSADC:
67028d0997cSElaine Zhang 		con = readl(&cru->clksel_con[41]);
67128d0997cSElaine Zhang 		div = (con & CLK_TSADC_DIV_MASK) >>
67228d0997cSElaine Zhang 		      CLK_TSADC_DIV_SHIFT;
67328d0997cSElaine Zhang 		sel = (con & CLK_TSADC_SEL_MASK) >>
67428d0997cSElaine Zhang 		      CLK_TSADC_SEL_SHIFT;
67528d0997cSElaine Zhang 		if (sel == CLK_TSADC_SEL_24M)
67628d0997cSElaine Zhang 			prate = OSC_HZ;
67728d0997cSElaine Zhang 		else
67828d0997cSElaine Zhang 			prate = 100 * MHz;
67928d0997cSElaine Zhang 		return DIV_TO_RATE(prate, div);
68028d0997cSElaine Zhang 	default:
68128d0997cSElaine Zhang 		return -ENOENT;
68228d0997cSElaine Zhang 	}
68328d0997cSElaine Zhang }
68428d0997cSElaine Zhang 
rk3588_adc_set_clk(struct rk3588_clk_priv * priv,ulong clk_id,ulong rate)68528d0997cSElaine Zhang static ulong rk3588_adc_set_clk(struct rk3588_clk_priv *priv,
68628d0997cSElaine Zhang 				ulong clk_id, ulong rate)
68728d0997cSElaine Zhang {
68828d0997cSElaine Zhang 	struct rk3588_cru *cru = priv->cru;
68928d0997cSElaine Zhang 	int src_clk_div;
69028d0997cSElaine Zhang 
69128d0997cSElaine Zhang 	switch (clk_id) {
69228d0997cSElaine Zhang 	case CLK_SARADC:
69328d0997cSElaine Zhang 		if (!(OSC_HZ % rate)) {
69428d0997cSElaine Zhang 			src_clk_div = DIV_ROUND_UP(OSC_HZ, rate);
69528d0997cSElaine Zhang 			assert(src_clk_div - 1 <= 255);
69628d0997cSElaine Zhang 			rk_clrsetreg(&cru->clksel_con[40],
69728d0997cSElaine Zhang 				     CLK_SARADC_SEL_MASK |
69828d0997cSElaine Zhang 				     CLK_SARADC_DIV_MASK,
69928d0997cSElaine Zhang 				     (CLK_SARADC_SEL_24M <<
70028d0997cSElaine Zhang 				      CLK_SARADC_SEL_SHIFT) |
70128d0997cSElaine Zhang 				     (src_clk_div - 1) <<
70228d0997cSElaine Zhang 				     CLK_SARADC_DIV_SHIFT);
70328d0997cSElaine Zhang 		} else {
70428d0997cSElaine Zhang 			src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
70528d0997cSElaine Zhang 			assert(src_clk_div - 1 <= 255);
70628d0997cSElaine Zhang 			rk_clrsetreg(&cru->clksel_con[40],
70728d0997cSElaine Zhang 				     CLK_SARADC_SEL_MASK |
70828d0997cSElaine Zhang 				     CLK_SARADC_DIV_MASK,
70928d0997cSElaine Zhang 				     (CLK_SARADC_SEL_GPLL <<
71028d0997cSElaine Zhang 				      CLK_SARADC_SEL_SHIFT) |
71128d0997cSElaine Zhang 				     (src_clk_div - 1) <<
71228d0997cSElaine Zhang 				     CLK_SARADC_DIV_SHIFT);
71328d0997cSElaine Zhang 		}
71428d0997cSElaine Zhang 		break;
71528d0997cSElaine Zhang 	case CLK_TSADC:
71628d0997cSElaine Zhang 		if (!(OSC_HZ % rate)) {
71728d0997cSElaine Zhang 			src_clk_div = DIV_ROUND_UP(OSC_HZ, rate);
71828d0997cSElaine Zhang 			assert(src_clk_div - 1 <= 255);
71928d0997cSElaine Zhang 			rk_clrsetreg(&cru->clksel_con[41],
72028d0997cSElaine Zhang 				     CLK_TSADC_SEL_MASK |
72128d0997cSElaine Zhang 				     CLK_TSADC_DIV_MASK,
72228d0997cSElaine Zhang 				     (CLK_TSADC_SEL_24M <<
72328d0997cSElaine Zhang 				      CLK_TSADC_SEL_SHIFT) |
72428d0997cSElaine Zhang 				     (src_clk_div - 1) <<
72528d0997cSElaine Zhang 				     CLK_TSADC_DIV_SHIFT);
72628d0997cSElaine Zhang 		} else {
72728d0997cSElaine Zhang 			src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
72828d0997cSElaine Zhang 			assert(src_clk_div - 1 <= 7);
72928d0997cSElaine Zhang 			rk_clrsetreg(&cru->clksel_con[41],
73028d0997cSElaine Zhang 				     CLK_TSADC_SEL_MASK |
73128d0997cSElaine Zhang 				     CLK_TSADC_DIV_MASK,
73228d0997cSElaine Zhang 				     (CLK_TSADC_SEL_GPLL <<
73328d0997cSElaine Zhang 				      CLK_TSADC_SEL_SHIFT) |
73428d0997cSElaine Zhang 				     (src_clk_div - 1) <<
73528d0997cSElaine Zhang 				     CLK_TSADC_DIV_SHIFT);
73628d0997cSElaine Zhang 		}
73728d0997cSElaine Zhang 		break;
73828d0997cSElaine Zhang 	default:
73928d0997cSElaine Zhang 		return -ENOENT;
74028d0997cSElaine Zhang 	}
74128d0997cSElaine Zhang 	return rk3588_adc_get_clk(priv, clk_id);
74228d0997cSElaine Zhang }
74328d0997cSElaine Zhang 
rk3588_mmc_get_clk(struct rk3588_clk_priv * priv,ulong clk_id)74428d0997cSElaine Zhang static ulong rk3588_mmc_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
74528d0997cSElaine Zhang {
74628d0997cSElaine Zhang 	struct rk3588_cru *cru = priv->cru;
74728d0997cSElaine Zhang 	u32 sel, con, div, prate;
74828d0997cSElaine Zhang 
74928d0997cSElaine Zhang 	switch (clk_id) {
75028d0997cSElaine Zhang 	case CCLK_SRC_SDIO:
75128d0997cSElaine Zhang 		con = readl(&cru->clksel_con[172]);
75228d0997cSElaine Zhang 		div = (con & CCLK_SDIO_SRC_DIV_MASK) >> CCLK_SDIO_SRC_DIV_SHIFT;
75328d0997cSElaine Zhang 		sel = (con & CCLK_SDIO_SRC_SEL_MASK) >>
75428d0997cSElaine Zhang 		      CCLK_SDIO_SRC_SEL_SHIFT;
75528d0997cSElaine Zhang 		if (sel == CCLK_SDIO_SRC_SEL_GPLL)
75628d0997cSElaine Zhang 			prate = priv->gpll_hz;
75728d0997cSElaine Zhang 		else if (sel == CCLK_SDIO_SRC_SEL_CPLL)
75828d0997cSElaine Zhang 			prate = priv->cpll_hz;
75928d0997cSElaine Zhang 		else
76028d0997cSElaine Zhang 			prate = OSC_HZ;
76128d0997cSElaine Zhang 		return DIV_TO_RATE(prate, div);
76228d0997cSElaine Zhang 	case CCLK_EMMC:
76328d0997cSElaine Zhang 		con = readl(&cru->clksel_con[77]);
76428d0997cSElaine Zhang 		div = (con & CCLK_EMMC_DIV_MASK) >> CCLK_EMMC_DIV_SHIFT;
76528d0997cSElaine Zhang 		sel = (con & CCLK_EMMC_SEL_MASK) >>
76628d0997cSElaine Zhang 		      CCLK_EMMC_SEL_SHIFT;
76728d0997cSElaine Zhang 		if (sel == CCLK_EMMC_SEL_GPLL)
76828d0997cSElaine Zhang 			prate = priv->gpll_hz;
76928d0997cSElaine Zhang 		else if (sel == CCLK_EMMC_SEL_CPLL)
77028d0997cSElaine Zhang 			prate = priv->cpll_hz;
77128d0997cSElaine Zhang 		else
77228d0997cSElaine Zhang 			prate = OSC_HZ;
77328d0997cSElaine Zhang 		return DIV_TO_RATE(prate, div);
77428d0997cSElaine Zhang 	case BCLK_EMMC:
77528d0997cSElaine Zhang 		con = readl(&cru->clksel_con[78]);
77628d0997cSElaine Zhang 		div = (con & BCLK_EMMC_DIV_MASK) >> BCLK_EMMC_DIV_SHIFT;
77728d0997cSElaine Zhang 		sel = (con & BCLK_EMMC_SEL_MASK) >>
77828d0997cSElaine Zhang 		      BCLK_EMMC_SEL_SHIFT;
77928d0997cSElaine Zhang 		if (sel == CCLK_EMMC_SEL_CPLL)
78028d0997cSElaine Zhang 			prate = priv->cpll_hz;
78128d0997cSElaine Zhang 		else
78228d0997cSElaine Zhang 			prate = priv->gpll_hz;
78328d0997cSElaine Zhang 		return DIV_TO_RATE(prate, div);
78428d0997cSElaine Zhang 	case SCLK_SFC:
78528d0997cSElaine Zhang 		con = readl(&cru->clksel_con[78]);
78628d0997cSElaine Zhang 		div = (con & SCLK_SFC_DIV_MASK) >> SCLK_SFC_DIV_SHIFT;
78728d0997cSElaine Zhang 		sel = (con & SCLK_SFC_SEL_MASK) >>
78828d0997cSElaine Zhang 		      SCLK_SFC_SEL_SHIFT;
78928d0997cSElaine Zhang 		if (sel == SCLK_SFC_SEL_GPLL)
79028d0997cSElaine Zhang 			prate = priv->gpll_hz;
79128d0997cSElaine Zhang 		else if (sel == SCLK_SFC_SEL_CPLL)
79228d0997cSElaine Zhang 			prate = priv->cpll_hz;
79328d0997cSElaine Zhang 		else
79428d0997cSElaine Zhang 			prate = OSC_HZ;
79528d0997cSElaine Zhang 		return DIV_TO_RATE(prate, div);
796d2b507bbSElaine Zhang 	case DCLK_DECOM:
797d2b507bbSElaine Zhang 		con = readl(&cru->clksel_con[62]);
798d2b507bbSElaine Zhang 		div = (con & DCLK_DECOM_DIV_MASK) >> DCLK_DECOM_DIV_SHIFT;
799d2b507bbSElaine Zhang 		sel = (con & DCLK_DECOM_SEL_MASK) >>
800d2b507bbSElaine Zhang 		      DCLK_DECOM_SEL_SHIFT;
801d2b507bbSElaine Zhang 		if (sel == DCLK_DECOM_SEL_SPLL)
802d2b507bbSElaine Zhang 			prate = 702 * MHz;
803d2b507bbSElaine Zhang 		else
804d2b507bbSElaine Zhang 			prate = priv->gpll_hz;
805d2b507bbSElaine Zhang 		return DIV_TO_RATE(prate, div);
80628d0997cSElaine Zhang 	default:
80728d0997cSElaine Zhang 		return -ENOENT;
80828d0997cSElaine Zhang 	}
80928d0997cSElaine Zhang }
81028d0997cSElaine Zhang 
rk3588_mmc_set_clk(struct rk3588_clk_priv * priv,ulong clk_id,ulong rate)81128d0997cSElaine Zhang static ulong rk3588_mmc_set_clk(struct rk3588_clk_priv *priv,
81228d0997cSElaine Zhang 				ulong clk_id, ulong rate)
81328d0997cSElaine Zhang {
81428d0997cSElaine Zhang 	struct rk3588_cru *cru = priv->cru;
81528d0997cSElaine Zhang 	int src_clk, div;
81628d0997cSElaine Zhang 
81728d0997cSElaine Zhang 	switch (clk_id) {
81828d0997cSElaine Zhang 	case CCLK_SRC_SDIO:
81928d0997cSElaine Zhang 	case CCLK_EMMC:
82028d0997cSElaine Zhang 	case SCLK_SFC:
82128d0997cSElaine Zhang 		if (!(OSC_HZ % rate)) {
82228d0997cSElaine Zhang 			src_clk = SCLK_SFC_SEL_24M;
82328d0997cSElaine Zhang 			div = DIV_ROUND_UP(OSC_HZ, rate);
82428d0997cSElaine Zhang 		} else if (!(priv->cpll_hz % rate)) {
82528d0997cSElaine Zhang 			src_clk = SCLK_SFC_SEL_CPLL;
82628d0997cSElaine Zhang 			div = DIV_ROUND_UP(priv->cpll_hz, rate);
82728d0997cSElaine Zhang 		} else {
82828d0997cSElaine Zhang 			src_clk = SCLK_SFC_SEL_GPLL;
82928d0997cSElaine Zhang 			div = DIV_ROUND_UP(priv->gpll_hz, rate);
83028d0997cSElaine Zhang 		}
83128d0997cSElaine Zhang 		break;
83228d0997cSElaine Zhang 	case BCLK_EMMC:
83328d0997cSElaine Zhang 		if (!(priv->cpll_hz % rate)) {
83428d0997cSElaine Zhang 			src_clk = CCLK_EMMC_SEL_CPLL;
83528d0997cSElaine Zhang 			div = DIV_ROUND_UP(priv->cpll_hz, rate);
83628d0997cSElaine Zhang 		} else {
83728d0997cSElaine Zhang 			src_clk = CCLK_EMMC_SEL_GPLL;
83828d0997cSElaine Zhang 			div = DIV_ROUND_UP(priv->gpll_hz, rate);
83928d0997cSElaine Zhang 		}
84028d0997cSElaine Zhang 		break;
841d2b507bbSElaine Zhang 	case DCLK_DECOM:
842d2b507bbSElaine Zhang 		if (!(702 * MHz % rate)) {
843d2b507bbSElaine Zhang 			src_clk = DCLK_DECOM_SEL_SPLL;
844d2b507bbSElaine Zhang 			div = DIV_ROUND_UP(702 * MHz, rate);
845d2b507bbSElaine Zhang 		} else {
846d2b507bbSElaine Zhang 			src_clk = DCLK_DECOM_SEL_GPLL;
847d2b507bbSElaine Zhang 			div = DIV_ROUND_UP(priv->gpll_hz, rate);
848d2b507bbSElaine Zhang 		}
849d2b507bbSElaine Zhang 		break;
85028d0997cSElaine Zhang 	default:
85128d0997cSElaine Zhang 		return -ENOENT;
85228d0997cSElaine Zhang 	}
85328d0997cSElaine Zhang 
85428d0997cSElaine Zhang 	switch (clk_id) {
85528d0997cSElaine Zhang 	case CCLK_SRC_SDIO:
85628d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[172],
85728d0997cSElaine Zhang 			     CCLK_SDIO_SRC_SEL_MASK |
85828d0997cSElaine Zhang 			     CCLK_SDIO_SRC_DIV_MASK,
85928d0997cSElaine Zhang 			     (src_clk << CCLK_SDIO_SRC_SEL_SHIFT) |
86028d0997cSElaine Zhang 			     (div - 1) << CCLK_SDIO_SRC_DIV_SHIFT);
86128d0997cSElaine Zhang 		break;
86228d0997cSElaine Zhang 	case CCLK_EMMC:
86328d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[77],
86428d0997cSElaine Zhang 			     CCLK_EMMC_SEL_MASK |
86528d0997cSElaine Zhang 			     CCLK_EMMC_DIV_MASK,
86628d0997cSElaine Zhang 			     (src_clk << CCLK_EMMC_SEL_SHIFT) |
86728d0997cSElaine Zhang 			     (div - 1) << CCLK_EMMC_DIV_SHIFT);
86828d0997cSElaine Zhang 		break;
86928d0997cSElaine Zhang 	case BCLK_EMMC:
87028d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[78],
87128d0997cSElaine Zhang 			     BCLK_EMMC_DIV_MASK |
87228d0997cSElaine Zhang 			     BCLK_EMMC_SEL_MASK,
87328d0997cSElaine Zhang 			     (src_clk << BCLK_EMMC_SEL_SHIFT) |
87428d0997cSElaine Zhang 			     (div - 1) << BCLK_EMMC_DIV_SHIFT);
87528d0997cSElaine Zhang 		break;
87628d0997cSElaine Zhang 	case SCLK_SFC:
87728d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[78],
87828d0997cSElaine Zhang 			     SCLK_SFC_DIV_MASK |
87928d0997cSElaine Zhang 			     SCLK_SFC_SEL_MASK,
88028d0997cSElaine Zhang 			     (src_clk << SCLK_SFC_SEL_SHIFT) |
88128d0997cSElaine Zhang 			     (div - 1) << SCLK_SFC_DIV_SHIFT);
88228d0997cSElaine Zhang 		break;
883d2b507bbSElaine Zhang 	case DCLK_DECOM:
884d2b507bbSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[62],
885d2b507bbSElaine Zhang 			     DCLK_DECOM_DIV_MASK |
886d2b507bbSElaine Zhang 			     DCLK_DECOM_SEL_MASK,
887d2b507bbSElaine Zhang 			     (src_clk << DCLK_DECOM_SEL_SHIFT) |
888d2b507bbSElaine Zhang 			     (div - 1) << DCLK_DECOM_DIV_SHIFT);
889d2b507bbSElaine Zhang 		break;
89028d0997cSElaine Zhang 	default:
89128d0997cSElaine Zhang 		return -ENOENT;
89228d0997cSElaine Zhang 	}
89328d0997cSElaine Zhang 
89428d0997cSElaine Zhang 	return rk3588_mmc_get_clk(priv, clk_id);
89528d0997cSElaine Zhang }
89628d0997cSElaine Zhang 
89728d0997cSElaine Zhang #ifndef CONFIG_SPL_BUILD
rk3588_aux16m_get_clk(struct rk3588_clk_priv * priv,ulong clk_id)898b6d6b016SZhang Yubing static ulong rk3588_aux16m_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
899b6d6b016SZhang Yubing {
900b6d6b016SZhang Yubing 	struct rk3588_cru *cru = priv->cru;
901b6d6b016SZhang Yubing 	u32 div, con, parent;
902b6d6b016SZhang Yubing 
903b6d6b016SZhang Yubing 	parent = priv->gpll_hz;
904b6d6b016SZhang Yubing 	con = readl(&cru->clksel_con[117]);
905b6d6b016SZhang Yubing 
906b6d6b016SZhang Yubing 	switch (clk_id) {
907b6d6b016SZhang Yubing 	case CLK_AUX16M_0:
908b6d6b016SZhang Yubing 		div = (con & CLK_AUX16MHZ_0_DIV_MASK) >> CLK_AUX16MHZ_0_DIV_SHIFT;
909b6d6b016SZhang Yubing 		return DIV_TO_RATE(parent, div);
910b6d6b016SZhang Yubing 	case CLK_AUX16M_1:
911b6d6b016SZhang Yubing 		div = (con & CLK_AUX16MHZ_1_DIV_MASK) >> CLK_AUX16MHZ_1_DIV_SHIFT;
912b6d6b016SZhang Yubing 		return DIV_TO_RATE(parent, div);
913b6d6b016SZhang Yubing 	default:
914b6d6b016SZhang Yubing 		return -ENOENT;
915b6d6b016SZhang Yubing 	}
916b6d6b016SZhang Yubing }
917b6d6b016SZhang Yubing 
rk3588_aux16m_set_clk(struct rk3588_clk_priv * priv,ulong clk_id,ulong rate)918b6d6b016SZhang Yubing static ulong rk3588_aux16m_set_clk(struct rk3588_clk_priv *priv,
919b6d6b016SZhang Yubing 				   ulong clk_id, ulong rate)
920b6d6b016SZhang Yubing {
921b6d6b016SZhang Yubing 	struct rk3588_cru *cru = priv->cru;
922b6d6b016SZhang Yubing 	u32 div;
923b6d6b016SZhang Yubing 
924b6d6b016SZhang Yubing 	if (!priv->gpll_hz) {
925b6d6b016SZhang Yubing 		printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
926b6d6b016SZhang Yubing 		return -ENOENT;
927b6d6b016SZhang Yubing 	}
928b6d6b016SZhang Yubing 
929b6d6b016SZhang Yubing 	div = DIV_ROUND_UP(priv->gpll_hz, rate);
930b6d6b016SZhang Yubing 
931b6d6b016SZhang Yubing 	switch (clk_id) {
932b6d6b016SZhang Yubing 	case CLK_AUX16M_0:
933b6d6b016SZhang Yubing 		rk_clrsetreg(&cru->clksel_con[117], CLK_AUX16MHZ_0_DIV_MASK,
934b6d6b016SZhang Yubing 			     (div - 1) << CLK_AUX16MHZ_0_DIV_SHIFT);
935b6d6b016SZhang Yubing 		break;
936b6d6b016SZhang Yubing 	case CLK_AUX16M_1:
937b6d6b016SZhang Yubing 		rk_clrsetreg(&cru->clksel_con[117], CLK_AUX16MHZ_1_DIV_MASK,
938b6d6b016SZhang Yubing 			     (div - 1) << CLK_AUX16MHZ_1_DIV_SHIFT);
939b6d6b016SZhang Yubing 		break;
940b6d6b016SZhang Yubing 	default:
941b6d6b016SZhang Yubing 		return -ENOENT;
942b6d6b016SZhang Yubing 	}
943b6d6b016SZhang Yubing 
944b6d6b016SZhang Yubing 	return rk3588_aux16m_get_clk(priv, clk_id);
945b6d6b016SZhang Yubing }
946b6d6b016SZhang Yubing 
rk3588_aclk_vop_get_clk(struct rk3588_clk_priv * priv,ulong clk_id)94728d0997cSElaine Zhang static ulong rk3588_aclk_vop_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
94828d0997cSElaine Zhang {
94928d0997cSElaine Zhang 	struct rk3588_cru *cru = priv->cru;
95028d0997cSElaine Zhang 	u32 div, sel, con, parent;
95128d0997cSElaine Zhang 
95228d0997cSElaine Zhang 	switch (clk_id) {
95328d0997cSElaine Zhang 	case ACLK_VOP_ROOT:
954477e465dSElaine Zhang 	case ACLK_VOP:
95528d0997cSElaine Zhang 		con = readl(&cru->clksel_con[110]);
95628d0997cSElaine Zhang 		div = (con & ACLK_VOP_ROOT_DIV_MASK) >> ACLK_VOP_ROOT_DIV_SHIFT;
95728d0997cSElaine Zhang 		sel = (con & ACLK_VOP_ROOT_SEL_MASK) >> ACLK_VOP_ROOT_SEL_SHIFT;
95828d0997cSElaine Zhang 		if (sel == ACLK_VOP_ROOT_SEL_GPLL)
95928d0997cSElaine Zhang 			parent = priv->gpll_hz;
96028d0997cSElaine Zhang 		else if (sel == ACLK_VOP_ROOT_SEL_CPLL)
96128d0997cSElaine Zhang 			parent = priv->cpll_hz;
96228d0997cSElaine Zhang 		else if (sel == ACLK_VOP_ROOT_SEL_AUPLL)
96328d0997cSElaine Zhang 			parent = priv->aupll_hz;
96428d0997cSElaine Zhang 		else if (sel == ACLK_VOP_ROOT_SEL_NPLL)
96528d0997cSElaine Zhang 			parent = priv->npll_hz;
96628d0997cSElaine Zhang 		else
96728d0997cSElaine Zhang 			parent = 702 * MHz;
96828d0997cSElaine Zhang 		return DIV_TO_RATE(parent, div);
96928d0997cSElaine Zhang 	case ACLK_VOP_LOW_ROOT:
97028d0997cSElaine Zhang 		con = readl(&cru->clksel_con[110]);
97128d0997cSElaine Zhang 		sel = (con & ACLK_VOP_LOW_ROOT_SEL_MASK) >>
97228d0997cSElaine Zhang 		      ACLK_VOP_LOW_ROOT_SEL_SHIFT;
97328d0997cSElaine Zhang 		if (sel == ACLK_VOP_LOW_ROOT_SEL_400M)
97428d0997cSElaine Zhang 			return 396 * MHz;
97528d0997cSElaine Zhang 		else if (sel == ACLK_VOP_LOW_ROOT_SEL_200M)
97628d0997cSElaine Zhang 			return 200 * MHz;
97728d0997cSElaine Zhang 		else if (sel == ACLK_VOP_LOW_ROOT_SEL_100M)
97828d0997cSElaine Zhang 			return 100 * MHz;
97928d0997cSElaine Zhang 		else
98028d0997cSElaine Zhang 			return OSC_HZ;
98128d0997cSElaine Zhang 	case HCLK_VOP_ROOT:
98228d0997cSElaine Zhang 		con = readl(&cru->clksel_con[110]);
98328d0997cSElaine Zhang 		sel = (con & HCLK_VOP_ROOT_SEL_MASK) >> HCLK_VOP_ROOT_SEL_SHIFT;
98428d0997cSElaine Zhang 		if (sel == HCLK_VOP_ROOT_SEL_200M)
98528d0997cSElaine Zhang 			return 200 * MHz;
98628d0997cSElaine Zhang 		else if (sel == HCLK_VOP_ROOT_SEL_100M)
98728d0997cSElaine Zhang 			return 100 * MHz;
98828d0997cSElaine Zhang 		else if (sel == HCLK_VOP_ROOT_SEL_50M)
98928d0997cSElaine Zhang 			return 50 * MHz;
99028d0997cSElaine Zhang 		else
99128d0997cSElaine Zhang 			return OSC_HZ;
99228d0997cSElaine Zhang 	default:
99328d0997cSElaine Zhang 		return -ENOENT;
99428d0997cSElaine Zhang 	}
99528d0997cSElaine Zhang }
99628d0997cSElaine Zhang 
rk3588_aclk_vop_set_clk(struct rk3588_clk_priv * priv,ulong clk_id,ulong rate)99728d0997cSElaine Zhang static ulong rk3588_aclk_vop_set_clk(struct rk3588_clk_priv *priv,
99828d0997cSElaine Zhang 				     ulong clk_id, ulong rate)
99928d0997cSElaine Zhang {
100028d0997cSElaine Zhang 	struct rk3588_cru *cru = priv->cru;
100128d0997cSElaine Zhang 	int src_clk, div;
100228d0997cSElaine Zhang 
100328d0997cSElaine Zhang 	switch (clk_id) {
100428d0997cSElaine Zhang 	case ACLK_VOP_ROOT:
1005477e465dSElaine Zhang 	case ACLK_VOP:
1006477e465dSElaine Zhang 		if (rate >= 850 * MHz) {
1007477e465dSElaine Zhang 			src_clk = ACLK_VOP_ROOT_SEL_NPLL;
1008477e465dSElaine Zhang 			div = 1;
1009477e465dSElaine Zhang 		} else if (rate >= 750 * MHz) {
1010477e465dSElaine Zhang 			src_clk = ACLK_VOP_ROOT_SEL_CPLL;
1011477e465dSElaine Zhang 			div = 2;
1012477e465dSElaine Zhang 		} else if (rate >= 700 * MHz) {
1013477e465dSElaine Zhang 			src_clk = ACLK_VOP_ROOT_SEL_SPLL;
1014477e465dSElaine Zhang 			div = 1;
1015477e465dSElaine Zhang 		} else if (!(priv->cpll_hz % rate)) {
101628d0997cSElaine Zhang 			src_clk = ACLK_VOP_ROOT_SEL_CPLL;
101728d0997cSElaine Zhang 			div = DIV_ROUND_UP(priv->cpll_hz, rate);
101828d0997cSElaine Zhang 		} else {
101928d0997cSElaine Zhang 			src_clk = ACLK_VOP_ROOT_SEL_GPLL;
102028d0997cSElaine Zhang 			div = DIV_ROUND_UP(priv->gpll_hz, rate);
102128d0997cSElaine Zhang 		}
102228d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[110],
102328d0997cSElaine Zhang 			     ACLK_VOP_ROOT_DIV_MASK |
102428d0997cSElaine Zhang 			     ACLK_VOP_ROOT_SEL_MASK,
102528d0997cSElaine Zhang 			     (src_clk << ACLK_VOP_ROOT_SEL_SHIFT) |
102628d0997cSElaine Zhang 			     (div - 1) << ACLK_VOP_ROOT_DIV_SHIFT);
102728d0997cSElaine Zhang 		break;
102828d0997cSElaine Zhang 	case ACLK_VOP_LOW_ROOT:
102928d0997cSElaine Zhang 		if (rate == 400 * MHz || rate == 396 * MHz)
103028d0997cSElaine Zhang 			src_clk = ACLK_VOP_LOW_ROOT_SEL_400M;
103128d0997cSElaine Zhang 		else if (rate == 200 * MHz)
103228d0997cSElaine Zhang 			src_clk = ACLK_VOP_LOW_ROOT_SEL_200M;
103328d0997cSElaine Zhang 		else if (rate == 100 * MHz)
103428d0997cSElaine Zhang 			src_clk = ACLK_VOP_LOW_ROOT_SEL_100M;
103528d0997cSElaine Zhang 		else
103628d0997cSElaine Zhang 			src_clk = ACLK_VOP_LOW_ROOT_SEL_24M;
103728d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[110],
103828d0997cSElaine Zhang 			     ACLK_VOP_LOW_ROOT_SEL_MASK,
103928d0997cSElaine Zhang 			     src_clk << ACLK_VOP_LOW_ROOT_SEL_SHIFT);
104028d0997cSElaine Zhang 		break;
104128d0997cSElaine Zhang 	case HCLK_VOP_ROOT:
104228d0997cSElaine Zhang 		if (rate == 200 * MHz)
104328d0997cSElaine Zhang 			src_clk = HCLK_VOP_ROOT_SEL_200M;
104428d0997cSElaine Zhang 		else if (rate == 100 * MHz)
104528d0997cSElaine Zhang 			src_clk = HCLK_VOP_ROOT_SEL_100M;
104628d0997cSElaine Zhang 		else if (rate == 50 * MHz)
104728d0997cSElaine Zhang 			src_clk = HCLK_VOP_ROOT_SEL_50M;
104828d0997cSElaine Zhang 		else
104928d0997cSElaine Zhang 			src_clk = HCLK_VOP_ROOT_SEL_24M;
105028d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[110],
105128d0997cSElaine Zhang 			     HCLK_VOP_ROOT_SEL_MASK,
105228d0997cSElaine Zhang 			     src_clk << HCLK_VOP_ROOT_SEL_SHIFT);
105328d0997cSElaine Zhang 		break;
105428d0997cSElaine Zhang 	default:
105528d0997cSElaine Zhang 		return -ENOENT;
105628d0997cSElaine Zhang 	}
105728d0997cSElaine Zhang 
105828d0997cSElaine Zhang 	return rk3588_aclk_vop_get_clk(priv, clk_id);
105928d0997cSElaine Zhang }
106028d0997cSElaine Zhang 
rk3588_dclk_vop_get_clk(struct rk3588_clk_priv * priv,ulong clk_id)106128d0997cSElaine Zhang static ulong rk3588_dclk_vop_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
106228d0997cSElaine Zhang {
106328d0997cSElaine Zhang 	struct rk3588_cru *cru = priv->cru;
106428d0997cSElaine Zhang 	u32 div, sel, con, parent;
106528d0997cSElaine Zhang 
106628d0997cSElaine Zhang 	switch (clk_id) {
106728d0997cSElaine Zhang 	case DCLK_VOP0:
106828d0997cSElaine Zhang 	case DCLK_VOP0_SRC:
106928d0997cSElaine Zhang 		con = readl(&cru->clksel_con[111]);
107028d0997cSElaine Zhang 		div = (con & DCLK0_VOP_SRC_DIV_MASK) >> DCLK0_VOP_SRC_DIV_SHIFT;
107128d0997cSElaine Zhang 		sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
107228d0997cSElaine Zhang 		break;
107328d0997cSElaine Zhang 	case DCLK_VOP1:
107428d0997cSElaine Zhang 	case DCLK_VOP1_SRC:
107528d0997cSElaine Zhang 		con = readl(&cru->clksel_con[111]);
107628d0997cSElaine Zhang 		div = (con & DCLK1_VOP_SRC_DIV_MASK) >> DCLK1_VOP_SRC_DIV_SHIFT;
107728d0997cSElaine Zhang 		sel = (con & DCLK1_VOP_SRC_SEL_MASK) >> DCLK1_VOP_SRC_SEL_SHIFT;
107828d0997cSElaine Zhang 		break;
107928d0997cSElaine Zhang 	case DCLK_VOP2:
108028d0997cSElaine Zhang 	case DCLK_VOP2_SRC:
108128d0997cSElaine Zhang 		con = readl(&cru->clksel_con[112]);
108228d0997cSElaine Zhang 		div = (con & DCLK2_VOP_SRC_DIV_MASK) >> DCLK2_VOP_SRC_DIV_SHIFT;
108328d0997cSElaine Zhang 		sel = (con & DCLK2_VOP_SRC_SEL_MASK) >> DCLK2_VOP_SRC_SEL_SHIFT;
108428d0997cSElaine Zhang 		break;
108528d0997cSElaine Zhang 	case DCLK_VOP3:
108628d0997cSElaine Zhang 		con = readl(&cru->clksel_con[113]);
108728d0997cSElaine Zhang 		div = (con & DCLK3_VOP_SRC_DIV_MASK) >> DCLK3_VOP_SRC_DIV_SHIFT;
108828d0997cSElaine Zhang 		sel = (con & DCLK3_VOP_SRC_SEL_MASK) >> DCLK3_VOP_SRC_SEL_SHIFT;
108928d0997cSElaine Zhang 		break;
109028d0997cSElaine Zhang 	default:
109128d0997cSElaine Zhang 		return -ENOENT;
109228d0997cSElaine Zhang 	}
109328d0997cSElaine Zhang 
109428d0997cSElaine Zhang 	if (sel == DCLK_VOP_SRC_SEL_AUPLL)
109528d0997cSElaine Zhang 		parent = priv->aupll_hz;
109628d0997cSElaine Zhang 	else if (sel == DCLK_VOP_SRC_SEL_V0PLL)
109728d0997cSElaine Zhang 		parent = rockchip_pll_get_rate(&rk3588_pll_clks[V0PLL],
109828d0997cSElaine Zhang 					       priv->cru, V0PLL);
109928d0997cSElaine Zhang 	else if (sel == DCLK_VOP_SRC_SEL_GPLL)
110028d0997cSElaine Zhang 		parent = priv->gpll_hz;
110128d0997cSElaine Zhang 	else
11023df2ec46SJianqun Xu 		parent = priv->cpll_hz;
110328d0997cSElaine Zhang 
110428d0997cSElaine Zhang 	return DIV_TO_RATE(parent, div);
110528d0997cSElaine Zhang }
110628d0997cSElaine Zhang 
1107e583fa2aSElaine Zhang #define RK3588_VOP_PLL_LIMIT_FREQ 594000000
110828d0997cSElaine Zhang 
rk3588_dclk_vop_set_clk(struct rk3588_clk_priv * priv,ulong clk_id,ulong rate)110928d0997cSElaine Zhang static ulong rk3588_dclk_vop_set_clk(struct rk3588_clk_priv *priv,
111028d0997cSElaine Zhang 				     ulong clk_id, ulong rate)
111128d0997cSElaine Zhang {
111228d0997cSElaine Zhang 	struct rk3588_cru *cru = priv->cru;
111328d0997cSElaine Zhang 	ulong pll_rate, now, best_rate = 0;
111428d0997cSElaine Zhang 	u32 i, conid, con, sel, div, best_div = 0, best_sel = 0;
111528d0997cSElaine Zhang 	u32 mask, div_shift, sel_shift;
111628d0997cSElaine Zhang 
111728d0997cSElaine Zhang 	switch (clk_id) {
111828d0997cSElaine Zhang 	case DCLK_VOP0:
111928d0997cSElaine Zhang 	case DCLK_VOP0_SRC:
112028d0997cSElaine Zhang 		conid = 111;
112128d0997cSElaine Zhang 		con = readl(&cru->clksel_con[111]);
112228d0997cSElaine Zhang 		sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
112328d0997cSElaine Zhang 		mask = DCLK0_VOP_SRC_SEL_MASK | DCLK0_VOP_SRC_DIV_MASK;
112428d0997cSElaine Zhang 		div_shift = DCLK0_VOP_SRC_DIV_SHIFT;
112528d0997cSElaine Zhang 		sel_shift = DCLK0_VOP_SRC_SEL_SHIFT;
112628d0997cSElaine Zhang 		break;
112728d0997cSElaine Zhang 	case DCLK_VOP1:
112828d0997cSElaine Zhang 	case DCLK_VOP1_SRC:
112928d0997cSElaine Zhang 		conid = 111;
113028d0997cSElaine Zhang 		con = readl(&cru->clksel_con[111]);
113128d0997cSElaine Zhang 		sel = (con & DCLK1_VOP_SRC_SEL_MASK) >> DCLK1_VOP_SRC_SEL_SHIFT;
113228d0997cSElaine Zhang 		mask = DCLK1_VOP_SRC_SEL_MASK | DCLK1_VOP_SRC_DIV_MASK;
113328d0997cSElaine Zhang 		div_shift = DCLK1_VOP_SRC_DIV_SHIFT;
113428d0997cSElaine Zhang 		sel_shift = DCLK1_VOP_SRC_SEL_SHIFT;
113528d0997cSElaine Zhang 		break;
113628d0997cSElaine Zhang 	case DCLK_VOP2:
113728d0997cSElaine Zhang 	case DCLK_VOP2_SRC:
113828d0997cSElaine Zhang 		conid = 112;
113928d0997cSElaine Zhang 		con = readl(&cru->clksel_con[112]);
114028d0997cSElaine Zhang 		sel = (con & DCLK2_VOP_SRC_SEL_MASK) >> DCLK2_VOP_SRC_SEL_SHIFT;
114128d0997cSElaine Zhang 		mask = DCLK2_VOP_SRC_SEL_MASK | DCLK2_VOP_SRC_DIV_MASK;
114228d0997cSElaine Zhang 		div_shift = DCLK2_VOP_SRC_DIV_SHIFT;
1143fd928c4dSWyon Bi 		sel_shift = DCLK2_VOP_SRC_SEL_SHIFT;
114428d0997cSElaine Zhang 		break;
114528d0997cSElaine Zhang 	case DCLK_VOP3:
114628d0997cSElaine Zhang 		conid = 113;
114728d0997cSElaine Zhang 		con = readl(&cru->clksel_con[113]);
114828d0997cSElaine Zhang 		sel = (con & DCLK3_VOP_SRC_SEL_MASK) >> DCLK3_VOP_SRC_SEL_SHIFT;
1149d6a0e942SElaine Zhang 		mask = DCLK3_VOP_SRC_SEL_MASK | DCLK3_VOP_SRC_DIV_MASK;
1150d6a0e942SElaine Zhang 		div_shift = DCLK3_VOP_SRC_DIV_SHIFT;
1151d6a0e942SElaine Zhang 		sel_shift = DCLK3_VOP_SRC_SEL_SHIFT;
115228d0997cSElaine Zhang 		break;
115328d0997cSElaine Zhang 	default:
115428d0997cSElaine Zhang 		return -ENOENT;
115528d0997cSElaine Zhang 	}
115628d0997cSElaine Zhang 
115728d0997cSElaine Zhang 	if (sel == DCLK_VOP_SRC_SEL_V0PLL) {
11583a215888SWyon Bi 		pll_rate = rockchip_pll_get_rate(&rk3588_pll_clks[V0PLL],
11593a215888SWyon Bi 						 priv->cru, V0PLL);
11603a215888SWyon Bi 		if (pll_rate >= RK3588_VOP_PLL_LIMIT_FREQ && pll_rate % rate == 0) {
11613a215888SWyon Bi 			div = DIV_ROUND_UP(pll_rate, rate);
11623a215888SWyon Bi 			rk_clrsetreg(&cru->clksel_con[conid],
11633a215888SWyon Bi 				     mask,
11643a215888SWyon Bi 				     DCLK_VOP_SRC_SEL_V0PLL << sel_shift |
11653a215888SWyon Bi 				     ((div - 1) << div_shift));
11663a215888SWyon Bi 		} else {
116728d0997cSElaine Zhang 			div = DIV_ROUND_UP(RK3588_VOP_PLL_LIMIT_FREQ, rate);
1168e583fa2aSElaine Zhang 			if (div % 2)
1169e583fa2aSElaine Zhang 				div = div + 1;
117028d0997cSElaine Zhang 			rk_clrsetreg(&cru->clksel_con[conid],
117128d0997cSElaine Zhang 				     mask,
1172fd928c4dSWyon Bi 				     DCLK_VOP_SRC_SEL_V0PLL << sel_shift |
117328d0997cSElaine Zhang 				     ((div - 1) << div_shift));
117428d0997cSElaine Zhang 			rockchip_pll_set_rate(&rk3588_pll_clks[V0PLL],
117528d0997cSElaine Zhang 					      priv->cru, V0PLL, div * rate);
11763a215888SWyon Bi 		}
117728d0997cSElaine Zhang 	} else {
117828d0997cSElaine Zhang 		for (i = 0; i <= DCLK_VOP_SRC_SEL_AUPLL; i++) {
117928d0997cSElaine Zhang 			switch (i) {
118028d0997cSElaine Zhang 			case DCLK_VOP_SRC_SEL_GPLL:
118128d0997cSElaine Zhang 				pll_rate = priv->gpll_hz;
118228d0997cSElaine Zhang 				break;
118328d0997cSElaine Zhang 			case DCLK_VOP_SRC_SEL_CPLL:
118428d0997cSElaine Zhang 				pll_rate = priv->cpll_hz;
118528d0997cSElaine Zhang 				break;
118628d0997cSElaine Zhang 			case DCLK_VOP_SRC_SEL_AUPLL:
118728d0997cSElaine Zhang 				pll_rate = priv->aupll_hz;
118828d0997cSElaine Zhang 				break;
118990269a17SDamon Ding 			case DCLK_VOP_SRC_SEL_V0PLL:
119090269a17SDamon Ding 				pll_rate = 0;
119190269a17SDamon Ding 				break;
119228d0997cSElaine Zhang 			default:
119328d0997cSElaine Zhang 				printf("do not support this vop pll sel\n");
119428d0997cSElaine Zhang 				return -EINVAL;
119528d0997cSElaine Zhang 			}
119628d0997cSElaine Zhang 
119728d0997cSElaine Zhang 			div = DIV_ROUND_UP(pll_rate, rate);
119828d0997cSElaine Zhang 			if (div > 255)
119928d0997cSElaine Zhang 				continue;
120028d0997cSElaine Zhang 			now = pll_rate / div;
120128d0997cSElaine Zhang 			if (abs(rate - now) < abs(rate - best_rate)) {
120228d0997cSElaine Zhang 				best_rate = now;
120328d0997cSElaine Zhang 				best_div = div;
120428d0997cSElaine Zhang 				best_sel = i;
120528d0997cSElaine Zhang 			}
120628d0997cSElaine Zhang 			debug("p_rate=%lu, best_rate=%lu, div=%u, sel=%u\n",
120728d0997cSElaine Zhang 			      pll_rate, best_rate, best_div, best_sel);
120828d0997cSElaine Zhang 		}
120928d0997cSElaine Zhang 
121028d0997cSElaine Zhang 		if (best_rate) {
121128d0997cSElaine Zhang 			rk_clrsetreg(&cru->clksel_con[conid],
121228d0997cSElaine Zhang 				     mask,
121328d0997cSElaine Zhang 				     best_sel << sel_shift |
121428d0997cSElaine Zhang 				     (best_div - 1) << div_shift);
121528d0997cSElaine Zhang 		} else {
121628d0997cSElaine Zhang 			printf("do not support this vop freq %lu\n", rate);
121728d0997cSElaine Zhang 			return -EINVAL;
121828d0997cSElaine Zhang 		}
121928d0997cSElaine Zhang 	}
122028d0997cSElaine Zhang 	return rk3588_dclk_vop_get_clk(priv, clk_id);
122128d0997cSElaine Zhang }
122228d0997cSElaine Zhang 
rk3588_clk_csihost_get_clk(struct rk3588_clk_priv * priv,ulong clk_id)12230265e00cSElaine Zhang static ulong rk3588_clk_csihost_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
12240265e00cSElaine Zhang {
12250265e00cSElaine Zhang 	struct rk3588_cru *cru = priv->cru;
12260265e00cSElaine Zhang 	u32 div, sel, con, parent;
12270265e00cSElaine Zhang 
12280265e00cSElaine Zhang 	switch (clk_id) {
12290265e00cSElaine Zhang 	case CLK_DSIHOST0:
12300265e00cSElaine Zhang 		con = readl(&cru->clksel_con[114]);
12310265e00cSElaine Zhang 		break;
12320265e00cSElaine Zhang 	case CLK_DSIHOST1:
12330265e00cSElaine Zhang 		con = readl(&cru->clksel_con[115]);
12340265e00cSElaine Zhang 		break;
12350265e00cSElaine Zhang 	default:
12360265e00cSElaine Zhang 		return -ENOENT;
12370265e00cSElaine Zhang 	}
12380265e00cSElaine Zhang 
12390265e00cSElaine Zhang 	div = (con & CLK_DSIHOST_DIV_MASK) >> CLK_DSIHOST_DIV_SHIFT;
12400265e00cSElaine Zhang 	sel = (con & CLK_DSIHOST_SEL_MASK) >> CLK_DSIHOST_SEL_SHIFT;
12410265e00cSElaine Zhang 
12420265e00cSElaine Zhang 	if (sel == CLK_DSIHOST_SEL_GPLL)
12430265e00cSElaine Zhang 		parent = priv->gpll_hz;
12440265e00cSElaine Zhang 	else if (sel == CLK_DSIHOST_SEL_CPLL)
12450265e00cSElaine Zhang 		parent = priv->cpll_hz;
12460265e00cSElaine Zhang 	else if (sel == CLK_DSIHOST_SEL_V0PLL)
12470265e00cSElaine Zhang 		parent = priv->v0pll_hz;
12480265e00cSElaine Zhang 	else
12490265e00cSElaine Zhang 		parent = priv->spll_hz;
12500265e00cSElaine Zhang 
12510265e00cSElaine Zhang 	return DIV_TO_RATE(parent, div);
12520265e00cSElaine Zhang }
12530265e00cSElaine Zhang 
rk3588_gmac_get_clk(struct rk3588_clk_priv * priv,ulong clk_id)125428d0997cSElaine Zhang static ulong rk3588_gmac_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
125528d0997cSElaine Zhang {
125628d0997cSElaine Zhang 	struct rk3588_cru *cru = priv->cru;
125728d0997cSElaine Zhang 	u32 con, div;
125828d0997cSElaine Zhang 
125928d0997cSElaine Zhang 	switch (clk_id) {
126028d0997cSElaine Zhang 	case CLK_GMAC0_PTP_REF:
126128d0997cSElaine Zhang 		con = readl(&cru->clksel_con[81]);
126228d0997cSElaine Zhang 		div = (con & CLK_GMAC0_PTP_DIV_MASK) >> CLK_GMAC0_PTP_DIV_SHIFT;
126328d0997cSElaine Zhang 		return DIV_TO_RATE(priv->cpll_hz, div);
126428d0997cSElaine Zhang 	case CLK_GMAC1_PTP_REF:
126528d0997cSElaine Zhang 		con = readl(&cru->clksel_con[81]);
126628d0997cSElaine Zhang 		div = (con & CLK_GMAC1_PTP_DIV_MASK) >> CLK_GMAC1_PTP_DIV_SHIFT;
126728d0997cSElaine Zhang 		return DIV_TO_RATE(priv->cpll_hz, div);
126828d0997cSElaine Zhang 	case CLK_GMAC_125M:
126928d0997cSElaine Zhang 		con = readl(&cru->clksel_con[83]);
127028d0997cSElaine Zhang 		div = (con & CLK_GMAC_125M_DIV_MASK) >> CLK_GMAC_125M_DIV_SHIFT;
127128d0997cSElaine Zhang 		return DIV_TO_RATE(priv->cpll_hz, div);
127228d0997cSElaine Zhang 	case CLK_GMAC_50M:
127328d0997cSElaine Zhang 		con = readl(&cru->clksel_con[84]);
127428d0997cSElaine Zhang 		div = (con & CLK_GMAC_50M_DIV_MASK) >> CLK_GMAC_50M_DIV_SHIFT;
127528d0997cSElaine Zhang 		return DIV_TO_RATE(priv->cpll_hz, div);
127628d0997cSElaine Zhang 	default:
127728d0997cSElaine Zhang 		return -ENOENT;
127828d0997cSElaine Zhang 	}
127928d0997cSElaine Zhang }
128028d0997cSElaine Zhang 
rk3588_gmac_set_clk(struct rk3588_clk_priv * priv,ulong clk_id,ulong rate)128128d0997cSElaine Zhang static ulong rk3588_gmac_set_clk(struct rk3588_clk_priv *priv,
128228d0997cSElaine Zhang 				 ulong clk_id, ulong rate)
128328d0997cSElaine Zhang {
128428d0997cSElaine Zhang 	struct rk3588_cru *cru = priv->cru;
128528d0997cSElaine Zhang 	int div;
128628d0997cSElaine Zhang 
128728d0997cSElaine Zhang 	div = DIV_ROUND_UP(priv->cpll_hz, rate);
128828d0997cSElaine Zhang 
128928d0997cSElaine Zhang 	switch (clk_id) {
129028d0997cSElaine Zhang 	case CLK_GMAC0_PTP_REF:
129128d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[81],
129228d0997cSElaine Zhang 			     CLK_GMAC0_PTP_DIV_MASK | CLK_GMAC0_PTP_SEL_MASK,
129328d0997cSElaine Zhang 			     CLK_GMAC0_PTP_SEL_CPLL << CLK_GMAC0_PTP_SEL_SHIFT |
129428d0997cSElaine Zhang 			     (div - 1) << CLK_GMAC0_PTP_DIV_SHIFT);
129528d0997cSElaine Zhang 		break;
129628d0997cSElaine Zhang 	case CLK_GMAC1_PTP_REF:
129728d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[81],
129828d0997cSElaine Zhang 			     CLK_GMAC1_PTP_DIV_MASK | CLK_GMAC1_PTP_SEL_MASK,
129928d0997cSElaine Zhang 			     CLK_GMAC1_PTP_SEL_CPLL << CLK_GMAC1_PTP_SEL_SHIFT |
130028d0997cSElaine Zhang 			     (div - 1) << CLK_GMAC1_PTP_DIV_SHIFT);
130128d0997cSElaine Zhang 		break;
1302b3fe4c57SDavid Wu 
130328d0997cSElaine Zhang 	case CLK_GMAC_125M:
130428d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[83],
130528d0997cSElaine Zhang 			     CLK_GMAC_125M_DIV_MASK | CLK_GMAC_125M_SEL_MASK,
130628d0997cSElaine Zhang 			     CLK_GMAC_125M_SEL_CPLL << CLK_GMAC_125M_SEL_SHIFT |
130728d0997cSElaine Zhang 			     (div - 1) << CLK_GMAC_125M_DIV_SHIFT);
130828d0997cSElaine Zhang 		break;
130928d0997cSElaine Zhang 	case CLK_GMAC_50M:
131028d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[84],
131128d0997cSElaine Zhang 			     CLK_GMAC_50M_DIV_MASK | CLK_GMAC_50M_SEL_MASK,
131228d0997cSElaine Zhang 			     CLK_GMAC_50M_SEL_CPLL << CLK_GMAC_50M_SEL_SHIFT |
131328d0997cSElaine Zhang 			     (div - 1) << CLK_GMAC_50M_DIV_SHIFT);
131428d0997cSElaine Zhang 		break;
131528d0997cSElaine Zhang 	default:
131628d0997cSElaine Zhang 		return -ENOENT;
131728d0997cSElaine Zhang 	}
131828d0997cSElaine Zhang 
131928d0997cSElaine Zhang 	return rk3588_gmac_get_clk(priv, clk_id);
132028d0997cSElaine Zhang }
132128d0997cSElaine Zhang 
rk3588_uart_get_rate(struct rk3588_clk_priv * priv,ulong clk_id)132228d0997cSElaine Zhang static ulong rk3588_uart_get_rate(struct rk3588_clk_priv *priv, ulong clk_id)
132328d0997cSElaine Zhang {
132428d0997cSElaine Zhang 	struct rk3588_cru *cru = priv->cru;
132528d0997cSElaine Zhang 	u32 reg, con, fracdiv, div, src, p_src, p_rate;
132628d0997cSElaine Zhang 	unsigned long m, n;
132728d0997cSElaine Zhang 
132828d0997cSElaine Zhang 	switch (clk_id) {
132928d0997cSElaine Zhang 	case SCLK_UART1:
133028d0997cSElaine Zhang 		reg = 41;
133128d0997cSElaine Zhang 		break;
133228d0997cSElaine Zhang 	case SCLK_UART2:
133328d0997cSElaine Zhang 		reg = 43;
133428d0997cSElaine Zhang 		break;
133528d0997cSElaine Zhang 	case SCLK_UART3:
133628d0997cSElaine Zhang 		reg = 45;
133728d0997cSElaine Zhang 		break;
133828d0997cSElaine Zhang 	case SCLK_UART4:
133928d0997cSElaine Zhang 		reg = 47;
134028d0997cSElaine Zhang 		break;
134128d0997cSElaine Zhang 	case SCLK_UART5:
134228d0997cSElaine Zhang 		reg = 49;
134328d0997cSElaine Zhang 		break;
134428d0997cSElaine Zhang 	case SCLK_UART6:
134528d0997cSElaine Zhang 		reg = 51;
134628d0997cSElaine Zhang 		break;
134728d0997cSElaine Zhang 	case SCLK_UART7:
134828d0997cSElaine Zhang 		reg = 53;
134928d0997cSElaine Zhang 		break;
135028d0997cSElaine Zhang 	case SCLK_UART8:
135128d0997cSElaine Zhang 		reg = 55;
135228d0997cSElaine Zhang 		break;
135328d0997cSElaine Zhang 	case SCLK_UART9:
135428d0997cSElaine Zhang 		reg = 57;
135528d0997cSElaine Zhang 		break;
135628d0997cSElaine Zhang 	default:
135728d0997cSElaine Zhang 		return -ENOENT;
135828d0997cSElaine Zhang 	}
135928d0997cSElaine Zhang 	con = readl(&cru->clksel_con[reg + 2]);
136028d0997cSElaine Zhang 	src = (con & CLK_UART_SEL_MASK) >> CLK_UART_SEL_SHIFT;
136128d0997cSElaine Zhang 	con = readl(&cru->clksel_con[reg]);
136228d0997cSElaine Zhang 	div = (con & CLK_UART_SRC_DIV_MASK) >> CLK_UART_SRC_DIV_SHIFT;
136328d0997cSElaine Zhang 	p_src = (con & CLK_UART_SRC_SEL_MASK) >> CLK_UART_SRC_SEL_SHIFT;
136428d0997cSElaine Zhang 	if (p_src == CLK_UART_SRC_SEL_GPLL)
136528d0997cSElaine Zhang 		p_rate = priv->gpll_hz;
136628d0997cSElaine Zhang 	else
136728d0997cSElaine Zhang 		p_rate = priv->cpll_hz;
136828d0997cSElaine Zhang 
136928d0997cSElaine Zhang 	if (src == CLK_UART_SEL_SRC) {
137028d0997cSElaine Zhang 		return DIV_TO_RATE(p_rate, div);
137128d0997cSElaine Zhang 	} else if (src == CLK_UART_SEL_FRAC) {
137228d0997cSElaine Zhang 		fracdiv = readl(&cru->clksel_con[reg + 1]);
137328d0997cSElaine Zhang 		n = fracdiv & CLK_UART_FRAC_NUMERATOR_MASK;
137428d0997cSElaine Zhang 		n >>= CLK_UART_FRAC_NUMERATOR_SHIFT;
137528d0997cSElaine Zhang 		m = fracdiv & CLK_UART_FRAC_DENOMINATOR_MASK;
137628d0997cSElaine Zhang 		m >>= CLK_UART_FRAC_DENOMINATOR_SHIFT;
137728d0997cSElaine Zhang 		return DIV_TO_RATE(p_rate, div) * n / m;
137828d0997cSElaine Zhang 	} else {
137928d0997cSElaine Zhang 		return OSC_HZ;
138028d0997cSElaine Zhang 	}
138128d0997cSElaine Zhang }
138228d0997cSElaine Zhang 
rk3588_uart_set_rate(struct rk3588_clk_priv * priv,ulong clk_id,ulong rate)138328d0997cSElaine Zhang static ulong rk3588_uart_set_rate(struct rk3588_clk_priv *priv,
138428d0997cSElaine Zhang 				  ulong clk_id, ulong rate)
138528d0997cSElaine Zhang {
138628d0997cSElaine Zhang 	struct rk3588_cru *cru = priv->cru;
138728d0997cSElaine Zhang 	u32 reg, clk_src, uart_src, div;
138828d0997cSElaine Zhang 	unsigned long m = 0, n = 0, val;
138928d0997cSElaine Zhang 
139028d0997cSElaine Zhang 	if (priv->gpll_hz % rate == 0) {
139128d0997cSElaine Zhang 		clk_src = CLK_UART_SRC_SEL_GPLL;
139228d0997cSElaine Zhang 		uart_src = CLK_UART_SEL_SRC;
139328d0997cSElaine Zhang 		div = DIV_ROUND_UP(priv->gpll_hz, rate);
139428d0997cSElaine Zhang 	} else if (priv->cpll_hz % rate == 0) {
139528d0997cSElaine Zhang 		clk_src = CLK_UART_SRC_SEL_CPLL;
139628d0997cSElaine Zhang 		uart_src = CLK_UART_SEL_SRC;
139728d0997cSElaine Zhang 		div = DIV_ROUND_UP(priv->gpll_hz, rate);
139828d0997cSElaine Zhang 	} else if (rate == OSC_HZ) {
139928d0997cSElaine Zhang 		clk_src = CLK_UART_SRC_SEL_GPLL;
140028d0997cSElaine Zhang 		uart_src = CLK_UART_SEL_XIN24M;
140128d0997cSElaine Zhang 		div = 2;
140228d0997cSElaine Zhang 	} else {
140328d0997cSElaine Zhang 		clk_src = CLK_UART_SRC_SEL_GPLL;
140428d0997cSElaine Zhang 		uart_src = CLK_UART_SEL_FRAC;
140528d0997cSElaine Zhang 		div = 2;
140628d0997cSElaine Zhang 		rational_best_approximation(rate, priv->gpll_hz / div,
140728d0997cSElaine Zhang 					    GENMASK(16 - 1, 0),
140828d0997cSElaine Zhang 					    GENMASK(16 - 1, 0),
140928d0997cSElaine Zhang 					    &m, &n);
141028d0997cSElaine Zhang 	}
141128d0997cSElaine Zhang 
141228d0997cSElaine Zhang 	switch (clk_id) {
141328d0997cSElaine Zhang 	case SCLK_UART1:
141428d0997cSElaine Zhang 		reg = 41;
141528d0997cSElaine Zhang 		break;
141628d0997cSElaine Zhang 	case SCLK_UART2:
141728d0997cSElaine Zhang 		reg = 43;
141828d0997cSElaine Zhang 		break;
141928d0997cSElaine Zhang 	case SCLK_UART3:
142028d0997cSElaine Zhang 		reg = 45;
142128d0997cSElaine Zhang 		break;
142228d0997cSElaine Zhang 	case SCLK_UART4:
142328d0997cSElaine Zhang 		reg = 47;
142428d0997cSElaine Zhang 		break;
142528d0997cSElaine Zhang 	case SCLK_UART5:
142628d0997cSElaine Zhang 		reg = 49;
142728d0997cSElaine Zhang 		break;
142828d0997cSElaine Zhang 	case SCLK_UART6:
142928d0997cSElaine Zhang 		reg = 51;
143028d0997cSElaine Zhang 		break;
143128d0997cSElaine Zhang 	case SCLK_UART7:
143228d0997cSElaine Zhang 		reg = 53;
143328d0997cSElaine Zhang 		break;
143428d0997cSElaine Zhang 	case SCLK_UART8:
143528d0997cSElaine Zhang 		reg = 55;
143628d0997cSElaine Zhang 		break;
143728d0997cSElaine Zhang 	case SCLK_UART9:
143828d0997cSElaine Zhang 		reg = 57;
143928d0997cSElaine Zhang 		break;
144028d0997cSElaine Zhang 	default:
144128d0997cSElaine Zhang 		return -ENOENT;
144228d0997cSElaine Zhang 	}
144328d0997cSElaine Zhang 	rk_clrsetreg(&cru->clksel_con[reg],
144428d0997cSElaine Zhang 		     CLK_UART_SRC_SEL_MASK |
144528d0997cSElaine Zhang 		     CLK_UART_SRC_DIV_MASK,
144628d0997cSElaine Zhang 		     (clk_src << CLK_UART_SRC_SEL_SHIFT) |
144728d0997cSElaine Zhang 		     ((div - 1) << CLK_UART_SRC_DIV_SHIFT));
144828d0997cSElaine Zhang 	rk_clrsetreg(&cru->clksel_con[reg + 2],
144928d0997cSElaine Zhang 		     CLK_UART_SEL_MASK,
145028d0997cSElaine Zhang 		     (uart_src << CLK_UART_SEL_SHIFT));
145128d0997cSElaine Zhang 	if (m && n) {
145228d0997cSElaine Zhang 		val = m << CLK_UART_FRAC_NUMERATOR_SHIFT | n;
145328d0997cSElaine Zhang 		writel(val, &cru->clksel_con[reg + 1]);
145428d0997cSElaine Zhang 	}
145528d0997cSElaine Zhang 
145628d0997cSElaine Zhang 	return rk3588_uart_get_rate(priv, clk_id);
145728d0997cSElaine Zhang }
1458921abd27SElaine Zhang 
rk3588_pciephy_get_rate(struct rk3588_clk_priv * priv,ulong clk_id)1459921abd27SElaine Zhang static ulong rk3588_pciephy_get_rate(struct rk3588_clk_priv *priv, ulong clk_id)
1460921abd27SElaine Zhang {
1461921abd27SElaine Zhang 	struct rk3588_cru *cru = priv->cru;
1462921abd27SElaine Zhang 	u32 con, div, src;
1463921abd27SElaine Zhang 
1464921abd27SElaine Zhang 	switch (clk_id) {
1465921abd27SElaine Zhang 	case CLK_REF_PIPE_PHY0:
1466921abd27SElaine Zhang 		con = readl(&cru->clksel_con[177]);
1467921abd27SElaine Zhang 		src = (con & CLK_PCIE_PHY0_REF_SEL_MASK) >> CLK_PCIE_PHY0_REF_SEL_SHIFT;
1468921abd27SElaine Zhang 		con = readl(&cru->clksel_con[176]);
1469921abd27SElaine Zhang 		div = (con & CLK_PCIE_PHY0_PLL_DIV_MASK) >> CLK_PCIE_PHY0_PLL_DIV_SHIFT;
1470921abd27SElaine Zhang 		break;
1471921abd27SElaine Zhang 	case CLK_REF_PIPE_PHY1:
1472921abd27SElaine Zhang 		con = readl(&cru->clksel_con[177]);
1473921abd27SElaine Zhang 		src = (con & CLK_PCIE_PHY1_REF_SEL_MASK) >> CLK_PCIE_PHY1_REF_SEL_SHIFT;
1474921abd27SElaine Zhang 		con = readl(&cru->clksel_con[176]);
1475921abd27SElaine Zhang 		div = (con & CLK_PCIE_PHY1_PLL_DIV_MASK) >> CLK_PCIE_PHY1_PLL_DIV_SHIFT;
1476921abd27SElaine Zhang 		break;
1477921abd27SElaine Zhang 	case CLK_REF_PIPE_PHY2:
1478921abd27SElaine Zhang 		con = readl(&cru->clksel_con[177]);
1479921abd27SElaine Zhang 		src = (con & CLK_PCIE_PHY2_REF_SEL_MASK) >> CLK_PCIE_PHY2_REF_SEL_SHIFT;
1480921abd27SElaine Zhang 		div = (con & CLK_PCIE_PHY2_PLL_DIV_MASK) >> CLK_PCIE_PHY2_PLL_DIV_SHIFT;
1481921abd27SElaine Zhang 		break;
1482921abd27SElaine Zhang 	default:
1483921abd27SElaine Zhang 		return -ENOENT;
1484921abd27SElaine Zhang 	}
1485921abd27SElaine Zhang 
1486921abd27SElaine Zhang 	if (src == CLK_PCIE_PHY_REF_SEL_PPLL) {
1487921abd27SElaine Zhang 		return DIV_TO_RATE(priv->ppll_hz, div);
1488921abd27SElaine Zhang 	} else {
1489921abd27SElaine Zhang 		return OSC_HZ;
1490921abd27SElaine Zhang 	}
1491921abd27SElaine Zhang }
1492921abd27SElaine Zhang 
rk3588_pciephy_set_rate(struct rk3588_clk_priv * priv,ulong clk_id,ulong rate)1493921abd27SElaine Zhang static ulong rk3588_pciephy_set_rate(struct rk3588_clk_priv *priv,
1494921abd27SElaine Zhang 				  ulong clk_id, ulong rate)
1495921abd27SElaine Zhang {
1496921abd27SElaine Zhang 	struct rk3588_cru *cru = priv->cru;
1497921abd27SElaine Zhang 	u32 clk_src, div;
1498921abd27SElaine Zhang 
1499921abd27SElaine Zhang 	if (rate == OSC_HZ) {
1500921abd27SElaine Zhang 		clk_src = CLK_PCIE_PHY_REF_SEL_24M;
1501921abd27SElaine Zhang 		div = 1;
1502921abd27SElaine Zhang 	} else {
1503921abd27SElaine Zhang 		clk_src = CLK_PCIE_PHY_REF_SEL_PPLL;
1504921abd27SElaine Zhang 		div = DIV_ROUND_UP(priv->ppll_hz, rate);
1505921abd27SElaine Zhang 	}
1506921abd27SElaine Zhang 
1507921abd27SElaine Zhang 	switch (clk_id) {
1508921abd27SElaine Zhang 	case CLK_REF_PIPE_PHY0:
1509921abd27SElaine Zhang 		rk_clrsetreg(&cru->clksel_con[177],
1510921abd27SElaine Zhang 		     CLK_PCIE_PHY0_REF_SEL_MASK,
1511921abd27SElaine Zhang 		     (clk_src << CLK_PCIE_PHY0_REF_SEL_SHIFT));
1512921abd27SElaine Zhang 		rk_clrsetreg(&cru->clksel_con[176],
1513921abd27SElaine Zhang 		     CLK_PCIE_PHY0_PLL_DIV_MASK,
1514921abd27SElaine Zhang 		     ((div - 1) << CLK_PCIE_PHY0_PLL_DIV_SHIFT));
1515921abd27SElaine Zhang 		break;
1516921abd27SElaine Zhang 	case CLK_REF_PIPE_PHY1:
1517921abd27SElaine Zhang 		rk_clrsetreg(&cru->clksel_con[177],
1518921abd27SElaine Zhang 		     CLK_PCIE_PHY1_REF_SEL_MASK,
1519921abd27SElaine Zhang 		     (clk_src << CLK_PCIE_PHY1_REF_SEL_SHIFT));
1520921abd27SElaine Zhang 		rk_clrsetreg(&cru->clksel_con[176],
1521921abd27SElaine Zhang 		     CLK_PCIE_PHY1_PLL_DIV_MASK,
1522921abd27SElaine Zhang 		     ((div - 1) << CLK_PCIE_PHY1_PLL_DIV_SHIFT));
1523921abd27SElaine Zhang 		break;
1524921abd27SElaine Zhang 	case CLK_REF_PIPE_PHY2:
1525921abd27SElaine Zhang 		rk_clrsetreg(&cru->clksel_con[177],
1526921abd27SElaine Zhang 		     CLK_PCIE_PHY2_REF_SEL_MASK |
1527921abd27SElaine Zhang 		     CLK_PCIE_PHY2_PLL_DIV_MASK,
1528921abd27SElaine Zhang 		     (clk_src << CLK_PCIE_PHY2_REF_SEL_SHIFT) |
1529921abd27SElaine Zhang 		     ((div - 1) << CLK_PCIE_PHY2_PLL_DIV_SHIFT));
1530921abd27SElaine Zhang 		break;
1531921abd27SElaine Zhang 	default:
1532921abd27SElaine Zhang 		return -ENOENT;
1533921abd27SElaine Zhang 	}
1534921abd27SElaine Zhang 
1535921abd27SElaine Zhang 	return rk3588_pciephy_get_rate(priv, clk_id);
1536921abd27SElaine Zhang }
153728d0997cSElaine Zhang #endif
153828d0997cSElaine Zhang 
rk3588_clk_get_rate(struct clk * clk)153928d0997cSElaine Zhang static ulong rk3588_clk_get_rate(struct clk *clk)
154028d0997cSElaine Zhang {
154128d0997cSElaine Zhang 	struct rk3588_clk_priv *priv = dev_get_priv(clk->dev);
154228d0997cSElaine Zhang 	ulong rate = 0;
154328d0997cSElaine Zhang 
154428d0997cSElaine Zhang 	if (!priv->gpll_hz) {
154528d0997cSElaine Zhang 		printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
154628d0997cSElaine Zhang 		return -ENOENT;
154728d0997cSElaine Zhang 	}
154828d0997cSElaine Zhang 
1549921abd27SElaine Zhang 	if (!priv->ppll_hz) {
1550921abd27SElaine Zhang 		priv->ppll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[PPLL],
1551921abd27SElaine Zhang 						      priv->cru, PPLL);
1552921abd27SElaine Zhang 	}
1553921abd27SElaine Zhang 
155428d0997cSElaine Zhang 	switch (clk->id) {
155528d0997cSElaine Zhang 	case PLL_LPLL:
155628d0997cSElaine Zhang 		rate = rockchip_pll_get_rate(&rk3588_pll_clks[LPLL], priv->cru,
155728d0997cSElaine Zhang 					     LPLL);
155828d0997cSElaine Zhang 		break;
155928d0997cSElaine Zhang 	case PLL_B0PLL:
156028d0997cSElaine Zhang 		rate = rockchip_pll_get_rate(&rk3588_pll_clks[B0PLL], priv->cru,
156128d0997cSElaine Zhang 					     B0PLL);
156228d0997cSElaine Zhang 		break;
156328d0997cSElaine Zhang 	case PLL_B1PLL:
156428d0997cSElaine Zhang 		rate = rockchip_pll_get_rate(&rk3588_pll_clks[B1PLL], priv->cru,
156528d0997cSElaine Zhang 					     B1PLL);
156628d0997cSElaine Zhang 		break;
156728d0997cSElaine Zhang 	case PLL_GPLL:
156828d0997cSElaine Zhang 		rate = rockchip_pll_get_rate(&rk3588_pll_clks[GPLL], priv->cru,
156928d0997cSElaine Zhang 					     GPLL);
157028d0997cSElaine Zhang 		break;
157128d0997cSElaine Zhang 	case PLL_CPLL:
157228d0997cSElaine Zhang 		rate = rockchip_pll_get_rate(&rk3588_pll_clks[CPLL], priv->cru,
157328d0997cSElaine Zhang 					     CPLL);
157428d0997cSElaine Zhang 		break;
157528d0997cSElaine Zhang 	case PLL_NPLL:
157628d0997cSElaine Zhang 		rate = rockchip_pll_get_rate(&rk3588_pll_clks[NPLL], priv->cru,
157728d0997cSElaine Zhang 					     NPLL);
157828d0997cSElaine Zhang 		break;
157928d0997cSElaine Zhang 	case PLL_V0PLL:
158028d0997cSElaine Zhang 		rate = rockchip_pll_get_rate(&rk3588_pll_clks[V0PLL], priv->cru,
158128d0997cSElaine Zhang 					     V0PLL);
158228d0997cSElaine Zhang 		break;
158328d0997cSElaine Zhang 	case PLL_AUPLL:
158428d0997cSElaine Zhang 		rate = rockchip_pll_get_rate(&rk3588_pll_clks[AUPLL], priv->cru,
158528d0997cSElaine Zhang 					     AUPLL);
158628d0997cSElaine Zhang 		break;
158728d0997cSElaine Zhang 	case PLL_PPLL:
158828d0997cSElaine Zhang 		rate = rockchip_pll_get_rate(&rk3588_pll_clks[PPLL], priv->cru,
158928d0997cSElaine Zhang 					     PPLL);
159028d0997cSElaine Zhang 		break;
159128d0997cSElaine Zhang 	case ACLK_CENTER_ROOT:
159228d0997cSElaine Zhang 	case PCLK_CENTER_ROOT:
159328d0997cSElaine Zhang 	case HCLK_CENTER_ROOT:
159428d0997cSElaine Zhang 	case ACLK_CENTER_LOW_ROOT:
159528d0997cSElaine Zhang 		rate = rk3588_center_get_clk(priv, clk->id);
159628d0997cSElaine Zhang 		break;
159728d0997cSElaine Zhang 	case ACLK_TOP_ROOT:
159828d0997cSElaine Zhang 	case PCLK_TOP_ROOT:
159928d0997cSElaine Zhang 	case ACLK_LOW_TOP_ROOT:
160028d0997cSElaine Zhang 		rate = rk3588_top_get_clk(priv, clk->id);
160128d0997cSElaine Zhang 		break;
160228d0997cSElaine Zhang 	case CLK_I2C0:
160328d0997cSElaine Zhang 	case CLK_I2C1:
160428d0997cSElaine Zhang 	case CLK_I2C2:
160528d0997cSElaine Zhang 	case CLK_I2C3:
160628d0997cSElaine Zhang 	case CLK_I2C4:
160728d0997cSElaine Zhang 	case CLK_I2C5:
160828d0997cSElaine Zhang 	case CLK_I2C6:
160928d0997cSElaine Zhang 	case CLK_I2C7:
161028d0997cSElaine Zhang 	case CLK_I2C8:
161128d0997cSElaine Zhang 		rate = rk3588_i2c_get_clk(priv, clk->id);
161228d0997cSElaine Zhang 		break;
161328d0997cSElaine Zhang 	case CLK_SPI0:
161428d0997cSElaine Zhang 	case CLK_SPI1:
161528d0997cSElaine Zhang 	case CLK_SPI2:
161628d0997cSElaine Zhang 	case CLK_SPI3:
161728d0997cSElaine Zhang 	case CLK_SPI4:
161828d0997cSElaine Zhang 		rate = rk3588_spi_get_clk(priv, clk->id);
161928d0997cSElaine Zhang 		break;
162028d0997cSElaine Zhang 	case CLK_PWM1:
162128d0997cSElaine Zhang 	case CLK_PWM2:
162228d0997cSElaine Zhang 	case CLK_PWM3:
16236fe01683SElaine Zhang 	case CLK_PMU1PWM:
162428d0997cSElaine Zhang 		rate = rk3588_pwm_get_clk(priv, clk->id);
162528d0997cSElaine Zhang 		break;
162628d0997cSElaine Zhang 	case CLK_SARADC:
162728d0997cSElaine Zhang 	case CLK_TSADC:
162828d0997cSElaine Zhang 		rate = rk3588_adc_get_clk(priv, clk->id);
162928d0997cSElaine Zhang 		break;
163028d0997cSElaine Zhang 	case CCLK_SRC_SDIO:
163128d0997cSElaine Zhang 	case CCLK_EMMC:
163228d0997cSElaine Zhang 	case BCLK_EMMC:
163328d0997cSElaine Zhang 	case SCLK_SFC:
1634d2b507bbSElaine Zhang 	case DCLK_DECOM:
163528d0997cSElaine Zhang 		rate = rk3588_mmc_get_clk(priv, clk->id);
163628d0997cSElaine Zhang 		break;
16372a12b75eSElaine Zhang 	case TCLK_WDT0:
16382a12b75eSElaine Zhang 		rate = OSC_HZ;
16392a12b75eSElaine Zhang 		break;
164028d0997cSElaine Zhang #ifndef CONFIG_SPL_BUILD
1641b6d6b016SZhang Yubing 	case CLK_AUX16M_0:
1642b6d6b016SZhang Yubing 	case CLK_AUX16M_1:
1643b6d6b016SZhang Yubing 		rk3588_aux16m_get_clk(priv, clk->id);
1644b6d6b016SZhang Yubing 		break;
164528d0997cSElaine Zhang 	case ACLK_VOP_ROOT:
1646477e465dSElaine Zhang 	case ACLK_VOP:
164728d0997cSElaine Zhang 	case ACLK_VOP_LOW_ROOT:
164828d0997cSElaine Zhang 	case HCLK_VOP_ROOT:
164928d0997cSElaine Zhang 		rate = rk3588_aclk_vop_get_clk(priv, clk->id);
165028d0997cSElaine Zhang 		break;
165128d0997cSElaine Zhang 	case DCLK_VOP0:
165228d0997cSElaine Zhang 	case DCLK_VOP0_SRC:
165328d0997cSElaine Zhang 	case DCLK_VOP1:
165428d0997cSElaine Zhang 	case DCLK_VOP1_SRC:
165528d0997cSElaine Zhang 	case DCLK_VOP2:
165628d0997cSElaine Zhang 	case DCLK_VOP2_SRC:
165728d0997cSElaine Zhang 	case DCLK_VOP3:
165828d0997cSElaine Zhang 		rate = rk3588_dclk_vop_get_clk(priv, clk->id);
165928d0997cSElaine Zhang 		break;
16600265e00cSElaine Zhang 	case CLK_DSIHOST0:
16610265e00cSElaine Zhang 	case CLK_DSIHOST1:
16620265e00cSElaine Zhang 		rate = rk3588_clk_csihost_get_clk(priv, clk->id);
16630265e00cSElaine Zhang 		break;
166428d0997cSElaine Zhang 	case CLK_GMAC0_PTP_REF:
166528d0997cSElaine Zhang 	case CLK_GMAC1_PTP_REF:
166628d0997cSElaine Zhang 	case CLK_GMAC_125M:
166728d0997cSElaine Zhang 	case CLK_GMAC_50M:
166828d0997cSElaine Zhang 		rate = rk3588_gmac_get_clk(priv, clk->id);
166928d0997cSElaine Zhang 		break;
167028d0997cSElaine Zhang 	case SCLK_UART1:
167128d0997cSElaine Zhang 	case SCLK_UART2:
167228d0997cSElaine Zhang 	case SCLK_UART3:
167328d0997cSElaine Zhang 	case SCLK_UART4:
167428d0997cSElaine Zhang 	case SCLK_UART5:
167528d0997cSElaine Zhang 	case SCLK_UART6:
167628d0997cSElaine Zhang 	case SCLK_UART7:
167728d0997cSElaine Zhang 	case SCLK_UART8:
167828d0997cSElaine Zhang 	case SCLK_UART9:
167928d0997cSElaine Zhang 		rate = rk3588_uart_get_rate(priv, clk->id);
168028d0997cSElaine Zhang 		break;
1681921abd27SElaine Zhang 	case CLK_REF_PIPE_PHY0:
1682921abd27SElaine Zhang 	case CLK_REF_PIPE_PHY1:
1683921abd27SElaine Zhang 	case CLK_REF_PIPE_PHY2:
1684921abd27SElaine Zhang 		rate = rk3588_pciephy_get_rate(priv, clk->id);
1685921abd27SElaine Zhang 		break;
168628d0997cSElaine Zhang #endif
168728d0997cSElaine Zhang 	default:
168828d0997cSElaine Zhang 		return -ENOENT;
168928d0997cSElaine Zhang 	}
169028d0997cSElaine Zhang 
169128d0997cSElaine Zhang 	return rate;
169228d0997cSElaine Zhang };
169328d0997cSElaine Zhang 
rk3588_clk_set_rate(struct clk * clk,ulong rate)169428d0997cSElaine Zhang static ulong rk3588_clk_set_rate(struct clk *clk, ulong rate)
169528d0997cSElaine Zhang {
169628d0997cSElaine Zhang 	struct rk3588_clk_priv *priv = dev_get_priv(clk->dev);
169728d0997cSElaine Zhang 	ulong ret = 0;
169828d0997cSElaine Zhang 
169928d0997cSElaine Zhang 	if (!priv->gpll_hz) {
170028d0997cSElaine Zhang 		printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
170128d0997cSElaine Zhang 		return -ENOENT;
170228d0997cSElaine Zhang 	}
170328d0997cSElaine Zhang 
1704921abd27SElaine Zhang 	if (!priv->ppll_hz) {
1705921abd27SElaine Zhang 		priv->ppll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[PPLL],
1706921abd27SElaine Zhang 						      priv->cru, PPLL);
1707921abd27SElaine Zhang 	}
1708921abd27SElaine Zhang 
170928d0997cSElaine Zhang 	switch (clk->id) {
171028d0997cSElaine Zhang 	case PLL_CPLL:
171128d0997cSElaine Zhang 		ret = rockchip_pll_set_rate(&rk3588_pll_clks[CPLL], priv->cru,
171228d0997cSElaine Zhang 					    CPLL, rate);
171328d0997cSElaine Zhang 		priv->cpll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[CPLL],
171428d0997cSElaine Zhang 						      priv->cru, CPLL);
171528d0997cSElaine Zhang 		break;
171628d0997cSElaine Zhang 	case PLL_GPLL:
171728d0997cSElaine Zhang 		ret = rockchip_pll_set_rate(&rk3588_pll_clks[GPLL], priv->cru,
171828d0997cSElaine Zhang 					    GPLL, rate);
171928d0997cSElaine Zhang 		priv->gpll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[GPLL],
172028d0997cSElaine Zhang 						      priv->cru, GPLL);
172128d0997cSElaine Zhang 		break;
172228d0997cSElaine Zhang 	case PLL_NPLL:
172328d0997cSElaine Zhang 		ret = rockchip_pll_set_rate(&rk3588_pll_clks[NPLL], priv->cru,
172428d0997cSElaine Zhang 					    NPLL, rate);
172528d0997cSElaine Zhang 		break;
172628d0997cSElaine Zhang 	case PLL_V0PLL:
172728d0997cSElaine Zhang 		ret = rockchip_pll_set_rate(&rk3588_pll_clks[V0PLL], priv->cru,
172828d0997cSElaine Zhang 					    V0PLL, rate);
172928d0997cSElaine Zhang 		priv->v0pll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[V0PLL],
173028d0997cSElaine Zhang 						       priv->cru, V0PLL);
173128d0997cSElaine Zhang 		break;
173228d0997cSElaine Zhang 	case PLL_AUPLL:
173328d0997cSElaine Zhang 		ret = rockchip_pll_set_rate(&rk3588_pll_clks[AUPLL], priv->cru,
173428d0997cSElaine Zhang 					    AUPLL, rate);
173528d0997cSElaine Zhang 		priv->aupll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[AUPLL],
173628d0997cSElaine Zhang 						       priv->cru, AUPLL);
173728d0997cSElaine Zhang 		break;
173828d0997cSElaine Zhang 	case PLL_PPLL:
173928d0997cSElaine Zhang 		ret = rockchip_pll_set_rate(&rk3588_pll_clks[PPLL], priv->cru,
174028d0997cSElaine Zhang 					    PPLL, rate);
174128d0997cSElaine Zhang 		priv->ppll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[PPLL],
174228d0997cSElaine Zhang 						      priv->cru, PPLL);
174328d0997cSElaine Zhang 		break;
174428d0997cSElaine Zhang 	case ACLK_CENTER_ROOT:
174528d0997cSElaine Zhang 	case PCLK_CENTER_ROOT:
174628d0997cSElaine Zhang 	case HCLK_CENTER_ROOT:
174728d0997cSElaine Zhang 	case ACLK_CENTER_LOW_ROOT:
174828d0997cSElaine Zhang 		ret = rk3588_center_set_clk(priv, clk->id, rate);
174928d0997cSElaine Zhang 		break;
175028d0997cSElaine Zhang 	case ACLK_TOP_ROOT:
175128d0997cSElaine Zhang 	case PCLK_TOP_ROOT:
175228d0997cSElaine Zhang 	case ACLK_LOW_TOP_ROOT:
175328d0997cSElaine Zhang 		ret = rk3588_top_set_clk(priv, clk->id, rate);
175428d0997cSElaine Zhang 		break;
175528d0997cSElaine Zhang 	case CLK_I2C0:
175628d0997cSElaine Zhang 	case CLK_I2C1:
175728d0997cSElaine Zhang 	case CLK_I2C2:
175828d0997cSElaine Zhang 	case CLK_I2C3:
175928d0997cSElaine Zhang 	case CLK_I2C4:
176028d0997cSElaine Zhang 	case CLK_I2C5:
176128d0997cSElaine Zhang 	case CLK_I2C6:
176228d0997cSElaine Zhang 	case CLK_I2C7:
176328d0997cSElaine Zhang 	case CLK_I2C8:
176428d0997cSElaine Zhang 		ret = rk3588_i2c_set_clk(priv, clk->id, rate);
176528d0997cSElaine Zhang 		break;
176628d0997cSElaine Zhang 	case CLK_SPI0:
176728d0997cSElaine Zhang 	case CLK_SPI1:
176828d0997cSElaine Zhang 	case CLK_SPI2:
176928d0997cSElaine Zhang 	case CLK_SPI3:
177028d0997cSElaine Zhang 	case CLK_SPI4:
177128d0997cSElaine Zhang 		ret = rk3588_spi_set_clk(priv, clk->id, rate);
177228d0997cSElaine Zhang 		break;
177328d0997cSElaine Zhang 	case CLK_PWM1:
177428d0997cSElaine Zhang 	case CLK_PWM2:
177528d0997cSElaine Zhang 	case CLK_PWM3:
17766fe01683SElaine Zhang 	case CLK_PMU1PWM:
177728d0997cSElaine Zhang 		ret = rk3588_pwm_set_clk(priv, clk->id, rate);
177828d0997cSElaine Zhang 		break;
177928d0997cSElaine Zhang 	case CLK_SARADC:
178028d0997cSElaine Zhang 	case CLK_TSADC:
178128d0997cSElaine Zhang 		ret = rk3588_adc_set_clk(priv, clk->id, rate);
178228d0997cSElaine Zhang 		break;
178328d0997cSElaine Zhang 	case CCLK_SRC_SDIO:
178428d0997cSElaine Zhang 	case CCLK_EMMC:
178528d0997cSElaine Zhang 	case BCLK_EMMC:
178628d0997cSElaine Zhang 	case SCLK_SFC:
1787d2b507bbSElaine Zhang 	case DCLK_DECOM:
178828d0997cSElaine Zhang 		ret = rk3588_mmc_set_clk(priv, clk->id, rate);
178928d0997cSElaine Zhang 		break;
17902a12b75eSElaine Zhang 	case TCLK_WDT0:
17912a12b75eSElaine Zhang 		ret = OSC_HZ;
17922a12b75eSElaine Zhang 		break;
179328d0997cSElaine Zhang #ifndef CONFIG_SPL_BUILD
1794b6d6b016SZhang Yubing 	case CLK_AUX16M_0:
1795b6d6b016SZhang Yubing 	case CLK_AUX16M_1:
1796b6d6b016SZhang Yubing 		rk3588_aux16m_set_clk(priv, clk->id, rate);
1797b6d6b016SZhang Yubing 		break;
179828d0997cSElaine Zhang 	case ACLK_VOP_ROOT:
1799477e465dSElaine Zhang 	case ACLK_VOP:
180028d0997cSElaine Zhang 	case ACLK_VOP_LOW_ROOT:
180128d0997cSElaine Zhang 	case HCLK_VOP_ROOT:
180228d0997cSElaine Zhang 		ret = rk3588_aclk_vop_set_clk(priv, clk->id, rate);
180328d0997cSElaine Zhang 		break;
180428d0997cSElaine Zhang 	case DCLK_VOP0:
180528d0997cSElaine Zhang 	case DCLK_VOP0_SRC:
180628d0997cSElaine Zhang 	case DCLK_VOP1:
180728d0997cSElaine Zhang 	case DCLK_VOP1_SRC:
180828d0997cSElaine Zhang 	case DCLK_VOP2:
180928d0997cSElaine Zhang 	case DCLK_VOP2_SRC:
181028d0997cSElaine Zhang 	case DCLK_VOP3:
181128d0997cSElaine Zhang 		ret = rk3588_dclk_vop_set_clk(priv, clk->id, rate);
181228d0997cSElaine Zhang 		break;
181328d0997cSElaine Zhang 	case CLK_GMAC0_PTP_REF:
181428d0997cSElaine Zhang 	case CLK_GMAC1_PTP_REF:
181528d0997cSElaine Zhang 	case CLK_GMAC_125M:
181628d0997cSElaine Zhang 	case CLK_GMAC_50M:
1817b3fe4c57SDavid Wu 		ret = rk3588_gmac_set_clk(priv, clk->id, rate);
181828d0997cSElaine Zhang 		break;
181928d0997cSElaine Zhang 	case SCLK_UART1:
182028d0997cSElaine Zhang 	case SCLK_UART2:
182128d0997cSElaine Zhang 	case SCLK_UART3:
182228d0997cSElaine Zhang 	case SCLK_UART4:
182328d0997cSElaine Zhang 	case SCLK_UART5:
182428d0997cSElaine Zhang 	case SCLK_UART6:
182528d0997cSElaine Zhang 	case SCLK_UART7:
182628d0997cSElaine Zhang 	case SCLK_UART8:
182728d0997cSElaine Zhang 	case SCLK_UART9:
182828d0997cSElaine Zhang 		ret = rk3588_uart_set_rate(priv, clk->id, rate);
182928d0997cSElaine Zhang 		break;
1830921abd27SElaine Zhang 	case CLK_REF_PIPE_PHY0:
1831921abd27SElaine Zhang 	case CLK_REF_PIPE_PHY1:
1832921abd27SElaine Zhang 	case CLK_REF_PIPE_PHY2:
1833921abd27SElaine Zhang 		ret = rk3588_pciephy_set_rate(priv, clk->id, rate);
1834921abd27SElaine Zhang 		break;
183528d0997cSElaine Zhang #endif
183628d0997cSElaine Zhang 	default:
183728d0997cSElaine Zhang 		return -ENOENT;
183828d0997cSElaine Zhang 	}
183928d0997cSElaine Zhang 
184028d0997cSElaine Zhang 	return ret;
184128d0997cSElaine Zhang };
184228d0997cSElaine Zhang 
184328d0997cSElaine Zhang #define ROCKCHIP_MMC_DELAY_SEL		BIT(10)
184428d0997cSElaine Zhang #define ROCKCHIP_MMC_DEGREE_MASK	0x3
184528d0997cSElaine Zhang #define ROCKCHIP_MMC_DELAYNUM_OFFSET	2
184628d0997cSElaine Zhang #define ROCKCHIP_MMC_DELAYNUM_MASK	(0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
184728d0997cSElaine Zhang 
184828d0997cSElaine Zhang #define PSECS_PER_SEC 1000000000000LL
184928d0997cSElaine Zhang /*
185028d0997cSElaine Zhang  * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
185128d0997cSElaine Zhang  * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
185228d0997cSElaine Zhang  */
185328d0997cSElaine Zhang #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
185428d0997cSElaine Zhang 
rk3588_mmc_get_phase(struct clk * clk)185528d0997cSElaine Zhang int rk3588_mmc_get_phase(struct clk *clk)
185628d0997cSElaine Zhang {
185728d0997cSElaine Zhang 	struct rk3588_clk_priv *priv = dev_get_priv(clk->dev);
185828d0997cSElaine Zhang 	struct rk3588_cru *cru = priv->cru;
185928d0997cSElaine Zhang 	u32 raw_value, delay_num;
186028d0997cSElaine Zhang 	u16 degrees = 0;
186128d0997cSElaine Zhang 	ulong rate;
186228d0997cSElaine Zhang 
186328d0997cSElaine Zhang 	rate = rk3588_clk_get_rate(clk);
18646ed0ecbdSJianqun Xu 	if (rate <= 0)
186528d0997cSElaine Zhang 		return rate;
186628d0997cSElaine Zhang 
186728d0997cSElaine Zhang 	if (clk->id == SCLK_SDMMC_SAMPLE)
186828d0997cSElaine Zhang 		raw_value = readl(&cru->sdmmc_con[1]);
186928d0997cSElaine Zhang 	else
187028d0997cSElaine Zhang 		return 0;
187128d0997cSElaine Zhang 
187228d0997cSElaine Zhang 	raw_value >>= 1;
187328d0997cSElaine Zhang 	degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
187428d0997cSElaine Zhang 
187528d0997cSElaine Zhang 	if (raw_value & ROCKCHIP_MMC_DELAY_SEL) {
187628d0997cSElaine Zhang 		/* degrees/delaynum * 10000 */
187728d0997cSElaine Zhang 		unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) *
187828d0997cSElaine Zhang 					36 * (rate / 1000000);
187928d0997cSElaine Zhang 
188028d0997cSElaine Zhang 		delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
188128d0997cSElaine Zhang 		delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET;
188228d0997cSElaine Zhang 		degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000);
188328d0997cSElaine Zhang 	}
188428d0997cSElaine Zhang 
188528d0997cSElaine Zhang 	return degrees % 360;
188628d0997cSElaine Zhang }
188728d0997cSElaine Zhang 
rk3588_mmc_set_phase(struct clk * clk,u32 degrees)188828d0997cSElaine Zhang int rk3588_mmc_set_phase(struct clk *clk, u32 degrees)
188928d0997cSElaine Zhang {
189028d0997cSElaine Zhang 	struct rk3588_clk_priv *priv = dev_get_priv(clk->dev);
189128d0997cSElaine Zhang 	struct rk3588_cru *cru = priv->cru;
189228d0997cSElaine Zhang 	u8 nineties, remainder, delay_num;
189328d0997cSElaine Zhang 	u32 raw_value, delay;
189428d0997cSElaine Zhang 	ulong rate;
189528d0997cSElaine Zhang 
189628d0997cSElaine Zhang 	rate = rk3588_clk_get_rate(clk);
18976ed0ecbdSJianqun Xu 	if (rate <= 0)
189828d0997cSElaine Zhang 		return rate;
189928d0997cSElaine Zhang 
190028d0997cSElaine Zhang 	nineties = degrees / 90;
190128d0997cSElaine Zhang 	remainder = (degrees % 90);
190228d0997cSElaine Zhang 
190328d0997cSElaine Zhang 	/*
190428d0997cSElaine Zhang 	 * Convert to delay; do a little extra work to make sure we
190528d0997cSElaine Zhang 	 * don't overflow 32-bit / 64-bit numbers.
190628d0997cSElaine Zhang 	 */
190728d0997cSElaine Zhang 	delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */
190828d0997cSElaine Zhang 	delay *= remainder;
190928d0997cSElaine Zhang 	delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 *
191028d0997cSElaine Zhang 				  (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10));
191128d0997cSElaine Zhang 
191228d0997cSElaine Zhang 	delay_num = (u8)min_t(u32, delay, 255);
191328d0997cSElaine Zhang 
191428d0997cSElaine Zhang 	raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
191528d0997cSElaine Zhang 	raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
191628d0997cSElaine Zhang 	raw_value |= nineties;
191728d0997cSElaine Zhang 
191828d0997cSElaine Zhang 	raw_value <<= 1;
191928d0997cSElaine Zhang 	if (clk->id == SCLK_SDMMC_SAMPLE)
192028d0997cSElaine Zhang 		writel(raw_value | 0xffff0000, &cru->sdmmc_con[1]);
192128d0997cSElaine Zhang 
192228d0997cSElaine Zhang 	debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n",
192328d0997cSElaine Zhang 	      degrees, delay_num, raw_value, rk3588_mmc_get_phase(clk));
192428d0997cSElaine Zhang 
192528d0997cSElaine Zhang 	return 0;
192628d0997cSElaine Zhang }
192728d0997cSElaine Zhang 
rk3588_clk_get_phase(struct clk * clk)192828d0997cSElaine Zhang static int rk3588_clk_get_phase(struct clk *clk)
192928d0997cSElaine Zhang {
193028d0997cSElaine Zhang 	int ret;
193128d0997cSElaine Zhang 
193228d0997cSElaine Zhang 	debug("%s %ld\n", __func__, clk->id);
193328d0997cSElaine Zhang 	switch (clk->id) {
193428d0997cSElaine Zhang 	case SCLK_SDMMC_SAMPLE:
193528d0997cSElaine Zhang 		ret = rk3588_mmc_get_phase(clk);
193628d0997cSElaine Zhang 		break;
193728d0997cSElaine Zhang 	default:
193828d0997cSElaine Zhang 		return -ENOENT;
193928d0997cSElaine Zhang 	}
194028d0997cSElaine Zhang 
194128d0997cSElaine Zhang 	return ret;
194228d0997cSElaine Zhang }
194328d0997cSElaine Zhang 
rk3588_clk_set_phase(struct clk * clk,int degrees)194428d0997cSElaine Zhang static int rk3588_clk_set_phase(struct clk *clk, int degrees)
194528d0997cSElaine Zhang {
194628d0997cSElaine Zhang 	int ret;
194728d0997cSElaine Zhang 
194828d0997cSElaine Zhang 	debug("%s %ld\n", __func__, clk->id);
194928d0997cSElaine Zhang 	switch (clk->id) {
195028d0997cSElaine Zhang 	case SCLK_SDMMC_SAMPLE:
195128d0997cSElaine Zhang 		ret = rk3588_mmc_set_phase(clk, degrees);
195228d0997cSElaine Zhang 		break;
195328d0997cSElaine Zhang 	default:
195428d0997cSElaine Zhang 		return -ENOENT;
195528d0997cSElaine Zhang 	}
195628d0997cSElaine Zhang 
195728d0997cSElaine Zhang 	return ret;
195828d0997cSElaine Zhang }
195928d0997cSElaine Zhang 
196028d0997cSElaine Zhang #if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA))
rk3588_dclk_vop_set_parent(struct clk * clk,struct clk * parent)196128d0997cSElaine Zhang static int __maybe_unused rk3588_dclk_vop_set_parent(struct clk *clk,
196228d0997cSElaine Zhang 						     struct clk *parent)
196328d0997cSElaine Zhang {
196428d0997cSElaine Zhang 	struct rk3588_clk_priv *priv = dev_get_priv(clk->dev);
196528d0997cSElaine Zhang 	struct rk3588_cru *cru = priv->cru;
196628d0997cSElaine Zhang 	u32 sel;
196702b00901SAlgea Cao 	const char *clock_dev_name = parent->dev->name;
196828d0997cSElaine Zhang 
196928d0997cSElaine Zhang 	if (parent->id == PLL_V0PLL)
197028d0997cSElaine Zhang 		sel = 2;
197128d0997cSElaine Zhang 	else if (parent->id == PLL_GPLL)
197228d0997cSElaine Zhang 		sel = 0;
197328d0997cSElaine Zhang 	else if (parent->id == PLL_CPLL)
197428d0997cSElaine Zhang 		sel = 1;
197528d0997cSElaine Zhang 	else
197628d0997cSElaine Zhang 		sel = 3;
197728d0997cSElaine Zhang 
197828d0997cSElaine Zhang 	switch (clk->id) {
197928d0997cSElaine Zhang 	case DCLK_VOP0_SRC:
198028d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[111], DCLK0_VOP_SRC_SEL_MASK,
198128d0997cSElaine Zhang 			     sel << DCLK0_VOP_SRC_SEL_SHIFT);
198228d0997cSElaine Zhang 		break;
198328d0997cSElaine Zhang 	case DCLK_VOP1_SRC:
198428d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[111], DCLK1_VOP_SRC_SEL_MASK,
198528d0997cSElaine Zhang 			     sel << DCLK1_VOP_SRC_SEL_SHIFT);
198628d0997cSElaine Zhang 		break;
198728d0997cSElaine Zhang 	case DCLK_VOP2_SRC:
198828d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[112], DCLK2_VOP_SRC_SEL_MASK,
198928d0997cSElaine Zhang 			     sel << DCLK2_VOP_SRC_SEL_SHIFT);
199028d0997cSElaine Zhang 		break;
199128d0997cSElaine Zhang 	case DCLK_VOP3:
199228d0997cSElaine Zhang 		rk_clrsetreg(&cru->clksel_con[113], DCLK3_VOP_SRC_SEL_MASK,
199328d0997cSElaine Zhang 			     sel << DCLK3_VOP_SRC_SEL_SHIFT);
199428d0997cSElaine Zhang 		break;
1995da48e024SAlgea Cao 	case DCLK_VOP0:
199602b00901SAlgea Cao 		if (!strcmp(clock_dev_name, "hdmiphypll_clk0"))
1997da48e024SAlgea Cao 			sel = 1;
199802b00901SAlgea Cao 		else if (!strcmp(clock_dev_name, "hdmiphypll_clk1"))
1999da48e024SAlgea Cao 			sel = 2;
2000da48e024SAlgea Cao 		else
2001da48e024SAlgea Cao 			sel = 0;
2002da48e024SAlgea Cao 		rk_clrsetreg(&cru->clksel_con[112], DCLK0_VOP_SEL_MASK,
2003da48e024SAlgea Cao 			     sel << DCLK0_VOP_SEL_SHIFT);
2004da48e024SAlgea Cao 		break;
2005da48e024SAlgea Cao 	case DCLK_VOP1:
200602b00901SAlgea Cao 		if (!strcmp(clock_dev_name, "hdmiphypll_clk0"))
2007da48e024SAlgea Cao 			sel = 1;
200802b00901SAlgea Cao 		else if (!strcmp(clock_dev_name, "hdmiphypll_clk1"))
2009da48e024SAlgea Cao 			sel = 2;
2010da48e024SAlgea Cao 		else
2011da48e024SAlgea Cao 			sel = 0;
2012da48e024SAlgea Cao 		rk_clrsetreg(&cru->clksel_con[112], DCLK1_VOP_SEL_MASK,
2013da48e024SAlgea Cao 			     sel << DCLK1_VOP_SEL_SHIFT);
2014da48e024SAlgea Cao 		break;
2015da48e024SAlgea Cao 	case DCLK_VOP2:
201602b00901SAlgea Cao 		if (!strcmp(clock_dev_name, "hdmiphypll_clk0"))
2017da48e024SAlgea Cao 			sel = 1;
201802b00901SAlgea Cao 		else if (!strcmp(clock_dev_name, "hdmiphypll_clk1"))
2019da48e024SAlgea Cao 			sel = 2;
2020da48e024SAlgea Cao 		else
2021da48e024SAlgea Cao 			sel = 0;
2022da48e024SAlgea Cao 		rk_clrsetreg(&cru->clksel_con[112], DCLK2_VOP_SEL_MASK,
2023da48e024SAlgea Cao 			     sel << DCLK2_VOP_SEL_SHIFT);
2024da48e024SAlgea Cao 		break;
202528d0997cSElaine Zhang 	default:
202628d0997cSElaine Zhang 		return -EINVAL;
202728d0997cSElaine Zhang 	}
202828d0997cSElaine Zhang 	return 0;
202928d0997cSElaine Zhang }
203028d0997cSElaine Zhang 
rk3588_clk_set_parent(struct clk * clk,struct clk * parent)203128d0997cSElaine Zhang static int rk3588_clk_set_parent(struct clk *clk, struct clk *parent)
203228d0997cSElaine Zhang {
203328d0997cSElaine Zhang 	switch (clk->id) {
203428d0997cSElaine Zhang 	case DCLK_VOP0_SRC:
203528d0997cSElaine Zhang 	case DCLK_VOP1_SRC:
203628d0997cSElaine Zhang 	case DCLK_VOP2_SRC:
2037da48e024SAlgea Cao 	case DCLK_VOP0:
2038da48e024SAlgea Cao 	case DCLK_VOP1:
2039da48e024SAlgea Cao 	case DCLK_VOP2:
204028d0997cSElaine Zhang 	case DCLK_VOP3:
204128d0997cSElaine Zhang 		return rk3588_dclk_vop_set_parent(clk, parent);
204228d0997cSElaine Zhang 	default:
204328d0997cSElaine Zhang 		return -ENOENT;
204428d0997cSElaine Zhang 	}
204528d0997cSElaine Zhang 
204628d0997cSElaine Zhang 	return 0;
204728d0997cSElaine Zhang }
204828d0997cSElaine Zhang #endif
204928d0997cSElaine Zhang 
205028d0997cSElaine Zhang static struct clk_ops rk3588_clk_ops = {
205128d0997cSElaine Zhang 	.get_rate = rk3588_clk_get_rate,
205228d0997cSElaine Zhang 	.set_rate = rk3588_clk_set_rate,
205328d0997cSElaine Zhang 	.get_phase = rk3588_clk_get_phase,
205428d0997cSElaine Zhang 	.set_phase = rk3588_clk_set_phase,
205528d0997cSElaine Zhang #if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA))
205628d0997cSElaine Zhang 	.set_parent = rk3588_clk_set_parent,
205728d0997cSElaine Zhang #endif
205828d0997cSElaine Zhang };
205928d0997cSElaine Zhang 
rk3588_clk_init(struct rk3588_clk_priv * priv)206028d0997cSElaine Zhang static void rk3588_clk_init(struct rk3588_clk_priv *priv)
206128d0997cSElaine Zhang {
206228d0997cSElaine Zhang 	int ret, div;
206328d0997cSElaine Zhang 
206428d0997cSElaine Zhang 	div = DIV_ROUND_UP(GPLL_HZ, 300 * MHz);
206528d0997cSElaine Zhang 	rk_clrsetreg(&priv->cru->clksel_con[38],
206628d0997cSElaine Zhang 		     ACLK_BUS_ROOT_SEL_MASK |
206728d0997cSElaine Zhang 		     ACLK_BUS_ROOT_DIV_MASK,
206828d0997cSElaine Zhang 		     div << ACLK_BUS_ROOT_DIV_SHIFT);
206928d0997cSElaine Zhang 
20700265e00cSElaine Zhang 	priv->spll_hz = 702000000;
207128d0997cSElaine Zhang 	if (priv->cpll_hz != CPLL_HZ) {
207228d0997cSElaine Zhang 		ret = rockchip_pll_set_rate(&rk3588_pll_clks[CPLL], priv->cru,
207328d0997cSElaine Zhang 					    CPLL, CPLL_HZ);
207428d0997cSElaine Zhang 		if (!ret)
207528d0997cSElaine Zhang 			priv->cpll_hz = CPLL_HZ;
207628d0997cSElaine Zhang 	}
207728d0997cSElaine Zhang 	if (priv->gpll_hz != GPLL_HZ) {
207828d0997cSElaine Zhang 		ret = rockchip_pll_set_rate(&rk3588_pll_clks[GPLL], priv->cru,
207928d0997cSElaine Zhang 					    GPLL, GPLL_HZ);
208028d0997cSElaine Zhang 		if (!ret)
208128d0997cSElaine Zhang 			priv->gpll_hz = GPLL_HZ;
208228d0997cSElaine Zhang 	}
208328d0997cSElaine Zhang 
20843a7297c2SKever Yang 	if (priv->ppll_hz != PPLL_HZ) {
20853a7297c2SKever Yang 		ret = rockchip_pll_set_rate(&rk3588_pll_clks[PPLL], priv->cru,
20863a7297c2SKever Yang 					    PPLL, PPLL_HZ);
20873a7297c2SKever Yang 		priv->ppll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[PPLL],
20883a7297c2SKever Yang 						      priv->cru, PPLL);
20893a7297c2SKever Yang 	}
209071cb44d0SYifeng Zhao 
209128d0997cSElaine Zhang 	rk_clrsetreg(&priv->cru->clksel_con[9],
209228d0997cSElaine Zhang 		     ACLK_TOP_S400_SEL_MASK |
209328d0997cSElaine Zhang 		     ACLK_TOP_S200_SEL_MASK,
209428d0997cSElaine Zhang 		     (ACLK_TOP_S400_SEL_400M << ACLK_TOP_S400_SEL_SHIFT) |
209528d0997cSElaine Zhang 		     (ACLK_TOP_S200_SEL_200M << ACLK_TOP_S200_SEL_SHIFT));
209628d0997cSElaine Zhang }
209728d0997cSElaine Zhang 
rk3588_clk_probe(struct udevice * dev)209828d0997cSElaine Zhang static int rk3588_clk_probe(struct udevice *dev)
209928d0997cSElaine Zhang {
210028d0997cSElaine Zhang 	struct rk3588_clk_priv *priv = dev_get_priv(dev);
210128d0997cSElaine Zhang 	int ret;
2102ffe7a059SYifeng Zhao 
2103ffe7a059SYifeng Zhao #if CONFIG_IS_ENABLED(CLK_SCMI)
21041e239139SElaine Zhang 	struct clk clk;
2105ffe7a059SYifeng Zhao #endif
21061e239139SElaine Zhang 
2107056cae5cSFinley Xiao 	priv->sync_kernel = false;
2108056cae5cSFinley Xiao 
2109c22f6846SElaine Zhang #ifdef CONFIG_SPL_BUILD
2110c22f6846SElaine Zhang 	rockchip_pll_set_rate(&rk3588_pll_clks[B0PLL], priv->cru,
2111c22f6846SElaine Zhang 			      B0PLL, LPLL_HZ);
2112c22f6846SElaine Zhang 	rockchip_pll_set_rate(&rk3588_pll_clks[B1PLL], priv->cru,
2113c22f6846SElaine Zhang 			      B1PLL, LPLL_HZ);
2114056cae5cSFinley Xiao 	if (!priv->armclk_enter_hz) {
2115056cae5cSFinley Xiao 		ret = rockchip_pll_set_rate(&rk3588_pll_clks[LPLL], priv->cru,
2116056cae5cSFinley Xiao 					    LPLL, LPLL_HZ);
2117056cae5cSFinley Xiao 		priv->armclk_enter_hz =
2118056cae5cSFinley Xiao 			rockchip_pll_get_rate(&rk3588_pll_clks[LPLL],
2119056cae5cSFinley Xiao 					      priv->cru, LPLL);
2120056cae5cSFinley Xiao 		priv->armclk_init_hz = priv->armclk_enter_hz;
2121056cae5cSFinley Xiao 	}
2122c22f6846SElaine Zhang #endif
2123c22f6846SElaine Zhang 
2124ffe7a059SYifeng Zhao #if CONFIG_IS_ENABLED(CLK_SCMI)
21251e239139SElaine Zhang 	ret = rockchip_get_scmi_clk(&clk.dev);
21261e239139SElaine Zhang 	if (ret) {
21271e239139SElaine Zhang 		printf("Failed to get scmi clk dev\n");
21281e239139SElaine Zhang 		return ret;
21291e239139SElaine Zhang 	}
21301e239139SElaine Zhang 	clk.id = SCMI_SPLL;
21311e239139SElaine Zhang 	ret = clk_set_rate(&clk, 702000000);
21321e239139SElaine Zhang 	if (ret < 0) {
21331e239139SElaine Zhang 		printf("Failed to set spll\n");
21341e239139SElaine Zhang 	}
213528d0997cSElaine Zhang 
2136056cae5cSFinley Xiao #ifndef CONFIG_SPL_BUILD
2137056cae5cSFinley Xiao 	if (!priv->armclk_enter_hz) {
2138056cae5cSFinley Xiao 		clk.id = SCMI_CLK_CPUL;
2139056cae5cSFinley Xiao 		ret = clk_set_rate(&clk, CPU_PVTPLL_HZ);
2140056cae5cSFinley Xiao 		if (ret < 0) {
2141056cae5cSFinley Xiao 			printf("Failed to set cpubl\n");
2142056cae5cSFinley Xiao 		} else {
2143056cae5cSFinley Xiao 			priv->armclk_enter_hz = CPU_PVTPLL_HZ;
2144056cae5cSFinley Xiao 			priv->armclk_init_hz = CPU_PVTPLL_HZ;
2145056cae5cSFinley Xiao 		}
2146056cae5cSFinley Xiao 	}
214740801113SFinley Xiao 	clk.id = SCMI_CLK_CPUB01;
2148056cae5cSFinley Xiao 	ret = clk_set_rate(&clk, CPU_PVTPLL_HZ);
214940801113SFinley Xiao 	if (ret < 0)
215040801113SFinley Xiao 		printf("Failed to set cpub01\n");
215140801113SFinley Xiao 	clk.id = SCMI_CLK_CPUB23;
2152056cae5cSFinley Xiao 	ret = clk_set_rate(&clk, CPU_PVTPLL_HZ);
215340801113SFinley Xiao 	if (ret < 0)
215440801113SFinley Xiao 		printf("Failed to set cpub23\n");
2155056cae5cSFinley Xiao #endif
2156ffe7a059SYifeng Zhao #endif
215740801113SFinley Xiao 
215828d0997cSElaine Zhang 	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
215928d0997cSElaine Zhang 	if (IS_ERR(priv->grf))
216028d0997cSElaine Zhang 		return PTR_ERR(priv->grf);
216128d0997cSElaine Zhang 
216228d0997cSElaine Zhang 	rk3588_clk_init(priv);
216328d0997cSElaine Zhang 
216428d0997cSElaine Zhang 	/* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
216528d0997cSElaine Zhang 	ret = clk_set_defaults(dev);
216628d0997cSElaine Zhang 	if (ret)
216728d0997cSElaine Zhang 		debug("%s clk_set_defaults failed %d\n", __func__, ret);
216828d0997cSElaine Zhang 	else
216928d0997cSElaine Zhang 		priv->sync_kernel = true;
217028d0997cSElaine Zhang 
217128d0997cSElaine Zhang 	return 0;
217228d0997cSElaine Zhang }
217328d0997cSElaine Zhang 
rk3588_clk_ofdata_to_platdata(struct udevice * dev)217428d0997cSElaine Zhang static int rk3588_clk_ofdata_to_platdata(struct udevice *dev)
217528d0997cSElaine Zhang {
217628d0997cSElaine Zhang 	struct rk3588_clk_priv *priv = dev_get_priv(dev);
217728d0997cSElaine Zhang 
217828d0997cSElaine Zhang 	priv->cru = dev_read_addr_ptr(dev);
217928d0997cSElaine Zhang 
218028d0997cSElaine Zhang 	return 0;
218128d0997cSElaine Zhang }
218228d0997cSElaine Zhang 
rk3588_clk_bind(struct udevice * dev)218328d0997cSElaine Zhang static int rk3588_clk_bind(struct udevice *dev)
218428d0997cSElaine Zhang {
218528d0997cSElaine Zhang 	int ret;
218628d0997cSElaine Zhang 	struct udevice *sys_child, *sf_child;
218728d0997cSElaine Zhang 	struct sysreset_reg *priv;
218828d0997cSElaine Zhang 	struct softreset_reg *sf_priv;
218928d0997cSElaine Zhang 
219028d0997cSElaine Zhang 	/* The reset driver does not have a device node, so bind it here */
219128d0997cSElaine Zhang 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
219228d0997cSElaine Zhang 				 &sys_child);
219328d0997cSElaine Zhang 	if (ret) {
219428d0997cSElaine Zhang 		debug("Warning: No sysreset driver: ret=%d\n", ret);
219528d0997cSElaine Zhang 	} else {
219628d0997cSElaine Zhang 		priv = malloc(sizeof(struct sysreset_reg));
219728d0997cSElaine Zhang 		priv->glb_srst_fst_value = offsetof(struct rk3588_cru,
219828d0997cSElaine Zhang 						    glb_srst_fst);
219928d0997cSElaine Zhang 		priv->glb_srst_snd_value = offsetof(struct rk3588_cru,
220028d0997cSElaine Zhang 						    glb_srsr_snd);
220128d0997cSElaine Zhang 		sys_child->priv = priv;
220228d0997cSElaine Zhang 	}
220328d0997cSElaine Zhang 
220428d0997cSElaine Zhang 	ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
220528d0997cSElaine Zhang 					 dev_ofnode(dev), &sf_child);
220628d0997cSElaine Zhang 	if (ret) {
220728d0997cSElaine Zhang 		debug("Warning: No rockchip reset driver: ret=%d\n", ret);
220828d0997cSElaine Zhang 	} else {
220928d0997cSElaine Zhang 		sf_priv = malloc(sizeof(struct softreset_reg));
221028d0997cSElaine Zhang 		sf_priv->sf_reset_offset = offsetof(struct rk3588_cru,
221128d0997cSElaine Zhang 						    softrst_con[0]);
221228d0997cSElaine Zhang 		sf_priv->sf_reset_num = 49158;
221328d0997cSElaine Zhang 		sf_child->priv = sf_priv;
221428d0997cSElaine Zhang 	}
221528d0997cSElaine Zhang 
221628d0997cSElaine Zhang 	return 0;
221728d0997cSElaine Zhang }
221828d0997cSElaine Zhang 
221928d0997cSElaine Zhang static const struct udevice_id rk3588_clk_ids[] = {
222028d0997cSElaine Zhang 	{ .compatible = "rockchip,rk3588-cru" },
222128d0997cSElaine Zhang 	{ }
222228d0997cSElaine Zhang };
222328d0997cSElaine Zhang 
222428d0997cSElaine Zhang U_BOOT_DRIVER(rockchip_rk3588_cru) = {
222528d0997cSElaine Zhang 	.name		= "rockchip_rk3588_cru",
222628d0997cSElaine Zhang 	.id		= UCLASS_CLK,
222728d0997cSElaine Zhang 	.of_match	= rk3588_clk_ids,
222828d0997cSElaine Zhang 	.priv_auto_alloc_size = sizeof(struct rk3588_clk_priv),
222928d0997cSElaine Zhang 	.ofdata_to_platdata = rk3588_clk_ofdata_to_platdata,
223028d0997cSElaine Zhang 	.ops		= &rk3588_clk_ops,
223128d0997cSElaine Zhang 	.bind		= rk3588_clk_bind,
223228d0997cSElaine Zhang 	.probe		= rk3588_clk_probe,
223328d0997cSElaine Zhang };
223428d0997cSElaine Zhang 
223554b0a818SElaine Zhang #ifdef CONFIG_SPL_BUILD
223654b0a818SElaine Zhang #define SCRU_BASE			0xfd7d0000
223754b0a818SElaine Zhang #define BUSSCRU_BASE			0xfd7d8000
223854b0a818SElaine Zhang #define GPLL_RATE			1188000000
223954b0a818SElaine Zhang #define SPLL_RATE			702000000
224054b0a818SElaine Zhang 
224154b0a818SElaine Zhang #ifndef BITS_WITH_WMASK
224254b0a818SElaine Zhang #define BITS_WITH_WMASK(bits, msk, shift) \
224354b0a818SElaine Zhang 	((bits) << (shift)) | ((msk) << ((shift) + 16))
224454b0a818SElaine Zhang #endif
224554b0a818SElaine Zhang 
224654b0a818SElaine Zhang #define CLKDIV_6BITS_SHF(div, shift)	BITS_WITH_WMASK(div, 0x3fU, shift)
224754b0a818SElaine Zhang #define CLKDIV_5BITS_SHF(div, shift)	BITS_WITH_WMASK(div, 0x1fU, shift)
224854b0a818SElaine Zhang 
rk3588_clk_scmi_get_rate(struct clk * clk)224954b0a818SElaine Zhang static ulong rk3588_clk_scmi_get_rate(struct clk *clk)
225054b0a818SElaine Zhang {
225154b0a818SElaine Zhang 	u32 src, div;
225254b0a818SElaine Zhang 
225354b0a818SElaine Zhang 	switch (clk->id) {
225454b0a818SElaine Zhang 	case SCMI_SPLL:
225554b0a818SElaine Zhang 		src = readl(BUSSCRU_BASE + RK3588_MODE_CON0) & 0x3;
225654b0a818SElaine Zhang 		if (src == 0)
225754b0a818SElaine Zhang 			return OSC_HZ;
225854b0a818SElaine Zhang 		else if (src == 1)
225954b0a818SElaine Zhang 			return 702 * MHz;
226054b0a818SElaine Zhang 		else
226154b0a818SElaine Zhang 			return 32768;
226254b0a818SElaine Zhang 	case SCMI_CCLK_SD:
226354b0a818SElaine Zhang 		src = readl(SCRU_BASE + RK3588_CLKSEL_CON(3)) & 0x3000;
226454b0a818SElaine Zhang 		src = src >> 12;
226554b0a818SElaine Zhang 		div = readl(SCRU_BASE + RK3588_CLKSEL_CON(3)) & 0x0fc0;
226654b0a818SElaine Zhang 		div = div >> 6;
226754b0a818SElaine Zhang 		if (src == 1)
226854b0a818SElaine Zhang 			return SPLL_RATE / (div + 1);
226954b0a818SElaine Zhang 		else if (src == 2)
227054b0a818SElaine Zhang 			return OSC_HZ / (div + 1);
227154b0a818SElaine Zhang 		else
227254b0a818SElaine Zhang 			return GPLL_RATE / (div + 1);
227354b0a818SElaine Zhang 	case SCMI_DCLK_SD:
227454b0a818SElaine Zhang 		src = readl(SCRU_BASE + RK3588_CLKSEL_CON(3)) & 0x0020;
227554b0a818SElaine Zhang 		div = readl(SCRU_BASE + RK3588_CLKSEL_CON(3)) & 0x001f;
227654b0a818SElaine Zhang 		if (src)
227754b0a818SElaine Zhang 			return SPLL_RATE / (div + 1);
227854b0a818SElaine Zhang 		else
227954b0a818SElaine Zhang 			return GPLL_RATE / (div + 1);
228054b0a818SElaine Zhang 	case SCMI_CRYPTO_RNG:
228154b0a818SElaine Zhang 		src = readl(SCRU_BASE + RK3588_CLKSEL_CON(1)) & 0xc000;
228254b0a818SElaine Zhang 		src = src >> 14;
228354b0a818SElaine Zhang 		if (src == 0)
228454b0a818SElaine Zhang 			return 175 * MHz;
228554b0a818SElaine Zhang 		else if (src == 1)
228654b0a818SElaine Zhang 			return 116 * MHz;
228754b0a818SElaine Zhang 		else if (src == 2)
228854b0a818SElaine Zhang 			return 58 * MHz;
228954b0a818SElaine Zhang 		else
229054b0a818SElaine Zhang 			return OSC_HZ;
229154b0a818SElaine Zhang 	case SCMI_CRYPTO_CORE:
229254b0a818SElaine Zhang 		src = readl(SCRU_BASE + RK3588_CLKSEL_CON(1)) & 0x0c00;
229354b0a818SElaine Zhang 		src = src >> 10;
229454b0a818SElaine Zhang 		if (src == 0)
229554b0a818SElaine Zhang 			return 350 * MHz;
229654b0a818SElaine Zhang 		else if (src == 1)
229754b0a818SElaine Zhang 			return 233 * MHz;
229854b0a818SElaine Zhang 		else if (src == 2)
229954b0a818SElaine Zhang 			return 116 * MHz;
230054b0a818SElaine Zhang 		else
230154b0a818SElaine Zhang 			return OSC_HZ;
230254b0a818SElaine Zhang 	case SCMI_CRYPTO_PKA:
230354b0a818SElaine Zhang 		src = readl(SCRU_BASE + RK3588_CLKSEL_CON(1)) & 0x3000;
230454b0a818SElaine Zhang 		src = src >> 12;
230554b0a818SElaine Zhang 		if (src == 0)
230654b0a818SElaine Zhang 			return 350 * MHz;
230754b0a818SElaine Zhang 		else if (src == 1)
230854b0a818SElaine Zhang 			return 233 * MHz;
230954b0a818SElaine Zhang 		else if (src == 2)
231054b0a818SElaine Zhang 			return 116 * MHz;
231154b0a818SElaine Zhang 		else
231254b0a818SElaine Zhang 			return OSC_HZ;
231354b0a818SElaine Zhang 	case SCMI_KEYLADDER_CORE:
231454b0a818SElaine Zhang 		src = readl(SCRU_BASE + RK3588_CLKSEL_CON(2)) & 0x00c0;
231554b0a818SElaine Zhang 		src = src >> 6;
231654b0a818SElaine Zhang 		if (src == 0)
231754b0a818SElaine Zhang 			return 350 * MHz;
231854b0a818SElaine Zhang 		else if (src == 1)
231954b0a818SElaine Zhang 			return 233 * MHz;
232054b0a818SElaine Zhang 		else if (src == 2)
232154b0a818SElaine Zhang 			return 116 * MHz;
232254b0a818SElaine Zhang 		else
232354b0a818SElaine Zhang 			return OSC_HZ;
232454b0a818SElaine Zhang 	case SCMI_KEYLADDER_RNG:
232554b0a818SElaine Zhang 		src = readl(SCRU_BASE + RK3588_CLKSEL_CON(2)) & 0x0300;
232654b0a818SElaine Zhang 		src = src >> 8;
232754b0a818SElaine Zhang 		if (src == 0)
232854b0a818SElaine Zhang 			return 175 * MHz;
232954b0a818SElaine Zhang 		else if (src == 1)
233054b0a818SElaine Zhang 			return 116 * MHz;
233154b0a818SElaine Zhang 		else if (src == 2)
233254b0a818SElaine Zhang 			return 58 * MHz;
233354b0a818SElaine Zhang 		else
233454b0a818SElaine Zhang 			return OSC_HZ;
233554b0a818SElaine Zhang 	case SCMI_TCLK_WDT:
233654b0a818SElaine Zhang 		return OSC_HZ;
233754b0a818SElaine Zhang 	case SCMI_HCLK_SD:
233854b0a818SElaine Zhang 	case SCMI_HCLK_SECURE_NS:
233954b0a818SElaine Zhang 		src = readl(SCRU_BASE + RK3588_CLKSEL_CON(1)) & 0x000c;
234054b0a818SElaine Zhang 		src = src >> 2;
234154b0a818SElaine Zhang 		if (src == 0)
234254b0a818SElaine Zhang 			return 150 * MHz;
234354b0a818SElaine Zhang 		else if (src == 1)
234454b0a818SElaine Zhang 			return 100 * MHz;
234554b0a818SElaine Zhang 		else if (src == 2)
234654b0a818SElaine Zhang 			return 50 * MHz;
234754b0a818SElaine Zhang 		else
234854b0a818SElaine Zhang 			return OSC_HZ;
234954b0a818SElaine Zhang 	default:
235054b0a818SElaine Zhang 		return -ENOENT;
235154b0a818SElaine Zhang 	}
235254b0a818SElaine Zhang };
235354b0a818SElaine Zhang 
rk3588_clk_scmi_set_rate(struct clk * clk,ulong rate)235454b0a818SElaine Zhang static ulong rk3588_clk_scmi_set_rate(struct clk *clk, ulong rate)
235554b0a818SElaine Zhang {
235654b0a818SElaine Zhang 	u32 src, div;
235754b0a818SElaine Zhang 
2358372f827aSElaine Zhang 	if ((readl(BUSSCRU_BASE + RK3588_PLL_CON(137)) & 0x01c0) == 0xc0) {
2359372f827aSElaine Zhang 		writel(BITS_WITH_WMASK(0, 0x3U, 0),
2360372f827aSElaine Zhang 			BUSSCRU_BASE + RK3588_MODE_CON0);
2361372f827aSElaine Zhang 		writel(BITS_WITH_WMASK(2, 0x7U, 6),
2362372f827aSElaine Zhang 			BUSSCRU_BASE + RK3588_PLL_CON(137));
2363372f827aSElaine Zhang 		writel(BITS_WITH_WMASK(1, 0x3U, 0),
2364372f827aSElaine Zhang 		       BUSSCRU_BASE + RK3588_MODE_CON0);
2365372f827aSElaine Zhang 	}
2366372f827aSElaine Zhang 
236754b0a818SElaine Zhang 	switch (clk->id) {
236854b0a818SElaine Zhang 	case SCMI_SPLL:
236954b0a818SElaine Zhang 		if (rate >= 700 * MHz)
237054b0a818SElaine Zhang 			src = 1;
237154b0a818SElaine Zhang 		else
237254b0a818SElaine Zhang 			src = 0;
2373372f827aSElaine Zhang 		writel(BITS_WITH_WMASK(0, 0x3U, 0),
2374372f827aSElaine Zhang 			BUSSCRU_BASE + RK3588_MODE_CON0);
2375372f827aSElaine Zhang 		writel(BITS_WITH_WMASK(2, 0x7U, 6),
2376372f827aSElaine Zhang 			BUSSCRU_BASE + RK3588_PLL_CON(137));
237754b0a818SElaine Zhang 		writel(BITS_WITH_WMASK(src, 0x3U, 0),
237854b0a818SElaine Zhang 		       BUSSCRU_BASE + RK3588_MODE_CON0);
237954b0a818SElaine Zhang 		break;
238054b0a818SElaine Zhang 	case SCMI_CCLK_SD:
238154b0a818SElaine Zhang 		if ((OSC_HZ % rate) == 0) {
238254b0a818SElaine Zhang 			div = DIV_ROUND_UP(OSC_HZ, rate);
238354b0a818SElaine Zhang 			writel(CLKDIV_6BITS_SHF(div - 1, 6) |
238454b0a818SElaine Zhang 			       BITS_WITH_WMASK(2U, 0x3U, 12),
238554b0a818SElaine Zhang 			       SCRU_BASE + RK3588_CLKSEL_CON(3));
238654b0a818SElaine Zhang 		} else if ((SPLL_RATE % rate) == 0) {
238754b0a818SElaine Zhang 			div = DIV_ROUND_UP(SPLL_RATE, rate);
238854b0a818SElaine Zhang 			writel(CLKDIV_6BITS_SHF(div - 1, 6) |
238954b0a818SElaine Zhang 			       BITS_WITH_WMASK(1U, 0x3U, 12),
239054b0a818SElaine Zhang 			       SCRU_BASE + RK3588_CLKSEL_CON(3));
239154b0a818SElaine Zhang 		} else {
239254b0a818SElaine Zhang 			div = DIV_ROUND_UP(GPLL_RATE, rate);
239354b0a818SElaine Zhang 			writel(CLKDIV_6BITS_SHF(div - 1, 6) |
239454b0a818SElaine Zhang 			       BITS_WITH_WMASK(0U, 0x3U, 12),
239554b0a818SElaine Zhang 			       SCRU_BASE + RK3588_CLKSEL_CON(3));
239654b0a818SElaine Zhang 		}
239754b0a818SElaine Zhang 		break;
239854b0a818SElaine Zhang 	case SCMI_DCLK_SD:
239954b0a818SElaine Zhang 		if ((SPLL_RATE % rate) == 0) {
240054b0a818SElaine Zhang 			div = DIV_ROUND_UP(SPLL_RATE, rate);
240154b0a818SElaine Zhang 			writel(CLKDIV_5BITS_SHF(div - 1, 0) |
240254b0a818SElaine Zhang 			       BITS_WITH_WMASK(1U, 0x1U, 5),
240354b0a818SElaine Zhang 			       SCRU_BASE + RK3588_CLKSEL_CON(3));
240454b0a818SElaine Zhang 		} else {
240554b0a818SElaine Zhang 			div = DIV_ROUND_UP(GPLL_RATE, rate);
240654b0a818SElaine Zhang 			writel(CLKDIV_5BITS_SHF(div - 1, 0) |
240754b0a818SElaine Zhang 			       BITS_WITH_WMASK(0U, 0x1U, 5),
240854b0a818SElaine Zhang 			       SCRU_BASE + RK3588_CLKSEL_CON(3));
240954b0a818SElaine Zhang 		}
241054b0a818SElaine Zhang 		break;
241154b0a818SElaine Zhang 	case SCMI_CRYPTO_RNG:
241254b0a818SElaine Zhang 		if (rate >= 175 * MHz)
241354b0a818SElaine Zhang 			src = 0;
241454b0a818SElaine Zhang 		else if (rate >= 116 * MHz)
241554b0a818SElaine Zhang 			src = 1;
241654b0a818SElaine Zhang 		else if (rate >= 58 * MHz)
241754b0a818SElaine Zhang 			src = 2;
241854b0a818SElaine Zhang 		else
241954b0a818SElaine Zhang 			src = 3;
242054b0a818SElaine Zhang 
242154b0a818SElaine Zhang 		writel(BITS_WITH_WMASK(src, 0x3U, 14),
242254b0a818SElaine Zhang 		       SCRU_BASE + RK3588_CLKSEL_CON(1));
242354b0a818SElaine Zhang 		break;
242454b0a818SElaine Zhang 	case SCMI_CRYPTO_CORE:
242554b0a818SElaine Zhang 		if (rate >= 350 * MHz)
242654b0a818SElaine Zhang 			src = 0;
242754b0a818SElaine Zhang 		else if (rate >= 233 * MHz)
242854b0a818SElaine Zhang 			src = 1;
242954b0a818SElaine Zhang 		else if (rate >= 116 * MHz)
243054b0a818SElaine Zhang 			src = 2;
243154b0a818SElaine Zhang 		else
243254b0a818SElaine Zhang 			src = 3;
243354b0a818SElaine Zhang 
243454b0a818SElaine Zhang 		writel(BITS_WITH_WMASK(src, 0x3U, 10),
243554b0a818SElaine Zhang 		       SCRU_BASE + RK3588_CLKSEL_CON(1));
243654b0a818SElaine Zhang 		break;
243754b0a818SElaine Zhang 	case SCMI_CRYPTO_PKA:
243854b0a818SElaine Zhang 		if (rate >= 350 * MHz)
243954b0a818SElaine Zhang 			src = 0;
244054b0a818SElaine Zhang 		else if (rate >= 233 * MHz)
244154b0a818SElaine Zhang 			src = 1;
244254b0a818SElaine Zhang 		else if (rate >= 116 * MHz)
244354b0a818SElaine Zhang 			src = 2;
244454b0a818SElaine Zhang 		else
244554b0a818SElaine Zhang 			src = 3;
244654b0a818SElaine Zhang 
244754b0a818SElaine Zhang 		writel(BITS_WITH_WMASK(src, 0x3U, 12),
244854b0a818SElaine Zhang 		       SCRU_BASE + RK3588_CLKSEL_CON(1));
244954b0a818SElaine Zhang 		break;
245054b0a818SElaine Zhang 	case SCMI_KEYLADDER_CORE:
245154b0a818SElaine Zhang 		if (rate >= 350 * MHz)
245254b0a818SElaine Zhang 			src = 0;
245354b0a818SElaine Zhang 		else if (rate >= 233 * MHz)
245454b0a818SElaine Zhang 			src = 1;
245554b0a818SElaine Zhang 		else if (rate >= 116 * MHz)
245654b0a818SElaine Zhang 			src = 2;
245754b0a818SElaine Zhang 		else
245854b0a818SElaine Zhang 			src = 3;
245954b0a818SElaine Zhang 
246054b0a818SElaine Zhang 		writel(BITS_WITH_WMASK(src, 0x3U, 6),
246154b0a818SElaine Zhang 		       SCRU_BASE + RK3588_CLKSEL_CON(2));
246254b0a818SElaine Zhang 		break;
246354b0a818SElaine Zhang 	case SCMI_KEYLADDER_RNG:
246454b0a818SElaine Zhang 		if (rate >= 175 * MHz)
246554b0a818SElaine Zhang 			src = 0;
246654b0a818SElaine Zhang 		else if (rate >= 116 * MHz)
246754b0a818SElaine Zhang 			src = 1;
246854b0a818SElaine Zhang 		else if (rate >= 58 * MHz)
246954b0a818SElaine Zhang 			src = 2;
247054b0a818SElaine Zhang 		else
247154b0a818SElaine Zhang 			src = 3;
247254b0a818SElaine Zhang 
247354b0a818SElaine Zhang 		writel(BITS_WITH_WMASK(src, 0x3U, 8),
247454b0a818SElaine Zhang 		       SCRU_BASE + RK3588_CLKSEL_CON(2));
247554b0a818SElaine Zhang 		break;
247654b0a818SElaine Zhang 	case SCMI_TCLK_WDT:
247754b0a818SElaine Zhang 		break;
247854b0a818SElaine Zhang 	case SCMI_HCLK_SD:
247954b0a818SElaine Zhang 	case SCMI_HCLK_SECURE_NS:
248054b0a818SElaine Zhang 		if (rate >= 150 * MHz)
248154b0a818SElaine Zhang 			src = 0;
248254b0a818SElaine Zhang 		else if (rate >= 100 * MHz)
248354b0a818SElaine Zhang 			src = 1;
248454b0a818SElaine Zhang 		else if (rate >= 50 * MHz)
248554b0a818SElaine Zhang 			src = 2;
248654b0a818SElaine Zhang 		else
248754b0a818SElaine Zhang 			src = 3;
248854b0a818SElaine Zhang 		writel(BITS_WITH_WMASK(src, 0x3U, 2),
248954b0a818SElaine Zhang 		       SCRU_BASE + RK3588_CLKSEL_CON(1));
249054b0a818SElaine Zhang 		break;
249154b0a818SElaine Zhang 	default:
249254b0a818SElaine Zhang 		return -ENOENT;
249354b0a818SElaine Zhang 	}
249454b0a818SElaine Zhang 	return 0;
249554b0a818SElaine Zhang };
249654b0a818SElaine Zhang 
249754b0a818SElaine Zhang /* A fake scmi driver for SPL/TPL where smccc agent is not available. */
249854b0a818SElaine Zhang static const struct clk_ops scmi_clk_ops = {
249954b0a818SElaine Zhang 	.get_rate = rk3588_clk_scmi_get_rate,
250054b0a818SElaine Zhang 	.set_rate = rk3588_clk_scmi_set_rate,
250154b0a818SElaine Zhang };
250254b0a818SElaine Zhang 
250354b0a818SElaine Zhang U_BOOT_DRIVER(scmi_clock) = {
250454b0a818SElaine Zhang 	.name = "scmi_clk",
250554b0a818SElaine Zhang 	.id = UCLASS_CLK,
250654b0a818SElaine Zhang 	.ops = &scmi_clk_ops,
250754b0a818SElaine Zhang };
250854b0a818SElaine Zhang #endif
250954b0a818SElaine Zhang 
251028d0997cSElaine Zhang #ifndef CONFIG_SPL_BUILD
251128d0997cSElaine Zhang /**
251228d0997cSElaine Zhang  * soc_clk_dump() - Print clock frequencies
251328d0997cSElaine Zhang  * Returns zero on success
251428d0997cSElaine Zhang  *
251528d0997cSElaine Zhang  * Implementation for the clk dump command.
251628d0997cSElaine Zhang  */
soc_clk_dump(void)251728d0997cSElaine Zhang int soc_clk_dump(void)
251828d0997cSElaine Zhang {
251928d0997cSElaine Zhang 	struct udevice *cru_dev;
252028d0997cSElaine Zhang 	struct rk3588_clk_priv *priv;
252128d0997cSElaine Zhang 	const struct rk3588_clk_info *clk_dump;
252228d0997cSElaine Zhang 	struct clk clk;
252328d0997cSElaine Zhang 	unsigned long clk_count = ARRAY_SIZE(clks_dump);
252428d0997cSElaine Zhang 	unsigned long rate;
252528d0997cSElaine Zhang 	int i, ret;
252628d0997cSElaine Zhang 
252728d0997cSElaine Zhang 	ret = uclass_get_device_by_driver(UCLASS_CLK,
252828d0997cSElaine Zhang 					  DM_GET_DRIVER(rockchip_rk3588_cru),
252928d0997cSElaine Zhang 					  &cru_dev);
253028d0997cSElaine Zhang 	if (ret) {
253128d0997cSElaine Zhang 		printf("%s failed to get cru device\n", __func__);
253228d0997cSElaine Zhang 		return ret;
253328d0997cSElaine Zhang 	}
253428d0997cSElaine Zhang 
253528d0997cSElaine Zhang 	priv = dev_get_priv(cru_dev);
253628d0997cSElaine Zhang 	printf("CLK: (%s. arm: enter %lu KHz, init %lu KHz, kernel %lu%s)\n",
253728d0997cSElaine Zhang 	       priv->sync_kernel ? "sync kernel" : "uboot",
253828d0997cSElaine Zhang 	       priv->armclk_enter_hz / 1000,
253928d0997cSElaine Zhang 	       priv->armclk_init_hz / 1000,
254028d0997cSElaine Zhang 	       priv->set_armclk_rate ? priv->armclk_hz / 1000 : 0,
254128d0997cSElaine Zhang 	       priv->set_armclk_rate ? " KHz" : "N/A");
254228d0997cSElaine Zhang 	for (i = 0; i < clk_count; i++) {
254328d0997cSElaine Zhang 		clk_dump = &clks_dump[i];
254428d0997cSElaine Zhang 		if (clk_dump->name) {
254547abc771SJianqun Xu 			memset(&clk, 0, sizeof(struct clk));
254628d0997cSElaine Zhang 			clk.id = clk_dump->id;
254728d0997cSElaine Zhang 			if (clk_dump->is_cru)
254828d0997cSElaine Zhang 				ret = clk_request(cru_dev, &clk);
254928d0997cSElaine Zhang 			if (ret < 0)
255028d0997cSElaine Zhang 				return ret;
255128d0997cSElaine Zhang 
255228d0997cSElaine Zhang 			rate = clk_get_rate(&clk);
255328d0997cSElaine Zhang 			clk_free(&clk);
255428d0997cSElaine Zhang 			if (rate < 0)
255528d0997cSElaine Zhang 				printf("  %s %s\n", clk_dump->name,
255628d0997cSElaine Zhang 				       "unknown");
255728d0997cSElaine Zhang 			else
255828d0997cSElaine Zhang 				printf("  %s %lu KHz\n", clk_dump->name,
255928d0997cSElaine Zhang 				       rate / 1000);
256028d0997cSElaine Zhang 		}
256128d0997cSElaine Zhang 	}
256228d0997cSElaine Zhang 
256328d0997cSElaine Zhang 	return 0;
256428d0997cSElaine Zhang }
256528d0997cSElaine Zhang #endif
2566