xref: /rk3399_rockchip-uboot/drivers/clk/rockchip/clk_rk3128.c (revision ed73b76733ce7cd243da2ebec965b0e1fca8924d)
1 /*
2  * (C) Copyright 2017 Rockchip Electronics Co., Ltd
3  *
4  * SPDX-License-Identifier:	GPL-2.0
5  */
6 
7 #include <common.h>
8 #include <clk-uclass.h>
9 #include <dm.h>
10 #include <errno.h>
11 #include <syscon.h>
12 #include <asm/io.h>
13 #include <asm/arch/clock.h>
14 #include <asm/arch/cru_rk3128.h>
15 #include <asm/arch/hardware.h>
16 #include <bitfield.h>
17 #include <dm/lists.h>
18 #include <dt-bindings/clock/rk3128-cru.h>
19 #include <linux/log2.h>
20 
21 DECLARE_GLOBAL_DATA_PTR;
22 
23 #define DIV_TO_RATE(input_rate, div)	((input_rate) / ((div) + 1))
24 
25 #ifndef CONFIG_SPL_BUILD
26 #define RK3128_CLK_DUMP(_id, _name, _iscru)	\
27 {						\
28 	.id = _id,				\
29 	.name = _name,				\
30 	.is_cru = _iscru,			\
31 }
32 #endif
33 
34 static struct rockchip_pll_rate_table rk3128_pll_rates[] = {
35 	/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
36 #ifndef CONFIG_SPL_BUILD
37 	RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
38 	RK3036_PLL_RATE(1188000000, 1, 99, 2, 1, 1, 0),
39 	RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
40 #endif
41 	RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0),
42 	RK3036_PLL_RATE(800000000, 1, 200, 6, 1, 1, 0),
43 	RK3036_PLL_RATE(600000000, 1, 75, 3, 1, 1, 0),
44 	RK3036_PLL_RATE(594000000, 1, 99, 4, 1, 1, 0),
45 	RK3036_PLL_RATE(500000000, 1, 125, 6, 1, 1, 0),
46 	RK3036_PLL_RATE(400000000, 1, 100, 6, 1, 1, 0),
47 	{ /* sentinel */ },
48 };
49 
50 #define RK3128_CPUCLK_RATE(_rate, _aclk_div, _pclk_div)		\
51 {								\
52 	.rate	= _rate##U,					\
53 	.aclk_div = _aclk_div,					\
54 	.pclk_div = _pclk_div,					\
55 }
56 
57 static struct rockchip_cpu_rate_table rk3128_cpu_rates[] = {
58 	RK3128_CPUCLK_RATE(1200000000, 1, 5),
59 	RK3128_CPUCLK_RATE(1008000000, 1, 5),
60 	RK3128_CPUCLK_RATE(816000000, 1, 3),
61 	RK3128_CPUCLK_RATE(600000000, 1, 3),
62 };
63 
64 #ifndef CONFIG_SPL_BUILD
65 static const struct rk3128_clk_info clks_dump[] = {
66 	RK3128_CLK_DUMP(PLL_APLL, "apll", true),
67 	RK3128_CLK_DUMP(PLL_DPLL, "dpll", true),
68 	RK3128_CLK_DUMP(PLL_CPLL, "cpll", true),
69 	RK3128_CLK_DUMP(PLL_GPLL, "gpll", true),
70 	RK3128_CLK_DUMP(ARMCLK, "armclk", true),
71 	RK3128_CLK_DUMP(ACLK_CPU, "aclk_cpu", true),
72 	RK3128_CLK_DUMP(HCLK_CPU, "hclk_cpu", true),
73 	RK3128_CLK_DUMP(PCLK_CPU, "pclk_cpu", true),
74 	RK3128_CLK_DUMP(ACLK_PERI, "aclk_peri", true),
75 	RK3128_CLK_DUMP(HCLK_PERI, "hclk_peri", true),
76 	RK3128_CLK_DUMP(PCLK_PERI, "pclk_peri", true),
77 };
78 #endif
79 
80 static struct rockchip_pll_clock rk3128_pll_clks[] = {
81 	[APLL] = PLL(pll_rk3036, PLL_APLL, RK2928_PLL_CON(0),
82 		     RK2928_MODE_CON, 0, 10, 0, rk3128_pll_rates),
83 	[DPLL] = PLL(pll_rk3036, PLL_DPLL, RK2928_PLL_CON(4),
84 		     RK2928_MODE_CON, 4, 10, 0, NULL),
85 	[CPLL] = PLL(pll_rk3036, PLL_CPLL, RK2928_PLL_CON(8),
86 		    RK2928_MODE_CON, 8, 10, 0, rk3128_pll_rates),
87 	[GPLL] = PLL(pll_rk3036, PLL_GPLL, RK2928_PLL_CON(12),
88 		     RK2928_MODE_CON, 12, 10, 0, rk3128_pll_rates),
89 };
90 
91 static ulong rk3128_armclk_set_clk(struct rk3128_clk_priv *priv, ulong hz)
92 {
93 	struct rk3128_cru *cru = priv->cru;
94 	const struct rockchip_cpu_rate_table *rate;
95 	ulong old_rate;
96 
97 	rate = rockchip_get_cpu_settings(rk3128_cpu_rates, hz);
98 	if (!rate) {
99 		printf("%s unsupported rate\n", __func__);
100 		return -EINVAL;
101 	}
102 
103 	/*
104 	 * select apll as cpu/core clock pll source and
105 	 * set up dependent divisors for PERI and ACLK clocks.
106 	 * core hz : apll = 1:1
107 	 */
108 	old_rate = rockchip_pll_get_rate(&rk3128_pll_clks[APLL],
109 					 priv->cru, APLL);
110 	if (old_rate > hz) {
111 		if (rockchip_pll_set_rate(&rk3128_pll_clks[APLL],
112 					  priv->cru, APLL, hz))
113 			return -EINVAL;
114 		rk_clrsetreg(&cru->cru_clksel_con[0],
115 			     CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK,
116 			     CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
117 			     0 << CORE_DIV_CON_SHIFT);
118 		rk_clrsetreg(&cru->cru_clksel_con[1],
119 			     CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
120 			     rate->aclk_div << CORE_ACLK_DIV_SHIFT |
121 			     rate->pclk_div << CORE_DBG_DIV_SHIFT);
122 	} else if (old_rate < hz) {
123 		rk_clrsetreg(&cru->cru_clksel_con[1],
124 			     CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
125 			     rate->aclk_div << CORE_ACLK_DIV_SHIFT |
126 			     rate->pclk_div << CORE_DBG_DIV_SHIFT);
127 		rk_clrsetreg(&cru->cru_clksel_con[0],
128 			     CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK,
129 			     CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
130 			     0 << CORE_DIV_CON_SHIFT);
131 		if (rockchip_pll_set_rate(&rk3128_pll_clks[APLL],
132 					  priv->cru, APLL, hz))
133 			return -EINVAL;
134 	}
135 
136 	return rockchip_pll_get_rate(&rk3128_pll_clks[APLL], priv->cru, APLL);
137 }
138 
139 static ulong rockchip_mmc_get_clk(struct rk3128_clk_priv *priv,
140 				  int periph)
141 {
142 	struct rk3128_cru *cru = priv->cru;
143 	uint src_rate;
144 	uint div, mux;
145 	u32 con;
146 
147 	switch (periph) {
148 	case HCLK_EMMC:
149 	case SCLK_EMMC:
150 	case SCLK_EMMC_SAMPLE:
151 		con = readl(&cru->cru_clksel_con[12]);
152 		mux = (con & EMMC_PLL_MASK) >> EMMC_PLL_SHIFT;
153 		div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT;
154 		break;
155 	case HCLK_SDMMC:
156 	case SCLK_SDMMC:
157 	case SCLK_SDMMC_SAMPLE:
158 		con = readl(&cru->cru_clksel_con[11]);
159 		mux = (con & MMC0_PLL_MASK) >> MMC0_PLL_SHIFT;
160 		div = (con & MMC0_DIV_MASK) >> MMC0_DIV_SHIFT;
161 		break;
162 	case HCLK_SDIO:
163 	case SCLK_SDIO:
164 	case SCLK_SDIO_SAMPLE:
165 		con = readl(&cru->cru_clksel_con[12]);
166 		mux = (con & SDIO_PLL_MASK) >> SDIO_PLL_SHIFT;
167 		div = (con & SDIO_DIV_MASK) >> SDIO_DIV_SHIFT;
168 		break;
169 	default:
170 		return -EINVAL;
171 	}
172 
173 	src_rate = mux == EMMC_SEL_24M ? OSC_HZ : priv->gpll_hz;
174 	return DIV_TO_RATE(src_rate, div);
175 }
176 
177 static ulong rockchip_mmc_set_clk(struct rk3128_clk_priv *priv,
178 				  int periph, uint freq)
179 {
180 	struct rk3128_cru *cru = priv->cru;
181 	int src_clk_div;
182 	int mux;
183 
184 	/* mmc clock defaulg div 2 internal, need provide double in cru */
185 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz / 2, freq);
186 
187 	if (src_clk_div > 128) {
188 		src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, freq);
189 		mux = EMMC_SEL_24M;
190 	} else {
191 		mux = EMMC_SEL_GPLL;
192 	}
193 
194 	switch (periph) {
195 	case HCLK_EMMC:
196 	case SCLK_EMMC:
197 		rk_clrsetreg(&cru->cru_clksel_con[12],
198 			     EMMC_PLL_MASK | EMMC_DIV_MASK,
199 			     mux << EMMC_PLL_SHIFT |
200 			     (src_clk_div - 1) << EMMC_DIV_SHIFT);
201 		break;
202 	case HCLK_SDMMC:
203 	case SCLK_SDMMC:
204 		rk_clrsetreg(&cru->cru_clksel_con[11],
205 			     MMC0_PLL_MASK | MMC0_DIV_MASK,
206 			     mux << MMC0_PLL_SHIFT |
207 			     (src_clk_div - 1) << MMC0_DIV_SHIFT);
208 		break;
209 	case HCLK_SDIO:
210 	case SCLK_SDIO:
211 		rk_clrsetreg(&cru->cru_clksel_con[12],
212 			     SDIO_PLL_MASK | SDIO_DIV_MASK,
213 			     mux << SDIO_PLL_SHIFT |
214 			     (src_clk_div - 1) << SDIO_DIV_SHIFT);
215 		break;
216 	default:
217 		return -EINVAL;
218 	}
219 
220 	return rockchip_mmc_get_clk(priv, periph);
221 }
222 
223 static ulong rk3128_peri_get_clk(struct rk3128_clk_priv *priv, ulong clk_id)
224 {
225 	struct rk3128_cru *cru = priv->cru;
226 	u32 div, con, parent;
227 
228 	switch (clk_id) {
229 	case ACLK_PERI:
230 		con = readl(&cru->cru_clksel_con[10]);
231 		div = (con & ACLK_PERI_DIV_MASK) >> ACLK_PERI_DIV_SHIFT;
232 		parent = priv->gpll_hz;
233 		break;
234 	case PCLK_PERI:
235 	case PCLK_I2C0:
236 	case PCLK_I2C1:
237 	case PCLK_I2C2:
238 	case PCLK_I2C3:
239 	case PCLK_PWM:
240 	case PCLK_WDT:
241 		con = readl(&cru->cru_clksel_con[10]);
242 		div = (con & PCLK_PERI_DIV_MASK) >> PCLK_PERI_DIV_SHIFT;
243 		parent = rk3128_peri_get_clk(priv, ACLK_PERI);
244 		break;
245 	case HCLK_PERI:
246 		con = readl(&cru->cru_clksel_con[10]);
247 		div = (con & HCLK_PERI_DIV_MASK) >> HCLK_PERI_DIV_SHIFT;
248 		parent = rk3128_peri_get_clk(priv, ACLK_PERI);
249 		break;
250 	default:
251 		printf("do not support this peripheral bus\n");
252 		return -EINVAL;
253 	}
254 
255 	return DIV_TO_RATE(parent, div);
256 }
257 
258 static ulong rk3128_peri_set_clk(struct rk3128_clk_priv *priv,
259 				 ulong clk_id, uint hz)
260 {
261 	struct rk3128_cru *cru = priv->cru;
262 	int src_clk_div;
263 
264 	switch (clk_id) {
265 	case ACLK_PERI:
266 		src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
267 		assert(src_clk_div - 1 < 32);
268 		rk_clrsetreg(&cru->cru_clksel_con[10],
269 			     PERI_PLL_SEL_MASK | ACLK_PERI_DIV_MASK,
270 			     PERI_PLL_SEL_GPLL << PERI_PLL_SEL_SHIFT |
271 			     (src_clk_div - 1) << ACLK_PERI_DIV_SHIFT);
272 		break;
273 	case PCLK_I2C0:
274 	case PCLK_I2C1:
275 	case PCLK_I2C2:
276 	case PCLK_I2C3:
277 	case PCLK_PWM:
278 	case PCLK_PERI:
279 		src_clk_div = DIV_ROUND_UP(rk3128_peri_get_clk(priv,
280 							       ACLK_PERI),
281 					   hz);
282 		assert(src_clk_div - 1 < 3);
283 		rk_clrsetreg(&cru->cru_clksel_con[10],
284 			     PCLK_PERI_DIV_MASK,
285 			     (src_clk_div - 1) << PCLK_PERI_DIV_SHIFT);
286 		break;
287 	case HCLK_PERI:
288 		src_clk_div = DIV_ROUND_UP(rk3128_peri_get_clk(priv,
289 							       ACLK_PERI),
290 					   hz);
291 		assert(src_clk_div - 1 < 7);
292 		rk_clrsetreg(&cru->cru_clksel_con[10],
293 			     HCLK_PERI_DIV_MASK,
294 			     (src_clk_div - 1) << HCLK_PERI_DIV_SHIFT);
295 		break;
296 	default:
297 		printf("do not support this peripheral bus\n");
298 		return -EINVAL;
299 	}
300 
301 	return rk3128_peri_get_clk(priv, clk_id);
302 }
303 
304 static ulong rk3128_bus_get_clk(struct rk3128_clk_priv *priv, ulong clk_id)
305 {
306 	struct rk3128_cru *cru = priv->cru;
307 	u32 div, con, parent;
308 
309 	switch (clk_id) {
310 	case ACLK_CPU:
311 		con = readl(&cru->cru_clksel_con[0]);
312 		div = (con & ACLK_BUS_DIV_MASK) >> ACLK_BUS_DIV_SHIFT;
313 		parent = priv->gpll_hz;
314 		break;
315 	case PCLK_CPU:
316 		con = readl(&cru->cru_clksel_con[1]);
317 		div = (con & PCLK_BUS_DIV_MASK) >> PCLK_BUS_DIV_SHIFT;
318 		parent = rk3128_bus_get_clk(priv, ACLK_CPU);
319 		break;
320 	case HCLK_CPU:
321 		con = readl(&cru->cru_clksel_con[1]);
322 		div = (con & HCLK_BUS_DIV_MASK) >> HCLK_BUS_DIV_SHIFT;
323 		parent = rk3128_bus_get_clk(priv, ACLK_CPU);
324 		break;
325 	default:
326 		printf("do not support this peripheral bus\n");
327 		return -EINVAL;
328 	}
329 
330 	return DIV_TO_RATE(parent, div);
331 }
332 
333 static ulong rk3128_bus_set_clk(struct rk3128_clk_priv *priv,
334 				ulong clk_id, uint hz)
335 {
336 	struct rk3128_cru *cru = priv->cru;
337 	int src_clk_div;
338 
339 	switch (clk_id) {
340 	case ACLK_CPU:
341 		src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
342 		assert(src_clk_div - 1 < 32);
343 		rk_clrsetreg(&cru->cru_clksel_con[0],
344 			     BUS_PLL_SEL_MASK | ACLK_BUS_DIV_MASK,
345 			     BUS_PLL_SEL_GPLL << BUS_PLL_SEL_SHIFT |
346 			     (src_clk_div - 1) << ACLK_BUS_DIV_SHIFT);
347 		break;
348 	case PCLK_CPU:
349 		src_clk_div = DIV_ROUND_UP(rk3128_bus_get_clk(priv,
350 							      ACLK_CPU),
351 					   hz);
352 		assert(src_clk_div - 1 < 3);
353 		rk_clrsetreg(&cru->cru_clksel_con[1],
354 			     PCLK_BUS_DIV_MASK,
355 			     (src_clk_div - 1) << PCLK_BUS_DIV_SHIFT);
356 		break;
357 	case HCLK_CPU:
358 		src_clk_div = DIV_ROUND_UP(rk3128_bus_get_clk(priv,
359 							      ACLK_CPU),
360 					   hz);
361 		assert(src_clk_div - 1 < 7);
362 		rk_clrsetreg(&cru->cru_clksel_con[1],
363 			     HCLK_BUS_DIV_MASK,
364 			     (src_clk_div - 1) << HCLK_BUS_DIV_SHIFT);
365 		break;
366 	default:
367 		printf("do not support this peripheral bus\n");
368 		return -EINVAL;
369 	}
370 
371 	return rk3128_bus_get_clk(priv, clk_id);
372 }
373 
374 #ifndef CONFIG_SPL_BUILD
375 static ulong rk3128_saradc_get_clk(struct rk3128_clk_priv *priv)
376 {
377 	struct rk3128_cru *cru = priv->cru;
378 	u32 div, val;
379 
380 	val = readl(&cru->cru_clksel_con[24]);
381 	div = bitfield_extract(val, SARADC_DIV_CON_SHIFT,
382 			       SARADC_DIV_CON_WIDTH);
383 
384 	return DIV_TO_RATE(OSC_HZ, div);
385 }
386 
387 static ulong rk3128_saradc_set_clk(struct rk3128_clk_priv *priv, uint hz)
388 {
389 	struct rk3128_cru *cru = priv->cru;
390 	int src_clk_div;
391 
392 	src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1;
393 	assert(src_clk_div < 128);
394 
395 	rk_clrsetreg(&cru->cru_clksel_con[24],
396 		     SARADC_DIV_CON_MASK,
397 		     src_clk_div << SARADC_DIV_CON_SHIFT);
398 
399 	return rk3128_saradc_get_clk(priv);
400 }
401 
402 #define RK3128_LCDC_PLL_LIMIT			600000000
403 
404 static ulong rk3128_vop_set_clk(struct rk3128_clk_priv *priv,
405 				ulong clk_id, uint hz)
406 {
407 	struct rk3128_cru *cru = priv->cru;
408 	int src_clk_div;
409 
410 	src_clk_div = GPLL_HZ / hz;
411 	assert(src_clk_div - 1 < 31);
412 
413 	switch (clk_id) {
414 	case ACLK_LCDC0:
415 	case ACLK_VIO0:
416 		rk_clrsetreg(&cru->cru_clksel_con[31],
417 			     VIO0_PLL_MASK | VIO0_DIV_MASK,
418 			     VIO0_SEL_GPLL << VIO0_PLL_SHIFT |
419 			     (src_clk_div - 1) << VIO0_DIV_SHIFT);
420 		break;
421 	case ACLK_VIO1:
422 		rk_clrsetreg(&cru->cru_clksel_con[31],
423 			     VIO1_PLL_MASK | VIO1_DIV_MASK,
424 			     VIO1_SEL_GPLL << VIO1_PLL_SHIFT |
425 			     (src_clk_div - 1) << VIO1_DIV_SHIFT);
426 		break;
427 	case DCLK_VOP:
428 		src_clk_div = DIV_ROUND_UP(RK3128_LCDC_PLL_LIMIT, hz);
429 		rockchip_pll_set_rate(&rk3128_pll_clks[CPLL],
430 				      priv->cru, CPLL, src_clk_div * hz);
431 		rk_clrsetreg(&cru->cru_clksel_con[27],
432 			      DCLK_VOP_SEL_MASK | DCLK_VOP_DIV_CON_MASK,
433 			     DCLK_VOP_PLL_SEL_CPLL << DCLK_VOP_SEL_SHIFT |
434 			     (src_clk_div - 1) << DCLK_VOP_DIV_CON_SHIFT);
435 		break;
436 	default:
437 		printf("do not support this vop freq\n");
438 		return -EINVAL;
439 	}
440 
441 	return hz;
442 }
443 
444 static ulong rk3128_vop_get_rate(struct rk3128_clk_priv *priv, ulong clk_id)
445 {
446 	struct rk3128_cru *cru = priv->cru;
447 	u32 div, con, parent;
448 
449 	switch (clk_id) {
450 	case ACLK_LCDC0:
451 	case ACLK_VIO0:
452 		con = readl(&cru->cru_clksel_con[31]);
453 		div = con  & 0x1f;
454 		parent = GPLL_HZ;
455 		break;
456 	case ACLK_VIO1:
457 		con = readl(&cru->cru_clksel_con[31]);
458 		div = (con >> 8) & 0x1f;
459 		parent = GPLL_HZ;
460 		break;
461 	case DCLK_VOP:
462 		con = readl(&cru->cru_clksel_con[27]);
463 		div = (con & DCLK_VOP_DIV_CON_MASK) >> DCLK_VOP_DIV_CON_SHIFT;
464 		parent = rockchip_pll_get_rate(&rk3128_pll_clks[CPLL],
465 					       priv->cru, CPLL);
466 		break;
467 	default:
468 		return -ENOENT;
469 	}
470 	return DIV_TO_RATE(parent, div);
471 }
472 #endif
473 
474 static ulong rk3128_clk_get_rate(struct clk *clk)
475 {
476 	struct rk3128_clk_priv *priv = dev_get_priv(clk->dev);
477 	ulong rate = 0;
478 
479 	switch (clk->id) {
480 	case PLL_APLL:
481 	case PLL_DPLL:
482 	case PLL_CPLL:
483 	case PLL_GPLL:
484 		rate =  rockchip_pll_get_rate(&rk3128_pll_clks[clk->id - 1],
485 					      priv->cru, clk->id - 1);
486 		break;
487 	case ARMCLK:
488 		rate = rockchip_pll_get_rate(&rk3128_pll_clks[APLL],
489 					     priv->cru, APLL);
490 		break;
491 	case HCLK_EMMC:
492 	case SCLK_EMMC:
493 	case HCLK_SDMMC:
494 	case SCLK_SDMMC:
495 	case HCLK_SDIO:
496 	case SCLK_SDIO:
497 		rate = rockchip_mmc_get_clk(priv, clk->id);
498 		break;
499 	case ACLK_PERI:
500 	case HCLK_PERI:
501 	case PCLK_PERI:
502 	case PCLK_I2C0:
503 	case PCLK_I2C1:
504 	case PCLK_I2C2:
505 	case PCLK_I2C3:
506 	case PCLK_PWM:
507 	case PCLK_WDT:
508 		rate = rk3128_peri_get_clk(priv, clk->id);
509 		break;
510 	case ACLK_CPU:
511 	case HCLK_CPU:
512 	case PCLK_CPU:
513 		rate = rk3128_bus_get_clk(priv, clk->id);
514 		break;
515 #ifndef CONFIG_SPL_BUILD
516 	case SCLK_SARADC:
517 		rate = rk3128_saradc_get_clk(priv);
518 		break;
519 	case DCLK_VOP:
520 	case ACLK_VIO0:
521 	case ACLK_VIO1:
522 	case ACLK_LCDC0:
523 		rate = rk3128_vop_get_rate(priv, clk->id);
524 		break;
525 #endif
526 	default:
527 		return -ENOENT;
528 	}
529 	return rate;
530 }
531 
532 static ulong rk3128_clk_set_rate(struct clk *clk, ulong rate)
533 {
534 	struct rk3128_clk_priv *priv = dev_get_priv(clk->dev);
535 	ulong ret = 0;
536 
537 	switch (clk->id) {
538 	case PLL_APLL:
539 	case PLL_DPLL:
540 	case PLL_CPLL:
541 		ret = rockchip_pll_set_rate(&rk3128_pll_clks[clk->id - 1],
542 					    priv->cru, clk->id - 1, rate);
543 	case PLL_GPLL:
544 		ret = rockchip_pll_set_rate(&rk3128_pll_clks[GPLL],
545 					    priv->cru, GPLL, rate);
546 		priv->gpll_hz = rate;
547 		break;
548 	case ARMCLK:
549 		if (priv->armclk_hz)
550 			ret = rk3128_armclk_set_clk(priv, rate);
551 		priv->armclk_hz = rate;
552 		break;
553 	case HCLK_EMMC:
554 	case SCLK_EMMC:
555 	case SCLK_EMMC_SAMPLE:
556 	case HCLK_SDMMC:
557 	case SCLK_SDMMC:
558 	case SCLK_SDMMC_SAMPLE:
559 	case HCLK_SDIO:
560 	case SCLK_SDIO:
561 	case SCLK_SDIO_SAMPLE:
562 		ret = rockchip_mmc_set_clk(priv, clk->id, rate);
563 		break;
564 	case ACLK_PERI:
565 	case PCLK_PERI:
566 	case HCLK_PERI:
567 	case PCLK_I2C0:
568 	case PCLK_I2C1:
569 	case PCLK_I2C2:
570 	case PCLK_I2C3:
571 	case PCLK_PWM:
572 		ret = rk3128_peri_set_clk(priv, clk->id, rate);
573 		break;
574 	case ACLK_CPU:
575 	case HCLK_CPU:
576 	case PCLK_CPU:
577 		ret = rk3128_bus_set_clk(priv, clk->id, rate);
578 		break;
579 #ifndef CONFIG_SPL_BUILD
580 	case SCLK_SARADC:
581 		ret = rk3128_saradc_set_clk(priv, rate);
582 		break;
583 	case DCLK_VOP:
584 	case ACLK_VIO0:
585 	case ACLK_VIO1:
586 	case ACLK_LCDC0:
587 		ret = rk3128_vop_set_clk(priv, clk->id, rate);
588 		break;
589 #endif
590 	default:
591 		return -ENOENT;
592 	}
593 	return ret;
594 }
595 
596 #define ROCKCHIP_MMC_DELAY_SEL		BIT(10)
597 #define ROCKCHIP_MMC_DEGREE_MASK	0x3
598 #define ROCKCHIP_MMC_DELAYNUM_OFFSET	2
599 #define ROCKCHIP_MMC_DELAYNUM_MASK	(0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
600 
601 #define PSECS_PER_SEC 1000000000000LL
602 /*
603  * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
604  * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
605  */
606 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
607 
608 int rk3128_mmc_get_phase(struct clk *clk)
609 {
610 	struct rk3128_clk_priv *priv = dev_get_priv(clk->dev);
611 	struct rk3128_cru *cru = priv->cru;
612 	u32 raw_value, delay_num;
613 	u16 degrees = 0;
614 	ulong rate;
615 
616 	rate = rk3128_clk_get_rate(clk);
617 
618 	if (rate < 0)
619 		return rate;
620 
621 	if (clk->id == SCLK_EMMC_SAMPLE)
622 		raw_value = readl(&cru->cru_emmc_con[1]);
623 	else if (clk->id == SCLK_SDMMC_SAMPLE)
624 		raw_value = readl(&cru->cru_sdmmc_con[1]);
625 	else
626 		raw_value = readl(&cru->cru_sdio_con[1]);
627 
628 	raw_value >>= 1;
629 	degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
630 
631 	if (raw_value & ROCKCHIP_MMC_DELAY_SEL) {
632 		/* degrees/delaynum * 10000 */
633 		unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) *
634 					36 * (rate / 1000000);
635 
636 		delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
637 		delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET;
638 		degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000);
639 	}
640 
641 	return degrees % 360;
642 }
643 
644 int rk3128_mmc_set_phase(struct clk *clk, u32 degrees)
645 {
646 	struct rk3128_clk_priv *priv = dev_get_priv(clk->dev);
647 	struct rk3128_cru *cru = priv->cru;
648 	u8 nineties, remainder, delay_num;
649 	u32 raw_value, delay;
650 	ulong rate;
651 
652 	rate = rk3128_clk_get_rate(clk);
653 
654 	if (rate < 0)
655 		return rate;
656 
657 	nineties = degrees / 90;
658 	remainder = (degrees % 90);
659 
660 	/*
661 	 * Convert to delay; do a little extra work to make sure we
662 	 * don't overflow 32-bit / 64-bit numbers.
663 	 */
664 	delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */
665 	delay *= remainder;
666 	delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 *
667 				(ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10));
668 
669 	delay_num = (u8)min_t(u32, delay, 255);
670 
671 	raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
672 	raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
673 	raw_value |= nineties;
674 
675 	raw_value <<= 1;
676 	if (clk->id == SCLK_EMMC_SAMPLE)
677 		writel(raw_value | 0xffff0000, &cru->cru_emmc_con[1]);
678 	else if (clk->id == SCLK_SDMMC_SAMPLE)
679 		writel(raw_value | 0xffff0000, &cru->cru_sdmmc_con[1]);
680 	else
681 		writel(raw_value | 0xffff0000, &cru->cru_sdio_con[1]);
682 
683 	debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n",
684 	      degrees, delay_num, raw_value, rk3128_mmc_get_phase(clk));
685 
686 	return 0;
687 }
688 
689 static int rk3128_clk_get_phase(struct clk *clk)
690 {
691 	int ret;
692 
693 	debug("%s %ld\n", __func__, clk->id);
694 	switch (clk->id) {
695 	case SCLK_EMMC_SAMPLE:
696 	case SCLK_SDMMC_SAMPLE:
697 	case SCLK_SDIO_SAMPLE:
698 		ret = rk3128_mmc_get_phase(clk);
699 		break;
700 	default:
701 		return -ENOENT;
702 	}
703 
704 	return ret;
705 }
706 
707 static int rk3128_clk_set_phase(struct clk *clk, int degrees)
708 {
709 	int ret;
710 
711 	debug("%s %ld\n", __func__, clk->id);
712 	switch (clk->id) {
713 	case SCLK_EMMC_SAMPLE:
714 	case SCLK_SDMMC_SAMPLE:
715 	case SCLK_SDIO_SAMPLE:
716 		ret = rk3128_mmc_set_phase(clk, degrees);
717 		break;
718 	default:
719 		return -ENOENT;
720 	}
721 
722 	return ret;
723 }
724 
725 static struct clk_ops rk3128_clk_ops = {
726 	.get_rate	= rk3128_clk_get_rate,
727 	.set_rate	= rk3128_clk_set_rate,
728 	.get_phase	= rk3128_clk_get_phase,
729 	.set_phase	= rk3128_clk_set_phase,
730 };
731 
732 static int rk3128_clk_ofdata_to_platdata(struct udevice *dev)
733 {
734 	struct rk3128_clk_priv *priv = dev_get_priv(dev);
735 
736 	priv->cru = dev_read_addr_ptr(dev);
737 
738 	return 0;
739 }
740 
741 static void rkclk_init(struct rk3128_clk_priv *priv)
742 {
743 	if (rockchip_pll_get_rate(&rk3128_pll_clks[APLL],
744 				  priv->cru, APLL) != APLL_HZ)
745 		rk3128_armclk_set_clk(priv, APLL_HZ);
746 
747 	priv->gpll_hz = rockchip_pll_get_rate(&rk3128_pll_clks[GPLL],
748 					      priv->cru, GPLL);
749 	rk3128_bus_set_clk(priv, ACLK_CPU, ACLK_BUS_HZ / 2);
750 	rk3128_peri_set_clk(priv, ACLK_PERI, ACLK_PERI_HZ / 2);
751 	rockchip_pll_set_rate(&rk3128_pll_clks[GPLL],
752 			      priv->cru, GPLL, GPLL_HZ);
753 	priv->gpll_hz = GPLL_HZ;
754 	rk_clrsetreg(&priv->cru->cru_clksel_con[2],
755 		     NANDC_PLL_SEL_MASK | NANDC_CLK_DIV_MASK,
756 		     NANDC_PLL_SEL_GPLL << NANDC_PLL_SEL_SHIFT |
757 		     3 << NANDC_CLK_DIV_SHIFT);
758 	rk_clrsetreg(&priv->cru->cru_clksel_con[11],
759 		     SFC_PLL_SEL_MASK | SFC_CLK_DIV_MASK,
760 		     SFC_PLL_SEL_GPLL << SFC_PLL_SEL_SHIFT |
761 		     9 << SFC_CLK_DIV_SHIFT);
762 
763 	rk3128_bus_set_clk(priv, ACLK_CPU, ACLK_BUS_HZ);
764 	rk3128_bus_set_clk(priv, HCLK_CPU, ACLK_BUS_HZ / 2);
765 	rk3128_bus_set_clk(priv, PCLK_CPU, ACLK_BUS_HZ / 2);
766 	rk3128_peri_set_clk(priv, ACLK_PERI, ACLK_PERI_HZ);
767 	rk3128_peri_set_clk(priv, HCLK_PERI, ACLK_PERI_HZ / 2);
768 	rk3128_peri_set_clk(priv, PCLK_PERI, ACLK_PERI_HZ / 2);
769 
770 	rockchip_pll_set_rate(&rk3128_pll_clks[CPLL],
771 			      priv->cru, CPLL, CPLL_HZ);
772 }
773 
774 static int rk3128_clk_probe(struct udevice *dev)
775 {
776 	struct rk3128_clk_priv *priv = dev_get_priv(dev);
777 
778 	priv->sync_kernel = false;
779 	if (!priv->armclk_enter_hz)
780 		priv->armclk_enter_hz =
781 		rockchip_pll_get_rate(&rk3128_pll_clks[APLL],
782 				      priv->cru, APLL);
783 	rkclk_init(priv);
784 	if (!priv->armclk_init_hz)
785 		priv->armclk_init_hz =
786 		rockchip_pll_get_rate(&rk3128_pll_clks[APLL],
787 				      priv->cru, APLL);
788 
789 	return 0;
790 }
791 
792 static int rk3128_clk_bind(struct udevice *dev)
793 {
794 	int ret;
795 	struct udevice *sys_child, *sf_child;
796 	struct sysreset_reg *priv;
797 	struct softreset_reg *sf_priv;
798 
799 	/* The reset driver does not have a device node, so bind it here */
800 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
801 				 &sys_child);
802 	if (ret) {
803 		debug("Warning: No sysreset driver: ret=%d\n", ret);
804 	} else {
805 		priv = malloc(sizeof(struct sysreset_reg));
806 		priv->glb_srst_fst_value = offsetof(struct rk3128_cru,
807 						    cru_glb_srst_fst_value);
808 		priv->glb_srst_snd_value = offsetof(struct rk3128_cru,
809 						    cru_glb_srst_snd_value);
810 		sys_child->priv = priv;
811 	}
812 
813 	ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
814 					 dev_ofnode(dev), &sf_child);
815 	if (ret) {
816 		debug("Warning: No rockchip reset driver: ret=%d\n", ret);
817 	} else {
818 		sf_priv = malloc(sizeof(struct softreset_reg));
819 		sf_priv->sf_reset_offset = offsetof(struct rk3128_cru,
820 						    cru_softrst_con[0]);
821 		sf_priv->sf_reset_num = 9;
822 		sf_child->priv = sf_priv;
823 	}
824 
825 	return 0;
826 }
827 
828 static const struct udevice_id rk3128_clk_ids[] = {
829 	{ .compatible = "rockchip,rk3128-cru" },
830 	{ .compatible = "rockchip,rk3126-cru" },
831 	{ }
832 };
833 
834 U_BOOT_DRIVER(rockchip_rk3128_cru) = {
835 	.name		= "clk_rk3128",
836 	.id		= UCLASS_CLK,
837 	.of_match	= rk3128_clk_ids,
838 	.priv_auto_alloc_size = sizeof(struct rk3128_clk_priv),
839 	.ofdata_to_platdata = rk3128_clk_ofdata_to_platdata,
840 	.ops		= &rk3128_clk_ops,
841 	.bind		= rk3128_clk_bind,
842 	.probe		= rk3128_clk_probe,
843 };
844 
845 #ifndef CONFIG_SPL_BUILD
846 /**
847  * soc_clk_dump() - Print clock frequencies
848  * Returns zero on success
849  *
850  * Implementation for the clk dump command.
851  */
852 int soc_clk_dump(void)
853 {
854 	struct udevice *cru_dev;
855 	struct rk3128_clk_priv *priv;
856 	const struct rk3128_clk_info *clk_dump;
857 	struct clk clk;
858 	unsigned long clk_count = ARRAY_SIZE(clks_dump);
859 	unsigned long rate;
860 	int i, ret;
861 
862 	ret = uclass_get_device_by_driver(UCLASS_CLK,
863 					  DM_GET_DRIVER(rockchip_rk3128_cru),
864 					  &cru_dev);
865 	if (ret) {
866 		printf("%s failed to get cru device\n", __func__);
867 		return ret;
868 	}
869 
870 	priv = dev_get_priv(cru_dev);
871 	printf("CLK: (%s. arm: enter %lu KHz, init %lu KHz, kernel %lu%s)\n",
872 	       priv->sync_kernel ? "sync kernel" : "uboot",
873 	       priv->armclk_enter_hz / 1000,
874 	       priv->armclk_init_hz / 1000,
875 	       priv->set_armclk_rate ? priv->armclk_hz / 1000 : 0,
876 	       priv->set_armclk_rate ? " KHz" : "N/A");
877 	for (i = 0; i < clk_count; i++) {
878 		clk_dump = &clks_dump[i];
879 		if (clk_dump->name) {
880 			clk.id = clk_dump->id;
881 			if (clk_dump->is_cru)
882 				ret = clk_request(cru_dev, &clk);
883 			if (ret < 0)
884 				return ret;
885 
886 			rate = clk_get_rate(&clk);
887 			clk_free(&clk);
888 			if (i == 0) {
889 				if (rate < 0)
890 					printf("  %s %s\n", clk_dump->name,
891 					       "unknown");
892 				else
893 					printf("  %s %lu KHz\n", clk_dump->name,
894 					       rate / 1000);
895 			} else {
896 				if (rate < 0)
897 					printf("  %s %s\n", clk_dump->name,
898 					       "unknown");
899 				else
900 					printf("  %s %lu KHz\n", clk_dump->name,
901 					       rate / 1000);
902 			}
903 		}
904 	}
905 
906 	return 0;
907 }
908 #endif
909 
910