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