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