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