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