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