xref: /rk3399_rockchip-uboot/drivers/clk/rockchip/clk_rk3188.c (revision 5ce558eee1d84a2b85f2bbc4c4547c8ea1c1dae4)
1 /*
2  * (C) Copyright 2015 Google, Inc
3  * (C) Copyright 2016 Heiko Stuebner <heiko@sntech.de>
4  *
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 <asm/io.h>
16 #include <asm/arch/clock.h>
17 #include <asm/arch/cru_rk3188.h>
18 #include <asm/arch/grf_rk3188.h>
19 #include <asm/arch/hardware.h>
20 #include <bitfield.h>
21 #include <dt-bindings/clock/rk3188-cru.h>
22 #include <dm/device-internal.h>
23 #include <dm/lists.h>
24 #include <dm/uclass-internal.h>
25 #include <linux/log2.h>
26 
27 DECLARE_GLOBAL_DATA_PTR;
28 
29 enum rk3188_clk_type {
30 	RK3188_CRU,
31 	RK3188A_CRU,
32 };
33 
34 struct rk3188_clk_plat {
35 #if CONFIG_IS_ENABLED(OF_PLATDATA)
36 	struct dtd_rockchip_rk3188_cru dtd;
37 #endif
38 };
39 
40 struct pll_div {
41 	u32 nr;
42 	u32 nf;
43 	u32 no;
44 };
45 
46 enum {
47 	VCO_MAX_HZ	= 2200U * 1000000,
48 	VCO_MIN_HZ	= 440 * 1000000,
49 	OUTPUT_MAX_HZ	= 2200U * 1000000,
50 	OUTPUT_MIN_HZ	= 30 * 1000000,
51 	FREF_MAX_HZ	= 2200U * 1000000,
52 	FREF_MIN_HZ	= 30 * 1000,
53 };
54 
55 enum {
56 	/* PLL CON0 */
57 	PLL_OD_MASK		= 0x0f,
58 
59 	/* PLL CON1 */
60 	PLL_NF_MASK		= 0x1fff,
61 
62 	/* PLL CON2 */
63 	PLL_BWADJ_MASK		= 0x0fff,
64 
65 	/* PLL CON3 */
66 	PLL_RESET_SHIFT		= 5,
67 
68 	/* GRF_SOC_STATUS0 */
69 	SOCSTS_DPLL_LOCK	= 1 << 5,
70 	SOCSTS_APLL_LOCK	= 1 << 6,
71 	SOCSTS_CPLL_LOCK	= 1 << 7,
72 	SOCSTS_GPLL_LOCK	= 1 << 8,
73 };
74 
75 #define DIV_TO_RATE(input_rate, div)	((input_rate) / ((div) + 1))
76 
77 #define PLL_DIVISORS(hz, _nr, _no) {\
78 	.nr = _nr, .nf = (u32)((u64)hz * _nr * _no / OSC_HZ), .no = _no};\
79 	_Static_assert(((u64)hz * _nr * _no / OSC_HZ) * OSC_HZ /\
80 		       (_nr * _no) == hz, #hz "Hz cannot be hit with PLL "\
81 		       "divisors on line " __stringify(__LINE__));
82 
83 /* Keep divisors as low as possible to reduce jitter and power usage */
84 #ifdef CONFIG_SPL_BUILD
85 static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 2, 2);
86 static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 1, 2);
87 #endif
88 
89 static int rkclk_set_pll(struct rk3188_cru *cru, enum rk_clk_id clk_id,
90 			 const struct pll_div *div, bool has_bwadj)
91 {
92 	int pll_id = rk_pll_id(clk_id);
93 	struct rk3188_pll *pll = &cru->pll[pll_id];
94 	/* All PLLs have same VCO and output frequency range restrictions. */
95 	uint vco_hz = OSC_HZ / 1000 * div->nf / div->nr * 1000;
96 	uint output_hz = vco_hz / div->no;
97 
98 	debug("PLL at %x: nf=%d, nr=%d, no=%d, vco=%u Hz, output=%u Hz\n",
99 	      (uint)pll, div->nf, div->nr, div->no, vco_hz, output_hz);
100 	assert(vco_hz >= VCO_MIN_HZ && vco_hz <= VCO_MAX_HZ &&
101 	       output_hz >= OUTPUT_MIN_HZ && output_hz <= OUTPUT_MAX_HZ &&
102 	       (div->no == 1 || !(div->no % 2)));
103 
104 	/* enter reset */
105 	rk_setreg(&pll->con3, 1 << PLL_RESET_SHIFT);
106 
107 	rk_clrsetreg(&pll->con0,
108 		     CLKR_MASK << CLKR_SHIFT | PLL_OD_MASK,
109 		     ((div->nr - 1) << CLKR_SHIFT) | (div->no - 1));
110 	rk_clrsetreg(&pll->con1, CLKF_MASK, div->nf - 1);
111 
112 	if (has_bwadj)
113 		rk_clrsetreg(&pll->con2, PLL_BWADJ_MASK, (div->nf >> 1) - 1);
114 
115 	udelay(10);
116 
117 	/* return from reset */
118 	rk_clrreg(&pll->con3, 1 << PLL_RESET_SHIFT);
119 
120 	return 0;
121 }
122 
123 static int rkclk_configure_ddr(struct rk3188_cru *cru, struct rk3188_grf *grf,
124 			       unsigned int hz, bool has_bwadj)
125 {
126 	static const struct pll_div dpll_cfg[] = {
127 		{.nf = 25, .nr = 2, .no = 1},
128 		{.nf = 400, .nr = 9, .no = 2},
129 		{.nf = 500, .nr = 9, .no = 2},
130 		{.nf = 100, .nr = 3, .no = 1},
131 	};
132 	int cfg;
133 
134 	switch (hz) {
135 	case 300000000:
136 		cfg = 0;
137 		break;
138 	case 533000000:	/* actually 533.3P MHz */
139 		cfg = 1;
140 		break;
141 	case 666000000:	/* actually 666.6P MHz */
142 		cfg = 2;
143 		break;
144 	case 800000000:
145 		cfg = 3;
146 		break;
147 	default:
148 		debug("Unsupported SDRAM frequency");
149 		return -EINVAL;
150 	}
151 
152 	/* pll enter slow-mode */
153 	rk_clrsetreg(&cru->cru_mode_con, DPLL_MODE_MASK << DPLL_MODE_SHIFT,
154 		     DPLL_MODE_SLOW << DPLL_MODE_SHIFT);
155 
156 	rkclk_set_pll(cru, CLK_DDR, &dpll_cfg[cfg], has_bwadj);
157 
158 	/* wait for pll lock */
159 	while (!(readl(&grf->soc_status0) & SOCSTS_DPLL_LOCK))
160 		udelay(1);
161 
162 	/* PLL enter normal-mode */
163 	rk_clrsetreg(&cru->cru_mode_con, DPLL_MODE_MASK << DPLL_MODE_SHIFT,
164 		     DPLL_MODE_NORMAL << DPLL_MODE_SHIFT);
165 
166 	return 0;
167 }
168 
169 static int rkclk_configure_cpu(struct rk3188_cru *cru, struct rk3188_grf *grf,
170 			      unsigned int hz, bool has_bwadj)
171 {
172 	static const struct pll_div apll_cfg[] = {
173 		{.nf = 50, .nr = 1, .no = 2},
174 		{.nf = 67, .nr = 1, .no = 1},
175 	};
176 	int div_core_peri, div_aclk_core, cfg;
177 
178 	/*
179 	 * We support two possible frequencies, the safe 600MHz
180 	 * which will work with default pmic settings and will
181 	 * be set in SPL to get away from the 24MHz default and
182 	 * the maximum of 1.6Ghz, which boards can set if they
183 	 * were able to get pmic support for it.
184 	 */
185 	switch (hz) {
186 	case APLL_SAFE_HZ:
187 		cfg = 0;
188 		div_core_peri = 1;
189 		div_aclk_core = 3;
190 		break;
191 	case APLL_HZ:
192 		cfg = 1;
193 		div_core_peri = 2;
194 		div_aclk_core = 3;
195 		break;
196 	default:
197 		debug("Unsupported ARMCLK frequency");
198 		return -EINVAL;
199 	}
200 
201 	/* pll enter slow-mode */
202 	rk_clrsetreg(&cru->cru_mode_con, APLL_MODE_MASK << APLL_MODE_SHIFT,
203 		     APLL_MODE_SLOW << APLL_MODE_SHIFT);
204 
205 	rkclk_set_pll(cru, CLK_ARM, &apll_cfg[cfg], has_bwadj);
206 
207 	/* waiting for pll lock */
208 	while (!(readl(&grf->soc_status0) & SOCSTS_APLL_LOCK))
209 		udelay(1);
210 
211 	/* Set divider for peripherals attached to the cpu core. */
212 	rk_clrsetreg(&cru->cru_clksel_con[0],
213 		CORE_PERI_DIV_MASK << CORE_PERI_DIV_SHIFT,
214 		div_core_peri << CORE_PERI_DIV_SHIFT);
215 
216 	/* set up dependent divisor for aclk_core */
217 	rk_clrsetreg(&cru->cru_clksel_con[1],
218 		CORE_ACLK_DIV_MASK << CORE_ACLK_DIV_SHIFT,
219 		div_aclk_core << CORE_ACLK_DIV_SHIFT);
220 
221 	/* PLL enter normal-mode */
222 	rk_clrsetreg(&cru->cru_mode_con, APLL_MODE_MASK << APLL_MODE_SHIFT,
223 		     APLL_MODE_NORMAL << APLL_MODE_SHIFT);
224 
225 	return hz;
226 }
227 
228 /* Get pll rate by id */
229 static uint32_t rkclk_pll_get_rate(struct rk3188_cru *cru,
230 				   enum rk_clk_id clk_id)
231 {
232 	uint32_t nr, no, nf;
233 	uint32_t con;
234 	int pll_id = rk_pll_id(clk_id);
235 	struct rk3188_pll *pll = &cru->pll[pll_id];
236 	static u8 clk_shift[CLK_COUNT] = {
237 		0xff, APLL_MODE_SHIFT, DPLL_MODE_SHIFT, CPLL_MODE_SHIFT,
238 		GPLL_MODE_SHIFT
239 	};
240 	uint shift;
241 
242 	con = readl(&cru->cru_mode_con);
243 	shift = clk_shift[clk_id];
244 	switch ((con >> shift) & APLL_MODE_MASK) {
245 	case APLL_MODE_SLOW:
246 		return OSC_HZ;
247 	case APLL_MODE_NORMAL:
248 		/* normal mode */
249 		con = readl(&pll->con0);
250 		no = ((con >> CLKOD_SHIFT) & CLKOD_MASK) + 1;
251 		nr = ((con >> CLKR_SHIFT) & CLKR_MASK) + 1;
252 		con = readl(&pll->con1);
253 		nf = ((con >> CLKF_SHIFT) & CLKF_MASK) + 1;
254 
255 		return (24 * nf / (nr * no)) * 1000000;
256 	case APLL_MODE_DEEP:
257 	default:
258 		return 32768;
259 	}
260 }
261 
262 static ulong rockchip_mmc_get_clk(struct rk3188_cru *cru, uint gclk_rate,
263 				  int periph)
264 {
265 	uint div;
266 	u32 con;
267 
268 	switch (periph) {
269 	case HCLK_EMMC:
270 	case SCLK_EMMC:
271 		con = readl(&cru->cru_clksel_con[12]);
272 		div = (con >> EMMC_DIV_SHIFT) & EMMC_DIV_MASK;
273 		break;
274 	case HCLK_SDMMC:
275 	case SCLK_SDMMC:
276 		con = readl(&cru->cru_clksel_con[11]);
277 		div = (con >> MMC0_DIV_SHIFT) & MMC0_DIV_MASK;
278 		break;
279 	case HCLK_SDIO:
280 	case SCLK_SDIO:
281 		con = readl(&cru->cru_clksel_con[12]);
282 		div = (con >> SDIO_DIV_SHIFT) & SDIO_DIV_MASK;
283 		break;
284 	default:
285 		return -EINVAL;
286 	}
287 
288 	return DIV_TO_RATE(gclk_rate, div) / 2;
289 }
290 
291 static ulong rockchip_mmc_set_clk(struct rk3188_cru *cru, uint gclk_rate,
292 				  int  periph, uint freq)
293 {
294 	int src_clk_div;
295 
296 	debug("%s: gclk_rate=%u\n", __func__, gclk_rate);
297 	/* mmc clock defaulg div 2 internal, need provide double in cru */
298 	src_clk_div = DIV_ROUND_UP(gclk_rate / 2, freq) - 1;
299 	assert(src_clk_div <= 0x3f);
300 
301 	switch (periph) {
302 	case HCLK_EMMC:
303 	case SCLK_EMMC:
304 		rk_clrsetreg(&cru->cru_clksel_con[12],
305 			     EMMC_DIV_MASK << EMMC_DIV_SHIFT,
306 			     src_clk_div << EMMC_DIV_SHIFT);
307 		break;
308 	case HCLK_SDMMC:
309 	case SCLK_SDMMC:
310 		rk_clrsetreg(&cru->cru_clksel_con[11],
311 			     MMC0_DIV_MASK << MMC0_DIV_SHIFT,
312 			     src_clk_div << MMC0_DIV_SHIFT);
313 		break;
314 	case HCLK_SDIO:
315 	case SCLK_SDIO:
316 		rk_clrsetreg(&cru->cru_clksel_con[12],
317 			     SDIO_DIV_MASK << SDIO_DIV_SHIFT,
318 			     src_clk_div << SDIO_DIV_SHIFT);
319 		break;
320 	default:
321 		return -EINVAL;
322 	}
323 
324 	return rockchip_mmc_get_clk(cru, gclk_rate, periph);
325 }
326 
327 static ulong rockchip_spi_get_clk(struct rk3188_cru *cru, uint gclk_rate,
328 				  int periph)
329 {
330 	uint div;
331 	u32 con;
332 
333 	switch (periph) {
334 	case SCLK_SPI0:
335 		con = readl(&cru->cru_clksel_con[25]);
336 		div = (con >> SPI0_DIV_SHIFT) & SPI0_DIV_MASK;
337 		break;
338 	case SCLK_SPI1:
339 		con = readl(&cru->cru_clksel_con[25]);
340 		div = (con >> SPI1_DIV_SHIFT) & SPI1_DIV_MASK;
341 		break;
342 	default:
343 		return -EINVAL;
344 	}
345 
346 	return DIV_TO_RATE(gclk_rate, div);
347 }
348 
349 static ulong rockchip_spi_set_clk(struct rk3188_cru *cru, uint gclk_rate,
350 				  int periph, uint freq)
351 {
352 	int src_clk_div = DIV_ROUND_UP(gclk_rate, freq) - 1;
353 
354 	assert(src_clk_div < 128);
355 	switch (periph) {
356 	case SCLK_SPI0:
357 		assert(src_clk_div <= SPI0_DIV_MASK);
358 		rk_clrsetreg(&cru->cru_clksel_con[25],
359 			     SPI0_DIV_MASK << SPI0_DIV_SHIFT,
360 			     src_clk_div << SPI0_DIV_SHIFT);
361 		break;
362 	case SCLK_SPI1:
363 		assert(src_clk_div <= SPI1_DIV_MASK);
364 		rk_clrsetreg(&cru->cru_clksel_con[25],
365 			     SPI1_DIV_MASK << SPI1_DIV_SHIFT,
366 			     src_clk_div << SPI1_DIV_SHIFT);
367 		break;
368 	default:
369 		return -EINVAL;
370 	}
371 
372 	return rockchip_spi_get_clk(cru, gclk_rate, periph);
373 }
374 
375 static ulong rk3188_saradc_get_clk(struct rk3188_cru *cru)
376 {
377 	u32 div, val;
378 
379 	val = readl(&cru->cru_clksel_con[24]);
380 	div = bitfield_extract(val, SARADC_DIV_SHIFT, SARADC_DIV_WIDTH);
381 
382 	return DIV_TO_RATE(OSC_HZ, div);
383 }
384 
385 static ulong rk3188_saradc_set_clk(struct rk3188_cru *cru, uint hz)
386 {
387 	int src_clk_div;
388 
389 	src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1;
390 	assert(src_clk_div < 128);
391 
392 	rk_clrsetreg(&cru->cru_clksel_con[24],
393 		     SARADC_DIV_MASK,
394 		     src_clk_div << SARADC_DIV_SHIFT);
395 
396 	return rk3188_saradc_get_clk(cru);
397 }
398 
399 #ifdef CONFIG_SPL_BUILD
400 static void rkclk_init(struct rk3188_cru *cru, struct rk3188_grf *grf,
401 		       bool has_bwadj)
402 {
403 	u32 aclk_div, hclk_div, pclk_div, h2p_div;
404 
405 	/* pll enter slow-mode */
406 	rk_clrsetreg(&cru->cru_mode_con,
407 		     GPLL_MODE_MASK << GPLL_MODE_SHIFT |
408 		     CPLL_MODE_MASK << CPLL_MODE_SHIFT,
409 		     GPLL_MODE_SLOW << GPLL_MODE_SHIFT |
410 		     CPLL_MODE_SLOW << CPLL_MODE_SHIFT);
411 
412 	/* init pll */
413 	rkclk_set_pll(cru, CLK_GENERAL, &gpll_init_cfg, has_bwadj);
414 	rkclk_set_pll(cru, CLK_CODEC, &cpll_init_cfg, has_bwadj);
415 
416 	/* waiting for pll lock */
417 	while ((readl(&grf->soc_status0) &
418 			(SOCSTS_CPLL_LOCK | SOCSTS_GPLL_LOCK)) !=
419 			(SOCSTS_CPLL_LOCK | SOCSTS_GPLL_LOCK))
420 		udelay(1);
421 
422 	/*
423 	 * cpu clock pll source selection and
424 	 * reparent aclk_cpu_pre from apll to gpll
425 	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
426 	 */
427 	aclk_div = DIV_ROUND_UP(GPLL_HZ, CPU_ACLK_HZ) - 1;
428 	assert((aclk_div + 1) * CPU_ACLK_HZ == GPLL_HZ && aclk_div <= 0x1f);
429 
430 	rk_clrsetreg(&cru->cru_clksel_con[0],
431 		     CPU_ACLK_PLL_MASK << CPU_ACLK_PLL_SHIFT |
432 		     A9_CPU_DIV_MASK << A9_CPU_DIV_SHIFT,
433 		     CPU_ACLK_PLL_SELECT_GPLL << CPU_ACLK_PLL_SHIFT |
434 		     aclk_div << A9_CPU_DIV_SHIFT);
435 
436 	hclk_div = ilog2(CPU_ACLK_HZ / CPU_HCLK_HZ);
437 	assert((1 << hclk_div) * CPU_HCLK_HZ == CPU_ACLK_HZ && hclk_div < 0x3);
438 	pclk_div = ilog2(CPU_ACLK_HZ / CPU_PCLK_HZ);
439 	assert((1 << pclk_div) * CPU_PCLK_HZ == CPU_ACLK_HZ && pclk_div < 0x4);
440 	h2p_div = ilog2(CPU_HCLK_HZ / CPU_H2P_HZ);
441 	assert((1 << h2p_div) * CPU_H2P_HZ == CPU_HCLK_HZ && pclk_div < 0x3);
442 
443 	rk_clrsetreg(&cru->cru_clksel_con[1],
444 		     AHB2APB_DIV_MASK << AHB2APB_DIV_SHIFT |
445 		     CPU_PCLK_DIV_MASK << CPU_PCLK_DIV_SHIFT |
446 		     CPU_HCLK_DIV_MASK << CPU_HCLK_DIV_SHIFT,
447 		     h2p_div << AHB2APB_DIV_SHIFT |
448 		     pclk_div << CPU_PCLK_DIV_SHIFT |
449 		     hclk_div << CPU_HCLK_DIV_SHIFT);
450 
451 	/*
452 	 * peri clock pll source selection and
453 	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
454 	 */
455 	aclk_div = GPLL_HZ / PERI_ACLK_HZ - 1;
456 	assert((aclk_div + 1) * PERI_ACLK_HZ == GPLL_HZ && aclk_div < 0x1f);
457 
458 	hclk_div = ilog2(PERI_ACLK_HZ / PERI_HCLK_HZ);
459 	assert((1 << hclk_div) * PERI_HCLK_HZ ==
460 		PERI_ACLK_HZ && (hclk_div < 0x4));
461 
462 	pclk_div = ilog2(PERI_ACLK_HZ / PERI_PCLK_HZ);
463 	assert((1 << pclk_div) * PERI_PCLK_HZ ==
464 		PERI_ACLK_HZ && (pclk_div < 0x4));
465 
466 	rk_clrsetreg(&cru->cru_clksel_con[10],
467 		     PERI_PCLK_DIV_MASK << PERI_PCLK_DIV_SHIFT |
468 		     PERI_HCLK_DIV_MASK << PERI_HCLK_DIV_SHIFT |
469 		     PERI_ACLK_DIV_MASK << PERI_ACLK_DIV_SHIFT,
470 		     PERI_SEL_GPLL << PERI_SEL_PLL_SHIFT |
471 		     pclk_div << PERI_PCLK_DIV_SHIFT |
472 		     hclk_div << PERI_HCLK_DIV_SHIFT |
473 		     aclk_div << PERI_ACLK_DIV_SHIFT);
474 
475 	/* PLL enter normal-mode */
476 	rk_clrsetreg(&cru->cru_mode_con,
477 		     GPLL_MODE_MASK << GPLL_MODE_SHIFT |
478 		     CPLL_MODE_MASK << CPLL_MODE_SHIFT,
479 		     GPLL_MODE_NORMAL << GPLL_MODE_SHIFT |
480 		     CPLL_MODE_NORMAL << CPLL_MODE_SHIFT);
481 
482 	rockchip_mmc_set_clk(cru, PERI_HCLK_HZ, HCLK_SDMMC, 16000000);
483 }
484 #endif
485 
486 static ulong rk3188_clk_get_rate(struct clk *clk)
487 {
488 	struct rk3188_clk_priv *priv = dev_get_priv(clk->dev);
489 	ulong new_rate, gclk_rate;
490 
491 	gclk_rate = rkclk_pll_get_rate(priv->cru, CLK_GENERAL);
492 	switch (clk->id) {
493 	case 1 ... 4:
494 		new_rate = rkclk_pll_get_rate(priv->cru, clk->id);
495 		break;
496 	case HCLK_EMMC:
497 	case HCLK_SDMMC:
498 	case HCLK_SDIO:
499 	case SCLK_EMMC:
500 	case SCLK_SDMMC:
501 	case SCLK_SDIO:
502 		new_rate = rockchip_mmc_get_clk(priv->cru, PERI_HCLK_HZ,
503 						clk->id);
504 		break;
505 	case SCLK_SPI0:
506 	case SCLK_SPI1:
507 		new_rate = rockchip_spi_get_clk(priv->cru, PERI_PCLK_HZ,
508 						clk->id);
509 		break;
510 	case PCLK_I2C0:
511 	case PCLK_I2C1:
512 	case PCLK_I2C2:
513 	case PCLK_I2C3:
514 	case PCLK_I2C4:
515 		return gclk_rate;
516 	case SCLK_SARADC:
517                 new_rate =  rk3188_saradc_get_clk(priv->cru);
518 	default:
519 		return -ENOENT;
520 	}
521 
522 	return new_rate;
523 }
524 
525 static ulong rk3188_clk_set_rate(struct clk *clk, ulong rate)
526 {
527 	struct rk3188_clk_priv *priv = dev_get_priv(clk->dev);
528 	struct rk3188_cru *cru = priv->cru;
529 	ulong new_rate;
530 
531 	switch (clk->id) {
532 	case PLL_APLL:
533 		new_rate = rkclk_configure_cpu(priv->cru, priv->grf, rate,
534 					       priv->has_bwadj);
535 		break;
536 	case CLK_DDR:
537 		new_rate = rkclk_configure_ddr(priv->cru, priv->grf, rate,
538 					       priv->has_bwadj);
539 		break;
540 	case HCLK_EMMC:
541 	case HCLK_SDMMC:
542 	case HCLK_SDIO:
543 	case SCLK_EMMC:
544 	case SCLK_SDMMC:
545 	case SCLK_SDIO:
546 		new_rate = rockchip_mmc_set_clk(cru, PERI_HCLK_HZ,
547 						clk->id, rate);
548 		break;
549 	case SCLK_SPI0:
550 	case SCLK_SPI1:
551 		new_rate = rockchip_spi_set_clk(cru, PERI_PCLK_HZ,
552 						clk->id, rate);
553 		break;
554 	case SCLK_SARADC:
555 		new_rate = rk3188_saradc_set_clk(priv->cru, rate);
556 		break;
557 	default:
558 		return -ENOENT;
559 	}
560 
561 	return new_rate;
562 }
563 
564 static struct clk_ops rk3188_clk_ops = {
565 	.get_rate	= rk3188_clk_get_rate,
566 	.set_rate	= rk3188_clk_set_rate,
567 };
568 
569 static int rk3188_clk_ofdata_to_platdata(struct udevice *dev)
570 {
571 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
572 	struct rk3188_clk_priv *priv = dev_get_priv(dev);
573 
574 	priv->cru = (struct rk3188_cru *)devfdt_get_addr(dev);
575 #endif
576 
577 	return 0;
578 }
579 
580 static int rk3188_clk_probe(struct udevice *dev)
581 {
582 	struct rk3188_clk_priv *priv = dev_get_priv(dev);
583 	enum rk3188_clk_type type = dev_get_driver_data(dev);
584 
585 	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
586 	if (IS_ERR(priv->grf))
587 		return PTR_ERR(priv->grf);
588 	priv->has_bwadj = (type == RK3188A_CRU) ? 1 : 0;
589 
590 #ifdef CONFIG_SPL_BUILD
591 #if CONFIG_IS_ENABLED(OF_PLATDATA)
592 	struct rk3188_clk_plat *plat = dev_get_platdata(dev);
593 
594 	priv->cru = map_sysmem(plat->dtd.reg[0], plat->dtd.reg[1]);
595 #endif
596 
597 	rkclk_init(priv->cru, priv->grf, priv->has_bwadj);
598 #endif
599 
600 	return 0;
601 }
602 
603 static int rk3188_clk_bind(struct udevice *dev)
604 {
605 	int ret;
606 	struct udevice *sys_child, *sf_child;
607 	struct sysreset_reg *priv;
608 	struct softreset_reg *sf_priv;
609 
610 	/* The reset driver does not have a device node, so bind it here */
611 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
612 				 &sys_child);
613 	if (ret) {
614 		debug("Warning: No sysreset driver: ret=%d\n", ret);
615 	} else {
616 		priv = malloc(sizeof(struct sysreset_reg));
617 		priv->glb_srst_fst_value = offsetof(struct rk3188_cru,
618 						    cru_glb_srst_fst_value);
619 		priv->glb_srst_snd_value = offsetof(struct rk3188_cru,
620 						    cru_glb_srst_snd_value);
621 		sys_child->priv = priv;
622 	}
623 
624 	ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
625 					 dev_ofnode(dev), &sf_child);
626 	if (ret) {
627 		debug("Warning: No rockchip reset driver: ret=%d\n", ret);
628 	} else {
629 		sf_priv = malloc(sizeof(struct softreset_reg));
630 		sf_priv->sf_reset_offset = offsetof(struct rk3188_cru,
631 						    cru_softrst_con[0]);
632 		sf_priv->sf_reset_num = 9;
633 		sf_child->priv = sf_priv;
634 	}
635 
636 	return 0;
637 }
638 
639 static const struct udevice_id rk3188_clk_ids[] = {
640 	{ .compatible = "rockchip,rk3188-cru", .data = RK3188_CRU },
641 	{ .compatible = "rockchip,rk3188a-cru", .data = RK3188A_CRU },
642 	{ }
643 };
644 
645 U_BOOT_DRIVER(rockchip_rk3188_cru) = {
646 	.name			= "rockchip_rk3188_cru",
647 	.id			= UCLASS_CLK,
648 	.of_match		= rk3188_clk_ids,
649 	.priv_auto_alloc_size	= sizeof(struct rk3188_clk_priv),
650 	.platdata_auto_alloc_size = sizeof(struct rk3188_clk_plat),
651 	.ops			= &rk3188_clk_ops,
652 	.bind			= rk3188_clk_bind,
653 	.ofdata_to_platdata	= rk3188_clk_ofdata_to_platdata,
654 	.probe			= rk3188_clk_probe,
655 };
656