xref: /openbmc/u-boot/drivers/clk/rockchip/clk_rk3328.c (revision d024236e5a31a2b4b82cbcc98b31b8170fc88d28)
1 /*
2  * (C) Copyright 2017 Rockchip Electronics Co., Ltd
3  *
4  * SPDX-License-Identifier:	GPL-2.0
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 <syscon.h>
13 #include <asm/arch/clock.h>
14 #include <asm/arch/cru_rk3328.h>
15 #include <asm/arch/hardware.h>
16 #include <asm/arch/grf_rk3328.h>
17 #include <asm/io.h>
18 #include <dm/lists.h>
19 #include <dt-bindings/clock/rk3328-cru.h>
20 
21 struct pll_div {
22 	u32 refdiv;
23 	u32 fbdiv;
24 	u32 postdiv1;
25 	u32 postdiv2;
26 	u32 frac;
27 };
28 
29 #define RATE_TO_DIV(input_rate, output_rate) \
30 	((input_rate) / (output_rate) - 1);
31 #define DIV_TO_RATE(input_rate, div)    ((input_rate) / ((div) + 1))
32 
33 #define PLL_DIVISORS(hz, _refdiv, _postdiv1, _postdiv2) {\
34 	.refdiv = _refdiv,\
35 	.fbdiv = (u32)((u64)hz * _refdiv * _postdiv1 * _postdiv2 / OSC_HZ),\
36 	.postdiv1 = _postdiv1, .postdiv2 = _postdiv2};
37 
38 static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 1, 4, 1);
39 static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 2, 2, 1);
40 
41 static const struct pll_div apll_816_cfg = PLL_DIVISORS(816 * MHz, 1, 2, 1);
42 static const struct pll_div apll_600_cfg = PLL_DIVISORS(600 * MHz, 1, 3, 1);
43 
44 static const struct pll_div *apll_cfgs[] = {
45 	[APLL_816_MHZ] = &apll_816_cfg,
46 	[APLL_600_MHZ] = &apll_600_cfg,
47 };
48 
49 enum {
50 	/* PLL_CON0 */
51 	PLL_POSTDIV1_SHIFT		= 12,
52 	PLL_POSTDIV1_MASK		= 0x7 << PLL_POSTDIV1_SHIFT,
53 	PLL_FBDIV_SHIFT			= 0,
54 	PLL_FBDIV_MASK			= 0xfff,
55 
56 	/* PLL_CON1 */
57 	PLL_DSMPD_SHIFT			= 12,
58 	PLL_DSMPD_MASK			= 1 << PLL_DSMPD_SHIFT,
59 	PLL_INTEGER_MODE		= 1,
60 	PLL_LOCK_STATUS_SHIFT		= 10,
61 	PLL_LOCK_STATUS_MASK		= 1 << PLL_LOCK_STATUS_SHIFT,
62 	PLL_POSTDIV2_SHIFT		= 6,
63 	PLL_POSTDIV2_MASK		= 0x7 << PLL_POSTDIV2_SHIFT,
64 	PLL_REFDIV_SHIFT		= 0,
65 	PLL_REFDIV_MASK			= 0x3f,
66 
67 	/* PLL_CON2 */
68 	PLL_FRACDIV_SHIFT		= 0,
69 	PLL_FRACDIV_MASK		= 0xffffff,
70 
71 	/* MODE_CON */
72 	APLL_MODE_SHIFT			= 0,
73 	NPLL_MODE_SHIFT			= 1,
74 	DPLL_MODE_SHIFT			= 4,
75 	CPLL_MODE_SHIFT			= 8,
76 	GPLL_MODE_SHIFT			= 12,
77 	PLL_MODE_SLOW			= 0,
78 	PLL_MODE_NORM,
79 
80 	/* CLKSEL_CON0 */
81 	CLK_CORE_PLL_SEL_APLL		= 0,
82 	CLK_CORE_PLL_SEL_GPLL,
83 	CLK_CORE_PLL_SEL_DPLL,
84 	CLK_CORE_PLL_SEL_NPLL,
85 	CLK_CORE_PLL_SEL_SHIFT		= 6,
86 	CLK_CORE_PLL_SEL_MASK		= 3 << CLK_CORE_PLL_SEL_SHIFT,
87 	CLK_CORE_DIV_SHIFT		= 0,
88 	CLK_CORE_DIV_MASK		= 0x1f,
89 
90 	/* CLKSEL_CON1 */
91 	ACLKM_CORE_DIV_SHIFT		= 4,
92 	ACLKM_CORE_DIV_MASK		= 0x7 << ACLKM_CORE_DIV_SHIFT,
93 	PCLK_DBG_DIV_SHIFT		= 0,
94 	PCLK_DBG_DIV_MASK		= 0xF << PCLK_DBG_DIV_SHIFT,
95 
96 	/* CLKSEL_CON27 */
97 	GMAC2IO_PLL_SEL_SHIFT		= 7,
98 	GMAC2IO_PLL_SEL_MASK		= 1 << GMAC2IO_PLL_SEL_SHIFT,
99 	GMAC2IO_PLL_SEL_CPLL		= 0,
100 	GMAC2IO_PLL_SEL_GPLL		= 1,
101 	GMAC2IO_CLK_DIV_MASK		= 0x1f,
102 	GMAC2IO_CLK_DIV_SHIFT		= 0,
103 
104 	/* CLKSEL_CON28 */
105 	ACLK_PERIHP_PLL_SEL_CPLL	= 0,
106 	ACLK_PERIHP_PLL_SEL_GPLL,
107 	ACLK_PERIHP_PLL_SEL_HDMIPHY,
108 	ACLK_PERIHP_PLL_SEL_SHIFT	= 6,
109 	ACLK_PERIHP_PLL_SEL_MASK	= 3 << ACLK_PERIHP_PLL_SEL_SHIFT,
110 	ACLK_PERIHP_DIV_CON_SHIFT	= 0,
111 	ACLK_PERIHP_DIV_CON_MASK	= 0x1f,
112 
113 	/* CLKSEL_CON29 */
114 	PCLK_PERIHP_DIV_CON_SHIFT	= 4,
115 	PCLK_PERIHP_DIV_CON_MASK	= 0x7 << PCLK_PERIHP_DIV_CON_SHIFT,
116 	HCLK_PERIHP_DIV_CON_SHIFT	= 0,
117 	HCLK_PERIHP_DIV_CON_MASK	= 3 << HCLK_PERIHP_DIV_CON_SHIFT,
118 
119 	/* CLKSEL_CON22 */
120 	CLK_TSADC_DIV_CON_SHIFT		= 0,
121 	CLK_TSADC_DIV_CON_MASK		= 0x3ff,
122 
123 	/* CLKSEL_CON23 */
124 	CLK_SARADC_DIV_CON_SHIFT	= 0,
125 	CLK_SARADC_DIV_CON_MASK		= GENMASK(9, 0),
126 	CLK_SARADC_DIV_CON_WIDTH	= 10,
127 
128 	/* CLKSEL_CON24 */
129 	CLK_PWM_PLL_SEL_CPLL		= 0,
130 	CLK_PWM_PLL_SEL_GPLL,
131 	CLK_PWM_PLL_SEL_SHIFT		= 15,
132 	CLK_PWM_PLL_SEL_MASK		= 1 << CLK_PWM_PLL_SEL_SHIFT,
133 	CLK_PWM_DIV_CON_SHIFT		= 8,
134 	CLK_PWM_DIV_CON_MASK		= 0x7f << CLK_PWM_DIV_CON_SHIFT,
135 
136 	CLK_SPI_PLL_SEL_CPLL		= 0,
137 	CLK_SPI_PLL_SEL_GPLL,
138 	CLK_SPI_PLL_SEL_SHIFT		= 7,
139 	CLK_SPI_PLL_SEL_MASK		= 1 << CLK_SPI_PLL_SEL_SHIFT,
140 	CLK_SPI_DIV_CON_SHIFT		= 0,
141 	CLK_SPI_DIV_CON_MASK		= 0x7f << CLK_SPI_DIV_CON_SHIFT,
142 
143 	/* CLKSEL_CON30 */
144 	CLK_SDMMC_PLL_SEL_CPLL		= 0,
145 	CLK_SDMMC_PLL_SEL_GPLL,
146 	CLK_SDMMC_PLL_SEL_24M,
147 	CLK_SDMMC_PLL_SEL_USBPHY,
148 	CLK_SDMMC_PLL_SHIFT		= 8,
149 	CLK_SDMMC_PLL_MASK		= 0x3 << CLK_SDMMC_PLL_SHIFT,
150 	CLK_SDMMC_DIV_CON_SHIFT          = 0,
151 	CLK_SDMMC_DIV_CON_MASK           = 0xff << CLK_SDMMC_DIV_CON_SHIFT,
152 
153 	/* CLKSEL_CON32 */
154 	CLK_EMMC_PLL_SEL_CPLL		= 0,
155 	CLK_EMMC_PLL_SEL_GPLL,
156 	CLK_EMMC_PLL_SEL_24M,
157 	CLK_EMMC_PLL_SEL_USBPHY,
158 	CLK_EMMC_PLL_SHIFT		= 8,
159 	CLK_EMMC_PLL_MASK		= 0x3 << CLK_EMMC_PLL_SHIFT,
160 	CLK_EMMC_DIV_CON_SHIFT          = 0,
161 	CLK_EMMC_DIV_CON_MASK           = 0xff << CLK_EMMC_DIV_CON_SHIFT,
162 
163 	/* CLKSEL_CON34 */
164 	CLK_I2C_PLL_SEL_CPLL		= 0,
165 	CLK_I2C_PLL_SEL_GPLL,
166 	CLK_I2C_DIV_CON_MASK		= 0x7f,
167 	CLK_I2C_PLL_SEL_MASK		= 1,
168 	CLK_I2C1_PLL_SEL_SHIFT		= 15,
169 	CLK_I2C1_DIV_CON_SHIFT		= 8,
170 	CLK_I2C0_PLL_SEL_SHIFT		= 7,
171 	CLK_I2C0_DIV_CON_SHIFT		= 0,
172 
173 	/* CLKSEL_CON35 */
174 	CLK_I2C3_PLL_SEL_SHIFT		= 15,
175 	CLK_I2C3_DIV_CON_SHIFT		= 8,
176 	CLK_I2C2_PLL_SEL_SHIFT		= 7,
177 	CLK_I2C2_DIV_CON_SHIFT		= 0,
178 };
179 
180 #define VCO_MAX_KHZ	(3200 * (MHz / KHz))
181 #define VCO_MIN_KHZ	(800 * (MHz / KHz))
182 #define OUTPUT_MAX_KHZ	(3200 * (MHz / KHz))
183 #define OUTPUT_MIN_KHZ	(16 * (MHz / KHz))
184 
185 /*
186  *  the div restructions of pll in integer mode, these are defined in
187  *  * CRU_*PLL_CON0 or PMUCRU_*PLL_CON0
188  */
189 #define PLL_DIV_MIN	16
190 #define PLL_DIV_MAX	3200
191 
192 /*
193  * How to calculate the PLL(from TRM V0.3 Part 1 Page 63):
194  * Formulas also embedded within the Fractional PLL Verilog model:
195  * If DSMPD = 1 (DSM is disabled, "integer mode")
196  * FOUTVCO = FREF / REFDIV * FBDIV
197  * FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2
198  * Where:
199  * FOUTVCO = Fractional PLL non-divided output frequency
200  * FOUTPOSTDIV = Fractional PLL divided output frequency
201  *               (output of second post divider)
202  * FREF = Fractional PLL input reference frequency, (the OSC_HZ 24MHz input)
203  * REFDIV = Fractional PLL input reference clock divider
204  * FBDIV = Integer value programmed into feedback divide
205  *
206  */
207 static void rkclk_set_pll(struct rk3328_cru *cru, enum rk_clk_id clk_id,
208 			const struct pll_div *div)
209 {
210 	u32 *pll_con;
211 	u32 mode_shift, mode_mask;
212 
213 	pll_con = NULL;
214 	mode_shift = 0;
215 	switch (clk_id) {
216 	case CLK_ARM:
217 		pll_con = cru->apll_con;
218 		mode_shift = APLL_MODE_SHIFT;
219 		break;
220 	case CLK_DDR:
221 		pll_con = cru->dpll_con;
222 		mode_shift = DPLL_MODE_SHIFT;
223 		break;
224 	case CLK_CODEC:
225 		pll_con = cru->cpll_con;
226 		mode_shift = CPLL_MODE_SHIFT;
227 		break;
228 	case CLK_GENERAL:
229 		pll_con = cru->gpll_con;
230 		mode_shift = GPLL_MODE_SHIFT;
231 		break;
232 	case CLK_NEW:
233 		pll_con = cru->npll_con;
234 		mode_shift = NPLL_MODE_SHIFT;
235 		break;
236 	default:
237 		break;
238 	}
239 	mode_mask = 1 << mode_shift;
240 
241 	/* All 8 PLLs have same VCO and output frequency range restrictions. */
242 	u32 vco_khz = OSC_HZ / 1000 * div->fbdiv / div->refdiv;
243 	u32 output_khz = vco_khz / div->postdiv1 / div->postdiv2;
244 
245 	debug("PLL at %p: fbdiv=%d, refdiv=%d, postdiv1=%d, \
246 	      postdiv2=%d, vco=%u khz, output=%u khz\n",
247 	      pll_con, div->fbdiv, div->refdiv, div->postdiv1,
248 	      div->postdiv2, vco_khz, output_khz);
249 	assert(vco_khz >= VCO_MIN_KHZ && vco_khz <= VCO_MAX_KHZ &&
250 	       output_khz >= OUTPUT_MIN_KHZ && output_khz <= OUTPUT_MAX_KHZ &&
251 	       div->fbdiv >= PLL_DIV_MIN && div->fbdiv <= PLL_DIV_MAX);
252 
253 	/*
254 	 * When power on or changing PLL setting,
255 	 * we must force PLL into slow mode to ensure output stable clock.
256 	 */
257 	rk_clrsetreg(&cru->mode_con, mode_mask, PLL_MODE_SLOW << mode_shift);
258 
259 	/* use integer mode */
260 	rk_clrsetreg(&pll_con[1], PLL_DSMPD_MASK,
261 		     PLL_INTEGER_MODE << PLL_DSMPD_SHIFT);
262 
263 	rk_clrsetreg(&pll_con[0],
264 		     PLL_FBDIV_MASK | PLL_POSTDIV1_MASK,
265 		     (div->fbdiv << PLL_FBDIV_SHIFT) |
266 		     (div->postdiv1 << PLL_POSTDIV1_SHIFT));
267 	rk_clrsetreg(&pll_con[1],
268 		     PLL_POSTDIV2_MASK | PLL_REFDIV_MASK,
269 		     (div->postdiv2 << PLL_POSTDIV2_SHIFT) |
270 		     (div->refdiv << PLL_REFDIV_SHIFT));
271 
272 	/* waiting for pll lock */
273 	while (!(readl(&pll_con[1]) & (1 << PLL_LOCK_STATUS_SHIFT)))
274 		udelay(1);
275 
276 	/* pll enter normal mode */
277 	rk_clrsetreg(&cru->mode_con, mode_mask, PLL_MODE_NORM << mode_shift);
278 }
279 
280 static void rkclk_init(struct rk3328_cru *cru)
281 {
282 	u32 aclk_div;
283 	u32 hclk_div;
284 	u32 pclk_div;
285 
286 	/* configure gpll cpll */
287 	rkclk_set_pll(cru, CLK_GENERAL, &gpll_init_cfg);
288 	rkclk_set_pll(cru, CLK_CODEC, &cpll_init_cfg);
289 
290 	/* configure perihp aclk, hclk, pclk */
291 	aclk_div = GPLL_HZ / PERIHP_ACLK_HZ - 1;
292 	hclk_div = PERIHP_ACLK_HZ / PERIHP_HCLK_HZ - 1;
293 	pclk_div = PERIHP_ACLK_HZ / PERIHP_PCLK_HZ - 1;
294 
295 	rk_clrsetreg(&cru->clksel_con[28],
296 		     ACLK_PERIHP_PLL_SEL_MASK | ACLK_PERIHP_DIV_CON_MASK,
297 		     ACLK_PERIHP_PLL_SEL_GPLL << ACLK_PERIHP_PLL_SEL_SHIFT |
298 		     aclk_div << ACLK_PERIHP_DIV_CON_SHIFT);
299 	rk_clrsetreg(&cru->clksel_con[29],
300 		     PCLK_PERIHP_DIV_CON_MASK | HCLK_PERIHP_DIV_CON_MASK,
301 		     pclk_div << PCLK_PERIHP_DIV_CON_SHIFT |
302 		     hclk_div << HCLK_PERIHP_DIV_CON_SHIFT);
303 }
304 
305 void rk3328_configure_cpu(struct rk3328_cru *cru,
306 			  enum apll_frequencies apll_freq)
307 {
308 	u32 clk_core_div;
309 	u32 aclkm_div;
310 	u32 pclk_dbg_div;
311 
312 	rkclk_set_pll(cru, CLK_ARM, apll_cfgs[apll_freq]);
313 
314 	clk_core_div = APLL_HZ / CLK_CORE_HZ - 1;
315 	aclkm_div = APLL_HZ / ACLKM_CORE_HZ / (clk_core_div + 1) - 1;
316 	pclk_dbg_div = APLL_HZ / PCLK_DBG_HZ / (clk_core_div + 1) - 1;
317 
318 	rk_clrsetreg(&cru->clksel_con[0],
319 		     CLK_CORE_PLL_SEL_MASK | CLK_CORE_DIV_MASK,
320 		     CLK_CORE_PLL_SEL_APLL << CLK_CORE_PLL_SEL_SHIFT |
321 		     clk_core_div << CLK_CORE_DIV_SHIFT);
322 
323 	rk_clrsetreg(&cru->clksel_con[1],
324 		     PCLK_DBG_DIV_MASK | ACLKM_CORE_DIV_MASK,
325 		     pclk_dbg_div << PCLK_DBG_DIV_SHIFT |
326 		     aclkm_div << ACLKM_CORE_DIV_SHIFT);
327 }
328 
329 
330 static ulong rk3328_i2c_get_clk(struct rk3328_cru *cru, ulong clk_id)
331 {
332 	u32 div, con;
333 
334 	switch (clk_id) {
335 	case SCLK_I2C0:
336 		con = readl(&cru->clksel_con[34]);
337 		div = con >> CLK_I2C0_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
338 		break;
339 	case SCLK_I2C1:
340 		con = readl(&cru->clksel_con[34]);
341 		div = con >> CLK_I2C1_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
342 		break;
343 	case SCLK_I2C2:
344 		con = readl(&cru->clksel_con[35]);
345 		div = con >> CLK_I2C2_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
346 		break;
347 	case SCLK_I2C3:
348 		con = readl(&cru->clksel_con[35]);
349 		div = con >> CLK_I2C3_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
350 		break;
351 	default:
352 		printf("do not support this i2c bus\n");
353 		return -EINVAL;
354 	}
355 
356 	return DIV_TO_RATE(GPLL_HZ, div);
357 }
358 
359 static ulong rk3328_i2c_set_clk(struct rk3328_cru *cru, ulong clk_id, uint hz)
360 {
361 	int src_clk_div;
362 
363 	src_clk_div = GPLL_HZ / hz;
364 	assert(src_clk_div - 1 < 127);
365 
366 	switch (clk_id) {
367 	case SCLK_I2C0:
368 		rk_clrsetreg(&cru->clksel_con[34],
369 			     CLK_I2C_DIV_CON_MASK << CLK_I2C0_DIV_CON_SHIFT |
370 			     CLK_I2C_PLL_SEL_MASK << CLK_I2C0_PLL_SEL_SHIFT,
371 			     (src_clk_div - 1) << CLK_I2C0_DIV_CON_SHIFT |
372 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C0_PLL_SEL_SHIFT);
373 		break;
374 	case SCLK_I2C1:
375 		rk_clrsetreg(&cru->clksel_con[34],
376 			     CLK_I2C_DIV_CON_MASK << CLK_I2C1_DIV_CON_SHIFT |
377 			     CLK_I2C_PLL_SEL_MASK << CLK_I2C1_PLL_SEL_SHIFT,
378 			     (src_clk_div - 1) << CLK_I2C1_DIV_CON_SHIFT |
379 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT);
380 		break;
381 	case SCLK_I2C2:
382 		rk_clrsetreg(&cru->clksel_con[35],
383 			     CLK_I2C_DIV_CON_MASK << CLK_I2C2_DIV_CON_SHIFT |
384 			     CLK_I2C_PLL_SEL_MASK << CLK_I2C2_PLL_SEL_SHIFT,
385 			     (src_clk_div - 1) << CLK_I2C2_DIV_CON_SHIFT |
386 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C2_PLL_SEL_SHIFT);
387 		break;
388 	case SCLK_I2C3:
389 		rk_clrsetreg(&cru->clksel_con[35],
390 			     CLK_I2C_DIV_CON_MASK << CLK_I2C3_DIV_CON_SHIFT |
391 			     CLK_I2C_PLL_SEL_MASK << CLK_I2C3_PLL_SEL_SHIFT,
392 			     (src_clk_div - 1) << CLK_I2C3_DIV_CON_SHIFT |
393 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT);
394 		break;
395 	default:
396 		printf("do not support this i2c bus\n");
397 		return -EINVAL;
398 	}
399 
400 	return DIV_TO_RATE(GPLL_HZ, src_clk_div);
401 }
402 
403 static ulong rk3328_gmac2io_set_clk(struct rk3328_cru *cru, ulong rate)
404 {
405 	struct rk3328_grf_regs *grf;
406 	ulong ret;
407 
408 	grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
409 
410 	/*
411 	 * The RGMII CLK can be derived either from an external "clkin"
412 	 * or can be generated from internally by a divider from SCLK_MAC.
413 	 */
414 	if (readl(&grf->mac_con[1]) & BIT(10) &&
415 	    readl(&grf->soc_con[4]) & BIT(14)) {
416 		/* An external clock will always generate the right rate... */
417 		ret = rate;
418 	} else {
419 		u32 con = readl(&cru->clksel_con[27]);
420 		ulong pll_rate;
421 		u8 div;
422 
423 		if ((con >> GMAC2IO_PLL_SEL_SHIFT) & GMAC2IO_PLL_SEL_GPLL)
424 			pll_rate = GPLL_HZ;
425 		else
426 			pll_rate = CPLL_HZ;
427 
428 		div = DIV_ROUND_UP(pll_rate, rate) - 1;
429 		if (div <= 0x1f)
430 			rk_clrsetreg(&cru->clksel_con[27], GMAC2IO_CLK_DIV_MASK,
431 				     div << GMAC2IO_CLK_DIV_SHIFT);
432 		else
433 			debug("Unsupported div for gmac:%d\n", div);
434 
435 		return DIV_TO_RATE(pll_rate, div);
436 	}
437 
438 	return ret;
439 }
440 
441 static ulong rk3328_mmc_get_clk(struct rk3328_cru *cru, uint clk_id)
442 {
443 	u32 div, con, con_id;
444 
445 	switch (clk_id) {
446 	case HCLK_SDMMC:
447 	case SCLK_SDMMC:
448 		con_id = 30;
449 		break;
450 	case HCLK_EMMC:
451 	case SCLK_EMMC:
452 		con_id = 32;
453 		break;
454 	default:
455 		return -EINVAL;
456 	}
457 	con = readl(&cru->clksel_con[con_id]);
458 	div = (con & CLK_EMMC_DIV_CON_MASK) >> CLK_EMMC_DIV_CON_SHIFT;
459 
460 	if ((con & CLK_EMMC_PLL_MASK) >> CLK_EMMC_PLL_SHIFT
461 	    == CLK_EMMC_PLL_SEL_24M)
462 		return DIV_TO_RATE(OSC_HZ, div) / 2;
463 	else
464 		return DIV_TO_RATE(GPLL_HZ, div) / 2;
465 }
466 
467 static ulong rk3328_mmc_set_clk(struct rk3328_cru *cru,
468 				ulong clk_id, ulong set_rate)
469 {
470 	int src_clk_div;
471 	u32 con_id;
472 
473 	switch (clk_id) {
474 	case HCLK_SDMMC:
475 	case SCLK_SDMMC:
476 		con_id = 30;
477 		break;
478 	case HCLK_EMMC:
479 	case SCLK_EMMC:
480 		con_id = 32;
481 		break;
482 	default:
483 		return -EINVAL;
484 	}
485 	/* Select clk_sdmmc/emmc source from GPLL by default */
486 	/* mmc clock defaulg div 2 internal, need provide double in cru */
487 	src_clk_div = DIV_ROUND_UP(GPLL_HZ / 2, set_rate);
488 
489 	if (src_clk_div > 127) {
490 		/* use 24MHz source for 400KHz clock */
491 		src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate);
492 		rk_clrsetreg(&cru->clksel_con[con_id],
493 			     CLK_EMMC_PLL_MASK | CLK_EMMC_DIV_CON_MASK,
494 			     CLK_EMMC_PLL_SEL_24M << CLK_EMMC_PLL_SHIFT |
495 			     (src_clk_div - 1) << CLK_EMMC_DIV_CON_SHIFT);
496 	} else {
497 		rk_clrsetreg(&cru->clksel_con[con_id],
498 			     CLK_EMMC_PLL_MASK | CLK_EMMC_DIV_CON_MASK,
499 			     CLK_EMMC_PLL_SEL_GPLL << CLK_EMMC_PLL_SHIFT |
500 			     (src_clk_div - 1) << CLK_EMMC_DIV_CON_SHIFT);
501 	}
502 
503 	return rk3328_mmc_get_clk(cru, clk_id);
504 }
505 
506 static ulong rk3328_pwm_get_clk(struct rk3328_cru *cru)
507 {
508 	u32 div, con;
509 
510 	con = readl(&cru->clksel_con[24]);
511 	div = (con & CLK_PWM_DIV_CON_MASK) >> CLK_PWM_DIV_CON_SHIFT;
512 
513 	return DIV_TO_RATE(GPLL_HZ, div);
514 }
515 
516 static ulong rk3328_pwm_set_clk(struct rk3328_cru *cru, uint hz)
517 {
518 	u32 div = GPLL_HZ / hz;
519 
520 	rk_clrsetreg(&cru->clksel_con[24],
521 		     CLK_PWM_PLL_SEL_MASK | CLK_PWM_DIV_CON_MASK,
522 		     CLK_PWM_PLL_SEL_GPLL << CLK_PWM_PLL_SEL_SHIFT |
523 		     (div - 1) << CLK_PWM_DIV_CON_SHIFT);
524 
525 	return DIV_TO_RATE(GPLL_HZ, div);
526 }
527 
528 static ulong rk3328_saradc_get_clk(struct rk3328_cru *cru)
529 {
530 	u32 div, val;
531 
532 	val = readl(&cru->clksel_con[23]);
533 	div = bitfield_extract(val, CLK_SARADC_DIV_CON_SHIFT,
534 			       CLK_SARADC_DIV_CON_WIDTH);
535 
536 	return DIV_TO_RATE(OSC_HZ, div);
537 }
538 
539 static ulong rk3328_saradc_set_clk(struct rk3328_cru *cru, uint hz)
540 {
541 	int src_clk_div;
542 
543 	src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1;
544 	assert(src_clk_div < 128);
545 
546 	rk_clrsetreg(&cru->clksel_con[23],
547 		     CLK_SARADC_DIV_CON_MASK,
548 		     src_clk_div << CLK_SARADC_DIV_CON_SHIFT);
549 
550 	return rk3328_saradc_get_clk(cru);
551 }
552 
553 static ulong rk3328_clk_get_rate(struct clk *clk)
554 {
555 	struct rk3328_clk_priv *priv = dev_get_priv(clk->dev);
556 	ulong rate = 0;
557 
558 	switch (clk->id) {
559 	case 0 ... 29:
560 		return 0;
561 	case HCLK_SDMMC:
562 	case HCLK_EMMC:
563 	case SCLK_SDMMC:
564 	case SCLK_EMMC:
565 		rate = rk3328_mmc_get_clk(priv->cru, clk->id);
566 		break;
567 	case SCLK_I2C0:
568 	case SCLK_I2C1:
569 	case SCLK_I2C2:
570 	case SCLK_I2C3:
571 		rate = rk3328_i2c_get_clk(priv->cru, clk->id);
572 		break;
573 	case SCLK_PWM:
574 		rate = rk3328_pwm_get_clk(priv->cru);
575 		break;
576 	case SCLK_SARADC:
577 		rate = rk3328_saradc_get_clk(priv->cru);
578 		break;
579 	default:
580 		return -ENOENT;
581 	}
582 
583 	return rate;
584 }
585 
586 static ulong rk3328_clk_set_rate(struct clk *clk, ulong rate)
587 {
588 	struct rk3328_clk_priv *priv = dev_get_priv(clk->dev);
589 	ulong ret = 0;
590 
591 	switch (clk->id) {
592 	case 0 ... 29:
593 		return 0;
594 	case HCLK_SDMMC:
595 	case HCLK_EMMC:
596 	case SCLK_SDMMC:
597 	case SCLK_EMMC:
598 		ret = rk3328_mmc_set_clk(priv->cru, clk->id, rate);
599 		break;
600 	case SCLK_I2C0:
601 	case SCLK_I2C1:
602 	case SCLK_I2C2:
603 	case SCLK_I2C3:
604 		ret = rk3328_i2c_set_clk(priv->cru, clk->id, rate);
605 		break;
606 	case SCLK_MAC2IO:
607 		ret = rk3328_gmac2io_set_clk(priv->cru, rate);
608 		break;
609 	case SCLK_PWM:
610 		ret = rk3328_pwm_set_clk(priv->cru, rate);
611 		break;
612 	case SCLK_SARADC:
613 		ret = rk3328_saradc_set_clk(priv->cru, rate);
614 		break;
615 	case DCLK_LCDC:
616 	case SCLK_PDM:
617 	case SCLK_RTC32K:
618 	case SCLK_UART0:
619 	case SCLK_UART1:
620 	case SCLK_UART2:
621 	case SCLK_SDIO:
622 	case SCLK_TSP:
623 	case SCLK_WIFI:
624 	case ACLK_BUS_PRE:
625 	case HCLK_BUS_PRE:
626 	case PCLK_BUS_PRE:
627 	case ACLK_PERI_PRE:
628 	case HCLK_PERI:
629 	case PCLK_PERI:
630 	case ACLK_VIO_PRE:
631 	case HCLK_VIO_PRE:
632 	case ACLK_RGA_PRE:
633 	case SCLK_RGA:
634 	case ACLK_VOP_PRE:
635 	case ACLK_RKVDEC_PRE:
636 	case ACLK_RKVENC:
637 	case ACLK_VPU_PRE:
638 	case SCLK_VDEC_CABAC:
639 	case SCLK_VDEC_CORE:
640 	case SCLK_VENC_CORE:
641 	case SCLK_VENC_DSP:
642 	case SCLK_EFUSE:
643 	case PCLK_DDR:
644 	case ACLK_GMAC:
645 	case PCLK_GMAC:
646 	case SCLK_USB3OTG_SUSPEND:
647 		return 0;
648 	default:
649 		return -ENOENT;
650 	}
651 
652 	return ret;
653 }
654 
655 static int rk3328_gmac2io_set_parent(struct clk *clk, struct clk *parent)
656 {
657 	struct rk3328_grf_regs *grf;
658 	const char *clock_output_name;
659 	int ret;
660 
661 	grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
662 
663 	/*
664 	 * If the requested parent is in the same clock-controller and the id
665 	 * is SCLK_MAC2IO_SRC ("clk_mac2io_src"), switch to the internal clock.
666 	 */
667 	if ((parent->dev == clk->dev) && (parent->id == SCLK_MAC2IO_SRC)) {
668 		debug("%s: switching RGMII to SCLK_MAC2IO_SRC\n", __func__);
669 		rk_clrreg(&grf->mac_con[1], BIT(10));
670 		return 0;
671 	}
672 
673 	/*
674 	 * Otherwise, we need to check the clock-output-names of the
675 	 * requested parent to see if the requested id is "gmac_clkin".
676 	 */
677 	ret = dev_read_string_index(parent->dev, "clock-output-names",
678 				    parent->id, &clock_output_name);
679 	if (ret < 0)
680 		return -ENODATA;
681 
682 	/* If this is "gmac_clkin", switch to the external clock input */
683 	if (!strcmp(clock_output_name, "gmac_clkin")) {
684 		debug("%s: switching RGMII to CLKIN\n", __func__);
685 		rk_setreg(&grf->mac_con[1], BIT(10));
686 		return 0;
687 	}
688 
689 	return -EINVAL;
690 }
691 
692 static int rk3328_gmac2io_ext_set_parent(struct clk *clk, struct clk *parent)
693 {
694 	struct rk3328_grf_regs *grf;
695 	const char *clock_output_name;
696 	int ret;
697 
698 	grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
699 
700 	/*
701 	 * If the requested parent is in the same clock-controller and the id
702 	 * is SCLK_MAC2IO ("clk_mac2io"), switch to the internal clock.
703 	 */
704 	if ((parent->dev == clk->dev) && (parent->id == SCLK_MAC2IO)) {
705 		debug("%s: switching RGMII to SCLK_MAC2IO\n", __func__);
706 		rk_clrreg(&grf->soc_con[4], BIT(14));
707 		return 0;
708 	}
709 
710 	/*
711 	 * Otherwise, we need to check the clock-output-names of the
712 	 * requested parent to see if the requested id is "gmac_clkin".
713 	 */
714 	ret = dev_read_string_index(parent->dev, "clock-output-names",
715 				    parent->id, &clock_output_name);
716 	if (ret < 0)
717 		return -ENODATA;
718 
719 	/* If this is "gmac_clkin", switch to the external clock input */
720 	if (!strcmp(clock_output_name, "gmac_clkin")) {
721 		debug("%s: switching RGMII to CLKIN\n", __func__);
722 		rk_setreg(&grf->soc_con[4], BIT(14));
723 		return 0;
724 	}
725 
726 	return -EINVAL;
727 }
728 
729 static int rk3328_clk_set_parent(struct clk *clk, struct clk *parent)
730 {
731 	switch (clk->id) {
732 	case SCLK_MAC2IO:
733 		return rk3328_gmac2io_set_parent(clk, parent);
734 	case SCLK_MAC2IO_EXT:
735 		return rk3328_gmac2io_ext_set_parent(clk, parent);
736 	case DCLK_LCDC:
737 	case SCLK_PDM:
738 	case SCLK_RTC32K:
739 	case SCLK_UART0:
740 	case SCLK_UART1:
741 	case SCLK_UART2:
742 		return 0;
743 	}
744 
745 	debug("%s: unsupported clk %ld\n", __func__, clk->id);
746 	return -ENOENT;
747 }
748 
749 static struct clk_ops rk3328_clk_ops = {
750 	.get_rate = rk3328_clk_get_rate,
751 	.set_rate = rk3328_clk_set_rate,
752 	.set_parent = rk3328_clk_set_parent,
753 };
754 
755 static int rk3328_clk_probe(struct udevice *dev)
756 {
757 	struct rk3328_clk_priv *priv = dev_get_priv(dev);
758 
759 	rkclk_init(priv->cru);
760 
761 	return 0;
762 }
763 
764 static int rk3328_clk_ofdata_to_platdata(struct udevice *dev)
765 {
766 	struct rk3328_clk_priv *priv = dev_get_priv(dev);
767 
768 	priv->cru = dev_read_addr_ptr(dev);
769 
770 	return 0;
771 }
772 
773 static int rk3328_clk_bind(struct udevice *dev)
774 {
775 	int ret;
776 	struct udevice *sys_child;
777 	struct sysreset_reg *priv;
778 
779 	/* The reset driver does not have a device node, so bind it here */
780 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
781 				 &sys_child);
782 	if (ret) {
783 		debug("Warning: No sysreset driver: ret=%d\n", ret);
784 	} else {
785 		priv = malloc(sizeof(struct sysreset_reg));
786 		priv->glb_srst_fst_value = offsetof(struct rk3328_cru,
787 						    glb_srst_fst_value);
788 		priv->glb_srst_snd_value = offsetof(struct rk3328_cru,
789 						    glb_srst_snd_value);
790 		sys_child->priv = priv;
791 	}
792 
793 #if CONFIG_IS_ENABLED(CONFIG_RESET_ROCKCHIP)
794 	ret = offsetof(struct rk3328_cru, softrst_con[0]);
795 	ret = rockchip_reset_bind(dev, ret, 12);
796 	if (ret)
797 		debug("Warning: software reset driver bind faile\n");
798 #endif
799 
800 	return ret;
801 }
802 
803 static const struct udevice_id rk3328_clk_ids[] = {
804 	{ .compatible = "rockchip,rk3328-cru" },
805 	{ }
806 };
807 
808 U_BOOT_DRIVER(rockchip_rk3328_cru) = {
809 	.name		= "rockchip_rk3328_cru",
810 	.id		= UCLASS_CLK,
811 	.of_match	= rk3328_clk_ids,
812 	.priv_auto_alloc_size = sizeof(struct rk3328_clk_priv),
813 	.ofdata_to_platdata = rk3328_clk_ofdata_to_platdata,
814 	.ops		= &rk3328_clk_ops,
815 	.bind		= rk3328_clk_bind,
816 	.probe		= rk3328_clk_probe,
817 };
818