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