xref: /rk3399_rockchip-uboot/drivers/clk/rockchip/clk_rk1808.c (revision 5e8564cf419797f9095431e6eb6f0c00dfa423d2)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd
4  */
5 
6 #include <common.h>
7 #include <bitfield.h>
8 #include <clk-uclass.h>
9 #include <dm.h>
10 #include <errno.h>
11 #include <syscon.h>
12 #include <clk.h>
13 #include <asm/arch/clock.h>
14 #include <asm/arch/cru_rk1808.h>
15 #include <asm/arch/hardware.h>
16 #include <asm/io.h>
17 #include <dm/lists.h>
18 #include <dt-bindings/clock/rk1808-cru.h>
19 #include <div64.h>
20 
21 DECLARE_GLOBAL_DATA_PTR;
22 
23 #define RK1808_CPUCLK_RATE(_rate, _aclk_div, _pclk_div)		\
24 {								\
25 	.rate	= _rate##U,					\
26 	.aclk_div = _aclk_div,					\
27 	.pclk_div = _pclk_div,					\
28 }
29 
30 #define DIV_TO_RATE(input_rate, div)    ((input_rate) / ((div) + 1))
31 
32 static struct rockchip_pll_rate_table rk1808_pll_rates[] = {
33 	/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
34 	RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
35 	RK3036_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0),
36 	RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0),
37 	RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
38 	RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0),
39 	RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0),
40 	RK3036_PLL_RATE(800000000, 6, 400, 2, 1, 1, 0),
41 	RK3036_PLL_RATE(600000000, 1, 75, 3, 1, 1, 0),
42 	RK3036_PLL_RATE(594000000, 2, 99, 2, 1, 1, 0),
43 	RK3036_PLL_RATE(500000000, 6, 250, 2, 1, 1, 0),
44 	RK3036_PLL_RATE(200000000, 1, 200, 6, 4, 1, 0),
45 	RK3036_PLL_RATE(100000000, 1, 150, 6, 6, 1, 0),
46 	{ /* sentinel */ },
47 };
48 
49 #ifndef CONFIG_SPL_BUILD
50 #define RK1808_CLK_DUMP(_id, _name, _iscru)	\
51 {						\
52 	.id = _id,				\
53 	.name = _name,				\
54 	.is_cru = _iscru,			\
55 }
56 
57 static const struct rk1808_clk_info clks_dump[] = {
58 	RK1808_CLK_DUMP(PLL_APLL, "apll", true),
59 	RK1808_CLK_DUMP(PLL_DPLL, "dpll", true),
60 	RK1808_CLK_DUMP(PLL_CPLL, "cpll", true),
61 	RK1808_CLK_DUMP(PLL_GPLL, "gpll", true),
62 	RK1808_CLK_DUMP(PLL_NPLL, "npll", true),
63 	RK1808_CLK_DUMP(PLL_PPLL, "ppll", true),
64 	RK1808_CLK_DUMP(HSCLK_BUS_PRE, "hsclk_bus", true),
65 	RK1808_CLK_DUMP(MSCLK_BUS_PRE, "msclk_bus", true),
66 	RK1808_CLK_DUMP(LSCLK_BUS_PRE, "lsclk_bus", true),
67 	RK1808_CLK_DUMP(MSCLK_PERI, "msclk_peri", true),
68 	RK1808_CLK_DUMP(LSCLK_PERI, "lsclk_peri", true),
69 };
70 #endif
71 
72 static struct rockchip_cpu_rate_table rk1808_cpu_rates[] = {
73 	RK1808_CPUCLK_RATE(1200000000, 1, 5),
74 	RK1808_CPUCLK_RATE(1008000000, 1, 5),
75 	RK1808_CPUCLK_RATE(816000000, 1, 3),
76 	RK1808_CPUCLK_RATE(600000000, 1, 3),
77 };
78 
79 static struct rockchip_pll_clock rk1808_pll_clks[] = {
80 	[APLL] = PLL(pll_rk3036, PLL_APLL, RK1808_PLL_CON(0),
81 		     RK1808_MODE_CON, 0, 10, 0, rk1808_pll_rates),
82 	[DPLL] = PLL(pll_rk3036, PLL_DPLL, RK1808_PLL_CON(8),
83 		     RK1808_MODE_CON, 2, 10, 0, NULL),
84 	[CPLL] = PLL(pll_rk3036, PLL_CPLL, RK1808_PLL_CON(16),
85 		    RK1808_MODE_CON, 4, 10, 0, rk1808_pll_rates),
86 	[GPLL] = PLL(pll_rk3036, PLL_GPLL, RK1808_PLL_CON(24),
87 		     RK1808_MODE_CON, 6, 10, 0, rk1808_pll_rates),
88 	[NPLL] = PLL(pll_rk3036, PLL_NPLL, RK1808_PLL_CON(32),
89 		     RK1808_MODE_CON, 8, 10, 0, rk1808_pll_rates),
90 	[PPLL] = PLL(pll_rk3036, PLL_PPLL, RK1808_PMU_PLL_CON(0),
91 		     RK1808_PMU_MODE_CON, 0, 10, 0, rk1808_pll_rates),
92 };
93 
94 #ifndef CONFIG_SPL_BUILD
95 static ulong rk1808_i2c_get_clk(struct rk1808_clk_priv *priv, ulong clk_id)
96 {
97 	struct rk1808_cru *cru = priv->cru;
98 	u32 div, con;
99 
100 	switch (clk_id) {
101 	case SCLK_PMU_I2C0:
102 		con = readl(&cru->pmu_clksel_con[7]);
103 		div = (con & CLK_I2C0_DIV_CON_MASK) >> CLK_I2C0_DIV_CON_SHIFT;
104 		break;
105 	case SCLK_I2C1:
106 		con = readl(&cru->clksel_con[59]);
107 		div = (con & CLK_I2C1_DIV_CON_MASK)  >> CLK_I2C1_DIV_CON_SHIFT;
108 		break;
109 	case SCLK_I2C2:
110 		con = readl(&cru->clksel_con[59]);
111 		div = (con & CLK_I2C2_DIV_CON_MASK) >> CLK_I2C2_DIV_CON_SHIFT;
112 		break;
113 	case SCLK_I2C3:
114 		con = readl(&cru->clksel_con[60]);
115 		div = (con & CLK_I2C3_DIV_CON_MASK) >> CLK_I2C3_DIV_CON_SHIFT;
116 		break;
117 	case SCLK_I2C4:
118 		con = readl(&cru->clksel_con[71]);
119 		div = (con & CLK_I2C4_DIV_CON_MASK) >> CLK_I2C4_DIV_CON_SHIFT;
120 		break;
121 	case SCLK_I2C5:
122 		con = readl(&cru->clksel_con[71]);
123 		div = (con & CLK_I2C5_DIV_CON_MASK) >> CLK_I2C5_DIV_CON_SHIFT;
124 		break;
125 	default:
126 		printf("do not support this i2c bus\n");
127 		return -EINVAL;
128 	}
129 
130 	return DIV_TO_RATE(priv->gpll_hz, div);
131 }
132 
133 static ulong rk1808_i2c_set_clk(struct rk1808_clk_priv *priv,
134 				ulong clk_id, uint hz)
135 {
136 	struct rk1808_cru *cru = priv->cru;
137 	int src_clk_div;
138 
139 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
140 	assert(src_clk_div - 1 < 127);
141 
142 	switch (clk_id) {
143 	case SCLK_PMU_I2C0:
144 		rk_clrsetreg(&cru->pmu_clksel_con[7],
145 			     CLK_I2C0_DIV_CON_MASK | CLK_I2C0_PLL_SEL_MASK,
146 			     (src_clk_div - 1) << CLK_I2C0_DIV_CON_SHIFT |
147 			     CLK_I2C0_PLL_SEL_PPLL << CLK_I2C0_PLL_SEL_SHIFT);
148 		break;
149 	case SCLK_I2C1:
150 		rk_clrsetreg(&cru->clksel_con[59],
151 			     CLK_I2C1_DIV_CON_MASK | CLK_I2C1_PLL_SEL_MASK,
152 			     (src_clk_div - 1) << CLK_I2C1_DIV_CON_SHIFT |
153 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT);
154 		break;
155 	case SCLK_I2C2:
156 		rk_clrsetreg(&cru->clksel_con[59],
157 			     CLK_I2C2_DIV_CON_MASK | CLK_I2C2_PLL_SEL_MASK,
158 			     (src_clk_div - 1) << CLK_I2C2_DIV_CON_SHIFT |
159 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C2_PLL_SEL_SHIFT);
160 		break;
161 	case SCLK_I2C3:
162 		rk_clrsetreg(&cru->clksel_con[60],
163 			     CLK_I2C3_DIV_CON_MASK | CLK_I2C3_PLL_SEL_MASK,
164 			     (src_clk_div - 1) << CLK_I2C3_DIV_CON_SHIFT |
165 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT);
166 		break;
167 	case SCLK_I2C4:
168 		rk_clrsetreg(&cru->clksel_con[71],
169 			     CLK_I2C4_DIV_CON_MASK | CLK_I2C4_PLL_SEL_MASK,
170 			     (src_clk_div - 1) << CLK_I2C4_DIV_CON_SHIFT |
171 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C4_PLL_SEL_SHIFT);
172 		break;
173 	case SCLK_I2C5:
174 		rk_clrsetreg(&cru->clksel_con[71],
175 			     CLK_I2C5_DIV_CON_MASK | CLK_I2C5_PLL_SEL_MASK,
176 			     (src_clk_div - 1) << CLK_I2C5_DIV_CON_SHIFT |
177 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C5_PLL_SEL_SHIFT);
178 		break;
179 	default:
180 		printf("do not support this i2c bus\n");
181 		return -EINVAL;
182 	}
183 
184 	return rk1808_i2c_get_clk(priv, clk_id);
185 }
186 #endif
187 
188 static ulong rk1808_mmc_get_clk(struct rk1808_clk_priv *priv, uint clk_id)
189 {
190 	struct rk1808_cru *cru = priv->cru;
191 	u32 div, con, con_id;
192 
193 	switch (clk_id) {
194 	case HCLK_SDMMC:
195 	case SCLK_SDMMC:
196 		con_id = 20;
197 		break;
198 	case HCLK_SDIO:
199 	case SCLK_SDIO:
200 		con_id = 22;
201 		break;
202 	case HCLK_EMMC:
203 	case SCLK_EMMC:
204 	case SCLK_EMMC_SAMPLE:
205 		con_id = 24;
206 		break;
207 	default:
208 		return -EINVAL;
209 	}
210 
211 	con = readl(&cru->clksel_con[con_id]);
212 	div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT;
213 
214 	if ((con & EMMC_PLL_MASK) >> EMMC_PLL_SHIFT
215 	    == EMMC_SEL_24M)
216 		return DIV_TO_RATE(OSC_HZ, div) / 2;
217 	else
218 		return DIV_TO_RATE(priv->gpll_hz, div) / 2;
219 }
220 
221 static ulong rk1808_mmc_set_clk(struct rk1808_clk_priv *priv,
222 				ulong clk_id, ulong set_rate)
223 {
224 	struct rk1808_cru *cru = priv->cru;
225 	int src_clk_div;
226 	u32 con_id;
227 
228 	switch (clk_id) {
229 	case HCLK_SDMMC:
230 	case SCLK_SDMMC:
231 		con_id = 20;
232 		break;
233 	case HCLK_SDIO:
234 	case SCLK_SDIO:
235 		con_id = 22;
236 		break;
237 	case HCLK_EMMC:
238 	case SCLK_EMMC:
239 		con_id = 24;
240 		break;
241 	default:
242 		return -EINVAL;
243 	}
244 
245 	/* Select clk_sdmmc/emmc source from GPLL by default */
246 	/* mmc clock defaulg div 2 internal, need provide double in cru */
247 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz / 2, set_rate);
248 
249 	if (src_clk_div > 127) {
250 		/* use 24MHz source for 400KHz clock */
251 		src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate);
252 		rk_clrsetreg(&cru->clksel_con[con_id],
253 			     EMMC_PLL_MASK | EMMC_DIV_MASK,
254 			     EMMC_SEL_24M << EMMC_PLL_SHIFT |
255 			     (src_clk_div - 1) << EMMC_DIV_SHIFT);
256 	} else {
257 		rk_clrsetreg(&cru->clksel_con[con_id],
258 			     EMMC_PLL_MASK | EMMC_DIV_MASK,
259 			     EMMC_SEL_GPLL << EMMC_PLL_SHIFT |
260 			     (src_clk_div - 1) << EMMC_DIV_SHIFT);
261 	}
262 	rk_clrsetreg(&cru->clksel_con[con_id + 1], EMMC_CLK_SEL_MASK,
263 		     EMMC_CLK_SEL_EMMC);
264 
265 	return rk1808_mmc_get_clk(priv, clk_id);
266 }
267 
268 #ifndef CONFIG_SPL_BUILD
269 static ulong rk1808_pwm_get_clk(struct rk1808_clk_priv *priv, ulong clk_id)
270 {
271 	struct rk1808_cru *cru = priv->cru;
272 	u32 div, con;
273 
274 	switch (clk_id) {
275 	case SCLK_PWM0:
276 		con = readl(&cru->clksel_con[69]);
277 		div = (con & CLK_PWM0_DIV_CON_MASK) >> CLK_PWM0_DIV_CON_SHIFT;
278 		break;
279 	case SCLK_PWM1:
280 		con = readl(&cru->clksel_con[69]);
281 		div = (con & CLK_PWM1_DIV_CON_MASK) >> CLK_PWM1_DIV_CON_SHIFT;
282 		break;
283 	case SCLK_PWM2:
284 		con = readl(&cru->clksel_con[70]);
285 		div = (con & CLK_PWM2_DIV_CON_MASK) >> CLK_PWM2_DIV_CON_SHIFT;
286 		break;
287 	default:
288 		printf("do not support this pwm bus\n");
289 		return -EINVAL;
290 	}
291 
292 	return DIV_TO_RATE(priv->gpll_hz, div);
293 }
294 
295 static ulong rk1808_pwm_set_clk(struct rk1808_clk_priv *priv,
296 				ulong clk_id, uint hz)
297 {
298 	struct rk1808_cru *cru = priv->cru;
299 	int src_clk_div;
300 
301 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
302 	assert(src_clk_div - 1 < 127);
303 
304 	switch (clk_id) {
305 	case SCLK_PWM0:
306 		rk_clrsetreg(&cru->clksel_con[69],
307 			     CLK_PWM0_DIV_CON_MASK | CLK_PWM0_PLL_SEL_MASK,
308 			     (src_clk_div - 1) << CLK_PWM0_DIV_CON_SHIFT |
309 			     CLK_PWM_PLL_SEL_GPLL << CLK_PWM0_PLL_SEL_SHIFT);
310 		break;
311 	case SCLK_PWM1:
312 		rk_clrsetreg(&cru->clksel_con[69],
313 			     CLK_PWM1_DIV_CON_MASK | CLK_PWM1_PLL_SEL_MASK,
314 			     (src_clk_div - 1) << CLK_PWM1_DIV_CON_SHIFT |
315 			     CLK_PWM_PLL_SEL_GPLL << CLK_PWM1_PLL_SEL_SHIFT);
316 		break;
317 	case SCLK_PWM2:
318 		rk_clrsetreg(&cru->clksel_con[70],
319 			     CLK_PWM2_DIV_CON_MASK | CLK_PWM2_PLL_SEL_MASK,
320 			     (src_clk_div - 1) << CLK_PWM2_DIV_CON_SHIFT |
321 			     CLK_PWM_PLL_SEL_GPLL << CLK_PWM2_PLL_SEL_SHIFT);
322 		break;
323 	default:
324 		printf("do not support this pwm bus\n");
325 		return -EINVAL;
326 	}
327 
328 	return rk1808_pwm_get_clk(priv, clk_id);
329 }
330 
331 static ulong rk1808_saradc_get_clk(struct rk1808_clk_priv *priv)
332 {
333 	struct rk1808_cru *cru = priv->cru;
334 	u32 div, con;
335 
336 	con = readl(&cru->clksel_con[63]);
337 	div = con & CLK_SARADC_DIV_CON_MASK;
338 
339 	return DIV_TO_RATE(OSC_HZ, div);
340 }
341 
342 static ulong rk1808_saradc_set_clk(struct rk1808_clk_priv *priv, uint hz)
343 {
344 	struct rk1808_cru *cru = priv->cru;
345 	int src_clk_div;
346 
347 	src_clk_div = DIV_ROUND_UP(OSC_HZ, hz);
348 	assert(src_clk_div - 1 < 2047);
349 
350 	rk_clrsetreg(&cru->clksel_con[63],
351 		     CLK_SARADC_DIV_CON_MASK,
352 		     (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT);
353 
354 	return rk1808_saradc_get_clk(priv);
355 }
356 
357 static ulong rk1808_tsadc_get_clk(struct rk1808_clk_priv *priv)
358 {
359 	struct rk1808_cru *cru = priv->cru;
360 	u32 div, con;
361 
362 	con = readl(&cru->clksel_con[62]);
363 	div = con & CLK_SARADC_DIV_CON_MASK;
364 
365 	return DIV_TO_RATE(OSC_HZ, div);
366 }
367 
368 static ulong rk1808_tsadc_set_clk(struct rk1808_clk_priv *priv, uint hz)
369 {
370 	struct rk1808_cru *cru = priv->cru;
371 	int src_clk_div;
372 
373 	src_clk_div = DIV_ROUND_UP(OSC_HZ, hz);
374 	assert(src_clk_div - 1 < 2047);
375 
376 	rk_clrsetreg(&cru->clksel_con[62],
377 		     CLK_SARADC_DIV_CON_MASK,
378 		     (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT);
379 
380 	return rk1808_tsadc_get_clk(priv);
381 }
382 
383 static ulong rk1808_spi_get_clk(struct rk1808_clk_priv *priv, ulong clk_id)
384 {
385 	struct rk1808_cru *cru = priv->cru;
386 	u32 div, con;
387 
388 	switch (clk_id) {
389 	case SCLK_SPI0:
390 		con = readl(&cru->clksel_con[60]);
391 		div = (con & CLK_SPI0_DIV_CON_MASK) >> CLK_SPI0_DIV_CON_SHIFT;
392 		break;
393 	case SCLK_SPI1:
394 		con = readl(&cru->clksel_con[61]);
395 		div = (con & CLK_SPI1_DIV_CON_MASK) >> CLK_SPI1_DIV_CON_SHIFT;
396 		break;
397 	case SCLK_SPI2:
398 		con = readl(&cru->clksel_con[61]);
399 		div = (con & CLK_SPI2_DIV_CON_MASK) >> CLK_SPI2_DIV_CON_SHIFT;
400 		break;
401 	default:
402 		printf("do not support this pwm bus\n");
403 		return -EINVAL;
404 	}
405 
406 	return DIV_TO_RATE(priv->gpll_hz, div);
407 }
408 
409 static ulong rk1808_spi_set_clk(struct rk1808_clk_priv *priv,
410 				ulong clk_id, uint hz)
411 {
412 	struct rk1808_cru *cru = priv->cru;
413 	int src_clk_div;
414 
415 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
416 	assert(src_clk_div - 1 < 127);
417 
418 	switch (clk_id) {
419 	case SCLK_SPI0:
420 		rk_clrsetreg(&cru->clksel_con[60],
421 			     CLK_SPI0_DIV_CON_MASK | CLK_SPI0_PLL_SEL_MASK,
422 			     (src_clk_div - 1) << CLK_SPI0_DIV_CON_SHIFT |
423 			     CLK_SPI_PLL_SEL_GPLL << CLK_SPI0_PLL_SEL_SHIFT);
424 		break;
425 	case SCLK_SPI1:
426 		rk_clrsetreg(&cru->clksel_con[61],
427 			     CLK_SPI1_DIV_CON_MASK | CLK_SPI1_PLL_SEL_MASK,
428 			     (src_clk_div - 1) << CLK_SPI1_DIV_CON_SHIFT |
429 			     CLK_SPI_PLL_SEL_GPLL << CLK_SPI1_PLL_SEL_SHIFT);
430 		break;
431 	case SCLK_SPI2:
432 		rk_clrsetreg(&cru->clksel_con[61],
433 			     CLK_SPI2_DIV_CON_MASK | CLK_SPI2_PLL_SEL_MASK,
434 			     (src_clk_div - 1) << CLK_SPI2_DIV_CON_SHIFT |
435 			     CLK_SPI_PLL_SEL_GPLL << CLK_SPI2_PLL_SEL_SHIFT);
436 		break;
437 	default:
438 		printf("do not support this pwm bus\n");
439 		return -EINVAL;
440 	}
441 
442 	return rk1808_spi_get_clk(priv, clk_id);
443 }
444 
445 #define RK1808_VOP_PLL_LIMIT_FREQ		600 * 1000000
446 static ulong rk1808_vop_get_clk(struct rk1808_clk_priv *priv, ulong clk_id)
447 {
448 	struct rk1808_cru *cru = priv->cru;
449 	u32 div, con, parent;
450 
451 	switch (clk_id) {
452 	case ACLK_VOPRAW:
453 	case ACLK_VOPLITE:
454 		con = readl(&cru->clksel_con[4]);
455 		div = (con & ACLK_VOP_DIV_CON_MASK) >> ACLK_VOP_DIV_CON_SHIFT;
456 		parent = priv->gpll_hz;
457 		break;
458 	case HCLK_VOPRAW:
459 	case HCLK_VOPLITE:
460 		parent = rk1808_vop_get_clk(priv, ACLK_VOPRAW);
461 		con = readl(&cru->clksel_con[4]);
462 		div = (con & HCLK_VOP_DIV_CON_MASK) >> HCLK_VOP_DIV_CON_SHIFT;
463 		break;
464 	case DCLK_VOPRAW:
465 		con = readl(&cru->clksel_con[5]);
466 		div = con & DCLK_VOPRAW_DIV_CON_MASK;
467 		parent = rockchip_pll_get_rate(&rk1808_pll_clks[NPLL],
468 					       priv->cru, NPLL);
469 		break;
470 	case DCLK_VOPLITE:
471 		con = readl(&cru->clksel_con[7]);
472 		div = con & DCLK_VOPLITE_DIV_CON_MASK;
473 		parent = (con & DCLK_VOPLITE_PLL_SEL_MASK) >>
474 			 DCLK_VOPLITE_PLL_SEL_SHIFT;
475 		if (parent == DCLK_VOPLITE_PLL_SEL_NPLL)
476 			parent = rockchip_pll_get_rate(&rk1808_pll_clks[NPLL],
477 						       priv->cru, NPLL);
478 		else if (parent == DCLK_VOPLITE_PLL_SEL_CPLL)
479 			parent = priv->cpll_hz;
480 		else
481 			parent = priv->gpll_hz;
482 		break;
483 	default:
484 		return -ENOENT;
485 	}
486 
487 	return DIV_TO_RATE(parent, div);
488 }
489 
490 static ulong rk1808_vop_set_clk(struct rk1808_clk_priv *priv,
491 				ulong clk_id, uint hz)
492 {
493 	struct rk1808_cru *cru = priv->cru;
494 	int src_clk_div, parent;
495 
496 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
497 	assert(src_clk_div - 1 < 31);
498 
499 	switch (clk_id) {
500 	case ACLK_VOPRAW:
501 	case ACLK_VOPLITE:
502 		rk_clrsetreg(&cru->clksel_con[4],
503 			     ACLK_VOP_PLL_SEL_MASK | ACLK_VOP_DIV_CON_MASK,
504 			     ACLK_VOP_PLL_SEL_GPLL << ACLK_VOP_PLL_SEL_SHIFT |
505 			     (src_clk_div - 1) << ACLK_VOP_DIV_CON_SHIFT);
506 		break;
507 	case HCLK_VOPRAW:
508 	case HCLK_VOPLITE:
509 		src_clk_div =
510 			DIV_ROUND_UP(rk1808_vop_get_clk(priv, ACLK_VOPRAW), hz);
511 		assert(src_clk_div - 1 < 15);
512 		rk_clrsetreg(&cru->clksel_con[4],
513 			     HCLK_VOP_DIV_CON_MASK,
514 			     (src_clk_div - 1) << HCLK_VOP_DIV_CON_SHIFT);
515 		break;
516 	case DCLK_VOPRAW:
517 		/*
518 		 * vopb dclk source from npll, and equals to
519 		 */
520 		src_clk_div = DIV_ROUND_UP(RK1808_VOP_PLL_LIMIT_FREQ, hz);
521 		rk_clrsetreg(&cru->clksel_con[5],
522 			     DCLK_VOPRAW_SEL_MASK |
523 			     DCLK_VOPRAW_PLL_SEL_MASK |
524 			     DCLK_VOPRAW_DIV_CON_MASK,
525 			     (DCLK_VOPRAW_SEL_VOPRAW <<
526 			     DCLK_VOPRAW_SEL_SHIFT) |
527 			     (DCLK_VOPRAW_PLL_SEL_NPLL <<
528 			     DCLK_VOPRAW_PLL_SEL_SHIFT) |
529 			     ((src_clk_div - 1) << DCLK_VOPRAW_DIV_CON_SHIFT));
530 		rockchip_pll_set_rate(&rk1808_pll_clks[NPLL],
531 				      priv->cru, NPLL, src_clk_div * hz);
532 
533 		break;
534 	case DCLK_VOPLITE:
535 		/*
536 		 * vopl dclk source from cpll, and equals to
537 		 */
538 		if (!(priv->cpll_hz % hz)) {
539 			parent = DCLK_VOPLITE_PLL_SEL_CPLL;
540 			src_clk_div = DIV_ROUND_UP(priv->cpll_hz, hz);
541 		} else if (!(priv->gpll_hz % hz)) {
542 			parent = DCLK_VOPLITE_PLL_SEL_GPLL;
543 			src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
544 		} else {
545 			parent = DCLK_VOPLITE_PLL_SEL_NPLL;
546 			src_clk_div = DIV_ROUND_UP(RK1808_VOP_PLL_LIMIT_FREQ,
547 						   hz);
548 			rockchip_pll_set_rate(&rk1808_pll_clks[NPLL],
549 					      priv->cru, NPLL,
550 					      src_clk_div * hz);
551 		}
552 		rk_clrsetreg(&cru->clksel_con[7],
553 			     DCLK_VOPLITE_SEL_MASK | DCLK_VOPLITE_PLL_SEL_MASK |
554 			     DCLK_VOPLITE_DIV_CON_MASK,
555 			     (DCLK_VOPLITE_SEL_VOPRAW <<
556 			     DCLK_VOPLITE_SEL_SHIFT) |
557 			     (parent << DCLK_VOPLITE_PLL_SEL_SHIFT) |
558 			     ((src_clk_div - 1) << DCLK_VOPLITE_DIV_CON_SHIFT));
559 		break;
560 	default:
561 		printf("do not support this vop freq\n");
562 		return -EINVAL;
563 	}
564 
565 	return rk1808_vop_get_clk(priv, clk_id);
566 }
567 
568 static ulong rk1808_mac_set_clk(struct clk *clk, uint hz)
569 {
570 	struct rk1808_clk_priv *priv = dev_get_priv(clk->dev);
571 	struct rk1808_cru *cru = priv->cru;
572 	u32 con = readl(&cru->clksel_con[26]);
573 	ulong pll_rate;
574 	u8 div;
575 
576 	if ((con >> GMAC_PLL_SEL_SHIFT) & GMAC_PLL_SEL_NPLL)
577 		pll_rate = rockchip_pll_get_rate(&rk1808_pll_clks[NPLL],
578 						 priv->cru, NPLL);
579 	else if ((con >> GMAC_PLL_SEL_SHIFT) & GMAC_PLL_SEL_PPLL)
580 		pll_rate = rockchip_pll_get_rate(&rk1808_pll_clks[PPLL],
581 						 priv->cru, PPLL);
582 	else
583 		pll_rate = rockchip_pll_get_rate(&rk1808_pll_clks[CPLL],
584 						 priv->cru, CPLL);
585 
586 	/*default set 50MHZ for gmac*/
587 	if (!hz)
588 		hz = 50000000;
589 
590 	div = DIV_ROUND_UP(pll_rate, hz) - 1;
591 	assert(div < 32);
592 	rk_clrsetreg(&cru->clksel_con[26], CLK_GMAC_DIV_MASK,
593 		     div << CLK_GMAC_DIV_SHIFT);
594 
595 	return DIV_TO_RATE(pll_rate, div);
596 }
597 
598 static int rk1808_mac_set_speed_clk(struct clk *clk, ulong clk_id, uint hz)
599 {
600 	struct rk1808_clk_priv *priv = dev_get_priv(clk->dev);
601 	struct rk1808_cru *cru = priv->cru;
602 	u32 sel;
603 
604 	switch (clk_id) {
605 	case SCLK_GMAC_RGMII_SPEED:
606 		if (hz == 125000000)
607 			sel = 0;
608 		else if (hz == 2500000)
609 			sel = 2;
610 		else
611 			sel = 3;
612 		rk_clrsetreg(&cru->clksel_con[27], RGMII_CLK_SEL_MASK,
613 			     sel << RGMII_CLK_SEL_SHIFT);
614 		break;
615 	case SCLK_GMAC_RMII_SPEED:
616 		if (hz == 2500000)
617 			sel = 0;
618 		else
619 			sel = 1;
620 		rk_clrsetreg(&cru->clksel_con[27], RMII_CLK_SEL_MASK,
621 			     sel << RMII_CLK_SEL_SHIFT);
622 		break;
623 	default:
624 		return -ENOENT;
625 	}
626 	return 0;
627 }
628 
629 static ulong rk1808_crypto_get_clk(struct rk1808_clk_priv *priv, ulong clk_id)
630 {
631 	struct rk1808_cru *cru = priv->cru;
632 	u32 div, con, parent;
633 
634 	switch (clk_id) {
635 	case SCLK_CRYPTO:
636 		con = readl(&cru->clksel_con[29]);
637 		div = (con & CRYPTO_DIV_MASK) >> CRYPTO_DIV_SHIFT;
638 		parent = priv->gpll_hz;
639 		break;
640 	case SCLK_CRYPTO_APK:
641 		con = readl(&cru->clksel_con[29]);
642 		div = (con & CRYPTO_APK_DIV_MASK) >> CRYPTO_APK_DIV_SHIFT;
643 		parent = priv->gpll_hz;
644 		break;
645 	default:
646 		return -ENOENT;
647 	}
648 
649 	return DIV_TO_RATE(parent, div);
650 }
651 
652 static ulong rk1808_crypto_set_clk(struct rk1808_clk_priv *priv, ulong clk_id,
653 				   ulong hz)
654 {
655 	struct rk1808_cru *cru = priv->cru;
656 	int src_clk_div;
657 
658 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
659 	assert(src_clk_div - 1 <= 31);
660 
661 	/*
662 	 * select gpll as crypto clock source and
663 	 * set up dependent divisors for crypto clocks.
664 	 */
665 	switch (clk_id) {
666 	case SCLK_CRYPTO:
667 		rk_clrsetreg(&cru->clksel_con[29],
668 			     CRYPTO_PLL_SEL_MASK | CRYPTO_DIV_MASK,
669 			     CRYPTO_PLL_SEL_GPLL << CRYPTO_PLL_SEL_SHIFT |
670 			     (src_clk_div - 1) << CRYPTO_DIV_SHIFT);
671 		break;
672 	case SCLK_CRYPTO_APK:
673 		rk_clrsetreg(&cru->clksel_con[29],
674 			     CRYPTO_APK_PLL_SEL_MASK | CRYPTO_APK_DIV_MASK,
675 			     CRYPTO_PLL_SEL_GPLL << CRYPTO_APK_SEL_SHIFT |
676 			     (src_clk_div - 1) << CRYPTO_APK_DIV_SHIFT);
677 		break;
678 	default:
679 		printf("do not support this peri freq\n");
680 		return -EINVAL;
681 	}
682 
683 	return rk1808_crypto_get_clk(priv, clk_id);
684 }
685 #endif
686 
687 static ulong rk1808_bus_get_clk(struct rk1808_clk_priv *priv, ulong clk_id)
688 {
689 	struct rk1808_cru *cru = priv->cru;
690 	u32 div, con, parent;
691 
692 	switch (clk_id) {
693 	case HSCLK_BUS_PRE:
694 		con = readl(&cru->clksel_con[27]);
695 		div = (con & HSCLK_BUS_DIV_CON_MASK) >> HSCLK_BUS_DIV_CON_SHIFT;
696 		parent = priv->gpll_hz;
697 		break;
698 	case MSCLK_BUS_PRE:
699 		con = readl(&cru->clksel_con[28]);
700 		div = (con & MSCLK_BUS_DIV_CON_MASK) >> MSCLK_BUS_DIV_CON_SHIFT;
701 		parent = priv->gpll_hz;
702 		break;
703 	case LSCLK_BUS_PRE:
704 	case PCLK_WDT:
705 		con = readl(&cru->clksel_con[28]);
706 		div = (con & LSCLK_BUS_DIV_CON_MASK) >> LSCLK_BUS_DIV_CON_SHIFT;
707 		parent = priv->gpll_hz;
708 		break;
709 	default:
710 		return -ENOENT;
711 	}
712 
713 	return DIV_TO_RATE(parent, div);
714 }
715 
716 static ulong rk1808_bus_set_clk(struct rk1808_clk_priv *priv,
717 				ulong clk_id, ulong hz)
718 {
719 	struct rk1808_cru *cru = priv->cru;
720 	int src_clk_div;
721 
722 	/*
723 	 * select gpll as pd_bus bus clock source and
724 	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
725 	 */
726 	switch (clk_id) {
727 	case HSCLK_BUS_PRE:
728 		src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
729 		assert(src_clk_div - 1 < 31);
730 		rk_clrsetreg(&cru->clksel_con[27],
731 			     CLK_BUS_PLL_SEL_MASK | HSCLK_BUS_DIV_CON_MASK,
732 			     CLK_BUS_PLL_SEL_GPLL << CLK_BUS_PLL_SEL_SHIFT |
733 			     (src_clk_div - 1) << HSCLK_BUS_DIV_CON_SHIFT);
734 		break;
735 	case MSCLK_BUS_PRE:
736 		src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
737 		assert(src_clk_div - 1 < 31);
738 		rk_clrsetreg(&cru->clksel_con[28],
739 			     CLK_BUS_PLL_SEL_MASK | MSCLK_BUS_DIV_CON_MASK,
740 			     CLK_BUS_PLL_SEL_GPLL << CLK_BUS_PLL_SEL_SHIFT |
741 			     (src_clk_div - 1) << MSCLK_BUS_DIV_CON_SHIFT);
742 		break;
743 	case LSCLK_BUS_PRE:
744 		src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
745 		assert(src_clk_div - 1 < 31);
746 		rk_clrsetreg(&cru->clksel_con[28],
747 			     CLK_BUS_PLL_SEL_MASK | LSCLK_BUS_DIV_CON_MASK,
748 			     CLK_BUS_PLL_SEL_GPLL << CLK_BUS_PLL_SEL_SHIFT |
749 			     (src_clk_div - 1) << LSCLK_BUS_DIV_CON_SHIFT);
750 		break;
751 	default:
752 		printf("do not support this bus freq\n");
753 		return -EINVAL;
754 	}
755 
756 	return rk1808_bus_get_clk(priv, clk_id);
757 }
758 
759 static ulong rk1808_peri_get_clk(struct rk1808_clk_priv *priv, ulong clk_id)
760 {
761 	struct rk1808_cru *cru = priv->cru;
762 	u32 div, con, parent;
763 
764 	switch (clk_id) {
765 	case MSCLK_PERI:
766 		con = readl(&cru->clksel_con[19]);
767 		div = (con & MSCLK_PERI_DIV_CON_MASK) >>
768 		      MSCLK_PERI_DIV_CON_SHIFT;
769 		parent = priv->gpll_hz;
770 		break;
771 	case LSCLK_PERI:
772 		con = readl(&cru->clksel_con[19]);
773 		div = (con & LSCLK_PERI_DIV_CON_MASK) >>
774 		      LSCLK_PERI_DIV_CON_SHIFT;
775 		parent = priv->gpll_hz;
776 		break;
777 	default:
778 		return -ENOENT;
779 	}
780 
781 	return DIV_TO_RATE(parent, div);
782 }
783 
784 static ulong rk1808_peri_set_clk(struct rk1808_clk_priv *priv,
785 				 ulong clk_id, ulong hz)
786 {
787 	struct rk1808_cru *cru = priv->cru;
788 	int src_clk_div;
789 
790 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
791 	assert(src_clk_div - 1 < 31);
792 
793 	/*
794 	 * select gpll as pd_peri bus clock source and
795 	 * set up dependent divisors for HCLK and ACLK clocks.
796 	 */
797 	switch (clk_id) {
798 	case MSCLK_PERI:
799 		rk_clrsetreg(&cru->clksel_con[19],
800 			     CLK_PERI_PLL_SEL_MASK | MSCLK_PERI_DIV_CON_MASK,
801 			     CLK_PERI_PLL_SEL_GPLL << CLK_PERI_PLL_SEL_SHIFT |
802 			     (src_clk_div - 1) << MSCLK_PERI_DIV_CON_SHIFT);
803 		break;
804 	case LSCLK_PERI:
805 		rk_clrsetreg(&cru->clksel_con[19],
806 			     CLK_PERI_PLL_SEL_MASK | LSCLK_PERI_DIV_CON_MASK,
807 			     CLK_PERI_PLL_SEL_GPLL << CLK_PERI_PLL_SEL_SHIFT |
808 			     (src_clk_div - 1) << LSCLK_PERI_DIV_CON_SHIFT);
809 		break;
810 	default:
811 		printf("do not support this peri freq\n");
812 		return -EINVAL;
813 	}
814 
815 	return rk1808_peri_get_clk(priv, clk_id);
816 }
817 
818 static ulong rk1808_pclk_pmu_set_clk(struct rk1808_clk_priv *priv,
819 				     ulong clk_id, ulong parent_hz, ulong hz)
820 {
821 	struct rk1808_cru *cru = priv->cru;
822 	int src_clk_div;
823 
824 	src_clk_div = DIV_ROUND_UP(parent_hz, hz);
825 	assert(src_clk_div - 1 < 31);
826 
827 	rk_clrsetreg(&cru->pmu_clksel_con[0],
828 		     PCLK_PMU_DIV_CON_MASK,
829 		     (src_clk_div - 1) << PCLK_PMU_DIV_CON_SHIFT);
830 
831 	return parent_hz / src_clk_div;
832 }
833 
834 static ulong rk1808_armclk_set_clk(struct rk1808_clk_priv *priv, ulong hz)
835 {
836 	struct rk1808_cru *cru = priv->cru;
837 	const struct rockchip_cpu_rate_table *rate;
838 	ulong old_rate;
839 
840 	rate = rockchip_get_cpu_settings(rk1808_cpu_rates, hz);
841 	if (!rate) {
842 		printf("%s unsupported rate\n", __func__);
843 		return -EINVAL;
844 	}
845 
846 	/*
847 	 * select apll as cpu/core clock pll source and
848 	 * set up dependent divisors for PERI and ACLK clocks.
849 	 * core hz : apll = 1:1
850 	 */
851 	old_rate = rockchip_pll_get_rate(&rk1808_pll_clks[APLL],
852 					 priv->cru, APLL);
853 	if (old_rate > hz) {
854 		if (rockchip_pll_set_rate(&rk1808_pll_clks[APLL],
855 					  priv->cru, APLL, hz))
856 			return -EINVAL;
857 		rk_clrsetreg(&cru->clksel_con[0],
858 			     CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
859 			     CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
860 			     rate->aclk_div << CORE_ACLK_DIV_SHIFT |
861 			     rate->pclk_div << CORE_DBG_DIV_SHIFT |
862 			     CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
863 			     0 << CORE_DIV_CON_SHIFT);
864 	} else if (old_rate < hz) {
865 		rk_clrsetreg(&cru->clksel_con[0],
866 			     CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
867 			     CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
868 			     rate->aclk_div << CORE_ACLK_DIV_SHIFT |
869 			     rate->pclk_div << CORE_DBG_DIV_SHIFT |
870 			     CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
871 			     0 << CORE_DIV_CON_SHIFT);
872 		if (rockchip_pll_set_rate(&rk1808_pll_clks[APLL],
873 					  priv->cru, APLL, hz))
874 			return -EINVAL;
875 	}
876 
877 	return rockchip_pll_get_rate(&rk1808_pll_clks[APLL], priv->cru, APLL);
878 }
879 
880 static ulong rk1808_clk_get_rate(struct clk *clk)
881 {
882 	struct rk1808_clk_priv *priv = dev_get_priv(clk->dev);
883 	ulong rate = 0;
884 
885 	debug("%s %ld\n", __func__, clk->id);
886 	switch (clk->id) {
887 	case PLL_APLL:
888 	case PLL_DPLL:
889 	case PLL_CPLL:
890 	case PLL_GPLL:
891 	case PLL_NPLL:
892 	case PLL_PPLL:
893 		rate = rockchip_pll_get_rate(&rk1808_pll_clks[clk->id - 1],
894 					     priv->cru, clk->id - 1);
895 		break;
896 	case ARMCLK:
897 		rate = rockchip_pll_get_rate(&rk1808_pll_clks[APLL],
898 					     priv->cru, APLL);
899 		break;
900 	case HCLK_SDMMC:
901 	case HCLK_EMMC:
902 	case HCLK_SDIO:
903 	case SCLK_SDMMC:
904 	case SCLK_EMMC:
905 	case SCLK_EMMC_SAMPLE:
906 	case SCLK_SDIO:
907 		rate = rk1808_mmc_get_clk(priv, clk->id);
908 		break;
909 #ifndef CONFIG_SPL_BUILD
910 	case SCLK_PMU_I2C0:
911 	case SCLK_I2C1:
912 	case SCLK_I2C2:
913 	case SCLK_I2C3:
914 	case SCLK_I2C4:
915 	case SCLK_I2C5:
916 		rate = rk1808_i2c_get_clk(priv, clk->id);
917 		break;
918 	case SCLK_PWM0:
919 	case SCLK_PWM1:
920 	case SCLK_PWM2:
921 		rate = rk1808_pwm_get_clk(priv, clk->id);
922 		break;
923 	case SCLK_SARADC:
924 		rate = rk1808_saradc_get_clk(priv);
925 		break;
926 	case SCLK_TSADC:
927 		rate = rk1808_tsadc_get_clk(priv);
928 		break;
929 	case SCLK_SPI0:
930 	case SCLK_SPI1:
931 	case SCLK_SPI2:
932 		rate = rk1808_spi_get_clk(priv, clk->id);
933 		break;
934 	case ACLK_VOPRAW:
935 	case DCLK_VOPRAW:
936 	case ACLK_VOPLITE:
937 	case DCLK_VOPLITE:
938 		rate = rk1808_vop_get_clk(priv, clk->id);
939 		break;
940 	case SCLK_CRYPTO:
941 	case SCLK_CRYPTO_APK:
942 		rate = rk1808_crypto_get_clk(priv, clk->id);
943 		break;
944 #endif
945 	case HSCLK_BUS_PRE:
946 	case MSCLK_BUS_PRE:
947 	case LSCLK_BUS_PRE:
948 	case PCLK_WDT:
949 		rate = rk1808_bus_get_clk(priv, clk->id);
950 		break;
951 	case MSCLK_PERI:
952 	case LSCLK_PERI:
953 		rate = rk1808_peri_get_clk(priv, clk->id);
954 		break;
955 	default:
956 		return -ENOENT;
957 	}
958 
959 	return rate;
960 }
961 
962 static ulong rk1808_clk_set_rate(struct clk *clk, ulong rate)
963 {
964 	struct rk1808_clk_priv *priv = dev_get_priv(clk->dev);
965 	ulong ret = 0;
966 
967 	debug("%s %ld %ld\n", __func__, clk->id, rate);
968 	switch (clk->id) {
969 	case PLL_APLL:
970 	case PLL_DPLL:
971 		ret = rockchip_pll_set_rate(&rk1808_pll_clks[clk->id - 1],
972 					    priv->cru, clk->id - 1, rate);
973 		break;
974 	case PLL_PPLL:
975 		ret = rk1808_pclk_pmu_set_clk(priv, clk->id, rate, PCLK_PMU_HZ);
976 		ret = rockchip_pll_set_rate(&rk1808_pll_clks[PPLL],
977 					    priv->cru, PPLL, rate);
978 		break;
979 	case PLL_CPLL:
980 		ret = rockchip_pll_set_rate(&rk1808_pll_clks[CPLL],
981 					    priv->cru, CPLL, rate);
982 		if (ret == 0)
983 			priv->cpll_hz = rate;
984 		break;
985 	case PLL_GPLL:
986 		ret = rockchip_pll_set_rate(&rk1808_pll_clks[GPLL],
987 					    priv->cru, GPLL, rate);
988 		if (ret == 0)
989 			priv->gpll_hz = rate;
990 		break;
991 	case PLL_NPLL:
992 		ret = rockchip_pll_set_rate(&rk1808_pll_clks[NPLL],
993 					    priv->cru, NPLL, rate);
994 		if (ret == 0)
995 			priv->npll_hz = rate;
996 		break;
997 	case ARMCLK:
998 		if (priv->armclk_hz)
999 			rk1808_armclk_set_clk(priv, rate);
1000 		priv->armclk_hz = rate;
1001 		break;
1002 	case HCLK_SDMMC:
1003 	case HCLK_EMMC:
1004 	case HCLK_SDIO:
1005 	case SCLK_SDMMC:
1006 	case SCLK_EMMC:
1007 	case SCLK_SDIO:
1008 		ret = rk1808_mmc_set_clk(priv, clk->id, rate);
1009 		break;
1010 #ifndef CONFIG_SPL_BUILD
1011 	case SCLK_PMU_I2C0:
1012 	case SCLK_I2C1:
1013 	case SCLK_I2C2:
1014 	case SCLK_I2C3:
1015 	case SCLK_I2C4:
1016 	case SCLK_I2C5:
1017 		ret = rk1808_i2c_set_clk(priv, clk->id, rate);
1018 		break;
1019 	case SCLK_PWM0:
1020 	case SCLK_PWM1:
1021 	case SCLK_PWM2:
1022 		ret = rk1808_pwm_set_clk(priv, clk->id, rate);
1023 		break;
1024 	case SCLK_SARADC:
1025 		ret = rk1808_saradc_set_clk(priv, rate);
1026 		break;
1027 	case SCLK_TSADC:
1028 		ret = rk1808_tsadc_set_clk(priv, rate);
1029 		break;
1030 	case SCLK_SPI0:
1031 	case SCLK_SPI1:
1032 	case SCLK_SPI2:
1033 		ret = rk1808_spi_set_clk(priv, clk->id, rate);
1034 		break;
1035 	case ACLK_VOPRAW:
1036 	case DCLK_VOPRAW:
1037 	case ACLK_VOPLITE:
1038 	case DCLK_VOPLITE:
1039 		ret = rk1808_vop_set_clk(priv, clk->id, rate);
1040 		break;
1041 	case SCLK_GMAC:
1042 	case SCLK_GMAC_SRC:
1043 		ret = rk1808_mac_set_clk(clk, rate);
1044 		break;
1045 	case SCLK_GMAC_RMII_SPEED:
1046 	case SCLK_GMAC_RGMII_SPEED:
1047 		ret = rk1808_mac_set_speed_clk(clk, clk->id, rate);
1048 		break;
1049 	case SCLK_CRYPTO:
1050 	case SCLK_CRYPTO_APK:
1051 		ret = rk1808_crypto_set_clk(priv, clk->id, rate);
1052 		break;
1053 #endif
1054 	case HSCLK_BUS_PRE:
1055 	case MSCLK_BUS_PRE:
1056 	case LSCLK_BUS_PRE:
1057 		ret = rk1808_bus_set_clk(priv, clk->id, rate);
1058 		break;
1059 	case MSCLK_PERI:
1060 	case LSCLK_PERI:
1061 		ret = rk1808_peri_set_clk(priv, clk->id, rate);
1062 		break;
1063 	case SCLK_32K_IOE:
1064 		return 0;
1065 	default:
1066 		return -ENOENT;
1067 	}
1068 
1069 	return ret;
1070 }
1071 
1072 #define ROCKCHIP_MMC_DELAY_SEL		BIT(10)
1073 #define ROCKCHIP_MMC_DEGREE_MASK	0x3
1074 #define ROCKCHIP_MMC_DELAYNUM_OFFSET	2
1075 #define ROCKCHIP_MMC_DELAYNUM_MASK	(0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
1076 
1077 #define PSECS_PER_SEC 1000000000000LL
1078 /*
1079  * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
1080  * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
1081  */
1082 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
1083 
1084 int rk1808_mmc_get_phase(struct clk *clk)
1085 {
1086 	struct rk1808_clk_priv *priv = dev_get_priv(clk->dev);
1087 	struct rk1808_cru *cru = priv->cru;
1088 	u32 raw_value, delay_num;
1089 	u16 degrees = 0;
1090 	ulong rate;
1091 
1092 	rate = rk1808_clk_get_rate(clk);
1093 
1094 	if (rate < 0)
1095 		return rate;
1096 
1097 	if (clk->id == SCLK_EMMC_SAMPLE)
1098 		raw_value = readl(&cru->emmc_con[1]);
1099 	else if (clk->id == SCLK_SDMMC_SAMPLE)
1100 		raw_value = readl(&cru->sdmmc_con[1]);
1101 	else
1102 		raw_value = readl(&cru->sdio_con[1]);
1103 
1104 	raw_value >>= 1;
1105 	degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
1106 
1107 	if (raw_value & ROCKCHIP_MMC_DELAY_SEL) {
1108 		/* degrees/delaynum * 10000 */
1109 		unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) *
1110 					36 * (rate / 1000000);
1111 
1112 		delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
1113 		delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET;
1114 		degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000);
1115 	}
1116 
1117 	return degrees % 360;
1118 }
1119 
1120 int rk1808_mmc_set_phase(struct clk *clk, u32 degrees)
1121 {
1122 	struct rk1808_clk_priv *priv = dev_get_priv(clk->dev);
1123 	struct rk1808_cru *cru = priv->cru;
1124 	u8 nineties, remainder, delay_num;
1125 	u32 raw_value, delay;
1126 	ulong rate;
1127 
1128 	rate = rk1808_clk_get_rate(clk);
1129 
1130 	if (rate < 0)
1131 		return rate;
1132 
1133 	nineties = degrees / 90;
1134 	remainder = (degrees % 90);
1135 
1136 	/*
1137 	 * Convert to delay; do a little extra work to make sure we
1138 	 * don't overflow 32-bit / 64-bit numbers.
1139 	 */
1140 	delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */
1141 	delay *= remainder;
1142 	delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 *
1143 				(ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10));
1144 
1145 	delay_num = (u8)min_t(u32, delay, 255);
1146 
1147 	raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
1148 	raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
1149 	raw_value |= nineties;
1150 
1151 	raw_value <<= 1;
1152 	if (clk->id == SCLK_EMMC_SAMPLE)
1153 		writel(raw_value | 0xffff0000, &cru->emmc_con[1]);
1154 	else if (clk->id == SCLK_SDMMC_SAMPLE)
1155 		writel(raw_value | 0xffff0000, &cru->sdmmc_con[1]);
1156 	else
1157 		writel(raw_value | 0xffff0000, &cru->sdio_con[1]);
1158 
1159 	debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n",
1160 	      degrees, delay_num, raw_value, rk1808_mmc_get_phase(clk));
1161 
1162 	return 0;
1163 }
1164 
1165 static int rk1808_clk_get_phase(struct clk *clk)
1166 {
1167 	int ret;
1168 
1169 	debug("%s %ld\n", __func__, clk->id);
1170 	switch (clk->id) {
1171 	case SCLK_EMMC_SAMPLE:
1172 	case SCLK_SDMMC_SAMPLE:
1173 	case SCLK_SDIO_SAMPLE:
1174 		ret = rk1808_mmc_get_phase(clk);
1175 		break;
1176 	default:
1177 		return -ENOENT;
1178 	}
1179 
1180 	return ret;
1181 }
1182 
1183 static int rk1808_clk_set_phase(struct clk *clk, int degrees)
1184 {
1185 	int ret;
1186 
1187 	debug("%s %ld\n", __func__, clk->id);
1188 	switch (clk->id) {
1189 	case SCLK_EMMC_SAMPLE:
1190 	case SCLK_SDMMC_SAMPLE:
1191 	case SCLK_SDIO_SAMPLE:
1192 		ret = rk1808_mmc_set_phase(clk, degrees);
1193 		break;
1194 	default:
1195 		return -ENOENT;
1196 	}
1197 
1198 	return ret;
1199 }
1200 
1201 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
1202 static int rk1808_gmac_set_parent(struct clk *clk, struct clk *parent)
1203 {
1204 	struct rk1808_clk_priv *priv = dev_get_priv(clk->dev);
1205 	struct rk1808_cru *cru = priv->cru;
1206 
1207 	if (parent->id == SCLK_GMAC_SRC) {
1208 		debug("%s: switching GAMC to SCLK_GMAC_SRC\n", __func__);
1209 		rk_clrsetreg(&cru->clksel_con[27], RMII_EXTCLK_SEL_MASK,
1210 			     RMII_EXTCLK_SEL_INT << RMII_EXTCLK_SEL_SHIFT);
1211 	} else {
1212 		debug("%s: switching GMAC to external clock\n", __func__);
1213 		rk_clrsetreg(&cru->clksel_con[27], RMII_EXTCLK_SEL_MASK,
1214 			     RMII_EXTCLK_SEL_EXT << RMII_EXTCLK_SEL_SHIFT);
1215 	}
1216 	return 0;
1217 }
1218 
1219 static int rk1808_clk_set_parent(struct clk *clk, struct clk *parent)
1220 {
1221 	switch (clk->id) {
1222 	case SCLK_GMAC:
1223 		return rk1808_gmac_set_parent(clk, parent);
1224 	case SCLK_32K_IOE:
1225 		return 0;
1226 	default:
1227 		return -ENOENT;
1228 	}
1229 }
1230 #endif
1231 
1232 static struct clk_ops rk1808_clk_ops = {
1233 	.get_rate = rk1808_clk_get_rate,
1234 	.set_rate = rk1808_clk_set_rate,
1235 	.get_phase	= rk1808_clk_get_phase,
1236 	.set_phase	= rk1808_clk_set_phase,
1237 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
1238 	.set_parent	= rk1808_clk_set_parent,
1239 #endif
1240 };
1241 
1242 static int rk1808_clk_probe(struct udevice *dev)
1243 {
1244 	struct rk1808_clk_priv *priv = dev_get_priv(dev);
1245 	int ret;
1246 
1247 	priv->sync_kernel = false;
1248 	if (!priv->armclk_enter_hz) {
1249 		priv->armclk_enter_hz =
1250 		rockchip_pll_get_rate(&rk1808_pll_clks[APLL],
1251 				      priv->cru, APLL);
1252 		priv->armclk_init_hz = priv->armclk_enter_hz;
1253 	}
1254 	if (rockchip_pll_get_rate(&rk1808_pll_clks[APLL],
1255 				  priv->cru, APLL) != APLL_HZ) {
1256 		ret = rk1808_armclk_set_clk(priv, APLL_HZ);
1257 		if (ret < 0)
1258 			printf("%s failed to set armclk rate\n", __func__);
1259 		priv->armclk_init_hz = APLL_HZ;
1260 	}
1261 
1262 	priv->cpll_hz = rockchip_pll_get_rate(&rk1808_pll_clks[CPLL],
1263 					      priv->cru, CPLL);
1264 	priv->gpll_hz = rockchip_pll_get_rate(&rk1808_pll_clks[GPLL],
1265 					      priv->cru, GPLL);
1266 	priv->npll_hz = rockchip_pll_get_rate(&rk1808_pll_clks[NPLL],
1267 					      priv->cru, NPLL);
1268 
1269 	/* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
1270 	ret = clk_set_defaults(dev);
1271 	if (ret)
1272 		debug("%s clk_set_defaults failed %d\n", __func__, ret);
1273 	else
1274 		priv->sync_kernel = true;
1275 
1276 	return 0;
1277 }
1278 
1279 static int rk1808_clk_ofdata_to_platdata(struct udevice *dev)
1280 {
1281 	struct rk1808_clk_priv *priv = dev_get_priv(dev);
1282 
1283 	priv->cru = dev_read_addr_ptr(dev);
1284 
1285 	return 0;
1286 }
1287 
1288 static int rk1808_clk_bind(struct udevice *dev)
1289 {
1290 	int ret;
1291 	struct udevice *sys_child, *sf_child;
1292 	struct sysreset_reg *priv;
1293 	struct softreset_reg *sf_priv;
1294 
1295 	/* The reset driver does not have a device node, so bind it here */
1296 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
1297 				 &sys_child);
1298 	if (ret) {
1299 		debug("Warning: No sysreset driver: ret=%d\n", ret);
1300 	} else {
1301 		priv = malloc(sizeof(struct sysreset_reg));
1302 		priv->glb_srst_fst_value = offsetof(struct rk1808_cru,
1303 						    glb_srst_fst);
1304 		priv->glb_srst_snd_value = offsetof(struct rk1808_cru,
1305 						    glb_srst_snd);
1306 		sys_child->priv = priv;
1307 	}
1308 
1309 	ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
1310 					 dev_ofnode(dev), &sf_child);
1311 	if (ret) {
1312 		debug("Warning: No rockchip reset driver: ret=%d\n", ret);
1313 	} else {
1314 		sf_priv = malloc(sizeof(struct softreset_reg));
1315 		sf_priv->sf_reset_offset = offsetof(struct rk1808_cru,
1316 						    softrst_con[0]);
1317 		sf_priv->sf_reset_num = 16;
1318 		sf_child->priv = sf_priv;
1319 	}
1320 
1321 	return 0;
1322 }
1323 
1324 static const struct udevice_id rk1808_clk_ids[] = {
1325 	{ .compatible = "rockchip,rk1808-cru" },
1326 	{ }
1327 };
1328 
1329 U_BOOT_DRIVER(rockchip_rk1808_cru) = {
1330 	.name		= "rockchip_rk1808_cru",
1331 	.id		= UCLASS_CLK,
1332 	.of_match	= rk1808_clk_ids,
1333 	.priv_auto_alloc_size = sizeof(struct rk1808_clk_priv),
1334 	.ofdata_to_platdata = rk1808_clk_ofdata_to_platdata,
1335 	.ops		= &rk1808_clk_ops,
1336 	.bind		= rk1808_clk_bind,
1337 	.probe		= rk1808_clk_probe,
1338 };
1339 
1340 #ifndef CONFIG_SPL_BUILD
1341 /**
1342  * soc_clk_dump() - Print clock frequencies
1343  * Returns zero on success
1344  *
1345  * Implementation for the clk dump command.
1346  */
1347 int soc_clk_dump(void)
1348 {
1349 	struct udevice *cru_dev;
1350 	struct rk1808_clk_priv *priv;
1351 	const struct rk1808_clk_info *clk_dump;
1352 	struct clk clk;
1353 	unsigned long clk_count = ARRAY_SIZE(clks_dump);
1354 	unsigned long rate;
1355 	int i, ret;
1356 
1357 	ret = uclass_get_device_by_driver(UCLASS_CLK,
1358 					  DM_GET_DRIVER(rockchip_rk1808_cru),
1359 					  &cru_dev);
1360 	if (ret) {
1361 		printf("%s failed to get cru device\n", __func__);
1362 		return ret;
1363 	}
1364 
1365 	priv = dev_get_priv(cru_dev);
1366 	printf("CLK: (%s. arm: enter %lu KHz, init %lu KHz, kernel %lu%s)\n",
1367 	       priv->sync_kernel ? "sync kernel" : "uboot",
1368 	       priv->armclk_enter_hz / 1000,
1369 	       priv->armclk_init_hz / 1000,
1370 	       priv->set_armclk_rate ? priv->armclk_hz / 1000 : 0,
1371 	       priv->set_armclk_rate ? " KHz" : "N/A");
1372 
1373 	for (i = 0; i < clk_count; i++) {
1374 		clk_dump = &clks_dump[i];
1375 		if (clk_dump->name) {
1376 			clk.id = clk_dump->id;
1377 			if (clk_dump->is_cru)
1378 				ret = clk_request(cru_dev, &clk);
1379 			if (ret < 0)
1380 				return ret;
1381 
1382 			rate = clk_get_rate(&clk);
1383 			clk_free(&clk);
1384 			if (i == 0) {
1385 				if (rate < 0)
1386 					printf("  %s %s\n", clk_dump->name,
1387 					       "unknown");
1388 				else
1389 					printf("  %s %lu KHz\n", clk_dump->name,
1390 					       rate / 1000);
1391 			} else {
1392 				if (rate < 0)
1393 					printf("  %s %s\n", clk_dump->name,
1394 					       "unknown");
1395 				else
1396 					printf("  %s %lu KHz\n", clk_dump->name,
1397 					       rate / 1000);
1398 			}
1399 		}
1400 	}
1401 
1402 	return 0;
1403 }
1404 #endif
1405