xref: /aosp_15_r20/external/coreboot/src/soc/rockchip/rk3399/clock.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <assert.h>
4 #include <commonlib/bsd/gcd.h>
5 #include <console/console.h>
6 #include <delay.h>
7 #include <device/mmio.h>
8 #include <soc/addressmap.h>
9 #include <soc/clock.h>
10 #include <soc/grf.h>
11 #include <soc/i2c.h>
12 #include <soc/soc.h>
13 #include <stdint.h>
14 
15 struct pll_div {
16 	u32 refdiv;
17 	u32 fbdiv;
18 	u32 postdiv1;
19 	u32 postdiv2;
20 	u32 frac;
21 	u32 freq;
22 };
23 
24 #define PLL_DIVISORS(hz, _refdiv, _postdiv1, _postdiv2) {\
25 	.refdiv = _refdiv,\
26 	.fbdiv = (u32)((u64)hz * _refdiv * _postdiv1 * _postdiv2 / OSC_HZ),\
27 	.postdiv1 = _postdiv1, .postdiv2 = _postdiv2, .freq = hz};\
28 	_Static_assert(((u64)hz * _refdiv * _postdiv1 * _postdiv2 / OSC_HZ) *\
29 			 OSC_HZ / (_refdiv * _postdiv1 * _postdiv2) == hz,\
30 			 STRINGIFY(hz) " Hz cannot be hit with PLL "\
31 			 "divisors on line " STRINGIFY(__LINE__))
32 
33 static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 1, 4, 1);
34 static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 1, 3, 1);
35 static const struct pll_div ppll_init_cfg = PLL_DIVISORS(PPLL_HZ, 3, 2, 1);
36 
37 static const struct pll_div apll_1512_cfg = PLL_DIVISORS(1512*MHz, 1, 1, 1);
38 static const struct pll_div apll_600_cfg = PLL_DIVISORS(600*MHz, 1, 3, 1);
39 
40 static const struct pll_div *apll_cfgs[] = {
41 	[APLL_1512_MHZ] = &apll_1512_cfg,
42 	[APLL_600_MHZ] = &apll_600_cfg,
43 };
44 
45 enum {
46 	/* PLL_CON0 */
47 	PLL_FBDIV_MASK			= 0xfff,
48 	PLL_FBDIV_SHIFT			= 0,
49 
50 	/* PLL_CON1 */
51 	PLL_POSTDIV2_MASK		= 0x7,
52 	PLL_POSTDIV2_SHIFT		= 12,
53 	PLL_POSTDIV1_MASK		= 0x7,
54 	PLL_POSTDIV1_SHIFT		= 8,
55 	PLL_REFDIV_MASK			= 0x3f,
56 	PLL_REFDIV_SHIFT		= 0,
57 
58 	/* PLL_CON2 */
59 	PLL_LOCK_STATUS_MASK		= 1,
60 	PLL_LOCK_STATUS_SHIFT		= 31,
61 	PLL_FRACDIV_MASK		= 0xffffff,
62 	PLL_FRACDIV_SHIFT		= 0,
63 
64 	/* PLL_CON3 */
65 	PLL_MODE_MASK			= 3,
66 	PLL_MODE_SHIFT			= 8,
67 	PLL_MODE_SLOW			= 0,
68 	PLL_MODE_NORM,
69 	PLL_MODE_DEEP,
70 	PLL_DSMPD_MASK			= 1,
71 	PLL_DSMPD_SHIFT			= 3,
72 	PLL_FRAC_MODE			= 0,
73 	PLL_INTEGER_MODE		= 1,
74 
75 	/* PLL_CON4 */
76 	PLL_SSMOD_BP_MASK		= 1,
77 	PLL_SSMOD_BP_SHIFT		= 0,
78 	PLL_SSMOD_DIS_SSCG_MASK		= 1,
79 	PLL_SSMOD_DIS_SSCG_SHIFT	= 1,
80 	PLL_SSMOD_RESET_MASK		= 1,
81 	PLL_SSMOD_RESET_SHIFT		= 2,
82 	PLL_SSMOD_DOWNSPEAD_MASK	= 1,
83 	PLL_SSMOD_DOWNSPEAD_SHIFT	= 3,
84 	PLL_SSMOD_DIVVAL_MASK		= 0xf,
85 	PLL_SSMOD_DIVVAL_SHIFT		= 4,
86 	PLL_SSMOD_SPREADAMP_MASK	= 0x1f,
87 	PLL_SSMOD_SPREADAMP_SHIFT	= 8,
88 
89 	/* PMUCRU_CLKSEL_CON0 */
90 	PMU_PCLK_DIV_CON_MASK		= 0x1f,
91 	PMU_PCLK_DIV_CON_SHIFT		= 0,
92 
93 	/* PMUCRU_CLKSEL_CON1 */
94 	SPI3_PLL_SEL_MASK		= 1,
95 	SPI3_PLL_SEL_SHIFT		= 7,
96 	SPI3_PLL_SEL_24M		= 0,
97 	SPI3_PLL_SEL_PPLL		= 1,
98 	SPI3_DIV_CON_MASK		= 0x7f,
99 	SPI3_DIV_CON_SHIFT		= 0x0,
100 
101 	/* PMUCRU_CLKSEL_CON2 */
102 	I2C_DIV_CON_MASK		= 0x7f,
103 	I2C8_DIV_CON_SHIFT		= 8,
104 	I2C0_DIV_CON_SHIFT		= 0,
105 
106 	/* PMUCRU_CLKSEL_CON3 */
107 	I2C4_DIV_CON_SHIFT		= 0,
108 
109 	/* CLKSEL_CON0 / CLKSEL_CON2 */
110 	ACLKM_CORE_DIV_CON_MASK	= 0x1f,
111 	ACLKM_CORE_DIV_CON_SHIFT	= 8,
112 	CLK_CORE_PLL_SEL_MASK		= 3,
113 	CLK_CORE_PLL_SEL_SHIFT		= 6,
114 	CLK_CORE_PLL_SEL_ALPLL		= 0x0,
115 	CLK_CORE_PLL_SEL_ABPLL		= 0x1,
116 	CLK_CORE_PLL_SEL_DPLL		= 0x10,
117 	CLK_CORE_PLL_SEL_GPLL		= 0x11,
118 	CLK_CORE_DIV_MASK		= 0x1f,
119 	CLK_CORE_DIV_SHIFT		= 0,
120 
121 	/* CLKSEL_CON1 / CLKSEL_CON3 */
122 	PCLK_DBG_DIV_MASK		= 0x1f,
123 	PCLK_DBG_DIV_SHIFT		= 0x8,
124 	ATCLK_CORE_DIV_MASK		= 0x1f,
125 	ATCLK_CORE_DIV_SHIFT		= 0,
126 
127 	/* CLKSEL_CON14 */
128 	PCLK_PERIHP_DIV_CON_MASK	= 0x7,
129 	PCLK_PERIHP_DIV_CON_SHIFT	= 12,
130 	HCLK_PERIHP_DIV_CON_MASK	= 3,
131 	HCLK_PERIHP_DIV_CON_SHIFT	= 8,
132 	ACLK_PERIHP_PLL_SEL_MASK	= 1,
133 	ACLK_PERIHP_PLL_SEL_SHIFT	= 7,
134 	ACLK_PERIHP_PLL_SEL_CPLL	= 0,
135 	ACLK_PERIHP_PLL_SEL_GPLL	= 1,
136 	ACLK_PERIHP_DIV_CON_MASK	= 0x1f,
137 	ACLK_PERIHP_DIV_CON_SHIFT	= 0,
138 
139 	/* CLKSEL_CON21 */
140 	ACLK_EMMC_PLL_SEL_MASK          = 0x1,
141 	ACLK_EMMC_PLL_SEL_SHIFT         = 7,
142 	ACLK_EMMC_PLL_SEL_GPLL          = 0x1,
143 	ACLK_EMMC_DIV_CON_MASK          = 0x1f,
144 	ACLK_EMMC_DIV_CON_SHIFT         = 0,
145 
146 	/* CLKSEL_CON22 */
147 	CLK_EMMC_PLL_MASK               = 0x7,
148 	CLK_EMMC_PLL_SHIFT              = 8,
149 	CLK_EMMC_PLL_SEL_GPLL           = 0x1,
150 	CLK_EMMC_DIV_CON_MASK           = 0x7f,
151 	CLK_EMMC_DIV_CON_SHIFT          = 0,
152 
153 	/* CLKSEL_CON23 */
154 	PCLK_PERILP0_DIV_CON_MASK	= 0x7,
155 	PCLK_PERILP0_DIV_CON_SHIFT	= 12,
156 	HCLK_PERILP0_DIV_CON_MASK	= 3,
157 	HCLK_PERILP0_DIV_CON_SHIFT	= 8,
158 	ACLK_PERILP0_PLL_SEL_MASK	= 1,
159 	ACLK_PERILP0_PLL_SEL_SHIFT	= 7,
160 	ACLK_PERILP0_PLL_SEL_CPLL	= 0,
161 	ACLK_PERILP0_PLL_SEL_GPLL	= 1,
162 	ACLK_PERILP0_DIV_CON_MASK	= 0x1f,
163 	ACLK_PERILP0_DIV_CON_SHIFT	= 0,
164 
165 	/* CLKSEL_CON25 */
166 	PCLK_PERILP1_DIV_CON_MASK	= 0x7,
167 	PCLK_PERILP1_DIV_CON_SHIFT	= 8,
168 	HCLK_PERILP1_PLL_SEL_MASK	= 1,
169 	HCLK_PERILP1_PLL_SEL_SHIFT	= 7,
170 	HCLK_PERILP1_PLL_SEL_CPLL	= 0,
171 	HCLK_PERILP1_PLL_SEL_GPLL	= 1,
172 	HCLK_PERILP1_DIV_CON_MASK	= 0x1f,
173 	HCLK_PERILP1_DIV_CON_SHIFT	= 0,
174 
175 	/* CLKSEL_CON26 */
176 	CLK_SARADC_DIV_CON_MASK		= 0xff,
177 	CLK_SARADC_DIV_CON_SHIFT	= 8,
178 
179 	/* CLKSEL_CON27 */
180 	CLK_TSADC_SEL_X24M		= 0x0,
181 	CLK_TSADC_SEL_MASK		= 1,
182 	CLK_TSADC_SEL_SHIFT		= 15,
183 	CLK_TSADC_DIV_CON_MASK		= 0x3ff,
184 	CLK_TSADC_DIV_CON_SHIFT		= 0,
185 
186 	/* CLKSEL_CON44 */
187 	CLK_PCLK_EDP_PLL_SEL_MASK	= 1,
188 	CLK_PCLK_EDP_PLL_SEL_SHIFT	= 15,
189 	CLK_PCLK_EDP_PLL_SEL_CPLL	= 0,
190 	CLK_PCLK_EDP_DIV_CON_MASK	= 0x3f,
191 	CLK_PCLK_EDP_DIV_CON_SHIFT	= 8,
192 
193 	/* CLKSEL_CON47 & CLKSEL_CON48 */
194 	ACLK_VOP_PLL_SEL_MASK		= 0x3,
195 	ACLK_VOP_PLL_SEL_SHIFT		= 6,
196 	ACLK_VOP_PLL_SEL_CPLL		= 0x1,
197 	ACLK_VOP_DIV_CON_MASK		= 0x1f,
198 	ACLK_VOP_DIV_CON_SHIFT		= 0,
199 
200 	/* CLKSEL_CON49 & CLKSEL_CON50 */
201 	DCLK_VOP_DCLK_SEL_MASK          = 1,
202 	DCLK_VOP_DCLK_SEL_SHIFT         = 11,
203 	DCLK_VOP_DCLK_SEL_DIVOUT        = 0,
204 	DCLK_VOP_PLL_SEL_MASK   = 3,
205 	DCLK_VOP_PLL_SEL_SHIFT          = 8,
206 	DCLK_VOP_PLL_SEL_VPLL   = 0,
207 	DCLK_VOP_DIV_CON_MASK   = 0xff,
208 	DCLK_VOP_DIV_CON_SHIFT          = 0,
209 
210 	/* CLKSEL_CON58 */
211 	CLK_SPI_PLL_SEL_MASK		= 1,
212 	CLK_SPI_PLL_SEL_CPLL		= 0,
213 	CLK_SPI_PLL_SEL_GPLL		= 1,
214 	CLK_SPI_PLL_DIV_CON_MASK	= 0x7f,
215 	CLK_SPI5_PLL_DIV_CON_SHIFT	= 8,
216 	CLK_SPI5_PLL_SEL_SHIFT		= 15,
217 
218 	/* CLKSEL_CON59 */
219 	CLK_SPI1_PLL_SEL_SHIFT		= 15,
220 	CLK_SPI1_PLL_DIV_CON_SHIFT	= 8,
221 	CLK_SPI0_PLL_SEL_SHIFT		= 7,
222 	CLK_SPI0_PLL_DIV_CON_SHIFT	= 0,
223 
224 	/* CLKSEL_CON60 */
225 	CLK_SPI4_PLL_SEL_SHIFT		= 15,
226 	CLK_SPI4_PLL_DIV_CON_SHIFT	= 8,
227 	CLK_SPI2_PLL_SEL_SHIFT		= 7,
228 	CLK_SPI2_PLL_DIV_CON_SHIFT	= 0,
229 
230 	/* CLKSEL_CON61 */
231 	CLK_I2C_PLL_SEL_MASK		= 1,
232 	CLK_I2C_PLL_SEL_CPLL		= 0,
233 	CLK_I2C_PLL_SEL_GPLL		= 1,
234 	CLK_I2C5_PLL_SEL_SHIFT		= 15,
235 	CLK_I2C5_DIV_CON_SHIFT		= 8,
236 	CLK_I2C1_PLL_SEL_SHIFT		= 7,
237 	CLK_I2C1_DIV_CON_SHIFT		= 0,
238 
239 	/* CLKSEL_CON62 */
240 	CLK_I2C6_PLL_SEL_SHIFT		= 15,
241 	CLK_I2C6_DIV_CON_SHIFT		= 8,
242 	CLK_I2C2_PLL_SEL_SHIFT		= 7,
243 	CLK_I2C2_DIV_CON_SHIFT		= 0,
244 
245 	/* CLKSEL_CON63 */
246 	CLK_I2C7_PLL_SEL_SHIFT		= 15,
247 	CLK_I2C7_DIV_CON_SHIFT		= 8,
248 	CLK_I2C3_PLL_SEL_SHIFT		= 7,
249 	CLK_I2C3_DIV_CON_SHIFT		= 0,
250 
251 	/* CRU_SOFTRST_CON4 */
252 #define RESETN_DDR_REQ_SHIFT(ch)	(8 + (ch) * 4)
253 #define RESETN_DDRPHY_REQ_SHIFT(ch)	(9 + (ch) * 4)
254 };
255 
256 #define VCO_MAX_KHZ	(3200 * (MHz / KHz))
257 #define VCO_MIN_KHZ	(800 * (MHz / KHz))
258 #define OUTPUT_MAX_KHZ	(3200 * (MHz / KHz))
259 #define OUTPUT_MIN_KHZ	(16 * (MHz / KHz))
260 
261 /* the div restrictions of pll in integer mode,
262  * these are defined in * CRU_*PLL_CON0 or PMUCRU_*PLL_CON0
263  */
264 #define PLL_DIV_MIN	16
265 #define PLL_DIV_MAX	3200
266 
267 /* How to calculate the PLL(from TRM V0.3 Part 1 Page 63):
268  * Formulas also embedded within the Fractional PLL Verilog model:
269  * If DSMPD = 1 (DSM is disabled, "integer mode")
270  * FOUTVCO = FREF / REFDIV * FBDIV
271  * FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2
272  * Where:
273  * FOUTVCO = Fractional PLL non-divided output frequency
274  * FOUTPOSTDIV = Fractional PLL divided output frequency
275  *               (output of second post divider)
276  * FREF = Fractional PLL input reference frequency, (the OSC_HZ 24MHz input)
277  * REFDIV = Fractional PLL input reference clock divider
278  * FBDIV = Integer value programmed into feedback divide
279  *
280  */
rkclk_set_pll(u32 * pll_con,const struct pll_div * div)281 static void rkclk_set_pll(u32 *pll_con, const struct pll_div *div)
282 {
283 	/* All 8 PLLs have same VCO and output frequency range restrictions. */
284 	u32 vco_khz = OSC_HZ / 1000 * div->fbdiv / div->refdiv;
285 	u32 output_khz = vco_khz / div->postdiv1 / div->postdiv2;
286 
287 	printk(BIOS_DEBUG, "PLL at %p: fbdiv=%d, refdiv=%d, postdiv1=%d, "
288 			   "postdiv2=%d, vco=%u kHz, output=%u kHz\n",
289 			   pll_con, div->fbdiv, div->refdiv, div->postdiv1,
290 			   div->postdiv2, vco_khz, output_khz);
291 	assert(vco_khz >= VCO_MIN_KHZ && vco_khz <= VCO_MAX_KHZ &&
292 	       output_khz >= OUTPUT_MIN_KHZ && output_khz <= OUTPUT_MAX_KHZ &&
293 	       div->fbdiv >= PLL_DIV_MIN && div->fbdiv <= PLL_DIV_MAX);
294 
295 	/* When power on or changing PLL setting,
296 	 * we must force PLL into slow mode to ensure output stable clock.
297 	 */
298 	write32(&pll_con[3], RK_CLRSETBITS(PLL_MODE_MASK << PLL_MODE_SHIFT,
299 					   PLL_MODE_SLOW << PLL_MODE_SHIFT));
300 
301 	/* use integer mode */
302 	write32(&pll_con[3],
303 		RK_CLRSETBITS(PLL_DSMPD_MASK << PLL_DSMPD_SHIFT,
304 			      PLL_INTEGER_MODE << PLL_DSMPD_SHIFT));
305 
306 	write32(&pll_con[0], RK_CLRSETBITS(PLL_FBDIV_MASK << PLL_FBDIV_SHIFT,
307 					   div->fbdiv << PLL_FBDIV_SHIFT));
308 	write32(&pll_con[1],
309 		RK_CLRSETBITS(PLL_POSTDIV2_MASK << PLL_POSTDIV2_SHIFT |
310 			      PLL_POSTDIV1_MASK << PLL_POSTDIV1_SHIFT |
311 			      PLL_REFDIV_MASK | PLL_REFDIV_SHIFT,
312 			      (div->postdiv2 << PLL_POSTDIV2_SHIFT) |
313 			      (div->postdiv1 << PLL_POSTDIV1_SHIFT) |
314 			      (div->refdiv << PLL_REFDIV_SHIFT)));
315 
316 	/* waiting for pll lock */
317 	while (!(read32(&pll_con[2]) & (1 << PLL_LOCK_STATUS_SHIFT)))
318 		udelay(1);
319 
320 	/* pll enter normal mode */
321 	write32(&pll_con[3], RK_CLRSETBITS(PLL_MODE_MASK << PLL_MODE_SHIFT,
322 					   PLL_MODE_NORM << PLL_MODE_SHIFT));
323 }
324 
325 /*
326  * Configure the DPLL spread spectrum feature on memory clock.
327  * Configure sequence:
328  * 1. PLL been configured as frac mode, and DACPD should be set to 1'b0.
329  * 2. Configure DOWNSPERAD, SPREAD, DIVVAL(option: configure xPLL_CON5 with
330  *    extern wave table).
331  * 3. set ssmod_disable_sscg = 1'b0, and set ssmod_bp = 1'b0.
332  * 4. Assert RESET = 1'b1 to SSMOD.
333  * 5. RESET = 1'b0 on SSMOD.
334  * 6. Adjust SPREAD/DIVVAL/DOWNSPREAD.
335  */
rkclk_set_dpllssc(struct pll_div * dpll_cfg)336 static void rkclk_set_dpllssc(struct pll_div *dpll_cfg)
337 {
338 	u32 divval;
339 
340 	assert(dpll_cfg->refdiv && dpll_cfg->refdiv <= 6);
341 
342 	/*
343 	 * Need to acquire ~30kHZ which is the target modulation frequency.
344 	 * The modulation frequency ~ 30kHz= OSC_HZ/revdiv/128/divval
345 	 * (the 128 is the number points in the query table).
346 	 */
347 	divval = OSC_HZ / 128 / (30 * KHz) / dpll_cfg->refdiv;
348 
349 	/*
350 	 * Use frac mode.
351 	 * Make sure the output frequency isn't offset, set 0 for Fractional
352 	 * part of feedback divide.
353 	 */
354 	write32(&cru_ptr->dpll_con[3],
355 		RK_CLRSETBITS(PLL_DSMPD_MASK << PLL_DSMPD_SHIFT,
356 			      PLL_FRAC_MODE << PLL_DSMPD_SHIFT));
357 	clrsetbits32(&cru_ptr->dpll_con[2],
358 		     PLL_FRACDIV_MASK << PLL_FRACDIV_SHIFT,
359 		     0 << PLL_FRACDIV_SHIFT);
360 
361 	/*
362 	 * Configure SSC divval.
363 	 * Spread amplitude range = 0.1 * SPREAD[4:0] (%).
364 	 * The below 8 means SPREAD[4:0] that appears to mitigate EMI on boards
365 	 * tested. Center and down spread modulation amplitudes based on the
366 	 * value of SPREAD.
367 	 * SPREAD[4:0]	Center Spread	Down Spread
368 	 *	0	0		0
369 	 *	1	+/-0.1%		-0.10%
370 	 *	2	+/-0.2%		-0.20%
371 	 *	3	+/-0.3%		-0.30%
372 	 *	4	+/-0.4%		-0.40%
373 	 *	5	+/-0.5%		-0.50%
374 	 *	...
375 	 *	31	+/-3.1%		-3.10%
376 	 */
377 	write32(&cru_ptr->dpll_con[4],
378 		RK_CLRSETBITS(PLL_SSMOD_DIVVAL_MASK << PLL_SSMOD_DIVVAL_SHIFT,
379 			      divval << PLL_SSMOD_DIVVAL_SHIFT));
380 	write32(&cru_ptr->dpll_con[4],
381 		RK_CLRSETBITS(PLL_SSMOD_SPREADAMP_MASK <<
382 			      PLL_SSMOD_SPREADAMP_SHIFT,
383 			      8 << PLL_SSMOD_SPREADAMP_SHIFT));
384 
385 	/* Enable SSC for DPLL */
386 	write32(&cru_ptr->dpll_con[4],
387 		RK_CLRBITS(PLL_SSMOD_BP_MASK << PLL_SSMOD_BP_SHIFT |
388 			   PLL_SSMOD_DIS_SSCG_MASK << PLL_SSMOD_DIS_SSCG_SHIFT));
389 
390 	/* Deassert reset SSMOD */
391 	write32(&cru_ptr->dpll_con[4],
392 		RK_CLRBITS(PLL_SSMOD_RESET_MASK << PLL_SSMOD_RESET_SHIFT));
393 
394 	udelay(20);
395 }
396 
pll_para_config(u32 freq_hz,struct pll_div * div)397 static int pll_para_config(u32 freq_hz, struct pll_div *div)
398 {
399 	u32 ref_khz = OSC_HZ / KHz, refdiv, fbdiv = 0;
400 	u32 postdiv1, postdiv2 = 1;
401 	u32 fref_khz;
402 	u32 diff_khz, best_diff_khz;
403 	const u32 max_refdiv = 63, max_fbdiv = 3200, min_fbdiv = 16;
404 	const u32 max_postdiv1 = 7, max_postdiv2 = 7;
405 	u32 vco_khz;
406 	u32 freq_khz = freq_hz / KHz;
407 
408 	if (!freq_hz) {
409 		printk(BIOS_ERR, "%s: the frequency can't be 0 Hz\n", __func__);
410 		return -1;
411 	}
412 
413 	postdiv1 = DIV_ROUND_UP(VCO_MIN_KHZ, freq_khz);
414 	if (postdiv1 > max_postdiv1) {
415 		postdiv2 = DIV_ROUND_UP(postdiv1, max_postdiv1);
416 		postdiv1 = DIV_ROUND_UP(postdiv1, postdiv2);
417 	}
418 
419 	vco_khz = freq_khz * postdiv1 * postdiv2;
420 
421 	if (vco_khz < VCO_MIN_KHZ || vco_khz > VCO_MAX_KHZ ||
422 	    postdiv2 > max_postdiv2) {
423 		printk(BIOS_ERR, "%s: Cannot find out a supported VCO"
424 		       " for Frequency (%uHz).\n", __func__, freq_hz);
425 		return -1;
426 	}
427 
428 	div->postdiv1 = postdiv1;
429 	div->postdiv2 = postdiv2;
430 
431 	best_diff_khz = vco_khz;
432 	for (refdiv = 1; refdiv < max_refdiv && best_diff_khz; refdiv++) {
433 		fref_khz = ref_khz / refdiv;
434 
435 		fbdiv = vco_khz / fref_khz;
436 		if ((fbdiv >= max_fbdiv) || (fbdiv <= min_fbdiv))
437 			continue;
438 		diff_khz = vco_khz - fbdiv * fref_khz;
439 		if (fbdiv + 1 < max_fbdiv && diff_khz > fref_khz / 2) {
440 			fbdiv++;
441 			diff_khz = fref_khz - diff_khz;
442 		}
443 
444 		if (diff_khz >= best_diff_khz)
445 			continue;
446 
447 		best_diff_khz = diff_khz;
448 		div->refdiv = refdiv;
449 		div->fbdiv = fbdiv;
450 	}
451 
452 	if (best_diff_khz > 4 * (MHz/KHz)) {
453 		printk(BIOS_ERR, "%s: Failed to match output frequency %u, "
454 		       "difference is %u Hz,exceed 4MHZ\n", __func__, freq_hz,
455 		       best_diff_khz * KHz);
456 		return -1;
457 	}
458 	return 0;
459 }
460 
rkclk_init(void)461 void rkclk_init(void)
462 {
463 	u32 aclk_div;
464 	u32 hclk_div;
465 	u32 pclk_div;
466 
467 	/* some cru registers changed by bootrom, we'd better reset them to
468 	 * reset/default values described in TRM to avoid confusion in kernel.
469 	 * Please consider these three lines as a fix of bootrom bug.
470 	 */
471 	write32(&cru_ptr->clksel_con[12], 0xffff4101);
472 	write32(&cru_ptr->clksel_con[19], 0xffff033f);
473 	write32(&cru_ptr->clksel_con[56], 0x00030003);
474 
475 	/* configure pmu pll(ppll) */
476 	rkclk_set_pll(&pmucru_ptr->ppll_con[0], &ppll_init_cfg);
477 
478 	/* configure pmu pclk */
479 	pclk_div = PPLL_HZ / PMU_PCLK_HZ - 1;
480 	assert((unsigned int)(PPLL_HZ - (pclk_div + 1) * PMU_PCLK_HZ) <= pclk_div
481 	       && pclk_div <= 0x1f);
482 	write32(&pmucru_ptr->pmucru_clksel[0],
483 		RK_CLRSETBITS(PMU_PCLK_DIV_CON_MASK << PMU_PCLK_DIV_CON_SHIFT,
484 			      pclk_div << PMU_PCLK_DIV_CON_SHIFT));
485 
486 	/* configure gpll cpll */
487 	rkclk_set_pll(&cru_ptr->gpll_con[0], &gpll_init_cfg);
488 	rkclk_set_pll(&cru_ptr->cpll_con[0], &cpll_init_cfg);
489 
490 	/* configure perihp aclk, hclk, pclk */
491 	aclk_div = GPLL_HZ / PERIHP_ACLK_HZ - 1;
492 	assert((aclk_div + 1) * PERIHP_ACLK_HZ == GPLL_HZ && aclk_div <= 0x1f);
493 
494 	hclk_div = PERIHP_ACLK_HZ / PERIHP_HCLK_HZ - 1;
495 	assert((hclk_div + 1) * PERIHP_HCLK_HZ ==
496 	       PERIHP_ACLK_HZ && (hclk_div <= 0x3));
497 
498 	pclk_div = PERIHP_ACLK_HZ / PERIHP_PCLK_HZ - 1;
499 	assert((pclk_div + 1) * PERIHP_PCLK_HZ ==
500 	       PERIHP_ACLK_HZ && (pclk_div <= 0x7));
501 
502 	write32(&cru_ptr->clksel_con[14],
503 		RK_CLRSETBITS(PCLK_PERIHP_DIV_CON_MASK <<
504 						PCLK_PERIHP_DIV_CON_SHIFT |
505 			      HCLK_PERIHP_DIV_CON_MASK <<
506 						HCLK_PERIHP_DIV_CON_SHIFT |
507 			      ACLK_PERIHP_PLL_SEL_MASK <<
508 						ACLK_PERIHP_PLL_SEL_SHIFT |
509 			      ACLK_PERIHP_DIV_CON_MASK <<
510 						ACLK_PERIHP_DIV_CON_SHIFT,
511 			      pclk_div << PCLK_PERIHP_DIV_CON_SHIFT |
512 			      hclk_div << HCLK_PERIHP_DIV_CON_SHIFT |
513 			      ACLK_PERIHP_PLL_SEL_GPLL <<
514 						ACLK_PERIHP_PLL_SEL_SHIFT |
515 			      aclk_div << ACLK_PERIHP_DIV_CON_SHIFT));
516 
517 	/* configure perilp0 aclk, hclk, pclk */
518 	aclk_div = GPLL_HZ / PERILP0_ACLK_HZ - 1;
519 	assert((aclk_div + 1) * PERILP0_ACLK_HZ == GPLL_HZ && aclk_div <= 0x1f);
520 
521 	hclk_div = PERILP0_ACLK_HZ / PERILP0_HCLK_HZ - 1;
522 	assert((hclk_div + 1) * PERILP0_HCLK_HZ ==
523 	       PERILP0_ACLK_HZ && (hclk_div <= 0x3));
524 
525 	pclk_div = PERILP0_ACLK_HZ / PERILP0_PCLK_HZ - 1;
526 	assert((pclk_div + 1) * PERILP0_PCLK_HZ ==
527 	       PERILP0_ACLK_HZ && (pclk_div <= 0x7));
528 
529 	write32(&cru_ptr->clksel_con[23],
530 		RK_CLRSETBITS(PCLK_PERILP0_DIV_CON_MASK <<
531 						PCLK_PERILP0_DIV_CON_SHIFT |
532 			      HCLK_PERILP0_DIV_CON_MASK <<
533 						HCLK_PERILP0_DIV_CON_SHIFT |
534 			      ACLK_PERILP0_PLL_SEL_MASK <<
535 						ACLK_PERILP0_PLL_SEL_SHIFT |
536 			      ACLK_PERILP0_DIV_CON_MASK <<
537 						ACLK_PERILP0_DIV_CON_SHIFT,
538 			      pclk_div << PCLK_PERILP0_DIV_CON_SHIFT |
539 			      hclk_div << HCLK_PERILP0_DIV_CON_SHIFT |
540 			      ACLK_PERILP0_PLL_SEL_GPLL <<
541 						ACLK_PERILP0_PLL_SEL_SHIFT |
542 			      aclk_div << ACLK_PERILP0_DIV_CON_SHIFT));
543 
544 	/* perilp1 hclk select gpll as source */
545 	hclk_div = GPLL_HZ / PERILP1_HCLK_HZ - 1;
546 	assert((hclk_div + 1) * PERILP1_HCLK_HZ ==
547 	       GPLL_HZ && (hclk_div <= 0x1f));
548 
549 	pclk_div = PERILP1_HCLK_HZ / PERILP1_PCLK_HZ - 1;
550 	assert((pclk_div + 1) * PERILP1_PCLK_HZ ==
551 	       PERILP1_HCLK_HZ && (pclk_div <= 0x7));
552 
553 	write32(&cru_ptr->clksel_con[25],
554 		RK_CLRSETBITS(PCLK_PERILP1_DIV_CON_MASK <<
555 						PCLK_PERILP1_DIV_CON_SHIFT |
556 			      HCLK_PERILP1_DIV_CON_MASK <<
557 						HCLK_PERILP1_DIV_CON_SHIFT |
558 			      HCLK_PERILP1_PLL_SEL_MASK <<
559 						HCLK_PERILP1_PLL_SEL_SHIFT,
560 			      pclk_div << PCLK_PERILP1_DIV_CON_SHIFT |
561 			      hclk_div << HCLK_PERILP1_DIV_CON_SHIFT |
562 			      HCLK_PERILP1_PLL_SEL_GPLL <<
563 						HCLK_PERILP1_PLL_SEL_SHIFT));
564 }
565 
rkclk_configure_cpu(enum apll_frequencies freq,enum cpu_cluster cluster)566 void rkclk_configure_cpu(enum apll_frequencies freq, enum cpu_cluster cluster)
567 {
568 	u32 aclkm_div, atclk_div, pclk_dbg_div, apll_hz;
569 	int con_base, parent;
570 	u32 *pll_con;
571 
572 	switch (cluster) {
573 	case CPU_CLUSTER_LITTLE:
574 		con_base = 0;
575 		parent = CLK_CORE_PLL_SEL_ALPLL;
576 		pll_con = &cru_ptr->apll_l_con[0];
577 		break;
578 	case CPU_CLUSTER_BIG:
579 	default:
580 		con_base = 2;
581 		parent = CLK_CORE_PLL_SEL_ABPLL;
582 		pll_con = &cru_ptr->apll_b_con[0];
583 		break;
584 	}
585 
586 	apll_hz = apll_cfgs[freq]->freq;
587 	rkclk_set_pll(pll_con, apll_cfgs[freq]);
588 
589 	aclkm_div = DIV_ROUND_UP(apll_hz, ACLKM_CORE_HZ) - 1;
590 	pclk_dbg_div = DIV_ROUND_UP(apll_hz, PCLK_DBG_HZ) - 1;
591 	atclk_div = DIV_ROUND_UP(apll_hz, ATCLK_CORE_HZ) - 1;
592 
593 	write32(&cru_ptr->clksel_con[con_base],
594 		RK_CLRSETBITS(ACLKM_CORE_DIV_CON_MASK <<
595 						ACLKM_CORE_DIV_CON_SHIFT |
596 			      CLK_CORE_PLL_SEL_MASK << CLK_CORE_PLL_SEL_SHIFT |
597 			      CLK_CORE_DIV_MASK << CLK_CORE_DIV_SHIFT,
598 			      aclkm_div << ACLKM_CORE_DIV_CON_SHIFT |
599 			      parent << CLK_CORE_PLL_SEL_SHIFT |
600 			      0 << CLK_CORE_DIV_SHIFT));
601 
602 	write32(&cru_ptr->clksel_con[con_base + 1],
603 		RK_CLRSETBITS(PCLK_DBG_DIV_MASK << PCLK_DBG_DIV_SHIFT |
604 			      ATCLK_CORE_DIV_MASK << ATCLK_CORE_DIV_SHIFT,
605 			      pclk_dbg_div << PCLK_DBG_DIV_SHIFT |
606 			      atclk_div << ATCLK_CORE_DIV_SHIFT));
607 }
608 
rkclk_configure_ddr(unsigned int hz)609 void rkclk_configure_ddr(unsigned int hz)
610 {
611 	struct pll_div dpll_cfg;
612 
613 	/* IC ECO bug, need to set this register */
614 	write32(&rk3399_pmusgrf->ddr_rgn_con[16], 0xc000c000);
615 
616 	/* clk_ddrc == DPLL = 24MHz / refdiv * fbdiv / postdiv1 / postdiv2 */
617 	switch (hz) {
618 	case 200*MHz:
619 		dpll_cfg = (struct pll_div)
620 		{.refdiv = 1, .fbdiv = 50, .postdiv1 = 3, .postdiv2 = 2};
621 		break;
622 	case 300*MHz:
623 		dpll_cfg = (struct pll_div)
624 		{.refdiv = 2, .fbdiv = 100, .postdiv1 = 4, .postdiv2 = 1};
625 		break;
626 	case 666*MHz:
627 		dpll_cfg = (struct pll_div)
628 		{.refdiv = 2, .fbdiv = 111, .postdiv1 = 2, .postdiv2 = 1};
629 		break;
630 	case 800*MHz:
631 		dpll_cfg = (struct pll_div)
632 		{.refdiv = 1, .fbdiv = 100, .postdiv1 = 3, .postdiv2 = 1};
633 		break;
634 	case 933*MHz:
635 		dpll_cfg = (struct pll_div)
636 		{.refdiv = 1, .fbdiv = 116, .postdiv1 = 3, .postdiv2 = 1};
637 		break;
638 	default:
639 		die("Unsupported SDRAM frequency, add to clock.c!");
640 	}
641 	rkclk_set_pll(&cru_ptr->dpll_con[0], &dpll_cfg);
642 
643 	if (CONFIG(RK3399_SPREAD_SPECTRUM_DDR))
644 		rkclk_set_dpllssc(&dpll_cfg);
645 }
646 
rkclk_ddr_reset(u32 ch,u32 ctl,u32 phy)647 void rkclk_ddr_reset(u32 ch, u32 ctl, u32 phy)
648 {
649 	write32(&cru_ptr->softrst_con[4], RK_CLRSETBITS(
650 		1 << RESETN_DDR_REQ_SHIFT(ch) | 1 << RESETN_DDRPHY_REQ_SHIFT(ch),
651 		ctl << RESETN_DDR_REQ_SHIFT(ch) | phy << RESETN_DDRPHY_REQ_SHIFT(ch)));
652 }
653 
654 #define SPI_CLK_REG_VALUE(bus, clk_div) \
655 		RK_CLRSETBITS(CLK_SPI_PLL_SEL_MASK << \
656 					CLK_SPI ##bus## _PLL_SEL_SHIFT | \
657 			      CLK_SPI_PLL_DIV_CON_MASK << \
658 					CLK_SPI ##bus## _PLL_DIV_CON_SHIFT, \
659 			      CLK_SPI_PLL_SEL_GPLL << \
660 					CLK_SPI ##bus## _PLL_SEL_SHIFT | \
661 			      (clk_div - 1) << \
662 					CLK_SPI ##bus## _PLL_DIV_CON_SHIFT)
663 
rkclk_configure_spi(unsigned int bus,unsigned int hz)664 void rkclk_configure_spi(unsigned int bus, unsigned int hz)
665 {
666 	int src_clk_div;
667 	int pll;
668 
669 	/* spi3 src clock from ppll, while spi0,1,2,4,5 src clock from gpll */
670 	pll = (bus == 3) ? PPLL_HZ : GPLL_HZ;
671 	src_clk_div = pll / hz;
672 	assert((src_clk_div - 1 <= 127) && (src_clk_div * hz == pll));
673 
674 	switch (bus) {
675 	case 0:
676 		write32(&cru_ptr->clksel_con[59],
677 			SPI_CLK_REG_VALUE(0, src_clk_div));
678 		break;
679 	case 1:
680 		write32(&cru_ptr->clksel_con[59],
681 			SPI_CLK_REG_VALUE(1, src_clk_div));
682 		break;
683 	case 2:
684 		write32(&cru_ptr->clksel_con[60],
685 			SPI_CLK_REG_VALUE(2, src_clk_div));
686 		break;
687 	case 3:
688 		write32(&pmucru_ptr->pmucru_clksel[1],
689 			RK_CLRSETBITS(SPI3_PLL_SEL_MASK << SPI3_PLL_SEL_SHIFT |
690 				      SPI3_DIV_CON_MASK << SPI3_DIV_CON_SHIFT,
691 				      SPI3_PLL_SEL_PPLL << SPI3_PLL_SEL_SHIFT |
692 				      (src_clk_div - 1) << SPI3_DIV_CON_SHIFT));
693 		break;
694 	case 4:
695 		write32(&cru_ptr->clksel_con[60],
696 			SPI_CLK_REG_VALUE(4, src_clk_div));
697 		break;
698 	case 5:
699 		write32(&cru_ptr->clksel_con[58],
700 			SPI_CLK_REG_VALUE(5, src_clk_div));
701 		break;
702 	default:
703 		printk(BIOS_ERR, "do not support this spi bus\n");
704 	}
705 }
706 
707 #define I2C_CLK_REG_VALUE(bus, clk_div) \
708 		RK_CLRSETBITS(I2C_DIV_CON_MASK << \
709 					CLK_I2C ##bus## _DIV_CON_SHIFT | \
710 			      CLK_I2C_PLL_SEL_MASK << \
711 					CLK_I2C ##bus## _PLL_SEL_SHIFT, \
712 			      (clk_div - 1) << \
713 					CLK_I2C ##bus## _DIV_CON_SHIFT | \
714 			      CLK_I2C_PLL_SEL_GPLL << \
715 					CLK_I2C ##bus## _PLL_SEL_SHIFT)
716 #define PMU_I2C_CLK_REG_VALUE(bus, clk_div) \
717 		RK_CLRSETBITS(I2C_DIV_CON_MASK << I2C ##bus## _DIV_CON_SHIFT, \
718 			      (clk_div - 1) << I2C ##bus## _DIV_CON_SHIFT)
719 
rkclk_i2c_clock_for_bus(unsigned int bus)720 uint32_t rkclk_i2c_clock_for_bus(unsigned int bus)
721 {
722 	int src_clk_div, pll, freq;
723 
724 	/* i2c0,4,8 src clock from ppll, i2c1,2,3,5,6,7 src clock from gpll */
725 	if (bus == 0 || bus == 4 || bus == 8) {
726 		pll = PPLL_HZ;
727 		freq = 338*MHz;
728 	} else {
729 		pll = GPLL_HZ;
730 		freq = 198*MHz;
731 	}
732 	src_clk_div = pll / freq;
733 	assert((src_clk_div - 1 <= 127) && (src_clk_div * freq == pll));
734 
735 	switch (bus) {
736 	case 0:
737 		write32(&pmucru_ptr->pmucru_clksel[2],
738 			PMU_I2C_CLK_REG_VALUE(0, src_clk_div));
739 		break;
740 	case 1:
741 		write32(&cru_ptr->clksel_con[61],
742 			I2C_CLK_REG_VALUE(1, src_clk_div));
743 		break;
744 	case 2:
745 		write32(&cru_ptr->clksel_con[62],
746 			I2C_CLK_REG_VALUE(2, src_clk_div));
747 		break;
748 	case 3:
749 		write32(&cru_ptr->clksel_con[63],
750 			I2C_CLK_REG_VALUE(3, src_clk_div));
751 		break;
752 	case 4:
753 		write32(&pmucru_ptr->pmucru_clksel[3],
754 			PMU_I2C_CLK_REG_VALUE(4, src_clk_div));
755 		break;
756 	case 5:
757 		write32(&cru_ptr->clksel_con[61],
758 			I2C_CLK_REG_VALUE(5, src_clk_div));
759 		break;
760 	case 6:
761 		write32(&cru_ptr->clksel_con[62],
762 			I2C_CLK_REG_VALUE(6, src_clk_div));
763 		break;
764 	case 7:
765 		write32(&cru_ptr->clksel_con[63],
766 			I2C_CLK_REG_VALUE(7, src_clk_div));
767 		break;
768 	case 8:
769 		write32(&pmucru_ptr->pmucru_clksel[2],
770 			PMU_I2C_CLK_REG_VALUE(8, src_clk_div));
771 		break;
772 	default:
773 		die("unknown i2c bus\n");
774 	}
775 
776 	return freq;
777 }
778 
rkclk_configure_i2s(unsigned int hz)779 void rkclk_configure_i2s(unsigned int hz)
780 {
781 	int n, d;
782 	int v;
783 
784 	/**
785 	 * clk_i2s0_sel: divider output from fraction
786 	 * clk_i2s0_pll_sel source clock: cpll
787 	 * clk_i2s0_div_con: 1 (div+1)
788 	 */
789 	write32(&cru_ptr->clksel_con[28],
790 		RK_CLRSETBITS(3 << 8 | 1 << 7 | 0x7f << 0,
791 			      1 << 8 | 0 << 7 | 0 << 0));
792 
793 	/* make sure and enable i2s0 path gates */
794 	write32(&cru_ptr->clkgate_con[8],
795 		RK_CLRBITS(1 << 12 | 1 << 5 | 1 << 4 | 1 << 3));
796 
797 	/* set frac divider */
798 	v = gcd(CPLL_HZ, hz);
799 	n = (CPLL_HZ / v) & (0xffff);
800 	d = (hz / v) & (0xffff);
801 	assert(hz == (u64)CPLL_HZ * d / n);
802 	write32(&cru_ptr->clksel_con[96], d << 16 | n);
803 
804 	/**
805 	 * clk_i2sout_sel clk_i2s
806 	 * clk_i2s_ch_sel: clk_i2s0
807 	 */
808 	write32(&cru_ptr->clksel_con[31],
809 		RK_CLRSETBITS(1 << 2 | 3 << 0,
810 			      0 << 2 | 0 << 0));
811 }
812 
rkclk_configure_saradc(unsigned int hz)813 void rkclk_configure_saradc(unsigned int hz)
814 {
815 	int src_clk_div;
816 
817 	/* saradc src clk from 24MHz */
818 	src_clk_div = 24 * MHz / hz;
819 	assert((src_clk_div - 1 <= 255) && (src_clk_div * hz == 24 * MHz));
820 
821 	write32(&cru_ptr->clksel_con[26],
822 		RK_CLRSETBITS(CLK_SARADC_DIV_CON_MASK <<
823 						CLK_SARADC_DIV_CON_SHIFT,
824 			      (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT));
825 }
826 
rkclk_configure_vop_aclk(u32 vop_id,u32 aclk_hz)827 void rkclk_configure_vop_aclk(u32 vop_id, u32 aclk_hz)
828 {
829 	u32 div;
830 	void *reg_addr = vop_id ? &cru_ptr->clksel_con[48] :
831 				  &cru_ptr->clksel_con[47];
832 
833 	/* vop aclk source clk: cpll */
834 	div = CPLL_HZ / aclk_hz;
835 	assert((div - 1 <= 31) && (div * aclk_hz == CPLL_HZ));
836 
837 	write32(reg_addr, RK_CLRSETBITS(
838 			ACLK_VOP_PLL_SEL_MASK << ACLK_VOP_PLL_SEL_SHIFT |
839 			ACLK_VOP_DIV_CON_MASK << ACLK_VOP_DIV_CON_SHIFT,
840 			ACLK_VOP_PLL_SEL_CPLL << ACLK_VOP_PLL_SEL_SHIFT |
841 			(div - 1) << ACLK_VOP_DIV_CON_SHIFT));
842 }
843 
rkclk_configure_vop_dclk(u32 vop_id,u32 dclk_hz)844 int rkclk_configure_vop_dclk(u32 vop_id, u32 dclk_hz)
845 {
846 	struct pll_div vpll_config = {0};
847 	void *reg_addr = vop_id ? &cru_ptr->clksel_con[50] :
848 				  &cru_ptr->clksel_con[49];
849 
850 	/* vop dclk source from vpll, and equals to vpll(means div == 1) */
851 	if (pll_para_config(dclk_hz, &vpll_config))
852 		return -1;
853 
854 	rkclk_set_pll(&cru_ptr->vpll_con[0], &vpll_config);
855 
856 	write32(reg_addr, RK_CLRSETBITS(
857 			DCLK_VOP_DCLK_SEL_MASK << DCLK_VOP_DCLK_SEL_SHIFT |
858 			DCLK_VOP_PLL_SEL_MASK << DCLK_VOP_PLL_SEL_SHIFT |
859 			DCLK_VOP_DIV_CON_MASK << DCLK_VOP_DIV_CON_SHIFT,
860 			DCLK_VOP_DCLK_SEL_DIVOUT << DCLK_VOP_DCLK_SEL_SHIFT |
861 			DCLK_VOP_PLL_SEL_VPLL << DCLK_VOP_PLL_SEL_SHIFT |
862 			(1 - 1) << DCLK_VOP_DIV_CON_SHIFT));
863 
864 	return 0;
865 }
866 
rkclk_configure_tsadc(unsigned int hz)867 void rkclk_configure_tsadc(unsigned int hz)
868 {
869 	int src_clk_div;
870 
871 	/* use 24M as src clock */
872 	src_clk_div = OSC_HZ / hz;
873 	assert((src_clk_div - 1 <= 1023) && (src_clk_div * hz == OSC_HZ));
874 
875 	write32(&cru_ptr->clksel_con[27], RK_CLRSETBITS(
876 			CLK_TSADC_DIV_CON_MASK << CLK_TSADC_DIV_CON_SHIFT |
877 			CLK_TSADC_SEL_MASK << CLK_TSADC_SEL_SHIFT,
878 			src_clk_div << CLK_TSADC_DIV_CON_SHIFT |
879 			CLK_TSADC_SEL_X24M << CLK_TSADC_SEL_SHIFT));
880 }
881 
rkclk_configure_emmc(void)882 void rkclk_configure_emmc(void)
883 {
884 	int src_clk_div;
885 	int aclk_emmc = 148500*KHz;
886 	int clk_emmc = 148500*KHz;
887 
888 	/* Select aclk_emmc source from GPLL */
889 	src_clk_div = GPLL_HZ / aclk_emmc;
890 	assert((src_clk_div - 1 <= 31) && (src_clk_div * aclk_emmc == GPLL_HZ));
891 
892 	write32(&cru_ptr->clksel_con[21],
893 		RK_CLRSETBITS(ACLK_EMMC_PLL_SEL_MASK <<
894 						ACLK_EMMC_PLL_SEL_SHIFT |
895 			      ACLK_EMMC_DIV_CON_MASK << ACLK_EMMC_DIV_CON_SHIFT,
896 			      ACLK_EMMC_PLL_SEL_GPLL <<
897 						ACLK_EMMC_PLL_SEL_SHIFT |
898 			      (src_clk_div - 1) << ACLK_EMMC_DIV_CON_SHIFT));
899 
900 	/* Select clk_emmc source from GPLL too */
901 	src_clk_div = GPLL_HZ / clk_emmc;
902 	assert((src_clk_div - 1 <= 127) && (src_clk_div * clk_emmc == GPLL_HZ));
903 
904 	write32(&cru_ptr->clksel_con[22],
905 		RK_CLRSETBITS(CLK_EMMC_PLL_MASK << CLK_EMMC_PLL_SHIFT |
906 			      CLK_EMMC_DIV_CON_MASK << CLK_EMMC_DIV_CON_SHIFT,
907 			      CLK_EMMC_PLL_SEL_GPLL << CLK_EMMC_PLL_SHIFT |
908 			      (src_clk_div - 1) << CLK_EMMC_DIV_CON_SHIFT));
909 }
910 
rkclk_was_watchdog_reset(void)911 int rkclk_was_watchdog_reset(void)
912 {
913 	/* Bits 5 and 4 are "second" and "first" global watchdog reset. */
914 	return read32(&cru_ptr->glb_rst_st) & 0x30;
915 }
916 
rkclk_configure_edp(unsigned int hz)917 void rkclk_configure_edp(unsigned int hz)
918 {
919 	int src_clk_div;
920 
921 	src_clk_div = CPLL_HZ / hz;
922 	assert((src_clk_div - 1 <= 63) && (src_clk_div * hz == CPLL_HZ));
923 
924 	write32(&cru_ptr->clksel_con[44],
925 		RK_CLRSETBITS(CLK_PCLK_EDP_PLL_SEL_MASK <<
926 			      CLK_PCLK_EDP_PLL_SEL_SHIFT |
927 			      CLK_PCLK_EDP_DIV_CON_MASK <<
928 			      CLK_PCLK_EDP_DIV_CON_SHIFT,
929 			      CLK_PCLK_EDP_PLL_SEL_CPLL <<
930 			      CLK_PCLK_EDP_PLL_SEL_SHIFT |
931 			      (src_clk_div - 1) <<
932 			      CLK_PCLK_EDP_DIV_CON_SHIFT));
933 }
934 
rkclk_configure_mipi(void)935 void rkclk_configure_mipi(void)
936 {
937 	/* Enable clk_mipidphy_ref and clk_mipidphy_cfg */
938 	write32(&cru_ptr->clkgate_con[11],
939 		RK_CLRBITS(1 << 14 | 1 << 15));
940 	/* Enable pclk_mipi_dsi0 */
941 	write32(&cru_ptr->clkgate_con[29],
942 		RK_CLRBITS(1 << 1));
943 }
944