1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * (C) Copyright 2016 Rockchip Electronics Co., Ltd
4  * Author: Andy Yan <andy.yan@rock-chips.com>
5  */
6 
7 #include <common.h>
8 #include <bitfield.h>
9 #include <clk-uclass.h>
10 #include <dm.h>
11 #include <errno.h>
12 #include <log.h>
13 #include <malloc.h>
14 #include <syscon.h>
15 #include <asm/global_data.h>
16 #include <asm/io.h>
17 #include <asm/arch-rockchip/clock.h>
18 #include <asm/arch-rockchip/cru_rv1108.h>
19 #include <asm/arch-rockchip/hardware.h>
20 #include <dm/device-internal.h>
21 #include <dm/lists.h>
22 #include <dt-bindings/clock/rv1108-cru.h>
23 #include <linux/delay.h>
24 #include <linux/stringify.h>
25 
26 DECLARE_GLOBAL_DATA_PTR;
27 
28 enum {
29 	VCO_MAX_HZ	= 2400U * 1000000,
30 	VCO_MIN_HZ	= 600 * 1000000,
31 	OUTPUT_MAX_HZ	= 2400U * 1000000,
32 	OUTPUT_MIN_HZ	= 24 * 1000000,
33 };
34 
35 #define DIV_TO_RATE(input_rate, div)	((input_rate) / ((div) + 1))
36 
37 #define PLL_DIVISORS(hz, _refdiv, _postdiv1, _postdiv2) {\
38 	.refdiv = _refdiv,\
39 	.fbdiv = (u32)((u64)hz * _refdiv * _postdiv1 * _postdiv2 / OSC_HZ),\
40 	.postdiv1 = _postdiv1, .postdiv2 = _postdiv2};\
41 	_Static_assert(((u64)hz * _refdiv * _postdiv1 * _postdiv2 / OSC_HZ) *\
42 			 OSC_HZ / (_refdiv * _postdiv1 * _postdiv2) == hz,\
43 			 #hz "Hz cannot be hit with PLL "\
44 			 "divisors on line " __stringify(__LINE__));
45 
46 static const struct pll_div apll_init_cfg = PLL_DIVISORS(APLL_HZ, 1, 3, 1);
47 static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 2, 2, 1);
48 
49 /* use integer mode */
rv1108_pll_id(enum rk_clk_id clk_id)50 static inline int rv1108_pll_id(enum rk_clk_id clk_id)
51 {
52 	int id = 0;
53 
54 	switch (clk_id) {
55 	case CLK_ARM:
56 	case CLK_DDR:
57 		id = clk_id - 1;
58 		break;
59 	case CLK_GENERAL:
60 		id = 2;
61 		break;
62 	default:
63 		printf("invalid pll id:%d\n", clk_id);
64 		id = -1;
65 		break;
66 	}
67 
68 	return id;
69 }
70 
rkclk_set_pll(struct rv1108_cru * cru,enum rk_clk_id clk_id,const struct pll_div * div)71 static int rkclk_set_pll(struct rv1108_cru *cru, enum rk_clk_id clk_id,
72 			 const struct pll_div *div)
73 {
74 	int pll_id = rv1108_pll_id(clk_id);
75 	struct rv1108_pll *pll = &cru->pll[pll_id];
76 
77 	/* All PLLs have same VCO and output frequency range restrictions. */
78 	uint vco_hz = OSC_HZ / 1000 * div->fbdiv / div->refdiv * 1000;
79 	uint output_hz = vco_hz / div->postdiv1 / div->postdiv2;
80 
81 	debug("PLL at %p: fb=%d, ref=%d, pst1=%d, pst2=%d, vco=%u Hz, output=%u Hz\n",
82 	      pll, div->fbdiv, div->refdiv, div->postdiv1,
83 	      div->postdiv2, vco_hz, output_hz);
84 	assert(vco_hz >= VCO_MIN_HZ && vco_hz <= VCO_MAX_HZ &&
85 	       output_hz >= OUTPUT_MIN_HZ && output_hz <= OUTPUT_MAX_HZ);
86 
87 	/*
88 	 * When power on or changing PLL setting,
89 	 * we must force PLL into slow mode to ensure output stable clock.
90 	 */
91 	rk_clrsetreg(&pll->con3, WORK_MODE_MASK,
92 		     WORK_MODE_SLOW << WORK_MODE_SHIFT);
93 
94 	/* use integer mode */
95 	rk_setreg(&pll->con3, 1 << DSMPD_SHIFT);
96 	/* Power down */
97 	rk_setreg(&pll->con3, 1 << GLOBAL_POWER_DOWN_SHIFT);
98 
99 	rk_clrsetreg(&pll->con0, FBDIV_MASK, div->fbdiv << FBDIV_SHIFT);
100 	rk_clrsetreg(&pll->con1, POSTDIV1_MASK | POSTDIV2_MASK | REFDIV_MASK,
101 		     (div->postdiv1 << POSTDIV1_SHIFT |
102 		     div->postdiv2 << POSTDIV2_SHIFT |
103 		     div->refdiv << REFDIV_SHIFT));
104 	rk_clrsetreg(&pll->con2, FRACDIV_MASK,
105 		     (div->refdiv << REFDIV_SHIFT));
106 
107 	/* Power Up */
108 	rk_clrreg(&pll->con3, 1 << GLOBAL_POWER_DOWN_SHIFT);
109 
110 	/* waiting for pll lock */
111 	while (readl(&pll->con2) & (1 << LOCK_STA_SHIFT))
112 		udelay(1);
113 
114 	/*
115 	 * set PLL into normal mode.
116 	 */
117 	rk_clrsetreg(&pll->con3, WORK_MODE_MASK,
118 		     WORK_MODE_NORMAL << WORK_MODE_SHIFT);
119 
120 	return 0;
121 }
122 
rkclk_pll_get_rate(struct rv1108_cru * cru,enum rk_clk_id clk_id)123 static uint32_t rkclk_pll_get_rate(struct rv1108_cru *cru,
124 				   enum rk_clk_id clk_id)
125 {
126 	uint32_t refdiv, fbdiv, postdiv1, postdiv2;
127 	uint32_t con0, con1, con3;
128 	int pll_id = rv1108_pll_id(clk_id);
129 	struct rv1108_pll *pll = &cru->pll[pll_id];
130 	uint32_t freq;
131 
132 	con3 = readl(&pll->con3);
133 
134 	if (con3 & WORK_MODE_MASK) {
135 		con0 = readl(&pll->con0);
136 		con1 = readl(&pll->con1);
137 		fbdiv = (con0 >> FBDIV_SHIFT) & FBDIV_MASK;
138 		postdiv1 = (con1 & POSTDIV1_MASK) >> POSTDIV1_SHIFT;
139 		postdiv2 = (con1 & POSTDIV2_MASK) >> POSTDIV2_SHIFT;
140 		refdiv = (con1 >> REFDIV_SHIFT) & REFDIV_MASK;
141 		freq = (24 * fbdiv / (refdiv * postdiv1 * postdiv2)) * 1000000;
142 	} else {
143 		freq = OSC_HZ;
144 	}
145 
146 	return freq;
147 }
148 
rv1108_mac_set_clk(struct rv1108_cru * cru,ulong rate)149 static int rv1108_mac_set_clk(struct rv1108_cru *cru, ulong rate)
150 {
151 	uint32_t con = readl(&cru->clksel_con[24]);
152 	ulong pll_rate;
153 	uint8_t div;
154 
155 	if ((con >> MAC_PLL_SEL_SHIFT) & MAC_PLL_SEL_GPLL)
156 		pll_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
157 	else
158 		pll_rate = rkclk_pll_get_rate(cru, CLK_ARM);
159 
160 	/*default set 50MHZ for gmac*/
161 	if (!rate)
162 		rate = 50000000;
163 
164 	div = DIV_ROUND_UP(pll_rate, rate) - 1;
165 	if (div <= 0x1f)
166 		rk_clrsetreg(&cru->clksel_con[24], MAC_CLK_DIV_MASK,
167 			     div << MAC_CLK_DIV_SHIFT);
168 	else
169 		debug("Unsupported div for gmac:%d\n", div);
170 
171 	return DIV_TO_RATE(pll_rate, div);
172 }
173 
rv1108_sfc_set_clk(struct rv1108_cru * cru,uint rate)174 static int rv1108_sfc_set_clk(struct rv1108_cru *cru, uint rate)
175 {
176 	u32 con = readl(&cru->clksel_con[27]);
177 	u32 pll_rate;
178 	u32 div;
179 
180 	if ((con >> SFC_PLL_SEL_SHIFT) && SFC_PLL_SEL_GPLL)
181 		pll_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
182 	else
183 		pll_rate = rkclk_pll_get_rate(cru, CLK_DDR);
184 
185 	div = DIV_ROUND_UP(pll_rate, rate) - 1;
186 	if (div <= 0x3f)
187 		rk_clrsetreg(&cru->clksel_con[27], SFC_CLK_DIV_MASK,
188 			     div << SFC_CLK_DIV_SHIFT);
189 	else
190 		debug("Unsupported sfc clk rate:%d\n", rate);
191 
192 	return DIV_TO_RATE(pll_rate, div);
193 }
194 
rv1108_saradc_get_clk(struct rv1108_cru * cru)195 static ulong rv1108_saradc_get_clk(struct rv1108_cru *cru)
196 {
197 	u32 div, val;
198 
199 	val = readl(&cru->clksel_con[22]);
200 	div = bitfield_extract(val, CLK_SARADC_DIV_CON_SHIFT,
201 			       CLK_SARADC_DIV_CON_WIDTH);
202 
203 	return DIV_TO_RATE(OSC_HZ, div);
204 }
205 
rv1108_saradc_set_clk(struct rv1108_cru * cru,uint hz)206 static ulong rv1108_saradc_set_clk(struct rv1108_cru *cru, uint hz)
207 {
208 	int src_clk_div;
209 
210 	src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1;
211 	assert(src_clk_div < 128);
212 
213 	rk_clrsetreg(&cru->clksel_con[22],
214 		     CLK_SARADC_DIV_CON_MASK,
215 		     src_clk_div << CLK_SARADC_DIV_CON_SHIFT);
216 
217 	return rv1108_saradc_get_clk(cru);
218 }
219 
rv1108_aclk_vio1_get_clk(struct rv1108_cru * cru)220 static ulong rv1108_aclk_vio1_get_clk(struct rv1108_cru *cru)
221 {
222 	u32 div, val;
223 
224 	val = readl(&cru->clksel_con[28]);
225 	div = bitfield_extract(val, ACLK_VIO1_CLK_DIV_SHIFT,
226 			       CLK_VIO_DIV_CON_WIDTH);
227 
228 	return DIV_TO_RATE(GPLL_HZ, div);
229 }
230 
rv1108_aclk_vio1_set_clk(struct rv1108_cru * cru,uint hz)231 static ulong rv1108_aclk_vio1_set_clk(struct rv1108_cru *cru, uint hz)
232 {
233 	int src_clk_div;
234 
235 	src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz) - 1;
236 	assert(src_clk_div < 32);
237 
238 	rk_clrsetreg(&cru->clksel_con[28],
239 		     ACLK_VIO1_CLK_DIV_MASK | ACLK_VIO1_PLL_SEL_MASK,
240 		     (src_clk_div << ACLK_VIO1_CLK_DIV_SHIFT) |
241 		     (VIO_PLL_SEL_GPLL << ACLK_VIO1_PLL_SEL_SHIFT));
242 
243 	return rv1108_aclk_vio1_get_clk(cru);
244 }
245 
rv1108_aclk_vio0_get_clk(struct rv1108_cru * cru)246 static ulong rv1108_aclk_vio0_get_clk(struct rv1108_cru *cru)
247 {
248 	u32 div, val;
249 
250 	val = readl(&cru->clksel_con[28]);
251 	div = bitfield_extract(val, ACLK_VIO0_CLK_DIV_SHIFT,
252 			       CLK_VIO_DIV_CON_WIDTH);
253 
254 	return DIV_TO_RATE(GPLL_HZ, div);
255 }
256 
rv1108_aclk_vio0_set_clk(struct rv1108_cru * cru,uint hz)257 static ulong rv1108_aclk_vio0_set_clk(struct rv1108_cru *cru, uint hz)
258 {
259 	int src_clk_div;
260 
261 	src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz) - 1;
262 	assert(src_clk_div < 32);
263 
264 	rk_clrsetreg(&cru->clksel_con[28],
265 		     ACLK_VIO0_CLK_DIV_MASK | ACLK_VIO0_PLL_SEL_MASK,
266 		     (src_clk_div << ACLK_VIO0_CLK_DIV_SHIFT) |
267 		     (VIO_PLL_SEL_GPLL << ACLK_VIO0_PLL_SEL_SHIFT));
268 
269 	/*HCLK_VIO default div = 4*/
270 	rk_clrsetreg(&cru->clksel_con[29],
271 		     HCLK_VIO_CLK_DIV_MASK,
272 		     3 << HCLK_VIO_CLK_DIV_SHIFT);
273 	/*PCLK_VIO default div = 4*/
274 	rk_clrsetreg(&cru->clksel_con[29],
275 		     PCLK_VIO_CLK_DIV_MASK,
276 		     3 << PCLK_VIO_CLK_DIV_SHIFT);
277 
278 	return rv1108_aclk_vio0_get_clk(cru);
279 }
280 
rv1108_dclk_vop_get_clk(struct rv1108_cru * cru)281 static ulong rv1108_dclk_vop_get_clk(struct rv1108_cru *cru)
282 {
283 	u32 div, val;
284 
285 	val = readl(&cru->clksel_con[32]);
286 	div = bitfield_extract(val, DCLK_VOP_CLK_DIV_SHIFT,
287 			       DCLK_VOP_DIV_CON_WIDTH);
288 
289 	return DIV_TO_RATE(GPLL_HZ, div);
290 }
291 
rv1108_dclk_vop_set_clk(struct rv1108_cru * cru,uint hz)292 static ulong rv1108_dclk_vop_set_clk(struct rv1108_cru *cru, uint hz)
293 {
294 	int src_clk_div;
295 
296 	src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz) - 1;
297 	assert(src_clk_div < 64);
298 
299 	rk_clrsetreg(&cru->clksel_con[32],
300 		     DCLK_VOP_CLK_DIV_MASK | DCLK_VOP_PLL_SEL_MASK |
301 		     DCLK_VOP_SEL_SHIFT,
302 		     (src_clk_div << DCLK_VOP_CLK_DIV_SHIFT) |
303 		     (DCLK_VOP_PLL_SEL_GPLL << DCLK_VOP_PLL_SEL_SHIFT) |
304 		     (DCLK_VOP_SEL_PLL << DCLK_VOP_SEL_SHIFT));
305 
306 	return rv1108_dclk_vop_get_clk(cru);
307 }
308 
rv1108_aclk_bus_get_clk(struct rv1108_cru * cru)309 static ulong rv1108_aclk_bus_get_clk(struct rv1108_cru *cru)
310 {
311 	u32 div, val;
312 	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
313 
314 	val = readl(&cru->clksel_con[2]);
315 	div = bitfield_extract(val, ACLK_BUS_DIV_CON_SHIFT,
316 			       ACLK_BUS_DIV_CON_WIDTH);
317 
318 	return DIV_TO_RATE(parent_rate, div);
319 }
320 
rv1108_aclk_bus_set_clk(struct rv1108_cru * cru,uint hz)321 static ulong rv1108_aclk_bus_set_clk(struct rv1108_cru *cru, uint hz)
322 {
323 	int src_clk_div;
324 	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
325 
326 	src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
327 	assert(src_clk_div < 32);
328 
329 	rk_clrsetreg(&cru->clksel_con[2],
330 		     ACLK_BUS_DIV_CON_MASK | ACLK_BUS_PLL_SEL_MASK,
331 		     (src_clk_div << ACLK_BUS_DIV_CON_SHIFT) |
332 		     (ACLK_BUS_PLL_SEL_GPLL << ACLK_BUS_PLL_SEL_SHIFT));
333 
334 	return rv1108_aclk_bus_get_clk(cru);
335 }
336 
rv1108_aclk_peri_get_clk(struct rv1108_cru * cru)337 static ulong rv1108_aclk_peri_get_clk(struct rv1108_cru *cru)
338 {
339 	u32 div, val;
340 	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
341 
342 	val = readl(&cru->clksel_con[23]);
343 	div = bitfield_extract(val, ACLK_PERI_DIV_CON_SHIFT,
344 			       PERI_DIV_CON_WIDTH);
345 
346 	return DIV_TO_RATE(parent_rate, div);
347 }
348 
rv1108_hclk_peri_get_clk(struct rv1108_cru * cru)349 static ulong rv1108_hclk_peri_get_clk(struct rv1108_cru *cru)
350 {
351 	u32 div, val;
352 	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
353 
354 	val = readl(&cru->clksel_con[23]);
355 	div = bitfield_extract(val, HCLK_PERI_DIV_CON_SHIFT,
356 			       PERI_DIV_CON_WIDTH);
357 
358 	return DIV_TO_RATE(parent_rate, div);
359 }
360 
rv1108_pclk_peri_get_clk(struct rv1108_cru * cru)361 static ulong rv1108_pclk_peri_get_clk(struct rv1108_cru *cru)
362 {
363 	u32 div, val;
364 	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
365 
366 	val = readl(&cru->clksel_con[23]);
367 	div = bitfield_extract(val, PCLK_PERI_DIV_CON_SHIFT,
368 			       PERI_DIV_CON_WIDTH);
369 
370 	return DIV_TO_RATE(parent_rate, div);
371 }
372 
rv1108_aclk_peri_set_clk(struct rv1108_cru * cru,uint hz)373 static ulong rv1108_aclk_peri_set_clk(struct rv1108_cru *cru, uint hz)
374 {
375 	int src_clk_div;
376 	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
377 
378 	src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
379 	assert(src_clk_div < 32);
380 
381 	rk_clrsetreg(&cru->clksel_con[23],
382 		     ACLK_PERI_DIV_CON_MASK | ACLK_PERI_PLL_SEL_MASK,
383 		     (src_clk_div << ACLK_PERI_DIV_CON_SHIFT) |
384 		     (ACLK_PERI_PLL_SEL_GPLL << ACLK_PERI_PLL_SEL_SHIFT));
385 
386 	return rv1108_aclk_peri_get_clk(cru);
387 }
388 
rv1108_hclk_peri_set_clk(struct rv1108_cru * cru,uint hz)389 static ulong rv1108_hclk_peri_set_clk(struct rv1108_cru *cru, uint hz)
390 {
391 	int src_clk_div;
392 	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
393 
394 	src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
395 	assert(src_clk_div < 32);
396 
397 	rk_clrsetreg(&cru->clksel_con[23],
398 		     HCLK_PERI_DIV_CON_MASK,
399 		     (src_clk_div << HCLK_PERI_DIV_CON_SHIFT));
400 
401 	return rv1108_hclk_peri_get_clk(cru);
402 }
403 
rv1108_pclk_peri_set_clk(struct rv1108_cru * cru,uint hz)404 static ulong rv1108_pclk_peri_set_clk(struct rv1108_cru *cru, uint hz)
405 {
406 	int src_clk_div;
407 	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
408 
409 	src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
410 	assert(src_clk_div < 32);
411 
412 	rk_clrsetreg(&cru->clksel_con[23],
413 		     PCLK_PERI_DIV_CON_MASK,
414 		     (src_clk_div << PCLK_PERI_DIV_CON_SHIFT));
415 
416 	return rv1108_pclk_peri_get_clk(cru);
417 }
418 
rv1108_i2c_get_clk(struct rv1108_cru * cru,ulong clk_id)419 static ulong rv1108_i2c_get_clk(struct rv1108_cru *cru, ulong clk_id)
420 {
421 	u32 div, con;
422 
423 	switch (clk_id) {
424 	case SCLK_I2C0_PMU:
425 		con = readl(&cru->clksel_con[19]);
426 		div = bitfield_extract(con, CLK_I2C0_DIV_CON_SHIFT,
427 				       I2C_DIV_CON_WIDTH);
428 		break;
429 	case SCLK_I2C1:
430 		con = readl(&cru->clksel_con[19]);
431 		div = bitfield_extract(con, CLK_I2C1_DIV_CON_SHIFT,
432 				       I2C_DIV_CON_WIDTH);
433 		break;
434 	case SCLK_I2C2:
435 		con = readl(&cru->clksel_con[20]);
436 		div = bitfield_extract(con, CLK_I2C2_DIV_CON_SHIFT,
437 				       I2C_DIV_CON_WIDTH);
438 		break;
439 	case SCLK_I2C3:
440 		con = readl(&cru->clksel_con[20]);
441 		div = bitfield_extract(con, CLK_I2C3_DIV_CON_SHIFT,
442 				       I2C_DIV_CON_WIDTH);
443 		break;
444 	default:
445 		printf("do not support this i2c bus\n");
446 		return -EINVAL;
447 	}
448 
449 	return DIV_TO_RATE(GPLL_HZ, div);
450 }
451 
rv1108_i2c_set_clk(struct rv1108_cru * cru,ulong clk_id,uint hz)452 static ulong rv1108_i2c_set_clk(struct rv1108_cru *cru, ulong clk_id, uint hz)
453 {
454 	int src_clk_div;
455 
456 	/* i2c0,4,8 src clock from ppll, i2c1,2,3,5,6,7 src clock from gpll*/
457 	src_clk_div = GPLL_HZ / hz;
458 	assert(src_clk_div - 1 <= 127);
459 
460 	switch (clk_id) {
461 	case SCLK_I2C0_PMU:
462 		rk_clrsetreg(&cru->clksel_con[19],
463 			     CLK_I2C0_DIV_CON_MASK | CLK_I2C1_PLL_SEL_MASK,
464 			     (src_clk_div << CLK_I2C0_DIV_CON_SHIFT) |
465 			     (CLK_I2C1_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT));
466 		break;
467 	case SCLK_I2C1:
468 		rk_clrsetreg(&cru->clksel_con[19],
469 			     CLK_I2C1_DIV_CON_MASK | CLK_I2C1_PLL_SEL_MASK,
470 			     (src_clk_div << CLK_I2C1_DIV_CON_SHIFT) |
471 			     (CLK_I2C1_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT));
472 		break;
473 	case SCLK_I2C2:
474 		rk_clrsetreg(&cru->clksel_con[20],
475 			     CLK_I2C2_DIV_CON_MASK | CLK_I2C3_PLL_SEL_MASK,
476 			     (src_clk_div << CLK_I2C2_DIV_CON_SHIFT) |
477 			     (CLK_I2C3_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT));
478 		break;
479 	case SCLK_I2C3:
480 		rk_clrsetreg(&cru->clksel_con[20],
481 			     CLK_I2C3_DIV_CON_MASK | CLK_I2C3_PLL_SEL_MASK,
482 			     (src_clk_div << CLK_I2C3_DIV_CON_SHIFT) |
483 			     (CLK_I2C3_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT));
484 		break;
485 	default:
486 		printf("do not support this i2c bus\n");
487 		return -EINVAL;
488 	}
489 
490 	return rv1108_i2c_get_clk(cru, clk_id);
491 }
492 
rv1108_mmc_get_clk(struct rv1108_cru * cru)493 static ulong rv1108_mmc_get_clk(struct rv1108_cru *cru)
494 {
495 	u32 div, con;
496 	ulong mmc_clk;
497 
498 	con = readl(&cru->clksel_con[26]);
499 	div = bitfield_extract(con, EMMC_CLK_DIV_SHIFT, 8);
500 
501 	con = readl(&cru->clksel_con[25]);
502 
503 	if ((con & EMMC_PLL_SEL_MASK) >> EMMC_PLL_SEL_SHIFT == EMMC_PLL_SEL_OSC)
504 		mmc_clk = DIV_TO_RATE(OSC_HZ, div) / 2;
505 	else
506 		mmc_clk = DIV_TO_RATE(GPLL_HZ, div) / 2;
507 
508 	debug("%s div %d get_clk %ld\n", __func__, div, mmc_clk);
509 	return mmc_clk;
510 }
511 
rv1108_mmc_set_clk(struct rv1108_cru * cru,ulong rate)512 static ulong rv1108_mmc_set_clk(struct rv1108_cru *cru, ulong rate)
513 {
514 	int div;
515 	u32 pll_rate;
516 
517 	div = DIV_ROUND_UP(rkclk_pll_get_rate(cru, CLK_GENERAL), rate);
518 
519 	if (div < 127) {
520 		debug("%s source gpll\n", __func__);
521 		rk_clrsetreg(&cru->clksel_con[25], EMMC_PLL_SEL_MASK,
522 			    (EMMC_PLL_SEL_GPLL << EMMC_PLL_SEL_SHIFT));
523 		pll_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
524 	} else {
525 		debug("%s source 24m\n", __func__);
526 		rk_clrsetreg(&cru->clksel_con[25], EMMC_PLL_SEL_MASK,
527 			    (EMMC_PLL_SEL_OSC << EMMC_PLL_SEL_SHIFT));
528 		pll_rate = OSC_HZ;
529 	}
530 
531 	div = DIV_ROUND_UP(pll_rate / 2, rate);
532 	rk_clrsetreg(&cru->clksel_con[26], EMMC_CLK_DIV_MASK,
533 		    ((div - 1) << EMMC_CLK_DIV_SHIFT));
534 
535 	debug("%s set_rate %ld div %d\n", __func__,  rate, div);
536 
537 	return DIV_TO_RATE(pll_rate, div);
538 }
539 
rv1108_clk_get_rate(struct clk * clk)540 static ulong rv1108_clk_get_rate(struct clk *clk)
541 {
542 	struct rv1108_clk_priv *priv = dev_get_priv(clk->dev);
543 
544 	switch (clk->id) {
545 	case 0 ... 63:
546 		return rkclk_pll_get_rate(priv->cru, clk->id);
547 	case SCLK_SARADC:
548 		return rv1108_saradc_get_clk(priv->cru);
549 	case ACLK_VIO0:
550 		return rv1108_aclk_vio0_get_clk(priv->cru);
551 	case ACLK_VIO1:
552 		return rv1108_aclk_vio1_get_clk(priv->cru);
553 	case DCLK_VOP:
554 		return rv1108_dclk_vop_get_clk(priv->cru);
555 	case ACLK_PRE:
556 		return rv1108_aclk_bus_get_clk(priv->cru);
557 	case ACLK_PERI:
558 		return rv1108_aclk_peri_get_clk(priv->cru);
559 	case HCLK_PERI:
560 		return rv1108_hclk_peri_get_clk(priv->cru);
561 	case PCLK_PERI:
562 		return rv1108_pclk_peri_get_clk(priv->cru);
563 	case SCLK_I2C0_PMU:
564 	case SCLK_I2C1:
565 	case SCLK_I2C2:
566 	case SCLK_I2C3:
567 		return rv1108_i2c_get_clk(priv->cru, clk->id);
568 	case HCLK_EMMC:
569 	case SCLK_EMMC:
570 	case SCLK_EMMC_SAMPLE:
571 		return rv1108_mmc_get_clk(priv->cru);
572 	default:
573 		return -ENOENT;
574 	}
575 }
576 
rv1108_clk_set_rate(struct clk * clk,ulong rate)577 static ulong rv1108_clk_set_rate(struct clk *clk, ulong rate)
578 {
579 	struct rv1108_clk_priv *priv = dev_get_priv(clk->dev);
580 	ulong new_rate;
581 
582 	switch (clk->id) {
583 	case SCLK_MAC:
584 		new_rate = rv1108_mac_set_clk(priv->cru, rate);
585 		break;
586 	case SCLK_SFC:
587 		new_rate = rv1108_sfc_set_clk(priv->cru, rate);
588 		break;
589 	case SCLK_SARADC:
590 		new_rate = rv1108_saradc_set_clk(priv->cru, rate);
591 		break;
592 	case ACLK_VIO0:
593 		new_rate = rv1108_aclk_vio0_set_clk(priv->cru, rate);
594 		break;
595 	case ACLK_VIO1:
596 		new_rate = rv1108_aclk_vio1_set_clk(priv->cru, rate);
597 		break;
598 	case DCLK_VOP:
599 		new_rate = rv1108_dclk_vop_set_clk(priv->cru, rate);
600 		break;
601 	case ACLK_PRE:
602 		new_rate = rv1108_aclk_bus_set_clk(priv->cru, rate);
603 		break;
604 	case ACLK_PERI:
605 		new_rate = rv1108_aclk_peri_set_clk(priv->cru, rate);
606 		break;
607 	case HCLK_PERI:
608 		new_rate = rv1108_hclk_peri_set_clk(priv->cru, rate);
609 		break;
610 	case PCLK_PERI:
611 		new_rate = rv1108_pclk_peri_set_clk(priv->cru, rate);
612 		break;
613 	case SCLK_I2C0_PMU:
614 	case SCLK_I2C1:
615 	case SCLK_I2C2:
616 	case SCLK_I2C3:
617 		new_rate = rv1108_i2c_set_clk(priv->cru, clk->id, rate);
618 		break;
619 	case HCLK_EMMC:
620 	case SCLK_EMMC:
621 		new_rate = rv1108_mmc_set_clk(priv->cru, rate);
622 		break;
623 	default:
624 		return -ENOENT;
625 	}
626 
627 	return new_rate;
628 }
629 
630 static const struct clk_ops rv1108_clk_ops = {
631 	.get_rate	= rv1108_clk_get_rate,
632 	.set_rate	= rv1108_clk_set_rate,
633 };
634 
rkclk_init(struct rv1108_cru * cru)635 static void rkclk_init(struct rv1108_cru *cru)
636 {
637 	unsigned int apll, dpll, gpll;
638 	unsigned int aclk_bus, aclk_peri, hclk_peri, pclk_peri;
639 
640 	aclk_bus = rv1108_aclk_bus_set_clk(cru, ACLK_BUS_HZ / 2);
641 	aclk_peri = rv1108_aclk_peri_set_clk(cru, ACLK_PERI_HZ / 2);
642 	hclk_peri = rv1108_hclk_peri_set_clk(cru, HCLK_PERI_HZ / 2);
643 	pclk_peri = rv1108_pclk_peri_set_clk(cru, PCLK_PERI_HZ / 2);
644 	rv1108_aclk_vio0_set_clk(cru, 297000000);
645 	rv1108_aclk_vio1_set_clk(cru, 297000000);
646 
647 	/* configure apll */
648 	rkclk_set_pll(cru, CLK_ARM, &apll_init_cfg);
649 	rkclk_set_pll(cru, CLK_GENERAL, &gpll_init_cfg);
650 	aclk_bus = rv1108_aclk_bus_set_clk(cru, ACLK_BUS_HZ);
651 	aclk_peri = rv1108_aclk_peri_set_clk(cru, ACLK_PERI_HZ);
652 	hclk_peri = rv1108_hclk_peri_set_clk(cru, HCLK_PERI_HZ);
653 	pclk_peri = rv1108_pclk_peri_set_clk(cru, PCLK_PERI_HZ);
654 
655 	apll = rkclk_pll_get_rate(cru, CLK_ARM);
656 	dpll = rkclk_pll_get_rate(cru, CLK_DDR);
657 	gpll = rkclk_pll_get_rate(cru, CLK_GENERAL);
658 
659 	rk_clrsetreg(&cru->clksel_con[0], CORE_CLK_DIV_MASK,
660 		     0 << MAC_CLK_DIV_SHIFT);
661 
662 	printf("APLL: %d DPLL:%d GPLL:%d\n", apll, dpll, gpll);
663 	printf("ACLK_BUS: %d ACLK_PERI:%d HCLK_PERI:%d PCLK_PERI:%d\n",
664 	       aclk_bus, aclk_peri, hclk_peri, pclk_peri);
665 }
666 
rv1108_clk_of_to_plat(struct udevice * dev)667 static int rv1108_clk_of_to_plat(struct udevice *dev)
668 {
669 	struct rv1108_clk_priv *priv = dev_get_priv(dev);
670 
671 	priv->cru = dev_read_addr_ptr(dev);
672 
673 	return 0;
674 }
675 
rv1108_clk_probe(struct udevice * dev)676 static int rv1108_clk_probe(struct udevice *dev)
677 {
678 	struct rv1108_clk_priv *priv = dev_get_priv(dev);
679 
680 	rkclk_init(priv->cru);
681 
682 	return 0;
683 }
684 
rv1108_clk_bind(struct udevice * dev)685 static int rv1108_clk_bind(struct udevice *dev)
686 {
687 	int ret;
688 	struct udevice *sys_child;
689 	struct sysreset_reg *priv;
690 
691 	/* The reset driver does not have a device node, so bind it here */
692 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
693 				 &sys_child);
694 	if (ret) {
695 		debug("Warning: No sysreset driver: ret=%d\n", ret);
696 	} else {
697 		priv = malloc(sizeof(struct sysreset_reg));
698 		priv->glb_srst_fst_value = offsetof(struct rv1108_cru,
699 						    glb_srst_fst_val);
700 		priv->glb_srst_snd_value = offsetof(struct rv1108_cru,
701 						    glb_srst_snd_val);
702 		dev_set_priv(sys_child, priv);
703 	}
704 
705 #if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
706 	ret = offsetof(struct rv1108_cru, softrst_con[0]);
707 	ret = rockchip_reset_bind(dev, ret, 13);
708 	if (ret)
709 		debug("Warning: software reset driver bind faile\n");
710 #endif
711 
712 	return 0;
713 }
714 
715 static const struct udevice_id rv1108_clk_ids[] = {
716 	{ .compatible = "rockchip,rv1108-cru" },
717 	{ }
718 };
719 
720 U_BOOT_DRIVER(clk_rv1108) = {
721 	.name		= "clk_rv1108",
722 	.id		= UCLASS_CLK,
723 	.of_match	= rv1108_clk_ids,
724 	.priv_auto	= sizeof(struct rv1108_clk_priv),
725 	.ops		= &rv1108_clk_ops,
726 	.bind		= rv1108_clk_bind,
727 	.of_to_plat	= rv1108_clk_of_to_plat,
728 	.probe		= rv1108_clk_probe,
729 };
730