1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * (C) Copyright 2017-2019 Rockchip Electronics Co., Ltd
4  */
5 #include <common.h>
6 #include <bitfield.h>
7 #include <clk-uclass.h>
8 #include <dm.h>
9 #include <div64.h>
10 #include <errno.h>
11 #include <log.h>
12 #include <malloc.h>
13 #include <syscon.h>
14 #include <asm/global_data.h>
15 #include <asm/io.h>
16 #include <asm/arch/cru_rk3308.h>
17 #include <asm/arch-rockchip/clock.h>
18 #include <asm/arch-rockchip/hardware.h>
19 #include <dm/device-internal.h>
20 #include <dm/lists.h>
21 #include <dt-bindings/clock/rk3308-cru.h>
22 #include <linux/bitops.h>
23 
24 DECLARE_GLOBAL_DATA_PTR;
25 
26 enum {
27 	VCO_MAX_HZ	= 3200U * 1000000,
28 	VCO_MIN_HZ	= 800 * 1000000,
29 	OUTPUT_MAX_HZ	= 3200U * 1000000,
30 	OUTPUT_MIN_HZ	= 24 * 1000000,
31 };
32 
33 #define DIV_TO_RATE(input_rate, div)    ((input_rate) / ((div) + 1))
34 
35 #define RK3308_CPUCLK_RATE(_rate, _aclk_div, _pclk_div)         \
36 {                                                               \
37 	.rate   = _rate##U,                                     \
38 	.aclk_div = _aclk_div,                                  \
39 	.pclk_div = _pclk_div,                                  \
40 }
41 
42 static struct rockchip_pll_rate_table rk3308_pll_rates[] = {
43 	/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
44 	RK3036_PLL_RATE(1300000000, 6, 325, 1, 1, 1, 0),
45 	RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
46 	RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0),
47 	RK3036_PLL_RATE(748000000, 2, 187, 3, 1, 1, 0),
48 };
49 
50 static struct rockchip_cpu_rate_table rk3308_cpu_rates[] = {
51 	RK3308_CPUCLK_RATE(1200000000, 1, 5),
52 	RK3308_CPUCLK_RATE(1008000000, 1, 5),
53 	RK3308_CPUCLK_RATE(816000000, 1, 3),
54 	RK3308_CPUCLK_RATE(600000000, 1, 3),
55 	RK3308_CPUCLK_RATE(408000000, 1, 1),
56 };
57 
58 static struct rockchip_pll_clock rk3308_pll_clks[] = {
59 	[APLL] = PLL(pll_rk3328, PLL_APLL, RK3308_PLL_CON(0),
60 		     RK3308_MODE_CON, 0, 10, 0, rk3308_pll_rates),
61 	[DPLL] = PLL(pll_rk3328, PLL_DPLL, RK3308_PLL_CON(8),
62 		     RK3308_MODE_CON, 2, 10, 0, NULL),
63 	[VPLL0] = PLL(pll_rk3328, PLL_VPLL0, RK3308_PLL_CON(16),
64 		      RK3308_MODE_CON, 4, 10, 0, NULL),
65 	[VPLL1] = PLL(pll_rk3328, PLL_VPLL1, RK3308_PLL_CON(24),
66 		      RK3308_MODE_CON, 6, 10, 0, NULL),
67 };
68 
rk3308_armclk_set_clk(struct rk3308_clk_priv * priv,ulong hz)69 static ulong rk3308_armclk_set_clk(struct rk3308_clk_priv *priv, ulong hz)
70 {
71 	struct rk3308_cru *cru = priv->cru;
72 	const struct rockchip_cpu_rate_table *rate;
73 	ulong old_rate;
74 
75 	rate = rockchip_get_cpu_settings(rk3308_cpu_rates, hz);
76 	if (!rate) {
77 		printf("%s unsupport rate\n", __func__);
78 		return -EINVAL;
79 	}
80 
81 	/*
82 	 * select apll as cpu/core clock pll source and
83 	 * set up dependent divisors for PERI and ACLK clocks.
84 	 * core hz : apll = 1:1
85 	 */
86 	old_rate = rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
87 					 priv->cru, APLL);
88 	if (old_rate > hz) {
89 		if (rockchip_pll_set_rate(&rk3308_pll_clks[APLL],
90 					  priv->cru, APLL, hz))
91 			return -EINVAL;
92 		rk_clrsetreg(&cru->clksel_con[0],
93 			     CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
94 			     CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
95 			     rate->aclk_div << CORE_ACLK_DIV_SHIFT |
96 			     rate->pclk_div << CORE_DBG_DIV_SHIFT |
97 			     CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
98 			     0 << CORE_DIV_CON_SHIFT);
99 	} else if (old_rate < hz) {
100 		rk_clrsetreg(&cru->clksel_con[0],
101 			     CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
102 			     CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
103 			     rate->aclk_div << CORE_ACLK_DIV_SHIFT |
104 			     rate->pclk_div << CORE_DBG_DIV_SHIFT |
105 			     CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
106 			     0 << CORE_DIV_CON_SHIFT);
107 		if (rockchip_pll_set_rate(&rk3308_pll_clks[APLL],
108 					  priv->cru, APLL, hz))
109 			return -EINVAL;
110 	}
111 
112 	return rockchip_pll_get_rate(&rk3308_pll_clks[APLL], priv->cru, APLL);
113 }
114 
rk3308_clk_get_pll_rate(struct rk3308_clk_priv * priv)115 static void rk3308_clk_get_pll_rate(struct rk3308_clk_priv *priv)
116 {
117 	if (!priv->dpll_hz)
118 		priv->dpll_hz = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL],
119 						      priv->cru, DPLL);
120 	if (!priv->vpll0_hz)
121 		priv->vpll0_hz = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL0],
122 						       priv->cru, VPLL0);
123 	if (!priv->vpll1_hz)
124 		priv->vpll1_hz = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL1],
125 						       priv->cru, VPLL1);
126 }
127 
rk3308_i2c_get_clk(struct clk * clk)128 static ulong rk3308_i2c_get_clk(struct clk *clk)
129 {
130 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
131 	struct rk3308_cru *cru = priv->cru;
132 	u32 div, con, con_id;
133 
134 	switch (clk->id) {
135 	case SCLK_I2C0:
136 		con_id = 25;
137 		break;
138 	case SCLK_I2C1:
139 		con_id = 26;
140 		break;
141 	case SCLK_I2C2:
142 		con_id = 27;
143 		break;
144 	case SCLK_I2C3:
145 		con_id = 28;
146 		break;
147 	default:
148 		printf("do not support this i2c bus\n");
149 		return -EINVAL;
150 	}
151 
152 	con = readl(&cru->clksel_con[con_id]);
153 	div = con >> CLK_I2C_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
154 
155 	return DIV_TO_RATE(priv->dpll_hz, div);
156 }
157 
rk3308_i2c_set_clk(struct clk * clk,uint hz)158 static ulong rk3308_i2c_set_clk(struct clk *clk, uint hz)
159 {
160 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
161 	struct rk3308_cru *cru = priv->cru;
162 	u32 src_clk_div, con_id;
163 
164 	src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz);
165 	assert(src_clk_div - 1 <= 127);
166 
167 	switch (clk->id) {
168 	case SCLK_I2C0:
169 		con_id = 25;
170 		break;
171 	case SCLK_I2C1:
172 		con_id = 26;
173 		break;
174 	case SCLK_I2C2:
175 		con_id = 27;
176 		break;
177 	case SCLK_I2C3:
178 		con_id = 28;
179 		break;
180 	default:
181 		printf("do not support this i2c bus\n");
182 		return -EINVAL;
183 	}
184 	rk_clrsetreg(&cru->clksel_con[con_id],
185 		     CLK_I2C_PLL_SEL_MASK | CLK_I2C_DIV_CON_MASK,
186 		     CLK_I2C_PLL_SEL_DPLL << CLK_I2C_PLL_SEL_SHIFT |
187 		     (src_clk_div - 1) << CLK_I2C_DIV_CON_SHIFT);
188 
189 	return rk3308_i2c_get_clk(clk);
190 }
191 
rk3308_mac_set_clk(struct clk * clk,uint hz)192 static ulong rk3308_mac_set_clk(struct clk *clk, uint hz)
193 {
194 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
195 	struct rk3308_cru *cru = priv->cru;
196 	u32 con = readl(&cru->clksel_con[43]);
197 	ulong pll_rate;
198 	u8 div;
199 
200 	if ((con >> MAC_PLL_SHIFT) & MAC_SEL_VPLL0)
201 		pll_rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL0],
202 						 priv->cru, VPLL0);
203 	else if ((con >> MAC_PLL_SHIFT) & MAC_SEL_VPLL1)
204 		pll_rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL1],
205 						 priv->cru, VPLL1);
206 	else
207 		pll_rate = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL],
208 						 priv->cru, DPLL);
209 
210 	/*default set 50MHZ for gmac*/
211 	if (!hz)
212 		hz = 50000000;
213 
214 	div = DIV_ROUND_UP(pll_rate, hz) - 1;
215 	assert(div < 32);
216 	rk_clrsetreg(&cru->clksel_con[43], MAC_DIV_MASK,
217 		     div << MAC_DIV_SHIFT);
218 
219 	return DIV_TO_RATE(pll_rate, div);
220 }
221 
rk3308_mac_set_speed_clk(struct clk * clk,uint hz)222 static int rk3308_mac_set_speed_clk(struct clk *clk, uint hz)
223 {
224 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
225 	struct rk3308_cru *cru = priv->cru;
226 
227 	if (hz != 2500000 && hz != 25000000) {
228 		debug("Unsupported mac speed:%d\n", hz);
229 		return -EINVAL;
230 	}
231 
232 	rk_clrsetreg(&cru->clksel_con[43], MAC_CLK_SPEED_SEL_MASK,
233 		     ((hz == 2500000) ? 0 : 1) << MAC_CLK_SPEED_SEL_SHIFT);
234 
235 	return 0;
236 }
237 
rk3308_mmc_get_clk(struct clk * clk)238 static ulong rk3308_mmc_get_clk(struct clk *clk)
239 {
240 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
241 	struct rk3308_cru *cru = priv->cru;
242 	u32 div, con, con_id;
243 
244 	switch (clk->id) {
245 	case HCLK_SDMMC:
246 	case SCLK_SDMMC:
247 		con_id = 39;
248 		break;
249 	case HCLK_EMMC:
250 	case SCLK_EMMC:
251 	case SCLK_EMMC_SAMPLE:
252 		con_id = 41;
253 		break;
254 	default:
255 		return -EINVAL;
256 	}
257 
258 	con = readl(&cru->clksel_con[con_id]);
259 	div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT;
260 
261 	if ((con & EMMC_PLL_MASK) >> EMMC_PLL_SHIFT
262 	    == EMMC_SEL_24M)
263 		return DIV_TO_RATE(OSC_HZ, div) / 2;
264 	else
265 		return DIV_TO_RATE(priv->vpll0_hz, div) / 2;
266 }
267 
rk3308_mmc_set_clk(struct clk * clk,ulong set_rate)268 static ulong rk3308_mmc_set_clk(struct clk *clk, ulong set_rate)
269 {
270 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
271 	struct rk3308_cru *cru = priv->cru;
272 	int src_clk_div;
273 	u32 con_id;
274 
275 	switch (clk->id) {
276 	case HCLK_SDMMC:
277 	case SCLK_SDMMC:
278 		con_id = 39;
279 		break;
280 	case HCLK_EMMC:
281 	case SCLK_EMMC:
282 		con_id = 41;
283 		break;
284 	default:
285 		return -EINVAL;
286 	}
287 	/* Select clk_sdmmc/emmc source from VPLL0 by default */
288 	/* mmc clock defaulg div 2 internal, need provide double in cru */
289 	src_clk_div = DIV_ROUND_UP(priv->vpll0_hz / 2, set_rate);
290 
291 	if (src_clk_div > 127) {
292 		/* use 24MHz source for 400KHz clock */
293 		src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate);
294 		rk_clrsetreg(&cru->clksel_con[con_id],
295 			     EMMC_PLL_MASK | EMMC_DIV_MASK | EMMC_CLK_SEL_MASK,
296 			     EMMC_CLK_SEL_EMMC << EMMC_CLK_SEL_SHIFT |
297 			     EMMC_SEL_24M << EMMC_PLL_SHIFT |
298 			     (src_clk_div - 1) << EMMC_DIV_SHIFT);
299 	} else {
300 		rk_clrsetreg(&cru->clksel_con[con_id],
301 			     EMMC_PLL_MASK | EMMC_DIV_MASK | EMMC_CLK_SEL_MASK,
302 			     EMMC_CLK_SEL_EMMC << EMMC_CLK_SEL_SHIFT |
303 			     EMMC_SEL_VPLL0 << EMMC_PLL_SHIFT |
304 			     (src_clk_div - 1) << EMMC_DIV_SHIFT);
305 	}
306 
307 	return rk3308_mmc_get_clk(clk);
308 }
309 
rk3308_saradc_get_clk(struct clk * clk)310 static ulong rk3308_saradc_get_clk(struct clk *clk)
311 {
312 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
313 	struct rk3308_cru *cru = priv->cru;
314 	u32 div, con;
315 
316 	con = readl(&cru->clksel_con[34]);
317 	div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK;
318 
319 	return DIV_TO_RATE(OSC_HZ, div);
320 }
321 
rk3308_saradc_set_clk(struct clk * clk,uint hz)322 static ulong rk3308_saradc_set_clk(struct clk *clk, uint hz)
323 {
324 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
325 	struct rk3308_cru *cru = priv->cru;
326 	int src_clk_div;
327 
328 	src_clk_div = DIV_ROUND_UP(OSC_HZ, hz);
329 	assert(src_clk_div - 1 <= 2047);
330 
331 	rk_clrsetreg(&cru->clksel_con[34],
332 		     CLK_SARADC_DIV_CON_MASK,
333 		     (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT);
334 
335 	return rk3308_saradc_get_clk(clk);
336 }
337 
rk3308_tsadc_get_clk(struct clk * clk)338 static ulong rk3308_tsadc_get_clk(struct clk *clk)
339 {
340 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
341 	struct rk3308_cru *cru = priv->cru;
342 	u32 div, con;
343 
344 	con = readl(&cru->clksel_con[33]);
345 	div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK;
346 
347 	return DIV_TO_RATE(OSC_HZ, div);
348 }
349 
rk3308_tsadc_set_clk(struct clk * clk,uint hz)350 static ulong rk3308_tsadc_set_clk(struct clk *clk, uint hz)
351 {
352 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
353 	struct rk3308_cru *cru = priv->cru;
354 	int src_clk_div;
355 
356 	src_clk_div = DIV_ROUND_UP(OSC_HZ, hz);
357 	assert(src_clk_div - 1 <= 2047);
358 
359 	rk_clrsetreg(&cru->clksel_con[33],
360 		     CLK_SARADC_DIV_CON_MASK,
361 		     (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT);
362 
363 	return rk3308_tsadc_get_clk(clk);
364 }
365 
rk3308_spi_get_clk(struct clk * clk)366 static ulong rk3308_spi_get_clk(struct clk *clk)
367 {
368 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
369 	struct rk3308_cru *cru = priv->cru;
370 	u32 div, con, con_id;
371 
372 	switch (clk->id) {
373 	case SCLK_SPI0:
374 		con_id = 30;
375 		break;
376 	case SCLK_SPI1:
377 		con_id = 31;
378 		break;
379 	case SCLK_SPI2:
380 		con_id = 32;
381 		break;
382 	default:
383 		printf("do not support this spi bus\n");
384 		return -EINVAL;
385 	}
386 
387 	con = readl(&cru->clksel_con[con_id]);
388 	div = con >> CLK_SPI_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK;
389 
390 	return DIV_TO_RATE(priv->dpll_hz, div);
391 }
392 
rk3308_spi_set_clk(struct clk * clk,uint hz)393 static ulong rk3308_spi_set_clk(struct clk *clk, uint hz)
394 {
395 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
396 	struct rk3308_cru *cru = priv->cru;
397 	u32 src_clk_div, con_id;
398 
399 	src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz);
400 	assert(src_clk_div - 1 <= 127);
401 
402 	switch (clk->id) {
403 	case SCLK_SPI0:
404 		con_id = 30;
405 		break;
406 	case SCLK_SPI1:
407 		con_id = 31;
408 		break;
409 	case SCLK_SPI2:
410 		con_id = 32;
411 		break;
412 	default:
413 		printf("do not support this spi bus\n");
414 		return -EINVAL;
415 	}
416 
417 	rk_clrsetreg(&cru->clksel_con[con_id],
418 		     CLK_SPI_PLL_SEL_MASK | CLK_SPI_DIV_CON_MASK,
419 		     CLK_SPI_PLL_SEL_DPLL << CLK_SPI_PLL_SEL_SHIFT |
420 		     (src_clk_div - 1) << CLK_SPI_DIV_CON_SHIFT);
421 
422 	return rk3308_spi_get_clk(clk);
423 }
424 
rk3308_pwm_get_clk(struct clk * clk)425 static ulong rk3308_pwm_get_clk(struct clk *clk)
426 {
427 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
428 	struct rk3308_cru *cru = priv->cru;
429 	u32 div, con;
430 
431 	con = readl(&cru->clksel_con[29]);
432 	div = con >> CLK_PWM_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK;
433 
434 	return DIV_TO_RATE(priv->dpll_hz, div);
435 }
436 
rk3308_pwm_set_clk(struct clk * clk,uint hz)437 static ulong rk3308_pwm_set_clk(struct clk *clk, uint hz)
438 {
439 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
440 	struct rk3308_cru *cru = priv->cru;
441 	int src_clk_div;
442 
443 	src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz);
444 	assert(src_clk_div - 1 <= 127);
445 
446 	rk_clrsetreg(&cru->clksel_con[29],
447 		     CLK_PWM_PLL_SEL_MASK | CLK_PWM_DIV_CON_MASK,
448 		     CLK_PWM_PLL_SEL_DPLL << CLK_PWM_PLL_SEL_SHIFT |
449 		     (src_clk_div - 1) << CLK_PWM_DIV_CON_SHIFT);
450 
451 	return rk3308_pwm_get_clk(clk);
452 }
453 
rk3308_vop_get_clk(struct clk * clk)454 static ulong rk3308_vop_get_clk(struct clk *clk)
455 {
456 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
457 	struct rk3308_cru *cru = priv->cru;
458 	u32 div, pll_sel, vol_sel, con, parent;
459 
460 	con = readl(&cru->clksel_con[8]);
461 	vol_sel = (con & DCLK_VOP_SEL_MASK) >> DCLK_VOP_SEL_SHIFT;
462 	pll_sel = (con & DCLK_VOP_PLL_SEL_MASK) >> DCLK_VOP_PLL_SEL_SHIFT;
463 	div = con & DCLK_VOP_DIV_MASK;
464 
465 	if (vol_sel == DCLK_VOP_SEL_24M) {
466 		parent = OSC_HZ;
467 	} else if (vol_sel == DCLK_VOP_SEL_DIVOUT) {
468 		switch (pll_sel) {
469 		case DCLK_VOP_PLL_SEL_DPLL:
470 			parent = priv->dpll_hz;
471 			break;
472 		case DCLK_VOP_PLL_SEL_VPLL0:
473 			parent = priv->vpll0_hz;
474 			break;
475 		case DCLK_VOP_PLL_SEL_VPLL1:
476 			parent = priv->vpll0_hz;
477 			break;
478 		default:
479 			printf("do not support this vop pll sel\n");
480 			return -EINVAL;
481 		}
482 	} else {
483 		printf("do not support this vop sel\n");
484 		return -EINVAL;
485 	}
486 
487 	return DIV_TO_RATE(parent, div);
488 }
489 
rk3308_vop_set_clk(struct clk * clk,ulong hz)490 static ulong rk3308_vop_set_clk(struct clk *clk, ulong hz)
491 {
492 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
493 	struct rk3308_cru *cru = priv->cru;
494 	ulong pll_rate, now, best_rate = 0;
495 	u32 i, div, best_div = 0, best_sel = 0;
496 
497 	for (i = 0; i <= DCLK_VOP_PLL_SEL_VPLL1; i++) {
498 		switch (i) {
499 		case DCLK_VOP_PLL_SEL_DPLL:
500 			pll_rate = priv->dpll_hz;
501 			break;
502 		case DCLK_VOP_PLL_SEL_VPLL0:
503 			pll_rate = priv->vpll0_hz;
504 			break;
505 		case DCLK_VOP_PLL_SEL_VPLL1:
506 			pll_rate = priv->vpll1_hz;
507 			break;
508 		default:
509 			printf("do not support this vop pll sel\n");
510 			return -EINVAL;
511 		}
512 
513 		div = DIV_ROUND_UP(pll_rate, hz);
514 		if (div > 255)
515 			continue;
516 		now = pll_rate / div;
517 		if (abs(hz - now) < abs(hz - best_rate)) {
518 			best_rate = now;
519 			best_div = div;
520 			best_sel = i;
521 		}
522 		debug("pll_rate=%lu, best_rate=%lu, best_div=%u, best_sel=%u\n",
523 		      pll_rate, best_rate, best_div, best_sel);
524 	}
525 
526 	if (best_rate != hz && hz == OSC_HZ) {
527 		rk_clrsetreg(&cru->clksel_con[8],
528 			     DCLK_VOP_SEL_MASK,
529 			     DCLK_VOP_SEL_24M << DCLK_VOP_SEL_SHIFT);
530 	} else if (best_rate) {
531 		rk_clrsetreg(&cru->clksel_con[8],
532 			     DCLK_VOP_SEL_MASK | DCLK_VOP_PLL_SEL_MASK |
533 			     DCLK_VOP_DIV_MASK,
534 			     DCLK_VOP_SEL_DIVOUT << DCLK_VOP_SEL_SHIFT |
535 			     best_sel << DCLK_VOP_PLL_SEL_SHIFT |
536 			     (best_div - 1) << DCLK_VOP_DIV_SHIFT);
537 	} else {
538 		printf("do not support this vop freq\n");
539 		return -EINVAL;
540 	}
541 
542 	return rk3308_vop_get_clk(clk);
543 }
544 
rk3308_bus_get_clk(struct rk3308_clk_priv * priv,ulong clk_id)545 static ulong rk3308_bus_get_clk(struct rk3308_clk_priv *priv, ulong clk_id)
546 {
547 	struct rk3308_cru *cru = priv->cru;
548 	u32 div, con, parent = priv->dpll_hz;
549 
550 	switch (clk_id) {
551 	case ACLK_BUS:
552 		con = readl(&cru->clksel_con[5]);
553 		div = (con & BUS_ACLK_DIV_MASK) >> BUS_ACLK_DIV_SHIFT;
554 		break;
555 	case HCLK_BUS:
556 		con = readl(&cru->clksel_con[6]);
557 		div = (con & BUS_HCLK_DIV_MASK) >> BUS_HCLK_DIV_SHIFT;
558 		break;
559 	case PCLK_BUS:
560 	case PCLK_WDT:
561 		con = readl(&cru->clksel_con[6]);
562 		div = (con & BUS_PCLK_DIV_MASK) >> BUS_PCLK_DIV_SHIFT;
563 		break;
564 	default:
565 		return -ENOENT;
566 	}
567 
568 	return DIV_TO_RATE(parent, div);
569 }
570 
rk3308_bus_set_clk(struct rk3308_clk_priv * priv,ulong clk_id,ulong hz)571 static ulong rk3308_bus_set_clk(struct rk3308_clk_priv *priv, ulong clk_id,
572 				ulong hz)
573 {
574 	struct rk3308_cru *cru = priv->cru;
575 	int src_clk_div;
576 
577 	src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz);
578 	assert(src_clk_div - 1 <= 31);
579 
580 	/*
581 	 * select dpll as pd_bus bus clock source and
582 	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
583 	 */
584 	switch (clk_id) {
585 	case ACLK_BUS:
586 		rk_clrsetreg(&cru->clksel_con[5],
587 			     BUS_PLL_SEL_MASK | BUS_ACLK_DIV_MASK,
588 			     BUS_PLL_SEL_DPLL << BUS_PLL_SEL_SHIFT |
589 			     (src_clk_div - 1) << BUS_ACLK_DIV_SHIFT);
590 		break;
591 	case HCLK_BUS:
592 		rk_clrsetreg(&cru->clksel_con[6],
593 			     BUS_HCLK_DIV_MASK,
594 			     (src_clk_div - 1) << BUS_HCLK_DIV_SHIFT);
595 		break;
596 	case PCLK_BUS:
597 		rk_clrsetreg(&cru->clksel_con[6],
598 			     BUS_PCLK_DIV_MASK,
599 			     (src_clk_div - 1) << BUS_PCLK_DIV_SHIFT);
600 		break;
601 	default:
602 		printf("do not support this bus freq\n");
603 		return -EINVAL;
604 	}
605 
606 	return rk3308_bus_get_clk(priv, clk_id);
607 }
608 
rk3308_peri_get_clk(struct rk3308_clk_priv * priv,ulong clk_id)609 static ulong rk3308_peri_get_clk(struct rk3308_clk_priv *priv, ulong clk_id)
610 {
611 	struct rk3308_cru *cru = priv->cru;
612 	u32 div, con, parent = priv->dpll_hz;
613 
614 	switch (clk_id) {
615 	case ACLK_PERI:
616 		con = readl(&cru->clksel_con[36]);
617 		div = (con & PERI_ACLK_DIV_MASK) >> PERI_ACLK_DIV_SHIFT;
618 		break;
619 	case HCLK_PERI:
620 		con = readl(&cru->clksel_con[37]);
621 		div = (con & PERI_HCLK_DIV_MASK) >> PERI_HCLK_DIV_SHIFT;
622 		break;
623 	case PCLK_PERI:
624 		con = readl(&cru->clksel_con[37]);
625 		div = (con & PERI_PCLK_DIV_MASK) >> PERI_PCLK_DIV_SHIFT;
626 		break;
627 	default:
628 		return -ENOENT;
629 	}
630 
631 	return DIV_TO_RATE(parent, div);
632 }
633 
rk3308_peri_set_clk(struct rk3308_clk_priv * priv,ulong clk_id,ulong hz)634 static ulong rk3308_peri_set_clk(struct rk3308_clk_priv *priv, ulong clk_id,
635 				 ulong hz)
636 {
637 	struct rk3308_cru *cru = priv->cru;
638 	int src_clk_div;
639 
640 	src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz);
641 	assert(src_clk_div - 1 <= 31);
642 
643 	/*
644 	 * select dpll as pd_peri bus clock source and
645 	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
646 	 */
647 	switch (clk_id) {
648 	case ACLK_PERI:
649 		rk_clrsetreg(&cru->clksel_con[36],
650 			     PERI_PLL_SEL_MASK | PERI_ACLK_DIV_MASK,
651 			     PERI_PLL_DPLL << PERI_PLL_SEL_SHIFT |
652 			     (src_clk_div - 1) << PERI_ACLK_DIV_SHIFT);
653 		break;
654 	case HCLK_PERI:
655 		rk_clrsetreg(&cru->clksel_con[37],
656 			     PERI_HCLK_DIV_MASK,
657 			     (src_clk_div - 1) << PERI_HCLK_DIV_SHIFT);
658 		break;
659 	case PCLK_PERI:
660 		rk_clrsetreg(&cru->clksel_con[37],
661 			     PERI_PCLK_DIV_MASK,
662 			     (src_clk_div - 1) << PERI_PCLK_DIV_SHIFT);
663 		break;
664 	default:
665 		printf("do not support this peri freq\n");
666 		return -EINVAL;
667 	}
668 
669 	return rk3308_peri_get_clk(priv, clk_id);
670 }
671 
rk3308_audio_get_clk(struct rk3308_clk_priv * priv,ulong clk_id)672 static ulong rk3308_audio_get_clk(struct rk3308_clk_priv *priv, ulong clk_id)
673 {
674 	struct rk3308_cru *cru = priv->cru;
675 	u32 div, con, parent = priv->vpll0_hz;
676 
677 	switch (clk_id) {
678 	case HCLK_AUDIO:
679 		con = readl(&cru->clksel_con[45]);
680 		div = (con & AUDIO_HCLK_DIV_MASK) >> AUDIO_HCLK_DIV_SHIFT;
681 		break;
682 	case PCLK_AUDIO:
683 		con = readl(&cru->clksel_con[45]);
684 		div = (con & AUDIO_PCLK_DIV_MASK) >> AUDIO_PCLK_DIV_SHIFT;
685 		break;
686 	default:
687 		return -ENOENT;
688 	}
689 
690 	return DIV_TO_RATE(parent, div);
691 }
692 
rk3308_audio_set_clk(struct rk3308_clk_priv * priv,ulong clk_id,ulong hz)693 static ulong rk3308_audio_set_clk(struct rk3308_clk_priv *priv, ulong clk_id,
694 				  ulong hz)
695 {
696 	struct rk3308_cru *cru = priv->cru;
697 	int src_clk_div;
698 
699 	src_clk_div = DIV_ROUND_UP(priv->vpll0_hz, hz);
700 	assert(src_clk_div - 1 <= 31);
701 
702 	/*
703 	 * select vpll0 as audio bus clock source and
704 	 * set up dependent divisors for HCLK and PCLK clocks.
705 	 */
706 	switch (clk_id) {
707 	case HCLK_AUDIO:
708 		rk_clrsetreg(&cru->clksel_con[45],
709 			     AUDIO_PLL_SEL_MASK | AUDIO_HCLK_DIV_MASK,
710 			     AUDIO_PLL_VPLL0 << AUDIO_PLL_SEL_SHIFT |
711 			     (src_clk_div - 1) << AUDIO_HCLK_DIV_SHIFT);
712 		break;
713 	case PCLK_AUDIO:
714 		rk_clrsetreg(&cru->clksel_con[45],
715 			     AUDIO_PLL_SEL_MASK | AUDIO_PCLK_DIV_MASK,
716 			     AUDIO_PLL_VPLL0 << AUDIO_PLL_SEL_SHIFT |
717 			     (src_clk_div - 1) << AUDIO_PCLK_DIV_SHIFT);
718 		break;
719 	default:
720 		printf("do not support this audio freq\n");
721 		return -EINVAL;
722 	}
723 
724 	return rk3308_peri_get_clk(priv, clk_id);
725 }
726 
rk3308_crypto_get_clk(struct rk3308_clk_priv * priv,ulong clk_id)727 static ulong rk3308_crypto_get_clk(struct rk3308_clk_priv *priv, ulong clk_id)
728 {
729 	struct rk3308_cru *cru = priv->cru;
730 	u32 div, con, parent;
731 
732 	switch (clk_id) {
733 	case SCLK_CRYPTO:
734 		con = readl(&cru->clksel_con[7]);
735 		div = (con & CRYPTO_DIV_MASK) >> CRYPTO_DIV_SHIFT;
736 		parent = priv->vpll0_hz;
737 		break;
738 	case SCLK_CRYPTO_APK:
739 		con = readl(&cru->clksel_con[7]);
740 		div = (con & CRYPTO_APK_DIV_MASK) >> CRYPTO_APK_DIV_SHIFT;
741 		parent = priv->vpll0_hz;
742 		break;
743 	default:
744 		return -ENOENT;
745 	}
746 
747 	return DIV_TO_RATE(parent, div);
748 }
749 
rk3308_crypto_set_clk(struct rk3308_clk_priv * priv,ulong clk_id,ulong hz)750 static ulong rk3308_crypto_set_clk(struct rk3308_clk_priv *priv, ulong clk_id,
751 				   ulong hz)
752 {
753 	struct rk3308_cru *cru = priv->cru;
754 	int src_clk_div;
755 
756 	src_clk_div = DIV_ROUND_UP(priv->vpll0_hz, hz);
757 	assert(src_clk_div - 1 <= 31);
758 
759 	/*
760 	 * select gpll as crypto clock source and
761 	 * set up dependent divisors for crypto clocks.
762 	 */
763 	switch (clk_id) {
764 	case SCLK_CRYPTO:
765 		rk_clrsetreg(&cru->clksel_con[7],
766 			     CRYPTO_PLL_SEL_MASK | CRYPTO_DIV_MASK,
767 			     CRYPTO_PLL_SEL_VPLL0 << CRYPTO_PLL_SEL_SHIFT |
768 			     (src_clk_div - 1) << CRYPTO_DIV_SHIFT);
769 		break;
770 	case SCLK_CRYPTO_APK:
771 		rk_clrsetreg(&cru->clksel_con[7],
772 			     CRYPTO_APK_PLL_SEL_MASK | CRYPTO_APK_DIV_MASK,
773 			     CRYPTO_PLL_SEL_VPLL0 << CRYPTO_APK_SEL_SHIFT |
774 			     (src_clk_div - 1) << CRYPTO_APK_DIV_SHIFT);
775 		break;
776 	default:
777 		printf("do not support this peri freq\n");
778 		return -EINVAL;
779 	}
780 
781 	return rk3308_crypto_get_clk(priv, clk_id);
782 }
783 
rk3308_clk_get_rate(struct clk * clk)784 static ulong rk3308_clk_get_rate(struct clk *clk)
785 {
786 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
787 	ulong rate = 0;
788 
789 	debug("%s id:%ld\n", __func__, clk->id);
790 
791 	switch (clk->id) {
792 	case PLL_APLL:
793 	case ARMCLK:
794 		rate = rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
795 					     priv->cru, APLL);
796 		break;
797 	case PLL_DPLL:
798 		rate = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL],
799 					     priv->cru, DPLL);
800 		break;
801 	case PLL_VPLL0:
802 		rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL0],
803 					     priv->cru, VPLL0);
804 		break;
805 	case PLL_VPLL1:
806 		rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL1],
807 					     priv->cru, VPLL1);
808 		break;
809 	case HCLK_SDMMC:
810 	case HCLK_EMMC:
811 	case SCLK_SDMMC:
812 	case SCLK_EMMC:
813 	case SCLK_EMMC_SAMPLE:
814 		rate = rk3308_mmc_get_clk(clk);
815 		break;
816 	case SCLK_I2C0:
817 	case SCLK_I2C1:
818 	case SCLK_I2C2:
819 	case SCLK_I2C3:
820 		rate = rk3308_i2c_get_clk(clk);
821 		break;
822 	case SCLK_SARADC:
823 		rate = rk3308_saradc_get_clk(clk);
824 		break;
825 	case SCLK_TSADC:
826 		rate = rk3308_tsadc_get_clk(clk);
827 		break;
828 	case SCLK_SPI0:
829 	case SCLK_SPI1:
830 		rate = rk3308_spi_get_clk(clk);
831 		break;
832 	case SCLK_PWM0:
833 		rate = rk3308_pwm_get_clk(clk);
834 		break;
835 	case DCLK_VOP:
836 		rate = rk3308_vop_get_clk(clk);
837 		break;
838 	case ACLK_BUS:
839 	case HCLK_BUS:
840 	case PCLK_BUS:
841 	case PCLK_WDT:
842 		rate = rk3308_bus_get_clk(priv, clk->id);
843 		break;
844 	case ACLK_PERI:
845 	case HCLK_PERI:
846 	case PCLK_PERI:
847 		rate = rk3308_peri_get_clk(priv, clk->id);
848 		break;
849 	case HCLK_AUDIO:
850 	case PCLK_AUDIO:
851 		rate = rk3308_audio_get_clk(priv, clk->id);
852 		break;
853 	case SCLK_CRYPTO:
854 	case SCLK_CRYPTO_APK:
855 		rate = rk3308_crypto_get_clk(priv, clk->id);
856 		break;
857 	default:
858 		return -ENOENT;
859 	}
860 
861 	return rate;
862 }
863 
rk3308_clk_set_rate(struct clk * clk,ulong rate)864 static ulong rk3308_clk_set_rate(struct clk *clk, ulong rate)
865 {
866 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
867 	ulong ret = 0;
868 
869 	debug("%s %ld %ld\n", __func__, clk->id, rate);
870 
871 	switch (clk->id) {
872 	case PLL_DPLL:
873 		ret = rockchip_pll_set_rate(&rk3308_pll_clks[DPLL], priv->cru,
874 					    DPLL, rate);
875 		priv->dpll_hz = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL],
876 						      priv->cru, DPLL);
877 		break;
878 	case ARMCLK:
879 		if (priv->armclk_hz)
880 			rk3308_armclk_set_clk(priv, rate);
881 		priv->armclk_hz = rate;
882 		break;
883 	case HCLK_SDMMC:
884 	case HCLK_EMMC:
885 	case SCLK_SDMMC:
886 	case SCLK_EMMC:
887 		ret = rk3308_mmc_set_clk(clk, rate);
888 		break;
889 	case SCLK_I2C0:
890 	case SCLK_I2C1:
891 	case SCLK_I2C2:
892 	case SCLK_I2C3:
893 		ret = rk3308_i2c_set_clk(clk, rate);
894 		break;
895 	case SCLK_MAC:
896 		ret = rk3308_mac_set_clk(clk, rate);
897 		break;
898 	case SCLK_MAC_RMII:
899 		ret = rk3308_mac_set_speed_clk(clk, rate);
900 		break;
901 	case SCLK_SARADC:
902 		ret = rk3308_saradc_set_clk(clk, rate);
903 		break;
904 	case SCLK_TSADC:
905 		ret = rk3308_tsadc_set_clk(clk, rate);
906 		break;
907 	case SCLK_SPI0:
908 	case SCLK_SPI1:
909 		ret = rk3308_spi_set_clk(clk, rate);
910 		break;
911 	case SCLK_PWM0:
912 		ret = rk3308_pwm_set_clk(clk, rate);
913 		break;
914 	case DCLK_VOP:
915 		ret = rk3308_vop_set_clk(clk, rate);
916 		break;
917 	case ACLK_BUS:
918 	case HCLK_BUS:
919 	case PCLK_BUS:
920 		rate = rk3308_bus_set_clk(priv, clk->id, rate);
921 		break;
922 	case ACLK_PERI:
923 	case HCLK_PERI:
924 	case PCLK_PERI:
925 		rate = rk3308_peri_set_clk(priv, clk->id, rate);
926 		break;
927 	case HCLK_AUDIO:
928 	case PCLK_AUDIO:
929 		rate = rk3308_audio_set_clk(priv, clk->id, rate);
930 		break;
931 	case SCLK_CRYPTO:
932 	case SCLK_CRYPTO_APK:
933 		ret = rk3308_crypto_set_clk(priv, clk->id, rate);
934 		break;
935 	default:
936 		return -ENOENT;
937 	}
938 
939 	return ret;
940 }
941 
942 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
rk3308_mac_set_parent(struct clk * clk,struct clk * parent)943 static int __maybe_unused rk3308_mac_set_parent(struct clk *clk, struct clk *parent)
944 {
945 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
946 
947 	/*
948 	 * If the requested parent is in the same clock-controller and
949 	 * the id is SCLK_MAC_SRC, switch to the internal clock.
950 	 */
951 	if (parent->id == SCLK_MAC_SRC) {
952 		debug("%s: switching RMII to SCLK_MAC\n", __func__);
953 		rk_clrreg(&priv->cru->clksel_con[43], BIT(14));
954 	} else {
955 		debug("%s: switching RMII to CLKIN\n", __func__);
956 		rk_setreg(&priv->cru->clksel_con[43], BIT(14));
957 	}
958 
959 	return 0;
960 }
961 
rk3308_clk_set_parent(struct clk * clk,struct clk * parent)962 static int __maybe_unused rk3308_clk_set_parent(struct clk *clk, struct clk *parent)
963 {
964 	switch (clk->id) {
965 	case SCLK_MAC:
966 		return rk3308_mac_set_parent(clk, parent);
967 	default:
968 		break;
969 	}
970 
971 	debug("%s: unsupported clk %ld\n", __func__, clk->id);
972 	return -ENOENT;
973 }
974 #endif
975 
976 static struct clk_ops rk3308_clk_ops = {
977 	.get_rate = rk3308_clk_get_rate,
978 	.set_rate = rk3308_clk_set_rate,
979 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
980 	.set_parent = rk3308_clk_set_parent,
981 #endif
982 };
983 
rk3308_clk_init(struct udevice * dev)984 static void rk3308_clk_init(struct udevice *dev)
985 {
986 	struct rk3308_clk_priv *priv = dev_get_priv(dev);
987 	int ret;
988 
989 	if (rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
990 				  priv->cru, APLL) != APLL_HZ) {
991 		ret = rk3308_armclk_set_clk(priv, APLL_HZ);
992 		if (ret < 0)
993 			printf("%s failed to set armclk rate\n", __func__);
994 	}
995 
996 	rk3308_clk_get_pll_rate(priv);
997 
998 	rk3308_bus_set_clk(priv, ACLK_BUS, BUS_ACLK_HZ);
999 	rk3308_bus_set_clk(priv, HCLK_BUS, BUS_HCLK_HZ);
1000 	rk3308_bus_set_clk(priv, PCLK_BUS, BUS_PCLK_HZ);
1001 
1002 	rk3308_peri_set_clk(priv, ACLK_PERI, PERI_ACLK_HZ);
1003 	rk3308_peri_set_clk(priv, HCLK_PERI, PERI_HCLK_HZ);
1004 	rk3308_peri_set_clk(priv, PCLK_PERI, PERI_PCLK_HZ);
1005 
1006 	rk3308_audio_set_clk(priv, HCLK_AUDIO, AUDIO_HCLK_HZ);
1007 	rk3308_audio_set_clk(priv, PCLK_AUDIO, AUDIO_PCLK_HZ);
1008 }
1009 
rk3308_clk_probe(struct udevice * dev)1010 static int rk3308_clk_probe(struct udevice *dev)
1011 {
1012 	int ret;
1013 
1014 	rk3308_clk_init(dev);
1015 
1016 	/* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
1017 	ret = clk_set_defaults(dev, 1);
1018 	if (ret)
1019 		debug("%s clk_set_defaults failed %d\n", __func__, ret);
1020 
1021 	return ret;
1022 }
1023 
rk3308_clk_of_to_plat(struct udevice * dev)1024 static int rk3308_clk_of_to_plat(struct udevice *dev)
1025 {
1026 	struct rk3308_clk_priv *priv = dev_get_priv(dev);
1027 
1028 	priv->cru = dev_read_addr_ptr(dev);
1029 
1030 	return 0;
1031 }
1032 
rk3308_clk_bind(struct udevice * dev)1033 static int rk3308_clk_bind(struct udevice *dev)
1034 {
1035 	int ret;
1036 	struct udevice *sys_child;
1037 	struct sysreset_reg *priv;
1038 
1039 	/* The reset driver does not have a device node, so bind it here */
1040 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
1041 				 &sys_child);
1042 	if (ret) {
1043 		debug("Warning: No sysreset driver: ret=%d\n", ret);
1044 	} else {
1045 		priv = malloc(sizeof(struct sysreset_reg));
1046 		priv->glb_srst_fst_value = offsetof(struct rk3308_cru,
1047 						    glb_srst_fst);
1048 		priv->glb_srst_snd_value = offsetof(struct rk3308_cru,
1049 						    glb_srst_snd);
1050 		dev_set_priv(sys_child, priv);
1051 	}
1052 
1053 #if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
1054 	ret = offsetof(struct rk3308_cru, softrst_con[0]);
1055 	ret = rockchip_reset_bind(dev, ret, 12);
1056 	if (ret)
1057 		debug("Warning: software reset driver bind faile\n");
1058 #endif
1059 
1060 	return 0;
1061 }
1062 
1063 static const struct udevice_id rk3308_clk_ids[] = {
1064 	{ .compatible = "rockchip,rk3308-cru" },
1065 	{ }
1066 };
1067 
1068 U_BOOT_DRIVER(rockchip_rk3308_cru) = {
1069 	.name		= "rockchip_rk3308_cru",
1070 	.id		= UCLASS_CLK,
1071 	.of_match	= rk3308_clk_ids,
1072 	.priv_auto	= sizeof(struct rk3308_clk_priv),
1073 	.of_to_plat = rk3308_clk_of_to_plat,
1074 	.ops		= &rk3308_clk_ops,
1075 	.bind		= rk3308_clk_bind,
1076 	.probe		= rk3308_clk_probe,
1077 };
1078