xref: /rk3399_rockchip-uboot/drivers/clk/rockchip/clk_rk1808.c (revision ed73b76733ce7cd243da2ebec965b0e1fca8924d)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd
4  */
5 
6 #include <common.h>
7 #include <bitfield.h>
8 #include <clk-uclass.h>
9 #include <dm.h>
10 #include <errno.h>
11 #include <syscon.h>
12 #include <clk.h>
13 #include <asm/arch/clock.h>
14 #include <asm/arch/cru_rk1808.h>
15 #include <asm/arch/hardware.h>
16 #include <asm/io.h>
17 #include <dm/lists.h>
18 #include <dt-bindings/clock/rk1808-cru.h>
19 #include <div64.h>
20 
21 DECLARE_GLOBAL_DATA_PTR;
22 
23 #define RK1808_CPUCLK_RATE(_rate, _aclk_div, _pclk_div)		\
24 {								\
25 	.rate	= _rate##U,					\
26 	.aclk_div = _aclk_div,					\
27 	.pclk_div = _pclk_div,					\
28 }
29 
30 #define DIV_TO_RATE(input_rate, div)    ((input_rate) / ((div) + 1))
31 
32 static struct rockchip_pll_rate_table rk1808_pll_rates[] = {
33 	/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
34 	RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
35 	RK3036_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0),
36 	RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0),
37 	RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
38 	RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0),
39 	RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0),
40 	RK3036_PLL_RATE(800000000, 6, 400, 2, 1, 1, 0),
41 	RK3036_PLL_RATE(600000000, 1, 75, 3, 1, 1, 0),
42 	RK3036_PLL_RATE(594000000, 2, 99, 2, 1, 1, 0),
43 	RK3036_PLL_RATE(500000000, 6, 250, 2, 1, 1, 0),
44 	RK3036_PLL_RATE(200000000, 1, 200, 6, 4, 1, 0),
45 	RK3036_PLL_RATE(100000000, 1, 150, 6, 6, 1, 0),
46 	{ /* sentinel */ },
47 };
48 
49 #ifndef CONFIG_SPL_BUILD
50 #define RK1808_CLK_DUMP(_id, _name, _iscru)	\
51 {						\
52 	.id = _id,				\
53 	.name = _name,				\
54 	.is_cru = _iscru,			\
55 }
56 
57 static const struct rk1808_clk_info clks_dump[] = {
58 	RK1808_CLK_DUMP(PLL_APLL, "apll", true),
59 	RK1808_CLK_DUMP(PLL_DPLL, "dpll", true),
60 	RK1808_CLK_DUMP(PLL_CPLL, "cpll", true),
61 	RK1808_CLK_DUMP(PLL_GPLL, "gpll", true),
62 	RK1808_CLK_DUMP(PLL_NPLL, "npll", true),
63 	RK1808_CLK_DUMP(PLL_PPLL, "ppll", true),
64 	RK1808_CLK_DUMP(HSCLK_BUS_PRE, "hsclk_bus", true),
65 	RK1808_CLK_DUMP(MSCLK_BUS_PRE, "msclk_bus", true),
66 	RK1808_CLK_DUMP(LSCLK_BUS_PRE, "lsclk_bus", true),
67 	RK1808_CLK_DUMP(MSCLK_PERI, "msclk_peri", true),
68 	RK1808_CLK_DUMP(LSCLK_PERI, "lsclk_peri", true),
69 };
70 #endif
71 
72 static struct rockchip_cpu_rate_table rk1808_cpu_rates[] = {
73 	RK1808_CPUCLK_RATE(1200000000, 1, 5),
74 	RK1808_CPUCLK_RATE(1008000000, 1, 5),
75 	RK1808_CPUCLK_RATE(816000000, 1, 3),
76 	RK1808_CPUCLK_RATE(600000000, 1, 3),
77 };
78 
79 static struct rockchip_pll_clock rk1808_pll_clks[] = {
80 	[APLL] = PLL(pll_rk3036, PLL_APLL, RK1808_PLL_CON(0),
81 		     RK1808_MODE_CON, 0, 10, 0, rk1808_pll_rates),
82 	[DPLL] = PLL(pll_rk3036, PLL_DPLL, RK1808_PLL_CON(8),
83 		     RK1808_MODE_CON, 2, 10, 0, NULL),
84 	[CPLL] = PLL(pll_rk3036, PLL_CPLL, RK1808_PLL_CON(16),
85 		    RK1808_MODE_CON, 4, 10, 0, rk1808_pll_rates),
86 	[GPLL] = PLL(pll_rk3036, PLL_GPLL, RK1808_PLL_CON(24),
87 		     RK1808_MODE_CON, 6, 10, 0, rk1808_pll_rates),
88 	[NPLL] = PLL(pll_rk3036, PLL_NPLL, RK1808_PLL_CON(32),
89 		     RK1808_MODE_CON, 8, 10, 0, rk1808_pll_rates),
90 	[PPLL] = PLL(pll_rk3036, PLL_PPLL, RK1808_PMU_PLL_CON(0),
91 		     RK1808_PMU_MODE_CON, 0, 10, 0, rk1808_pll_rates),
92 };
93 
94 #ifndef CONFIG_SPL_BUILD
95 static ulong rk1808_i2c_get_clk(struct rk1808_clk_priv *priv, ulong clk_id)
96 {
97 	struct rk1808_cru *cru = priv->cru;
98 	u32 div, con;
99 
100 	switch (clk_id) {
101 	case SCLK_PMU_I2C0:
102 		con = readl(&cru->pmu_clksel_con[7]);
103 		div = (con & CLK_I2C0_DIV_CON_MASK) >> CLK_I2C0_DIV_CON_SHIFT;
104 		break;
105 	case SCLK_I2C1:
106 		con = readl(&cru->clksel_con[59]);
107 		div = (con & CLK_I2C1_DIV_CON_MASK)  >> CLK_I2C1_DIV_CON_SHIFT;
108 		break;
109 	case SCLK_I2C2:
110 		con = readl(&cru->clksel_con[59]);
111 		div = (con & CLK_I2C2_DIV_CON_MASK) >> CLK_I2C2_DIV_CON_SHIFT;
112 		break;
113 	case SCLK_I2C3:
114 		con = readl(&cru->clksel_con[60]);
115 		div = (con & CLK_I2C3_DIV_CON_MASK) >> CLK_I2C3_DIV_CON_SHIFT;
116 		break;
117 	case SCLK_I2C4:
118 		con = readl(&cru->clksel_con[71]);
119 		div = (con & CLK_I2C4_DIV_CON_MASK) >> CLK_I2C4_DIV_CON_SHIFT;
120 		break;
121 	case SCLK_I2C5:
122 		con = readl(&cru->clksel_con[71]);
123 		div = (con & CLK_I2C5_DIV_CON_MASK) >> CLK_I2C5_DIV_CON_SHIFT;
124 		break;
125 	default:
126 		printf("do not support this i2c bus\n");
127 		return -EINVAL;
128 	}
129 
130 	return DIV_TO_RATE(priv->gpll_hz, div);
131 }
132 
133 static ulong rk1808_i2c_set_clk(struct rk1808_clk_priv *priv,
134 				ulong clk_id, uint hz)
135 {
136 	struct rk1808_cru *cru = priv->cru;
137 	int src_clk_div;
138 
139 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
140 	assert(src_clk_div - 1 < 127);
141 
142 	switch (clk_id) {
143 	case SCLK_PMU_I2C0:
144 		rk_clrsetreg(&cru->pmu_clksel_con[7],
145 			     CLK_I2C0_DIV_CON_MASK | CLK_I2C0_PLL_SEL_MASK,
146 			     (src_clk_div - 1) << CLK_I2C0_DIV_CON_SHIFT |
147 			     CLK_I2C0_PLL_SEL_PPLL << CLK_I2C0_PLL_SEL_SHIFT);
148 		break;
149 	case SCLK_I2C1:
150 		rk_clrsetreg(&cru->clksel_con[59],
151 			     CLK_I2C1_DIV_CON_MASK | CLK_I2C1_PLL_SEL_MASK,
152 			     (src_clk_div - 1) << CLK_I2C1_DIV_CON_SHIFT |
153 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT);
154 		break;
155 	case SCLK_I2C2:
156 		rk_clrsetreg(&cru->clksel_con[59],
157 			     CLK_I2C2_DIV_CON_MASK | CLK_I2C2_PLL_SEL_MASK,
158 			     (src_clk_div - 1) << CLK_I2C2_DIV_CON_SHIFT |
159 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C2_PLL_SEL_SHIFT);
160 		break;
161 	case SCLK_I2C3:
162 		rk_clrsetreg(&cru->clksel_con[60],
163 			     CLK_I2C3_DIV_CON_MASK | CLK_I2C3_PLL_SEL_MASK,
164 			     (src_clk_div - 1) << CLK_I2C3_DIV_CON_SHIFT |
165 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT);
166 		break;
167 	case SCLK_I2C4:
168 		rk_clrsetreg(&cru->clksel_con[71],
169 			     CLK_I2C4_DIV_CON_MASK | CLK_I2C4_PLL_SEL_MASK,
170 			     (src_clk_div - 1) << CLK_I2C4_DIV_CON_SHIFT |
171 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C4_PLL_SEL_SHIFT);
172 		break;
173 	case SCLK_I2C5:
174 		rk_clrsetreg(&cru->clksel_con[71],
175 			     CLK_I2C5_DIV_CON_MASK | CLK_I2C5_PLL_SEL_MASK,
176 			     (src_clk_div - 1) << CLK_I2C5_DIV_CON_SHIFT |
177 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C5_PLL_SEL_SHIFT);
178 		break;
179 	default:
180 		printf("do not support this i2c bus\n");
181 		return -EINVAL;
182 	}
183 
184 	return rk1808_i2c_get_clk(priv, clk_id);
185 }
186 #endif
187 
188 static ulong rk1808_mmc_get_clk(struct rk1808_clk_priv *priv, uint clk_id)
189 {
190 	struct rk1808_cru *cru = priv->cru;
191 	u32 div, con, con_id;
192 
193 	switch (clk_id) {
194 	case HCLK_SDMMC:
195 	case SCLK_SDMMC:
196 		con_id = 20;
197 		break;
198 	case HCLK_SDIO:
199 	case SCLK_SDIO:
200 		con_id = 22;
201 		break;
202 	case HCLK_EMMC:
203 	case SCLK_EMMC:
204 	case SCLK_EMMC_SAMPLE:
205 		con_id = 24;
206 		break;
207 	default:
208 		return -EINVAL;
209 	}
210 
211 	con = readl(&cru->clksel_con[con_id]);
212 	div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT;
213 
214 	if ((con & EMMC_PLL_MASK) >> EMMC_PLL_SHIFT
215 	    == EMMC_SEL_24M)
216 		return DIV_TO_RATE(OSC_HZ, div) / 2;
217 	else
218 		return DIV_TO_RATE(priv->gpll_hz, div) / 2;
219 }
220 
221 static ulong rk1808_mmc_set_clk(struct rk1808_clk_priv *priv,
222 				ulong clk_id, ulong set_rate)
223 {
224 	struct rk1808_cru *cru = priv->cru;
225 	int src_clk_div;
226 	u32 con_id;
227 
228 	switch (clk_id) {
229 	case HCLK_SDMMC:
230 	case SCLK_SDMMC:
231 		con_id = 20;
232 		break;
233 	case HCLK_SDIO:
234 	case SCLK_SDIO:
235 		con_id = 22;
236 		break;
237 	case HCLK_EMMC:
238 	case SCLK_EMMC:
239 		con_id = 24;
240 		break;
241 	default:
242 		return -EINVAL;
243 	}
244 
245 	/* Select clk_sdmmc/emmc source from GPLL by default */
246 	/* mmc clock defaulg div 2 internal, need provide double in cru */
247 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz / 2, set_rate);
248 
249 	if (src_clk_div > 127) {
250 		/* use 24MHz source for 400KHz clock */
251 		src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate);
252 		rk_clrsetreg(&cru->clksel_con[con_id],
253 			     EMMC_PLL_MASK | EMMC_DIV_MASK,
254 			     EMMC_SEL_24M << EMMC_PLL_SHIFT |
255 			     (src_clk_div - 1) << EMMC_DIV_SHIFT);
256 	} else {
257 		rk_clrsetreg(&cru->clksel_con[con_id],
258 			     EMMC_PLL_MASK | EMMC_DIV_MASK,
259 			     EMMC_SEL_GPLL << EMMC_PLL_SHIFT |
260 			     (src_clk_div - 1) << EMMC_DIV_SHIFT);
261 	}
262 	rk_clrsetreg(&cru->clksel_con[con_id + 1], EMMC_CLK_SEL_MASK,
263 		     EMMC_CLK_SEL_EMMC);
264 
265 	return rk1808_mmc_get_clk(priv, clk_id);
266 }
267 
268 #ifndef CONFIG_SPL_BUILD
269 static ulong rk1808_pwm_get_clk(struct rk1808_clk_priv *priv, ulong clk_id)
270 {
271 	struct rk1808_cru *cru = priv->cru;
272 	u32 div, con;
273 
274 	switch (clk_id) {
275 	case SCLK_PWM0:
276 		con = readl(&cru->clksel_con[69]);
277 		div = (con & CLK_PWM0_DIV_CON_MASK) >> CLK_PWM0_DIV_CON_SHIFT;
278 		break;
279 	case SCLK_PWM1:
280 		con = readl(&cru->clksel_con[69]);
281 		div = (con & CLK_PWM1_DIV_CON_MASK) >> CLK_PWM1_DIV_CON_SHIFT;
282 		break;
283 	case SCLK_PWM2:
284 		con = readl(&cru->clksel_con[70]);
285 		div = (con & CLK_PWM2_DIV_CON_MASK) >> CLK_PWM2_DIV_CON_SHIFT;
286 		break;
287 	default:
288 		printf("do not support this pwm bus\n");
289 		return -EINVAL;
290 	}
291 
292 	return DIV_TO_RATE(priv->gpll_hz, div);
293 }
294 
295 static ulong rk1808_pwm_set_clk(struct rk1808_clk_priv *priv,
296 				ulong clk_id, uint hz)
297 {
298 	struct rk1808_cru *cru = priv->cru;
299 	int src_clk_div;
300 
301 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
302 	assert(src_clk_div - 1 < 127);
303 
304 	switch (clk_id) {
305 	case SCLK_PWM0:
306 		rk_clrsetreg(&cru->clksel_con[69],
307 			     CLK_PWM0_DIV_CON_MASK | CLK_PWM0_PLL_SEL_MASK,
308 			     (src_clk_div - 1) << CLK_PWM0_DIV_CON_SHIFT |
309 			     CLK_PWM_PLL_SEL_GPLL << CLK_PWM0_PLL_SEL_SHIFT);
310 		break;
311 	case SCLK_PWM1:
312 		rk_clrsetreg(&cru->clksel_con[69],
313 			     CLK_PWM1_DIV_CON_MASK | CLK_PWM1_PLL_SEL_MASK,
314 			     (src_clk_div - 1) << CLK_PWM1_DIV_CON_SHIFT |
315 			     CLK_PWM_PLL_SEL_GPLL << CLK_PWM1_PLL_SEL_SHIFT);
316 		break;
317 	case SCLK_PWM2:
318 		rk_clrsetreg(&cru->clksel_con[70],
319 			     CLK_PWM2_DIV_CON_MASK | CLK_PWM2_PLL_SEL_MASK,
320 			     (src_clk_div - 1) << CLK_PWM2_DIV_CON_SHIFT |
321 			     CLK_PWM_PLL_SEL_GPLL << CLK_PWM2_PLL_SEL_SHIFT);
322 		break;
323 	default:
324 		printf("do not support this pwm bus\n");
325 		return -EINVAL;
326 	}
327 
328 	return rk1808_pwm_get_clk(priv, clk_id);
329 }
330 
331 static ulong rk1808_saradc_get_clk(struct rk1808_clk_priv *priv)
332 {
333 	struct rk1808_cru *cru = priv->cru;
334 	u32 div, con;
335 
336 	con = readl(&cru->clksel_con[63]);
337 	div = con & CLK_SARADC_DIV_CON_MASK;
338 
339 	return DIV_TO_RATE(OSC_HZ, div);
340 }
341 
342 static ulong rk1808_saradc_set_clk(struct rk1808_clk_priv *priv, uint hz)
343 {
344 	struct rk1808_cru *cru = priv->cru;
345 	int src_clk_div;
346 
347 	src_clk_div = DIV_ROUND_UP(OSC_HZ, hz);
348 	assert(src_clk_div - 1 < 2047);
349 
350 	rk_clrsetreg(&cru->clksel_con[63],
351 		     CLK_SARADC_DIV_CON_MASK,
352 		     (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT);
353 
354 	return rk1808_saradc_get_clk(priv);
355 }
356 
357 static ulong rk1808_tsadc_get_clk(struct rk1808_clk_priv *priv)
358 {
359 	struct rk1808_cru *cru = priv->cru;
360 	u32 div, con;
361 
362 	con = readl(&cru->clksel_con[62]);
363 	div = con & CLK_SARADC_DIV_CON_MASK;
364 
365 	return DIV_TO_RATE(OSC_HZ, div);
366 }
367 
368 static ulong rk1808_tsadc_set_clk(struct rk1808_clk_priv *priv, uint hz)
369 {
370 	struct rk1808_cru *cru = priv->cru;
371 	int src_clk_div;
372 
373 	src_clk_div = DIV_ROUND_UP(OSC_HZ, hz);
374 	assert(src_clk_div - 1 < 2047);
375 
376 	rk_clrsetreg(&cru->clksel_con[62],
377 		     CLK_SARADC_DIV_CON_MASK,
378 		     (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT);
379 
380 	return rk1808_tsadc_get_clk(priv);
381 }
382 
383 static ulong rk1808_spi_get_clk(struct rk1808_clk_priv *priv, ulong clk_id)
384 {
385 	struct rk1808_cru *cru = priv->cru;
386 	u32 div, con;
387 
388 	switch (clk_id) {
389 	case SCLK_SPI0:
390 		con = readl(&cru->clksel_con[60]);
391 		div = (con & CLK_SPI0_DIV_CON_MASK) >> CLK_SPI0_DIV_CON_SHIFT;
392 		break;
393 	case SCLK_SPI1:
394 		con = readl(&cru->clksel_con[61]);
395 		div = (con & CLK_SPI1_DIV_CON_MASK) >> CLK_SPI1_DIV_CON_SHIFT;
396 		break;
397 	case SCLK_SPI2:
398 		con = readl(&cru->clksel_con[61]);
399 		div = (con & CLK_SPI2_DIV_CON_MASK) >> CLK_SPI2_DIV_CON_SHIFT;
400 		break;
401 	default:
402 		printf("do not support this pwm bus\n");
403 		return -EINVAL;
404 	}
405 
406 	return DIV_TO_RATE(priv->gpll_hz, div);
407 }
408 
409 static ulong rk1808_spi_set_clk(struct rk1808_clk_priv *priv,
410 				ulong clk_id, uint hz)
411 {
412 	struct rk1808_cru *cru = priv->cru;
413 	int src_clk_div;
414 
415 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
416 	assert(src_clk_div - 1 < 127);
417 
418 	switch (clk_id) {
419 	case SCLK_SPI0:
420 		rk_clrsetreg(&cru->clksel_con[60],
421 			     CLK_SPI0_DIV_CON_MASK | CLK_SPI0_PLL_SEL_MASK,
422 			     (src_clk_div - 1) << CLK_SPI0_DIV_CON_SHIFT |
423 			     CLK_SPI_PLL_SEL_GPLL << CLK_SPI0_PLL_SEL_SHIFT);
424 		break;
425 	case SCLK_SPI1:
426 		rk_clrsetreg(&cru->clksel_con[61],
427 			     CLK_SPI1_DIV_CON_MASK | CLK_SPI1_PLL_SEL_MASK,
428 			     (src_clk_div - 1) << CLK_SPI1_DIV_CON_SHIFT |
429 			     CLK_SPI_PLL_SEL_GPLL << CLK_SPI1_PLL_SEL_SHIFT);
430 		break;
431 	case SCLK_SPI2:
432 		rk_clrsetreg(&cru->clksel_con[61],
433 			     CLK_SPI2_DIV_CON_MASK | CLK_SPI2_PLL_SEL_MASK,
434 			     (src_clk_div - 1) << CLK_SPI2_DIV_CON_SHIFT |
435 			     CLK_SPI_PLL_SEL_GPLL << CLK_SPI2_PLL_SEL_SHIFT);
436 		break;
437 	default:
438 		printf("do not support this pwm bus\n");
439 		return -EINVAL;
440 	}
441 
442 	return rk1808_spi_get_clk(priv, clk_id);
443 }
444 
445 #define RK1808_VOP_PLL_LIMIT_FREQ		600 * 1000000
446 static ulong rk1808_vop_get_clk(struct rk1808_clk_priv *priv, ulong clk_id)
447 {
448 	struct rk1808_cru *cru = priv->cru;
449 	u32 div, con, parent;
450 
451 	switch (clk_id) {
452 	case ACLK_VOPRAW:
453 	case ACLK_VOPLITE:
454 		con = readl(&cru->clksel_con[4]);
455 		div = (con & ACLK_VOP_DIV_CON_MASK) >> ACLK_VOP_DIV_CON_SHIFT;
456 		parent = priv->gpll_hz;
457 		break;
458 	case HCLK_VOPRAW:
459 	case HCLK_VOPLITE:
460 		parent = rk1808_vop_get_clk(priv, ACLK_VOPRAW);
461 		con = readl(&cru->clksel_con[4]);
462 		div = (con & HCLK_VOP_DIV_CON_MASK) >> HCLK_VOP_DIV_CON_SHIFT;
463 		break;
464 	case DCLK_VOPRAW:
465 		con = readl(&cru->clksel_con[5]);
466 		div = con & DCLK_VOPRAW_DIV_CON_MASK;
467 		parent = rockchip_pll_get_rate(&rk1808_pll_clks[NPLL],
468 					       priv->cru, NPLL);
469 		break;
470 	case DCLK_VOPLITE:
471 		con = readl(&cru->clksel_con[7]);
472 		div = con & DCLK_VOPLITE_DIV_CON_MASK;
473 		parent = (con & DCLK_VOPLITE_PLL_SEL_MASK) >>
474 			 DCLK_VOPLITE_PLL_SEL_SHIFT;
475 		if (parent == DCLK_VOPLITE_PLL_SEL_NPLL)
476 			parent = rockchip_pll_get_rate(&rk1808_pll_clks[NPLL],
477 						       priv->cru, NPLL);
478 		else if (parent == DCLK_VOPLITE_PLL_SEL_CPLL)
479 			parent = priv->cpll_hz;
480 		else
481 			parent = priv->gpll_hz;
482 		break;
483 	default:
484 		return -ENOENT;
485 	}
486 
487 	return DIV_TO_RATE(parent, div);
488 }
489 
490 static ulong rk1808_vop_set_clk(struct rk1808_clk_priv *priv,
491 				ulong clk_id, uint hz)
492 {
493 	struct rk1808_cru *cru = priv->cru;
494 	int src_clk_div, parent;
495 
496 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
497 	assert(src_clk_div - 1 < 31);
498 
499 	switch (clk_id) {
500 	case ACLK_VOPRAW:
501 	case ACLK_VOPLITE:
502 		rk_clrsetreg(&cru->clksel_con[4],
503 			     ACLK_VOP_PLL_SEL_MASK | ACLK_VOP_DIV_CON_MASK,
504 			     ACLK_VOP_PLL_SEL_GPLL << ACLK_VOP_PLL_SEL_SHIFT |
505 			     (src_clk_div - 1) << ACLK_VOP_DIV_CON_SHIFT);
506 		break;
507 	case HCLK_VOPRAW:
508 	case HCLK_VOPLITE:
509 		src_clk_div =
510 			DIV_ROUND_UP(rk1808_vop_get_clk(priv, ACLK_VOPRAW), hz);
511 		assert(src_clk_div - 1 < 15);
512 		rk_clrsetreg(&cru->clksel_con[4],
513 			     HCLK_VOP_DIV_CON_MASK,
514 			     (src_clk_div - 1) << HCLK_VOP_DIV_CON_SHIFT);
515 		break;
516 	case DCLK_VOPRAW:
517 		/*
518 		 * vopb dclk source from npll, and equals to
519 		 */
520 		src_clk_div = DIV_ROUND_UP(RK1808_VOP_PLL_LIMIT_FREQ, hz);
521 		rk_clrsetreg(&cru->clksel_con[5],
522 			     DCLK_VOPRAW_SEL_MASK |
523 			     DCLK_VOPRAW_PLL_SEL_MASK |
524 			     DCLK_VOPRAW_DIV_CON_MASK,
525 			     (DCLK_VOPRAW_SEL_VOPRAW <<
526 			     DCLK_VOPRAW_SEL_SHIFT) |
527 			     (DCLK_VOPRAW_PLL_SEL_NPLL <<
528 			     DCLK_VOPRAW_PLL_SEL_SHIFT) |
529 			     ((src_clk_div - 1) << DCLK_VOPRAW_DIV_CON_SHIFT));
530 		rockchip_pll_set_rate(&rk1808_pll_clks[NPLL],
531 				      priv->cru, NPLL, src_clk_div * hz);
532 
533 		break;
534 	case DCLK_VOPLITE:
535 		/*
536 		 * vopl dclk source from cpll, and equals to
537 		 */
538 		if (!(priv->cpll_hz % hz)) {
539 			parent = DCLK_VOPLITE_PLL_SEL_CPLL;
540 			src_clk_div = DIV_ROUND_UP(priv->cpll_hz, hz);
541 		} else if (!(priv->gpll_hz % hz)) {
542 			parent = DCLK_VOPLITE_PLL_SEL_GPLL;
543 			src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
544 		} else {
545 			parent = DCLK_VOPLITE_PLL_SEL_NPLL;
546 			src_clk_div = DIV_ROUND_UP(RK1808_VOP_PLL_LIMIT_FREQ,
547 						   hz);
548 			rockchip_pll_set_rate(&rk1808_pll_clks[NPLL],
549 					      priv->cru, NPLL,
550 					      src_clk_div * hz);
551 		}
552 		rk_clrsetreg(&cru->clksel_con[7],
553 			     DCLK_VOPLITE_SEL_MASK | DCLK_VOPLITE_PLL_SEL_MASK |
554 			     DCLK_VOPLITE_DIV_CON_MASK,
555 			     (DCLK_VOPLITE_SEL_VOPRAW <<
556 			     DCLK_VOPLITE_SEL_SHIFT) |
557 			     (parent << DCLK_VOPLITE_PLL_SEL_SHIFT) |
558 			     ((src_clk_div - 1) << DCLK_VOPLITE_DIV_CON_SHIFT));
559 		break;
560 	default:
561 		printf("do not support this vop freq\n");
562 		return -EINVAL;
563 	}
564 
565 	return rk1808_vop_get_clk(priv, clk_id);
566 }
567 
568 static ulong rk1808_mac_set_clk(struct clk *clk, uint hz)
569 {
570 	struct rk1808_clk_priv *priv = dev_get_priv(clk->dev);
571 	struct rk1808_cru *cru = priv->cru;
572 	u32 con = readl(&cru->clksel_con[26]);
573 	ulong pll_rate;
574 	u8 div;
575 
576 	if ((con >> GMAC_PLL_SEL_SHIFT) & GMAC_PLL_SEL_NPLL)
577 		pll_rate = rockchip_pll_get_rate(&rk1808_pll_clks[NPLL],
578 						 priv->cru, NPLL);
579 	else if ((con >> GMAC_PLL_SEL_SHIFT) & GMAC_PLL_SEL_PPLL)
580 		pll_rate = rockchip_pll_get_rate(&rk1808_pll_clks[PPLL],
581 						 priv->cru, PPLL);
582 	else
583 		pll_rate = rockchip_pll_get_rate(&rk1808_pll_clks[CPLL],
584 						 priv->cru, CPLL);
585 
586 	/*default set 50MHZ for gmac*/
587 	if (!hz)
588 		hz = 50000000;
589 
590 	div = DIV_ROUND_UP(pll_rate, hz) - 1;
591 	assert(div < 32);
592 	rk_clrsetreg(&cru->clksel_con[26], CLK_GMAC_DIV_MASK,
593 		     div << CLK_GMAC_DIV_SHIFT);
594 
595 	return DIV_TO_RATE(pll_rate, div);
596 }
597 
598 static int rk1808_mac_set_speed_clk(struct clk *clk, ulong clk_id, uint hz)
599 {
600 	struct rk1808_clk_priv *priv = dev_get_priv(clk->dev);
601 	struct rk1808_cru *cru = priv->cru;
602 	u32 sel;
603 
604 	switch (clk_id) {
605 	case SCLK_GMAC_RGMII_SPEED:
606 		if (hz == 125000000)
607 			sel = 0;
608 		else if (hz == 2500000)
609 			sel = 2;
610 		else
611 			sel = 3;
612 		rk_clrsetreg(&cru->clksel_con[27], RGMII_CLK_SEL_MASK,
613 			     sel << RGMII_CLK_SEL_SHIFT);
614 		break;
615 	case SCLK_GMAC_RMII_SPEED:
616 		if (hz == 2500000)
617 			sel = 0;
618 		else
619 			sel = 1;
620 		rk_clrsetreg(&cru->clksel_con[27], RMII_CLK_SEL_MASK,
621 			     sel << RMII_CLK_SEL_SHIFT);
622 		break;
623 	default:
624 		return -ENOENT;
625 	}
626 	return 0;
627 }
628 #endif
629 
630 static ulong rk1808_bus_get_clk(struct rk1808_clk_priv *priv, ulong clk_id)
631 {
632 	struct rk1808_cru *cru = priv->cru;
633 	u32 div, con, parent;
634 
635 	switch (clk_id) {
636 	case HSCLK_BUS_PRE:
637 		con = readl(&cru->clksel_con[27]);
638 		div = (con & HSCLK_BUS_DIV_CON_MASK) >> HSCLK_BUS_DIV_CON_SHIFT;
639 		parent = priv->gpll_hz;
640 		break;
641 	case MSCLK_BUS_PRE:
642 		con = readl(&cru->clksel_con[28]);
643 		div = (con & MSCLK_BUS_DIV_CON_MASK) >> MSCLK_BUS_DIV_CON_SHIFT;
644 		parent = priv->gpll_hz;
645 		break;
646 	case LSCLK_BUS_PRE:
647 	case PCLK_WDT:
648 		con = readl(&cru->clksel_con[28]);
649 		div = (con & LSCLK_BUS_DIV_CON_MASK) >> LSCLK_BUS_DIV_CON_SHIFT;
650 		parent = priv->gpll_hz;
651 		break;
652 	default:
653 		return -ENOENT;
654 	}
655 
656 	return DIV_TO_RATE(parent, div);
657 }
658 
659 static ulong rk1808_bus_set_clk(struct rk1808_clk_priv *priv,
660 				ulong clk_id, ulong hz)
661 {
662 	struct rk1808_cru *cru = priv->cru;
663 	int src_clk_div;
664 
665 	/*
666 	 * select gpll as pd_bus bus clock source and
667 	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
668 	 */
669 	switch (clk_id) {
670 	case HSCLK_BUS_PRE:
671 		src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
672 		assert(src_clk_div - 1 < 31);
673 		rk_clrsetreg(&cru->clksel_con[27],
674 			     CLK_BUS_PLL_SEL_MASK | HSCLK_BUS_DIV_CON_MASK,
675 			     CLK_BUS_PLL_SEL_GPLL << CLK_BUS_PLL_SEL_SHIFT |
676 			     (src_clk_div - 1) << HSCLK_BUS_DIV_CON_SHIFT);
677 		break;
678 	case MSCLK_BUS_PRE:
679 		src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
680 		assert(src_clk_div - 1 < 31);
681 		rk_clrsetreg(&cru->clksel_con[28],
682 			     CLK_BUS_PLL_SEL_MASK | MSCLK_BUS_DIV_CON_MASK,
683 			     CLK_BUS_PLL_SEL_GPLL << CLK_BUS_PLL_SEL_SHIFT |
684 			     (src_clk_div - 1) << MSCLK_BUS_DIV_CON_SHIFT);
685 		break;
686 	case LSCLK_BUS_PRE:
687 		src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
688 		assert(src_clk_div - 1 < 31);
689 		rk_clrsetreg(&cru->clksel_con[28],
690 			     CLK_BUS_PLL_SEL_MASK | LSCLK_BUS_DIV_CON_MASK,
691 			     CLK_BUS_PLL_SEL_GPLL << CLK_BUS_PLL_SEL_SHIFT |
692 			     (src_clk_div - 1) << LSCLK_BUS_DIV_CON_SHIFT);
693 		break;
694 	default:
695 		printf("do not support this bus freq\n");
696 		return -EINVAL;
697 	}
698 
699 	return rk1808_bus_get_clk(priv, clk_id);
700 }
701 
702 static ulong rk1808_peri_get_clk(struct rk1808_clk_priv *priv, ulong clk_id)
703 {
704 	struct rk1808_cru *cru = priv->cru;
705 	u32 div, con, parent;
706 
707 	switch (clk_id) {
708 	case MSCLK_PERI:
709 		con = readl(&cru->clksel_con[19]);
710 		div = (con & MSCLK_PERI_DIV_CON_MASK) >>
711 		      MSCLK_PERI_DIV_CON_SHIFT;
712 		parent = priv->gpll_hz;
713 		break;
714 	case LSCLK_PERI:
715 		con = readl(&cru->clksel_con[19]);
716 		div = (con & LSCLK_PERI_DIV_CON_MASK) >>
717 		      LSCLK_PERI_DIV_CON_SHIFT;
718 		parent = priv->gpll_hz;
719 		break;
720 	default:
721 		return -ENOENT;
722 	}
723 
724 	return DIV_TO_RATE(parent, div);
725 }
726 
727 static ulong rk1808_peri_set_clk(struct rk1808_clk_priv *priv,
728 				 ulong clk_id, ulong hz)
729 {
730 	struct rk1808_cru *cru = priv->cru;
731 	int src_clk_div;
732 
733 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
734 	assert(src_clk_div - 1 < 31);
735 
736 	/*
737 	 * select gpll as pd_peri bus clock source and
738 	 * set up dependent divisors for HCLK and ACLK clocks.
739 	 */
740 	switch (clk_id) {
741 	case MSCLK_PERI:
742 		rk_clrsetreg(&cru->clksel_con[19],
743 			     CLK_PERI_PLL_SEL_MASK | MSCLK_PERI_DIV_CON_MASK,
744 			     CLK_PERI_PLL_SEL_GPLL << CLK_PERI_PLL_SEL_SHIFT |
745 			     (src_clk_div - 1) << MSCLK_PERI_DIV_CON_SHIFT);
746 		break;
747 	case LSCLK_PERI:
748 		rk_clrsetreg(&cru->clksel_con[19],
749 			     CLK_PERI_PLL_SEL_MASK | LSCLK_PERI_DIV_CON_MASK,
750 			     CLK_PERI_PLL_SEL_GPLL << CLK_PERI_PLL_SEL_SHIFT |
751 			     (src_clk_div - 1) << LSCLK_PERI_DIV_CON_SHIFT);
752 		break;
753 	default:
754 		printf("do not support this peri freq\n");
755 		return -EINVAL;
756 	}
757 
758 	return rk1808_peri_get_clk(priv, clk_id);
759 }
760 
761 static ulong rk1808_pclk_pmu_set_clk(struct rk1808_clk_priv *priv,
762 				     ulong clk_id, ulong parent_hz, ulong hz)
763 {
764 	struct rk1808_cru *cru = priv->cru;
765 	int src_clk_div;
766 
767 	src_clk_div = DIV_ROUND_UP(parent_hz, hz);
768 	assert(src_clk_div - 1 < 31);
769 
770 	rk_clrsetreg(&cru->pmu_clksel_con[0],
771 		     PCLK_PMU_DIV_CON_MASK,
772 		     (src_clk_div - 1) << PCLK_PMU_DIV_CON_SHIFT);
773 
774 	return parent_hz / src_clk_div;
775 }
776 
777 static ulong rk1808_armclk_set_clk(struct rk1808_clk_priv *priv, ulong hz)
778 {
779 	struct rk1808_cru *cru = priv->cru;
780 	const struct rockchip_cpu_rate_table *rate;
781 	ulong old_rate;
782 
783 	rate = rockchip_get_cpu_settings(rk1808_cpu_rates, hz);
784 	if (!rate) {
785 		printf("%s unsupported rate\n", __func__);
786 		return -EINVAL;
787 	}
788 
789 	/*
790 	 * select apll as cpu/core clock pll source and
791 	 * set up dependent divisors for PERI and ACLK clocks.
792 	 * core hz : apll = 1:1
793 	 */
794 	old_rate = rockchip_pll_get_rate(&rk1808_pll_clks[APLL],
795 					 priv->cru, APLL);
796 	if (old_rate > hz) {
797 		if (rockchip_pll_set_rate(&rk1808_pll_clks[APLL],
798 					  priv->cru, APLL, hz))
799 			return -EINVAL;
800 		rk_clrsetreg(&cru->clksel_con[0],
801 			     CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
802 			     CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
803 			     rate->aclk_div << CORE_ACLK_DIV_SHIFT |
804 			     rate->pclk_div << CORE_DBG_DIV_SHIFT |
805 			     CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
806 			     0 << CORE_DIV_CON_SHIFT);
807 	} else if (old_rate < hz) {
808 		rk_clrsetreg(&cru->clksel_con[0],
809 			     CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
810 			     CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
811 			     rate->aclk_div << CORE_ACLK_DIV_SHIFT |
812 			     rate->pclk_div << CORE_DBG_DIV_SHIFT |
813 			     CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
814 			     0 << CORE_DIV_CON_SHIFT);
815 		if (rockchip_pll_set_rate(&rk1808_pll_clks[APLL],
816 					  priv->cru, APLL, hz))
817 			return -EINVAL;
818 	}
819 
820 	return rockchip_pll_get_rate(&rk1808_pll_clks[APLL], priv->cru, APLL);
821 }
822 
823 static ulong rk1808_clk_get_rate(struct clk *clk)
824 {
825 	struct rk1808_clk_priv *priv = dev_get_priv(clk->dev);
826 	ulong rate = 0;
827 
828 	debug("%s %ld\n", __func__, clk->id);
829 	switch (clk->id) {
830 	case PLL_APLL:
831 	case PLL_DPLL:
832 	case PLL_CPLL:
833 	case PLL_GPLL:
834 	case PLL_NPLL:
835 	case PLL_PPLL:
836 		rate = rockchip_pll_get_rate(&rk1808_pll_clks[clk->id - 1],
837 					     priv->cru, clk->id - 1);
838 		break;
839 	case ARMCLK:
840 		rate = rockchip_pll_get_rate(&rk1808_pll_clks[APLL],
841 					     priv->cru, APLL);
842 		break;
843 	case HCLK_SDMMC:
844 	case HCLK_EMMC:
845 	case HCLK_SDIO:
846 	case SCLK_SDMMC:
847 	case SCLK_EMMC:
848 	case SCLK_EMMC_SAMPLE:
849 	case SCLK_SDIO:
850 		rate = rk1808_mmc_get_clk(priv, clk->id);
851 		break;
852 #ifndef CONFIG_SPL_BUILD
853 	case SCLK_PMU_I2C0:
854 	case SCLK_I2C1:
855 	case SCLK_I2C2:
856 	case SCLK_I2C3:
857 	case SCLK_I2C4:
858 	case SCLK_I2C5:
859 		rate = rk1808_i2c_get_clk(priv, clk->id);
860 		break;
861 	case SCLK_PWM0:
862 	case SCLK_PWM1:
863 	case SCLK_PWM2:
864 		rate = rk1808_pwm_get_clk(priv, clk->id);
865 		break;
866 	case SCLK_SARADC:
867 		rate = rk1808_saradc_get_clk(priv);
868 		break;
869 	case SCLK_TSADC:
870 		rate = rk1808_tsadc_get_clk(priv);
871 		break;
872 	case SCLK_SPI0:
873 	case SCLK_SPI1:
874 	case SCLK_SPI2:
875 		rate = rk1808_spi_get_clk(priv, clk->id);
876 		break;
877 	case ACLK_VOPRAW:
878 	case DCLK_VOPRAW:
879 	case ACLK_VOPLITE:
880 	case DCLK_VOPLITE:
881 		rate = rk1808_vop_get_clk(priv, clk->id);
882 		break;
883 #endif
884 	case HSCLK_BUS_PRE:
885 	case MSCLK_BUS_PRE:
886 	case LSCLK_BUS_PRE:
887 	case PCLK_WDT:
888 		rate = rk1808_bus_get_clk(priv, clk->id);
889 		break;
890 	case MSCLK_PERI:
891 	case LSCLK_PERI:
892 		rate = rk1808_peri_get_clk(priv, clk->id);
893 		break;
894 	default:
895 		return -ENOENT;
896 	}
897 
898 	return rate;
899 }
900 
901 static ulong rk1808_clk_set_rate(struct clk *clk, ulong rate)
902 {
903 	struct rk1808_clk_priv *priv = dev_get_priv(clk->dev);
904 	ulong ret = 0;
905 
906 	debug("%s %ld %ld\n", __func__, clk->id, rate);
907 	switch (clk->id) {
908 	case PLL_APLL:
909 	case PLL_DPLL:
910 		ret = rockchip_pll_set_rate(&rk1808_pll_clks[clk->id - 1],
911 					    priv->cru, clk->id - 1, rate);
912 		break;
913 	case PLL_PPLL:
914 		ret = rk1808_pclk_pmu_set_clk(priv, clk->id, rate, PCLK_PMU_HZ);
915 		ret = rockchip_pll_set_rate(&rk1808_pll_clks[PPLL],
916 					    priv->cru, PPLL, rate);
917 		break;
918 	case PLL_CPLL:
919 		ret = rockchip_pll_set_rate(&rk1808_pll_clks[CPLL],
920 					    priv->cru, CPLL, rate);
921 		if (ret == 0)
922 			priv->cpll_hz = rate;
923 		break;
924 	case PLL_GPLL:
925 		ret = rockchip_pll_set_rate(&rk1808_pll_clks[GPLL],
926 					    priv->cru, GPLL, rate);
927 		if (ret == 0)
928 			priv->gpll_hz = rate;
929 		break;
930 	case PLL_NPLL:
931 		ret = rockchip_pll_set_rate(&rk1808_pll_clks[NPLL],
932 					    priv->cru, NPLL, rate);
933 		if (ret == 0)
934 			priv->npll_hz = rate;
935 		break;
936 	case ARMCLK:
937 		if (priv->armclk_hz)
938 			rk1808_armclk_set_clk(priv, rate);
939 		priv->armclk_hz = rate;
940 		break;
941 	case HCLK_SDMMC:
942 	case HCLK_EMMC:
943 	case HCLK_SDIO:
944 	case SCLK_SDMMC:
945 	case SCLK_EMMC:
946 	case SCLK_SDIO:
947 		ret = rk1808_mmc_set_clk(priv, clk->id, rate);
948 		break;
949 #ifndef CONFIG_SPL_BUILD
950 	case SCLK_PMU_I2C0:
951 	case SCLK_I2C1:
952 	case SCLK_I2C2:
953 	case SCLK_I2C3:
954 	case SCLK_I2C4:
955 	case SCLK_I2C5:
956 		ret = rk1808_i2c_set_clk(priv, clk->id, rate);
957 		break;
958 	case SCLK_PWM0:
959 	case SCLK_PWM1:
960 	case SCLK_PWM2:
961 		ret = rk1808_pwm_set_clk(priv, clk->id, rate);
962 		break;
963 	case SCLK_SARADC:
964 		ret = rk1808_saradc_set_clk(priv, rate);
965 		break;
966 	case SCLK_TSADC:
967 		ret = rk1808_tsadc_set_clk(priv, rate);
968 		break;
969 	case SCLK_SPI0:
970 	case SCLK_SPI1:
971 	case SCLK_SPI2:
972 		ret = rk1808_spi_set_clk(priv, clk->id, rate);
973 		break;
974 	case ACLK_VOPRAW:
975 	case DCLK_VOPRAW:
976 	case ACLK_VOPLITE:
977 	case DCLK_VOPLITE:
978 		ret = rk1808_vop_set_clk(priv, clk->id, rate);
979 		break;
980 	case SCLK_GMAC:
981 	case SCLK_GMAC_SRC:
982 		ret = rk1808_mac_set_clk(clk, rate);
983 		break;
984 	case SCLK_GMAC_RMII_SPEED:
985 	case SCLK_GMAC_RGMII_SPEED:
986 		ret = rk1808_mac_set_speed_clk(clk, clk->id, rate);
987 		break;
988 #endif
989 	case HSCLK_BUS_PRE:
990 	case MSCLK_BUS_PRE:
991 	case LSCLK_BUS_PRE:
992 		ret = rk1808_bus_set_clk(priv, clk->id, rate);
993 		break;
994 	case MSCLK_PERI:
995 	case LSCLK_PERI:
996 		ret = rk1808_peri_set_clk(priv, clk->id, rate);
997 		break;
998 	case SCLK_32K_IOE:
999 		return 0;
1000 	default:
1001 		return -ENOENT;
1002 	}
1003 
1004 	return ret;
1005 }
1006 
1007 #define ROCKCHIP_MMC_DELAY_SEL		BIT(10)
1008 #define ROCKCHIP_MMC_DEGREE_MASK	0x3
1009 #define ROCKCHIP_MMC_DELAYNUM_OFFSET	2
1010 #define ROCKCHIP_MMC_DELAYNUM_MASK	(0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
1011 
1012 #define PSECS_PER_SEC 1000000000000LL
1013 /*
1014  * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
1015  * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
1016  */
1017 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
1018 
1019 int rk1808_mmc_get_phase(struct clk *clk)
1020 {
1021 	struct rk1808_clk_priv *priv = dev_get_priv(clk->dev);
1022 	struct rk1808_cru *cru = priv->cru;
1023 	u32 raw_value, delay_num;
1024 	u16 degrees = 0;
1025 	ulong rate;
1026 
1027 	rate = rk1808_clk_get_rate(clk);
1028 
1029 	if (rate < 0)
1030 		return rate;
1031 
1032 	if (clk->id == SCLK_EMMC_SAMPLE)
1033 		raw_value = readl(&cru->emmc_con[1]);
1034 	else if (clk->id == SCLK_SDMMC_SAMPLE)
1035 		raw_value = readl(&cru->sdmmc_con[1]);
1036 	else
1037 		raw_value = readl(&cru->sdio_con[1]);
1038 
1039 	raw_value >>= 1;
1040 	degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
1041 
1042 	if (raw_value & ROCKCHIP_MMC_DELAY_SEL) {
1043 		/* degrees/delaynum * 10000 */
1044 		unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) *
1045 					36 * (rate / 1000000);
1046 
1047 		delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
1048 		delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET;
1049 		degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000);
1050 	}
1051 
1052 	return degrees % 360;
1053 }
1054 
1055 int rk1808_mmc_set_phase(struct clk *clk, u32 degrees)
1056 {
1057 	struct rk1808_clk_priv *priv = dev_get_priv(clk->dev);
1058 	struct rk1808_cru *cru = priv->cru;
1059 	u8 nineties, remainder, delay_num;
1060 	u32 raw_value, delay;
1061 	ulong rate;
1062 
1063 	rate = rk1808_clk_get_rate(clk);
1064 
1065 	if (rate < 0)
1066 		return rate;
1067 
1068 	nineties = degrees / 90;
1069 	remainder = (degrees % 90);
1070 
1071 	/*
1072 	 * Convert to delay; do a little extra work to make sure we
1073 	 * don't overflow 32-bit / 64-bit numbers.
1074 	 */
1075 	delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */
1076 	delay *= remainder;
1077 	delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 *
1078 				(ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10));
1079 
1080 	delay_num = (u8)min_t(u32, delay, 255);
1081 
1082 	raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
1083 	raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
1084 	raw_value |= nineties;
1085 
1086 	raw_value <<= 1;
1087 	if (clk->id == SCLK_EMMC_SAMPLE)
1088 		writel(raw_value | 0xffff0000, &cru->emmc_con[1]);
1089 	else if (clk->id == SCLK_SDMMC_SAMPLE)
1090 		writel(raw_value | 0xffff0000, &cru->sdmmc_con[1]);
1091 	else
1092 		writel(raw_value | 0xffff0000, &cru->sdio_con[1]);
1093 
1094 	debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n",
1095 	      degrees, delay_num, raw_value, rk1808_mmc_get_phase(clk));
1096 
1097 	return 0;
1098 }
1099 
1100 static int rk1808_clk_get_phase(struct clk *clk)
1101 {
1102 	int ret;
1103 
1104 	debug("%s %ld\n", __func__, clk->id);
1105 	switch (clk->id) {
1106 	case SCLK_EMMC_SAMPLE:
1107 	case SCLK_SDMMC_SAMPLE:
1108 	case SCLK_SDIO_SAMPLE:
1109 		ret = rk1808_mmc_get_phase(clk);
1110 		break;
1111 	default:
1112 		return -ENOENT;
1113 	}
1114 
1115 	return ret;
1116 }
1117 
1118 static int rk1808_clk_set_phase(struct clk *clk, int degrees)
1119 {
1120 	int ret;
1121 
1122 	debug("%s %ld\n", __func__, clk->id);
1123 	switch (clk->id) {
1124 	case SCLK_EMMC_SAMPLE:
1125 	case SCLK_SDMMC_SAMPLE:
1126 	case SCLK_SDIO_SAMPLE:
1127 		ret = rk1808_mmc_set_phase(clk, degrees);
1128 		break;
1129 	default:
1130 		return -ENOENT;
1131 	}
1132 
1133 	return ret;
1134 }
1135 
1136 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
1137 static int rk1808_gmac_set_parent(struct clk *clk, struct clk *parent)
1138 {
1139 	struct rk1808_clk_priv *priv = dev_get_priv(clk->dev);
1140 	struct rk1808_cru *cru = priv->cru;
1141 
1142 	if (parent->id == SCLK_GMAC_SRC) {
1143 		debug("%s: switching GAMC to SCLK_GMAC_SRC\n", __func__);
1144 		rk_clrsetreg(&cru->clksel_con[27], RMII_EXTCLK_SEL_MASK,
1145 			     RMII_EXTCLK_SEL_INT << RMII_EXTCLK_SEL_SHIFT);
1146 	} else {
1147 		debug("%s: switching GMAC to external clock\n", __func__);
1148 		rk_clrsetreg(&cru->clksel_con[27], RMII_EXTCLK_SEL_MASK,
1149 			     RMII_EXTCLK_SEL_EXT << RMII_EXTCLK_SEL_SHIFT);
1150 	}
1151 	return 0;
1152 }
1153 
1154 static int rk1808_clk_set_parent(struct clk *clk, struct clk *parent)
1155 {
1156 	switch (clk->id) {
1157 	case SCLK_GMAC:
1158 		return rk1808_gmac_set_parent(clk, parent);
1159 	case SCLK_32K_IOE:
1160 		return 0;
1161 	default:
1162 		return -ENOENT;
1163 	}
1164 }
1165 #endif
1166 
1167 static struct clk_ops rk1808_clk_ops = {
1168 	.get_rate = rk1808_clk_get_rate,
1169 	.set_rate = rk1808_clk_set_rate,
1170 	.get_phase	= rk1808_clk_get_phase,
1171 	.set_phase	= rk1808_clk_set_phase,
1172 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
1173 	.set_parent	= rk1808_clk_set_parent,
1174 #endif
1175 };
1176 
1177 static int rk1808_clk_probe(struct udevice *dev)
1178 {
1179 	struct rk1808_clk_priv *priv = dev_get_priv(dev);
1180 	int ret;
1181 
1182 	priv->sync_kernel = false;
1183 	if (!priv->armclk_enter_hz) {
1184 		priv->armclk_enter_hz =
1185 		rockchip_pll_get_rate(&rk1808_pll_clks[APLL],
1186 				      priv->cru, APLL);
1187 		priv->armclk_init_hz = priv->armclk_enter_hz;
1188 	}
1189 	if (rockchip_pll_get_rate(&rk1808_pll_clks[APLL],
1190 				  priv->cru, APLL) != APLL_HZ) {
1191 		ret = rk1808_armclk_set_clk(priv, APLL_HZ);
1192 		if (ret < 0)
1193 			printf("%s failed to set armclk rate\n", __func__);
1194 		priv->armclk_init_hz = APLL_HZ;
1195 	}
1196 
1197 	priv->cpll_hz = rockchip_pll_get_rate(&rk1808_pll_clks[CPLL],
1198 					      priv->cru, CPLL);
1199 	priv->gpll_hz = rockchip_pll_get_rate(&rk1808_pll_clks[GPLL],
1200 					      priv->cru, GPLL);
1201 	priv->npll_hz = rockchip_pll_get_rate(&rk1808_pll_clks[NPLL],
1202 					      priv->cru, NPLL);
1203 
1204 	/* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
1205 	ret = clk_set_defaults(dev);
1206 	if (ret)
1207 		debug("%s clk_set_defaults failed %d\n", __func__, ret);
1208 	else
1209 		priv->sync_kernel = true;
1210 
1211 	return 0;
1212 }
1213 
1214 static int rk1808_clk_ofdata_to_platdata(struct udevice *dev)
1215 {
1216 	struct rk1808_clk_priv *priv = dev_get_priv(dev);
1217 
1218 	priv->cru = dev_read_addr_ptr(dev);
1219 
1220 	return 0;
1221 }
1222 
1223 static int rk1808_clk_bind(struct udevice *dev)
1224 {
1225 	int ret;
1226 	struct udevice *sys_child, *sf_child;
1227 	struct sysreset_reg *priv;
1228 	struct softreset_reg *sf_priv;
1229 
1230 	/* The reset driver does not have a device node, so bind it here */
1231 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
1232 				 &sys_child);
1233 	if (ret) {
1234 		debug("Warning: No sysreset driver: ret=%d\n", ret);
1235 	} else {
1236 		priv = malloc(sizeof(struct sysreset_reg));
1237 		priv->glb_srst_fst_value = offsetof(struct rk1808_cru,
1238 						    glb_srst_fst);
1239 		priv->glb_srst_snd_value = offsetof(struct rk1808_cru,
1240 						    glb_srst_snd);
1241 		sys_child->priv = priv;
1242 	}
1243 
1244 	ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
1245 					 dev_ofnode(dev), &sf_child);
1246 	if (ret) {
1247 		debug("Warning: No rockchip reset driver: ret=%d\n", ret);
1248 	} else {
1249 		sf_priv = malloc(sizeof(struct softreset_reg));
1250 		sf_priv->sf_reset_offset = offsetof(struct rk1808_cru,
1251 						    softrst_con[0]);
1252 		sf_priv->sf_reset_num = 16;
1253 		sf_child->priv = sf_priv;
1254 	}
1255 
1256 	return 0;
1257 }
1258 
1259 static const struct udevice_id rk1808_clk_ids[] = {
1260 	{ .compatible = "rockchip,rk1808-cru" },
1261 	{ }
1262 };
1263 
1264 U_BOOT_DRIVER(rockchip_rk1808_cru) = {
1265 	.name		= "rockchip_rk1808_cru",
1266 	.id		= UCLASS_CLK,
1267 	.of_match	= rk1808_clk_ids,
1268 	.priv_auto_alloc_size = sizeof(struct rk1808_clk_priv),
1269 	.ofdata_to_platdata = rk1808_clk_ofdata_to_platdata,
1270 	.ops		= &rk1808_clk_ops,
1271 	.bind		= rk1808_clk_bind,
1272 	.probe		= rk1808_clk_probe,
1273 };
1274 
1275 #ifndef CONFIG_SPL_BUILD
1276 /**
1277  * soc_clk_dump() - Print clock frequencies
1278  * Returns zero on success
1279  *
1280  * Implementation for the clk dump command.
1281  */
1282 int soc_clk_dump(void)
1283 {
1284 	struct udevice *cru_dev;
1285 	struct rk1808_clk_priv *priv;
1286 	const struct rk1808_clk_info *clk_dump;
1287 	struct clk clk;
1288 	unsigned long clk_count = ARRAY_SIZE(clks_dump);
1289 	unsigned long rate;
1290 	int i, ret;
1291 
1292 	ret = uclass_get_device_by_driver(UCLASS_CLK,
1293 					  DM_GET_DRIVER(rockchip_rk1808_cru),
1294 					  &cru_dev);
1295 	if (ret) {
1296 		printf("%s failed to get cru device\n", __func__);
1297 		return ret;
1298 	}
1299 
1300 	priv = dev_get_priv(cru_dev);
1301 	printf("CLK: (%s. arm: enter %lu KHz, init %lu KHz, kernel %lu%s)\n",
1302 	       priv->sync_kernel ? "sync kernel" : "uboot",
1303 	       priv->armclk_enter_hz / 1000,
1304 	       priv->armclk_init_hz / 1000,
1305 	       priv->set_armclk_rate ? priv->armclk_hz / 1000 : 0,
1306 	       priv->set_armclk_rate ? " KHz" : "N/A");
1307 
1308 	for (i = 0; i < clk_count; i++) {
1309 		clk_dump = &clks_dump[i];
1310 		if (clk_dump->name) {
1311 			clk.id = clk_dump->id;
1312 			if (clk_dump->is_cru)
1313 				ret = clk_request(cru_dev, &clk);
1314 			if (ret < 0)
1315 				return ret;
1316 
1317 			rate = clk_get_rate(&clk);
1318 			clk_free(&clk);
1319 			if (i == 0) {
1320 				if (rate < 0)
1321 					printf("  %s %s\n", clk_dump->name,
1322 					       "unknown");
1323 				else
1324 					printf("  %s %lu KHz\n", clk_dump->name,
1325 					       rate / 1000);
1326 			} else {
1327 				if (rate < 0)
1328 					printf("  %s %s\n", clk_dump->name,
1329 					       "unknown");
1330 				else
1331 					printf("  %s %lu KHz\n", clk_dump->name,
1332 					       rate / 1000);
1333 			}
1334 		}
1335 	}
1336 
1337 	return 0;
1338 }
1339 #endif
1340