xref: /rk3399_rockchip-uboot/drivers/clk/rockchip/clk_rk3128.c (revision 2c6a058b7ea25398013cb25b4e3bb96fe40da1a5)
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 		con = readl(&cru->cru_clksel_con[10]);
241 		div = (con & PCLK_PERI_DIV_MASK) >> PCLK_PERI_DIV_SHIFT;
242 		parent = rk3128_peri_get_clk(priv, ACLK_PERI);
243 		break;
244 	case HCLK_PERI:
245 		con = readl(&cru->cru_clksel_con[10]);
246 		div = (con & HCLK_PERI_DIV_MASK) >> HCLK_PERI_DIV_SHIFT;
247 		parent = rk3128_peri_get_clk(priv, ACLK_PERI);
248 		break;
249 	default:
250 		printf("do not support this peripheral bus\n");
251 		return -EINVAL;
252 	}
253 
254 	return DIV_TO_RATE(parent, div);
255 }
256 
257 static ulong rk3128_peri_set_clk(struct rk3128_clk_priv *priv,
258 				 ulong clk_id, uint hz)
259 {
260 	struct rk3128_cru *cru = priv->cru;
261 	int src_clk_div;
262 
263 	switch (clk_id) {
264 	case ACLK_PERI:
265 		src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
266 		assert(src_clk_div - 1 < 32);
267 		rk_clrsetreg(&cru->cru_clksel_con[10],
268 			     PERI_PLL_SEL_MASK | ACLK_PERI_DIV_MASK,
269 			     PERI_PLL_SEL_GPLL << PERI_PLL_SEL_SHIFT |
270 			     (src_clk_div - 1) << ACLK_PERI_DIV_SHIFT);
271 		break;
272 	case PCLK_I2C0:
273 	case PCLK_I2C1:
274 	case PCLK_I2C2:
275 	case PCLK_I2C3:
276 	case PCLK_PWM:
277 	case PCLK_PERI:
278 		src_clk_div = DIV_ROUND_UP(rk3128_peri_get_clk(priv,
279 							       ACLK_PERI),
280 					   hz);
281 		assert(src_clk_div - 1 < 3);
282 		rk_clrsetreg(&cru->cru_clksel_con[10],
283 			     PCLK_PERI_DIV_MASK,
284 			     (src_clk_div - 1) << PCLK_PERI_DIV_SHIFT);
285 		break;
286 	case HCLK_PERI:
287 		src_clk_div = DIV_ROUND_UP(rk3128_peri_get_clk(priv,
288 							       ACLK_PERI),
289 					   hz);
290 		assert(src_clk_div - 1 < 7);
291 		rk_clrsetreg(&cru->cru_clksel_con[10],
292 			     HCLK_PERI_DIV_MASK,
293 			     (src_clk_div - 1) << HCLK_PERI_DIV_SHIFT);
294 		break;
295 	default:
296 		printf("do not support this peripheral bus\n");
297 		return -EINVAL;
298 	}
299 
300 	return rk3128_peri_get_clk(priv, clk_id);
301 }
302 
303 static ulong rk3128_bus_get_clk(struct rk3128_clk_priv *priv, ulong clk_id)
304 {
305 	struct rk3128_cru *cru = priv->cru;
306 	u32 div, con, parent;
307 
308 	switch (clk_id) {
309 	case ACLK_CPU:
310 		con = readl(&cru->cru_clksel_con[0]);
311 		div = (con & ACLK_BUS_DIV_MASK) >> ACLK_BUS_DIV_SHIFT;
312 		parent = priv->gpll_hz;
313 		break;
314 	case PCLK_CPU:
315 		con = readl(&cru->cru_clksel_con[1]);
316 		div = (con & PCLK_BUS_DIV_MASK) >> PCLK_BUS_DIV_SHIFT;
317 		parent = rk3128_bus_get_clk(priv, ACLK_CPU);
318 		break;
319 	case HCLK_CPU:
320 		con = readl(&cru->cru_clksel_con[1]);
321 		div = (con & HCLK_BUS_DIV_MASK) >> HCLK_BUS_DIV_SHIFT;
322 		parent = rk3128_bus_get_clk(priv, ACLK_CPU);
323 		break;
324 	default:
325 		printf("do not support this peripheral bus\n");
326 		return -EINVAL;
327 	}
328 
329 	return DIV_TO_RATE(parent, div);
330 }
331 
332 static ulong rk3128_bus_set_clk(struct rk3128_clk_priv *priv,
333 				ulong clk_id, uint hz)
334 {
335 	struct rk3128_cru *cru = priv->cru;
336 	int src_clk_div;
337 
338 	switch (clk_id) {
339 	case ACLK_CPU:
340 		src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
341 		assert(src_clk_div - 1 < 32);
342 		rk_clrsetreg(&cru->cru_clksel_con[0],
343 			     BUS_PLL_SEL_MASK | ACLK_BUS_DIV_MASK,
344 			     BUS_PLL_SEL_GPLL << BUS_PLL_SEL_SHIFT |
345 			     (src_clk_div - 1) << ACLK_BUS_DIV_SHIFT);
346 		break;
347 	case PCLK_CPU:
348 		src_clk_div = DIV_ROUND_UP(rk3128_bus_get_clk(priv,
349 							      ACLK_CPU),
350 					   hz);
351 		assert(src_clk_div - 1 < 3);
352 		rk_clrsetreg(&cru->cru_clksel_con[1],
353 			     PCLK_BUS_DIV_MASK,
354 			     (src_clk_div - 1) << PCLK_BUS_DIV_SHIFT);
355 		break;
356 	case HCLK_CPU:
357 		src_clk_div = DIV_ROUND_UP(rk3128_bus_get_clk(priv,
358 							      ACLK_CPU),
359 					   hz);
360 		assert(src_clk_div - 1 < 7);
361 		rk_clrsetreg(&cru->cru_clksel_con[1],
362 			     HCLK_BUS_DIV_MASK,
363 			     (src_clk_div - 1) << HCLK_BUS_DIV_SHIFT);
364 		break;
365 	default:
366 		printf("do not support this peripheral bus\n");
367 		return -EINVAL;
368 	}
369 
370 	return rk3128_bus_get_clk(priv, clk_id);
371 }
372 
373 #ifndef CONFIG_SPL_BUILD
374 static ulong rk3128_saradc_get_clk(struct rk3128_clk_priv *priv)
375 {
376 	struct rk3128_cru *cru = priv->cru;
377 	u32 div, val;
378 
379 	val = readl(&cru->cru_clksel_con[24]);
380 	div = bitfield_extract(val, SARADC_DIV_CON_SHIFT,
381 			       SARADC_DIV_CON_WIDTH);
382 
383 	return DIV_TO_RATE(OSC_HZ, div);
384 }
385 
386 static ulong rk3128_saradc_set_clk(struct rk3128_clk_priv *priv, uint hz)
387 {
388 	struct rk3128_cru *cru = priv->cru;
389 	int src_clk_div;
390 
391 	src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1;
392 	assert(src_clk_div < 128);
393 
394 	rk_clrsetreg(&cru->cru_clksel_con[24],
395 		     SARADC_DIV_CON_MASK,
396 		     src_clk_div << SARADC_DIV_CON_SHIFT);
397 
398 	return rk3128_saradc_get_clk(priv);
399 }
400 
401 #define RK3128_LCDC_PLL_LIMIT			600000000
402 
403 static ulong rk3128_vop_set_clk(struct rk3128_clk_priv *priv,
404 				ulong clk_id, uint hz)
405 {
406 	struct rk3128_cru *cru = priv->cru;
407 	int src_clk_div;
408 
409 	src_clk_div = GPLL_HZ / hz;
410 	assert(src_clk_div - 1 < 31);
411 
412 	switch (clk_id) {
413 	case ACLK_LCDC0:
414 	case ACLK_VIO0:
415 		rk_clrsetreg(&cru->cru_clksel_con[31],
416 			     VIO0_PLL_MASK | VIO0_DIV_MASK,
417 			     VIO0_SEL_GPLL << VIO0_PLL_SHIFT |
418 			     (src_clk_div - 1) << VIO0_DIV_SHIFT);
419 		break;
420 	case ACLK_VIO1:
421 		rk_clrsetreg(&cru->cru_clksel_con[31],
422 			     VIO1_PLL_MASK | VIO1_DIV_MASK,
423 			     VIO1_SEL_GPLL << VIO1_PLL_SHIFT |
424 			     (src_clk_div - 1) << VIO1_DIV_SHIFT);
425 		break;
426 	case DCLK_VOP:
427 		src_clk_div = DIV_ROUND_UP(RK3128_LCDC_PLL_LIMIT, hz);
428 		rockchip_pll_set_rate(&rk3128_pll_clks[CPLL],
429 				      priv->cru, CPLL, src_clk_div * hz);
430 		rk_clrsetreg(&cru->cru_clksel_con[27],
431 			      DCLK_VOP_SEL_MASK | DCLK_VOP_DIV_CON_MASK,
432 			     DCLK_VOP_PLL_SEL_CPLL << DCLK_VOP_SEL_SHIFT |
433 			     (src_clk_div - 1) << DCLK_VOP_DIV_CON_SHIFT);
434 		break;
435 	default:
436 		printf("do not support this vop freq\n");
437 		return -EINVAL;
438 	}
439 
440 	return hz;
441 }
442 
443 static ulong rk3128_vop_get_rate(struct rk3128_clk_priv *priv, ulong clk_id)
444 {
445 	struct rk3128_cru *cru = priv->cru;
446 	u32 div, con, parent;
447 
448 	switch (clk_id) {
449 	case ACLK_LCDC0:
450 	case ACLK_VIO0:
451 		con = readl(&cru->cru_clksel_con[31]);
452 		div = con  & 0x1f;
453 		parent = GPLL_HZ;
454 		break;
455 	case ACLK_VIO1:
456 		con = readl(&cru->cru_clksel_con[31]);
457 		div = (con >> 8) & 0x1f;
458 		parent = GPLL_HZ;
459 		break;
460 	case DCLK_VOP:
461 		con = readl(&cru->cru_clksel_con[27]);
462 		div = (con & DCLK_VOP_DIV_CON_MASK) >> DCLK_VOP_DIV_CON_SHIFT;
463 		parent = rockchip_pll_get_rate(&rk3128_pll_clks[CPLL],
464 					       priv->cru, CPLL);
465 		break;
466 	default:
467 		return -ENOENT;
468 	}
469 	return DIV_TO_RATE(parent, div);
470 }
471 #endif
472 
473 static ulong rk3128_clk_get_rate(struct clk *clk)
474 {
475 	struct rk3128_clk_priv *priv = dev_get_priv(clk->dev);
476 	ulong rate = 0;
477 
478 	switch (clk->id) {
479 	case PLL_APLL:
480 	case PLL_DPLL:
481 	case PLL_CPLL:
482 	case PLL_GPLL:
483 		rate =  rockchip_pll_get_rate(&rk3128_pll_clks[clk->id - 1],
484 					      priv->cru, clk->id - 1);
485 		break;
486 	case ARMCLK:
487 		rate = rockchip_pll_get_rate(&rk3128_pll_clks[APLL],
488 					     priv->cru, APLL);
489 		break;
490 	case HCLK_EMMC:
491 	case SCLK_EMMC:
492 	case HCLK_SDMMC:
493 	case SCLK_SDMMC:
494 	case HCLK_SDIO:
495 	case SCLK_SDIO:
496 		rate = rockchip_mmc_get_clk(priv, clk->id);
497 		break;
498 	case ACLK_PERI:
499 	case HCLK_PERI:
500 	case PCLK_PERI:
501 	case PCLK_I2C0:
502 	case PCLK_I2C1:
503 	case PCLK_I2C2:
504 	case PCLK_I2C3:
505 	case PCLK_PWM:
506 		rate = rk3128_peri_get_clk(priv, clk->id);
507 		break;
508 	case ACLK_CPU:
509 	case HCLK_CPU:
510 	case PCLK_CPU:
511 		rate = rk3128_bus_get_clk(priv, clk->id);
512 		break;
513 #ifndef CONFIG_SPL_BUILD
514 	case SCLK_SARADC:
515 		rate = rk3128_saradc_get_clk(priv);
516 		break;
517 	case DCLK_VOP:
518 	case ACLK_VIO0:
519 	case ACLK_VIO1:
520 	case ACLK_LCDC0:
521 		rate = rk3128_vop_get_rate(priv, clk->id);
522 		break;
523 #endif
524 	default:
525 		return -ENOENT;
526 	}
527 	return rate;
528 }
529 
530 static ulong rk3128_clk_set_rate(struct clk *clk, ulong rate)
531 {
532 	struct rk3128_clk_priv *priv = dev_get_priv(clk->dev);
533 	ulong ret;
534 
535 	switch (clk->id) {
536 	case PLL_APLL:
537 	case PLL_DPLL:
538 	case PLL_CPLL:
539 		ret = rockchip_pll_set_rate(&rk3128_pll_clks[clk->id - 1],
540 					    priv->cru, clk->id - 1, rate);
541 	case PLL_GPLL:
542 		ret = rockchip_pll_set_rate(&rk3128_pll_clks[GPLL],
543 					    priv->cru, GPLL, rate);
544 		priv->gpll_hz = rate;
545 		break;
546 	case ARMCLK:
547 		ret = rk3128_armclk_set_clk(priv, rate);
548 		break;
549 	case HCLK_EMMC:
550 	case SCLK_EMMC:
551 	case SCLK_EMMC_SAMPLE:
552 	case HCLK_SDMMC:
553 	case SCLK_SDMMC:
554 	case SCLK_SDMMC_SAMPLE:
555 	case HCLK_SDIO:
556 	case SCLK_SDIO:
557 	case SCLK_SDIO_SAMPLE:
558 		ret = rockchip_mmc_set_clk(priv, clk->id, rate);
559 		break;
560 	case ACLK_PERI:
561 	case PCLK_PERI:
562 	case HCLK_PERI:
563 	case PCLK_I2C0:
564 	case PCLK_I2C1:
565 	case PCLK_I2C2:
566 	case PCLK_I2C3:
567 	case PCLK_PWM:
568 		ret = rk3128_peri_set_clk(priv, clk->id, rate);
569 		break;
570 	case ACLK_CPU:
571 	case HCLK_CPU:
572 	case PCLK_CPU:
573 		ret = rk3128_bus_set_clk(priv, clk->id, rate);
574 		break;
575 #ifndef CONFIG_SPL_BUILD
576 	case SCLK_SARADC:
577 		ret = rk3128_saradc_set_clk(priv, rate);
578 		break;
579 	case DCLK_VOP:
580 	case ACLK_VIO0:
581 	case ACLK_VIO1:
582 	case ACLK_LCDC0:
583 		ret = rk3128_vop_set_clk(priv, clk->id, rate);
584 		break;
585 #endif
586 	default:
587 		return -ENOENT;
588 	}
589 	return ret;
590 }
591 
592 #define ROCKCHIP_MMC_DELAY_SEL		BIT(10)
593 #define ROCKCHIP_MMC_DEGREE_MASK	0x3
594 #define ROCKCHIP_MMC_DELAYNUM_OFFSET	2
595 #define ROCKCHIP_MMC_DELAYNUM_MASK	(0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
596 
597 #define PSECS_PER_SEC 1000000000000LL
598 /*
599  * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
600  * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
601  */
602 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
603 
604 int rk3128_mmc_get_phase(struct clk *clk)
605 {
606 	struct rk3128_clk_priv *priv = dev_get_priv(clk->dev);
607 	struct rk3128_cru *cru = priv->cru;
608 	u32 raw_value, delay_num;
609 	u16 degrees = 0;
610 	ulong rate;
611 
612 	rate = rk3128_clk_get_rate(clk);
613 
614 	if (rate < 0)
615 		return rate;
616 
617 	if (clk->id == SCLK_EMMC_SAMPLE)
618 		raw_value = readl(&cru->cru_emmc_con[1]);
619 	else if (clk->id == SCLK_SDMMC_SAMPLE)
620 		raw_value = readl(&cru->cru_sdmmc_con[1]);
621 	else
622 		raw_value = readl(&cru->cru_sdio_con[1]);
623 
624 	raw_value >>= 1;
625 	degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
626 
627 	if (raw_value & ROCKCHIP_MMC_DELAY_SEL) {
628 		/* degrees/delaynum * 10000 */
629 		unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) *
630 					36 * (rate / 1000000);
631 
632 		delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
633 		delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET;
634 		degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000);
635 	}
636 
637 	return degrees % 360;
638 }
639 
640 int rk3128_mmc_set_phase(struct clk *clk, u32 degrees)
641 {
642 	struct rk3128_clk_priv *priv = dev_get_priv(clk->dev);
643 	struct rk3128_cru *cru = priv->cru;
644 	u8 nineties, remainder, delay_num;
645 	u32 raw_value, delay;
646 	ulong rate;
647 
648 	rate = rk3128_clk_get_rate(clk);
649 
650 	if (rate < 0)
651 		return rate;
652 
653 	nineties = degrees / 90;
654 	remainder = (degrees % 90);
655 
656 	/*
657 	 * Convert to delay; do a little extra work to make sure we
658 	 * don't overflow 32-bit / 64-bit numbers.
659 	 */
660 	delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */
661 	delay *= remainder;
662 	delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 *
663 				(ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10));
664 
665 	delay_num = (u8)min_t(u32, delay, 255);
666 
667 	raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
668 	raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
669 	raw_value |= nineties;
670 
671 	raw_value <<= 1;
672 	if (clk->id == SCLK_EMMC_SAMPLE)
673 		writel(raw_value | 0xffff0000, &cru->cru_emmc_con[1]);
674 	else if (clk->id == SCLK_SDMMC_SAMPLE)
675 		writel(raw_value | 0xffff0000, &cru->cru_sdmmc_con[1]);
676 	else
677 		writel(raw_value | 0xffff0000, &cru->cru_sdio_con[1]);
678 
679 	debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n",
680 	      degrees, delay_num, raw_value, rk3128_mmc_get_phase(clk));
681 
682 	return 0;
683 }
684 
685 static int rk3128_clk_get_phase(struct clk *clk)
686 {
687 	int ret;
688 
689 	debug("%s %ld\n", __func__, clk->id);
690 	switch (clk->id) {
691 	case SCLK_EMMC_SAMPLE:
692 	case SCLK_SDMMC_SAMPLE:
693 	case SCLK_SDIO_SAMPLE:
694 		ret = rk3128_mmc_get_phase(clk);
695 		break;
696 	default:
697 		return -ENOENT;
698 	}
699 
700 	return ret;
701 }
702 
703 static int rk3128_clk_set_phase(struct clk *clk, int degrees)
704 {
705 	int ret;
706 
707 	debug("%s %ld\n", __func__, clk->id);
708 	switch (clk->id) {
709 	case SCLK_EMMC_SAMPLE:
710 	case SCLK_SDMMC_SAMPLE:
711 	case SCLK_SDIO_SAMPLE:
712 		ret = rk3128_mmc_set_phase(clk, degrees);
713 		break;
714 	default:
715 		return -ENOENT;
716 	}
717 
718 	return ret;
719 }
720 
721 static struct clk_ops rk3128_clk_ops = {
722 	.get_rate	= rk3128_clk_get_rate,
723 	.set_rate	= rk3128_clk_set_rate,
724 	.get_phase	= rk3128_clk_get_phase,
725 	.set_phase	= rk3128_clk_set_phase,
726 };
727 
728 static int rk3128_clk_ofdata_to_platdata(struct udevice *dev)
729 {
730 	struct rk3128_clk_priv *priv = dev_get_priv(dev);
731 
732 	priv->cru = dev_read_addr_ptr(dev);
733 
734 	return 0;
735 }
736 
737 static void rkclk_init(struct rk3128_clk_priv *priv)
738 {
739 	if (rockchip_pll_get_rate(&rk3128_pll_clks[APLL],
740 				  priv->cru, APLL) != APLL_HZ)
741 		rk3128_armclk_set_clk(priv, APLL_HZ);
742 
743 	priv->gpll_hz = rockchip_pll_get_rate(&rk3128_pll_clks[GPLL],
744 					      priv->cru, GPLL);
745 	rk3128_bus_set_clk(priv, ACLK_CPU, ACLK_BUS_HZ / 2);
746 	rk3128_peri_set_clk(priv, ACLK_PERI, ACLK_PERI_HZ / 2);
747 	rockchip_pll_set_rate(&rk3128_pll_clks[GPLL],
748 			      priv->cru, GPLL, GPLL_HZ);
749 	priv->gpll_hz = GPLL_HZ;
750 	rk_clrsetreg(&priv->cru->cru_clksel_con[2],
751 		     NANDC_PLL_SEL_MASK | NANDC_CLK_DIV_MASK,
752 		     NANDC_PLL_SEL_GPLL << NANDC_PLL_SEL_SHIFT |
753 		     3 << NANDC_CLK_DIV_SHIFT);
754 	rk3128_bus_set_clk(priv, ACLK_CPU, ACLK_BUS_HZ);
755 	rk3128_bus_set_clk(priv, HCLK_CPU, ACLK_BUS_HZ / 2);
756 	rk3128_bus_set_clk(priv, PCLK_CPU, ACLK_BUS_HZ / 2);
757 	rk3128_peri_set_clk(priv, ACLK_PERI, ACLK_PERI_HZ);
758 	rk3128_peri_set_clk(priv, HCLK_PERI, ACLK_PERI_HZ / 2);
759 	rk3128_peri_set_clk(priv, PCLK_PERI, ACLK_PERI_HZ / 2);
760 
761 	rockchip_pll_set_rate(&rk3128_pll_clks[CPLL],
762 			      priv->cru, CPLL, CPLL_HZ);
763 }
764 
765 static int rk3128_clk_probe(struct udevice *dev)
766 {
767 	struct rk3128_clk_priv *priv = dev_get_priv(dev);
768 
769 	rkclk_init(priv);
770 
771 	return 0;
772 }
773 
774 static int rk3128_clk_bind(struct udevice *dev)
775 {
776 	int ret;
777 	struct udevice *sys_child, *sf_child;
778 	struct sysreset_reg *priv;
779 	struct softreset_reg *sf_priv;
780 
781 	/* The reset driver does not have a device node, so bind it here */
782 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
783 				 &sys_child);
784 	if (ret) {
785 		debug("Warning: No sysreset driver: ret=%d\n", ret);
786 	} else {
787 		priv = malloc(sizeof(struct sysreset_reg));
788 		priv->glb_srst_fst_value = offsetof(struct rk3128_cru,
789 						    cru_glb_srst_fst_value);
790 		priv->glb_srst_snd_value = offsetof(struct rk3128_cru,
791 						    cru_glb_srst_snd_value);
792 		sys_child->priv = priv;
793 	}
794 
795 	ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
796 					 dev_ofnode(dev), &sf_child);
797 	if (ret) {
798 		debug("Warning: No rockchip reset driver: ret=%d\n", ret);
799 	} else {
800 		sf_priv = malloc(sizeof(struct softreset_reg));
801 		sf_priv->sf_reset_offset = offsetof(struct rk3128_cru,
802 						    cru_softrst_con[0]);
803 		sf_priv->sf_reset_num = 9;
804 		sf_child->priv = sf_priv;
805 	}
806 
807 	return 0;
808 }
809 
810 static const struct udevice_id rk3128_clk_ids[] = {
811 	{ .compatible = "rockchip,rk3128-cru" },
812 	{ .compatible = "rockchip,rk3126-cru" },
813 	{ }
814 };
815 
816 U_BOOT_DRIVER(rockchip_rk3128_cru) = {
817 	.name		= "clk_rk3128",
818 	.id		= UCLASS_CLK,
819 	.of_match	= rk3128_clk_ids,
820 	.priv_auto_alloc_size = sizeof(struct rk3128_clk_priv),
821 	.ofdata_to_platdata = rk3128_clk_ofdata_to_platdata,
822 	.ops		= &rk3128_clk_ops,
823 	.bind		= rk3128_clk_bind,
824 	.probe		= rk3128_clk_probe,
825 };
826 
827 #ifndef CONFIG_SPL_BUILD
828 /**
829  * soc_clk_dump() - Print clock frequencies
830  * Returns zero on success
831  *
832  * Implementation for the clk dump command.
833  */
834 int soc_clk_dump(void)
835 {
836 	struct udevice *cru_dev;
837 	const struct rk3128_clk_info *clk_dump;
838 	struct clk clk;
839 	unsigned long clk_count = ARRAY_SIZE(clks_dump);
840 	unsigned long rate;
841 	int i, ret;
842 
843 	ret = uclass_get_device_by_driver(UCLASS_CLK,
844 					  DM_GET_DRIVER(rockchip_rk3128_cru),
845 					  &cru_dev);
846 	if (ret) {
847 		printf("%s failed to get cru device\n", __func__);
848 		return ret;
849 	}
850 
851 	printf("CLK:");
852 	for (i = 0; i < clk_count; i++) {
853 		clk_dump = &clks_dump[i];
854 		if (clk_dump->name) {
855 			clk.id = clk_dump->id;
856 			if (clk_dump->is_cru)
857 				ret = clk_request(cru_dev, &clk);
858 			if (ret < 0)
859 				return ret;
860 
861 			rate = clk_get_rate(&clk);
862 			clk_free(&clk);
863 			if (i == 0) {
864 				if (rate < 0)
865 					printf("%10s%20s\n", clk_dump->name,
866 					       "unknown");
867 				else
868 					printf("%10s%20lu Hz\n", clk_dump->name,
869 					       rate);
870 			} else {
871 				if (rate < 0)
872 					printf("%14s%20s\n", clk_dump->name,
873 					       "unknown");
874 				else
875 					printf("%14s%20lu Hz\n", clk_dump->name,
876 					       rate);
877 			}
878 		}
879 	}
880 
881 	return 0;
882 }
883 #endif
884 
885