xref: /rk3399_rockchip-uboot/drivers/clk/rockchip/clk_rk3128.c (revision e8c34540a61ba8ec3ef255e3e8a72e7d3409f5f5)
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 
473 static ulong rk3128_crypto_get_rate(struct rk3128_clk_priv *priv)
474 {
475 	struct rk3128_cru *cru = priv->cru;
476 	u32 div, val;
477 
478 	val = readl(&cru->cru_clksel_con[24]);
479 	div = (val & CLK_CRYPTO_DIV_CON_MASK) >> CLK_CRYPTO_DIV_CON_SHIFT;
480 
481 	return DIV_TO_RATE(rk3128_bus_get_clk(priv, ACLK_CPU), div);
482 }
483 
484 static ulong rk3128_crypto_set_rate(struct rk3128_clk_priv *priv,
485 				    uint hz)
486 {
487 	struct rk3128_cru *cru = priv->cru;
488 	int src_clk_div;
489 	uint p_rate;
490 
491 	p_rate = rk3128_bus_get_clk(priv, ACLK_CPU);
492 	src_clk_div = DIV_ROUND_UP(p_rate, hz) - 1;
493 	assert(src_clk_div < 3);
494 
495 	rk_clrsetreg(&cru->cru_clksel_con[24],
496 		     CLK_CRYPTO_DIV_CON_MASK,
497 		     src_clk_div << CLK_CRYPTO_DIV_CON_SHIFT);
498 
499 	return rk3128_crypto_get_rate(priv);
500 }
501 #endif
502 
503 static ulong rk3128_clk_get_rate(struct clk *clk)
504 {
505 	struct rk3128_clk_priv *priv = dev_get_priv(clk->dev);
506 	ulong rate = 0;
507 
508 	switch (clk->id) {
509 	case PLL_APLL:
510 	case PLL_DPLL:
511 	case PLL_CPLL:
512 	case PLL_GPLL:
513 		rate =  rockchip_pll_get_rate(&rk3128_pll_clks[clk->id - 1],
514 					      priv->cru, clk->id - 1);
515 		break;
516 	case ARMCLK:
517 		rate = rockchip_pll_get_rate(&rk3128_pll_clks[APLL],
518 					     priv->cru, APLL);
519 		break;
520 	case HCLK_EMMC:
521 	case SCLK_EMMC:
522 	case HCLK_SDMMC:
523 	case SCLK_SDMMC:
524 	case HCLK_SDIO:
525 	case SCLK_SDIO:
526 		rate = rockchip_mmc_get_clk(priv, clk->id);
527 		break;
528 	case ACLK_PERI:
529 	case HCLK_PERI:
530 	case PCLK_PERI:
531 	case PCLK_I2C0:
532 	case PCLK_I2C1:
533 	case PCLK_I2C2:
534 	case PCLK_I2C3:
535 	case PCLK_PWM:
536 	case PCLK_WDT:
537 		rate = rk3128_peri_get_clk(priv, clk->id);
538 		break;
539 	case ACLK_CPU:
540 	case HCLK_CPU:
541 	case PCLK_CPU:
542 		rate = rk3128_bus_get_clk(priv, clk->id);
543 		break;
544 #ifndef CONFIG_SPL_BUILD
545 	case SCLK_SARADC:
546 		rate = rk3128_saradc_get_clk(priv);
547 		break;
548 	case DCLK_VOP:
549 	case ACLK_VIO0:
550 	case ACLK_VIO1:
551 	case ACLK_LCDC0:
552 		rate = rk3128_vop_get_rate(priv, clk->id);
553 		break;
554 	case SCLK_CRYPTO:
555 		rate = rk3128_crypto_get_rate(priv);
556 		break;
557 #endif
558 	default:
559 		return -ENOENT;
560 	}
561 	return rate;
562 }
563 
564 static ulong rk3128_clk_set_rate(struct clk *clk, ulong rate)
565 {
566 	struct rk3128_clk_priv *priv = dev_get_priv(clk->dev);
567 	ulong ret = 0;
568 
569 	switch (clk->id) {
570 	case PLL_APLL:
571 	case PLL_DPLL:
572 	case PLL_CPLL:
573 		ret = rockchip_pll_set_rate(&rk3128_pll_clks[clk->id - 1],
574 					    priv->cru, clk->id - 1, rate);
575 	case PLL_GPLL:
576 		ret = rockchip_pll_set_rate(&rk3128_pll_clks[GPLL],
577 					    priv->cru, GPLL, rate);
578 		priv->gpll_hz = rate;
579 		break;
580 	case ARMCLK:
581 		if (priv->armclk_hz)
582 			ret = rk3128_armclk_set_clk(priv, rate);
583 		priv->armclk_hz = rate;
584 		break;
585 	case HCLK_EMMC:
586 	case SCLK_EMMC:
587 	case SCLK_EMMC_SAMPLE:
588 	case HCLK_SDMMC:
589 	case SCLK_SDMMC:
590 	case SCLK_SDMMC_SAMPLE:
591 	case HCLK_SDIO:
592 	case SCLK_SDIO:
593 	case SCLK_SDIO_SAMPLE:
594 		ret = rockchip_mmc_set_clk(priv, clk->id, rate);
595 		break;
596 	case ACLK_PERI:
597 	case PCLK_PERI:
598 	case HCLK_PERI:
599 	case PCLK_I2C0:
600 	case PCLK_I2C1:
601 	case PCLK_I2C2:
602 	case PCLK_I2C3:
603 	case PCLK_PWM:
604 		ret = rk3128_peri_set_clk(priv, clk->id, rate);
605 		break;
606 	case ACLK_CPU:
607 	case HCLK_CPU:
608 	case PCLK_CPU:
609 		ret = rk3128_bus_set_clk(priv, clk->id, rate);
610 		break;
611 #ifndef CONFIG_SPL_BUILD
612 	case SCLK_SARADC:
613 		ret = rk3128_saradc_set_clk(priv, rate);
614 		break;
615 	case DCLK_VOP:
616 	case ACLK_VIO0:
617 	case ACLK_VIO1:
618 	case ACLK_LCDC0:
619 		ret = rk3128_vop_set_clk(priv, clk->id, rate);
620 		break;
621 	case SCLK_CRYPTO:
622 		ret = rk3128_crypto_set_rate(priv, rate);
623 		break;
624 #endif
625 	default:
626 		return -ENOENT;
627 	}
628 	return ret;
629 }
630 
631 #define ROCKCHIP_MMC_DELAY_SEL		BIT(10)
632 #define ROCKCHIP_MMC_DEGREE_MASK	0x3
633 #define ROCKCHIP_MMC_DELAYNUM_OFFSET	2
634 #define ROCKCHIP_MMC_DELAYNUM_MASK	(0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
635 
636 #define PSECS_PER_SEC 1000000000000LL
637 /*
638  * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
639  * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
640  */
641 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
642 
643 int rk3128_mmc_get_phase(struct clk *clk)
644 {
645 	struct rk3128_clk_priv *priv = dev_get_priv(clk->dev);
646 	struct rk3128_cru *cru = priv->cru;
647 	u32 raw_value, delay_num;
648 	u16 degrees = 0;
649 	ulong rate;
650 
651 	rate = rk3128_clk_get_rate(clk);
652 
653 	if (rate < 0)
654 		return rate;
655 
656 	if (clk->id == SCLK_EMMC_SAMPLE)
657 		raw_value = readl(&cru->cru_emmc_con[1]);
658 	else if (clk->id == SCLK_SDMMC_SAMPLE)
659 		raw_value = readl(&cru->cru_sdmmc_con[1]);
660 	else
661 		raw_value = readl(&cru->cru_sdio_con[1]);
662 
663 	raw_value >>= 1;
664 	degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
665 
666 	if (raw_value & ROCKCHIP_MMC_DELAY_SEL) {
667 		/* degrees/delaynum * 10000 */
668 		unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) *
669 					36 * (rate / 1000000);
670 
671 		delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
672 		delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET;
673 		degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000);
674 	}
675 
676 	return degrees % 360;
677 }
678 
679 int rk3128_mmc_set_phase(struct clk *clk, u32 degrees)
680 {
681 	struct rk3128_clk_priv *priv = dev_get_priv(clk->dev);
682 	struct rk3128_cru *cru = priv->cru;
683 	u8 nineties, remainder, delay_num;
684 	u32 raw_value, delay;
685 	ulong rate;
686 
687 	rate = rk3128_clk_get_rate(clk);
688 
689 	if (rate < 0)
690 		return rate;
691 
692 	nineties = degrees / 90;
693 	remainder = (degrees % 90);
694 
695 	/*
696 	 * Convert to delay; do a little extra work to make sure we
697 	 * don't overflow 32-bit / 64-bit numbers.
698 	 */
699 	delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */
700 	delay *= remainder;
701 	delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 *
702 				(ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10));
703 
704 	delay_num = (u8)min_t(u32, delay, 255);
705 
706 	raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
707 	raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
708 	raw_value |= nineties;
709 
710 	raw_value <<= 1;
711 	if (clk->id == SCLK_EMMC_SAMPLE)
712 		writel(raw_value | 0xffff0000, &cru->cru_emmc_con[1]);
713 	else if (clk->id == SCLK_SDMMC_SAMPLE)
714 		writel(raw_value | 0xffff0000, &cru->cru_sdmmc_con[1]);
715 	else
716 		writel(raw_value | 0xffff0000, &cru->cru_sdio_con[1]);
717 
718 	debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n",
719 	      degrees, delay_num, raw_value, rk3128_mmc_get_phase(clk));
720 
721 	return 0;
722 }
723 
724 static int rk3128_clk_get_phase(struct clk *clk)
725 {
726 	int ret;
727 
728 	debug("%s %ld\n", __func__, clk->id);
729 	switch (clk->id) {
730 	case SCLK_EMMC_SAMPLE:
731 	case SCLK_SDMMC_SAMPLE:
732 	case SCLK_SDIO_SAMPLE:
733 		ret = rk3128_mmc_get_phase(clk);
734 		break;
735 	default:
736 		return -ENOENT;
737 	}
738 
739 	return ret;
740 }
741 
742 static int rk3128_clk_set_phase(struct clk *clk, int degrees)
743 {
744 	int ret;
745 
746 	debug("%s %ld\n", __func__, clk->id);
747 	switch (clk->id) {
748 	case SCLK_EMMC_SAMPLE:
749 	case SCLK_SDMMC_SAMPLE:
750 	case SCLK_SDIO_SAMPLE:
751 		ret = rk3128_mmc_set_phase(clk, degrees);
752 		break;
753 	default:
754 		return -ENOENT;
755 	}
756 
757 	return ret;
758 }
759 
760 static struct clk_ops rk3128_clk_ops = {
761 	.get_rate	= rk3128_clk_get_rate,
762 	.set_rate	= rk3128_clk_set_rate,
763 	.get_phase	= rk3128_clk_get_phase,
764 	.set_phase	= rk3128_clk_set_phase,
765 };
766 
767 static int rk3128_clk_ofdata_to_platdata(struct udevice *dev)
768 {
769 	struct rk3128_clk_priv *priv = dev_get_priv(dev);
770 
771 	priv->cru = dev_read_addr_ptr(dev);
772 
773 	return 0;
774 }
775 
776 static void rkclk_init(struct rk3128_clk_priv *priv)
777 {
778 	if (rockchip_pll_get_rate(&rk3128_pll_clks[APLL],
779 				  priv->cru, APLL) != APLL_HZ)
780 		rk3128_armclk_set_clk(priv, APLL_HZ);
781 
782 	priv->gpll_hz = rockchip_pll_get_rate(&rk3128_pll_clks[GPLL],
783 					      priv->cru, GPLL);
784 	rk3128_bus_set_clk(priv, ACLK_CPU, ACLK_BUS_HZ / 2);
785 	rk3128_peri_set_clk(priv, ACLK_PERI, ACLK_PERI_HZ / 2);
786 	rockchip_pll_set_rate(&rk3128_pll_clks[GPLL],
787 			      priv->cru, GPLL, GPLL_HZ);
788 	priv->gpll_hz = GPLL_HZ;
789 	rk_clrsetreg(&priv->cru->cru_clksel_con[2],
790 		     NANDC_PLL_SEL_MASK | NANDC_CLK_DIV_MASK,
791 		     NANDC_PLL_SEL_GPLL << NANDC_PLL_SEL_SHIFT |
792 		     3 << NANDC_CLK_DIV_SHIFT);
793 	rk_clrsetreg(&priv->cru->cru_clksel_con[11],
794 		     SFC_PLL_SEL_MASK | SFC_CLK_DIV_MASK,
795 		     SFC_PLL_SEL_GPLL << SFC_PLL_SEL_SHIFT |
796 		     9 << SFC_CLK_DIV_SHIFT);
797 
798 	rk3128_bus_set_clk(priv, ACLK_CPU, ACLK_BUS_HZ);
799 	rk3128_bus_set_clk(priv, HCLK_CPU, ACLK_BUS_HZ / 2);
800 	rk3128_bus_set_clk(priv, PCLK_CPU, ACLK_BUS_HZ / 2);
801 	rk3128_peri_set_clk(priv, ACLK_PERI, ACLK_PERI_HZ);
802 	rk3128_peri_set_clk(priv, HCLK_PERI, ACLK_PERI_HZ / 2);
803 	rk3128_peri_set_clk(priv, PCLK_PERI, ACLK_PERI_HZ / 2);
804 
805 	rockchip_pll_set_rate(&rk3128_pll_clks[CPLL],
806 			      priv->cru, CPLL, CPLL_HZ);
807 }
808 
809 static int rk3128_clk_probe(struct udevice *dev)
810 {
811 	struct rk3128_clk_priv *priv = dev_get_priv(dev);
812 
813 	priv->sync_kernel = false;
814 	if (!priv->armclk_enter_hz)
815 		priv->armclk_enter_hz =
816 		rockchip_pll_get_rate(&rk3128_pll_clks[APLL],
817 				      priv->cru, APLL);
818 	rkclk_init(priv);
819 	if (!priv->armclk_init_hz)
820 		priv->armclk_init_hz =
821 		rockchip_pll_get_rate(&rk3128_pll_clks[APLL],
822 				      priv->cru, APLL);
823 
824 	return 0;
825 }
826 
827 static int rk3128_clk_bind(struct udevice *dev)
828 {
829 	int ret;
830 	struct udevice *sys_child, *sf_child;
831 	struct sysreset_reg *priv;
832 	struct softreset_reg *sf_priv;
833 
834 	/* The reset driver does not have a device node, so bind it here */
835 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
836 				 &sys_child);
837 	if (ret) {
838 		debug("Warning: No sysreset driver: ret=%d\n", ret);
839 	} else {
840 		priv = malloc(sizeof(struct sysreset_reg));
841 		priv->glb_srst_fst_value = offsetof(struct rk3128_cru,
842 						    cru_glb_srst_fst_value);
843 		priv->glb_srst_snd_value = offsetof(struct rk3128_cru,
844 						    cru_glb_srst_snd_value);
845 		sys_child->priv = priv;
846 	}
847 
848 	ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
849 					 dev_ofnode(dev), &sf_child);
850 	if (ret) {
851 		debug("Warning: No rockchip reset driver: ret=%d\n", ret);
852 	} else {
853 		sf_priv = malloc(sizeof(struct softreset_reg));
854 		sf_priv->sf_reset_offset = offsetof(struct rk3128_cru,
855 						    cru_softrst_con[0]);
856 		sf_priv->sf_reset_num = 9;
857 		sf_child->priv = sf_priv;
858 	}
859 
860 	return 0;
861 }
862 
863 static const struct udevice_id rk3128_clk_ids[] = {
864 	{ .compatible = "rockchip,rk3128-cru" },
865 	{ .compatible = "rockchip,rk3126-cru" },
866 	{ }
867 };
868 
869 U_BOOT_DRIVER(rockchip_rk3128_cru) = {
870 	.name		= "clk_rk3128",
871 	.id		= UCLASS_CLK,
872 	.of_match	= rk3128_clk_ids,
873 	.priv_auto_alloc_size = sizeof(struct rk3128_clk_priv),
874 	.ofdata_to_platdata = rk3128_clk_ofdata_to_platdata,
875 	.ops		= &rk3128_clk_ops,
876 	.bind		= rk3128_clk_bind,
877 	.probe		= rk3128_clk_probe,
878 };
879 
880 #ifndef CONFIG_SPL_BUILD
881 /**
882  * soc_clk_dump() - Print clock frequencies
883  * Returns zero on success
884  *
885  * Implementation for the clk dump command.
886  */
887 int soc_clk_dump(void)
888 {
889 	struct udevice *cru_dev;
890 	struct rk3128_clk_priv *priv;
891 	const struct rk3128_clk_info *clk_dump;
892 	struct clk clk;
893 	unsigned long clk_count = ARRAY_SIZE(clks_dump);
894 	unsigned long rate;
895 	int i, ret;
896 
897 	ret = uclass_get_device_by_driver(UCLASS_CLK,
898 					  DM_GET_DRIVER(rockchip_rk3128_cru),
899 					  &cru_dev);
900 	if (ret) {
901 		printf("%s failed to get cru device\n", __func__);
902 		return ret;
903 	}
904 
905 	priv = dev_get_priv(cru_dev);
906 	printf("CLK: (%s. arm: enter %lu KHz, init %lu KHz, kernel %lu%s)\n",
907 	       priv->sync_kernel ? "sync kernel" : "uboot",
908 	       priv->armclk_enter_hz / 1000,
909 	       priv->armclk_init_hz / 1000,
910 	       priv->set_armclk_rate ? priv->armclk_hz / 1000 : 0,
911 	       priv->set_armclk_rate ? " KHz" : "N/A");
912 	for (i = 0; i < clk_count; i++) {
913 		clk_dump = &clks_dump[i];
914 		if (clk_dump->name) {
915 			clk.id = clk_dump->id;
916 			if (clk_dump->is_cru)
917 				ret = clk_request(cru_dev, &clk);
918 			if (ret < 0)
919 				return ret;
920 
921 			rate = clk_get_rate(&clk);
922 			clk_free(&clk);
923 			if (i == 0) {
924 				if (rate < 0)
925 					printf("  %s %s\n", clk_dump->name,
926 					       "unknown");
927 				else
928 					printf("  %s %lu KHz\n", clk_dump->name,
929 					       rate / 1000);
930 			} else {
931 				if (rate < 0)
932 					printf("  %s %s\n", clk_dump->name,
933 					       "unknown");
934 				else
935 					printf("  %s %lu KHz\n", clk_dump->name,
936 					       rate / 1000);
937 			}
938 		}
939 	}
940 
941 	return 0;
942 }
943 #endif
944 
945