xref: /rk3399_rockchip-uboot/drivers/clk/rockchip/clk_rk1808.c (revision 2c6a058b7ea25398013cb25b4e3bb96fe40da1a5)
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 #endif
568 
569 static ulong rk1808_bus_get_clk(struct rk1808_clk_priv *priv, ulong clk_id)
570 {
571 	struct rk1808_cru *cru = priv->cru;
572 	u32 div, con, parent;
573 
574 	switch (clk_id) {
575 	case HSCLK_BUS_PRE:
576 		con = readl(&cru->clksel_con[27]);
577 		div = (con & HSCLK_BUS_DIV_CON_MASK) >> HSCLK_BUS_DIV_CON_SHIFT;
578 		parent = priv->gpll_hz;
579 		break;
580 	case MSCLK_BUS_PRE:
581 		con = readl(&cru->clksel_con[28]);
582 		div = (con & MSCLK_BUS_DIV_CON_MASK) >> MSCLK_BUS_DIV_CON_SHIFT;
583 		parent = priv->gpll_hz;
584 		break;
585 	case LSCLK_BUS_PRE:
586 		con = readl(&cru->clksel_con[28]);
587 		div = (con & LSCLK_BUS_DIV_CON_MASK) >> LSCLK_BUS_DIV_CON_SHIFT;
588 		parent = priv->gpll_hz;
589 		break;
590 	default:
591 		return -ENOENT;
592 	}
593 
594 	return DIV_TO_RATE(parent, div);
595 }
596 
597 static ulong rk1808_bus_set_clk(struct rk1808_clk_priv *priv,
598 				ulong clk_id, ulong hz)
599 {
600 	struct rk1808_cru *cru = priv->cru;
601 	int src_clk_div;
602 
603 	/*
604 	 * select gpll as pd_bus bus clock source and
605 	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
606 	 */
607 	switch (clk_id) {
608 	case HSCLK_BUS_PRE:
609 		src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
610 		assert(src_clk_div - 1 < 31);
611 		rk_clrsetreg(&cru->clksel_con[27],
612 			     CLK_BUS_PLL_SEL_MASK | HSCLK_BUS_DIV_CON_MASK,
613 			     CLK_BUS_PLL_SEL_GPLL << CLK_BUS_PLL_SEL_SHIFT |
614 			     (src_clk_div - 1) << HSCLK_BUS_DIV_CON_SHIFT);
615 		break;
616 	case MSCLK_BUS_PRE:
617 		src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
618 		assert(src_clk_div - 1 < 31);
619 		rk_clrsetreg(&cru->clksel_con[28],
620 			     CLK_BUS_PLL_SEL_MASK | MSCLK_BUS_DIV_CON_MASK,
621 			     CLK_BUS_PLL_SEL_GPLL << CLK_BUS_PLL_SEL_SHIFT |
622 			     (src_clk_div - 1) << MSCLK_BUS_DIV_CON_SHIFT);
623 		break;
624 	case LSCLK_BUS_PRE:
625 		src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
626 		assert(src_clk_div - 1 < 31);
627 		rk_clrsetreg(&cru->clksel_con[28],
628 			     CLK_BUS_PLL_SEL_MASK | LSCLK_BUS_DIV_CON_MASK,
629 			     CLK_BUS_PLL_SEL_GPLL << CLK_BUS_PLL_SEL_SHIFT |
630 			     (src_clk_div - 1) << LSCLK_BUS_DIV_CON_SHIFT);
631 		break;
632 	default:
633 		printf("do not support this bus freq\n");
634 		return -EINVAL;
635 	}
636 
637 	return rk1808_bus_get_clk(priv, clk_id);
638 }
639 
640 static ulong rk1808_peri_get_clk(struct rk1808_clk_priv *priv, ulong clk_id)
641 {
642 	struct rk1808_cru *cru = priv->cru;
643 	u32 div, con, parent;
644 
645 	switch (clk_id) {
646 	case MSCLK_PERI:
647 		con = readl(&cru->clksel_con[19]);
648 		div = (con & MSCLK_PERI_DIV_CON_MASK) >>
649 		      MSCLK_PERI_DIV_CON_SHIFT;
650 		parent = priv->gpll_hz;
651 		break;
652 	case LSCLK_PERI:
653 		con = readl(&cru->clksel_con[19]);
654 		div = (con & LSCLK_PERI_DIV_CON_MASK) >>
655 		      LSCLK_PERI_DIV_CON_SHIFT;
656 		parent = priv->gpll_hz;
657 		break;
658 	default:
659 		return -ENOENT;
660 	}
661 
662 	return DIV_TO_RATE(parent, div);
663 }
664 
665 static ulong rk1808_peri_set_clk(struct rk1808_clk_priv *priv,
666 				 ulong clk_id, ulong hz)
667 {
668 	struct rk1808_cru *cru = priv->cru;
669 	int src_clk_div;
670 
671 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
672 	assert(src_clk_div - 1 < 31);
673 
674 	/*
675 	 * select gpll as pd_peri bus clock source and
676 	 * set up dependent divisors for HCLK and ACLK clocks.
677 	 */
678 	switch (clk_id) {
679 	case MSCLK_PERI:
680 		rk_clrsetreg(&cru->clksel_con[19],
681 			     CLK_PERI_PLL_SEL_MASK | MSCLK_PERI_DIV_CON_MASK,
682 			     CLK_PERI_PLL_SEL_GPLL << CLK_PERI_PLL_SEL_SHIFT |
683 			     (src_clk_div - 1) << MSCLK_PERI_DIV_CON_SHIFT);
684 		break;
685 	case LSCLK_PERI:
686 		rk_clrsetreg(&cru->clksel_con[19],
687 			     CLK_PERI_PLL_SEL_MASK | LSCLK_PERI_DIV_CON_MASK,
688 			     CLK_PERI_PLL_SEL_GPLL << CLK_PERI_PLL_SEL_SHIFT |
689 			     (src_clk_div - 1) << LSCLK_PERI_DIV_CON_SHIFT);
690 		break;
691 	default:
692 		printf("do not support this peri freq\n");
693 		return -EINVAL;
694 	}
695 
696 	return rk1808_peri_get_clk(priv, clk_id);
697 }
698 
699 static ulong rk1808_pclk_pmu_set_clk(struct rk1808_clk_priv *priv,
700 				     ulong clk_id, ulong parent_hz, ulong hz)
701 {
702 	struct rk1808_cru *cru = priv->cru;
703 	int src_clk_div;
704 
705 	src_clk_div = DIV_ROUND_UP(parent_hz, hz);
706 	assert(src_clk_div - 1 < 31);
707 
708 	rk_clrsetreg(&cru->pmu_clksel_con[0],
709 		     PCLK_PMU_DIV_CON_MASK,
710 		     (src_clk_div - 1) << PCLK_PMU_DIV_CON_SHIFT);
711 
712 	return parent_hz / src_clk_div;
713 }
714 
715 static ulong rk1808_armclk_set_clk(struct rk1808_clk_priv *priv, ulong hz)
716 {
717 	struct rk1808_cru *cru = priv->cru;
718 	const struct rockchip_cpu_rate_table *rate;
719 	ulong old_rate;
720 
721 	rate = rockchip_get_cpu_settings(rk1808_cpu_rates, hz);
722 	if (!rate) {
723 		printf("%s unsupported rate\n", __func__);
724 		return -EINVAL;
725 	}
726 
727 	/*
728 	 * select apll as cpu/core clock pll source and
729 	 * set up dependent divisors for PERI and ACLK clocks.
730 	 * core hz : apll = 1:1
731 	 */
732 	old_rate = rockchip_pll_get_rate(&rk1808_pll_clks[APLL],
733 					 priv->cru, APLL);
734 	if (old_rate > hz) {
735 		if (rockchip_pll_set_rate(&rk1808_pll_clks[APLL],
736 					  priv->cru, APLL, hz))
737 			return -EINVAL;
738 		rk_clrsetreg(&cru->clksel_con[0],
739 			     CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
740 			     CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
741 			     rate->aclk_div << CORE_ACLK_DIV_SHIFT |
742 			     rate->pclk_div << CORE_DBG_DIV_SHIFT |
743 			     CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
744 			     0 << CORE_DIV_CON_SHIFT);
745 	} else if (old_rate < hz) {
746 		rk_clrsetreg(&cru->clksel_con[0],
747 			     CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
748 			     CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
749 			     rate->aclk_div << CORE_ACLK_DIV_SHIFT |
750 			     rate->pclk_div << CORE_DBG_DIV_SHIFT |
751 			     CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
752 			     0 << CORE_DIV_CON_SHIFT);
753 		if (rockchip_pll_set_rate(&rk1808_pll_clks[APLL],
754 					  priv->cru, APLL, hz))
755 			return -EINVAL;
756 	}
757 
758 	return rockchip_pll_get_rate(&rk1808_pll_clks[APLL], priv->cru, APLL);
759 }
760 
761 static ulong rk1808_clk_get_rate(struct clk *clk)
762 {
763 	struct rk1808_clk_priv *priv = dev_get_priv(clk->dev);
764 	ulong rate = 0;
765 
766 	debug("%s %ld\n", __func__, clk->id);
767 	switch (clk->id) {
768 	case PLL_APLL:
769 	case PLL_DPLL:
770 	case PLL_CPLL:
771 	case PLL_GPLL:
772 	case PLL_NPLL:
773 	case PLL_PPLL:
774 		rate = rockchip_pll_get_rate(&rk1808_pll_clks[clk->id - 1],
775 					     priv->cru, clk->id - 1);
776 		break;
777 	case ARMCLK:
778 		rate = rockchip_pll_get_rate(&rk1808_pll_clks[APLL],
779 					     priv->cru, APLL);
780 		break;
781 	case HCLK_SDMMC:
782 	case HCLK_EMMC:
783 	case HCLK_SDIO:
784 	case SCLK_SDMMC:
785 	case SCLK_EMMC:
786 	case SCLK_EMMC_SAMPLE:
787 	case SCLK_SDIO:
788 		rate = rk1808_mmc_get_clk(priv, clk->id);
789 		break;
790 #ifndef CONFIG_SPL_BUILD
791 	case SCLK_PMU_I2C0:
792 	case SCLK_I2C1:
793 	case SCLK_I2C2:
794 	case SCLK_I2C3:
795 	case SCLK_I2C4:
796 	case SCLK_I2C5:
797 		rate = rk1808_i2c_get_clk(priv, clk->id);
798 		break;
799 	case SCLK_PWM0:
800 	case SCLK_PWM1:
801 	case SCLK_PWM2:
802 		rate = rk1808_pwm_get_clk(priv, clk->id);
803 		break;
804 	case SCLK_SARADC:
805 		rate = rk1808_saradc_get_clk(priv);
806 		break;
807 	case SCLK_TSADC:
808 		rate = rk1808_tsadc_get_clk(priv);
809 		break;
810 	case SCLK_SPI0:
811 	case SCLK_SPI1:
812 	case SCLK_SPI2:
813 		rate = rk1808_spi_get_clk(priv, clk->id);
814 		break;
815 	case ACLK_VOPRAW:
816 	case DCLK_VOPRAW:
817 	case ACLK_VOPLITE:
818 	case DCLK_VOPLITE:
819 		rate = rk1808_vop_get_clk(priv, clk->id);
820 		break;
821 #endif
822 	case HSCLK_BUS_PRE:
823 	case MSCLK_BUS_PRE:
824 	case LSCLK_BUS_PRE:
825 		rate = rk1808_bus_get_clk(priv, clk->id);
826 		break;
827 	case MSCLK_PERI:
828 	case LSCLK_PERI:
829 		rate = rk1808_peri_get_clk(priv, clk->id);
830 		break;
831 	default:
832 		return -ENOENT;
833 	}
834 
835 	return rate;
836 }
837 
838 static ulong rk1808_clk_set_rate(struct clk *clk, ulong rate)
839 {
840 	struct rk1808_clk_priv *priv = dev_get_priv(clk->dev);
841 	ulong ret = 0;
842 
843 	debug("%s %ld %ld\n", __func__, clk->id, rate);
844 	switch (clk->id) {
845 	case PLL_APLL:
846 	case PLL_DPLL:
847 		ret = rockchip_pll_set_rate(&rk1808_pll_clks[clk->id - 1],
848 					    priv->cru, clk->id - 1, rate);
849 		break;
850 	case PLL_PPLL:
851 		ret = rk1808_pclk_pmu_set_clk(priv, clk->id, rate, PCLK_PMU_HZ);
852 		ret = rockchip_pll_set_rate(&rk1808_pll_clks[PPLL],
853 					    priv->cru, PPLL, rate);
854 		break;
855 	case PLL_CPLL:
856 		ret = rockchip_pll_set_rate(&rk1808_pll_clks[CPLL],
857 					    priv->cru, CPLL, rate);
858 		if (ret == 0)
859 			priv->cpll_hz = rate;
860 		break;
861 	case PLL_GPLL:
862 		ret = rockchip_pll_set_rate(&rk1808_pll_clks[GPLL],
863 					    priv->cru, GPLL, rate);
864 		if (ret == 0)
865 			priv->gpll_hz = rate;
866 		break;
867 	case PLL_NPLL:
868 		ret = rockchip_pll_set_rate(&rk1808_pll_clks[NPLL],
869 					    priv->cru, NPLL, rate);
870 		if (ret == 0)
871 			priv->npll_hz = rate;
872 		break;
873 	case ARMCLK:
874 		if (priv->armclk_hz)
875 			rk1808_armclk_set_clk(priv, rate);
876 		priv->armclk_hz = rate;
877 		break;
878 	case HCLK_SDMMC:
879 	case HCLK_EMMC:
880 	case HCLK_SDIO:
881 	case SCLK_SDMMC:
882 	case SCLK_EMMC:
883 	case SCLK_SDIO:
884 		ret = rk1808_mmc_set_clk(priv, clk->id, rate);
885 		break;
886 #ifndef CONFIG_SPL_BUILD
887 	case SCLK_PMU_I2C0:
888 	case SCLK_I2C1:
889 	case SCLK_I2C2:
890 	case SCLK_I2C3:
891 	case SCLK_I2C4:
892 	case SCLK_I2C5:
893 		ret = rk1808_i2c_set_clk(priv, clk->id, rate);
894 		break;
895 	case SCLK_PWM0:
896 	case SCLK_PWM1:
897 	case SCLK_PWM2:
898 		ret = rk1808_pwm_set_clk(priv, clk->id, rate);
899 		break;
900 	case SCLK_SARADC:
901 		ret = rk1808_saradc_set_clk(priv, rate);
902 		break;
903 	case SCLK_TSADC:
904 		ret = rk1808_tsadc_set_clk(priv, rate);
905 		break;
906 	case SCLK_SPI0:
907 	case SCLK_SPI1:
908 	case SCLK_SPI2:
909 		ret = rk1808_spi_set_clk(priv, clk->id, rate);
910 		break;
911 	case ACLK_VOPRAW:
912 	case DCLK_VOPRAW:
913 	case ACLK_VOPLITE:
914 	case DCLK_VOPLITE:
915 		ret = rk1808_vop_set_clk(priv, clk->id, rate);
916 		break;
917 #endif
918 	case HSCLK_BUS_PRE:
919 	case MSCLK_BUS_PRE:
920 	case LSCLK_BUS_PRE:
921 		ret = rk1808_bus_set_clk(priv, clk->id, rate);
922 		break;
923 	case MSCLK_PERI:
924 	case LSCLK_PERI:
925 		ret = rk1808_peri_set_clk(priv, clk->id, rate);
926 		break;
927 	default:
928 		return -ENOENT;
929 	}
930 
931 	return ret;
932 }
933 
934 #define ROCKCHIP_MMC_DELAY_SEL		BIT(10)
935 #define ROCKCHIP_MMC_DEGREE_MASK	0x3
936 #define ROCKCHIP_MMC_DELAYNUM_OFFSET	2
937 #define ROCKCHIP_MMC_DELAYNUM_MASK	(0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
938 
939 #define PSECS_PER_SEC 1000000000000LL
940 /*
941  * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
942  * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
943  */
944 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
945 
946 int rk1808_mmc_get_phase(struct clk *clk)
947 {
948 	struct rk1808_clk_priv *priv = dev_get_priv(clk->dev);
949 	struct rk1808_cru *cru = priv->cru;
950 	u32 raw_value, delay_num;
951 	u16 degrees = 0;
952 	ulong rate;
953 
954 	rate = rk1808_clk_get_rate(clk);
955 
956 	if (rate < 0)
957 		return rate;
958 
959 	if (clk->id == SCLK_EMMC_SAMPLE)
960 		raw_value = readl(&cru->emmc_con[1]);
961 	else if (clk->id == SCLK_SDMMC_SAMPLE)
962 		raw_value = readl(&cru->sdmmc_con[1]);
963 	else
964 		raw_value = readl(&cru->sdio_con[1]);
965 
966 	raw_value >>= 1;
967 	degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
968 
969 	if (raw_value & ROCKCHIP_MMC_DELAY_SEL) {
970 		/* degrees/delaynum * 10000 */
971 		unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) *
972 					36 * (rate / 1000000);
973 
974 		delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
975 		delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET;
976 		degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000);
977 	}
978 
979 	return degrees % 360;
980 }
981 
982 int rk1808_mmc_set_phase(struct clk *clk, u32 degrees)
983 {
984 	struct rk1808_clk_priv *priv = dev_get_priv(clk->dev);
985 	struct rk1808_cru *cru = priv->cru;
986 	u8 nineties, remainder, delay_num;
987 	u32 raw_value, delay;
988 	ulong rate;
989 
990 	rate = rk1808_clk_get_rate(clk);
991 
992 	if (rate < 0)
993 		return rate;
994 
995 	nineties = degrees / 90;
996 	remainder = (degrees % 90);
997 
998 	/*
999 	 * Convert to delay; do a little extra work to make sure we
1000 	 * don't overflow 32-bit / 64-bit numbers.
1001 	 */
1002 	delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */
1003 	delay *= remainder;
1004 	delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 *
1005 				(ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10));
1006 
1007 	delay_num = (u8)min_t(u32, delay, 255);
1008 
1009 	raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
1010 	raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
1011 	raw_value |= nineties;
1012 
1013 	raw_value <<= 1;
1014 	if (clk->id == SCLK_EMMC_SAMPLE)
1015 		writel(raw_value | 0xffff0000, &cru->emmc_con[1]);
1016 	else if (clk->id == SCLK_SDMMC_SAMPLE)
1017 		writel(raw_value | 0xffff0000, &cru->sdmmc_con[1]);
1018 	else
1019 		writel(raw_value | 0xffff0000, &cru->sdio_con[1]);
1020 
1021 	debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n",
1022 	      degrees, delay_num, raw_value, rk1808_mmc_get_phase(clk));
1023 
1024 	return 0;
1025 }
1026 
1027 static int rk1808_clk_get_phase(struct clk *clk)
1028 {
1029 	int ret;
1030 
1031 	debug("%s %ld\n", __func__, clk->id);
1032 	switch (clk->id) {
1033 	case SCLK_EMMC_SAMPLE:
1034 	case SCLK_SDMMC_SAMPLE:
1035 	case SCLK_SDIO_SAMPLE:
1036 		ret = rk1808_mmc_get_phase(clk);
1037 		break;
1038 	default:
1039 		return -ENOENT;
1040 	}
1041 
1042 	return ret;
1043 }
1044 
1045 static int rk1808_clk_set_phase(struct clk *clk, int degrees)
1046 {
1047 	int ret;
1048 
1049 	debug("%s %ld\n", __func__, clk->id);
1050 	switch (clk->id) {
1051 	case SCLK_EMMC_SAMPLE:
1052 	case SCLK_SDMMC_SAMPLE:
1053 	case SCLK_SDIO_SAMPLE:
1054 		ret = rk1808_mmc_set_phase(clk, degrees);
1055 		break;
1056 	default:
1057 		return -ENOENT;
1058 	}
1059 
1060 	return ret;
1061 }
1062 
1063 static struct clk_ops rk1808_clk_ops = {
1064 	.get_rate = rk1808_clk_get_rate,
1065 	.set_rate = rk1808_clk_set_rate,
1066 	.get_phase	= rk1808_clk_get_phase,
1067 	.set_phase	= rk1808_clk_set_phase,
1068 };
1069 
1070 static int rk1808_clk_probe(struct udevice *dev)
1071 {
1072 	struct rk1808_clk_priv *priv = dev_get_priv(dev);
1073 	int ret;
1074 
1075 	if (rockchip_pll_get_rate(&rk1808_pll_clks[APLL],
1076 				  priv->cru, APLL) != APLL_HZ) {
1077 		ret = rk1808_armclk_set_clk(priv, APLL_HZ);
1078 		if (ret < 0)
1079 			printf("%s failed to set armclk rate\n", __func__);
1080 	}
1081 
1082 	priv->cpll_hz = rockchip_pll_get_rate(&rk1808_pll_clks[CPLL],
1083 					      priv->cru, CPLL);
1084 	priv->gpll_hz = rockchip_pll_get_rate(&rk1808_pll_clks[GPLL],
1085 					      priv->cru, GPLL);
1086 	priv->npll_hz = rockchip_pll_get_rate(&rk1808_pll_clks[NPLL],
1087 					      priv->cru, NPLL);
1088 
1089 	/* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
1090 	ret = clk_set_defaults(dev);
1091 	if (ret)
1092 		debug("%s clk_set_defaults failed %d\n", __func__, ret);
1093 
1094 	return 0;
1095 }
1096 
1097 static int rk1808_clk_ofdata_to_platdata(struct udevice *dev)
1098 {
1099 	struct rk1808_clk_priv *priv = dev_get_priv(dev);
1100 
1101 	priv->cru = dev_read_addr_ptr(dev);
1102 
1103 	return 0;
1104 }
1105 
1106 static int rk1808_clk_bind(struct udevice *dev)
1107 {
1108 	int ret;
1109 	struct udevice *sys_child, *sf_child;
1110 	struct sysreset_reg *priv;
1111 	struct softreset_reg *sf_priv;
1112 
1113 	/* The reset driver does not have a device node, so bind it here */
1114 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
1115 				 &sys_child);
1116 	if (ret) {
1117 		debug("Warning: No sysreset driver: ret=%d\n", ret);
1118 	} else {
1119 		priv = malloc(sizeof(struct sysreset_reg));
1120 		priv->glb_srst_fst_value = offsetof(struct rk1808_cru,
1121 						    glb_srst_fst);
1122 		priv->glb_srst_snd_value = offsetof(struct rk1808_cru,
1123 						    glb_srst_snd);
1124 		sys_child->priv = priv;
1125 	}
1126 
1127 	ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
1128 					 dev_ofnode(dev), &sf_child);
1129 	if (ret) {
1130 		debug("Warning: No rockchip reset driver: ret=%d\n", ret);
1131 	} else {
1132 		sf_priv = malloc(sizeof(struct softreset_reg));
1133 		sf_priv->sf_reset_offset = offsetof(struct rk1808_cru,
1134 						    softrst_con[0]);
1135 		sf_priv->sf_reset_num = 16;
1136 		sf_child->priv = sf_priv;
1137 	}
1138 
1139 	return 0;
1140 }
1141 
1142 static const struct udevice_id rk1808_clk_ids[] = {
1143 	{ .compatible = "rockchip,rk1808-cru" },
1144 	{ }
1145 };
1146 
1147 U_BOOT_DRIVER(rockchip_rk1808_cru) = {
1148 	.name		= "rockchip_rk1808_cru",
1149 	.id		= UCLASS_CLK,
1150 	.of_match	= rk1808_clk_ids,
1151 	.priv_auto_alloc_size = sizeof(struct rk1808_clk_priv),
1152 	.ofdata_to_platdata = rk1808_clk_ofdata_to_platdata,
1153 	.ops		= &rk1808_clk_ops,
1154 	.bind		= rk1808_clk_bind,
1155 	.probe		= rk1808_clk_probe,
1156 };
1157 
1158 #ifndef CONFIG_SPL_BUILD
1159 /**
1160  * soc_clk_dump() - Print clock frequencies
1161  * Returns zero on success
1162  *
1163  * Implementation for the clk dump command.
1164  */
1165 int soc_clk_dump(void)
1166 {
1167 	struct udevice *cru_dev;
1168 	const struct rk1808_clk_info *clk_dump;
1169 	struct clk clk;
1170 	unsigned long clk_count = ARRAY_SIZE(clks_dump);
1171 	unsigned long rate;
1172 	int i, ret;
1173 
1174 	ret = uclass_get_device_by_driver(UCLASS_CLK,
1175 					  DM_GET_DRIVER(rockchip_rk1808_cru),
1176 					  &cru_dev);
1177 	if (ret) {
1178 		printf("%s failed to get cru device\n", __func__);
1179 		return ret;
1180 	}
1181 
1182 	printf("CLK:");
1183 	for (i = 0; i < clk_count; i++) {
1184 		clk_dump = &clks_dump[i];
1185 		if (clk_dump->name) {
1186 			clk.id = clk_dump->id;
1187 			if (clk_dump->is_cru)
1188 				ret = clk_request(cru_dev, &clk);
1189 			if (ret < 0)
1190 				return ret;
1191 
1192 			rate = clk_get_rate(&clk);
1193 			clk_free(&clk);
1194 			if (i == 0) {
1195 				if (rate < 0)
1196 					printf("%s %s\n", clk_dump->name,
1197 					       "unknown");
1198 				else
1199 					printf("%s %lu KHz\n", clk_dump->name,
1200 					       rate / 1000);
1201 			} else {
1202 				if (rate < 0)
1203 					printf("%s %s\n", clk_dump->name,
1204 					       "unknown");
1205 				else
1206 					printf("%s %lu KHz\n", clk_dump->name,
1207 					       rate / 1000);
1208 			}
1209 		}
1210 	}
1211 
1212 	return 0;
1213 }
1214 #endif
1215