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