1 /*
2  * (C) Copyright 2015 Google, Inc
3  *
4  * SPDX-License-Identifier:	GPL-2.0
5  */
6 
7 #include <common.h>
8 #include <clk-uclass.h>
9 #include <dm.h>
10 #include <dt-structs.h>
11 #include <errno.h>
12 #include <mapmem.h>
13 #include <syscon.h>
14 #include <asm/io.h>
15 #include <asm/arch/clock.h>
16 #include <asm/arch/cru_rk3399.h>
17 #include <asm/arch/hardware.h>
18 #include <dm/lists.h>
19 #include <dt-bindings/clock/rk3399-cru.h>
20 
21 DECLARE_GLOBAL_DATA_PTR;
22 
23 #if CONFIG_IS_ENABLED(OF_PLATDATA)
24 struct rk3399_clk_plat {
25 	struct dtd_rockchip_rk3399_cru dtd;
26 };
27 
28 struct rk3399_pmuclk_plat {
29 	struct dtd_rockchip_rk3399_pmucru dtd;
30 };
31 #endif
32 
33 struct pll_div {
34 	u32 refdiv;
35 	u32 fbdiv;
36 	u32 postdiv1;
37 	u32 postdiv2;
38 	u32 frac;
39 };
40 
41 #define RATE_TO_DIV(input_rate, output_rate) \
42 	((input_rate) / (output_rate) - 1);
43 #define DIV_TO_RATE(input_rate, div)    ((input_rate) / ((div) + 1))
44 
45 #define PLL_DIVISORS(hz, _refdiv, _postdiv1, _postdiv2) {\
46 	.refdiv = _refdiv,\
47 	.fbdiv = (u32)((u64)hz * _refdiv * _postdiv1 * _postdiv2 / OSC_HZ),\
48 	.postdiv1 = _postdiv1, .postdiv2 = _postdiv2};
49 
50 static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 2, 2, 1);
51 static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 1, 2, 2);
52 static const struct pll_div ppll_init_cfg = PLL_DIVISORS(PPLL_HZ, 2, 2, 1);
53 
54 static const struct pll_div apll_l_1600_cfg = PLL_DIVISORS(1600*MHz, 3, 1, 1);
55 static const struct pll_div apll_l_600_cfg = PLL_DIVISORS(600*MHz, 1, 2, 1);
56 
57 static const struct pll_div *apll_l_cfgs[] = {
58 	[APLL_L_1600_MHZ] = &apll_l_1600_cfg,
59 	[APLL_L_600_MHZ] = &apll_l_600_cfg,
60 };
61 
62 enum {
63 	/* PLL_CON0 */
64 	PLL_FBDIV_MASK			= 0xfff,
65 	PLL_FBDIV_SHIFT			= 0,
66 
67 	/* PLL_CON1 */
68 	PLL_POSTDIV2_SHIFT		= 12,
69 	PLL_POSTDIV2_MASK		= 0x7 << PLL_POSTDIV2_SHIFT,
70 	PLL_POSTDIV1_SHIFT		= 8,
71 	PLL_POSTDIV1_MASK		= 0x7 << PLL_POSTDIV1_SHIFT,
72 	PLL_REFDIV_MASK			= 0x3f,
73 	PLL_REFDIV_SHIFT		= 0,
74 
75 	/* PLL_CON2 */
76 	PLL_LOCK_STATUS_SHIFT		= 31,
77 	PLL_LOCK_STATUS_MASK		= 1 << PLL_LOCK_STATUS_SHIFT,
78 	PLL_FRACDIV_MASK		= 0xffffff,
79 	PLL_FRACDIV_SHIFT		= 0,
80 
81 	/* PLL_CON3 */
82 	PLL_MODE_SHIFT			= 8,
83 	PLL_MODE_MASK			= 3 << PLL_MODE_SHIFT,
84 	PLL_MODE_SLOW			= 0,
85 	PLL_MODE_NORM,
86 	PLL_MODE_DEEP,
87 	PLL_DSMPD_SHIFT			= 3,
88 	PLL_DSMPD_MASK			= 1 << PLL_DSMPD_SHIFT,
89 	PLL_INTEGER_MODE		= 1,
90 
91 	/* PMUCRU_CLKSEL_CON0 */
92 	PMU_PCLK_DIV_CON_MASK		= 0x1f,
93 	PMU_PCLK_DIV_CON_SHIFT		= 0,
94 
95 	/* PMUCRU_CLKSEL_CON1 */
96 	SPI3_PLL_SEL_SHIFT		= 7,
97 	SPI3_PLL_SEL_MASK		= 1 << SPI3_PLL_SEL_SHIFT,
98 	SPI3_PLL_SEL_24M		= 0,
99 	SPI3_PLL_SEL_PPLL		= 1,
100 	SPI3_DIV_CON_SHIFT		= 0x0,
101 	SPI3_DIV_CON_MASK		= 0x7f,
102 
103 	/* PMUCRU_CLKSEL_CON2 */
104 	I2C_DIV_CON_MASK		= 0x7f,
105 	CLK_I2C8_DIV_CON_SHIFT		= 8,
106 	CLK_I2C0_DIV_CON_SHIFT		= 0,
107 
108 	/* PMUCRU_CLKSEL_CON3 */
109 	CLK_I2C4_DIV_CON_SHIFT		= 0,
110 
111 	/* CLKSEL_CON0 */
112 	ACLKM_CORE_L_DIV_CON_SHIFT	= 8,
113 	ACLKM_CORE_L_DIV_CON_MASK	= 0x1f << ACLKM_CORE_L_DIV_CON_SHIFT,
114 	CLK_CORE_L_PLL_SEL_SHIFT	= 6,
115 	CLK_CORE_L_PLL_SEL_MASK		= 3 << CLK_CORE_L_PLL_SEL_SHIFT,
116 	CLK_CORE_L_PLL_SEL_ALPLL	= 0x0,
117 	CLK_CORE_L_PLL_SEL_ABPLL	= 0x1,
118 	CLK_CORE_L_PLL_SEL_DPLL		= 0x10,
119 	CLK_CORE_L_PLL_SEL_GPLL		= 0x11,
120 	CLK_CORE_L_DIV_MASK		= 0x1f,
121 	CLK_CORE_L_DIV_SHIFT		= 0,
122 
123 	/* CLKSEL_CON1 */
124 	PCLK_DBG_L_DIV_SHIFT		= 0x8,
125 	PCLK_DBG_L_DIV_MASK		= 0x1f << PCLK_DBG_L_DIV_SHIFT,
126 	ATCLK_CORE_L_DIV_SHIFT		= 0,
127 	ATCLK_CORE_L_DIV_MASK		= 0x1f << ATCLK_CORE_L_DIV_SHIFT,
128 
129 	/* CLKSEL_CON14 */
130 	PCLK_PERIHP_DIV_CON_SHIFT	= 12,
131 	PCLK_PERIHP_DIV_CON_MASK	= 0x7 << PCLK_PERIHP_DIV_CON_SHIFT,
132 	HCLK_PERIHP_DIV_CON_SHIFT	= 8,
133 	HCLK_PERIHP_DIV_CON_MASK	= 3 << HCLK_PERIHP_DIV_CON_SHIFT,
134 	ACLK_PERIHP_PLL_SEL_SHIFT	= 7,
135 	ACLK_PERIHP_PLL_SEL_MASK	= 1 << ACLK_PERIHP_PLL_SEL_SHIFT,
136 	ACLK_PERIHP_PLL_SEL_CPLL	= 0,
137 	ACLK_PERIHP_PLL_SEL_GPLL	= 1,
138 	ACLK_PERIHP_DIV_CON_SHIFT	= 0,
139 	ACLK_PERIHP_DIV_CON_MASK	= 0x1f,
140 
141 	/* CLKSEL_CON21 */
142 	ACLK_EMMC_PLL_SEL_SHIFT         = 7,
143 	ACLK_EMMC_PLL_SEL_MASK          = 0x1 << ACLK_EMMC_PLL_SEL_SHIFT,
144 	ACLK_EMMC_PLL_SEL_GPLL          = 0x1,
145 	ACLK_EMMC_DIV_CON_SHIFT         = 0,
146 	ACLK_EMMC_DIV_CON_MASK          = 0x1f,
147 
148 	/* CLKSEL_CON22 */
149 	CLK_EMMC_PLL_SHIFT              = 8,
150 	CLK_EMMC_PLL_MASK               = 0x7 << CLK_EMMC_PLL_SHIFT,
151 	CLK_EMMC_PLL_SEL_GPLL           = 0x1,
152 	CLK_EMMC_PLL_SEL_24M            = 0x5,
153 	CLK_EMMC_DIV_CON_SHIFT          = 0,
154 	CLK_EMMC_DIV_CON_MASK           = 0x7f << CLK_EMMC_DIV_CON_SHIFT,
155 
156 	/* CLKSEL_CON23 */
157 	PCLK_PERILP0_DIV_CON_SHIFT	= 12,
158 	PCLK_PERILP0_DIV_CON_MASK	= 0x7 << PCLK_PERILP0_DIV_CON_SHIFT,
159 	HCLK_PERILP0_DIV_CON_SHIFT	= 8,
160 	HCLK_PERILP0_DIV_CON_MASK	= 3 << HCLK_PERILP0_DIV_CON_SHIFT,
161 	ACLK_PERILP0_PLL_SEL_SHIFT	= 7,
162 	ACLK_PERILP0_PLL_SEL_MASK	= 1 << ACLK_PERILP0_PLL_SEL_SHIFT,
163 	ACLK_PERILP0_PLL_SEL_CPLL	= 0,
164 	ACLK_PERILP0_PLL_SEL_GPLL	= 1,
165 	ACLK_PERILP0_DIV_CON_SHIFT	= 0,
166 	ACLK_PERILP0_DIV_CON_MASK	= 0x1f,
167 
168 	/* CLKSEL_CON25 */
169 	PCLK_PERILP1_DIV_CON_SHIFT	= 8,
170 	PCLK_PERILP1_DIV_CON_MASK	= 0x7 << PCLK_PERILP1_DIV_CON_SHIFT,
171 	HCLK_PERILP1_PLL_SEL_SHIFT	= 7,
172 	HCLK_PERILP1_PLL_SEL_MASK	= 1 << HCLK_PERILP1_PLL_SEL_SHIFT,
173 	HCLK_PERILP1_PLL_SEL_CPLL	= 0,
174 	HCLK_PERILP1_PLL_SEL_GPLL	= 1,
175 	HCLK_PERILP1_DIV_CON_SHIFT	= 0,
176 	HCLK_PERILP1_DIV_CON_MASK	= 0x1f,
177 
178 	/* CLKSEL_CON26 */
179 	CLK_SARADC_DIV_CON_SHIFT	= 8,
180 	CLK_SARADC_DIV_CON_MASK		= 0xff << CLK_SARADC_DIV_CON_SHIFT,
181 
182 	/* CLKSEL_CON27 */
183 	CLK_TSADC_SEL_X24M		= 0x0,
184 	CLK_TSADC_SEL_SHIFT		= 15,
185 	CLK_TSADC_SEL_MASK		= 1 << CLK_TSADC_SEL_SHIFT,
186 	CLK_TSADC_DIV_CON_SHIFT		= 0,
187 	CLK_TSADC_DIV_CON_MASK		= 0x3ff,
188 
189 	/* CLKSEL_CON47 & CLKSEL_CON48 */
190 	ACLK_VOP_PLL_SEL_SHIFT		= 6,
191 	ACLK_VOP_PLL_SEL_MASK		= 0x3 << ACLK_VOP_PLL_SEL_SHIFT,
192 	ACLK_VOP_PLL_SEL_CPLL		= 0x1,
193 	ACLK_VOP_DIV_CON_SHIFT		= 0,
194 	ACLK_VOP_DIV_CON_MASK		= 0x1f << ACLK_VOP_DIV_CON_SHIFT,
195 
196 	/* CLKSEL_CON49 & CLKSEL_CON50 */
197 	DCLK_VOP_DCLK_SEL_SHIFT         = 11,
198 	DCLK_VOP_DCLK_SEL_MASK          = 1 << DCLK_VOP_DCLK_SEL_SHIFT,
199 	DCLK_VOP_DCLK_SEL_DIVOUT        = 0,
200 	DCLK_VOP_PLL_SEL_SHIFT          = 8,
201 	DCLK_VOP_PLL_SEL_MASK           = 3 << DCLK_VOP_PLL_SEL_SHIFT,
202 	DCLK_VOP_PLL_SEL_VPLL           = 0,
203 	DCLK_VOP_DIV_CON_MASK           = 0xff,
204 	DCLK_VOP_DIV_CON_SHIFT          = 0,
205 
206 	/* CLKSEL_CON58 */
207 	CLK_SPI_PLL_SEL_MASK		= 1,
208 	CLK_SPI_PLL_SEL_CPLL		= 0,
209 	CLK_SPI_PLL_SEL_GPLL		= 1,
210 	CLK_SPI_PLL_DIV_CON_MASK	= 0x7f,
211 	CLK_SPI5_PLL_DIV_CON_SHIFT	= 8,
212 	CLK_SPI5_PLL_SEL_SHIFT		= 15,
213 
214 	/* CLKSEL_CON59 */
215 	CLK_SPI1_PLL_SEL_SHIFT		= 15,
216 	CLK_SPI1_PLL_DIV_CON_SHIFT	= 8,
217 	CLK_SPI0_PLL_SEL_SHIFT		= 7,
218 	CLK_SPI0_PLL_DIV_CON_SHIFT	= 0,
219 
220 	/* CLKSEL_CON60 */
221 	CLK_SPI4_PLL_SEL_SHIFT		= 15,
222 	CLK_SPI4_PLL_DIV_CON_SHIFT	= 8,
223 	CLK_SPI2_PLL_SEL_SHIFT		= 7,
224 	CLK_SPI2_PLL_DIV_CON_SHIFT	= 0,
225 
226 	/* CLKSEL_CON61 */
227 	CLK_I2C_PLL_SEL_MASK		= 1,
228 	CLK_I2C_PLL_SEL_CPLL		= 0,
229 	CLK_I2C_PLL_SEL_GPLL		= 1,
230 	CLK_I2C5_PLL_SEL_SHIFT		= 15,
231 	CLK_I2C5_DIV_CON_SHIFT		= 8,
232 	CLK_I2C1_PLL_SEL_SHIFT		= 7,
233 	CLK_I2C1_DIV_CON_SHIFT		= 0,
234 
235 	/* CLKSEL_CON62 */
236 	CLK_I2C6_PLL_SEL_SHIFT		= 15,
237 	CLK_I2C6_DIV_CON_SHIFT		= 8,
238 	CLK_I2C2_PLL_SEL_SHIFT		= 7,
239 	CLK_I2C2_DIV_CON_SHIFT		= 0,
240 
241 	/* CLKSEL_CON63 */
242 	CLK_I2C7_PLL_SEL_SHIFT		= 15,
243 	CLK_I2C7_DIV_CON_SHIFT		= 8,
244 	CLK_I2C3_PLL_SEL_SHIFT		= 7,
245 	CLK_I2C3_DIV_CON_SHIFT		= 0,
246 
247 	/* CRU_SOFTRST_CON4 */
248 	RESETN_DDR0_REQ_SHIFT		= 8,
249 	RESETN_DDR0_REQ_MASK		= 1 << RESETN_DDR0_REQ_SHIFT,
250 	RESETN_DDRPHY0_REQ_SHIFT	= 9,
251 	RESETN_DDRPHY0_REQ_MASK		= 1 << RESETN_DDRPHY0_REQ_SHIFT,
252 	RESETN_DDR1_REQ_SHIFT		= 12,
253 	RESETN_DDR1_REQ_MASK		= 1 << RESETN_DDR1_REQ_SHIFT,
254 	RESETN_DDRPHY1_REQ_SHIFT	= 13,
255 	RESETN_DDRPHY1_REQ_MASK		= 1 << RESETN_DDRPHY1_REQ_SHIFT,
256 };
257 
258 #define VCO_MAX_KHZ	(3200 * (MHz / KHz))
259 #define VCO_MIN_KHZ	(800 * (MHz / KHz))
260 #define OUTPUT_MAX_KHZ	(3200 * (MHz / KHz))
261 #define OUTPUT_MIN_KHZ	(16 * (MHz / KHz))
262 
263 /*
264  *  the div restructions of pll in integer mode, these are defined in
265  *  * CRU_*PLL_CON0 or PMUCRU_*PLL_CON0
266  */
267 #define PLL_DIV_MIN	16
268 #define PLL_DIV_MAX	3200
269 
270 /*
271  * How to calculate the PLL(from TRM V0.3 Part 1 Page 63):
272  * Formulas also embedded within the Fractional PLL Verilog model:
273  * If DSMPD = 1 (DSM is disabled, "integer mode")
274  * FOUTVCO = FREF / REFDIV * FBDIV
275  * FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2
276  * Where:
277  * FOUTVCO = Fractional PLL non-divided output frequency
278  * FOUTPOSTDIV = Fractional PLL divided output frequency
279  *               (output of second post divider)
280  * FREF = Fractional PLL input reference frequency, (the OSC_HZ 24MHz input)
281  * REFDIV = Fractional PLL input reference clock divider
282  * FBDIV = Integer value programmed into feedback divide
283  *
284  */
285 static void rkclk_set_pll(u32 *pll_con, const struct pll_div *div)
286 {
287 	/* All 8 PLLs have same VCO and output frequency range restrictions. */
288 	u32 vco_khz = OSC_HZ / 1000 * div->fbdiv / div->refdiv;
289 	u32 output_khz = vco_khz / div->postdiv1 / div->postdiv2;
290 
291 	debug("PLL at %p: fbdiv=%d, refdiv=%d, postdiv1=%d, "
292 			   "postdiv2=%d, vco=%u khz, output=%u khz\n",
293 			   pll_con, div->fbdiv, div->refdiv, div->postdiv1,
294 			   div->postdiv2, vco_khz, output_khz);
295 	assert(vco_khz >= VCO_MIN_KHZ && vco_khz <= VCO_MAX_KHZ &&
296 	       output_khz >= OUTPUT_MIN_KHZ && output_khz <= OUTPUT_MAX_KHZ &&
297 	       div->fbdiv >= PLL_DIV_MIN && div->fbdiv <= PLL_DIV_MAX);
298 
299 	/*
300 	 * When power on or changing PLL setting,
301 	 * we must force PLL into slow mode to ensure output stable clock.
302 	 */
303 	rk_clrsetreg(&pll_con[3], PLL_MODE_MASK,
304 		     PLL_MODE_SLOW << PLL_MODE_SHIFT);
305 
306 	/* use integer mode */
307 	rk_clrsetreg(&pll_con[3], PLL_DSMPD_MASK,
308 		     PLL_INTEGER_MODE << PLL_DSMPD_SHIFT);
309 
310 	rk_clrsetreg(&pll_con[0], PLL_FBDIV_MASK,
311 		     div->fbdiv << PLL_FBDIV_SHIFT);
312 	rk_clrsetreg(&pll_con[1],
313 		     PLL_POSTDIV2_MASK | PLL_POSTDIV1_MASK |
314 		     PLL_REFDIV_MASK | PLL_REFDIV_SHIFT,
315 		     (div->postdiv2 << PLL_POSTDIV2_SHIFT) |
316 		     (div->postdiv1 << PLL_POSTDIV1_SHIFT) |
317 		     (div->refdiv << PLL_REFDIV_SHIFT));
318 
319 	/* waiting for pll lock */
320 	while (!(readl(&pll_con[2]) & (1 << PLL_LOCK_STATUS_SHIFT)))
321 		udelay(1);
322 
323 	/* pll enter normal mode */
324 	rk_clrsetreg(&pll_con[3], PLL_MODE_MASK,
325 		     PLL_MODE_NORM << PLL_MODE_SHIFT);
326 }
327 
328 static int pll_para_config(u32 freq_hz, struct pll_div *div)
329 {
330 	u32 ref_khz = OSC_HZ / KHz, refdiv, fbdiv = 0;
331 	u32 postdiv1, postdiv2 = 1;
332 	u32 fref_khz;
333 	u32 diff_khz, best_diff_khz;
334 	const u32 max_refdiv = 63, max_fbdiv = 3200, min_fbdiv = 16;
335 	const u32 max_postdiv1 = 7, max_postdiv2 = 7;
336 	u32 vco_khz;
337 	u32 freq_khz = freq_hz / KHz;
338 
339 	if (!freq_hz) {
340 		printf("%s: the frequency can't be 0 Hz\n", __func__);
341 		return -1;
342 	}
343 
344 	postdiv1 = DIV_ROUND_UP(VCO_MIN_KHZ, freq_khz);
345 	if (postdiv1 > max_postdiv1) {
346 		postdiv2 = DIV_ROUND_UP(postdiv1, max_postdiv1);
347 		postdiv1 = DIV_ROUND_UP(postdiv1, postdiv2);
348 	}
349 
350 	vco_khz = freq_khz * postdiv1 * postdiv2;
351 
352 	if (vco_khz < VCO_MIN_KHZ || vco_khz > VCO_MAX_KHZ ||
353 	    postdiv2 > max_postdiv2) {
354 		printf("%s: Cannot find out a supported VCO"
355 		       " for Frequency (%uHz).\n", __func__, freq_hz);
356 		return -1;
357 	}
358 
359 	div->postdiv1 = postdiv1;
360 	div->postdiv2 = postdiv2;
361 
362 	best_diff_khz = vco_khz;
363 	for (refdiv = 1; refdiv < max_refdiv && best_diff_khz; refdiv++) {
364 		fref_khz = ref_khz / refdiv;
365 
366 		fbdiv = vco_khz / fref_khz;
367 		if ((fbdiv >= max_fbdiv) || (fbdiv <= min_fbdiv))
368 			continue;
369 		diff_khz = vco_khz - fbdiv * fref_khz;
370 		if (fbdiv + 1 < max_fbdiv && diff_khz > fref_khz / 2) {
371 			fbdiv++;
372 			diff_khz = fref_khz - diff_khz;
373 		}
374 
375 		if (diff_khz >= best_diff_khz)
376 			continue;
377 
378 		best_diff_khz = diff_khz;
379 		div->refdiv = refdiv;
380 		div->fbdiv = fbdiv;
381 	}
382 
383 	if (best_diff_khz > 4 * (MHz/KHz)) {
384 		printf("%s: Failed to match output frequency %u, "
385 		       "difference is %u Hz,exceed 4MHZ\n", __func__, freq_hz,
386 		       best_diff_khz * KHz);
387 		return -1;
388 	}
389 	return 0;
390 }
391 
392 #ifdef CONFIG_SPL_BUILD
393 static void rkclk_init(struct rk3399_cru *cru)
394 {
395 	u32 aclk_div;
396 	u32 hclk_div;
397 	u32 pclk_div;
398 
399 	/*
400 	 * some cru registers changed by bootrom, we'd better reset them to
401 	 * reset/default values described in TRM to avoid confusion in kernel.
402 	 * Please consider these three lines as a fix of bootrom bug.
403 	 */
404 	rk_clrsetreg(&cru->clksel_con[12], 0xffff, 0x4101);
405 	rk_clrsetreg(&cru->clksel_con[19], 0xffff, 0x033f);
406 	rk_clrsetreg(&cru->clksel_con[56], 0x0003, 0x0003);
407 
408 	/* configure gpll cpll */
409 	rkclk_set_pll(&cru->gpll_con[0], &gpll_init_cfg);
410 	rkclk_set_pll(&cru->cpll_con[0], &cpll_init_cfg);
411 
412 	/* configure perihp aclk, hclk, pclk */
413 	aclk_div = GPLL_HZ / PERIHP_ACLK_HZ - 1;
414 	assert((aclk_div + 1) * PERIHP_ACLK_HZ == GPLL_HZ && aclk_div < 0x1f);
415 
416 	hclk_div = PERIHP_ACLK_HZ / PERIHP_HCLK_HZ - 1;
417 	assert((hclk_div + 1) * PERIHP_HCLK_HZ ==
418 	       PERIHP_ACLK_HZ && (hclk_div < 0x4));
419 
420 	pclk_div = PERIHP_ACLK_HZ / PERIHP_PCLK_HZ - 1;
421 	assert((pclk_div + 1) * PERIHP_PCLK_HZ ==
422 	       PERIHP_ACLK_HZ && (pclk_div < 0x7));
423 
424 	rk_clrsetreg(&cru->clksel_con[14],
425 		     PCLK_PERIHP_DIV_CON_MASK | HCLK_PERIHP_DIV_CON_MASK |
426 		     ACLK_PERIHP_PLL_SEL_MASK | ACLK_PERIHP_DIV_CON_MASK,
427 		     pclk_div << PCLK_PERIHP_DIV_CON_SHIFT |
428 		     hclk_div << HCLK_PERIHP_DIV_CON_SHIFT |
429 		     ACLK_PERIHP_PLL_SEL_GPLL << ACLK_PERIHP_PLL_SEL_SHIFT |
430 		     aclk_div << ACLK_PERIHP_DIV_CON_SHIFT);
431 
432 	/* configure perilp0 aclk, hclk, pclk */
433 	aclk_div = GPLL_HZ / PERILP0_ACLK_HZ - 1;
434 	assert((aclk_div + 1) * PERILP0_ACLK_HZ == GPLL_HZ && aclk_div < 0x1f);
435 
436 	hclk_div = PERILP0_ACLK_HZ / PERILP0_HCLK_HZ - 1;
437 	assert((hclk_div + 1) * PERILP0_HCLK_HZ ==
438 	       PERILP0_ACLK_HZ && (hclk_div < 0x4));
439 
440 	pclk_div = PERILP0_ACLK_HZ / PERILP0_PCLK_HZ - 1;
441 	assert((pclk_div + 1) * PERILP0_PCLK_HZ ==
442 	       PERILP0_ACLK_HZ && (pclk_div < 0x7));
443 
444 	rk_clrsetreg(&cru->clksel_con[23],
445 		     PCLK_PERILP0_DIV_CON_MASK | HCLK_PERILP0_DIV_CON_MASK |
446 		     ACLK_PERILP0_PLL_SEL_MASK | ACLK_PERILP0_DIV_CON_MASK,
447 		     pclk_div << PCLK_PERILP0_DIV_CON_SHIFT |
448 		     hclk_div << HCLK_PERILP0_DIV_CON_SHIFT |
449 		     ACLK_PERILP0_PLL_SEL_GPLL << ACLK_PERILP0_PLL_SEL_SHIFT |
450 		     aclk_div << ACLK_PERILP0_DIV_CON_SHIFT);
451 
452 	/* perilp1 hclk select gpll as source */
453 	hclk_div = GPLL_HZ / PERILP1_HCLK_HZ - 1;
454 	assert((hclk_div + 1) * PERILP1_HCLK_HZ ==
455 	       GPLL_HZ && (hclk_div < 0x1f));
456 
457 	pclk_div = PERILP1_HCLK_HZ / PERILP1_HCLK_HZ - 1;
458 	assert((pclk_div + 1) * PERILP1_HCLK_HZ ==
459 	       PERILP1_HCLK_HZ && (hclk_div < 0x7));
460 
461 	rk_clrsetreg(&cru->clksel_con[25],
462 		     PCLK_PERILP1_DIV_CON_MASK | HCLK_PERILP1_DIV_CON_MASK |
463 		     HCLK_PERILP1_PLL_SEL_MASK,
464 		     pclk_div << PCLK_PERILP1_DIV_CON_SHIFT |
465 		     hclk_div << HCLK_PERILP1_DIV_CON_SHIFT |
466 		     HCLK_PERILP1_PLL_SEL_GPLL << HCLK_PERILP1_PLL_SEL_SHIFT);
467 }
468 #endif
469 
470 void rk3399_configure_cpu(struct rk3399_cru *cru,
471 			  enum apll_l_frequencies apll_l_freq)
472 {
473 	u32 aclkm_div;
474 	u32 pclk_dbg_div;
475 	u32 atclk_div;
476 
477 	rkclk_set_pll(&cru->apll_l_con[0], apll_l_cfgs[apll_l_freq]);
478 
479 	aclkm_div = APLL_HZ / ACLKM_CORE_HZ - 1;
480 	assert((aclkm_div + 1) * ACLKM_CORE_HZ == APLL_HZ &&
481 	       aclkm_div < 0x1f);
482 
483 	pclk_dbg_div = APLL_HZ / PCLK_DBG_HZ - 1;
484 	assert((pclk_dbg_div + 1) * PCLK_DBG_HZ == APLL_HZ &&
485 	       pclk_dbg_div < 0x1f);
486 
487 	atclk_div = APLL_HZ / ATCLK_CORE_HZ - 1;
488 	assert((atclk_div + 1) * ATCLK_CORE_HZ == APLL_HZ &&
489 	       atclk_div < 0x1f);
490 
491 	rk_clrsetreg(&cru->clksel_con[0],
492 		     ACLKM_CORE_L_DIV_CON_MASK | CLK_CORE_L_PLL_SEL_MASK |
493 		     CLK_CORE_L_DIV_MASK,
494 		     aclkm_div << ACLKM_CORE_L_DIV_CON_SHIFT |
495 		     CLK_CORE_L_PLL_SEL_ALPLL << CLK_CORE_L_PLL_SEL_SHIFT |
496 		     0 << CLK_CORE_L_DIV_SHIFT);
497 
498 	rk_clrsetreg(&cru->clksel_con[1],
499 		     PCLK_DBG_L_DIV_MASK | ATCLK_CORE_L_DIV_MASK,
500 		     pclk_dbg_div << PCLK_DBG_L_DIV_SHIFT |
501 		     atclk_div << ATCLK_CORE_L_DIV_SHIFT);
502 }
503 #define I2C_CLK_REG_MASK(bus) \
504 			(I2C_DIV_CON_MASK << \
505 			CLK_I2C ##bus## _DIV_CON_SHIFT | \
506 			CLK_I2C_PLL_SEL_MASK << \
507 			CLK_I2C ##bus## _PLL_SEL_SHIFT)
508 
509 #define I2C_CLK_REG_VALUE(bus, clk_div) \
510 			      ((clk_div - 1) << \
511 					CLK_I2C ##bus## _DIV_CON_SHIFT | \
512 			      CLK_I2C_PLL_SEL_GPLL << \
513 					CLK_I2C ##bus## _PLL_SEL_SHIFT)
514 
515 #define I2C_CLK_DIV_VALUE(con, bus) \
516 			(con >> CLK_I2C ##bus## _DIV_CON_SHIFT) & \
517 				I2C_DIV_CON_MASK;
518 
519 #define I2C_PMUCLK_REG_MASK(bus) \
520 			(I2C_DIV_CON_MASK << \
521 			 CLK_I2C ##bus## _DIV_CON_SHIFT)
522 
523 #define I2C_PMUCLK_REG_VALUE(bus, clk_div) \
524 				((clk_div - 1) << \
525 				CLK_I2C ##bus## _DIV_CON_SHIFT)
526 
527 static ulong rk3399_i2c_get_clk(struct rk3399_cru *cru, ulong clk_id)
528 {
529 	u32 div, con;
530 
531 	switch (clk_id) {
532 	case SCLK_I2C1:
533 		con = readl(&cru->clksel_con[61]);
534 		div = I2C_CLK_DIV_VALUE(con, 1);
535 		break;
536 	case SCLK_I2C2:
537 		con = readl(&cru->clksel_con[62]);
538 		div = I2C_CLK_DIV_VALUE(con, 2);
539 		break;
540 	case SCLK_I2C3:
541 		con = readl(&cru->clksel_con[63]);
542 		div = I2C_CLK_DIV_VALUE(con, 3);
543 		break;
544 	case SCLK_I2C5:
545 		con = readl(&cru->clksel_con[61]);
546 		div = I2C_CLK_DIV_VALUE(con, 5);
547 		break;
548 	case SCLK_I2C6:
549 		con = readl(&cru->clksel_con[62]);
550 		div = I2C_CLK_DIV_VALUE(con, 6);
551 		break;
552 	case SCLK_I2C7:
553 		con = readl(&cru->clksel_con[63]);
554 		div = I2C_CLK_DIV_VALUE(con, 7);
555 		break;
556 	default:
557 		printf("do not support this i2c bus\n");
558 		return -EINVAL;
559 	}
560 
561 	return DIV_TO_RATE(GPLL_HZ, div);
562 }
563 
564 static ulong rk3399_i2c_set_clk(struct rk3399_cru *cru, ulong clk_id, uint hz)
565 {
566 	int src_clk_div;
567 
568 	/* i2c0,4,8 src clock from ppll, i2c1,2,3,5,6,7 src clock from gpll*/
569 	src_clk_div = GPLL_HZ / hz;
570 	assert(src_clk_div - 1 < 127);
571 
572 	switch (clk_id) {
573 	case SCLK_I2C1:
574 		rk_clrsetreg(&cru->clksel_con[61], I2C_CLK_REG_MASK(1),
575 			     I2C_CLK_REG_VALUE(1, src_clk_div));
576 		break;
577 	case SCLK_I2C2:
578 		rk_clrsetreg(&cru->clksel_con[62], I2C_CLK_REG_MASK(2),
579 			     I2C_CLK_REG_VALUE(2, src_clk_div));
580 		break;
581 	case SCLK_I2C3:
582 		rk_clrsetreg(&cru->clksel_con[63], I2C_CLK_REG_MASK(3),
583 			     I2C_CLK_REG_VALUE(3, src_clk_div));
584 		break;
585 	case SCLK_I2C5:
586 		rk_clrsetreg(&cru->clksel_con[61], I2C_CLK_REG_MASK(5),
587 			     I2C_CLK_REG_VALUE(5, src_clk_div));
588 		break;
589 	case SCLK_I2C6:
590 		rk_clrsetreg(&cru->clksel_con[62], I2C_CLK_REG_MASK(6),
591 			     I2C_CLK_REG_VALUE(6, src_clk_div));
592 		break;
593 	case SCLK_I2C7:
594 		rk_clrsetreg(&cru->clksel_con[63], I2C_CLK_REG_MASK(7),
595 			     I2C_CLK_REG_VALUE(7, src_clk_div));
596 		break;
597 	default:
598 		printf("do not support this i2c bus\n");
599 		return -EINVAL;
600 	}
601 
602 	return DIV_TO_RATE(GPLL_HZ, src_clk_div);
603 }
604 
605 static ulong rk3399_vop_set_clk(struct rk3399_cru *cru, ulong clk_id, u32 hz)
606 {
607 	struct pll_div vpll_config = {0};
608 	int aclk_vop = 198*MHz;
609 	void *aclkreg_addr, *dclkreg_addr;
610 	u32 div;
611 
612 	switch (clk_id) {
613 	case DCLK_VOP0:
614 		aclkreg_addr = &cru->clksel_con[47];
615 		dclkreg_addr = &cru->clksel_con[49];
616 		break;
617 	case DCLK_VOP1:
618 		aclkreg_addr = &cru->clksel_con[48];
619 		dclkreg_addr = &cru->clksel_con[50];
620 		break;
621 	default:
622 		return -EINVAL;
623 	}
624 	/* vop aclk source clk: cpll */
625 	div = CPLL_HZ / aclk_vop;
626 	assert(div - 1 < 32);
627 
628 	rk_clrsetreg(aclkreg_addr,
629 		     ACLK_VOP_PLL_SEL_MASK | ACLK_VOP_DIV_CON_MASK,
630 		     ACLK_VOP_PLL_SEL_CPLL << ACLK_VOP_PLL_SEL_SHIFT |
631 		     (div - 1) << ACLK_VOP_DIV_CON_SHIFT);
632 
633 	/* vop dclk source from vpll, and equals to vpll(means div == 1) */
634 	if (pll_para_config(hz, &vpll_config))
635 		return -1;
636 
637 	rkclk_set_pll(&cru->vpll_con[0], &vpll_config);
638 
639 	rk_clrsetreg(dclkreg_addr,
640 		     DCLK_VOP_DCLK_SEL_MASK | DCLK_VOP_PLL_SEL_MASK|
641 		     DCLK_VOP_DIV_CON_MASK,
642 		     DCLK_VOP_DCLK_SEL_DIVOUT << DCLK_VOP_DCLK_SEL_SHIFT |
643 		     DCLK_VOP_PLL_SEL_VPLL << DCLK_VOP_PLL_SEL_SHIFT |
644 		     (1 - 1) << DCLK_VOP_DIV_CON_SHIFT);
645 
646 	return hz;
647 }
648 
649 static ulong rk3399_mmc_get_clk(struct rk3399_cru *cru, uint clk_id)
650 {
651 	u32 div, con;
652 
653 	switch (clk_id) {
654 	case SCLK_SDMMC:
655 		con = readl(&cru->clksel_con[16]);
656 		break;
657 	case SCLK_EMMC:
658 		con = readl(&cru->clksel_con[21]);
659 		break;
660 	default:
661 		return -EINVAL;
662 	}
663 	div = (con & CLK_EMMC_DIV_CON_MASK) >> CLK_EMMC_DIV_CON_SHIFT;
664 
665 	if ((con & CLK_EMMC_PLL_MASK) >> CLK_EMMC_PLL_SHIFT
666 			== CLK_EMMC_PLL_SEL_24M)
667 		return DIV_TO_RATE(24*1024*1024, div);
668 	else
669 		return DIV_TO_RATE(GPLL_HZ, div);
670 }
671 
672 static ulong rk3399_mmc_set_clk(struct rk3399_cru *cru,
673 				ulong clk_id, ulong set_rate)
674 {
675 	int src_clk_div;
676 	int aclk_emmc = 198*MHz;
677 
678 	switch (clk_id) {
679 	case SCLK_SDMMC:
680 		/* Select clk_sdmmc source from GPLL by default */
681 		src_clk_div = GPLL_HZ / set_rate;
682 
683 		if (src_clk_div > 127) {
684 			/* use 24MHz source for 400KHz clock */
685 			src_clk_div = 24*1024*1024 / set_rate;
686 			rk_clrsetreg(&cru->clksel_con[16],
687 				     CLK_EMMC_PLL_MASK | CLK_EMMC_DIV_CON_MASK,
688 				     CLK_EMMC_PLL_SEL_24M << CLK_EMMC_PLL_SHIFT |
689 				     (src_clk_div - 1) << CLK_EMMC_DIV_CON_SHIFT);
690 		} else {
691 			rk_clrsetreg(&cru->clksel_con[16],
692 				     CLK_EMMC_PLL_MASK | CLK_EMMC_DIV_CON_MASK,
693 				     CLK_EMMC_PLL_SEL_GPLL << CLK_EMMC_PLL_SHIFT |
694 				     (src_clk_div - 1) << CLK_EMMC_DIV_CON_SHIFT);
695 		}
696 		break;
697 	case SCLK_EMMC:
698 		/* Select aclk_emmc source from GPLL */
699 		src_clk_div = GPLL_HZ / aclk_emmc;
700 		assert(src_clk_div - 1 < 31);
701 
702 		rk_clrsetreg(&cru->clksel_con[21],
703 			     ACLK_EMMC_PLL_SEL_MASK | ACLK_EMMC_DIV_CON_MASK,
704 			     ACLK_EMMC_PLL_SEL_GPLL << ACLK_EMMC_PLL_SEL_SHIFT |
705 			     (src_clk_div - 1) << ACLK_EMMC_DIV_CON_SHIFT);
706 
707 		/* Select clk_emmc source from GPLL too */
708 		src_clk_div = GPLL_HZ / set_rate;
709 		assert(src_clk_div - 1 < 127);
710 
711 		rk_clrsetreg(&cru->clksel_con[22],
712 			     CLK_EMMC_PLL_MASK | CLK_EMMC_DIV_CON_MASK,
713 			     CLK_EMMC_PLL_SEL_GPLL << CLK_EMMC_PLL_SHIFT |
714 			     (src_clk_div - 1) << CLK_EMMC_DIV_CON_SHIFT);
715 		break;
716 	default:
717 		return -EINVAL;
718 	}
719 	return rk3399_mmc_get_clk(cru, clk_id);
720 }
721 
722 #define PMUSGRF_DDR_RGN_CON16 0xff330040
723 static ulong rk3399_ddr_set_clk(struct rk3399_cru *cru,
724 				ulong set_rate)
725 {
726 	struct pll_div dpll_cfg;
727 
728 	/*  IC ECO bug, need to set this register */
729 	writel(0xc000c000, PMUSGRF_DDR_RGN_CON16);
730 
731 	/*  clk_ddrc == DPLL = 24MHz / refdiv * fbdiv / postdiv1 / postdiv2 */
732 	switch (set_rate) {
733 	case 200*MHz:
734 		dpll_cfg = (struct pll_div)
735 		{.refdiv = 1, .fbdiv = 50, .postdiv1 = 6, .postdiv2 = 1};
736 		break;
737 	case 300*MHz:
738 		dpll_cfg = (struct pll_div)
739 		{.refdiv = 2, .fbdiv = 100, .postdiv1 = 4, .postdiv2 = 1};
740 		break;
741 	case 666*MHz:
742 		dpll_cfg = (struct pll_div)
743 		{.refdiv = 2, .fbdiv = 111, .postdiv1 = 2, .postdiv2 = 1};
744 		break;
745 	case 800*MHz:
746 		dpll_cfg = (struct pll_div)
747 		{.refdiv = 1, .fbdiv = 100, .postdiv1 = 3, .postdiv2 = 1};
748 		break;
749 	case 933*MHz:
750 		dpll_cfg = (struct pll_div)
751 		{.refdiv = 1, .fbdiv = 116, .postdiv1 = 3, .postdiv2 = 1};
752 		break;
753 	default:
754 		error("Unsupported SDRAM frequency!,%ld\n", set_rate);
755 	}
756 	rkclk_set_pll(&cru->dpll_con[0], &dpll_cfg);
757 
758 	return set_rate;
759 }
760 static ulong rk3399_clk_get_rate(struct clk *clk)
761 {
762 	struct rk3399_clk_priv *priv = dev_get_priv(clk->dev);
763 	ulong rate = 0;
764 
765 	switch (clk->id) {
766 	case 0 ... 63:
767 		return 0;
768 	case SCLK_SDMMC:
769 	case SCLK_EMMC:
770 		rate = rk3399_mmc_get_clk(priv->cru, clk->id);
771 		break;
772 	case SCLK_I2C1:
773 	case SCLK_I2C2:
774 	case SCLK_I2C3:
775 	case SCLK_I2C5:
776 	case SCLK_I2C6:
777 	case SCLK_I2C7:
778 		rate = rk3399_i2c_get_clk(priv->cru, clk->id);
779 		break;
780 	case DCLK_VOP0:
781 	case DCLK_VOP1:
782 		break;
783 	default:
784 		return -ENOENT;
785 	}
786 
787 	return rate;
788 }
789 
790 static ulong rk3399_clk_set_rate(struct clk *clk, ulong rate)
791 {
792 	struct rk3399_clk_priv *priv = dev_get_priv(clk->dev);
793 	ulong ret = 0;
794 
795 	switch (clk->id) {
796 	case 0 ... 63:
797 		return 0;
798 	case SCLK_SDMMC:
799 	case SCLK_EMMC:
800 		ret = rk3399_mmc_set_clk(priv->cru, clk->id, rate);
801 		break;
802 	case SCLK_I2C1:
803 	case SCLK_I2C2:
804 	case SCLK_I2C3:
805 	case SCLK_I2C5:
806 	case SCLK_I2C6:
807 	case SCLK_I2C7:
808 		ret = rk3399_i2c_set_clk(priv->cru, clk->id, rate);
809 		break;
810 	case DCLK_VOP0:
811 	case DCLK_VOP1:
812 		ret = rk3399_vop_set_clk(priv->cru, clk->id, rate);
813 		break;
814 	case SCLK_DDRCLK:
815 		ret = rk3399_ddr_set_clk(priv->cru, rate);
816 		break;
817 	default:
818 		return -ENOENT;
819 	}
820 
821 	return ret;
822 }
823 
824 static struct clk_ops rk3399_clk_ops = {
825 	.get_rate = rk3399_clk_get_rate,
826 	.set_rate = rk3399_clk_set_rate,
827 };
828 
829 static int rk3399_clk_probe(struct udevice *dev)
830 {
831 #ifdef CONFIG_SPL_BUILD
832 	struct rk3399_clk_priv *priv = dev_get_priv(dev);
833 
834 #if CONFIG_IS_ENABLED(OF_PLATDATA)
835 	struct rk3399_clk_plat *plat = dev_get_platdata(dev);
836 
837 	priv->cru = map_sysmem(plat->dtd.reg[1], plat->dtd.reg[3]);
838 #endif
839 	rkclk_init(priv->cru);
840 #endif
841 	return 0;
842 }
843 
844 static int rk3399_clk_ofdata_to_platdata(struct udevice *dev)
845 {
846 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
847 	struct rk3399_clk_priv *priv = dev_get_priv(dev);
848 
849 	priv->cru = (struct rk3399_cru *)dev_get_addr(dev);
850 #endif
851 	return 0;
852 }
853 
854 static int rk3399_clk_bind(struct udevice *dev)
855 {
856 	int ret;
857 
858 	/* The reset driver does not have a device node, so bind it here */
859 	ret = device_bind_driver(gd->dm_root, "rk3399_sysreset", "reset", &dev);
860 	if (ret)
861 		printf("Warning: No RK3399 reset driver: ret=%d\n", ret);
862 
863 	return 0;
864 }
865 
866 static const struct udevice_id rk3399_clk_ids[] = {
867 	{ .compatible = "rockchip,rk3399-cru" },
868 	{ }
869 };
870 
871 U_BOOT_DRIVER(clk_rk3399) = {
872 	.name		= "rockchip_rk3399_cru",
873 	.id		= UCLASS_CLK,
874 	.of_match	= rk3399_clk_ids,
875 	.priv_auto_alloc_size = sizeof(struct rk3399_clk_priv),
876 	.ofdata_to_platdata = rk3399_clk_ofdata_to_platdata,
877 	.ops		= &rk3399_clk_ops,
878 	.bind		= rk3399_clk_bind,
879 	.probe		= rk3399_clk_probe,
880 #if CONFIG_IS_ENABLED(OF_PLATDATA)
881 	.platdata_auto_alloc_size = sizeof(struct rk3399_clk_plat),
882 #endif
883 };
884 
885 static ulong rk3399_i2c_get_pmuclk(struct rk3399_pmucru *pmucru, ulong clk_id)
886 {
887 	u32 div, con;
888 
889 	switch (clk_id) {
890 	case SCLK_I2C0_PMU:
891 		con = readl(&pmucru->pmucru_clksel[2]);
892 		div = I2C_CLK_DIV_VALUE(con, 0);
893 		break;
894 	case SCLK_I2C4_PMU:
895 		con = readl(&pmucru->pmucru_clksel[3]);
896 		div = I2C_CLK_DIV_VALUE(con, 4);
897 		break;
898 	case SCLK_I2C8_PMU:
899 		con = readl(&pmucru->pmucru_clksel[2]);
900 		div = I2C_CLK_DIV_VALUE(con, 8);
901 		break;
902 	default:
903 		printf("do not support this i2c bus\n");
904 		return -EINVAL;
905 	}
906 
907 	return DIV_TO_RATE(PPLL_HZ, div);
908 }
909 
910 static ulong rk3399_i2c_set_pmuclk(struct rk3399_pmucru *pmucru, ulong clk_id,
911 				   uint hz)
912 {
913 	int src_clk_div;
914 
915 	src_clk_div = PPLL_HZ / hz;
916 	assert(src_clk_div - 1 < 127);
917 
918 	switch (clk_id) {
919 	case SCLK_I2C0_PMU:
920 		rk_clrsetreg(&pmucru->pmucru_clksel[2], I2C_PMUCLK_REG_MASK(0),
921 			     I2C_PMUCLK_REG_VALUE(0, src_clk_div));
922 		break;
923 	case SCLK_I2C4_PMU:
924 		rk_clrsetreg(&pmucru->pmucru_clksel[3], I2C_PMUCLK_REG_MASK(4),
925 			     I2C_PMUCLK_REG_VALUE(4, src_clk_div));
926 		break;
927 	case SCLK_I2C8_PMU:
928 		rk_clrsetreg(&pmucru->pmucru_clksel[2], I2C_PMUCLK_REG_MASK(8),
929 			     I2C_PMUCLK_REG_VALUE(8, src_clk_div));
930 		break;
931 	default:
932 		printf("do not support this i2c bus\n");
933 		return -EINVAL;
934 	}
935 
936 	return DIV_TO_RATE(PPLL_HZ, src_clk_div);
937 }
938 
939 static ulong rk3399_pwm_get_clk(struct rk3399_pmucru *pmucru)
940 {
941 	u32 div, con;
942 
943 	/* PWM closk rate is same as pclk_pmu */
944 	con = readl(&pmucru->pmucru_clksel[0]);
945 	div = con & PMU_PCLK_DIV_CON_MASK;
946 
947 	return DIV_TO_RATE(PPLL_HZ, div);
948 }
949 
950 static ulong rk3399_pmuclk_get_rate(struct clk *clk)
951 {
952 	struct rk3399_pmuclk_priv *priv = dev_get_priv(clk->dev);
953 	ulong rate = 0;
954 
955 	switch (clk->id) {
956 	case PCLK_RKPWM_PMU:
957 		rate = rk3399_pwm_get_clk(priv->pmucru);
958 		break;
959 	case SCLK_I2C0_PMU:
960 	case SCLK_I2C4_PMU:
961 	case SCLK_I2C8_PMU:
962 		rate = rk3399_i2c_get_pmuclk(priv->pmucru, clk->id);
963 		break;
964 	default:
965 		return -ENOENT;
966 	}
967 
968 	return rate;
969 }
970 
971 static ulong rk3399_pmuclk_set_rate(struct clk *clk, ulong rate)
972 {
973 	struct rk3399_pmuclk_priv *priv = dev_get_priv(clk->dev);
974 	ulong ret = 0;
975 
976 	switch (clk->id) {
977 	case SCLK_I2C0_PMU:
978 	case SCLK_I2C4_PMU:
979 	case SCLK_I2C8_PMU:
980 		ret = rk3399_i2c_set_pmuclk(priv->pmucru, clk->id, rate);
981 		break;
982 	default:
983 		return -ENOENT;
984 	}
985 
986 	return ret;
987 }
988 
989 static struct clk_ops rk3399_pmuclk_ops = {
990 	.get_rate = rk3399_pmuclk_get_rate,
991 	.set_rate = rk3399_pmuclk_set_rate,
992 };
993 
994 #ifndef CONFIG_SPL_BUILD
995 static void pmuclk_init(struct rk3399_pmucru *pmucru)
996 {
997 	u32 pclk_div;
998 
999 	/*  configure pmu pll(ppll) */
1000 	rkclk_set_pll(&pmucru->ppll_con[0], &ppll_init_cfg);
1001 
1002 	/*  configure pmu pclk */
1003 	pclk_div = PPLL_HZ / PMU_PCLK_HZ - 1;
1004 	rk_clrsetreg(&pmucru->pmucru_clksel[0],
1005 		     PMU_PCLK_DIV_CON_MASK,
1006 		     pclk_div << PMU_PCLK_DIV_CON_SHIFT);
1007 }
1008 #endif
1009 
1010 static int rk3399_pmuclk_probe(struct udevice *dev)
1011 {
1012 	struct rk3399_pmuclk_priv *priv = dev_get_priv(dev);
1013 
1014 #if CONFIG_IS_ENABLED(OF_PLATDATA)
1015 	struct rk3399_pmuclk_plat *plat = dev_get_platdata(dev);
1016 
1017 	priv->pmucru = map_sysmem(plat->dtd.reg[1], plat->dtd.reg[3]);
1018 #endif
1019 
1020 #ifndef CONFIG_SPL_BUILD
1021 	pmuclk_init(priv->pmucru);
1022 #endif
1023 	return 0;
1024 }
1025 
1026 static int rk3399_pmuclk_ofdata_to_platdata(struct udevice *dev)
1027 {
1028 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
1029 	struct rk3399_pmuclk_priv *priv = dev_get_priv(dev);
1030 
1031 	priv->pmucru = (struct rk3399_pmucru *)dev_get_addr(dev);
1032 #endif
1033 	return 0;
1034 }
1035 
1036 static const struct udevice_id rk3399_pmuclk_ids[] = {
1037 	{ .compatible = "rockchip,rk3399-pmucru" },
1038 	{ }
1039 };
1040 
1041 U_BOOT_DRIVER(rockchip_rk3399_pmuclk) = {
1042 	.name		= "rockchip_rk3399_pmucru",
1043 	.id		= UCLASS_CLK,
1044 	.of_match	= rk3399_pmuclk_ids,
1045 	.priv_auto_alloc_size = sizeof(struct rk3399_pmuclk_priv),
1046 	.ofdata_to_platdata = rk3399_pmuclk_ofdata_to_platdata,
1047 	.ops		= &rk3399_pmuclk_ops,
1048 	.probe		= rk3399_pmuclk_probe,
1049 #if CONFIG_IS_ENABLED(OF_PLATDATA)
1050 	.platdata_auto_alloc_size = sizeof(struct rk3399_pmuclk_plat),
1051 #endif
1052 };
1053