xref: /rk3399_rockchip-uboot/drivers/clk/rockchip/clk_rk3368.c (revision 73b4df6a98d2d973cbf1e2b18947abbdbdb82bc1)
1 /*
2  * (C) Copyright 2017 Rockchip Electronics Co., Ltd
3  * Author: Andy Yan <andy.yan@rock-chips.com>
4  * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
5  * SPDX-License-Identifier:	GPL-2.0
6  */
7 
8 #include <common.h>
9 #include <clk-uclass.h>
10 #include <dm.h>
11 #include <dt-structs.h>
12 #include <errno.h>
13 #include <mapmem.h>
14 #include <syscon.h>
15 #include <bitfield.h>
16 #include <asm/arch/clock.h>
17 #include <asm/arch/cru_rk3368.h>
18 #include <asm/arch/hardware.h>
19 #include <asm/io.h>
20 #include <dm/lists.h>
21 #include <dt-bindings/clock/rk3368-cru.h>
22 
23 DECLARE_GLOBAL_DATA_PTR;
24 
25 #if CONFIG_IS_ENABLED(OF_PLATDATA)
26 struct rk3368_clk_plat {
27 	struct dtd_rockchip_rk3368_cru dtd;
28 };
29 #endif
30 
31 struct pll_div {
32 	u32 nr;
33 	u32 nf;
34 	u32 no;
35 };
36 
37 #define OSC_HZ		(24 * 1000 * 1000)
38 #define APLL_L_HZ	(800 * 1000 * 1000)
39 #define APLL_B_HZ	(816 * 1000 * 1000)
40 #define GPLL_HZ		(576 * 1000 * 1000)
41 #define CPLL_HZ		(400 * 1000 * 1000)
42 #define NPLL_HZ		(594 * 1000 * 1000)
43 
44 #define DIV_TO_RATE(input_rate, div)    ((input_rate) / ((div) + 1))
45 
46 #if !defined(CONFIG_SPL_BUILD)
47 #define RK3368_CLK_DUMP(_id, _name, _iscru)	\
48 {						\
49 	.id = _id,				\
50 	.name = _name,				\
51 	.is_cru = _iscru,			\
52 }
53 
54 static const struct rk3368_clk_info clks_dump[] = {
55 	RK3368_CLK_DUMP(PLL_APLLB, "apllb", true),
56 	RK3368_CLK_DUMP(PLL_APLLL, "aplll", true),
57 	RK3368_CLK_DUMP(PLL_DPLL, "dpll", true),
58 	RK3368_CLK_DUMP(PLL_CPLL, "cpll", true),
59 	RK3368_CLK_DUMP(PLL_GPLL, "gpll", true),
60 	RK3368_CLK_DUMP(PLL_NPLL, "npll", true),
61 	RK3368_CLK_DUMP(ARMCLKB, "armclkb", true),
62 	RK3368_CLK_DUMP(ARMCLKL, "armclkl", true),
63 	RK3368_CLK_DUMP(ACLK_BUS, "aclk_bus", true),
64 	RK3368_CLK_DUMP(HCLK_BUS, "hclk_bus", true),
65 	RK3368_CLK_DUMP(PCLK_BUS, "pclk_Bus", true),
66 	RK3368_CLK_DUMP(ACLK_PERI, "aclk_peri", true),
67 	RK3368_CLK_DUMP(HCLK_PERI, "hclk_peri", true),
68 	RK3368_CLK_DUMP(PCLK_PERI, "pclk_peri", true),
69 };
70 #endif
71 
72 #define RK3368_CPUCLK_RATE(_rate, _aclk_div, _pclk_div)		\
73 {								\
74 	.rate	= _rate##U,					\
75 	.aclk_div = _aclk_div,					\
76 	.pclk_div = _pclk_div,					\
77 }
78 
79 static struct rockchip_cpu_rate_table rk3368_cpu_rates[] = {
80 #if !defined(CONFIG_SPL_BUILD)
81 	RK3368_CPUCLK_RATE(1200000000, 1, 5),
82 	RK3368_CPUCLK_RATE(1008000000, 1, 5),
83 #endif
84 	RK3368_CPUCLK_RATE(816000000, 1, 3),
85 	RK3368_CPUCLK_RATE(600000000, 1, 3),
86 };
87 
88 #define PLL_DIVISORS(hz, _nr, _no) { \
89 	.nr = _nr, .nf = (u32)((u64)hz * _nr * _no / OSC_HZ), .no = _no}; \
90 	_Static_assert(((u64)hz * _nr * _no / OSC_HZ) * OSC_HZ /\
91 		       (_nr * _no) == hz, #hz "Hz cannot be hit with PLL " \
92 		       "divisors on line " __stringify(__LINE__));
93 
94 #if IS_ENABLED(CONFIG_SPL_BUILD) || IS_ENABLED(CONFIG_TPL_BUILD)
95 static const struct pll_div apll_l_init_cfg = PLL_DIVISORS(APLL_L_HZ, 12, 2);
96 static const struct pll_div apll_b_init_cfg = PLL_DIVISORS(APLL_B_HZ, 1, 2);
97 #if !defined(CONFIG_TPL_BUILD)
98 static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 1, 2);
99 static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 1, 6);
100 #endif
101 #endif
102 static const struct pll_div npll_init_cfg = PLL_DIVISORS(NPLL_HZ, 1, 4);
103 
104 static ulong rk3368_clk_get_rate(struct clk *clk);
105 
106 #define VCO_MAX_KHZ	2200000
107 #define VCO_MIN_KHZ	440000
108 #define FREF_MAX_KHZ	2200000
109 #define FREF_MIN_KHZ	269
110 #define PLL_LIMIT_FREQ	400000000
111 
112 static int pll_para_config(ulong freq_hz, struct pll_div *div, uint *ext_div)
113 {
114 	uint ref_khz = OSC_HZ / 1000, nr, nf = 0;
115 	uint fref_khz;
116 	uint diff_khz, best_diff_khz;
117 	const uint max_nr = 1 << 6, max_nf = 1 << 12, max_no = 1 << 4;
118 	uint vco_khz;
119 	uint no = 1;
120 	uint freq_khz = freq_hz / 1000;
121 
122 	if (!freq_hz) {
123 		printf("%s: the frequency can not be 0 Hz\n", __func__);
124 		return -EINVAL;
125 	}
126 
127 	no = DIV_ROUND_UP(VCO_MIN_KHZ, freq_khz);
128 	if (ext_div) {
129 		*ext_div = DIV_ROUND_UP(PLL_LIMIT_FREQ, freq_hz);
130 		no = DIV_ROUND_UP(no, *ext_div);
131 	}
132 
133 	/* only even divisors (and 1) are supported */
134 	if (no > 1)
135 		no = DIV_ROUND_UP(no, 2) * 2;
136 
137 	vco_khz = freq_khz * no;
138 	if (ext_div)
139 		vco_khz *= *ext_div;
140 
141 	if (vco_khz < VCO_MIN_KHZ || vco_khz > VCO_MAX_KHZ || no > max_no) {
142 		printf("%s: Cannot find out VCO for Frequency (%luHz).\n",
143 		       __func__, freq_hz);
144 		return -1;
145 	}
146 
147 	div->no = no;
148 
149 	best_diff_khz = vco_khz;
150 	for (nr = 1; nr < max_nr && best_diff_khz; nr++) {
151 		fref_khz = ref_khz / nr;
152 		if (fref_khz < FREF_MIN_KHZ)
153 			break;
154 		if (fref_khz > FREF_MAX_KHZ)
155 			continue;
156 
157 		nf = vco_khz / fref_khz;
158 		if (nf >= max_nf)
159 			continue;
160 		diff_khz = vco_khz - nf * fref_khz;
161 		if (nf + 1 < max_nf && diff_khz > fref_khz / 2) {
162 			nf++;
163 			diff_khz = fref_khz - diff_khz;
164 		}
165 
166 		if (diff_khz >= best_diff_khz)
167 			continue;
168 
169 		best_diff_khz = diff_khz;
170 		div->nr = nr;
171 		div->nf = nf;
172 	}
173 
174 	if (best_diff_khz > 4 * 1000) {
175 		printf("%s:Fail to match output freq %lu,best_is %u Hz\n",
176 		       __func__, freq_hz, best_diff_khz * 1000);
177 		return -EINVAL;
178 	}
179 
180 	return 0;
181 }
182 
183 /* Get pll rate by id */
184 static uint32_t rkclk_pll_get_rate(struct rk3368_cru *cru,
185 				   enum rk3368_pll_id pll_id)
186 {
187 	uint32_t nr, no, nf;
188 	uint32_t con;
189 	struct rk3368_pll *pll = &cru->pll[pll_id];
190 
191 	con = readl(&pll->con3);
192 
193 	switch ((con & PLL_MODE_MASK) >> PLL_MODE_SHIFT) {
194 	case PLL_MODE_SLOW:
195 		return OSC_HZ;
196 	case PLL_MODE_NORMAL:
197 		con = readl(&pll->con0);
198 		no = ((con & PLL_OD_MASK) >> PLL_OD_SHIFT) + 1;
199 		nr = ((con & PLL_NR_MASK) >> PLL_NR_SHIFT) + 1;
200 		con = readl(&pll->con1);
201 		nf = ((con & PLL_NF_MASK) >> PLL_NF_SHIFT) + 1;
202 
203 		return (24 * nf / (nr * no)) * 1000000;
204 	case PLL_MODE_DEEP_SLOW:
205 	default:
206 		return 32768;
207 	}
208 }
209 
210 static int rkclk_set_pll(struct rk3368_cru *cru, enum rk3368_pll_id pll_id,
211 			 const struct pll_div *div)
212 {
213 	struct rk3368_pll *pll = &cru->pll[pll_id];
214 	/* All PLLs have same VCO and output frequency range restrictions*/
215 	uint vco_hz = OSC_HZ / 1000 * div->nf / div->nr * 1000;
216 	uint output_hz = vco_hz / div->no;
217 
218 	debug("PLL at %p: nf=%d, nr=%d, no=%d, vco=%u Hz, output=%u Hz\n",
219 	      pll, div->nf, div->nr, div->no, vco_hz, output_hz);
220 
221 	/* enter slow mode and reset pll */
222 	rk_clrsetreg(&pll->con3, PLL_MODE_MASK | PLL_RESET_MASK,
223 		     PLL_RESET << PLL_RESET_SHIFT);
224 
225 	rk_clrsetreg(&pll->con0, PLL_NR_MASK | PLL_OD_MASK,
226 		     ((div->nr - 1) << PLL_NR_SHIFT) |
227 		     ((div->no - 1) << PLL_OD_SHIFT));
228 	writel((div->nf - 1) << PLL_NF_SHIFT, &pll->con1);
229 	/*
230 	 * BWADJ should be set to NF / 2 to ensure the nominal bandwidth.
231 	 * Compare the RK3368 TRM, section "3.6.4 PLL Bandwidth Adjustment".
232 	 */
233 	if (pll_id == NPLL)
234 		clrsetbits_le32(&pll->con2, PLL_BWADJ_MASK, 0);
235 	else
236 		clrsetbits_le32(&pll->con2, PLL_BWADJ_MASK, (div->nf >> 1) - 1);
237 
238 	udelay(10);
239 
240 	/* return from reset */
241 	rk_clrreg(&pll->con3, PLL_RESET_MASK);
242 
243 	/* waiting for pll lock */
244 	while (!(readl(&pll->con1) & PLL_LOCK_STA))
245 		udelay(1);
246 
247 	rk_clrsetreg(&pll->con3, PLL_MODE_MASK,
248 		     PLL_MODE_NORMAL << PLL_MODE_SHIFT);
249 
250 	return 0;
251 }
252 
253 #if !IS_ENABLED(CONFIG_SPL_BUILD) || CONFIG_IS_ENABLED(MMC_SUPPORT)
254 static ulong rk3368_mmc_get_clk(struct rk3368_cru *cru, uint clk_id)
255 {
256 	u32 div, con, con_id, rate;
257 	u32 pll_rate;
258 
259 	switch (clk_id) {
260 	case HCLK_SDMMC:
261 		con_id = 50;
262 		break;
263 	case HCLK_EMMC:
264 		con_id = 51;
265 		break;
266 	case SCLK_SDIO0:
267 		con_id = 48;
268 		break;
269 	default:
270 		return -EINVAL;
271 	}
272 
273 	con = readl(&cru->clksel_con[con_id]);
274 	switch (con & MMC_PLL_SEL_MASK) {
275 	case MMC_PLL_SEL_GPLL:
276 		pll_rate = rkclk_pll_get_rate(cru, GPLL);
277 		break;
278 	case MMC_PLL_SEL_24M:
279 		pll_rate = OSC_HZ;
280 		break;
281 	case MMC_PLL_SEL_CPLL:
282 		pll_rate = rkclk_pll_get_rate(cru, CPLL);
283 		break;
284 	case MMC_PLL_SEL_USBPHY_480M:
285 	default:
286 		return -EINVAL;
287 	}
288 	div = (con & MMC_CLK_DIV_MASK) >> MMC_CLK_DIV_SHIFT;
289 	rate = DIV_TO_RATE(pll_rate, div);
290 
291 	debug("%s: raw rate %d (post-divide by 2)\n", __func__, rate);
292 	return rate >> 1;
293 }
294 
295 static ulong rk3368_mmc_find_best_rate_and_parent(struct clk *clk,
296 						  ulong rate,
297 						  u32 *best_mux,
298 						  u32 *best_div)
299 {
300 	int i;
301 	ulong best_rate = 0;
302 	const ulong MHz = 1000000;
303 	const struct {
304 		u32 mux;
305 		ulong rate;
306 	} parents[] = {
307 		{ .mux = MMC_PLL_SEL_CPLL, .rate = CPLL_HZ },
308 		{ .mux = MMC_PLL_SEL_GPLL, .rate = GPLL_HZ },
309 		{ .mux = MMC_PLL_SEL_24M,  .rate = 24 * MHz }
310 	};
311 
312 	debug("%s: target rate %ld\n", __func__, rate);
313 	for (i = 0; i < ARRAY_SIZE(parents); ++i) {
314 		/*
315 		 * Find the largest rate no larger than the target-rate for
316 		 * the current parent.
317 		 */
318 		ulong parent_rate = parents[i].rate;
319 		u32 div = DIV_ROUND_UP(parent_rate, rate);
320 		u32 adj_div = div;
321 		ulong new_rate = parent_rate / adj_div;
322 
323 		debug("%s: rate %ld, parent-mux %d, parent-rate %ld, div %d\n",
324 		      __func__, rate, parents[i].mux, parents[i].rate, div);
325 
326 		/* Skip, if not representable */
327 		if ((div - 1) > MMC_CLK_DIV_MASK)
328 			continue;
329 
330 		/* Skip, if we already have a better (or equal) solution */
331 		if (new_rate <= best_rate)
332 			continue;
333 
334 		/* This is our new best rate. */
335 		best_rate = new_rate;
336 		*best_mux = parents[i].mux;
337 		*best_div = div - 1;
338 	}
339 
340 	debug("%s: best_mux = %x, best_div = %d, best_rate = %ld\n",
341 	      __func__, *best_mux, *best_div, best_rate);
342 
343 	return best_rate;
344 }
345 
346 static ulong rk3368_mmc_set_clk(struct clk *clk, ulong rate)
347 {
348 	struct rk3368_clk_priv *priv = dev_get_priv(clk->dev);
349 	struct rk3368_cru *cru = priv->cru;
350 	ulong clk_id = clk->id;
351 	u32 con_id, mux = 0, div = 0;
352 
353 	/* Find the best parent and rate */
354 	rk3368_mmc_find_best_rate_and_parent(clk, rate << 1, &mux, &div);
355 
356 	switch (clk_id) {
357 	case HCLK_SDMMC:
358 		con_id = 50;
359 		break;
360 	case HCLK_EMMC:
361 		con_id = 51;
362 		break;
363 	case SCLK_SDIO0:
364 		con_id = 48;
365 		break;
366 	default:
367 		return -EINVAL;
368 	}
369 
370 	rk_clrsetreg(&cru->clksel_con[con_id],
371 		     MMC_PLL_SEL_MASK | MMC_CLK_DIV_MASK,
372 		     mux | div);
373 
374 	return rk3368_mmc_get_clk(cru, clk_id);
375 }
376 #endif
377 
378 #if IS_ENABLED(CONFIG_TPL_BUILD)
379 static ulong rk3368_ddr_set_clk(struct rk3368_cru *cru, ulong set_rate)
380 {
381 	const struct pll_div *dpll_cfg = NULL;
382 	const ulong MHz = 1000000;
383 
384 	/* Fout = ((Fin /NR) * NF )/ NO */
385 	static const struct pll_div dpll_1200 = PLL_DIVISORS(1200 * MHz, 1, 1);
386 	static const struct pll_div dpll_1332 =	PLL_DIVISORS(1332 * MHz, 2, 1);
387 	static const struct pll_div dpll_1600 =	PLL_DIVISORS(1600 * MHz, 3, 2);
388 
389 	switch (set_rate) {
390 	case 1200*MHz:
391 		dpll_cfg = &dpll_1200;
392 		break;
393 	case 1332*MHz:
394 		dpll_cfg = &dpll_1332;
395 		break;
396 	case 1600*MHz:
397 		dpll_cfg = &dpll_1600;
398 		break;
399 	default:
400 		pr_err("Unsupported SDRAM frequency!,%ld\n", set_rate);
401 	}
402 	rkclk_set_pll(cru, DPLL, dpll_cfg);
403 
404 	return set_rate;
405 }
406 #endif
407 
408 #if CONFIG_IS_ENABLED(GMAC_ROCKCHIP)
409 static ulong rk3368_gmac_set_clk(struct rk3368_cru *cru, ulong set_rate)
410 {
411 	ulong ret;
412 
413 	/*
414 	 * The gmac clock can be derived either from an external clock
415 	 * or can be generated from internally by a divider from SCLK_MAC.
416 	 */
417 	if (readl(&cru->clksel_con[43]) & GMAC_MUX_SEL_EXTCLK) {
418 		/* An external clock will always generate the right rate... */
419 		ret = set_rate;
420 	} else {
421 		u32 con = readl(&cru->clksel_con[43]);
422 		ulong pll_rate;
423 		u8 div;
424 
425 		if (((con >> GMAC_PLL_SHIFT) & GMAC_PLL_MASK) ==
426 		    GMAC_PLL_SELECT_GENERAL)
427 			pll_rate = GPLL_HZ;
428 		else if (((con >> GMAC_PLL_SHIFT) & GMAC_PLL_MASK) ==
429 			 GMAC_PLL_SELECT_CODEC)
430 			pll_rate = CPLL_HZ;
431 		else
432 			/* CPLL is not set */
433 			return -EPERM;
434 
435 		div = DIV_ROUND_UP(pll_rate, set_rate) - 1;
436 		if (div <= 0x1f)
437 			rk_clrsetreg(&cru->clksel_con[43], GMAC_DIV_CON_MASK,
438 				     div << GMAC_DIV_CON_SHIFT);
439 		else
440 			debug("Unsupported div for gmac:%d\n", div);
441 
442 		return DIV_TO_RATE(pll_rate, div);
443 	}
444 
445 	return ret;
446 }
447 #endif
448 
449 /*
450  * RK3368 SPI clocks have a common divider-width (7 bits) and a single bit
451  * to select either CPLL or GPLL as the clock-parent. The location within
452  * the enclosing CLKSEL_CON (i.e. div_shift and sel_shift) are variable.
453  */
454 
455 struct spi_clkreg {
456 	uint8_t reg;  /* CLKSEL_CON[reg] register in CRU */
457 	uint8_t div_shift;
458 	uint8_t sel_shift;
459 };
460 
461 /*
462  * The entries are numbered relative to their offset from SCLK_SPI0.
463  */
464 static const struct spi_clkreg spi_clkregs[] = {
465 	[0] = { .reg = 45, .div_shift = 0, .sel_shift = 7, },
466 	[1] = { .reg = 45, .div_shift = 8, .sel_shift = 15, },
467 	[2] = { .reg = 46, .div_shift = 8, .sel_shift = 15, },
468 };
469 
470 static inline u32 extract_bits(u32 val, unsigned width, unsigned shift)
471 {
472 	return (val >> shift) & ((1 << width) - 1);
473 }
474 
475 static ulong rk3368_spi_get_clk(struct rk3368_cru *cru, ulong clk_id)
476 {
477 	const struct spi_clkreg *spiclk = NULL;
478 	u32 div, val;
479 
480 	switch (clk_id) {
481 	case SCLK_SPI0 ... SCLK_SPI2:
482 		spiclk = &spi_clkregs[clk_id - SCLK_SPI0];
483 		break;
484 
485 	default:
486 		pr_err("%s: SPI clk-id %ld not supported\n", __func__, clk_id);
487 		return -EINVAL;
488 	}
489 
490 	val = readl(&cru->clksel_con[spiclk->reg]);
491 	div = extract_bits(val, 7, spiclk->div_shift);
492 
493 	debug("%s: div 0x%x\n", __func__, div);
494 	return DIV_TO_RATE(GPLL_HZ, div);
495 }
496 
497 static ulong rk3368_spi_set_clk(struct rk3368_cru *cru, ulong clk_id, uint hz)
498 {
499 	const struct spi_clkreg *spiclk = NULL;
500 	int src_clk_div;
501 
502 	src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz);
503 	assert(src_clk_div < 127);
504 
505 	switch (clk_id) {
506 	case SCLK_SPI0 ... SCLK_SPI2:
507 		spiclk = &spi_clkregs[clk_id - SCLK_SPI0];
508 		break;
509 
510 	default:
511 		pr_err("%s: SPI clk-id %ld not supported\n", __func__, clk_id);
512 		return -EINVAL;
513 	}
514 
515 	rk_clrsetreg(&cru->clksel_con[spiclk->reg],
516 		     ((0x7f << spiclk->div_shift) |
517 		      (0x1 << spiclk->sel_shift)),
518 		     ((src_clk_div << spiclk->div_shift) |
519 		      (1 << spiclk->sel_shift)));
520 
521 	return rk3368_spi_get_clk(cru, clk_id);
522 }
523 
524 static ulong rk3368_saradc_get_clk(struct rk3368_cru *cru)
525 {
526 	u32 div, val;
527 
528 	val = readl(&cru->clksel_con[25]);
529 	div = bitfield_extract(val, CLK_SARADC_DIV_CON_SHIFT,
530 			       CLK_SARADC_DIV_CON_WIDTH);
531 
532 	return DIV_TO_RATE(OSC_HZ, div);
533 }
534 
535 static ulong rk3368_saradc_set_clk(struct rk3368_cru *cru, uint hz)
536 {
537 	int src_clk_div;
538 
539 	src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1;
540 	assert(src_clk_div < 128);
541 
542 	rk_clrsetreg(&cru->clksel_con[25],
543 		     CLK_SARADC_DIV_CON_MASK,
544 		     src_clk_div << CLK_SARADC_DIV_CON_SHIFT);
545 
546 	return rk3368_saradc_get_clk(cru);
547 }
548 
549 static ulong rk3368_bus_get_clk(struct rk3368_cru *cru, ulong clk_id)
550 {
551 	u32 div, con, parent;
552 
553 	switch (clk_id) {
554 	case ACLK_BUS:
555 		con = readl(&cru->clksel_con[8]);
556 		div = (con & ACLK_BUS_DIV_CON_MASK) >> ACLK_BUS_DIV_CON_SHIFT;
557 		parent = rkclk_pll_get_rate(cru, GPLL);
558 		break;
559 	case HCLK_BUS:
560 		con = readl(&cru->clksel_con[8]);
561 		div = (con & HCLK_BUS_DIV_CON_MASK) >> HCLK_BUS_DIV_CON_SHIFT;
562 		parent = rk3368_bus_get_clk(cru, ACLK_BUS);
563 		break;
564 	case PCLK_BUS:
565 	case PCLK_PWM0:
566 	case PCLK_PWM1:
567 	case PCLK_I2C0:
568 	case PCLK_I2C1:
569 		con = readl(&cru->clksel_con[8]);
570 		div = (con & PCLK_BUS_DIV_CON_MASK) >> PCLK_BUS_DIV_CON_SHIFT;
571 		parent = rk3368_bus_get_clk(cru, ACLK_BUS);
572 		break;
573 	default:
574 		return -ENOENT;
575 	}
576 
577 	return DIV_TO_RATE(parent, div);
578 }
579 
580 static ulong rk3368_bus_set_clk(struct rk3368_cru *cru,
581 				ulong clk_id, ulong hz)
582 {
583 	int src_clk_div;
584 
585 	/*
586 	 * select gpll as pd_bus bus clock source and
587 	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
588 	 */
589 	switch (clk_id) {
590 	case ACLK_BUS:
591 		src_clk_div = DIV_ROUND_UP(rkclk_pll_get_rate(cru, GPLL), hz);
592 		assert(src_clk_div - 1 < 31);
593 		rk_clrsetreg(&cru->clksel_con[8],
594 			     CLK_BUS_PLL_SEL_MASK | ACLK_BUS_DIV_CON_MASK,
595 			     CLK_BUS_PLL_SEL_GPLL << CLK_BUS_PLL_SEL_SHIFT |
596 			     (src_clk_div - 1) << ACLK_BUS_DIV_CON_SHIFT);
597 		break;
598 	case HCLK_BUS:
599 		src_clk_div = DIV_ROUND_UP(rk3368_bus_get_clk(cru,
600 							      ACLK_BUS),
601 					   hz);
602 		assert(src_clk_div - 1 < 3);
603 		rk_clrsetreg(&cru->clksel_con[8],
604 			     HCLK_BUS_DIV_CON_MASK,
605 			     (src_clk_div - 1) << HCLK_BUS_DIV_CON_SHIFT);
606 		break;
607 	case PCLK_BUS:
608 		src_clk_div = DIV_ROUND_UP(rk3368_bus_get_clk(cru,
609 							      ACLK_BUS),
610 					   hz);
611 		assert(src_clk_div - 1 < 3);
612 		rk_clrsetreg(&cru->clksel_con[8],
613 			     PCLK_BUS_DIV_CON_MASK,
614 			     (src_clk_div - 1) << PCLK_BUS_DIV_CON_SHIFT);
615 		break;
616 	default:
617 		printf("do not support this bus freq\n");
618 		return -EINVAL;
619 	}
620 	return rk3368_bus_get_clk(cru, clk_id);
621 }
622 
623 static ulong rk3368_peri_get_clk(struct rk3368_cru *cru, ulong clk_id)
624 {
625 	u32 div, con, parent;
626 
627 	switch (clk_id) {
628 	case ACLK_PERI:
629 		con = readl(&cru->clksel_con[9]);
630 		div = (con & ACLK_PERI_DIV_CON_MASK) >> ACLK_PERI_DIV_CON_SHIFT;
631 		parent = rkclk_pll_get_rate(cru, GPLL);
632 		break;
633 	case HCLK_PERI:
634 		con = readl(&cru->clksel_con[9]);
635 		div = (con & HCLK_PERI_DIV_CON_MASK) >> HCLK_PERI_DIV_CON_SHIFT;
636 		parent = rk3368_peri_get_clk(cru, ACLK_PERI);
637 		break;
638 	case PCLK_PERI:
639 	case PCLK_I2C2:
640 	case PCLK_I2C3:
641 	case PCLK_I2C4:
642 	case PCLK_I2C5:
643 		con = readl(&cru->clksel_con[9]);
644 		div = (con & PCLK_PERI_DIV_CON_MASK) >> PCLK_PERI_DIV_CON_SHIFT;
645 		parent = rk3368_peri_get_clk(cru, ACLK_PERI);
646 		break;
647 	default:
648 		return -ENOENT;
649 	}
650 
651 	return DIV_TO_RATE(parent, div);
652 }
653 
654 static ulong rk3368_peri_set_clk(struct rk3368_cru *cru,
655 				 ulong clk_id, ulong hz)
656 {
657 	int src_clk_div;
658 
659 	/*
660 	 * select gpll as pd_bus bus clock source and
661 	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
662 	 */
663 	switch (clk_id) {
664 	case ACLK_PERI:
665 		src_clk_div = DIV_ROUND_UP(rkclk_pll_get_rate(cru, GPLL), hz);
666 		assert(src_clk_div - 1 < 31);
667 		rk_clrsetreg(&cru->clksel_con[9],
668 			     CLK_PERI_PLL_SEL_MASK | ACLK_PERI_DIV_CON_MASK,
669 			     CLK_PERI_PLL_SEL_GPLL << CLK_PERI_PLL_SEL_SHIFT |
670 			     (src_clk_div - 1) << ACLK_PERI_DIV_CON_SHIFT);
671 		break;
672 	case HCLK_PERI:
673 		src_clk_div = DIV_ROUND_UP(rk3368_peri_get_clk(cru,
674 							       ACLK_PERI),
675 					   hz);
676 		assert(src_clk_div - 1 < 3);
677 		rk_clrsetreg(&cru->clksel_con[9],
678 			     HCLK_PERI_DIV_CON_MASK,
679 			     (src_clk_div - 1) << HCLK_PERI_DIV_CON_SHIFT);
680 		break;
681 	case PCLK_PERI:
682 		src_clk_div = DIV_ROUND_UP(rk3368_peri_get_clk(cru,
683 							       ACLK_PERI),
684 					   hz);
685 		assert(src_clk_div - 1 < 3);
686 		rk_clrsetreg(&cru->clksel_con[9],
687 			     PCLK_PERI_DIV_CON_MASK,
688 			     (src_clk_div - 1) << PCLK_PERI_DIV_CON_SHIFT);
689 		break;
690 	default:
691 		printf("do not support this bus freq\n");
692 		return -EINVAL;
693 	}
694 
695 	return rk3368_peri_get_clk(cru, clk_id);
696 }
697 
698 #if !defined(CONFIG_SPL_BUILD)
699 static ulong rk3368_vop_get_clk(struct rk3368_cru *cru,  int clk_id)
700 {
701 	u32 div, con, parent, sel;
702 
703 	switch (clk_id) {
704 	case DCLK_VOP:
705 		con = readl(&cru->clksel_con[20]);
706 		div = con & DCLK_VOP_DIV_MASK;
707 		parent = rkclk_pll_get_rate(cru, NPLL);
708 		break;
709 	case ACLK_VOP:
710 		con = readl(&cru->clksel_con[19]);
711 		div = con & ACLK_VOP_DIV_MASK;
712 		sel =  (con & (ACLK_VOP_PLL_SEL_MASK <<
713 			ACLK_VOP_PLL_SEL_SHIFT)) >>
714 			ACLK_VOP_PLL_SEL_SHIFT;
715 		if (sel == ACLK_VOP_PLL_SEL_CPLL)
716 			parent = rkclk_pll_get_rate(cru, CPLL);
717 		else if (ACLK_VOP_PLL_SEL_GPLL)
718 			parent = rkclk_pll_get_rate(cru, GPLL);
719 		else
720 			parent = 480000000;
721 		break;
722 	default:
723 		return -EINVAL;
724 	}
725 
726 	return DIV_TO_RATE(parent, div);
727 }
728 
729 static ulong rk3368_vop_set_clk(struct rk3368_cru *cru, int clk_id, uint hz)
730 {
731 	struct pll_div npll_config = {0};
732 	u32 lcdc_div;
733 	int ret;
734 
735 	switch (clk_id) {
736 	case DCLK_VOP:
737 		if (!(NPLL_HZ % hz)) {
738 			rkclk_set_pll(cru, NPLL, &npll_init_cfg);
739 			lcdc_div = NPLL_HZ / hz;
740 		} else {
741 			ret = pll_para_config(hz, &npll_config, &lcdc_div);
742 			if (ret)
743 				return ret;
744 
745 			rkclk_set_pll(cru, NPLL, &npll_config);
746 		}
747 		/* vop dclk source clk: npll,dclk_div: 1 */
748 		rk_clrsetreg(&cru->clksel_con[20],
749 			     (DCLK_VOP_PLL_SEL_MASK << DCLK_VOP_PLL_SEL_SHIFT) |
750 			     (DCLK_VOP_DIV_MASK << DCLK_VOP_DIV_SHIFT),
751 			     (DCLK_VOP_PLL_SEL_NPLL << DCLK_VOP_PLL_SEL_SHIFT) |
752 			     (lcdc_div - 1) << DCLK_VOP_DIV_SHIFT);
753 		break;
754 	case ACLK_VOP:
755 		if ((rkclk_pll_get_rate(cru, CPLL) % hz) == 0) {
756 			lcdc_div = rkclk_pll_get_rate(cru, CPLL) / hz;
757 			rk_clrsetreg(&cru->clksel_con[19],
758 				     (ACLK_VOP_PLL_SEL_MASK <<
759 				     ACLK_VOP_PLL_SEL_SHIFT) |
760 				     (ACLK_VOP_DIV_MASK <<
761 				     ACLK_VOP_DIV_SHIFT),
762 				     (ACLK_VOP_PLL_SEL_CPLL <<
763 				     ACLK_VOP_PLL_SEL_SHIFT) |
764 				     (lcdc_div - 1) <<
765 				     ACLK_VOP_DIV_SHIFT);
766 		} else {
767 			lcdc_div = rkclk_pll_get_rate(cru, GPLL) / hz;
768 			rk_clrsetreg(&cru->clksel_con[19],
769 				     (ACLK_VOP_PLL_SEL_MASK <<
770 				     ACLK_VOP_PLL_SEL_SHIFT) |
771 				     (ACLK_VOP_DIV_MASK <<
772 				     ACLK_VOP_DIV_SHIFT),
773 				     (ACLK_VOP_PLL_SEL_GPLL <<
774 				     ACLK_VOP_PLL_SEL_SHIFT) |
775 				     (lcdc_div - 1) <<
776 				     ACLK_VOP_DIV_SHIFT);
777 		}
778 		break;
779 	default:
780 		return -EINVAL;
781 	}
782 
783 	return 0;
784 }
785 
786 static ulong rk3368_alive_get_clk(struct rk3368_clk_priv *priv)
787 {
788 	struct rk3368_cru *cru = priv->cru;
789 	u32 div, con, parent;
790 
791 	con = readl(&cru->clksel_con[10]);
792 	div = (con & PCLK_ALIVE_DIV_CON_MASK) >>
793 	      PCLK_ALIVE_DIV_CON_SHIFT;
794 	parent = GPLL_HZ;
795 	return DIV_TO_RATE(parent, div);
796 }
797 
798 static ulong rk3368_crypto_get_rate(struct rk3368_clk_priv *priv)
799 {
800 	struct rk3368_cru *cru = priv->cru;
801 	u32 div, val;
802 
803 	val = readl(&cru->clksel_con[10]);
804 	div = (val & CLK_CRYPTO_DIV_CON_MASK) >> CLK_CRYPTO_DIV_CON_SHIFT;
805 
806 	return DIV_TO_RATE(rk3368_bus_get_clk(priv->cru, ACLK_BUS), div);
807 }
808 
809 static ulong rk3368_crypto_set_rate(struct rk3368_clk_priv *priv,
810 				    uint hz)
811 {
812 	struct rk3368_cru *cru = priv->cru;
813 	int src_clk_div;
814 	uint p_rate;
815 
816 	p_rate = rk3368_bus_get_clk(priv->cru, ACLK_BUS);
817 	src_clk_div = DIV_ROUND_UP(p_rate, hz) - 1;
818 	assert(src_clk_div < 3);
819 
820 	rk_clrsetreg(&cru->clksel_con[10],
821 		     CLK_CRYPTO_DIV_CON_MASK,
822 		     src_clk_div << CLK_CRYPTO_DIV_CON_SHIFT);
823 
824 	return rk3368_crypto_get_rate(priv);
825 }
826 #endif
827 
828 static ulong rk3368_armclk_set_clk(struct rk3368_clk_priv *priv,
829 				   int clk_id, ulong hz)
830 {
831 	struct rk3368_cru *cru = priv->cru;
832 	const struct rockchip_cpu_rate_table *rate;
833 	struct pll_div pll_config = {0};
834 	ulong old_rate;
835 	u32 pll_div, pll_id, con_id;
836 	int ret;
837 
838 	rate = rockchip_get_cpu_settings(rk3368_cpu_rates, hz);
839 	if (!rate) {
840 		printf("%s unsupported rate\n", __func__);
841 		return -EINVAL;
842 	}
843 
844 	/*
845 	 * select apll as cpu/core clock pll source and
846 	 * set up dependent divisors for PERI and ACLK clocks.
847 	 * core hz : apll = 1:1
848 	 */
849 
850 	ret = pll_para_config(hz, &pll_config, &pll_div);
851 	if (ret)
852 		return ret;
853 
854 	if (clk_id == ARMCLKB) {
855 		old_rate = rkclk_pll_get_rate(priv->cru, APLLB);
856 		pll_id = APLLB;
857 		con_id = 0;
858 	} else {
859 		old_rate = rkclk_pll_get_rate(priv->cru, APLLL);
860 		pll_id = APLLL;
861 		con_id = 2;
862 	}
863 
864 	if (old_rate > hz) {
865 		ret = rkclk_set_pll(priv->cru, pll_id, &pll_config);
866 		rk_clrsetreg(&cru->clksel_con[con_id],
867 			     CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK,
868 			     CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
869 			     0 << CORE_DIV_CON_SHIFT);
870 		rk_clrsetreg(&cru->clksel_con[con_id + 1],
871 			     CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
872 			     rate->aclk_div << CORE_ACLK_DIV_SHIFT |
873 			     rate->pclk_div << CORE_DBG_DIV_SHIFT);
874 	} else if (old_rate < hz) {
875 		rk_clrsetreg(&cru->clksel_con[con_id],
876 			     CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK,
877 			     CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
878 			     0 << CORE_DIV_CON_SHIFT);
879 		rk_clrsetreg(&cru->clksel_con[con_id + 1],
880 			     CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
881 			     rate->aclk_div << CORE_ACLK_DIV_SHIFT |
882 			     rate->pclk_div << CORE_DBG_DIV_SHIFT);
883 		ret = rkclk_set_pll(priv->cru, pll_id, &pll_config);
884 	}
885 
886 	return rkclk_pll_get_rate(priv->cru, pll_id);
887 }
888 
889 static ulong rk3368_clk_get_rate(struct clk *clk)
890 {
891 	struct rk3368_clk_priv *priv = dev_get_priv(clk->dev);
892 	ulong rate = 0;
893 
894 	debug("%s: id %ld\n", __func__, clk->id);
895 	switch (clk->id) {
896 	case PLL_APLLB:
897 	case PLL_APLLL:
898 	case PLL_DPLL:
899 	case PLL_CPLL:
900 	case PLL_GPLL:
901 	case PLL_NPLL:
902 		rate = rkclk_pll_get_rate(priv->cru, clk->id - 1);
903 		break;
904 	case ARMCLKB:
905 		rate = rkclk_pll_get_rate(priv->cru, APLLB);
906 		break;
907 	case ARMCLKL:
908 		rate = rkclk_pll_get_rate(priv->cru, APLLL);
909 		break;
910 	case SCLK_SPI0 ... SCLK_SPI2:
911 		rate = rk3368_spi_get_clk(priv->cru, clk->id);
912 		break;
913 	case ACLK_BUS:
914 	case HCLK_BUS:
915 	case PCLK_BUS:
916 	case PCLK_PWM0:
917 	case PCLK_PWM1:
918 	case PCLK_I2C0:
919 	case PCLK_I2C1:
920 		rate = rk3368_bus_get_clk(priv->cru, clk->id);
921 		break;
922 	case ACLK_PERI:
923 	case HCLK_PERI:
924 	case PCLK_PERI:
925 	case PCLK_I2C2:
926 	case PCLK_I2C3:
927 	case PCLK_I2C4:
928 	case PCLK_I2C5:
929 		rate = rk3368_peri_get_clk(priv->cru, clk->id);
930 		break;
931 #if !IS_ENABLED(CONFIG_SPL_BUILD) || CONFIG_IS_ENABLED(MMC_SUPPORT)
932 	case HCLK_SDMMC:
933 	case HCLK_EMMC:
934 		rate = rk3368_mmc_get_clk(priv->cru, clk->id);
935 		break;
936 #endif
937 	case SCLK_SARADC:
938 		rate = rk3368_saradc_get_clk(priv->cru);
939 		break;
940 #if !defined(CONFIG_SPL_BUILD)
941 	case ACLK_VOP:
942 	case DCLK_VOP:
943 		rate =  rk3368_vop_get_clk(priv->cru, clk->id);
944 		break;
945 	case PCLK_WDT:
946 		rate = rk3368_alive_get_clk(priv);
947 		break;
948 	case SCLK_CRYPTO:
949 		rate = rk3368_crypto_get_rate(priv);
950 		break;
951 #endif
952 	default:
953 		return -ENOENT;
954 	}
955 	return rate;
956 }
957 
958 static ulong rk3368_clk_set_rate(struct clk *clk, ulong rate)
959 {
960 	__maybe_unused struct rk3368_clk_priv *priv = dev_get_priv(clk->dev);
961 	struct pll_div pll_config = {0};
962 	u32 pll_div;
963 	ulong ret = 0;
964 
965 	switch (clk->id) {
966 	case PLL_APLLB:
967 	case PLL_APLLL:
968 	case PLL_CPLL:
969 	case PLL_GPLL:
970 	case PLL_NPLL:
971 		ret = pll_para_config(rate, &pll_config, &pll_div);
972 		if (ret)
973 			return ret;
974 
975 		ret = rkclk_set_pll(priv->cru, clk->id - 1, &pll_config);
976 		break;
977 	case ARMCLKB:
978 		if (priv->armbclk_hz)
979 			ret = rk3368_armclk_set_clk(priv, clk->id, rate);
980 		priv->armbclk_hz = rate;
981 		break;
982 	case ARMCLKL:
983 		if (priv->armlclk_hz)
984 			ret = rk3368_armclk_set_clk(priv, clk->id, rate);
985 		priv->armlclk_hz = rate;
986 		break;
987 	case SCLK_SPI0 ... SCLK_SPI2:
988 		ret = rk3368_spi_set_clk(priv->cru, clk->id, rate);
989 		break;
990 #if IS_ENABLED(CONFIG_TPL_BUILD)
991 	case SCLK_DDRCLK:
992 		ret = rk3368_ddr_set_clk(priv->cru, rate);
993 		break;
994 #endif
995 	case ACLK_BUS:
996 	case HCLK_BUS:
997 	case PCLK_BUS:
998 		rate = rk3368_bus_set_clk(priv->cru, clk->id, rate);
999 		break;
1000 	case ACLK_PERI:
1001 	case HCLK_PERI:
1002 	case PCLK_PERI:
1003 		rate = rk3368_peri_set_clk(priv->cru, clk->id, rate);
1004 		break;
1005 #if !IS_ENABLED(CONFIG_SPL_BUILD) || CONFIG_IS_ENABLED(MMC_SUPPORT)
1006 	case HCLK_SDMMC:
1007 	case HCLK_EMMC:
1008 		ret = rk3368_mmc_set_clk(clk, rate);
1009 		break;
1010 #endif
1011 #if CONFIG_IS_ENABLED(GMAC_ROCKCHIP)
1012 	case SCLK_MAC:
1013 		/* select the external clock */
1014 		ret = rk3368_gmac_set_clk(priv->cru, rate);
1015 		break;
1016 #endif
1017 	case SCLK_SARADC:
1018 		ret =  rk3368_saradc_set_clk(priv->cru, rate);
1019 		break;
1020 #if !defined(CONFIG_SPL_BUILD)
1021 	case ACLK_VOP:
1022 	case DCLK_VOP:
1023 		ret =  rk3368_vop_set_clk(priv->cru, clk->id, rate);
1024 		break;
1025 	case ACLK_CCI_PRE:
1026 		ret =  0;
1027 		break;
1028 	case SCLK_CRYPTO:
1029 		ret = rk3368_crypto_set_rate(priv, rate);
1030 		break;
1031 #endif
1032 	default:
1033 		return -ENOENT;
1034 	}
1035 
1036 	return ret;
1037 }
1038 
1039 static int __maybe_unused rk3368_gmac_set_parent(struct clk *clk, struct clk *parent)
1040 {
1041 	struct rk3368_clk_priv *priv = dev_get_priv(clk->dev);
1042 	struct rk3368_cru *cru = priv->cru;
1043 	const char *clock_output_name;
1044 	int ret;
1045 
1046 	/*
1047 	 * If the requested parent is in the same clock-controller and
1048 	 * the id is SCLK_MAC ("sclk_mac"), switch to the internal
1049 	 * clock.
1050 	 */
1051 	if ((parent->dev == clk->dev) && (parent->id == SCLK_MAC)) {
1052 		debug("%s: switching GAMC to SCLK_MAC\n", __func__);
1053 		rk_clrreg(&cru->clksel_con[43], GMAC_MUX_SEL_EXTCLK);
1054 		return 0;
1055 	}
1056 
1057 	/*
1058 	 * Otherwise, we need to check the clock-output-names of the
1059 	 * requested parent to see if the requested id is "ext_gmac".
1060 	 */
1061 	ret = dev_read_string_index(parent->dev, "clock-output-names",
1062 				    parent->id, &clock_output_name);
1063 	if (ret < 0)
1064 		return -ENODATA;
1065 
1066 	/* If this is "ext_gmac", switch to the external clock input */
1067 	if (!strcmp(clock_output_name, "ext_gmac")) {
1068 		debug("%s: switching GMAC to external clock\n", __func__);
1069 		rk_setreg(&cru->clksel_con[43], GMAC_MUX_SEL_EXTCLK);
1070 		return 0;
1071 	}
1072 
1073 	return -EINVAL;
1074 }
1075 
1076 static int __maybe_unused rk3368_clk_set_parent(struct clk *clk, struct clk *parent)
1077 {
1078 	switch (clk->id) {
1079 	case SCLK_MAC:
1080 		return rk3368_gmac_set_parent(clk, parent);
1081 	}
1082 
1083 	debug("%s: unsupported clk %ld\n", __func__, clk->id);
1084 	return -ENOENT;
1085 }
1086 
1087 #define ROCKCHIP_MMC_DELAY_SEL		BIT(10)
1088 #define ROCKCHIP_MMC_DEGREE_MASK	0x3
1089 #define ROCKCHIP_MMC_DELAYNUM_OFFSET	2
1090 #define ROCKCHIP_MMC_DELAYNUM_MASK	(0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
1091 
1092 #define PSECS_PER_SEC 1000000000000LL
1093 /*
1094  * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
1095  * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
1096  */
1097 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
1098 
1099 int rk3368_mmc_get_phase(struct clk *clk)
1100 {
1101 	struct rk3368_clk_priv *priv = dev_get_priv(clk->dev);
1102 	struct rk3368_cru *cru = priv->cru;
1103 	u32 raw_value, delay_num;
1104 	u16 degrees = 0;
1105 	ulong rate;
1106 
1107 	rate = rk3368_clk_get_rate(clk);
1108 
1109 	if (rate < 0)
1110 		return rate;
1111 
1112 	if (clk->id == SCLK_EMMC_SAMPLE)
1113 		raw_value = readl(&cru->emmc_con[1]);
1114 	else if (clk->id == SCLK_SDMMC_SAMPLE)
1115 		raw_value = readl(&cru->sdmmc_con[1]);
1116 	else
1117 		raw_value = readl(&cru->sdio0_con[1]);
1118 
1119 	raw_value >>= 1;
1120 	degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
1121 
1122 	if (raw_value & ROCKCHIP_MMC_DELAY_SEL) {
1123 		/* degrees/delaynum * 10000 */
1124 		unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) *
1125 					36 * (rate / 1000000);
1126 
1127 		delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
1128 		delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET;
1129 		degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000);
1130 	}
1131 
1132 	return degrees % 360;
1133 }
1134 
1135 int rk3368_mmc_set_phase(struct clk *clk, u32 degrees)
1136 {
1137 	struct rk3368_clk_priv *priv = dev_get_priv(clk->dev);
1138 	struct rk3368_cru *cru = priv->cru;
1139 	u8 nineties, remainder, delay_num;
1140 	u32 raw_value, delay;
1141 	ulong rate;
1142 
1143 	rate = rk3368_clk_get_rate(clk);
1144 
1145 	if (rate < 0)
1146 		return rate;
1147 
1148 	nineties = degrees / 90;
1149 	remainder = (degrees % 90);
1150 
1151 	/*
1152 	 * Convert to delay; do a little extra work to make sure we
1153 	 * don't overflow 32-bit / 64-bit numbers.
1154 	 */
1155 	delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */
1156 	delay *= remainder;
1157 	delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 *
1158 				(ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10));
1159 
1160 	delay_num = (u8)min_t(u32, delay, 255);
1161 
1162 	raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
1163 	raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
1164 	raw_value |= nineties;
1165 
1166 	raw_value <<= 1;
1167 	if (clk->id == SCLK_EMMC_SAMPLE)
1168 		writel(raw_value | 0xffff0000, &cru->emmc_con[1]);
1169 	else if (clk->id == SCLK_SDMMC_SAMPLE)
1170 		writel(raw_value | 0xffff0000, &cru->sdmmc_con[1]);
1171 	else
1172 		writel(raw_value | 0xffff0000, &cru->sdio0_con[1]);
1173 
1174 	debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n",
1175 	      degrees, delay_num, raw_value, rk3368_mmc_get_phase(clk));
1176 
1177 	return 0;
1178 }
1179 
1180 static int rk3368_clk_get_phase(struct clk *clk)
1181 {
1182 	int ret;
1183 
1184 	debug("%s %ld\n", __func__, clk->id);
1185 	switch (clk->id) {
1186 	case SCLK_EMMC_SAMPLE:
1187 	case SCLK_SDMMC_SAMPLE:
1188 	case SCLK_SDIO0_SAMPLE:
1189 		ret = rk3368_mmc_get_phase(clk);
1190 		break;
1191 	default:
1192 		return -ENOENT;
1193 	}
1194 
1195 	return ret;
1196 }
1197 
1198 static int rk3368_clk_set_phase(struct clk *clk, int degrees)
1199 {
1200 	int ret;
1201 
1202 	debug("%s %ld\n", __func__, clk->id);
1203 	switch (clk->id) {
1204 	case SCLK_EMMC_SAMPLE:
1205 	case SCLK_SDMMC_SAMPLE:
1206 	case SCLK_SDIO0_SAMPLE:
1207 		ret = rk3368_mmc_set_phase(clk, degrees);
1208 		break;
1209 	default:
1210 		return -ENOENT;
1211 	}
1212 
1213 	return ret;
1214 }
1215 
1216 static struct clk_ops rk3368_clk_ops = {
1217 	.get_rate = rk3368_clk_get_rate,
1218 	.set_rate = rk3368_clk_set_rate,
1219 	.get_phase = rk3368_clk_get_phase,
1220 	.set_phase = rk3368_clk_set_phase,
1221 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
1222 	.set_parent = rk3368_clk_set_parent,
1223 #endif
1224 };
1225 
1226 #if IS_ENABLED(CONFIG_SPL_BUILD) || IS_ENABLED(CONFIG_TPL_BUILD)
1227 static void rkclk_init(struct rk3368_cru *cru)
1228 {
1229 	u32 apllb, aplll, dpll, cpll, gpll;
1230 
1231 	rkclk_set_pll(cru, APLLB, &apll_b_init_cfg);
1232 	rkclk_set_pll(cru, APLLL, &apll_l_init_cfg);
1233 #if !defined(CONFIG_TPL_BUILD)
1234 	/*
1235 	 * If we plan to return to the boot ROM, we can't increase the
1236 	 * GPLL rate from the SPL stage.
1237 	 */
1238 	rkclk_set_pll(cru, GPLL, &gpll_init_cfg);
1239 	rkclk_set_pll(cru, CPLL, &cpll_init_cfg);
1240 #endif
1241 rk_clrsetreg(&cru->clksel_con[37],  (1 << 8), 1 << 8);
1242 	apllb = rkclk_pll_get_rate(cru, APLLB);
1243 	aplll = rkclk_pll_get_rate(cru, APLLL);
1244 	dpll = rkclk_pll_get_rate(cru, DPLL);
1245 	cpll = rkclk_pll_get_rate(cru, CPLL);
1246 	gpll = rkclk_pll_get_rate(cru, GPLL);
1247 
1248 	debug("%s apllb(%d) apll(%d) dpll(%d) cpll(%d) gpll(%d)\n",
1249 	      __func__, apllb, aplll, dpll, cpll, gpll);
1250 }
1251 #endif
1252 
1253 static int rk3368_clk_probe(struct udevice *dev)
1254 {
1255 	struct rk3368_clk_priv __maybe_unused *priv = dev_get_priv(dev);
1256 	int ret;
1257 #if CONFIG_IS_ENABLED(OF_PLATDATA)
1258 	struct rk3368_clk_plat *plat = dev_get_platdata(dev);
1259 
1260 	priv->cru = map_sysmem(plat->dtd.reg[0], plat->dtd.reg[1]);
1261 #endif
1262 	priv->sync_kernel = false;
1263 	if (!priv->armlclk_enter_hz)
1264 		priv->armlclk_enter_hz = rkclk_pll_get_rate(priv->cru, APLLL);
1265 	if (!priv->armbclk_enter_hz)
1266 		priv->armbclk_enter_hz = rkclk_pll_get_rate(priv->cru, APLLB);
1267 #if IS_ENABLED(CONFIG_SPL_BUILD) || IS_ENABLED(CONFIG_TPL_BUILD)
1268 	rkclk_init(priv->cru);
1269 #endif
1270 	rkclk_set_pll(priv->cru, NPLL, &npll_init_cfg);
1271 	if (!priv->armlclk_init_hz)
1272 		priv->armlclk_init_hz = rkclk_pll_get_rate(priv->cru, APLLL);
1273 	if (!priv->armbclk_init_hz)
1274 		priv->armbclk_init_hz = rkclk_pll_get_rate(priv->cru, APLLB);
1275 	/* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
1276 	ret = clk_set_defaults(dev);
1277 	if (ret)
1278 		debug("%s clk_set_defaults failed %d\n", __func__, ret);
1279 	else
1280 		priv->sync_kernel = true;
1281 	return 0;
1282 }
1283 
1284 static int rk3368_clk_ofdata_to_platdata(struct udevice *dev)
1285 {
1286 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
1287 	struct rk3368_clk_priv *priv = dev_get_priv(dev);
1288 
1289 	priv->cru = dev_read_addr_ptr(dev);
1290 #endif
1291 
1292 	return 0;
1293 }
1294 
1295 static int rk3368_clk_bind(struct udevice *dev)
1296 {
1297 	int ret;
1298 	struct udevice *sys_child, *sf_child;
1299 	struct sysreset_reg *priv;
1300 	struct softreset_reg *sf_priv;
1301 
1302 	/* The reset driver does not have a device node, so bind it here */
1303 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
1304 				 &sys_child);
1305 	if (ret) {
1306 		debug("Warning: No sysreset driver: ret=%d\n", ret);
1307 	} else {
1308 		priv = malloc(sizeof(struct sysreset_reg));
1309 		priv->glb_srst_fst_value = offsetof(struct rk3368_cru,
1310 						    glb_srst_fst_val);
1311 		priv->glb_srst_snd_value = offsetof(struct rk3368_cru,
1312 						    glb_srst_snd_val);
1313 		sys_child->priv = priv;
1314 	}
1315 
1316 	ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
1317 					 dev_ofnode(dev), &sf_child);
1318 	if (ret) {
1319 		debug("Warning: No rockchip reset driver: ret=%d\n", ret);
1320 	} else {
1321 		sf_priv = malloc(sizeof(struct softreset_reg));
1322 		sf_priv->sf_reset_offset = offsetof(struct rk3368_cru,
1323 						    softrst_con[0]);
1324 		sf_priv->sf_reset_num = 15;
1325 		sf_child->priv = sf_priv;
1326 	}
1327 
1328 	return 0;
1329 }
1330 
1331 static const struct udevice_id rk3368_clk_ids[] = {
1332 	{ .compatible = "rockchip,rk3368-cru" },
1333 	{ }
1334 };
1335 
1336 U_BOOT_DRIVER(rockchip_rk3368_cru) = {
1337 	.name		= "rockchip_rk3368_cru",
1338 	.id		= UCLASS_CLK,
1339 	.of_match	= rk3368_clk_ids,
1340 	.priv_auto_alloc_size = sizeof(struct rk3368_clk_priv),
1341 #if CONFIG_IS_ENABLED(OF_PLATDATA)
1342 	.platdata_auto_alloc_size = sizeof(struct rk3368_clk_plat),
1343 #endif
1344 	.ofdata_to_platdata = rk3368_clk_ofdata_to_platdata,
1345 	.ops		= &rk3368_clk_ops,
1346 	.bind		= rk3368_clk_bind,
1347 	.probe		= rk3368_clk_probe,
1348 };
1349 
1350 #if !defined(CONFIG_SPL_BUILD)
1351 /**
1352  * soc_clk_dump() - Print clock frequencies
1353  * Returns zero on success
1354  *
1355  * Implementation for the clk dump command.
1356  */
1357 int soc_clk_dump(void)
1358 {
1359 	struct udevice *cru_dev;
1360 	struct rk3368_clk_priv *priv;
1361 	const struct rk3368_clk_info *clk_dump;
1362 	struct clk clk;
1363 	unsigned long clk_count = ARRAY_SIZE(clks_dump);
1364 	unsigned long rate;
1365 	int i, ret;
1366 
1367 	ret = uclass_get_device_by_driver(UCLASS_CLK,
1368 					  DM_GET_DRIVER(rockchip_rk3368_cru),
1369 					  &cru_dev);
1370 	if (ret) {
1371 		printf("%s failed to get cru device\n", __func__);
1372 		return ret;
1373 	}
1374 
1375 	priv = dev_get_priv(cru_dev);
1376 	printf("CLK: (%s. arml: enter %lu KHz, init %lu KHz, kernel %lu%s)\n",
1377 	       priv->sync_kernel ? "sync kernel" : "uboot",
1378 	       priv->armlclk_enter_hz / 1000,
1379 	       priv->armlclk_init_hz / 1000,
1380 	       priv->set_armclk_rate ? priv->armlclk_hz / 1000 : 0,
1381 	       priv->set_armclk_rate ? " KHz" : "N/A");
1382 	printf("CLK: (%s. armb: enter %lu KHz, init %lu KHz, kernel %lu%s)\n",
1383 	       priv->sync_kernel ? "sync kernel" : "uboot",
1384 	       priv->armbclk_enter_hz / 1000,
1385 	       priv->armbclk_init_hz / 1000,
1386 	       priv->set_armclk_rate ? priv->armlclk_hz / 1000 : 0,
1387 	       priv->set_armclk_rate ? " KHz" : "N/A");
1388 	for (i = 0; i < clk_count; i++) {
1389 		clk_dump = &clks_dump[i];
1390 		if (clk_dump->name) {
1391 			clk.id = clk_dump->id;
1392 			if (clk_dump->is_cru)
1393 				ret = clk_request(cru_dev, &clk);
1394 			if (ret < 0)
1395 				return ret;
1396 
1397 			rate = clk_get_rate(&clk);
1398 			clk_free(&clk);
1399 			if (i == 0) {
1400 				if (rate < 0)
1401 					printf("  %s %s\n", clk_dump->name,
1402 					       "unknown");
1403 				else
1404 					printf("  %s %lu KHz\n", clk_dump->name,
1405 					       rate / 1000);
1406 			} else {
1407 				if (rate < 0)
1408 					printf("  %s %s\n", clk_dump->name,
1409 					       "unknown");
1410 				else
1411 					printf("  %s %lu KHz\n", clk_dump->name,
1412 					       rate / 1000);
1413 			}
1414 		}
1415 	}
1416 
1417 	return 0;
1418 }
1419 #endif
1420