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