xref: /OK3568_Linux_fs/u-boot/drivers/clk/rockchip/clk_rk3562.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (c) 2022 Rockchip Electronics Co., Ltd
4*4882a593Smuzhiyun  * Author: Finley Xiao <finley.xiao@rock-chips.com>
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun #include <common.h>
8*4882a593Smuzhiyun #include <clk-uclass.h>
9*4882a593Smuzhiyun #include <dm.h>
10*4882a593Smuzhiyun #include <syscon.h>
11*4882a593Smuzhiyun #include <asm/arch/clock.h>
12*4882a593Smuzhiyun #include <asm/arch/cru_rk3562.h>
13*4882a593Smuzhiyun #include <asm/arch/hardware.h>
14*4882a593Smuzhiyun #include <asm/io.h>
15*4882a593Smuzhiyun #include <dm/lists.h>
16*4882a593Smuzhiyun #include <dt-bindings/clock/rk3562-cru.h>
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun #define DIV_TO_RATE(input_rate, div)    ((input_rate) / ((div) + 1))
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun static struct rockchip_pll_rate_table rk3562_pll_rates[] = {
23*4882a593Smuzhiyun 	/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
24*4882a593Smuzhiyun 	RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0),
25*4882a593Smuzhiyun 	RK3036_PLL_RATE(1416000000, 1, 118, 2, 1, 1, 0),
26*4882a593Smuzhiyun 	RK3036_PLL_RATE(1296000000, 1, 108, 2, 1, 1, 0),
27*4882a593Smuzhiyun 	RK3036_PLL_RATE(1200000000, 1, 100, 2, 1, 1, 0),
28*4882a593Smuzhiyun 	RK3036_PLL_RATE(1188000000, 1, 99, 2, 1, 1, 0),
29*4882a593Smuzhiyun 	RK3036_PLL_RATE(1104000000, 1, 92, 2, 1, 1, 0),
30*4882a593Smuzhiyun 	RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
31*4882a593Smuzhiyun 	RK3036_PLL_RATE(1000000000, 3, 250, 2, 1, 1, 0),
32*4882a593Smuzhiyun 	RK3036_PLL_RATE(912000000, 1, 76, 2, 1, 1, 0),
33*4882a593Smuzhiyun 	RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0),
34*4882a593Smuzhiyun 	RK3036_PLL_RATE(600000000, 1, 100, 4, 1, 1, 0),
35*4882a593Smuzhiyun 	RK3036_PLL_RATE(594000000, 1, 99, 4, 1, 1, 0),
36*4882a593Smuzhiyun 	RK3036_PLL_RATE(500000000, 1, 125, 6, 1, 1, 0),
37*4882a593Smuzhiyun 	RK3036_PLL_RATE(408000000, 1, 68, 2, 2, 1, 0),
38*4882a593Smuzhiyun 	RK3036_PLL_RATE(312000000, 1, 78, 6, 1, 1, 0),
39*4882a593Smuzhiyun 	RK3036_PLL_RATE(216000000, 1, 72, 4, 2, 1, 0),
40*4882a593Smuzhiyun 	RK3036_PLL_RATE(96000000, 1, 96, 6, 4, 1, 0),
41*4882a593Smuzhiyun 	{ /* sentinel */ },
42*4882a593Smuzhiyun };
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun static struct rockchip_pll_clock rk3562_pll_clks[] = {
45*4882a593Smuzhiyun 	[APLL] = PLL(pll_rk3328, PLL_APLL, RK3562_PLL_CON(0),
46*4882a593Smuzhiyun 		     RK3562_MODE_CON, 0, 10, 0, rk3562_pll_rates),
47*4882a593Smuzhiyun 	[GPLL] = PLL(pll_rk3328, PLL_GPLL, RK3562_PLL_CON(24),
48*4882a593Smuzhiyun 		     RK3562_MODE_CON, 2, 10, 0, rk3562_pll_rates),
49*4882a593Smuzhiyun 	[VPLL] = PLL(pll_rk3328, PLL_VPLL, RK3562_PLL_CON(32),
50*4882a593Smuzhiyun 		     RK3562_MODE_CON, 6, 10, 0, rk3562_pll_rates),
51*4882a593Smuzhiyun 	[HPLL] = PLL(pll_rk3328, PLL_HPLL, RK3562_PLL_CON(40),
52*4882a593Smuzhiyun 		     RK3562_MODE_CON, 8, 10, 0, rk3562_pll_rates),
53*4882a593Smuzhiyun 	[CPLL] = PLL(pll_rk3328, PLL_CPLL, RK3562_PMU1_PLL_CON(0),
54*4882a593Smuzhiyun 		     RK3562_PMU1_MODE_CON, 0, 10, 0, rk3562_pll_rates),
55*4882a593Smuzhiyun 	[DPLL] = PLL(pll_rk3328, PLL_DPLL, RK3562_SUBDDR_PLL_CON(0),
56*4882a593Smuzhiyun 		     RK3562_SUBDDR_MODE_CON, 0, 10, 0, NULL),
57*4882a593Smuzhiyun };
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun #define RK3562_CPUCLK_RATE(_rate, _aclk_m_core, _pclk_dbg)	\
60*4882a593Smuzhiyun {								\
61*4882a593Smuzhiyun 	.rate = _rate##U,					\
62*4882a593Smuzhiyun 	.aclk_div = _aclk_m_core,				\
63*4882a593Smuzhiyun 	.pclk_div = _pclk_dbg,					\
64*4882a593Smuzhiyun }
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun static struct rockchip_cpu_rate_table rk3562_cpu_rates[] = {
67*4882a593Smuzhiyun 	RK3562_CPUCLK_RATE(1416000000, 1, 8),
68*4882a593Smuzhiyun 	RK3562_CPUCLK_RATE(1296000000, 1, 8),
69*4882a593Smuzhiyun 	RK3562_CPUCLK_RATE(1200000000, 1, 8),
70*4882a593Smuzhiyun 	RK3562_CPUCLK_RATE(1104000000, 1, 8),
71*4882a593Smuzhiyun 	RK3562_CPUCLK_RATE(1008000000, 1, 8),
72*4882a593Smuzhiyun 	RK3562_CPUCLK_RATE(912000000, 1, 6),
73*4882a593Smuzhiyun 	RK3562_CPUCLK_RATE(816000000, 1, 6),
74*4882a593Smuzhiyun 	RK3562_CPUCLK_RATE(600000000, 1, 6),
75*4882a593Smuzhiyun 	RK3562_CPUCLK_RATE(408000000, 1, 4),
76*4882a593Smuzhiyun 	{ /* sentinel */ },
77*4882a593Smuzhiyun };
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun #ifndef CONFIG_SPL_BUILD
80*4882a593Smuzhiyun #define RK3562_CLK_DUMP(_id, _name)		\
81*4882a593Smuzhiyun {						\
82*4882a593Smuzhiyun 	.id = _id,				\
83*4882a593Smuzhiyun 	.name = _name,				\
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun static const struct rk3562_clk_info clks_dump[] = {
87*4882a593Smuzhiyun 	RK3562_CLK_DUMP(PLL_APLL, "apll"),
88*4882a593Smuzhiyun 	RK3562_CLK_DUMP(PLL_GPLL, "gpll"),
89*4882a593Smuzhiyun 	RK3562_CLK_DUMP(PLL_VPLL, "vpll"),
90*4882a593Smuzhiyun 	RK3562_CLK_DUMP(PLL_HPLL, "hpll"),
91*4882a593Smuzhiyun 	RK3562_CLK_DUMP(PLL_CPLL, "cpll"),
92*4882a593Smuzhiyun 	RK3562_CLK_DUMP(PLL_DPLL, "dpll"),
93*4882a593Smuzhiyun 	RK3562_CLK_DUMP(ACLK_BUS, "aclk_bus"),
94*4882a593Smuzhiyun 	RK3562_CLK_DUMP(HCLK_BUS, "hclk_bus"),
95*4882a593Smuzhiyun 	RK3562_CLK_DUMP(PCLK_BUS, "pclk_bus"),
96*4882a593Smuzhiyun 	RK3562_CLK_DUMP(ACLK_PERI, "aclk_peri"),
97*4882a593Smuzhiyun 	RK3562_CLK_DUMP(HCLK_PERI, "hclk_peri"),
98*4882a593Smuzhiyun 	RK3562_CLK_DUMP(PCLK_PERI, "pclk_peri"),
99*4882a593Smuzhiyun };
100*4882a593Smuzhiyun #endif
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun /*
103*4882a593Smuzhiyun  *
104*4882a593Smuzhiyun  * rational_best_approximation(31415, 10000,
105*4882a593Smuzhiyun  *		(1 << 8) - 1, (1 << 5) - 1, &n, &d);
106*4882a593Smuzhiyun  *
107*4882a593Smuzhiyun  * you may look at given_numerator as a fixed point number,
108*4882a593Smuzhiyun  * with the fractional part size described in given_denominator.
109*4882a593Smuzhiyun  *
110*4882a593Smuzhiyun  * for theoretical background, see:
111*4882a593Smuzhiyun  * http://en.wikipedia.org/wiki/Continued_fraction
112*4882a593Smuzhiyun  */
rational_best_approximation(unsigned long given_numerator,unsigned long given_denominator,unsigned long max_numerator,unsigned long max_denominator,unsigned long * best_numerator,unsigned long * best_denominator)113*4882a593Smuzhiyun static void rational_best_approximation(unsigned long given_numerator,
114*4882a593Smuzhiyun 					unsigned long given_denominator,
115*4882a593Smuzhiyun 					unsigned long max_numerator,
116*4882a593Smuzhiyun 					unsigned long max_denominator,
117*4882a593Smuzhiyun 					unsigned long *best_numerator,
118*4882a593Smuzhiyun 					unsigned long *best_denominator)
119*4882a593Smuzhiyun {
120*4882a593Smuzhiyun 	unsigned long n, d, n0, d0, n1, d1;
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun 	n = given_numerator;
123*4882a593Smuzhiyun 	d = given_denominator;
124*4882a593Smuzhiyun 	n0 = 0;
125*4882a593Smuzhiyun 	d1 = 0;
126*4882a593Smuzhiyun 	n1 = 1;
127*4882a593Smuzhiyun 	d0 = 1;
128*4882a593Smuzhiyun 	for (;;) {
129*4882a593Smuzhiyun 		unsigned long t, a;
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 		if (n1 > max_numerator || d1 > max_denominator) {
132*4882a593Smuzhiyun 			n1 = n0;
133*4882a593Smuzhiyun 			d1 = d0;
134*4882a593Smuzhiyun 			break;
135*4882a593Smuzhiyun 		}
136*4882a593Smuzhiyun 		if (d == 0)
137*4882a593Smuzhiyun 			break;
138*4882a593Smuzhiyun 		t = d;
139*4882a593Smuzhiyun 		a = n / d;
140*4882a593Smuzhiyun 		d = n % d;
141*4882a593Smuzhiyun 		n = t;
142*4882a593Smuzhiyun 		t = n0 + a * n1;
143*4882a593Smuzhiyun 		n0 = n1;
144*4882a593Smuzhiyun 		n1 = t;
145*4882a593Smuzhiyun 		t = d0 + a * d1;
146*4882a593Smuzhiyun 		d0 = d1;
147*4882a593Smuzhiyun 		d1 = t;
148*4882a593Smuzhiyun 	}
149*4882a593Smuzhiyun 	*best_numerator = n1;
150*4882a593Smuzhiyun 	*best_denominator = d1;
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun 
rk3562_armclk_set_rate(struct rk3562_clk_priv * priv,ulong new_rate)153*4882a593Smuzhiyun static int rk3562_armclk_set_rate(struct rk3562_clk_priv *priv, ulong new_rate)
154*4882a593Smuzhiyun {
155*4882a593Smuzhiyun 	const struct rockchip_cpu_rate_table *rate;
156*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
157*4882a593Smuzhiyun 	ulong old_rate;
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 	rate = rockchip_get_cpu_settings(rk3562_cpu_rates, new_rate);
160*4882a593Smuzhiyun 	if (!rate) {
161*4882a593Smuzhiyun 		printf("%s unsupported rate\n", __func__);
162*4882a593Smuzhiyun 		return -EINVAL;
163*4882a593Smuzhiyun 	}
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun 	/*
166*4882a593Smuzhiyun 	 * set up dependent divisors for DBG and ACLK clocks.
167*4882a593Smuzhiyun 	 */
168*4882a593Smuzhiyun 	old_rate = rockchip_pll_get_rate(&rk3562_pll_clks[APLL], priv->cru,
169*4882a593Smuzhiyun 					 APLL);
170*4882a593Smuzhiyun 	if (old_rate == new_rate) {
171*4882a593Smuzhiyun 		rk_clrsetreg(&cru->clksel_con[11], ACLK_CORE_PRE_DIV_MASK,
172*4882a593Smuzhiyun 			     rate->aclk_div << ACLK_CORE_PRE_DIV_SHIFT);
173*4882a593Smuzhiyun 		rk_clrsetreg(&cru->clksel_con[12], PCLK_DBG_PRE_DIV_MASK,
174*4882a593Smuzhiyun 			     rate->pclk_div << PCLK_DBG_PRE_DIV_SHIFT);
175*4882a593Smuzhiyun 		rk_clrsetreg(&cru->clksel_con[10], CLK_CORE_PRE_DIV_MASK, 0);
176*4882a593Smuzhiyun 	} else if (old_rate > new_rate) {
177*4882a593Smuzhiyun 		if (rockchip_pll_set_rate(&rk3562_pll_clks[APLL],
178*4882a593Smuzhiyun 					  priv->cru, APLL, new_rate))
179*4882a593Smuzhiyun 			return -EINVAL;
180*4882a593Smuzhiyun 		rk_clrsetreg(&cru->clksel_con[11], ACLK_CORE_PRE_DIV_MASK,
181*4882a593Smuzhiyun 			     rate->aclk_div << ACLK_CORE_PRE_DIV_SHIFT);
182*4882a593Smuzhiyun 		rk_clrsetreg(&cru->clksel_con[12], PCLK_DBG_PRE_DIV_MASK,
183*4882a593Smuzhiyun 			     rate->pclk_div << PCLK_DBG_PRE_DIV_SHIFT);
184*4882a593Smuzhiyun 		rk_clrsetreg(&cru->clksel_con[10], CLK_CORE_PRE_DIV_MASK, 0);
185*4882a593Smuzhiyun 	} else if (old_rate < new_rate) {
186*4882a593Smuzhiyun 		rk_clrsetreg(&cru->clksel_con[11], ACLK_CORE_PRE_DIV_MASK,
187*4882a593Smuzhiyun 			     rate->aclk_div << ACLK_CORE_PRE_DIV_SHIFT);
188*4882a593Smuzhiyun 		rk_clrsetreg(&cru->clksel_con[12], PCLK_DBG_PRE_DIV_MASK,
189*4882a593Smuzhiyun 			     rate->pclk_div << PCLK_DBG_PRE_DIV_SHIFT);
190*4882a593Smuzhiyun 		rk_clrsetreg(&cru->clksel_con[10], CLK_CORE_PRE_DIV_MASK, 0);
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 		if (rockchip_pll_set_rate(&rk3562_pll_clks[APLL],
193*4882a593Smuzhiyun 					  priv->cru, APLL, new_rate))
194*4882a593Smuzhiyun 			return -EINVAL;
195*4882a593Smuzhiyun 	}
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	return 0;
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun 
rk3562_bus_get_rate(struct rk3562_clk_priv * priv,ulong clk_id)200*4882a593Smuzhiyun static ulong rk3562_bus_get_rate(struct rk3562_clk_priv *priv, ulong clk_id)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
203*4882a593Smuzhiyun 	u32 sel, con, div;
204*4882a593Smuzhiyun 	ulong rate;
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	switch (clk_id) {
207*4882a593Smuzhiyun 	case ACLK_BUS:
208*4882a593Smuzhiyun 		con = readl(&cru->clksel_con[40]);
209*4882a593Smuzhiyun 		sel = (con & ACLK_BUS_SEL_MASK) >> ACLK_BUS_SEL_SHIFT;
210*4882a593Smuzhiyun 		div = (con & ACLK_BUS_DIV_MASK) >> ACLK_BUS_DIV_SHIFT;
211*4882a593Smuzhiyun 		break;
212*4882a593Smuzhiyun 	case HCLK_BUS:
213*4882a593Smuzhiyun 		con = readl(&cru->clksel_con[40]);
214*4882a593Smuzhiyun 		sel = (con & HCLK_BUS_SEL_MASK) >> HCLK_BUS_SEL_SHIFT;
215*4882a593Smuzhiyun 		div = (con & HCLK_BUS_DIV_MASK) >> HCLK_BUS_DIV_SHIFT;
216*4882a593Smuzhiyun 		break;
217*4882a593Smuzhiyun 	case PCLK_BUS:
218*4882a593Smuzhiyun 		con = readl(&cru->clksel_con[41]);
219*4882a593Smuzhiyun 		sel = (con & PCLK_BUS_SEL_MASK) >> PCLK_BUS_SEL_SHIFT;
220*4882a593Smuzhiyun 		div = (con & PCLK_BUS_DIV_MASK) >> PCLK_BUS_DIV_SHIFT;
221*4882a593Smuzhiyun 		break;
222*4882a593Smuzhiyun 	default:
223*4882a593Smuzhiyun 		return -ENOENT;
224*4882a593Smuzhiyun 	}
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	if (sel == ACLK_BUS_SEL_CPLL)
227*4882a593Smuzhiyun 		rate = priv->cpll_hz;
228*4882a593Smuzhiyun 	else
229*4882a593Smuzhiyun 		rate = priv->gpll_hz;
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 	return DIV_TO_RATE(rate, div);
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun 
rk3562_bus_set_rate(struct rk3562_clk_priv * priv,ulong clk_id,ulong rate)234*4882a593Smuzhiyun static ulong rk3562_bus_set_rate(struct rk3562_clk_priv *priv, ulong clk_id,
235*4882a593Smuzhiyun 				 ulong rate)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
238*4882a593Smuzhiyun 	u32 sel, div;
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 	if (priv->cpll_hz % rate == 0) {
241*4882a593Smuzhiyun 		sel = ACLK_BUS_SEL_CPLL;
242*4882a593Smuzhiyun 		div = DIV_ROUND_UP(priv->cpll_hz, rate);
243*4882a593Smuzhiyun 	} else {
244*4882a593Smuzhiyun 		sel= ACLK_BUS_SEL_GPLL;
245*4882a593Smuzhiyun 		div = DIV_ROUND_UP(priv->gpll_hz, rate);
246*4882a593Smuzhiyun 	}
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	switch (clk_id) {
249*4882a593Smuzhiyun 	case ACLK_BUS:
250*4882a593Smuzhiyun 		rk_clrsetreg(&cru->clksel_con[40],
251*4882a593Smuzhiyun 			     ACLK_BUS_SEL_MASK | ACLK_BUS_DIV_MASK,
252*4882a593Smuzhiyun 			     (sel << ACLK_BUS_SEL_SHIFT) |
253*4882a593Smuzhiyun 			     ((div - 1) << ACLK_BUS_DIV_SHIFT));
254*4882a593Smuzhiyun 		break;
255*4882a593Smuzhiyun 	case HCLK_BUS:
256*4882a593Smuzhiyun 		rk_clrsetreg(&cru->clksel_con[40],
257*4882a593Smuzhiyun 			     HCLK_BUS_SEL_MASK | HCLK_BUS_DIV_MASK,
258*4882a593Smuzhiyun 			     (sel << HCLK_BUS_SEL_SHIFT) |
259*4882a593Smuzhiyun 			     ((div - 1) << HCLK_BUS_DIV_SHIFT));
260*4882a593Smuzhiyun 		break;
261*4882a593Smuzhiyun 	case PCLK_BUS:
262*4882a593Smuzhiyun 		rk_clrsetreg(&cru->clksel_con[41],
263*4882a593Smuzhiyun 			     PCLK_BUS_SEL_MASK | PCLK_BUS_DIV_MASK,
264*4882a593Smuzhiyun 			     (sel << PCLK_BUS_SEL_SHIFT) |
265*4882a593Smuzhiyun 			     ((div - 1) << PCLK_BUS_DIV_SHIFT));
266*4882a593Smuzhiyun 		break;
267*4882a593Smuzhiyun 	default:
268*4882a593Smuzhiyun 		return -ENOENT;
269*4882a593Smuzhiyun 	}
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 	return rk3562_bus_get_rate(priv, clk_id);
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun 
rk3562_peri_get_rate(struct rk3562_clk_priv * priv,ulong clk_id)274*4882a593Smuzhiyun static ulong rk3562_peri_get_rate(struct rk3562_clk_priv *priv, ulong clk_id)
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
277*4882a593Smuzhiyun 	u32 sel, con, div;
278*4882a593Smuzhiyun 	ulong rate;
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun 	switch (clk_id) {
281*4882a593Smuzhiyun 	case ACLK_PERI:
282*4882a593Smuzhiyun 		con = readl(&cru->periclksel_con[0]);
283*4882a593Smuzhiyun 		sel = (con & ACLK_PERI_SEL_MASK) >> ACLK_PERI_SEL_SHIFT;
284*4882a593Smuzhiyun 		div = (con & ACLK_PERI_DIV_MASK) >> ACLK_PERI_DIV_SHIFT;
285*4882a593Smuzhiyun 		break;
286*4882a593Smuzhiyun 	case HCLK_PERI:
287*4882a593Smuzhiyun 		con = readl(&cru->periclksel_con[0]);
288*4882a593Smuzhiyun 		sel = (con & HCLK_PERI_SEL_MASK) >> HCLK_PERI_SEL_SHIFT;
289*4882a593Smuzhiyun 		div = (con & HCLK_PERI_DIV_MASK) >> HCLK_PERI_DIV_SHIFT;
290*4882a593Smuzhiyun 		break;
291*4882a593Smuzhiyun 	case PCLK_PERI:
292*4882a593Smuzhiyun 		con = readl(&cru->periclksel_con[1]);
293*4882a593Smuzhiyun 		sel = (con & PCLK_PERI_SEL_MASK) >> PCLK_PERI_SEL_SHIFT;
294*4882a593Smuzhiyun 		div = (con & PCLK_PERI_DIV_MASK) >> PCLK_PERI_DIV_SHIFT;
295*4882a593Smuzhiyun 		break;
296*4882a593Smuzhiyun 	default:
297*4882a593Smuzhiyun 		return -ENOENT;
298*4882a593Smuzhiyun 	}
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	if (sel == ACLK_PERI_SEL_CPLL)
301*4882a593Smuzhiyun 		rate = priv->cpll_hz;
302*4882a593Smuzhiyun 	else
303*4882a593Smuzhiyun 		rate = priv->gpll_hz;
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	return DIV_TO_RATE(rate, div);
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun 
rk3562_peri_set_rate(struct rk3562_clk_priv * priv,ulong clk_id,ulong rate)308*4882a593Smuzhiyun static ulong rk3562_peri_set_rate(struct rk3562_clk_priv *priv, ulong clk_id,
309*4882a593Smuzhiyun 				  ulong rate)
310*4882a593Smuzhiyun {
311*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
312*4882a593Smuzhiyun 	u32 sel, div;
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun 	if (priv->cpll_hz % rate == 0) {
315*4882a593Smuzhiyun 		sel = ACLK_PERI_SEL_CPLL;
316*4882a593Smuzhiyun 		div = DIV_ROUND_UP(priv->cpll_hz, rate);
317*4882a593Smuzhiyun 	} else {
318*4882a593Smuzhiyun 		sel= ACLK_PERI_SEL_GPLL;
319*4882a593Smuzhiyun 		div = DIV_ROUND_UP(priv->gpll_hz, rate);
320*4882a593Smuzhiyun 	}
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun 	switch (clk_id) {
323*4882a593Smuzhiyun 	case ACLK_PERI:
324*4882a593Smuzhiyun 		rk_clrsetreg(&cru->periclksel_con[0],
325*4882a593Smuzhiyun 			     ACLK_PERI_SEL_MASK | ACLK_PERI_DIV_MASK,
326*4882a593Smuzhiyun 			     (sel << ACLK_PERI_SEL_SHIFT) |
327*4882a593Smuzhiyun 			     ((div - 1) << ACLK_PERI_DIV_SHIFT));
328*4882a593Smuzhiyun 		break;
329*4882a593Smuzhiyun 	case HCLK_PERI:
330*4882a593Smuzhiyun 		rk_clrsetreg(&cru->periclksel_con[0],
331*4882a593Smuzhiyun 			     HCLK_PERI_SEL_MASK | HCLK_PERI_DIV_MASK,
332*4882a593Smuzhiyun 			     (sel << HCLK_PERI_SEL_SHIFT) |
333*4882a593Smuzhiyun 			     ((div - 1) << HCLK_PERI_DIV_SHIFT));
334*4882a593Smuzhiyun 		break;
335*4882a593Smuzhiyun 	case PCLK_PERI:
336*4882a593Smuzhiyun 		rk_clrsetreg(&cru->periclksel_con[1],
337*4882a593Smuzhiyun 			     PCLK_PERI_SEL_MASK | PCLK_PERI_DIV_MASK,
338*4882a593Smuzhiyun 			     (sel << PCLK_PERI_SEL_SHIFT) |
339*4882a593Smuzhiyun 			     ((div - 1) << PCLK_PERI_DIV_SHIFT));
340*4882a593Smuzhiyun 		break;
341*4882a593Smuzhiyun 	default:
342*4882a593Smuzhiyun 		return -ENOENT;
343*4882a593Smuzhiyun 	}
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 	return rk3562_peri_get_rate(priv, clk_id);
346*4882a593Smuzhiyun }
347*4882a593Smuzhiyun 
rk3562_i2c_get_rate(struct rk3562_clk_priv * priv,ulong clk_id)348*4882a593Smuzhiyun static ulong rk3562_i2c_get_rate(struct rk3562_clk_priv *priv, ulong clk_id)
349*4882a593Smuzhiyun {
350*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
351*4882a593Smuzhiyun 	u32 sel, con, div;
352*4882a593Smuzhiyun 	ulong rate;
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 	switch (clk_id) {
355*4882a593Smuzhiyun 	case CLK_PMU0_I2C0:
356*4882a593Smuzhiyun 		con = readl(&cru->pmu0clksel_con[3]);
357*4882a593Smuzhiyun 		sel = (con & CLK_PMU0_I2C0_SEL_MASK) >> CLK_PMU0_I2C0_SEL_SHIFT;
358*4882a593Smuzhiyun 		if (sel == CLK_PMU0_I2C0_SEL_200M)
359*4882a593Smuzhiyun 			rate = 200 * MHz;
360*4882a593Smuzhiyun 		else if (sel == CLK_PMU0_I2C0_SEL_24M)
361*4882a593Smuzhiyun 			rate = OSC_HZ;
362*4882a593Smuzhiyun 		else
363*4882a593Smuzhiyun 			rate = 32768;
364*4882a593Smuzhiyun 		div = (con & CLK_PMU0_I2C0_DIV_MASK) >> CLK_PMU0_I2C0_DIV_SHIFT;
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun 		return DIV_TO_RATE(rate, div);
367*4882a593Smuzhiyun 	case CLK_I2C:
368*4882a593Smuzhiyun 	case CLK_I2C1:
369*4882a593Smuzhiyun 	case CLK_I2C2:
370*4882a593Smuzhiyun 	case CLK_I2C3:
371*4882a593Smuzhiyun 	case CLK_I2C4:
372*4882a593Smuzhiyun 	case CLK_I2C5:
373*4882a593Smuzhiyun 		con = readl(&cru->clksel_con[41]);
374*4882a593Smuzhiyun 		sel = (con & CLK_I2C_SEL_MASK) >> CLK_I2C_SEL_SHIFT;
375*4882a593Smuzhiyun 		if (sel == CLK_I2C_SEL_200M)
376*4882a593Smuzhiyun 			rate = 200 * MHz;
377*4882a593Smuzhiyun 		else if (sel == CLK_I2C_SEL_100M)
378*4882a593Smuzhiyun 			rate = 100 * MHz;
379*4882a593Smuzhiyun 		else if (sel == CLK_I2C_SEL_50M)
380*4882a593Smuzhiyun 			rate = 50 * MHz;
381*4882a593Smuzhiyun 		else
382*4882a593Smuzhiyun 			rate = OSC_HZ;
383*4882a593Smuzhiyun 		break;
384*4882a593Smuzhiyun 	default:
385*4882a593Smuzhiyun 		return -ENOENT;
386*4882a593Smuzhiyun 	}
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 	return rate;
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun 
rk3562_i2c_set_rate(struct rk3562_clk_priv * priv,ulong clk_id,ulong rate)391*4882a593Smuzhiyun static ulong rk3562_i2c_set_rate(struct rk3562_clk_priv *priv, ulong clk_id,
392*4882a593Smuzhiyun 				 ulong rate)
393*4882a593Smuzhiyun {
394*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
395*4882a593Smuzhiyun 	u32 sel, div;
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun 	switch (clk_id) {
398*4882a593Smuzhiyun 	case CLK_PMU0_I2C0:
399*4882a593Smuzhiyun 		if (rate == 200 * MHz) {
400*4882a593Smuzhiyun 			sel = CLK_PMU0_I2C0_SEL_200M;
401*4882a593Smuzhiyun 			div = 1;
402*4882a593Smuzhiyun 		} else if (rate == OSC_HZ) {
403*4882a593Smuzhiyun 			sel = CLK_PMU0_I2C0_SEL_24M;
404*4882a593Smuzhiyun 			div = 1;
405*4882a593Smuzhiyun 		} else if (rate == 32768) {
406*4882a593Smuzhiyun 			sel = CLK_PMU0_I2C0_SEL_32K;
407*4882a593Smuzhiyun 			div = 1;
408*4882a593Smuzhiyun 		} else {
409*4882a593Smuzhiyun 			sel = CLK_PMU0_I2C0_SEL_200M;
410*4882a593Smuzhiyun 			div = DIV_ROUND_UP(200 * MHz, rate);
411*4882a593Smuzhiyun 			assert(div - 1 <= 31);
412*4882a593Smuzhiyun 		}
413*4882a593Smuzhiyun 		rk_clrsetreg(&cru->pmu0clksel_con[3], CLK_PMU0_I2C0_DIV_MASK,
414*4882a593Smuzhiyun 			     (div - 1) << CLK_PMU0_I2C0_DIV_SHIFT);
415*4882a593Smuzhiyun 		rk_clrsetreg(&cru->pmu0clksel_con[3], CLK_PMU0_I2C0_SEL_MASK,
416*4882a593Smuzhiyun 			     sel << CLK_PMU0_I2C0_SEL_SHIFT);
417*4882a593Smuzhiyun 		break;
418*4882a593Smuzhiyun 	case CLK_I2C:
419*4882a593Smuzhiyun 	case CLK_I2C2:
420*4882a593Smuzhiyun 	case CLK_I2C3:
421*4882a593Smuzhiyun 	case CLK_I2C4:
422*4882a593Smuzhiyun 	case CLK_I2C5:
423*4882a593Smuzhiyun 		if (rate == 200 * MHz)
424*4882a593Smuzhiyun 			sel = CLK_I2C_SEL_200M;
425*4882a593Smuzhiyun 		else if (rate == 100 * MHz)
426*4882a593Smuzhiyun 			sel = CLK_I2C_SEL_100M;
427*4882a593Smuzhiyun 		else if (rate == 50 * MHz)
428*4882a593Smuzhiyun 			sel = CLK_I2C_SEL_50M;
429*4882a593Smuzhiyun 		else
430*4882a593Smuzhiyun 			sel = CLK_I2C_SEL_24M;
431*4882a593Smuzhiyun 		rk_clrsetreg(&cru->clksel_con[41], CLK_I2C_SEL_MASK,
432*4882a593Smuzhiyun 			     sel << CLK_I2C_SEL_SHIFT);
433*4882a593Smuzhiyun 		break;
434*4882a593Smuzhiyun 	default:
435*4882a593Smuzhiyun 		return -ENOENT;
436*4882a593Smuzhiyun 	}
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun 	return rk3562_i2c_get_rate(priv, clk_id);
440*4882a593Smuzhiyun }
441*4882a593Smuzhiyun 
rk3562_uart_get_rate(struct rk3562_clk_priv * priv,ulong clk_id)442*4882a593Smuzhiyun static ulong rk3562_uart_get_rate(struct rk3562_clk_priv *priv, ulong clk_id)
443*4882a593Smuzhiyun {
444*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
445*4882a593Smuzhiyun 	u32 reg, con, fracdiv, div, src, p_src, p_rate;
446*4882a593Smuzhiyun 	unsigned long m, n;
447*4882a593Smuzhiyun 
448*4882a593Smuzhiyun 	switch (clk_id) {
449*4882a593Smuzhiyun 	case SCLK_PMU1_UART0:
450*4882a593Smuzhiyun 		con = readl(&cru->pmu1clksel_con[2]);
451*4882a593Smuzhiyun 		src = (con & CLK_PMU1_UART0_SEL_MASK) >>
452*4882a593Smuzhiyun 		       CLK_PMU1_UART0_SEL_SHIFT;
453*4882a593Smuzhiyun 		div = (con & CLK_PMU1_UART0_SRC_DIV_MASK) >>
454*4882a593Smuzhiyun 		       CLK_PMU1_UART0_SRC_DIV_SHIFT;
455*4882a593Smuzhiyun 		if (src == CLK_UART_SEL_SRC) {
456*4882a593Smuzhiyun 			return DIV_TO_RATE(priv->cpll_hz, div);
457*4882a593Smuzhiyun 		} else if (src == CLK_UART_SEL_FRAC) {
458*4882a593Smuzhiyun 			fracdiv = readl(&cru->pmu1clksel_con[3]);
459*4882a593Smuzhiyun 			n = fracdiv & CLK_UART_FRAC_NUMERATOR_MASK;
460*4882a593Smuzhiyun 			n >>= CLK_UART_FRAC_NUMERATOR_SHIFT;
461*4882a593Smuzhiyun 			m = fracdiv & CLK_UART_FRAC_DENOMINATOR_MASK;
462*4882a593Smuzhiyun 			m >>= CLK_UART_FRAC_DENOMINATOR_SHIFT;
463*4882a593Smuzhiyun 			return DIV_TO_RATE(priv->cpll_hz, div) * n / m;
464*4882a593Smuzhiyun 		} else {
465*4882a593Smuzhiyun 			return OSC_HZ;
466*4882a593Smuzhiyun 		}
467*4882a593Smuzhiyun 	case SCLK_UART1:
468*4882a593Smuzhiyun 		reg = 21;
469*4882a593Smuzhiyun 		break;
470*4882a593Smuzhiyun 	case SCLK_UART2:
471*4882a593Smuzhiyun 		reg = 23;
472*4882a593Smuzhiyun 		break;
473*4882a593Smuzhiyun 	case SCLK_UART3:
474*4882a593Smuzhiyun 		reg = 25;
475*4882a593Smuzhiyun 		break;
476*4882a593Smuzhiyun 	case SCLK_UART4:
477*4882a593Smuzhiyun 		reg = 27;
478*4882a593Smuzhiyun 		break;
479*4882a593Smuzhiyun 	case SCLK_UART5:
480*4882a593Smuzhiyun 		reg = 29;
481*4882a593Smuzhiyun 		break;
482*4882a593Smuzhiyun 	case SCLK_UART6:
483*4882a593Smuzhiyun 		reg = 31;
484*4882a593Smuzhiyun 		break;
485*4882a593Smuzhiyun 	case SCLK_UART7:
486*4882a593Smuzhiyun 		reg = 33;
487*4882a593Smuzhiyun 		break;
488*4882a593Smuzhiyun 	case SCLK_UART8:
489*4882a593Smuzhiyun 		reg = 35;
490*4882a593Smuzhiyun 		break;
491*4882a593Smuzhiyun 	case SCLK_UART9:
492*4882a593Smuzhiyun 		reg = 37;
493*4882a593Smuzhiyun 		break;
494*4882a593Smuzhiyun 	default:
495*4882a593Smuzhiyun 		return -ENOENT;
496*4882a593Smuzhiyun 	}
497*4882a593Smuzhiyun 	con = readl(&cru->periclksel_con[reg]);
498*4882a593Smuzhiyun 	src = (con & CLK_UART_SEL_MASK) >> CLK_UART_SEL_SHIFT;
499*4882a593Smuzhiyun 	div = (con & CLK_UART_SRC_DIV_MASK) >> CLK_UART_SRC_DIV_SHIFT;
500*4882a593Smuzhiyun 	p_src = (con & CLK_UART_SRC_SEL_MASK) >> CLK_UART_SRC_SEL_SHIFT;
501*4882a593Smuzhiyun 	if (p_src == CLK_UART_SRC_SEL_GPLL)
502*4882a593Smuzhiyun 		p_rate = priv->gpll_hz;
503*4882a593Smuzhiyun 	else
504*4882a593Smuzhiyun 		p_rate = priv->cpll_hz;
505*4882a593Smuzhiyun 	if (src == CLK_UART_SEL_SRC) {
506*4882a593Smuzhiyun 		return DIV_TO_RATE(p_rate, div);
507*4882a593Smuzhiyun 	} else if (src == CLK_UART_SEL_FRAC) {
508*4882a593Smuzhiyun 		fracdiv = readl(&cru->periclksel_con[reg + 1]);
509*4882a593Smuzhiyun 		n = fracdiv & CLK_UART_FRAC_NUMERATOR_MASK;
510*4882a593Smuzhiyun 		n >>= CLK_UART_FRAC_NUMERATOR_SHIFT;
511*4882a593Smuzhiyun 		m = fracdiv & CLK_UART_FRAC_DENOMINATOR_MASK;
512*4882a593Smuzhiyun 		m >>= CLK_UART_FRAC_DENOMINATOR_SHIFT;
513*4882a593Smuzhiyun 		return DIV_TO_RATE(p_rate, div) * n / m;
514*4882a593Smuzhiyun 	} else {
515*4882a593Smuzhiyun 		return OSC_HZ;
516*4882a593Smuzhiyun 	}
517*4882a593Smuzhiyun }
518*4882a593Smuzhiyun 
rk3562_uart_set_rate(struct rk3562_clk_priv * priv,ulong clk_id,ulong rate)519*4882a593Smuzhiyun static ulong rk3562_uart_set_rate(struct rk3562_clk_priv *priv, ulong clk_id,
520*4882a593Smuzhiyun 				  ulong rate)
521*4882a593Smuzhiyun {
522*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
523*4882a593Smuzhiyun 	u32 reg, clk_src, uart_src, div;
524*4882a593Smuzhiyun 	unsigned long m = 0, n = 0, val;
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun 	switch (clk_id) {
527*4882a593Smuzhiyun 	case SCLK_PMU1_UART0:
528*4882a593Smuzhiyun 		if (priv->cpll_hz % rate == 0) {
529*4882a593Smuzhiyun 			uart_src = CLK_UART_SEL_SRC;
530*4882a593Smuzhiyun 			div = DIV_ROUND_UP(priv->cpll_hz, rate);
531*4882a593Smuzhiyun 		} else if (rate == OSC_HZ) {
532*4882a593Smuzhiyun 			uart_src = CLK_UART_SEL_XIN24M;
533*4882a593Smuzhiyun 			div = 2;
534*4882a593Smuzhiyun 		} else {
535*4882a593Smuzhiyun 			uart_src = CLK_UART_SEL_FRAC;
536*4882a593Smuzhiyun 			div = 2;
537*4882a593Smuzhiyun 			rational_best_approximation(rate, priv->cpll_hz / div,
538*4882a593Smuzhiyun 						    GENMASK(16 - 1, 0),
539*4882a593Smuzhiyun 						    GENMASK(16 - 1, 0),
540*4882a593Smuzhiyun 						    &n, &m);
541*4882a593Smuzhiyun 		}
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun 		rk_clrsetreg(&cru->pmu1clksel_con[2],
544*4882a593Smuzhiyun 			     CLK_PMU1_UART0_SEL_MASK |
545*4882a593Smuzhiyun 			     CLK_PMU1_UART0_SRC_DIV_MASK,
546*4882a593Smuzhiyun 			     (uart_src << CLK_PMU1_UART0_SEL_SHIFT) |
547*4882a593Smuzhiyun 			     ((div - 1) << CLK_PMU1_UART0_SRC_DIV_SHIFT));
548*4882a593Smuzhiyun 		if (m && n) {
549*4882a593Smuzhiyun 			val = n << CLK_UART_FRAC_NUMERATOR_SHIFT | m;
550*4882a593Smuzhiyun 			writel(val, &cru->pmu1clksel_con[3]);
551*4882a593Smuzhiyun 		}
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun 		return rk3562_uart_get_rate(priv, clk_id);
554*4882a593Smuzhiyun 	case SCLK_UART1:
555*4882a593Smuzhiyun 		reg = 21;
556*4882a593Smuzhiyun 		break;
557*4882a593Smuzhiyun 	case SCLK_UART2:
558*4882a593Smuzhiyun 		reg = 23;
559*4882a593Smuzhiyun 		break;
560*4882a593Smuzhiyun 	case SCLK_UART3:
561*4882a593Smuzhiyun 		reg = 25;
562*4882a593Smuzhiyun 		break;
563*4882a593Smuzhiyun 	case SCLK_UART4:
564*4882a593Smuzhiyun 		reg = 27;
565*4882a593Smuzhiyun 		break;
566*4882a593Smuzhiyun 	case SCLK_UART5:
567*4882a593Smuzhiyun 		reg = 29;
568*4882a593Smuzhiyun 		break;
569*4882a593Smuzhiyun 	case SCLK_UART6:
570*4882a593Smuzhiyun 		reg = 31;
571*4882a593Smuzhiyun 		break;
572*4882a593Smuzhiyun 	case SCLK_UART7:
573*4882a593Smuzhiyun 		reg = 33;
574*4882a593Smuzhiyun 		break;
575*4882a593Smuzhiyun 	case SCLK_UART8:
576*4882a593Smuzhiyun 		reg = 35;
577*4882a593Smuzhiyun 		break;
578*4882a593Smuzhiyun 	case SCLK_UART9:
579*4882a593Smuzhiyun 		reg = 37;
580*4882a593Smuzhiyun 		break;
581*4882a593Smuzhiyun 	default:
582*4882a593Smuzhiyun 		return -ENOENT;
583*4882a593Smuzhiyun 	}
584*4882a593Smuzhiyun 
585*4882a593Smuzhiyun 	if (priv->gpll_hz % rate == 0) {
586*4882a593Smuzhiyun 		clk_src = CLK_UART_SRC_SEL_GPLL;
587*4882a593Smuzhiyun 		uart_src = CLK_UART_SEL_SRC;
588*4882a593Smuzhiyun 		div = DIV_ROUND_UP(priv->gpll_hz, rate);
589*4882a593Smuzhiyun 	} else if (priv->cpll_hz % rate == 0) {
590*4882a593Smuzhiyun 		clk_src = CLK_UART_SRC_SEL_CPLL;
591*4882a593Smuzhiyun 		uart_src = CLK_UART_SEL_SRC;
592*4882a593Smuzhiyun 		div = DIV_ROUND_UP(priv->cpll_hz, rate);
593*4882a593Smuzhiyun 	} else if (rate == OSC_HZ) {
594*4882a593Smuzhiyun 		clk_src = CLK_UART_SRC_SEL_GPLL;
595*4882a593Smuzhiyun 		uart_src = CLK_UART_SEL_XIN24M;
596*4882a593Smuzhiyun 		div = 2;
597*4882a593Smuzhiyun 	} else {
598*4882a593Smuzhiyun 		clk_src = CLK_UART_SRC_SEL_GPLL;
599*4882a593Smuzhiyun 		uart_src = CLK_UART_SEL_FRAC;
600*4882a593Smuzhiyun 		div = 2;
601*4882a593Smuzhiyun 		rational_best_approximation(rate, priv->gpll_hz / div,
602*4882a593Smuzhiyun 					    GENMASK(16 - 1, 0),
603*4882a593Smuzhiyun 					    GENMASK(16 - 1, 0),
604*4882a593Smuzhiyun 					    &n, &m);
605*4882a593Smuzhiyun 	}
606*4882a593Smuzhiyun 
607*4882a593Smuzhiyun 	rk_clrsetreg(&cru->periclksel_con[reg],
608*4882a593Smuzhiyun 		     CLK_UART_SEL_MASK | CLK_UART_SRC_SEL_MASK |
609*4882a593Smuzhiyun 		     CLK_UART_SRC_DIV_MASK,
610*4882a593Smuzhiyun 		     (clk_src << CLK_UART_SRC_SEL_SHIFT) |
611*4882a593Smuzhiyun 		     (uart_src << CLK_UART_SEL_SHIFT) |
612*4882a593Smuzhiyun 		     ((div - 1) << CLK_UART_SRC_DIV_SHIFT));
613*4882a593Smuzhiyun 	if (m && n) {
614*4882a593Smuzhiyun 		val = n << CLK_UART_FRAC_NUMERATOR_SHIFT | m;
615*4882a593Smuzhiyun 		writel(val, &cru->periclksel_con[reg + 1]);
616*4882a593Smuzhiyun 	}
617*4882a593Smuzhiyun 
618*4882a593Smuzhiyun 	return rk3562_uart_get_rate(priv, clk_id);
619*4882a593Smuzhiyun }
620*4882a593Smuzhiyun 
rk3562_pwm_get_rate(struct rk3562_clk_priv * priv,ulong clk_id)621*4882a593Smuzhiyun static ulong rk3562_pwm_get_rate(struct rk3562_clk_priv *priv, ulong clk_id)
622*4882a593Smuzhiyun {
623*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
624*4882a593Smuzhiyun 	u32 sel, con, div, mask, shift;
625*4882a593Smuzhiyun 	ulong rate;
626*4882a593Smuzhiyun 
627*4882a593Smuzhiyun 	switch (clk_id) {
628*4882a593Smuzhiyun 	case CLK_PMU1_PWM0:
629*4882a593Smuzhiyun 		con = readl(&cru->pmu1clksel_con[4]);
630*4882a593Smuzhiyun 		sel = (con & CLK_PMU1_PWM0_SEL_MASK) >> CLK_PMU1_PWM0_SEL_SHIFT;
631*4882a593Smuzhiyun 		if (sel == CLK_PMU1_PWM0_SEL_200M)
632*4882a593Smuzhiyun 			rate = 200 * MHz;
633*4882a593Smuzhiyun 		else if (sel == CLK_PMU1_PWM0_SEL_24M)
634*4882a593Smuzhiyun 			rate = OSC_HZ;
635*4882a593Smuzhiyun 		else
636*4882a593Smuzhiyun 			rate = 32768;
637*4882a593Smuzhiyun 		div = (con & CLK_PMU1_PWM0_DIV_MASK) >> CLK_PMU1_PWM0_DIV_SHIFT;
638*4882a593Smuzhiyun 
639*4882a593Smuzhiyun 		return DIV_TO_RATE(rate, div);
640*4882a593Smuzhiyun 	case CLK_PWM1_PERI:
641*4882a593Smuzhiyun 		mask = CLK_PWM1_PERI_SEL_MASK;
642*4882a593Smuzhiyun 		shift = CLK_PWM1_PERI_SEL_SHIFT;
643*4882a593Smuzhiyun 		break;
644*4882a593Smuzhiyun 	case CLK_PWM2_PERI:
645*4882a593Smuzhiyun 		mask = CLK_PWM2_PERI_SEL_MASK;
646*4882a593Smuzhiyun 		shift = CLK_PWM2_PERI_SEL_SHIFT;
647*4882a593Smuzhiyun 		break;
648*4882a593Smuzhiyun 	case CLK_PWM3_PERI:
649*4882a593Smuzhiyun 		mask = CLK_PWM3_PERI_SEL_MASK;
650*4882a593Smuzhiyun 		shift = CLK_PWM3_PERI_SEL_SHIFT;
651*4882a593Smuzhiyun 		break;
652*4882a593Smuzhiyun 	default:
653*4882a593Smuzhiyun 		return -ENOENT;
654*4882a593Smuzhiyun 	}
655*4882a593Smuzhiyun 
656*4882a593Smuzhiyun 	con = readl(&cru->periclksel_con[40]);
657*4882a593Smuzhiyun 	sel = (con & mask) >> shift;
658*4882a593Smuzhiyun 	if (sel == CLK_PWM_SEL_100M)
659*4882a593Smuzhiyun 		rate = 100 * MHz;
660*4882a593Smuzhiyun 	else if (sel == CLK_PWM_SEL_50M)
661*4882a593Smuzhiyun 		rate = 50 * MHz;
662*4882a593Smuzhiyun 	else
663*4882a593Smuzhiyun 		rate = OSC_HZ;
664*4882a593Smuzhiyun 
665*4882a593Smuzhiyun 	return rate;
666*4882a593Smuzhiyun }
667*4882a593Smuzhiyun 
rk3562_pwm_set_rate(struct rk3562_clk_priv * priv,ulong clk_id,ulong rate)668*4882a593Smuzhiyun static ulong rk3562_pwm_set_rate(struct rk3562_clk_priv *priv, ulong clk_id,
669*4882a593Smuzhiyun 				 ulong rate)
670*4882a593Smuzhiyun {
671*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
672*4882a593Smuzhiyun 	u32 sel, div, mask, shift;
673*4882a593Smuzhiyun 
674*4882a593Smuzhiyun 	switch (clk_id) {
675*4882a593Smuzhiyun 	case CLK_PMU1_PWM0:
676*4882a593Smuzhiyun 		if (rate == 200 * MHz) {
677*4882a593Smuzhiyun 			sel = CLK_PMU1_PWM0_SEL_200M;
678*4882a593Smuzhiyun 			div = 1;
679*4882a593Smuzhiyun 		} else if (rate == OSC_HZ) {
680*4882a593Smuzhiyun 			sel = CLK_PMU1_PWM0_SEL_24M;
681*4882a593Smuzhiyun 			div = 1;
682*4882a593Smuzhiyun 		} else if (rate == 32768) {
683*4882a593Smuzhiyun 			sel = CLK_PMU1_PWM0_SEL_32K;
684*4882a593Smuzhiyun 			div = 1;
685*4882a593Smuzhiyun 		} else {
686*4882a593Smuzhiyun 			sel = CLK_PMU1_PWM0_SEL_200M;
687*4882a593Smuzhiyun 			div = DIV_ROUND_UP(200 * MHz, rate);
688*4882a593Smuzhiyun 			assert(div - 1 <= 3);
689*4882a593Smuzhiyun 		}
690*4882a593Smuzhiyun 		rk_clrsetreg(&cru->pmu1clksel_con[4], CLK_PMU1_PWM0_DIV_MASK,
691*4882a593Smuzhiyun 			     (div - 1) << CLK_PMU1_PWM0_DIV_SHIFT);
692*4882a593Smuzhiyun 		rk_clrsetreg(&cru->pmu1clksel_con[4], CLK_PMU1_PWM0_SEL_MASK,
693*4882a593Smuzhiyun 			     sel << CLK_PMU1_PWM0_SEL_SHIFT);
694*4882a593Smuzhiyun 
695*4882a593Smuzhiyun 		return rk3562_pwm_get_rate(priv, clk_id);
696*4882a593Smuzhiyun 	case CLK_PWM1_PERI:
697*4882a593Smuzhiyun 		mask = CLK_PWM1_PERI_SEL_MASK;
698*4882a593Smuzhiyun 		shift = CLK_PWM1_PERI_SEL_SHIFT;
699*4882a593Smuzhiyun 		break;
700*4882a593Smuzhiyun 	case CLK_PWM2_PERI:
701*4882a593Smuzhiyun 		mask = CLK_PWM2_PERI_SEL_MASK;
702*4882a593Smuzhiyun 		shift = CLK_PWM2_PERI_SEL_SHIFT;
703*4882a593Smuzhiyun 		break;
704*4882a593Smuzhiyun 	case CLK_PWM3_PERI:
705*4882a593Smuzhiyun 		mask = CLK_PWM3_PERI_SEL_MASK;
706*4882a593Smuzhiyun 		shift = CLK_PWM3_PERI_SEL_SHIFT;
707*4882a593Smuzhiyun 		break;
708*4882a593Smuzhiyun 	default:
709*4882a593Smuzhiyun 		return -ENOENT;
710*4882a593Smuzhiyun 	}
711*4882a593Smuzhiyun 
712*4882a593Smuzhiyun 	if (rate == 100 * MHz)
713*4882a593Smuzhiyun 		sel = CLK_PWM_SEL_100M;
714*4882a593Smuzhiyun 	else if (rate == 50 * MHz)
715*4882a593Smuzhiyun 		sel = CLK_PWM_SEL_50M;
716*4882a593Smuzhiyun 	else
717*4882a593Smuzhiyun 		sel = CLK_PWM_SEL_24M;
718*4882a593Smuzhiyun 	rk_clrsetreg(&cru->periclksel_con[40], mask, sel << shift);
719*4882a593Smuzhiyun 
720*4882a593Smuzhiyun 	return rk3562_pwm_get_rate(priv, clk_id);
721*4882a593Smuzhiyun }
722*4882a593Smuzhiyun 
rk3562_spi_get_rate(struct rk3562_clk_priv * priv,ulong clk_id)723*4882a593Smuzhiyun static ulong rk3562_spi_get_rate(struct rk3562_clk_priv *priv, ulong clk_id)
724*4882a593Smuzhiyun {
725*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
726*4882a593Smuzhiyun 	u32 sel, con, div, mask, shift;
727*4882a593Smuzhiyun 	ulong rate;
728*4882a593Smuzhiyun 
729*4882a593Smuzhiyun 	switch (clk_id) {
730*4882a593Smuzhiyun 	case CLK_PMU1_SPI0:
731*4882a593Smuzhiyun 		con = readl(&cru->pmu1clksel_con[4]);
732*4882a593Smuzhiyun 		sel = (con & CLK_PMU1_SPI0_SEL_MASK) >> CLK_PMU1_SPI0_SEL_SHIFT;
733*4882a593Smuzhiyun 		if (sel == CLK_PMU1_SPI0_SEL_200M)
734*4882a593Smuzhiyun 			rate = 200 * MHz;
735*4882a593Smuzhiyun 		else if (sel == CLK_PMU1_SPI0_SEL_24M)
736*4882a593Smuzhiyun 			rate = OSC_HZ;
737*4882a593Smuzhiyun 		else
738*4882a593Smuzhiyun 			rate = 32768;
739*4882a593Smuzhiyun 		div = (con & CLK_PMU1_SPI0_DIV_MASK) >> CLK_PMU1_SPI0_DIV_SHIFT;
740*4882a593Smuzhiyun 
741*4882a593Smuzhiyun 		return DIV_TO_RATE(rate, div);
742*4882a593Smuzhiyun 	case CLK_SPI1:
743*4882a593Smuzhiyun 		mask = CLK_SPI1_SEL_MASK;
744*4882a593Smuzhiyun 		shift = CLK_SPI1_SEL_SHIFT;
745*4882a593Smuzhiyun 		break;
746*4882a593Smuzhiyun 	case CLK_SPI2:
747*4882a593Smuzhiyun 		mask = CLK_SPI2_SEL_MASK;
748*4882a593Smuzhiyun 		shift = CLK_SPI2_SEL_SHIFT;
749*4882a593Smuzhiyun 		break;
750*4882a593Smuzhiyun 	default:
751*4882a593Smuzhiyun 		return -ENOENT;
752*4882a593Smuzhiyun 	}
753*4882a593Smuzhiyun 
754*4882a593Smuzhiyun 	con = readl(&cru->periclksel_con[20]);
755*4882a593Smuzhiyun 	sel = (con & mask) >> shift;
756*4882a593Smuzhiyun 	if (sel == CLK_SPI_SEL_200M)
757*4882a593Smuzhiyun 		rate = 200 * MHz;
758*4882a593Smuzhiyun 	else if (sel == CLK_SPI_SEL_100M)
759*4882a593Smuzhiyun 		rate = 100 * MHz;
760*4882a593Smuzhiyun 	else if (sel == CLK_SPI_SEL_50M)
761*4882a593Smuzhiyun 		rate = 50 * MHz;
762*4882a593Smuzhiyun 	else
763*4882a593Smuzhiyun 		rate = OSC_HZ;
764*4882a593Smuzhiyun 
765*4882a593Smuzhiyun 	return rate;
766*4882a593Smuzhiyun }
767*4882a593Smuzhiyun 
rk3562_spi_set_rate(struct rk3562_clk_priv * priv,ulong clk_id,ulong rate)768*4882a593Smuzhiyun static ulong rk3562_spi_set_rate(struct rk3562_clk_priv *priv, ulong clk_id,
769*4882a593Smuzhiyun 				 ulong rate)
770*4882a593Smuzhiyun {
771*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
772*4882a593Smuzhiyun 	u32 sel, div, mask, shift;
773*4882a593Smuzhiyun 
774*4882a593Smuzhiyun 	switch (clk_id) {
775*4882a593Smuzhiyun 	case CLK_PMU1_SPI0:
776*4882a593Smuzhiyun 		if (rate == 200 * MHz) {
777*4882a593Smuzhiyun 			sel = CLK_PMU1_SPI0_SEL_200M;
778*4882a593Smuzhiyun 			div = 1;
779*4882a593Smuzhiyun 		} else if (rate == OSC_HZ) {
780*4882a593Smuzhiyun 			sel = CLK_PMU1_SPI0_SEL_24M;
781*4882a593Smuzhiyun 			div = 1;
782*4882a593Smuzhiyun 		} else if (rate == 32768) {
783*4882a593Smuzhiyun 			sel = CLK_PMU1_SPI0_SEL_32K;
784*4882a593Smuzhiyun 			div = 1;
785*4882a593Smuzhiyun 		} else {
786*4882a593Smuzhiyun 			sel = CLK_PMU1_SPI0_SEL_200M;
787*4882a593Smuzhiyun 			div = DIV_ROUND_UP(200 * MHz, rate);
788*4882a593Smuzhiyun 			assert(div - 1 <= 3);
789*4882a593Smuzhiyun 		}
790*4882a593Smuzhiyun 		rk_clrsetreg(&cru->pmu1clksel_con[4], CLK_PMU1_SPI0_DIV_MASK,
791*4882a593Smuzhiyun 			     (div - 1) << CLK_PMU1_SPI0_DIV_SHIFT);
792*4882a593Smuzhiyun 		rk_clrsetreg(&cru->pmu1clksel_con[4], CLK_PMU1_SPI0_SEL_MASK,
793*4882a593Smuzhiyun 			     sel << CLK_PMU1_SPI0_SEL_SHIFT);
794*4882a593Smuzhiyun 
795*4882a593Smuzhiyun 		return rk3562_spi_get_rate(priv, clk_id);
796*4882a593Smuzhiyun 	case CLK_SPI1:
797*4882a593Smuzhiyun 		mask = CLK_SPI1_SEL_MASK;
798*4882a593Smuzhiyun 		shift = CLK_SPI1_SEL_SHIFT;
799*4882a593Smuzhiyun 		break;
800*4882a593Smuzhiyun 	case CLK_SPI2:
801*4882a593Smuzhiyun 		mask = CLK_SPI2_SEL_MASK;
802*4882a593Smuzhiyun 		shift = CLK_SPI2_SEL_SHIFT;
803*4882a593Smuzhiyun 		break;
804*4882a593Smuzhiyun 	default:
805*4882a593Smuzhiyun 		return -ENOENT;
806*4882a593Smuzhiyun 	}
807*4882a593Smuzhiyun 
808*4882a593Smuzhiyun 	if (rate == 200 * MHz)
809*4882a593Smuzhiyun 		sel = CLK_SPI_SEL_200M;
810*4882a593Smuzhiyun 	else if (rate == 100 * MHz)
811*4882a593Smuzhiyun 		sel = CLK_SPI_SEL_100M;
812*4882a593Smuzhiyun 	else if (rate == 50 * MHz)
813*4882a593Smuzhiyun 		sel = CLK_SPI_SEL_50M;
814*4882a593Smuzhiyun 	else
815*4882a593Smuzhiyun 		sel = CLK_SPI_SEL_24M;
816*4882a593Smuzhiyun 	rk_clrsetreg(&cru->periclksel_con[20], mask, sel << shift);
817*4882a593Smuzhiyun 
818*4882a593Smuzhiyun 	return rk3562_spi_get_rate(priv, clk_id);
819*4882a593Smuzhiyun }
820*4882a593Smuzhiyun 
rk3562_tsadc_get_rate(struct rk3562_clk_priv * priv,ulong clk_id)821*4882a593Smuzhiyun static ulong rk3562_tsadc_get_rate(struct rk3562_clk_priv *priv, ulong clk_id)
822*4882a593Smuzhiyun {
823*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
824*4882a593Smuzhiyun 	u32 div, con;
825*4882a593Smuzhiyun 
826*4882a593Smuzhiyun 	con = readl(&cru->clksel_con[43]);
827*4882a593Smuzhiyun 	switch (clk_id) {
828*4882a593Smuzhiyun 	case CLK_TSADC_TSEN:
829*4882a593Smuzhiyun 		div = (con & CLK_TSADC_TSEN_DIV_MASK) >>
830*4882a593Smuzhiyun 		       CLK_TSADC_TSEN_DIV_SHIFT;
831*4882a593Smuzhiyun 		break;
832*4882a593Smuzhiyun 	case CLK_TSADC:
833*4882a593Smuzhiyun 		div = (con & CLK_TSADC_DIV_MASK) >> CLK_TSADC_DIV_SHIFT;
834*4882a593Smuzhiyun 		break;
835*4882a593Smuzhiyun 	default:
836*4882a593Smuzhiyun 		return -ENOENT;
837*4882a593Smuzhiyun 	}
838*4882a593Smuzhiyun 
839*4882a593Smuzhiyun 	return DIV_TO_RATE(OSC_HZ, div);
840*4882a593Smuzhiyun }
841*4882a593Smuzhiyun 
rk3562_tsadc_set_rate(struct rk3562_clk_priv * priv,ulong clk_id,ulong rate)842*4882a593Smuzhiyun static ulong rk3562_tsadc_set_rate(struct rk3562_clk_priv *priv, ulong clk_id,
843*4882a593Smuzhiyun 				   ulong rate)
844*4882a593Smuzhiyun {
845*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
846*4882a593Smuzhiyun 	u32 div, mask, shift;
847*4882a593Smuzhiyun 
848*4882a593Smuzhiyun 	switch (clk_id) {
849*4882a593Smuzhiyun 	case CLK_TSADC_TSEN:
850*4882a593Smuzhiyun 		mask = CLK_TSADC_TSEN_DIV_MASK;
851*4882a593Smuzhiyun 		shift =	CLK_TSADC_TSEN_DIV_SHIFT;
852*4882a593Smuzhiyun 		break;
853*4882a593Smuzhiyun 	case CLK_TSADC:
854*4882a593Smuzhiyun 		mask = CLK_TSADC_DIV_MASK;
855*4882a593Smuzhiyun 		shift =	CLK_TSADC_DIV_SHIFT;
856*4882a593Smuzhiyun 		break;
857*4882a593Smuzhiyun 	default:
858*4882a593Smuzhiyun 		return -ENOENT;
859*4882a593Smuzhiyun 	}
860*4882a593Smuzhiyun 
861*4882a593Smuzhiyun 	div = DIV_ROUND_UP(OSC_HZ, rate);
862*4882a593Smuzhiyun 	rk_clrsetreg(&cru->clksel_con[43], mask, (div - 1) << shift);
863*4882a593Smuzhiyun 
864*4882a593Smuzhiyun 	return rk3562_tsadc_get_rate(priv, clk_id);
865*4882a593Smuzhiyun }
866*4882a593Smuzhiyun 
rk3562_saradc_get_rate(struct rk3562_clk_priv * priv,ulong clk_id)867*4882a593Smuzhiyun static ulong rk3562_saradc_get_rate(struct rk3562_clk_priv *priv, ulong clk_id)
868*4882a593Smuzhiyun {
869*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
870*4882a593Smuzhiyun 	u32 div, con;
871*4882a593Smuzhiyun 
872*4882a593Smuzhiyun 	switch (clk_id) {
873*4882a593Smuzhiyun 	case CLK_SARADC_VCCIO156:
874*4882a593Smuzhiyun 		con = readl(&cru->clksel_con[44]);
875*4882a593Smuzhiyun 		div = (con & CLK_SARADC_VCCIO156_DIV_MASK) >>
876*4882a593Smuzhiyun 		       CLK_SARADC_VCCIO156_DIV_SHIFT;
877*4882a593Smuzhiyun 		break;
878*4882a593Smuzhiyun 	case CLK_SARADC:
879*4882a593Smuzhiyun 		con = readl(&cru->periclksel_con[46]);
880*4882a593Smuzhiyun 		div = (con & CLK_SARADC_DIV_MASK) >> CLK_SARADC_DIV_SHIFT;
881*4882a593Smuzhiyun 		break;
882*4882a593Smuzhiyun 	default:
883*4882a593Smuzhiyun 		return -ENOENT;
884*4882a593Smuzhiyun 	}
885*4882a593Smuzhiyun 
886*4882a593Smuzhiyun 	return DIV_TO_RATE(OSC_HZ, div);
887*4882a593Smuzhiyun }
888*4882a593Smuzhiyun 
rk3562_saradc_set_rate(struct rk3562_clk_priv * priv,ulong clk_id,ulong rate)889*4882a593Smuzhiyun static ulong rk3562_saradc_set_rate(struct rk3562_clk_priv *priv, ulong clk_id,
890*4882a593Smuzhiyun 				    ulong rate)
891*4882a593Smuzhiyun {
892*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
893*4882a593Smuzhiyun 	u32 div;
894*4882a593Smuzhiyun 
895*4882a593Smuzhiyun 	switch (clk_id) {
896*4882a593Smuzhiyun 	case CLK_SARADC_VCCIO156:
897*4882a593Smuzhiyun 		div = DIV_ROUND_UP(OSC_HZ, rate);
898*4882a593Smuzhiyun 		rk_clrsetreg(&cru->clksel_con[44], CLK_SARADC_VCCIO156_DIV_MASK,
899*4882a593Smuzhiyun 			     (div - 1) << CLK_SARADC_VCCIO156_DIV_SHIFT);
900*4882a593Smuzhiyun 		break;
901*4882a593Smuzhiyun 	case CLK_SARADC:
902*4882a593Smuzhiyun 		div = DIV_ROUND_UP(OSC_HZ, rate);
903*4882a593Smuzhiyun 		rk_clrsetreg(&cru->periclksel_con[46], CLK_SARADC_DIV_MASK,
904*4882a593Smuzhiyun 			     (div - 1) << CLK_SARADC_DIV_SHIFT);
905*4882a593Smuzhiyun 		break;
906*4882a593Smuzhiyun 	default:
907*4882a593Smuzhiyun 		return -ENOENT;
908*4882a593Smuzhiyun 	}
909*4882a593Smuzhiyun 
910*4882a593Smuzhiyun 	return rk3562_saradc_get_rate(priv, clk_id);
911*4882a593Smuzhiyun }
912*4882a593Smuzhiyun 
rk3562_sfc_get_rate(struct rk3562_clk_priv * priv)913*4882a593Smuzhiyun static ulong rk3562_sfc_get_rate(struct rk3562_clk_priv *priv)
914*4882a593Smuzhiyun {
915*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
916*4882a593Smuzhiyun 	u32 div, sel, con, parent;
917*4882a593Smuzhiyun 
918*4882a593Smuzhiyun 	con = readl(&cru->periclksel_con[20]);
919*4882a593Smuzhiyun 	div = (con & SCLK_SFC_DIV_MASK) >> SCLK_SFC_DIV_SHIFT;
920*4882a593Smuzhiyun 	sel = (con & SCLK_SFC_SEL_MASK) >> SCLK_SFC_SEL_SHIFT;
921*4882a593Smuzhiyun 	if (sel == SCLK_SFC_SRC_SEL_GPLL)
922*4882a593Smuzhiyun 		parent = priv->gpll_hz;
923*4882a593Smuzhiyun 	else if (sel == SCLK_SFC_SRC_SEL_CPLL)
924*4882a593Smuzhiyun 		parent = priv->cpll_hz;
925*4882a593Smuzhiyun 	else
926*4882a593Smuzhiyun 		parent = OSC_HZ;
927*4882a593Smuzhiyun 
928*4882a593Smuzhiyun 	return DIV_TO_RATE(parent, div);
929*4882a593Smuzhiyun }
930*4882a593Smuzhiyun 
rk3562_sfc_set_rate(struct rk3562_clk_priv * priv,ulong rate)931*4882a593Smuzhiyun static ulong rk3562_sfc_set_rate(struct rk3562_clk_priv *priv, ulong rate)
932*4882a593Smuzhiyun {
933*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
934*4882a593Smuzhiyun 	int div, sel;
935*4882a593Smuzhiyun 
936*4882a593Smuzhiyun 	if (OSC_HZ % rate == 0) {
937*4882a593Smuzhiyun 		div = DIV_ROUND_UP(OSC_HZ, rate);
938*4882a593Smuzhiyun 		sel = SCLK_SFC_SRC_SEL_24M;
939*4882a593Smuzhiyun 	} else if ((priv->cpll_hz % rate) == 0) {
940*4882a593Smuzhiyun 		div = DIV_ROUND_UP(priv->cpll_hz, rate);
941*4882a593Smuzhiyun 		sel = SCLK_SFC_SRC_SEL_CPLL;
942*4882a593Smuzhiyun 	} else {
943*4882a593Smuzhiyun 		div = DIV_ROUND_UP(priv->gpll_hz, rate);
944*4882a593Smuzhiyun 		sel = SCLK_SFC_SRC_SEL_GPLL;
945*4882a593Smuzhiyun 	}
946*4882a593Smuzhiyun 
947*4882a593Smuzhiyun 	assert(div - 1 <= 255);
948*4882a593Smuzhiyun 	rk_clrsetreg(&cru->periclksel_con[20],
949*4882a593Smuzhiyun 		     SCLK_SFC_SEL_MASK | SCLK_SFC_DIV_MASK,
950*4882a593Smuzhiyun 		     sel << SCLK_SFC_SEL_SHIFT |
951*4882a593Smuzhiyun 		     (div - 1) << SCLK_SFC_DIV_SHIFT);
952*4882a593Smuzhiyun 
953*4882a593Smuzhiyun 	return rk3562_sfc_get_rate(priv);
954*4882a593Smuzhiyun }
955*4882a593Smuzhiyun 
rk3562_emmc_get_rate(struct rk3562_clk_priv * priv,ulong clk_id)956*4882a593Smuzhiyun static ulong rk3562_emmc_get_rate(struct rk3562_clk_priv *priv, ulong clk_id)
957*4882a593Smuzhiyun {
958*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
959*4882a593Smuzhiyun 	u32 div, sel, con, parent;
960*4882a593Smuzhiyun 
961*4882a593Smuzhiyun 	switch (clk_id) {
962*4882a593Smuzhiyun 	case CCLK_EMMC:
963*4882a593Smuzhiyun 		con = readl(&cru->periclksel_con[18]);
964*4882a593Smuzhiyun 		div = (con & CCLK_EMMC_DIV_MASK) >> CCLK_EMMC_DIV_SHIFT;
965*4882a593Smuzhiyun 		sel = (con & CCLK_EMMC_SEL_MASK) >> CCLK_EMMC_SEL_SHIFT;
966*4882a593Smuzhiyun 		if (sel == CCLK_EMMC_SEL_GPLL)
967*4882a593Smuzhiyun 			parent = priv->gpll_hz;
968*4882a593Smuzhiyun 		else if (sel == CCLK_EMMC_SEL_CPLL)
969*4882a593Smuzhiyun 			parent = priv->cpll_hz;
970*4882a593Smuzhiyun 		else if (sel == CCLK_EMMC_SEL_HPLL)
971*4882a593Smuzhiyun 			parent = priv->hpll_hz;
972*4882a593Smuzhiyun 		else
973*4882a593Smuzhiyun 			parent = OSC_HZ;
974*4882a593Smuzhiyun 		break;
975*4882a593Smuzhiyun 	case BCLK_EMMC:
976*4882a593Smuzhiyun 		con = readl(&cru->periclksel_con[19]);
977*4882a593Smuzhiyun 		div = (con & BCLK_EMMC_DIV_MASK) >> BCLK_EMMC_DIV_SHIFT;
978*4882a593Smuzhiyun 		sel = (con & BCLK_EMMC_SEL_MASK) >> BCLK_EMMC_SEL_SHIFT;
979*4882a593Smuzhiyun 		if (sel == BCLK_EMMC_SEL_GPLL)
980*4882a593Smuzhiyun 			parent = priv->gpll_hz;
981*4882a593Smuzhiyun 		else
982*4882a593Smuzhiyun 			parent = priv->cpll_hz;
983*4882a593Smuzhiyun 		break;
984*4882a593Smuzhiyun 	default:
985*4882a593Smuzhiyun 		return -ENOENT;
986*4882a593Smuzhiyun 	}
987*4882a593Smuzhiyun 
988*4882a593Smuzhiyun 	return DIV_TO_RATE(parent, div);
989*4882a593Smuzhiyun }
990*4882a593Smuzhiyun 
rk3562_emmc_set_rate(struct rk3562_clk_priv * priv,ulong clk_id,ulong rate)991*4882a593Smuzhiyun static ulong rk3562_emmc_set_rate(struct rk3562_clk_priv *priv, ulong clk_id,
992*4882a593Smuzhiyun 				  ulong rate)
993*4882a593Smuzhiyun {
994*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
995*4882a593Smuzhiyun 	int div, sel;
996*4882a593Smuzhiyun 
997*4882a593Smuzhiyun 	switch (clk_id) {
998*4882a593Smuzhiyun 	case CCLK_EMMC:
999*4882a593Smuzhiyun 		if (OSC_HZ % rate == 0) {
1000*4882a593Smuzhiyun 			div = DIV_ROUND_UP(OSC_HZ, rate);
1001*4882a593Smuzhiyun 			sel = CCLK_EMMC_SEL_24M;
1002*4882a593Smuzhiyun 		} else if ((priv->cpll_hz % rate) == 0) {
1003*4882a593Smuzhiyun 			div = DIV_ROUND_UP(priv->cpll_hz, rate);
1004*4882a593Smuzhiyun 			sel = CCLK_EMMC_SEL_CPLL;
1005*4882a593Smuzhiyun 		} else if ((priv->hpll_hz % rate) == 0) {
1006*4882a593Smuzhiyun 			div = DIV_ROUND_UP(priv->hpll_hz, rate);
1007*4882a593Smuzhiyun 			sel = CCLK_EMMC_SEL_HPLL;
1008*4882a593Smuzhiyun 		} else {
1009*4882a593Smuzhiyun 			div = DIV_ROUND_UP(priv->gpll_hz, rate);
1010*4882a593Smuzhiyun 			sel = CCLK_EMMC_SEL_GPLL;
1011*4882a593Smuzhiyun 		}
1012*4882a593Smuzhiyun 		rk_clrsetreg(&cru->periclksel_con[18],
1013*4882a593Smuzhiyun 			     CCLK_EMMC_SEL_MASK | CCLK_EMMC_DIV_MASK,
1014*4882a593Smuzhiyun 			     sel << CCLK_EMMC_SEL_SHIFT |
1015*4882a593Smuzhiyun 			     (div - 1) << CCLK_EMMC_DIV_SHIFT);
1016*4882a593Smuzhiyun 		break;
1017*4882a593Smuzhiyun 	case BCLK_EMMC:
1018*4882a593Smuzhiyun 		if ((priv->cpll_hz % rate) == 0) {
1019*4882a593Smuzhiyun 			div = DIV_ROUND_UP(priv->cpll_hz, rate);
1020*4882a593Smuzhiyun 			sel = BCLK_EMMC_SEL_CPLL;
1021*4882a593Smuzhiyun 		} else {
1022*4882a593Smuzhiyun 			div = DIV_ROUND_UP(priv->gpll_hz, rate);
1023*4882a593Smuzhiyun 			sel = BCLK_EMMC_SEL_GPLL;
1024*4882a593Smuzhiyun 		}
1025*4882a593Smuzhiyun 		rk_clrsetreg(&cru->periclksel_con[19],
1026*4882a593Smuzhiyun 			     BCLK_EMMC_SEL_MASK | BCLK_EMMC_DIV_MASK,
1027*4882a593Smuzhiyun 			     sel << BCLK_EMMC_SEL_SHIFT |
1028*4882a593Smuzhiyun 			     (div - 1) << BCLK_EMMC_DIV_SHIFT);
1029*4882a593Smuzhiyun 		break;
1030*4882a593Smuzhiyun 	default:
1031*4882a593Smuzhiyun 		return -ENOENT;
1032*4882a593Smuzhiyun 	}
1033*4882a593Smuzhiyun 
1034*4882a593Smuzhiyun 	return rk3562_emmc_get_rate(priv, clk_id);
1035*4882a593Smuzhiyun }
1036*4882a593Smuzhiyun 
rk3562_sdmmc_get_rate(struct rk3562_clk_priv * priv,ulong clk_id)1037*4882a593Smuzhiyun static ulong rk3562_sdmmc_get_rate(struct rk3562_clk_priv *priv, ulong clk_id)
1038*4882a593Smuzhiyun {
1039*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
1040*4882a593Smuzhiyun 	u32 div, sel, con;
1041*4882a593Smuzhiyun 	ulong prate;
1042*4882a593Smuzhiyun 
1043*4882a593Smuzhiyun 	switch (clk_id) {
1044*4882a593Smuzhiyun 	case HCLK_SDMMC0:
1045*4882a593Smuzhiyun 	case CCLK_SDMMC0:
1046*4882a593Smuzhiyun 	case SCLK_SDMMC0_SAMPLE:
1047*4882a593Smuzhiyun 		con = readl(&cru->periclksel_con[16]);
1048*4882a593Smuzhiyun 		div = (con & CCLK_SDMMC0_DIV_MASK) >> CCLK_SDMMC0_DIV_SHIFT;
1049*4882a593Smuzhiyun 		sel = (con & CCLK_SDMMC0_SEL_MASK) >> CCLK_SDMMC0_SEL_SHIFT;
1050*4882a593Smuzhiyun 		break;
1051*4882a593Smuzhiyun 	case HCLK_SDMMC1:
1052*4882a593Smuzhiyun 	case CCLK_SDMMC1:
1053*4882a593Smuzhiyun 	case SCLK_SDMMC1_SAMPLE:
1054*4882a593Smuzhiyun 		con = readl(&cru->periclksel_con[17]);
1055*4882a593Smuzhiyun 		div = (con & CCLK_SDMMC1_DIV_MASK) >> CCLK_SDMMC1_DIV_SHIFT;
1056*4882a593Smuzhiyun 		sel = (con & CCLK_SDMMC1_SEL_MASK) >> CCLK_SDMMC1_SEL_SHIFT;
1057*4882a593Smuzhiyun 		break;
1058*4882a593Smuzhiyun 	default:
1059*4882a593Smuzhiyun 		return -ENOENT;
1060*4882a593Smuzhiyun 	}
1061*4882a593Smuzhiyun 
1062*4882a593Smuzhiyun 	if (sel == CCLK_SDMMC_SEL_GPLL)
1063*4882a593Smuzhiyun 		prate = priv->gpll_hz;
1064*4882a593Smuzhiyun 	else if (sel == CCLK_SDMMC_SEL_CPLL)
1065*4882a593Smuzhiyun 		prate = priv->cpll_hz;
1066*4882a593Smuzhiyun 	else if (sel == CCLK_SDMMC_SEL_HPLL)
1067*4882a593Smuzhiyun 		prate = priv->hpll_hz;
1068*4882a593Smuzhiyun 	else
1069*4882a593Smuzhiyun 		prate = OSC_HZ;
1070*4882a593Smuzhiyun 
1071*4882a593Smuzhiyun 	return DIV_TO_RATE(prate, div);
1072*4882a593Smuzhiyun }
1073*4882a593Smuzhiyun 
rk3562_sdmmc_set_rate(struct rk3562_clk_priv * priv,ulong clk_id,ulong rate)1074*4882a593Smuzhiyun static ulong rk3562_sdmmc_set_rate(struct rk3562_clk_priv *priv,
1075*4882a593Smuzhiyun 				   ulong clk_id, ulong rate)
1076*4882a593Smuzhiyun {
1077*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
1078*4882a593Smuzhiyun 	u32 div, sel;
1079*4882a593Smuzhiyun 
1080*4882a593Smuzhiyun 	if (OSC_HZ % rate == 0) {
1081*4882a593Smuzhiyun 		div = DIV_ROUND_UP(OSC_HZ, rate);
1082*4882a593Smuzhiyun 		sel = CCLK_SDMMC_SEL_24M;
1083*4882a593Smuzhiyun 	} else if ((priv->cpll_hz % rate) == 0) {
1084*4882a593Smuzhiyun 		div = DIV_ROUND_UP(priv->cpll_hz, rate);
1085*4882a593Smuzhiyun 		sel = CCLK_SDMMC_SEL_CPLL;
1086*4882a593Smuzhiyun 	} else if ((priv->hpll_hz % rate) == 0) {
1087*4882a593Smuzhiyun 		div = DIV_ROUND_UP(priv->hpll_hz, rate);
1088*4882a593Smuzhiyun 		sel = CCLK_SDMMC_SEL_HPLL;
1089*4882a593Smuzhiyun 	} else {
1090*4882a593Smuzhiyun 		div = DIV_ROUND_UP(priv->gpll_hz, rate);
1091*4882a593Smuzhiyun 		sel = CCLK_SDMMC_SEL_CPLL;
1092*4882a593Smuzhiyun 	}
1093*4882a593Smuzhiyun 
1094*4882a593Smuzhiyun 	switch (clk_id) {
1095*4882a593Smuzhiyun 	case HCLK_SDMMC0:
1096*4882a593Smuzhiyun 	case CCLK_SDMMC0:
1097*4882a593Smuzhiyun 		rk_clrsetreg(&cru->periclksel_con[16],
1098*4882a593Smuzhiyun 			     CCLK_SDMMC0_SEL_MASK | CCLK_SDMMC0_DIV_MASK,
1099*4882a593Smuzhiyun 			     sel << CCLK_SDMMC0_SEL_SHIFT |
1100*4882a593Smuzhiyun 			     (div - 1) << CCLK_SDMMC0_DIV_SHIFT);
1101*4882a593Smuzhiyun 		break;
1102*4882a593Smuzhiyun 	case HCLK_SDMMC1:
1103*4882a593Smuzhiyun 	case CCLK_SDMMC1:
1104*4882a593Smuzhiyun 		rk_clrsetreg(&cru->periclksel_con[17],
1105*4882a593Smuzhiyun 			     CCLK_SDMMC1_SEL_MASK | CCLK_SDMMC1_DIV_MASK,
1106*4882a593Smuzhiyun 			     sel << CCLK_SDMMC1_SEL_SHIFT |
1107*4882a593Smuzhiyun 			     (div - 1) << CCLK_SDMMC1_DIV_SHIFT);
1108*4882a593Smuzhiyun 		break;
1109*4882a593Smuzhiyun 	default:
1110*4882a593Smuzhiyun 		return -ENOENT;
1111*4882a593Smuzhiyun 	}
1112*4882a593Smuzhiyun 
1113*4882a593Smuzhiyun 	return rk3562_sdmmc_get_rate(priv, clk_id);
1114*4882a593Smuzhiyun }
1115*4882a593Smuzhiyun 
rk3562_vop_get_rate(struct rk3562_clk_priv * priv,ulong clk_id)1116*4882a593Smuzhiyun static ulong rk3562_vop_get_rate(struct rk3562_clk_priv *priv, ulong clk_id)
1117*4882a593Smuzhiyun {
1118*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
1119*4882a593Smuzhiyun 	u32 con, sel, div;
1120*4882a593Smuzhiyun 	ulong prate;
1121*4882a593Smuzhiyun 
1122*4882a593Smuzhiyun 	switch (clk_id) {
1123*4882a593Smuzhiyun 	case ACLK_VOP:
1124*4882a593Smuzhiyun 		con = readl(&cru->clksel_con[28]);
1125*4882a593Smuzhiyun 		div = (con & ACLK_VOP_DIV_MASK) >> ACLK_VOP_DIV_SHIFT;
1126*4882a593Smuzhiyun 		sel = (con & ACLK_VOP_SEL_MASK) >> ACLK_VOP_SEL_SHIFT;
1127*4882a593Smuzhiyun 		if (sel == ACLK_VOP_SEL_GPLL)
1128*4882a593Smuzhiyun 			prate = priv->gpll_hz;
1129*4882a593Smuzhiyun 		else if (sel == ACLK_VOP_SEL_CPLL)
1130*4882a593Smuzhiyun 			prate = priv->cpll_hz;
1131*4882a593Smuzhiyun 		else if (sel == ACLK_VOP_SEL_HPLL)
1132*4882a593Smuzhiyun 			prate = priv->hpll_hz;
1133*4882a593Smuzhiyun 		else if (sel == ACLK_VOP_SEL_VPLL)
1134*4882a593Smuzhiyun 			prate = priv->vpll_hz;
1135*4882a593Smuzhiyun 		else
1136*4882a593Smuzhiyun 			return -ENOENT;
1137*4882a593Smuzhiyun 
1138*4882a593Smuzhiyun 		return DIV_TO_RATE(prate, div);
1139*4882a593Smuzhiyun 	case DCLK_VOP:
1140*4882a593Smuzhiyun 		con = readl(&cru->clksel_con[30]);
1141*4882a593Smuzhiyun 		div = (con & DCLK_VOP_DIV_MASK) >> DCLK_VOP_DIV_SHIFT;
1142*4882a593Smuzhiyun 		sel = (con & DCLK_VOP_SEL_MASK) >> DCLK_VOP_SEL_SHIFT;
1143*4882a593Smuzhiyun 		if (sel == DCLK_VOP_SEL_VPLL)
1144*4882a593Smuzhiyun 			priv->vpll_hz =
1145*4882a593Smuzhiyun 				rockchip_pll_get_rate(&rk3562_pll_clks[VPLL],
1146*4882a593Smuzhiyun 						      priv->cru, VPLL);
1147*4882a593Smuzhiyun 		break;
1148*4882a593Smuzhiyun 	case DCLK_VOP1:
1149*4882a593Smuzhiyun 		con = readl(&cru->clksel_con[31]);
1150*4882a593Smuzhiyun 		div = (con & DCLK_VOP1_DIV_MASK) >> DCLK_VOP1_DIV_SHIFT;
1151*4882a593Smuzhiyun 		sel = (con & DCLK_VOP1_SEL_MASK) >> DCLK_VOP1_SEL_SHIFT;
1152*4882a593Smuzhiyun 		break;
1153*4882a593Smuzhiyun 	default:
1154*4882a593Smuzhiyun 		return -ENOENT;
1155*4882a593Smuzhiyun 	}
1156*4882a593Smuzhiyun 
1157*4882a593Smuzhiyun 	if (sel == DCLK_VOP_SEL_GPLL)
1158*4882a593Smuzhiyun 		prate = priv->gpll_hz;
1159*4882a593Smuzhiyun 	else if (sel == DCLK_VOP_SEL_HPLL)
1160*4882a593Smuzhiyun 		prate = priv->hpll_hz;
1161*4882a593Smuzhiyun 	else if (sel == DCLK_VOP_SEL_VPLL)
1162*4882a593Smuzhiyun 		prate = priv->vpll_hz;
1163*4882a593Smuzhiyun 	else
1164*4882a593Smuzhiyun 		return -ENOENT;
1165*4882a593Smuzhiyun 
1166*4882a593Smuzhiyun 	return DIV_TO_RATE(prate, div);
1167*4882a593Smuzhiyun }
1168*4882a593Smuzhiyun 
1169*4882a593Smuzhiyun #define RK3562_VOP_PLL_LIMIT_FREQ 600000000
1170*4882a593Smuzhiyun 
rk3562_vop_set_rate(struct rk3562_clk_priv * priv,ulong clk_id,ulong rate)1171*4882a593Smuzhiyun static ulong rk3562_vop_set_rate(struct rk3562_clk_priv *priv, ulong clk_id,
1172*4882a593Smuzhiyun 				 ulong rate)
1173*4882a593Smuzhiyun {
1174*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
1175*4882a593Smuzhiyun 	u32 i, div, sel, best_div = 0, best_sel = 0;
1176*4882a593Smuzhiyun 	ulong pll_rate, now, best_rate = 0;
1177*4882a593Smuzhiyun 
1178*4882a593Smuzhiyun 	switch (clk_id) {
1179*4882a593Smuzhiyun 	case ACLK_VOP:
1180*4882a593Smuzhiyun 		if ((priv->cpll_hz % rate) == 0) {
1181*4882a593Smuzhiyun 			div = DIV_ROUND_UP(priv->cpll_hz, rate);
1182*4882a593Smuzhiyun 			sel = ACLK_VOP_SEL_CPLL;
1183*4882a593Smuzhiyun 		} else if ((priv->hpll_hz % rate) == 0) {
1184*4882a593Smuzhiyun 			div = DIV_ROUND_UP(priv->hpll_hz, rate);
1185*4882a593Smuzhiyun 			sel = ACLK_VOP_SEL_HPLL;
1186*4882a593Smuzhiyun 		} else if ((priv->vpll_hz % rate) == 0) {
1187*4882a593Smuzhiyun 			div = DIV_ROUND_UP(priv->vpll_hz, rate);
1188*4882a593Smuzhiyun 			sel = ACLK_VOP_SEL_VPLL;
1189*4882a593Smuzhiyun 		} else {
1190*4882a593Smuzhiyun 			div = DIV_ROUND_UP(priv->gpll_hz, rate);
1191*4882a593Smuzhiyun 			sel = ACLK_VOP_SEL_GPLL;
1192*4882a593Smuzhiyun 		}
1193*4882a593Smuzhiyun 		rk_clrsetreg(&cru->clksel_con[28],
1194*4882a593Smuzhiyun 			     ACLK_VOP_SEL_MASK | ACLK_VOP_DIV_MASK,
1195*4882a593Smuzhiyun 			     sel << ACLK_VOP_SEL_SHIFT |
1196*4882a593Smuzhiyun 			     ((div - 1) << ACLK_VOP_DIV_SHIFT));
1197*4882a593Smuzhiyun 
1198*4882a593Smuzhiyun 		return rk3562_vop_get_rate(priv, clk_id);
1199*4882a593Smuzhiyun 	case DCLK_VOP:
1200*4882a593Smuzhiyun 		div = DIV_ROUND_UP(RK3562_VOP_PLL_LIMIT_FREQ, rate);
1201*4882a593Smuzhiyun 		rk_clrsetreg(&cru->clksel_con[30],
1202*4882a593Smuzhiyun 			     DCLK_VOP_SEL_MASK | DCLK_VOP_DIV_MASK,
1203*4882a593Smuzhiyun 			     DCLK_VOP_SEL_VPLL << DCLK_VOP_SEL_SHIFT |
1204*4882a593Smuzhiyun 			     ((div - 1) << DCLK_VOP_DIV_SHIFT));
1205*4882a593Smuzhiyun 		rockchip_pll_set_rate(&rk3562_pll_clks[VPLL], priv->cru,
1206*4882a593Smuzhiyun 				      VPLL, div * rate);
1207*4882a593Smuzhiyun 		break;
1208*4882a593Smuzhiyun 	case DCLK_VOP1:
1209*4882a593Smuzhiyun 		for (i = 0; i <= DCLK_VOP_SEL_APLL; i++) {
1210*4882a593Smuzhiyun 			switch (i) {
1211*4882a593Smuzhiyun 			case DCLK_VOP_SEL_GPLL:
1212*4882a593Smuzhiyun 				pll_rate = priv->gpll_hz;
1213*4882a593Smuzhiyun 				break;
1214*4882a593Smuzhiyun 			case DCLK_VOP_SEL_HPLL:
1215*4882a593Smuzhiyun 				pll_rate = priv->hpll_hz;
1216*4882a593Smuzhiyun 				break;
1217*4882a593Smuzhiyun 			case DCLK_VOP_SEL_VPLL:
1218*4882a593Smuzhiyun 			case DCLK_VOP_SEL_APLL:
1219*4882a593Smuzhiyun 				continue;
1220*4882a593Smuzhiyun 			default:
1221*4882a593Smuzhiyun 				printf("do not support this vop pll sel\n");
1222*4882a593Smuzhiyun 				return -EINVAL;
1223*4882a593Smuzhiyun 			}
1224*4882a593Smuzhiyun 
1225*4882a593Smuzhiyun 			div = DIV_ROUND_UP(pll_rate, rate);
1226*4882a593Smuzhiyun 			if (div > 255)
1227*4882a593Smuzhiyun 				continue;
1228*4882a593Smuzhiyun 			now = pll_rate / div;
1229*4882a593Smuzhiyun 			if (abs(rate - now) < abs(rate - best_rate)) {
1230*4882a593Smuzhiyun 				best_rate = now;
1231*4882a593Smuzhiyun 				best_div = div;
1232*4882a593Smuzhiyun 				best_sel = i;
1233*4882a593Smuzhiyun 			}
1234*4882a593Smuzhiyun 			debug("p_rate=%lu, best_rate=%lu, div=%u, sel=%u\n",
1235*4882a593Smuzhiyun 			      pll_rate, best_rate, best_div, best_sel);
1236*4882a593Smuzhiyun 		}
1237*4882a593Smuzhiyun 		if (best_rate) {
1238*4882a593Smuzhiyun 			rk_clrsetreg(&cru->clksel_con[31],
1239*4882a593Smuzhiyun 				     DCLK_VOP1_SEL_MASK | DCLK_VOP1_DIV_MASK,
1240*4882a593Smuzhiyun 				     best_sel << DCLK_VOP1_SEL_SHIFT |
1241*4882a593Smuzhiyun 				     (best_div - 1) << DCLK_VOP1_DIV_SHIFT);
1242*4882a593Smuzhiyun 		} else {
1243*4882a593Smuzhiyun 			printf("do not support this vop freq %lu\n", rate);
1244*4882a593Smuzhiyun 			return -EINVAL;
1245*4882a593Smuzhiyun 		}
1246*4882a593Smuzhiyun 		break;
1247*4882a593Smuzhiyun 	default:
1248*4882a593Smuzhiyun 		return -ENOENT;
1249*4882a593Smuzhiyun 	}
1250*4882a593Smuzhiyun 
1251*4882a593Smuzhiyun 	return rk3562_vop_get_rate(priv, clk_id);
1252*4882a593Smuzhiyun }
1253*4882a593Smuzhiyun 
rk3562_gmac_get_rate(struct rk3562_clk_priv * priv,ulong clk_id)1254*4882a593Smuzhiyun static ulong rk3562_gmac_get_rate(struct rk3562_clk_priv *priv, ulong clk_id)
1255*4882a593Smuzhiyun {
1256*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
1257*4882a593Smuzhiyun 	u32 con, sel, div;
1258*4882a593Smuzhiyun 	ulong prate;
1259*4882a593Smuzhiyun 
1260*4882a593Smuzhiyun 	switch (clk_id) {
1261*4882a593Smuzhiyun 	case CLK_GMAC_125M_CRU_I:
1262*4882a593Smuzhiyun 		con = readl(&cru->clksel_con[45]);
1263*4882a593Smuzhiyun 		sel = (con & CLK_GMAC_125M_SEL_MASK) >> CLK_GMAC_125M_SEL_SHIFT;
1264*4882a593Smuzhiyun 		if (sel == CLK_GMAC_125M)
1265*4882a593Smuzhiyun 			return 125000000;
1266*4882a593Smuzhiyun 		else
1267*4882a593Smuzhiyun 			return OSC_HZ;
1268*4882a593Smuzhiyun 	case CLK_GMAC_50M_CRU_I:
1269*4882a593Smuzhiyun 		con = readl(&cru->clksel_con[45]);
1270*4882a593Smuzhiyun 		sel = (con & CLK_GMAC_50M_SEL_MASK) >> CLK_GMAC_50M_SEL_SHIFT;
1271*4882a593Smuzhiyun 		if (sel == CLK_GMAC_50M)
1272*4882a593Smuzhiyun 			return 50000000;
1273*4882a593Smuzhiyun 		else
1274*4882a593Smuzhiyun 			return OSC_HZ;
1275*4882a593Smuzhiyun 	case CLK_MAC100_50M_MATRIX:
1276*4882a593Smuzhiyun 		con = readl(&cru->clksel_con[47]);
1277*4882a593Smuzhiyun 		sel = (con & CLK_GMAC_50M_SEL_MASK) >> CLK_GMAC_50M_SEL_SHIFT;
1278*4882a593Smuzhiyun 		if (sel == CLK_GMAC_50M)
1279*4882a593Smuzhiyun 			return 50000000;
1280*4882a593Smuzhiyun 		else
1281*4882a593Smuzhiyun 			return OSC_HZ;
1282*4882a593Smuzhiyun 	case CLK_GMAC_ETH_OUT2IO:
1283*4882a593Smuzhiyun 		con = readl(&cru->clksel_con[46]);
1284*4882a593Smuzhiyun 		sel = (con & CLK_GMAC_ETH_OUT2IO_SEL_MASK) >> CLK_GMAC_ETH_OUT2IO_SEL_SHIFT;
1285*4882a593Smuzhiyun 		div = (con & CLK_GMAC_ETH_OUT2IO_DIV_MASK) >> CLK_GMAC_ETH_OUT2IO_DIV_SHIFT;
1286*4882a593Smuzhiyun 		if (sel == CLK_GMAC_ETH_OUT2IO_GPLL)
1287*4882a593Smuzhiyun 			prate = priv->gpll_hz;
1288*4882a593Smuzhiyun 		else
1289*4882a593Smuzhiyun 			prate = priv->cpll_hz;
1290*4882a593Smuzhiyun 		break;
1291*4882a593Smuzhiyun 	default:
1292*4882a593Smuzhiyun 		return -ENOENT;
1293*4882a593Smuzhiyun 	}
1294*4882a593Smuzhiyun 
1295*4882a593Smuzhiyun 	return DIV_TO_RATE(prate, div);
1296*4882a593Smuzhiyun }
1297*4882a593Smuzhiyun 
rk3562_gmac_set_rate(struct rk3562_clk_priv * priv,ulong clk_id,ulong rate)1298*4882a593Smuzhiyun static ulong rk3562_gmac_set_rate(struct rk3562_clk_priv *priv, ulong clk_id,
1299*4882a593Smuzhiyun 				  ulong rate)
1300*4882a593Smuzhiyun {
1301*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
1302*4882a593Smuzhiyun 	u32 sel, div;
1303*4882a593Smuzhiyun 
1304*4882a593Smuzhiyun 	switch (clk_id) {
1305*4882a593Smuzhiyun 	case CLK_GMAC_125M_CRU_I:
1306*4882a593Smuzhiyun 		if (rate == 125000000)
1307*4882a593Smuzhiyun 			sel = CLK_GMAC_125M;
1308*4882a593Smuzhiyun 		else
1309*4882a593Smuzhiyun 			sel = CLK_GMAC_24M;
1310*4882a593Smuzhiyun 		rk_clrsetreg(&cru->clksel_con[45], CLK_GMAC_125M_SEL_MASK,
1311*4882a593Smuzhiyun 			     sel << CLK_GMAC_125M_SEL_SHIFT);
1312*4882a593Smuzhiyun 		break;
1313*4882a593Smuzhiyun 	case CLK_GMAC_50M_CRU_I:
1314*4882a593Smuzhiyun 		if (rate == 50000000)
1315*4882a593Smuzhiyun 			sel = CLK_GMAC_50M;
1316*4882a593Smuzhiyun 		else
1317*4882a593Smuzhiyun 			sel = CLK_GMAC_24M;
1318*4882a593Smuzhiyun 		rk_clrsetreg(&cru->clksel_con[45], CLK_GMAC_50M_SEL_MASK,
1319*4882a593Smuzhiyun 			     sel << CLK_GMAC_50M_SEL_SHIFT);
1320*4882a593Smuzhiyun 		break;
1321*4882a593Smuzhiyun 	case CLK_MAC100_50M_MATRIX:
1322*4882a593Smuzhiyun 		if (rate == 50000000)
1323*4882a593Smuzhiyun 			sel = CLK_GMAC_50M;
1324*4882a593Smuzhiyun 		else
1325*4882a593Smuzhiyun 			sel = CLK_GMAC_24M;
1326*4882a593Smuzhiyun 		rk_clrsetreg(&cru->clksel_con[47], CLK_GMAC_50M_SEL_MASK,
1327*4882a593Smuzhiyun 			     sel << CLK_GMAC_50M_SEL_SHIFT);
1328*4882a593Smuzhiyun 		break;
1329*4882a593Smuzhiyun 	case CLK_GMAC_ETH_OUT2IO:
1330*4882a593Smuzhiyun 		if ((priv->cpll_hz % rate) == 0) {
1331*4882a593Smuzhiyun 			div = DIV_ROUND_UP(priv->cpll_hz, rate);
1332*4882a593Smuzhiyun 			sel = CLK_GMAC_ETH_OUT2IO_CPLL;
1333*4882a593Smuzhiyun 		} else {
1334*4882a593Smuzhiyun 			div = DIV_ROUND_UP(priv->gpll_hz, rate);
1335*4882a593Smuzhiyun 			sel = CLK_GMAC_ETH_OUT2IO_GPLL;
1336*4882a593Smuzhiyun 		}
1337*4882a593Smuzhiyun 		rk_clrsetreg(&cru->clksel_con[46],
1338*4882a593Smuzhiyun 			     CLK_GMAC_ETH_OUT2IO_SEL_MASK | CLK_GMAC_ETH_OUT2IO_DIV_MASK,
1339*4882a593Smuzhiyun 			     sel << CLK_GMAC_ETH_OUT2IO_SEL_SHIFT |
1340*4882a593Smuzhiyun 			     (div - 1) << CLK_GMAC_ETH_OUT2IO_DIV_SHIFT);
1341*4882a593Smuzhiyun 		break;
1342*4882a593Smuzhiyun 	default:
1343*4882a593Smuzhiyun 		return -ENOENT;
1344*4882a593Smuzhiyun 	}
1345*4882a593Smuzhiyun 
1346*4882a593Smuzhiyun 	return rk3562_gmac_get_rate(priv, clk_id);
1347*4882a593Smuzhiyun }
1348*4882a593Smuzhiyun 
rk3562_clk_get_rate(struct clk * clk)1349*4882a593Smuzhiyun static ulong rk3562_clk_get_rate(struct clk *clk)
1350*4882a593Smuzhiyun {
1351*4882a593Smuzhiyun 	struct rk3562_clk_priv *priv = dev_get_priv(clk->dev);
1352*4882a593Smuzhiyun 	ulong rate = 0;
1353*4882a593Smuzhiyun 
1354*4882a593Smuzhiyun 	if (!priv->gpll_hz || !priv->cpll_hz || !priv->hpll_hz) {
1355*4882a593Smuzhiyun 		printf("%s: gpll=%lu, cpll=%lu, hpll=%lu\n",
1356*4882a593Smuzhiyun 		       __func__, priv->gpll_hz, priv->cpll_hz, priv->hpll_hz);
1357*4882a593Smuzhiyun 		return -ENOENT;
1358*4882a593Smuzhiyun 	}
1359*4882a593Smuzhiyun 
1360*4882a593Smuzhiyun 	switch (clk->id) {
1361*4882a593Smuzhiyun 	case PLL_APLL:
1362*4882a593Smuzhiyun 	case ARMCLK:
1363*4882a593Smuzhiyun 		rate = rockchip_pll_get_rate(&rk3562_pll_clks[APLL], priv->cru,
1364*4882a593Smuzhiyun 					     APLL);
1365*4882a593Smuzhiyun 		break;
1366*4882a593Smuzhiyun 	case PLL_GPLL:
1367*4882a593Smuzhiyun 		rate = rockchip_pll_get_rate(&rk3562_pll_clks[GPLL], priv->cru,
1368*4882a593Smuzhiyun 					     GPLL);
1369*4882a593Smuzhiyun 		break;
1370*4882a593Smuzhiyun 
1371*4882a593Smuzhiyun 	case PLL_VPLL:
1372*4882a593Smuzhiyun 		rate = rockchip_pll_get_rate(&rk3562_pll_clks[VPLL], priv->cru,
1373*4882a593Smuzhiyun 					     VPLL);
1374*4882a593Smuzhiyun 		break;
1375*4882a593Smuzhiyun 	case PLL_HPLL:
1376*4882a593Smuzhiyun 		rate = rockchip_pll_get_rate(&rk3562_pll_clks[HPLL], priv->cru,
1377*4882a593Smuzhiyun 					     HPLL);
1378*4882a593Smuzhiyun 		break;
1379*4882a593Smuzhiyun 	case PLL_CPLL:
1380*4882a593Smuzhiyun 		rate = rockchip_pll_get_rate(&rk3562_pll_clks[CPLL], priv->cru,
1381*4882a593Smuzhiyun 					     CPLL);
1382*4882a593Smuzhiyun 		break;
1383*4882a593Smuzhiyun 	case PLL_DPLL:
1384*4882a593Smuzhiyun 		rate = rockchip_pll_get_rate(&rk3562_pll_clks[DPLL], priv->cru,
1385*4882a593Smuzhiyun 					     DPLL);
1386*4882a593Smuzhiyun 		break;
1387*4882a593Smuzhiyun 	case ACLK_BUS:
1388*4882a593Smuzhiyun 	case HCLK_BUS:
1389*4882a593Smuzhiyun 	case PCLK_BUS:
1390*4882a593Smuzhiyun 		rate = rk3562_bus_get_rate(priv, clk->id);
1391*4882a593Smuzhiyun 		break;
1392*4882a593Smuzhiyun 	case ACLK_PERI:
1393*4882a593Smuzhiyun 	case HCLK_PERI:
1394*4882a593Smuzhiyun 	case PCLK_PERI:
1395*4882a593Smuzhiyun 		rate = rk3562_peri_get_rate(priv, clk->id);
1396*4882a593Smuzhiyun 		break;
1397*4882a593Smuzhiyun 	case CLK_PMU0_I2C0:
1398*4882a593Smuzhiyun 	case CLK_I2C:
1399*4882a593Smuzhiyun 	case CLK_I2C1:
1400*4882a593Smuzhiyun 	case CLK_I2C2:
1401*4882a593Smuzhiyun 	case CLK_I2C3:
1402*4882a593Smuzhiyun 	case CLK_I2C4:
1403*4882a593Smuzhiyun 	case CLK_I2C5:
1404*4882a593Smuzhiyun 		rate = rk3562_i2c_get_rate(priv, clk->id);
1405*4882a593Smuzhiyun 		break;
1406*4882a593Smuzhiyun 	case SCLK_PMU1_UART0:
1407*4882a593Smuzhiyun 	case SCLK_UART1:
1408*4882a593Smuzhiyun 	case SCLK_UART2:
1409*4882a593Smuzhiyun 	case SCLK_UART3:
1410*4882a593Smuzhiyun 	case SCLK_UART4:
1411*4882a593Smuzhiyun 	case SCLK_UART5:
1412*4882a593Smuzhiyun 	case SCLK_UART6:
1413*4882a593Smuzhiyun 	case SCLK_UART7:
1414*4882a593Smuzhiyun 	case SCLK_UART8:
1415*4882a593Smuzhiyun 	case SCLK_UART9:
1416*4882a593Smuzhiyun 		rate = rk3562_uart_get_rate(priv, clk->id);
1417*4882a593Smuzhiyun 		break;
1418*4882a593Smuzhiyun 	case CLK_PMU1_PWM0:
1419*4882a593Smuzhiyun 	case CLK_PWM1_PERI:
1420*4882a593Smuzhiyun 	case CLK_PWM2_PERI:
1421*4882a593Smuzhiyun 	case CLK_PWM3_PERI:
1422*4882a593Smuzhiyun 		rate = rk3562_pwm_get_rate(priv, clk->id);
1423*4882a593Smuzhiyun 		break;
1424*4882a593Smuzhiyun 	case CLK_PMU1_SPI0:
1425*4882a593Smuzhiyun 	case CLK_SPI1:
1426*4882a593Smuzhiyun 	case CLK_SPI2:
1427*4882a593Smuzhiyun 		rate = rk3562_spi_get_rate(priv, clk->id);
1428*4882a593Smuzhiyun 		break;
1429*4882a593Smuzhiyun 	case CLK_TSADC:
1430*4882a593Smuzhiyun 	case CLK_TSADC_TSEN:
1431*4882a593Smuzhiyun 		rate = rk3562_tsadc_get_rate(priv, clk->id);
1432*4882a593Smuzhiyun 		break;
1433*4882a593Smuzhiyun 	case CLK_SARADC:
1434*4882a593Smuzhiyun 	case CLK_SARADC_VCCIO156:
1435*4882a593Smuzhiyun 		rate = rk3562_saradc_get_rate(priv, clk->id);
1436*4882a593Smuzhiyun 		break;
1437*4882a593Smuzhiyun 	case SCLK_SFC:
1438*4882a593Smuzhiyun 		rate = rk3562_sfc_get_rate(priv);
1439*4882a593Smuzhiyun 		break;
1440*4882a593Smuzhiyun 	case CCLK_EMMC:
1441*4882a593Smuzhiyun 	case BCLK_EMMC:
1442*4882a593Smuzhiyun 		rate = rk3562_emmc_get_rate(priv, clk->id);
1443*4882a593Smuzhiyun 		break;
1444*4882a593Smuzhiyun 	case HCLK_SDMMC0:
1445*4882a593Smuzhiyun 	case HCLK_SDMMC1:
1446*4882a593Smuzhiyun 	case CCLK_SDMMC0:
1447*4882a593Smuzhiyun 	case CCLK_SDMMC1:
1448*4882a593Smuzhiyun 	case SCLK_SDMMC0_SAMPLE:
1449*4882a593Smuzhiyun 	case SCLK_SDMMC1_SAMPLE:
1450*4882a593Smuzhiyun 		rate = rk3562_sdmmc_get_rate(priv, clk->id);
1451*4882a593Smuzhiyun 		break;
1452*4882a593Smuzhiyun 	case ACLK_VOP:
1453*4882a593Smuzhiyun 	case DCLK_VOP:
1454*4882a593Smuzhiyun 	case DCLK_VOP1:
1455*4882a593Smuzhiyun 		rate = rk3562_vop_get_rate(priv, clk->id);
1456*4882a593Smuzhiyun 		break;
1457*4882a593Smuzhiyun 	case CLK_GMAC_125M_CRU_I:
1458*4882a593Smuzhiyun 	case CLK_GMAC_50M_CRU_I:
1459*4882a593Smuzhiyun 	case CLK_GMAC_ETH_OUT2IO:
1460*4882a593Smuzhiyun 	case CLK_MAC100_50M_MATRIX:
1461*4882a593Smuzhiyun 		rate = rk3562_gmac_get_rate(priv, clk->id);
1462*4882a593Smuzhiyun 		break;
1463*4882a593Smuzhiyun 	case CLK_WDTNS:
1464*4882a593Smuzhiyun 		rate = OSC_HZ;
1465*4882a593Smuzhiyun 		break;
1466*4882a593Smuzhiyun 	default:
1467*4882a593Smuzhiyun 		return -ENOENT;
1468*4882a593Smuzhiyun 	}
1469*4882a593Smuzhiyun 
1470*4882a593Smuzhiyun 	return rate;
1471*4882a593Smuzhiyun };
1472*4882a593Smuzhiyun 
rk3562_clk_set_rate(struct clk * clk,ulong rate)1473*4882a593Smuzhiyun static ulong rk3562_clk_set_rate(struct clk *clk, ulong rate)
1474*4882a593Smuzhiyun {
1475*4882a593Smuzhiyun 	struct rk3562_clk_priv *priv = dev_get_priv(clk->dev);
1476*4882a593Smuzhiyun 	ulong ret = 0;
1477*4882a593Smuzhiyun 
1478*4882a593Smuzhiyun 	if (!priv->gpll_hz || !priv->cpll_hz || !priv->hpll_hz) {
1479*4882a593Smuzhiyun 		printf("%s: gpll=%lu, cpll=%lu, hpll=%lu\n",
1480*4882a593Smuzhiyun 		       __func__, priv->gpll_hz, priv->cpll_hz, priv->hpll_hz);
1481*4882a593Smuzhiyun 		return -ENOENT;
1482*4882a593Smuzhiyun 	}
1483*4882a593Smuzhiyun 
1484*4882a593Smuzhiyun 	debug("%s: id=%ld, rate=%ld\n", __func__, clk->id, rate);
1485*4882a593Smuzhiyun 
1486*4882a593Smuzhiyun 	switch (clk->id) {
1487*4882a593Smuzhiyun 	case PLL_APLL:
1488*4882a593Smuzhiyun 	case ARMCLK:
1489*4882a593Smuzhiyun 		if (priv->armclk_hz)
1490*4882a593Smuzhiyun 			rk3562_armclk_set_rate(priv, rate);
1491*4882a593Smuzhiyun 		priv->armclk_hz = rate;
1492*4882a593Smuzhiyun 		break;
1493*4882a593Smuzhiyun 	case PLL_GPLL:
1494*4882a593Smuzhiyun 		ret = rockchip_pll_set_rate(&rk3562_pll_clks[GPLL], priv->cru,
1495*4882a593Smuzhiyun 					    GPLL, rate);
1496*4882a593Smuzhiyun 		priv->gpll_hz = rockchip_pll_get_rate(&rk3562_pll_clks[GPLL],
1497*4882a593Smuzhiyun 						      priv->cru, GPLL);
1498*4882a593Smuzhiyun 		break;
1499*4882a593Smuzhiyun 	case PLL_VPLL:
1500*4882a593Smuzhiyun 		ret = rockchip_pll_set_rate(&rk3562_pll_clks[VPLL], priv->cru,
1501*4882a593Smuzhiyun 					    VPLL, rate);
1502*4882a593Smuzhiyun 		priv->vpll_hz = rockchip_pll_get_rate(&rk3562_pll_clks[VPLL],
1503*4882a593Smuzhiyun 						      priv->cru, VPLL);
1504*4882a593Smuzhiyun 		break;
1505*4882a593Smuzhiyun 	case PLL_HPLL:
1506*4882a593Smuzhiyun 		ret = rockchip_pll_set_rate(&rk3562_pll_clks[HPLL], priv->cru,
1507*4882a593Smuzhiyun 					    HPLL, rate);
1508*4882a593Smuzhiyun 		priv->hpll_hz = rockchip_pll_get_rate(&rk3562_pll_clks[HPLL],
1509*4882a593Smuzhiyun 						      priv->cru, HPLL);
1510*4882a593Smuzhiyun 		break;
1511*4882a593Smuzhiyun 	case ACLK_BUS:
1512*4882a593Smuzhiyun 	case HCLK_BUS:
1513*4882a593Smuzhiyun 	case PCLK_BUS:
1514*4882a593Smuzhiyun 		ret = rk3562_bus_set_rate(priv, clk->id, rate);
1515*4882a593Smuzhiyun 		break;
1516*4882a593Smuzhiyun 	case ACLK_PERI:
1517*4882a593Smuzhiyun 	case HCLK_PERI:
1518*4882a593Smuzhiyun 	case PCLK_PERI:
1519*4882a593Smuzhiyun 		ret = rk3562_peri_set_rate(priv, clk->id, rate);
1520*4882a593Smuzhiyun 		break;
1521*4882a593Smuzhiyun 	case CLK_PMU0_I2C0:
1522*4882a593Smuzhiyun 	case CLK_I2C:
1523*4882a593Smuzhiyun 	case CLK_I2C1:
1524*4882a593Smuzhiyun 	case CLK_I2C2:
1525*4882a593Smuzhiyun 	case CLK_I2C3:
1526*4882a593Smuzhiyun 	case CLK_I2C4:
1527*4882a593Smuzhiyun 	case CLK_I2C5:
1528*4882a593Smuzhiyun 		ret = rk3562_i2c_set_rate(priv, clk->id, rate);
1529*4882a593Smuzhiyun 		break;
1530*4882a593Smuzhiyun 	case SCLK_PMU1_UART0:
1531*4882a593Smuzhiyun 	case SCLK_UART1:
1532*4882a593Smuzhiyun 	case SCLK_UART2:
1533*4882a593Smuzhiyun 	case SCLK_UART3:
1534*4882a593Smuzhiyun 	case SCLK_UART4:
1535*4882a593Smuzhiyun 	case SCLK_UART5:
1536*4882a593Smuzhiyun 	case SCLK_UART6:
1537*4882a593Smuzhiyun 	case SCLK_UART7:
1538*4882a593Smuzhiyun 	case SCLK_UART8:
1539*4882a593Smuzhiyun 	case SCLK_UART9:
1540*4882a593Smuzhiyun 		ret = rk3562_uart_set_rate(priv, clk->id, rate);
1541*4882a593Smuzhiyun 		break;
1542*4882a593Smuzhiyun 	case CLK_PMU1_PWM0:
1543*4882a593Smuzhiyun 	case CLK_PWM1_PERI:
1544*4882a593Smuzhiyun 	case CLK_PWM2_PERI:
1545*4882a593Smuzhiyun 	case CLK_PWM3_PERI:
1546*4882a593Smuzhiyun 		ret = rk3562_pwm_set_rate(priv, clk->id, rate);
1547*4882a593Smuzhiyun 		break;
1548*4882a593Smuzhiyun 	case CLK_PMU1_SPI0:
1549*4882a593Smuzhiyun 	case CLK_SPI1:
1550*4882a593Smuzhiyun 	case CLK_SPI2:
1551*4882a593Smuzhiyun 		ret = rk3562_spi_set_rate(priv, clk->id, rate);
1552*4882a593Smuzhiyun 		break;
1553*4882a593Smuzhiyun 	case CLK_TSADC:
1554*4882a593Smuzhiyun 	case CLK_TSADC_TSEN:
1555*4882a593Smuzhiyun 		ret = rk3562_tsadc_set_rate(priv, clk->id, rate);
1556*4882a593Smuzhiyun 		break;
1557*4882a593Smuzhiyun 	case CLK_SARADC:
1558*4882a593Smuzhiyun 	case CLK_SARADC_VCCIO156:
1559*4882a593Smuzhiyun 		ret = rk3562_saradc_set_rate(priv, clk->id, rate);
1560*4882a593Smuzhiyun 		break;
1561*4882a593Smuzhiyun 	case SCLK_SFC:
1562*4882a593Smuzhiyun 		ret = rk3562_sfc_set_rate(priv, rate);
1563*4882a593Smuzhiyun 		break;
1564*4882a593Smuzhiyun 	case CCLK_EMMC:
1565*4882a593Smuzhiyun 	case BCLK_EMMC:
1566*4882a593Smuzhiyun 		ret = rk3562_emmc_set_rate(priv, clk->id, rate);
1567*4882a593Smuzhiyun 		break;
1568*4882a593Smuzhiyun 	case HCLK_SDMMC0:
1569*4882a593Smuzhiyun 	case HCLK_SDMMC1:
1570*4882a593Smuzhiyun 	case CCLK_SDMMC0:
1571*4882a593Smuzhiyun 	case CCLK_SDMMC1:
1572*4882a593Smuzhiyun 		ret = rk3562_sdmmc_set_rate(priv, clk->id, rate);
1573*4882a593Smuzhiyun 		break;
1574*4882a593Smuzhiyun 	case ACLK_VOP:
1575*4882a593Smuzhiyun 	case DCLK_VOP:
1576*4882a593Smuzhiyun 	case DCLK_VOP1:
1577*4882a593Smuzhiyun 		ret = rk3562_vop_set_rate(priv, clk->id, rate);
1578*4882a593Smuzhiyun 		break;
1579*4882a593Smuzhiyun 	case CLK_GMAC_125M_CRU_I:
1580*4882a593Smuzhiyun 	case CLK_GMAC_50M_CRU_I:
1581*4882a593Smuzhiyun 	case CLK_GMAC_ETH_OUT2IO:
1582*4882a593Smuzhiyun 	case CLK_MAC100_50M_MATRIX:
1583*4882a593Smuzhiyun 		ret = rk3562_gmac_set_rate(priv, clk->id, rate);
1584*4882a593Smuzhiyun 		break;
1585*4882a593Smuzhiyun 	default:
1586*4882a593Smuzhiyun 		return -ENOENT;
1587*4882a593Smuzhiyun 	}
1588*4882a593Smuzhiyun 
1589*4882a593Smuzhiyun 	return ret;
1590*4882a593Smuzhiyun };
1591*4882a593Smuzhiyun 
1592*4882a593Smuzhiyun #define ROCKCHIP_MMC_DELAY_SEL		BIT(11)
1593*4882a593Smuzhiyun #define ROCKCHIP_MMC_DEGREE_SHIFT	1
1594*4882a593Smuzhiyun #define ROCKCHIP_MMC_DEGREE_MASK	(0x3 << ROCKCHIP_MMC_DEGREE_SHIFT)
1595*4882a593Smuzhiyun #define ROCKCHIP_MMC_DELAYNUM_SHIFT	3
1596*4882a593Smuzhiyun #define ROCKCHIP_MMC_DELAYNUM_MASK	(0xff << ROCKCHIP_MMC_DELAYNUM_SHIFT)
1597*4882a593Smuzhiyun #define PSECS_PER_SEC 1000000000000LL
1598*4882a593Smuzhiyun 
1599*4882a593Smuzhiyun /*
1600*4882a593Smuzhiyun  * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
1601*4882a593Smuzhiyun  * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
1602*4882a593Smuzhiyun  */
1603*4882a593Smuzhiyun #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
1604*4882a593Smuzhiyun 
rk3562_mmc_get_phase(struct clk * clk)1605*4882a593Smuzhiyun int rk3562_mmc_get_phase(struct clk *clk)
1606*4882a593Smuzhiyun {
1607*4882a593Smuzhiyun 	struct rk3562_clk_priv *priv = dev_get_priv(clk->dev);
1608*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
1609*4882a593Smuzhiyun 	u32 raw_value, delay_num;
1610*4882a593Smuzhiyun 	u16 degrees = 0;
1611*4882a593Smuzhiyun 	ulong rate;
1612*4882a593Smuzhiyun 
1613*4882a593Smuzhiyun 	rate = rk3562_clk_get_rate(clk);
1614*4882a593Smuzhiyun 	if (rate < 0)
1615*4882a593Smuzhiyun 		return rate;
1616*4882a593Smuzhiyun 
1617*4882a593Smuzhiyun 	if (clk->id == SCLK_SDMMC0_SAMPLE)
1618*4882a593Smuzhiyun 		raw_value = readl(&cru->sdmmc0_con[1]);
1619*4882a593Smuzhiyun 	else if (clk->id == SCLK_SDMMC0_SAMPLE)
1620*4882a593Smuzhiyun 		raw_value = readl(&cru->sdmmc1_con[1]);
1621*4882a593Smuzhiyun 	else
1622*4882a593Smuzhiyun 		return -ENONET;
1623*4882a593Smuzhiyun 
1624*4882a593Smuzhiyun 	raw_value &= ROCKCHIP_MMC_DEGREE_MASK;
1625*4882a593Smuzhiyun 	degrees = (raw_value >>  ROCKCHIP_MMC_DEGREE_SHIFT) * 90;
1626*4882a593Smuzhiyun 
1627*4882a593Smuzhiyun 	if (raw_value & ROCKCHIP_MMC_DELAY_SEL) {
1628*4882a593Smuzhiyun 		/* degrees/delaynum * 10000 */
1629*4882a593Smuzhiyun 		unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) *
1630*4882a593Smuzhiyun 					36 * (rate / 1000000);
1631*4882a593Smuzhiyun 
1632*4882a593Smuzhiyun 		delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
1633*4882a593Smuzhiyun 		delay_num >>= ROCKCHIP_MMC_DELAYNUM_SHIFT;
1634*4882a593Smuzhiyun 		degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000);
1635*4882a593Smuzhiyun 	}
1636*4882a593Smuzhiyun 
1637*4882a593Smuzhiyun 	return degrees % 360;
1638*4882a593Smuzhiyun }
1639*4882a593Smuzhiyun 
rk3562_mmc_set_phase(struct clk * clk,u32 degrees)1640*4882a593Smuzhiyun int rk3562_mmc_set_phase(struct clk *clk, u32 degrees)
1641*4882a593Smuzhiyun {
1642*4882a593Smuzhiyun 	struct rk3562_clk_priv *priv = dev_get_priv(clk->dev);
1643*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
1644*4882a593Smuzhiyun 	u8 nineties, remainder, delay_num;
1645*4882a593Smuzhiyun 	u32 raw_value, delay;
1646*4882a593Smuzhiyun 	ulong rate;
1647*4882a593Smuzhiyun 
1648*4882a593Smuzhiyun 	rate = rk3562_clk_get_rate(clk);
1649*4882a593Smuzhiyun 	if (rate < 0)
1650*4882a593Smuzhiyun 		return rate;
1651*4882a593Smuzhiyun 
1652*4882a593Smuzhiyun 	nineties = degrees / 90;
1653*4882a593Smuzhiyun 	remainder = (degrees % 90);
1654*4882a593Smuzhiyun 
1655*4882a593Smuzhiyun 	/*
1656*4882a593Smuzhiyun 	 * Convert to delay; do a little extra work to make sure we
1657*4882a593Smuzhiyun 	 * don't overflow 32-bit / 64-bit numbers.
1658*4882a593Smuzhiyun 	 */
1659*4882a593Smuzhiyun 	delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */
1660*4882a593Smuzhiyun 	delay *= remainder;
1661*4882a593Smuzhiyun 	delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 *
1662*4882a593Smuzhiyun 				(ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10));
1663*4882a593Smuzhiyun 
1664*4882a593Smuzhiyun 	delay_num = (u8)min_t(u32, delay, 255);
1665*4882a593Smuzhiyun 
1666*4882a593Smuzhiyun 	raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
1667*4882a593Smuzhiyun 	raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_SHIFT;
1668*4882a593Smuzhiyun 	raw_value |= nineties << ROCKCHIP_MMC_DEGREE_SHIFT;
1669*4882a593Smuzhiyun 
1670*4882a593Smuzhiyun 	if (clk->id == SCLK_SDMMC0_SAMPLE)
1671*4882a593Smuzhiyun 		writel(raw_value | 0xffff0000, &cru->sdmmc0_con[1]);
1672*4882a593Smuzhiyun 	else
1673*4882a593Smuzhiyun 		writel(raw_value | 0xffff0000, &cru->sdmmc1_con[1]);
1674*4882a593Smuzhiyun 
1675*4882a593Smuzhiyun 	debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n",
1676*4882a593Smuzhiyun 	      degrees, delay_num, raw_value, rk3562_mmc_get_phase(clk));
1677*4882a593Smuzhiyun 
1678*4882a593Smuzhiyun 	return 0;
1679*4882a593Smuzhiyun }
1680*4882a593Smuzhiyun 
rk3562_clk_get_phase(struct clk * clk)1681*4882a593Smuzhiyun static int rk3562_clk_get_phase(struct clk *clk)
1682*4882a593Smuzhiyun {
1683*4882a593Smuzhiyun 	int ret;
1684*4882a593Smuzhiyun 
1685*4882a593Smuzhiyun 	switch (clk->id) {
1686*4882a593Smuzhiyun 	case SCLK_SDMMC0_SAMPLE:
1687*4882a593Smuzhiyun 	case SCLK_SDMMC1_SAMPLE:
1688*4882a593Smuzhiyun 		ret = rk3562_mmc_get_phase(clk);
1689*4882a593Smuzhiyun 		break;
1690*4882a593Smuzhiyun 	default:
1691*4882a593Smuzhiyun 		return -ENOENT;
1692*4882a593Smuzhiyun 	}
1693*4882a593Smuzhiyun 
1694*4882a593Smuzhiyun 	return ret;
1695*4882a593Smuzhiyun }
1696*4882a593Smuzhiyun 
rk3562_clk_set_phase(struct clk * clk,int degrees)1697*4882a593Smuzhiyun static int rk3562_clk_set_phase(struct clk *clk, int degrees)
1698*4882a593Smuzhiyun {
1699*4882a593Smuzhiyun 	int ret;
1700*4882a593Smuzhiyun 
1701*4882a593Smuzhiyun 	switch (clk->id) {
1702*4882a593Smuzhiyun 	case SCLK_SDMMC0_SAMPLE:
1703*4882a593Smuzhiyun 	case SCLK_SDMMC1_SAMPLE:
1704*4882a593Smuzhiyun 		ret = rk3562_mmc_set_phase(clk, degrees);
1705*4882a593Smuzhiyun 		break;
1706*4882a593Smuzhiyun 	default:
1707*4882a593Smuzhiyun 		return -ENOENT;
1708*4882a593Smuzhiyun 	}
1709*4882a593Smuzhiyun 
1710*4882a593Smuzhiyun 	return ret;
1711*4882a593Smuzhiyun }
1712*4882a593Smuzhiyun 
1713*4882a593Smuzhiyun static struct clk_ops rk3562_clk_ops = {
1714*4882a593Smuzhiyun 	.get_rate = rk3562_clk_get_rate,
1715*4882a593Smuzhiyun 	.set_rate = rk3562_clk_set_rate,
1716*4882a593Smuzhiyun 	.get_phase = rk3562_clk_get_phase,
1717*4882a593Smuzhiyun 	.set_phase = rk3562_clk_set_phase,
1718*4882a593Smuzhiyun };
1719*4882a593Smuzhiyun 
1720*4882a593Smuzhiyun #ifndef CONFIG_SPL_BUILD
1721*4882a593Smuzhiyun /**
1722*4882a593Smuzhiyun  * soc_clk_dump() - Print clock frequencies
1723*4882a593Smuzhiyun  * Returns zero on success
1724*4882a593Smuzhiyun  *
1725*4882a593Smuzhiyun  * Implementation for the clk dump command.
1726*4882a593Smuzhiyun  */
soc_clk_dump(void)1727*4882a593Smuzhiyun int soc_clk_dump(void)
1728*4882a593Smuzhiyun {
1729*4882a593Smuzhiyun 	const struct rk3562_clk_info *clk_dump;
1730*4882a593Smuzhiyun 	struct rk3562_clk_priv *priv;
1731*4882a593Smuzhiyun 	struct udevice *cru_dev;
1732*4882a593Smuzhiyun 	struct clk clk;
1733*4882a593Smuzhiyun 	ulong clk_count = ARRAY_SIZE(clks_dump);
1734*4882a593Smuzhiyun 	ulong rate;
1735*4882a593Smuzhiyun 	int i, ret;
1736*4882a593Smuzhiyun 
1737*4882a593Smuzhiyun 	ret = uclass_get_device_by_driver(UCLASS_CLK,
1738*4882a593Smuzhiyun 					  DM_GET_DRIVER(rockchip_rk3562_cru),
1739*4882a593Smuzhiyun 					  &cru_dev);
1740*4882a593Smuzhiyun 	if (ret) {
1741*4882a593Smuzhiyun 		printf("%s failed to get cru device\n", __func__);
1742*4882a593Smuzhiyun 		return ret;
1743*4882a593Smuzhiyun 	}
1744*4882a593Smuzhiyun 
1745*4882a593Smuzhiyun 	priv = dev_get_priv(cru_dev);
1746*4882a593Smuzhiyun 	printf("CLK: (%s. arm: enter %lu KHz, init %lu KHz, kernel %lu%s)\n",
1747*4882a593Smuzhiyun 	       priv->sync_kernel ? "sync kernel" : "uboot",
1748*4882a593Smuzhiyun 	       priv->armclk_enter_hz / 1000,
1749*4882a593Smuzhiyun 	       priv->armclk_init_hz / 1000,
1750*4882a593Smuzhiyun 	       priv->set_armclk_rate ? priv->armclk_hz / 1000 : 0,
1751*4882a593Smuzhiyun 	       priv->set_armclk_rate ? " KHz" : "N/A");
1752*4882a593Smuzhiyun 	for (i = 0; i < clk_count; i++) {
1753*4882a593Smuzhiyun 		clk_dump = &clks_dump[i];
1754*4882a593Smuzhiyun 		if (clk_dump->name) {
1755*4882a593Smuzhiyun 			clk.id = clk_dump->id;
1756*4882a593Smuzhiyun 			ret = clk_request(cru_dev, &clk);
1757*4882a593Smuzhiyun 			if (ret < 0)
1758*4882a593Smuzhiyun 				return ret;
1759*4882a593Smuzhiyun 
1760*4882a593Smuzhiyun 			rate = clk_get_rate(&clk);
1761*4882a593Smuzhiyun 			clk_free(&clk);
1762*4882a593Smuzhiyun 			if (i == 0) {
1763*4882a593Smuzhiyun 				if (rate < 0)
1764*4882a593Smuzhiyun 					printf("  %s %s\n", clk_dump->name,
1765*4882a593Smuzhiyun 					       "unknown");
1766*4882a593Smuzhiyun 				else
1767*4882a593Smuzhiyun 					printf("  %s %lu KHz\n", clk_dump->name,
1768*4882a593Smuzhiyun 					       rate / 1000);
1769*4882a593Smuzhiyun 			} else {
1770*4882a593Smuzhiyun 				if (rate < 0)
1771*4882a593Smuzhiyun 					printf("  %s %s\n", clk_dump->name,
1772*4882a593Smuzhiyun 					       "unknown");
1773*4882a593Smuzhiyun 				else
1774*4882a593Smuzhiyun 					printf("  %s %lu KHz\n", clk_dump->name,
1775*4882a593Smuzhiyun 					       rate / 1000);
1776*4882a593Smuzhiyun 			}
1777*4882a593Smuzhiyun 		}
1778*4882a593Smuzhiyun 	}
1779*4882a593Smuzhiyun 
1780*4882a593Smuzhiyun 	return 0;
1781*4882a593Smuzhiyun }
1782*4882a593Smuzhiyun #endif
1783*4882a593Smuzhiyun 
rk3562_clk_init(struct rk3562_clk_priv * priv)1784*4882a593Smuzhiyun static void rk3562_clk_init(struct rk3562_clk_priv *priv)
1785*4882a593Smuzhiyun {
1786*4882a593Smuzhiyun 	int ret;
1787*4882a593Smuzhiyun 
1788*4882a593Smuzhiyun 	priv->sync_kernel = false;
1789*4882a593Smuzhiyun 	if (!priv->armclk_enter_hz)
1790*4882a593Smuzhiyun 		priv->armclk_enter_hz =
1791*4882a593Smuzhiyun 			rockchip_pll_get_rate(&rk3562_pll_clks[APLL],
1792*4882a593Smuzhiyun 					      priv->cru, APLL);
1793*4882a593Smuzhiyun 
1794*4882a593Smuzhiyun 	if (!priv->armclk_init_hz) {
1795*4882a593Smuzhiyun #ifdef CONFIG_SPL_BUILD
1796*4882a593Smuzhiyun 		ret = rk3562_armclk_set_rate(priv, APLL_HZ);
1797*4882a593Smuzhiyun 		if (!ret)
1798*4882a593Smuzhiyun 			priv->armclk_init_hz = APLL_HZ;
1799*4882a593Smuzhiyun 
1800*4882a593Smuzhiyun #else
1801*4882a593Smuzhiyun 		struct clk clk;
1802*4882a593Smuzhiyun 
1803*4882a593Smuzhiyun 		ret = rockchip_get_scmi_clk(&clk.dev);
1804*4882a593Smuzhiyun 		if (ret) {
1805*4882a593Smuzhiyun 			printf("Failed to get scmi clk dev\n");
1806*4882a593Smuzhiyun 			return;
1807*4882a593Smuzhiyun 		}
1808*4882a593Smuzhiyun 
1809*4882a593Smuzhiyun 		clk.id = ARMCLK;
1810*4882a593Smuzhiyun 		ret = clk_set_rate(&clk, CPU_PVTPLL_HZ);
1811*4882a593Smuzhiyun 		if (ret < 0) {
1812*4882a593Smuzhiyun 			printf("Failed to set scmi cpu %dhz\n", CPU_PVTPLL_HZ);
1813*4882a593Smuzhiyun 			return;
1814*4882a593Smuzhiyun 		} else {
1815*4882a593Smuzhiyun 			priv->armclk_init_hz = CPU_PVTPLL_HZ;
1816*4882a593Smuzhiyun 		}
1817*4882a593Smuzhiyun #endif
1818*4882a593Smuzhiyun 	}
1819*4882a593Smuzhiyun 	if (priv->cpll_hz != CPLL_HZ) {
1820*4882a593Smuzhiyun 		ret = rockchip_pll_set_rate(&rk3562_pll_clks[CPLL], priv->cru,
1821*4882a593Smuzhiyun 					    CPLL, CPLL_HZ);
1822*4882a593Smuzhiyun 		if (!ret)
1823*4882a593Smuzhiyun 			priv->cpll_hz = CPLL_HZ;
1824*4882a593Smuzhiyun 	}
1825*4882a593Smuzhiyun 
1826*4882a593Smuzhiyun 	if (priv->gpll_hz != GPLL_HZ) {
1827*4882a593Smuzhiyun 		ret = rockchip_pll_set_rate(&rk3562_pll_clks[GPLL], priv->cru,
1828*4882a593Smuzhiyun 					    GPLL, GPLL_HZ);
1829*4882a593Smuzhiyun 		if (!ret)
1830*4882a593Smuzhiyun 			priv->gpll_hz = GPLL_HZ;
1831*4882a593Smuzhiyun 	}
1832*4882a593Smuzhiyun 
1833*4882a593Smuzhiyun 	if (priv->hpll_hz != HPLL_HZ) {
1834*4882a593Smuzhiyun 		ret = rockchip_pll_set_rate(&rk3562_pll_clks[HPLL], priv->cru,
1835*4882a593Smuzhiyun 					    HPLL, HPLL_HZ);
1836*4882a593Smuzhiyun 		if (!ret)
1837*4882a593Smuzhiyun 			priv->hpll_hz = HPLL_HZ;
1838*4882a593Smuzhiyun 	}
1839*4882a593Smuzhiyun }
1840*4882a593Smuzhiyun 
rk3562_clk_probe(struct udevice * dev)1841*4882a593Smuzhiyun static int rk3562_clk_probe(struct udevice *dev)
1842*4882a593Smuzhiyun {
1843*4882a593Smuzhiyun 	struct rk3562_clk_priv *priv = dev_get_priv(dev);
1844*4882a593Smuzhiyun 	int ret;
1845*4882a593Smuzhiyun 
1846*4882a593Smuzhiyun 	rk3562_clk_init(priv);
1847*4882a593Smuzhiyun 
1848*4882a593Smuzhiyun 	/* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
1849*4882a593Smuzhiyun 	ret = clk_set_defaults(dev);
1850*4882a593Smuzhiyun 	if (ret)
1851*4882a593Smuzhiyun 		debug("%s clk_set_defaults failed %d\n", __func__, ret);
1852*4882a593Smuzhiyun 	else
1853*4882a593Smuzhiyun 		priv->sync_kernel = true;
1854*4882a593Smuzhiyun 
1855*4882a593Smuzhiyun 	return 0;
1856*4882a593Smuzhiyun }
1857*4882a593Smuzhiyun 
rk3562_clk_ofdata_to_platdata(struct udevice * dev)1858*4882a593Smuzhiyun static int rk3562_clk_ofdata_to_platdata(struct udevice *dev)
1859*4882a593Smuzhiyun {
1860*4882a593Smuzhiyun 	struct rk3562_clk_priv *priv = dev_get_priv(dev);
1861*4882a593Smuzhiyun 
1862*4882a593Smuzhiyun 	priv->cru = dev_read_addr_ptr(dev);
1863*4882a593Smuzhiyun 
1864*4882a593Smuzhiyun 	return 0;
1865*4882a593Smuzhiyun }
1866*4882a593Smuzhiyun 
rk3562_clk_bind(struct udevice * dev)1867*4882a593Smuzhiyun static int rk3562_clk_bind(struct udevice *dev)
1868*4882a593Smuzhiyun {
1869*4882a593Smuzhiyun 	struct udevice *sys_child, *sf_child;
1870*4882a593Smuzhiyun 	struct softreset_reg *sf_priv;
1871*4882a593Smuzhiyun 	struct sysreset_reg *priv;
1872*4882a593Smuzhiyun 	int ret;
1873*4882a593Smuzhiyun 
1874*4882a593Smuzhiyun 	/* The reset driver does not have a device node, so bind it here */
1875*4882a593Smuzhiyun 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
1876*4882a593Smuzhiyun 				 &sys_child);
1877*4882a593Smuzhiyun 	if (ret) {
1878*4882a593Smuzhiyun 		debug("Warning: No sysreset driver: ret=%d\n", ret);
1879*4882a593Smuzhiyun 	} else {
1880*4882a593Smuzhiyun 		priv = malloc(sizeof(struct sysreset_reg));
1881*4882a593Smuzhiyun 		priv->glb_srst_fst_value = offsetof(struct rk3562_cru,
1882*4882a593Smuzhiyun 						    glb_srst_fst);
1883*4882a593Smuzhiyun 		priv->glb_srst_snd_value = offsetof(struct rk3562_cru,
1884*4882a593Smuzhiyun 						    glb_srst_snd);
1885*4882a593Smuzhiyun 		sys_child->priv = priv;
1886*4882a593Smuzhiyun 	}
1887*4882a593Smuzhiyun 
1888*4882a593Smuzhiyun 	ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
1889*4882a593Smuzhiyun 					 dev_ofnode(dev), &sf_child);
1890*4882a593Smuzhiyun 	if (ret) {
1891*4882a593Smuzhiyun 		debug("Warning: No rockchip reset driver: ret=%d\n", ret);
1892*4882a593Smuzhiyun 	} else {
1893*4882a593Smuzhiyun 		sf_priv = malloc(sizeof(struct softreset_reg));
1894*4882a593Smuzhiyun 		sf_priv->sf_reset_offset = offsetof(struct rk3562_cru,
1895*4882a593Smuzhiyun 						    softrst_con[0]);
1896*4882a593Smuzhiyun 		/* (0x30444 - 0x400) / 4 + 1 = 49170 */
1897*4882a593Smuzhiyun 		sf_priv->sf_reset_num = 49170;
1898*4882a593Smuzhiyun 		sf_child->priv = sf_priv;
1899*4882a593Smuzhiyun 	}
1900*4882a593Smuzhiyun 
1901*4882a593Smuzhiyun 	return 0;
1902*4882a593Smuzhiyun }
1903*4882a593Smuzhiyun 
1904*4882a593Smuzhiyun static const struct udevice_id rk3562_clk_ids[] = {
1905*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk3562-cru" },
1906*4882a593Smuzhiyun 	{ }
1907*4882a593Smuzhiyun };
1908*4882a593Smuzhiyun 
1909*4882a593Smuzhiyun U_BOOT_DRIVER(rockchip_rk3562_cru) = {
1910*4882a593Smuzhiyun 	.name		= "rockchip_rk3562_cru",
1911*4882a593Smuzhiyun 	.id		= UCLASS_CLK,
1912*4882a593Smuzhiyun 	.of_match	= rk3562_clk_ids,
1913*4882a593Smuzhiyun 	.priv_auto_alloc_size = sizeof(struct rk3562_clk_priv),
1914*4882a593Smuzhiyun 	.ofdata_to_platdata = rk3562_clk_ofdata_to_platdata,
1915*4882a593Smuzhiyun 	.ops		= &rk3562_clk_ops,
1916*4882a593Smuzhiyun 	.bind		= rk3562_clk_bind,
1917*4882a593Smuzhiyun 	.probe		= rk3562_clk_probe,
1918*4882a593Smuzhiyun };
1919*4882a593Smuzhiyun 
1920*4882a593Smuzhiyun /* spl scmi clk */
1921*4882a593Smuzhiyun #ifdef CONFIG_SPL_BUILD
1922*4882a593Smuzhiyun 
rk3562_crypto_get_rate(struct rk3562_clk_priv * priv,ulong clk_id)1923*4882a593Smuzhiyun static ulong rk3562_crypto_get_rate(struct rk3562_clk_priv *priv, ulong clk_id)
1924*4882a593Smuzhiyun {
1925*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
1926*4882a593Smuzhiyun 	u32 sel, con;
1927*4882a593Smuzhiyun 	ulong rate;
1928*4882a593Smuzhiyun 
1929*4882a593Smuzhiyun 	con = readl(&cru->periclksel_con[43]);
1930*4882a593Smuzhiyun 	switch (clk_id) {
1931*4882a593Smuzhiyun 	case CLK_CORE_CRYPTO:
1932*4882a593Smuzhiyun 		sel = (con & CLK_CORE_CRYPTO_SEL_MASK) >>
1933*4882a593Smuzhiyun 		       CLK_CORE_CRYPTO_SEL_SHIFT;
1934*4882a593Smuzhiyun 		if (sel == CLK_CORE_CRYPTO_SEL_200M)
1935*4882a593Smuzhiyun 			rate = 200 * MHz;
1936*4882a593Smuzhiyun 		else if (sel == CLK_CORE_CRYPTO_SEL_100M)
1937*4882a593Smuzhiyun 			rate = 100 * MHz;
1938*4882a593Smuzhiyun 		else
1939*4882a593Smuzhiyun 			rate = OSC_HZ;
1940*4882a593Smuzhiyun 		break;
1941*4882a593Smuzhiyun 	case CLK_PKA_CRYPTO:
1942*4882a593Smuzhiyun 		sel = (con & CLK_PKA_CRYPTO_SEL_MASK) >>
1943*4882a593Smuzhiyun 		       CLK_PKA_CRYPTO_SEL_SHIFT;
1944*4882a593Smuzhiyun 		if (sel == CLK_PKA_CRYPTO_SEL_300M)
1945*4882a593Smuzhiyun 			rate = 300 * MHz;
1946*4882a593Smuzhiyun 		else if (sel == CLK_PKA_CRYPTO_SEL_200M)
1947*4882a593Smuzhiyun 			rate = 200 * MHz;
1948*4882a593Smuzhiyun 		else if (sel == CLK_PKA_CRYPTO_SEL_100M)
1949*4882a593Smuzhiyun 			rate = 100 * MHz;
1950*4882a593Smuzhiyun 		else
1951*4882a593Smuzhiyun 			rate = OSC_HZ;
1952*4882a593Smuzhiyun 		break;
1953*4882a593Smuzhiyun 	default:
1954*4882a593Smuzhiyun 		return -ENOENT;
1955*4882a593Smuzhiyun 	}
1956*4882a593Smuzhiyun 
1957*4882a593Smuzhiyun 	return rate;
1958*4882a593Smuzhiyun }
1959*4882a593Smuzhiyun 
rk3562_crypto_set_rate(struct rk3562_clk_priv * priv,ulong clk_id,ulong rate)1960*4882a593Smuzhiyun static ulong rk3562_crypto_set_rate(struct rk3562_clk_priv *priv, ulong clk_id,
1961*4882a593Smuzhiyun 				    ulong rate)
1962*4882a593Smuzhiyun {
1963*4882a593Smuzhiyun 	struct rk3562_cru *cru = priv->cru;
1964*4882a593Smuzhiyun 	u32 mask, shift, sel;
1965*4882a593Smuzhiyun 
1966*4882a593Smuzhiyun 	switch (clk_id) {
1967*4882a593Smuzhiyun 	case CLK_CORE_CRYPTO:
1968*4882a593Smuzhiyun 		mask = CLK_CORE_CRYPTO_SEL_MASK;
1969*4882a593Smuzhiyun 		shift =	CLK_CORE_CRYPTO_SEL_SHIFT;
1970*4882a593Smuzhiyun 		if (rate == 200 * MHz)
1971*4882a593Smuzhiyun 			sel = CLK_CORE_CRYPTO_SEL_200M;
1972*4882a593Smuzhiyun 		else if (rate == 100 * MHz)
1973*4882a593Smuzhiyun 			sel = CLK_CORE_CRYPTO_SEL_100M;
1974*4882a593Smuzhiyun 		else
1975*4882a593Smuzhiyun 			sel = CLK_CORE_CRYPTO_SEL_24M;
1976*4882a593Smuzhiyun 		break;
1977*4882a593Smuzhiyun 	case CLK_PKA_CRYPTO:
1978*4882a593Smuzhiyun 		mask = CLK_PKA_CRYPTO_SEL_MASK;
1979*4882a593Smuzhiyun 		shift =	CLK_PKA_CRYPTO_SEL_SHIFT;
1980*4882a593Smuzhiyun 		if (rate == 300 * MHz)
1981*4882a593Smuzhiyun 			sel = CLK_PKA_CRYPTO_SEL_300M;
1982*4882a593Smuzhiyun 		else if (rate == 200 * MHz)
1983*4882a593Smuzhiyun 			sel = CLK_PKA_CRYPTO_SEL_200M;
1984*4882a593Smuzhiyun 		else if (rate == 100 * MHz)
1985*4882a593Smuzhiyun 			sel = CLK_PKA_CRYPTO_SEL_100M;
1986*4882a593Smuzhiyun 		else
1987*4882a593Smuzhiyun 			sel = CLK_PKA_CRYPTO_SEL_24M;
1988*4882a593Smuzhiyun 		break;
1989*4882a593Smuzhiyun 	default:
1990*4882a593Smuzhiyun 		return -ENOENT;
1991*4882a593Smuzhiyun 	}
1992*4882a593Smuzhiyun 	rk_clrsetreg(&cru->periclksel_con[43], mask, sel << shift);
1993*4882a593Smuzhiyun 
1994*4882a593Smuzhiyun 	return rk3562_crypto_get_rate(priv, clk_id);
1995*4882a593Smuzhiyun }
1996*4882a593Smuzhiyun 
rk3562_clk_scmi_get_rate(struct clk * clk)1997*4882a593Smuzhiyun static ulong rk3562_clk_scmi_get_rate(struct clk *clk)
1998*4882a593Smuzhiyun {
1999*4882a593Smuzhiyun 	struct rk3562_clk_priv *priv = dev_get_priv(clk->dev);
2000*4882a593Smuzhiyun 
2001*4882a593Smuzhiyun 	switch (clk->id) {
2002*4882a593Smuzhiyun 	case CLK_CORE_CRYPTO:
2003*4882a593Smuzhiyun 	case CLK_PKA_CRYPTO:
2004*4882a593Smuzhiyun 		return rk3562_crypto_get_rate(priv, clk->id);
2005*4882a593Smuzhiyun 	default:
2006*4882a593Smuzhiyun 		return -ENOENT;
2007*4882a593Smuzhiyun 	}
2008*4882a593Smuzhiyun };
2009*4882a593Smuzhiyun 
rk3562_clk_scmi_set_rate(struct clk * clk,ulong rate)2010*4882a593Smuzhiyun static ulong rk3562_clk_scmi_set_rate(struct clk *clk, ulong rate)
2011*4882a593Smuzhiyun {
2012*4882a593Smuzhiyun 	struct rk3562_clk_priv *priv = dev_get_priv(clk->dev);
2013*4882a593Smuzhiyun 
2014*4882a593Smuzhiyun 	switch (clk->id) {
2015*4882a593Smuzhiyun 	case CLK_CORE_CRYPTO:
2016*4882a593Smuzhiyun 	case CLK_PKA_CRYPTO:
2017*4882a593Smuzhiyun 		return rk3562_crypto_set_rate(priv, clk->id, rate);
2018*4882a593Smuzhiyun 	default:
2019*4882a593Smuzhiyun 		return -ENOENT;
2020*4882a593Smuzhiyun 	}
2021*4882a593Smuzhiyun 	return 0;
2022*4882a593Smuzhiyun };
2023*4882a593Smuzhiyun 
rk3562_scmi_clk_ofdata_to_platdata(struct udevice * dev)2024*4882a593Smuzhiyun static int rk3562_scmi_clk_ofdata_to_platdata(struct udevice *dev)
2025*4882a593Smuzhiyun {
2026*4882a593Smuzhiyun 	struct rk3562_clk_priv *priv = dev_get_priv(dev);
2027*4882a593Smuzhiyun 
2028*4882a593Smuzhiyun 	priv->cru = (struct rk3562_cru *)0xff100000;
2029*4882a593Smuzhiyun 
2030*4882a593Smuzhiyun 	return 0;
2031*4882a593Smuzhiyun }
2032*4882a593Smuzhiyun 
2033*4882a593Smuzhiyun /* A fake scmi driver for SPL/TPL where smccc agent is not available. */
2034*4882a593Smuzhiyun static const struct clk_ops scmi_clk_ops = {
2035*4882a593Smuzhiyun 	.get_rate = rk3562_clk_scmi_get_rate,
2036*4882a593Smuzhiyun 	.set_rate = rk3562_clk_scmi_set_rate,
2037*4882a593Smuzhiyun };
2038*4882a593Smuzhiyun 
2039*4882a593Smuzhiyun U_BOOT_DRIVER(scmi_clock) = {
2040*4882a593Smuzhiyun 	.name = "scmi_clk",
2041*4882a593Smuzhiyun 	.id = UCLASS_CLK,
2042*4882a593Smuzhiyun 	.ops = &scmi_clk_ops,
2043*4882a593Smuzhiyun 	.priv_auto_alloc_size = sizeof(struct rk3562_clk_priv),
2044*4882a593Smuzhiyun 	.ofdata_to_platdata = rk3562_scmi_clk_ofdata_to_platdata,
2045*4882a593Smuzhiyun };
2046*4882a593Smuzhiyun #endif
2047