xref: /OK3568_Linux_fs/kernel/drivers/media/i2c/rk628/rk628_cru.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2020 Rockchip Electronics Co. Ltd.
4  *
5  * Author: Shunqing Chen <csq@rock-chips.com>
6  */
7 
8 #include <linux/delay.h>
9 #include "rk628.h"
10 #include "rk628_cru.h"
11 
12 #define REFCLK_RATE		24000000UL
13 #define MIN_FREF_RATE		10000000UL
14 #define MAX_FREF_RATE		800000000UL
15 #define MIN_FREFDIV_RATE	1000000UL
16 #define MAX_FREFDIV_RATE	100000000UL
17 #define MIN_FVCO_RATE		600000000UL
18 #define MAX_FVCO_RATE		1600000000UL
19 #define MIN_FOUTPOSTDIV_RATE	12000000UL
20 #define MAX_FOUTPOSTDIV_RATE	1600000000UL
21 
rational_best_approximation(unsigned long given_numerator,unsigned long given_denominator,unsigned long max_numerator,unsigned long max_denominator,unsigned long * best_numerator,unsigned long * best_denominator)22 static void rational_best_approximation(unsigned long given_numerator,
23 					unsigned long given_denominator,
24 					unsigned long max_numerator,
25 					unsigned long max_denominator,
26 					unsigned long *best_numerator,
27 					unsigned long *best_denominator)
28 {
29 	unsigned long n, d, n0, d0, n1, d1;
30 
31 	n = given_numerator;
32 	d = given_denominator;
33 	n0 = d1 = 0;
34 	n1 = d0 = 1;
35 	for (;;) {
36 		unsigned long t, a;
37 
38 		if ((n1 > max_numerator) || (d1 > max_denominator)) {
39 			n1 = n0;
40 			d1 = d0;
41 			break;
42 		}
43 		if (d == 0)
44 			break;
45 		t = d;
46 		a = n / d;
47 		d = n % d;
48 		n = t;
49 		t = n0 + a * n1;
50 		n0 = n1;
51 		n1 = t;
52 		t = d0 + a * d1;
53 		d0 = d1;
54 		d1 = t;
55 	}
56 	*best_numerator = n1;
57 	*best_denominator = d1;
58 }
59 
rk628_cru_clk_get_rate_pll(struct rk628 * rk628,unsigned int id)60 static unsigned long rk628_cru_clk_get_rate_pll(struct rk628 *rk628,
61 						unsigned int id)
62 {
63 	unsigned long parent_rate = REFCLK_RATE;
64 	u32 postdiv1, fbdiv, dsmpd, postdiv2, refdiv, frac, bypass;
65 	u32 con0, con1, con2;
66 	u64 foutvco, foutpostdiv;
67 	u32 offset, val;
68 
69 	rk628_i2c_read(rk628, CRU_MODE_CON00, &val);
70 	if (id == CGU_CLK_CPLL) {
71 		val &= CLK_CPLL_MODE_MASK;
72 		val >>= CLK_CPLL_MODE_SHIFT;
73 		if (val == CLK_CPLL_MODE_OSC)
74 			return parent_rate;
75 
76 		offset = 0x00;
77 	} else {
78 		val &= CLK_GPLL_MODE_MASK;
79 		val >>= CLK_GPLL_MODE_SHIFT;
80 		if (val == CLK_GPLL_MODE_OSC)
81 			return parent_rate;
82 
83 		offset = 0x20;
84 	}
85 
86 	rk628_i2c_read(rk628, offset + CRU_CPLL_CON0, &con0);
87 	rk628_i2c_read(rk628, offset + CRU_CPLL_CON1, &con1);
88 	rk628_i2c_read(rk628, offset + CRU_CPLL_CON2, &con2);
89 
90 	bypass = (con0 & PLL_BYPASS_MASK) >> PLL_BYPASS_SHIFT;
91 	postdiv1 = (con0 & PLL_POSTDIV1_MASK) >> PLL_POSTDIV1_SHIFT;
92 	fbdiv = (con0 & PLL_FBDIV_MASK) >> PLL_FBDIV_SHIFT;
93 	dsmpd = (con1 & PLL_DSMPD_MASK) >> PLL_DSMPD_SHIFT;
94 	postdiv2 = (con1 & PLL_POSTDIV2_MASK) >> PLL_POSTDIV2_SHIFT;
95 	refdiv = (con1 & PLL_REFDIV_MASK) >> PLL_REFDIV_SHIFT;
96 	frac = (con2 & PLL_FRAC_MASK) >> PLL_FRAC_SHIFT;
97 
98 	if (bypass)
99 		return parent_rate;
100 
101 	foutvco = parent_rate * fbdiv;
102 	do_div(foutvco, refdiv);
103 
104 	if (!dsmpd) {
105 		u64 frac_rate = (u64)parent_rate * frac;
106 
107 		do_div(frac_rate, refdiv);
108 		foutvco += frac_rate >> 24;
109 	}
110 
111 	foutpostdiv = foutvco;
112 	do_div(foutpostdiv, postdiv1);
113 	do_div(foutpostdiv, postdiv2);
114 
115 	return foutpostdiv;
116 }
117 
rk628_cru_clk_set_rate_pll(struct rk628 * rk628,unsigned int id,unsigned long rate)118 static unsigned long rk628_cru_clk_set_rate_pll(struct rk628 *rk628,
119 						unsigned int id,
120 						unsigned long rate)
121 {
122 	unsigned long fin = REFCLK_RATE, fout = rate;
123 	u8 min_refdiv, max_refdiv, postdiv, div1, div2;
124 	u8 dsmpd = 1, postdiv1 = 0, postdiv2 = 0, refdiv = 0;
125 	u16 fbdiv = 0;
126 	u32 frac = 0;
127 	u64 foutvco, foutpostdiv;
128 	u32 offset, val;
129 
130 	/*
131 	 * FREF : 10MHz ~ 800MHz
132 	 * FREFDIV : 1MHz ~ 40MHz
133 	 * FOUTVCO : 400MHz ~ 1.6GHz
134 	 * FOUTPOSTDIV : 8MHz ~ 1.6GHz
135 	 */
136 	if (fin < MIN_FREF_RATE || fin > MAX_FREF_RATE)
137 		return 0;
138 
139 	if (fout < MIN_FOUTPOSTDIV_RATE || fout > MAX_FOUTPOSTDIV_RATE)
140 		return 0;
141 
142 	if (id == CGU_CLK_CPLL)
143 		offset = 0x00;
144 	else
145 		offset = 0x20;
146 
147 	if (fin == fout) {
148 		rk628_i2c_write(rk628, offset + CRU_CPLL_CON0, PLL_BYPASS(1));
149 		rk628_i2c_write(rk628, offset + CRU_CPLL_CON1, PLL_PD(0));
150 		while (1) {
151 			rk628_i2c_read(rk628, offset + CRU_CPLL_CON1, &val);
152 			if (val & PLL_LOCK)
153 				break;
154 		}
155 		return fin;
156 	}
157 
158 	min_refdiv = fin / MAX_FREFDIV_RATE + 1;
159 	max_refdiv = fin / MIN_FREFDIV_RATE;
160 	if (max_refdiv > 64)
161 		max_refdiv = 64;
162 
163 	if (fout < MIN_FVCO_RATE) {
164 		div1 = DIV_ROUND_UP(MIN_FVCO_RATE, fout);
165 		div2 = DIV_ROUND_UP(MAX_FVCO_RATE, fout);
166 		for (postdiv = div1; postdiv <= div2; postdiv++) {
167 			/* fix prime number that can not find right div*/
168 			for (postdiv2 = 1; postdiv2 < 8; postdiv2++) {
169 				if (postdiv % postdiv2)
170 					continue;
171 
172 				postdiv1 = postdiv / postdiv2;
173 
174 				if (postdiv1 > 0 && postdiv1 < 8)
175 					break;
176 			}
177 			if (postdiv2 > 7)
178 				continue;
179 			else
180 				break;
181 		}
182 
183 		if (postdiv > div2)
184 			return 0;
185 
186 		fout *= postdiv1 * postdiv2;
187 	} else {
188 		postdiv1 = 1;
189 		postdiv2 = 1;
190 	}
191 
192 	for (refdiv = min_refdiv; refdiv <= max_refdiv; refdiv++) {
193 		u64 tmp, frac_rate;
194 
195 		if (fin % refdiv)
196 			continue;
197 
198 		tmp = (u64)fout * refdiv;
199 		do_div(tmp, fin);
200 		fbdiv = tmp;
201 		if (fbdiv < 10 || fbdiv > 1600)
202 			continue;
203 
204 		tmp = (u64)fbdiv * fin;
205 		do_div(tmp, refdiv);
206 		if (fout < MIN_FVCO_RATE || fout > MAX_FVCO_RATE)
207 			continue;
208 
209 		frac_rate = fout - tmp;
210 
211 		if (frac_rate) {
212 			tmp = (u64)frac_rate * refdiv;
213 			tmp <<= 24;
214 			do_div(tmp, fin);
215 			frac = tmp;
216 			dsmpd = 0;
217 		}
218 
219 		break;
220 	}
221 
222 	/*
223 	 * If DSMPD = 1 (DSM is disabled, "integer mode")
224 	 * FOUTVCO = FREF / REFDIV * FBDIV
225 	 * FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2
226 	 *
227 	 * If DSMPD = 0 (DSM is enabled, "fractional mode")
228 	 * FOUTVCO = FREF / REFDIV * (FBDIV + FRAC / 2^24)
229 	 * FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2
230 	 */
231 	foutvco = fin * fbdiv;
232 	do_div(foutvco, refdiv);
233 
234 	if (!dsmpd) {
235 		u64 frac_rate = (u64)fin * frac;
236 
237 		do_div(frac_rate, refdiv);
238 		foutvco += frac_rate >> 24;
239 	}
240 
241 	foutpostdiv = foutvco;
242 	do_div(foutpostdiv, postdiv1);
243 	do_div(foutpostdiv, postdiv2);
244 
245 	rk628_i2c_write(rk628, offset + CRU_CPLL_CON0,
246 			PLL_BYPASS(0) | PLL_POSTDIV1(postdiv1) |
247 			PLL_FBDIV(fbdiv));
248 	rk628_i2c_write(rk628, offset + CRU_CPLL_CON1,
249 			PLL_DSMPD(dsmpd) | PLL_POSTDIV2(postdiv2) |
250 			PLL_REFDIV(refdiv));
251 	rk628_i2c_write(rk628, offset + CRU_CPLL_CON2, PLL_FRAC(frac));
252 
253 	while (1) {
254 		rk628_i2c_read(rk628, offset + CRU_CPLL_CON1, &val);
255 		if (val & PLL_LOCK)
256 			break;
257 	}
258 
259 	return (unsigned long)foutpostdiv;
260 }
261 
rk628_cru_clk_set_rate_sclk_vop(struct rk628 * rk628,unsigned long rate)262 static unsigned long rk628_cru_clk_set_rate_sclk_vop(struct rk628 *rk628,
263 						     unsigned long rate)
264 {
265 	unsigned long m, n, parent_rate;
266 	u32 val;
267 
268 	rk628_i2c_read(rk628, CRU_CLKSEL_CON02, &val);
269 	val &= SCLK_VOP_SEL_MASK;
270 	val >>= SCLK_VOP_SEL_SHIFT;
271 	if (val == SCLK_VOP_SEL_GPLL)
272 		parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_GPLL);
273 	else
274 		parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_CPLL);
275 
276 	rational_best_approximation(rate, parent_rate,
277 				    GENMASK(15, 0), GENMASK(15, 0),
278 				    &m, &n);
279 	rk628_i2c_write(rk628, CRU_CLKSEL_CON13, m << 16 | n);
280 
281 	return rate;
282 }
283 
rk628_cru_clk_set_rate_sclk_hdmirx_aud(struct rk628 * rk628,unsigned long rate)284 static unsigned long rk628_cru_clk_set_rate_sclk_hdmirx_aud(struct rk628 *rk628,
285 						      unsigned long rate)
286 {
287 	u64 parent_rate;
288 	u8 div;
289 
290 	parent_rate = rk628_cru_clk_set_rate_pll(rk628, CGU_CLK_GPLL, rate*4);
291 	div = DIV_ROUND_CLOSEST_ULL(parent_rate, rate);
292 	do_div(parent_rate, div);
293 	rate = parent_rate;
294 	rk628_i2c_write(rk628, CRU_CLKSEL_CON05, 0x3fc0 << 16 | ((div - 1) << 6) |
295 			CLK_HDMIRX_AUD_SEL << 16 | CLK_HDMIRX_AUD_SEL);
296 	return rate;
297 }
298 
rk628_cru_clk_get_rate_sclk_hdmirx_aud(struct rk628 * rk628)299 static unsigned long rk628_cru_clk_get_rate_sclk_hdmirx_aud(struct rk628 *rk628)
300 {
301 	unsigned long rate;
302 	u64 parent_rate;
303 	u8 div;
304 	u32 val;
305 
306 	rk628_i2c_read(rk628, CRU_CLKSEL_CON05, &val);
307 	if (val & CLK_HDMIRX_AUD_SEL)
308 		parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_GPLL);
309 	else
310 		parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_CPLL);
311 	div = ((val&0x3fc0) >> 6) + 1;
312 	do_div(parent_rate, div);
313 	rate = parent_rate;
314 	return rate;
315 }
316 
rk628_cru_clk_get_rate_sclk_vop(struct rk628 * rk628)317 static unsigned long rk628_cru_clk_get_rate_sclk_vop(struct rk628 *rk628)
318 {
319 	unsigned long rate, parent_rate, m, n;
320 	u32 mux, div;
321 
322 	rk628_i2c_read(rk628, CRU_CLKSEL_CON02, &mux);
323 	mux &= CLK_UART_SRC_SEL_MASK;
324 	mux >>= SCLK_VOP_SEL_SHIFT;
325 	if (mux == SCLK_VOP_SEL_GPLL)
326 		parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_GPLL);
327 	else
328 		parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_CPLL);
329 
330 	rk628_i2c_read(rk628, CRU_CLKSEL_CON13, &div);
331 	m = div >> 16 & 0xffff;
332 	n = div & 0xffff;
333 	rate = parent_rate * m / n;
334 
335 	return rate;
336 }
337 
rk628_cru_clk_set_rate_rx_read(struct rk628 * rk628,unsigned long rate)338 static unsigned long rk628_cru_clk_set_rate_rx_read(struct rk628 *rk628,
339 						    unsigned long rate)
340 {
341 	unsigned long m, n, parent_rate;
342 	u32 val;
343 
344 	rk628_i2c_read(rk628, CRU_CLKSEL_CON02, &val);
345 	val &= CLK_RX_READ_SEL_MASK;
346 	val >>= CLK_RX_READ_SEL_SHIFT;
347 	if (val == CLK_RX_READ_SEL_GPLL)
348 		parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_GPLL);
349 	else
350 		parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_CPLL);
351 
352 	rational_best_approximation(rate, parent_rate,
353 				    GENMASK(15, 0), GENMASK(15, 0),
354 				    &m, &n);
355 	rk628_i2c_write(rk628, CRU_CLKSEL_CON14, m << 16 | n);
356 
357 	return rate;
358 }
359 
rk628_cru_clk_get_rate_uart_src(struct rk628 * rk628)360 static unsigned long rk628_cru_clk_get_rate_uart_src(struct rk628 *rk628)
361 {
362 	unsigned long rate, parent_rate;
363 	u32 mux, div;
364 
365 	rk628_i2c_read(rk628, CRU_CLKSEL_CON21, &mux);
366 	mux &= SCLK_VOP_SEL_MASK;
367 	if (mux == CLK_UART_SRC_SEL_GPLL)
368 		parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_GPLL);
369 	else
370 		parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_CPLL);
371 
372 	rk628_i2c_read(rk628, CRU_CLKSEL_CON21, &div);
373 	div &= CLK_UART_SRC_DIV_MASK;
374 	div >>= CLK_UART_SRC_DIV_SHIFT;
375 	rate = parent_rate / (div + 1);
376 
377 	return rate;
378 }
379 
rk628_cru_clk_set_rate_sclk_uart(struct rk628 * rk628,unsigned long rate)380 static unsigned long rk628_cru_clk_set_rate_sclk_uart(struct rk628 *rk628,
381 						      unsigned long rate)
382 {
383 	unsigned long m, n, parent_rate;
384 
385 	parent_rate = rk628_cru_clk_get_rate_uart_src(rk628);
386 
387 	if (rate == REFCLK_RATE) {
388 		rk628_i2c_write(rk628, CRU_CLKSEL_CON06,
389 				SCLK_UART_SEL(SCLK_UART_SEL_OSC));
390 		return rate;
391 	} else if (rate == parent_rate) {
392 		rk628_i2c_write(rk628, CRU_CLKSEL_CON06,
393 				SCLK_UART_SEL(SCLK_UART_SEL_UART_SRC));
394 		return rate;
395 	}
396 
397 	rk628_i2c_write(rk628, CRU_CLKSEL_CON06,
398 			SCLK_UART_SEL(SCLK_UART_SEL_UART_FRAC));
399 
400 	rational_best_approximation(rate, parent_rate,
401 				    GENMASK(15, 0), GENMASK(15, 0),
402 				    &m, &n);
403 	rk628_i2c_write(rk628, CRU_CLKSEL_CON20, m << 16 | n);
404 
405 	return rate;
406 }
407 
rk628_clk_mux_testout(struct rk628 * rk628,int id)408 void rk628_clk_mux_testout(struct rk628 *rk628, int id)
409 {
410 	switch (id) {
411 	case CGU_CLK_CPLL:
412 		rk628_i2c_write(rk628, CRU_CLKSEL_CON06, 0x000f0004);
413 		break;
414 	case CGU_CLK_GPLL:
415 		rk628_i2c_write(rk628, CRU_CLKSEL_CON06, 0x000f0002);
416 		break;
417 	case CGU_CLK_HDMIRX_AUD:
418 		rk628_i2c_write(rk628, CRU_CLKSEL_CON06, 0x000f000b);
419 		break;
420 	}
421 }
422 EXPORT_SYMBOL(rk628_clk_mux_testout);
423 
rk628_clk_set_rate(struct rk628 * rk628,unsigned int id,unsigned long rate)424 int rk628_clk_set_rate(struct rk628 *rk628, unsigned int id,
425 		       unsigned long rate)
426 {
427 	switch (id) {
428 	case CGU_CLK_CPLL:
429 	case CGU_CLK_GPLL:
430 		rk628_cru_clk_set_rate_pll(rk628, id, rate);
431 		break;
432 	case CGU_CLK_RX_READ:
433 		rk628_cru_clk_set_rate_rx_read(rk628, rate);
434 		break;
435 	case CGU_SCLK_VOP:
436 		rk628_cru_clk_set_rate_sclk_vop(rk628, rate);
437 		break;
438 	case CGU_SCLK_UART:
439 		rk628_cru_clk_set_rate_sclk_uart(rk628, rate);
440 		break;
441 	case CGU_CLK_HDMIRX_AUD:
442 		rk628_cru_clk_set_rate_sclk_hdmirx_aud(rk628, rate);
443 		break;
444 	default:
445 		return -1;
446 	}
447 
448 	return 0;
449 }
450 EXPORT_SYMBOL(rk628_clk_set_rate);
451 
rk628_clk_get_rate(struct rk628 * rk628,unsigned int id)452 unsigned long rk628_clk_get_rate(struct rk628 *rk628, unsigned int id)
453 {
454 	unsigned long rate;
455 
456 	switch (id) {
457 	case CGU_CLK_CPLL:
458 	case CGU_CLK_GPLL:
459 		rate = rk628_cru_clk_get_rate_pll(rk628, id);
460 		break;
461 	case CGU_SCLK_VOP:
462 		rate = rk628_cru_clk_get_rate_sclk_vop(rk628);
463 		break;
464 	case CGU_CLK_HDMIRX_AUD:
465 		rate = rk628_cru_clk_get_rate_sclk_hdmirx_aud(rk628);
466 		break;
467 	default:
468 		return 0;
469 	}
470 
471 	return rate;
472 }
473 EXPORT_SYMBOL(rk628_clk_get_rate);
474 
475 struct rk628_rgu_data {
476 	unsigned int id;
477 	unsigned int reg;
478 	unsigned int bit;
479 };
480 
481 #define RSTGEN(_id, _reg, _bit)	\
482 	{	\
483 		.id = (_id),	\
484 		.reg = (_reg),	\
485 		.bit = (_bit),	\
486 	}
487 
488 static const struct rk628_rgu_data rk628_rgu_data[] = {
489 	RSTGEN(RGU_LOGIC,	CRU_SOFTRST_CON00,  0),
490 	RSTGEN(RGU_CRU,		CRU_SOFTRST_CON00,  1),
491 	RSTGEN(RGU_REGFILE,	CRU_SOFTRST_CON00,  2),
492 	RSTGEN(RGU_I2C2APB,	CRU_SOFTRST_CON00,  3),
493 	RSTGEN(RGU_EFUSE,	CRU_SOFTRST_CON00,  5),
494 	RSTGEN(RGU_ADAPTER,	CRU_SOFTRST_CON00,  7),
495 	RSTGEN(RGU_CLK_RX,	CRU_SOFTRST_CON00, 11),
496 	RSTGEN(RGU_BT1120DEC,	CRU_SOFTRST_CON00, 12),
497 	RSTGEN(RGU_VOP,		CRU_SOFTRST_CON00, 13),
498 
499 	RSTGEN(RGU_GPIO0,	CRU_SOFTRST_CON01,  0),
500 	RSTGEN(RGU_GPIO1,	CRU_SOFTRST_CON01,  1),
501 	RSTGEN(RGU_GPIO2,	CRU_SOFTRST_CON01,  2),
502 	RSTGEN(RGU_GPIO3,	CRU_SOFTRST_CON01,  3),
503 	RSTGEN(RGU_GPIO_DB0,	CRU_SOFTRST_CON01,  4),
504 	RSTGEN(RGU_GPIO_DB1,	CRU_SOFTRST_CON01,  5),
505 	RSTGEN(RGU_GPIO_DB2,	CRU_SOFTRST_CON01,  6),
506 	RSTGEN(RGU_GPIO_DB3,	CRU_SOFTRST_CON01,  7),
507 
508 	RSTGEN(RGU_RXPHY,	CRU_SOFTRST_CON02,  0),
509 	RSTGEN(RGU_HDMIRX,	CRU_SOFTRST_CON02,  2),
510 	RSTGEN(RGU_TXPHY_CON,	CRU_SOFTRST_CON02,  3),
511 	RSTGEN(RGU_HDMITX,	CRU_SOFTRST_CON02,  4),
512 	RSTGEN(RGU_GVIHOST,	CRU_SOFTRST_CON02,  5),
513 	RSTGEN(RGU_DSI0,	CRU_SOFTRST_CON02,  6),
514 	RSTGEN(RGU_DSI1,	CRU_SOFTRST_CON02,  7),
515 	RSTGEN(RGU_CSI,		CRU_SOFTRST_CON02,  8),
516 	RSTGEN(RGU_TXDATA,	CRU_SOFTRST_CON02,  9),
517 	RSTGEN(RGU_DECODER,	CRU_SOFTRST_CON02, 10),
518 	RSTGEN(RGU_ENCODER,	CRU_SOFTRST_CON02, 11),
519 	RSTGEN(RGU_HDMIRX_PON,	CRU_SOFTRST_CON02, 12),
520 	RSTGEN(RGU_TXBYTEHS,	CRU_SOFTRST_CON02, 13),
521 	RSTGEN(RGU_TXESC,	CRU_SOFTRST_CON02, 14),
522 };
523 
rk628_rgu_update(struct rk628 * rk628,unsigned long id,int assert)524 static int rk628_rgu_update(struct rk628 *rk628, unsigned long id, int assert)
525 {
526 	const struct rk628_rgu_data *data = &rk628_rgu_data[id];
527 
528 	return rk628_i2c_write(rk628, data->reg,
529 			    BIT(data->bit + 16) | (assert << data->bit));
530 }
531 
rk628_control_assert(struct rk628 * rk628,unsigned long id)532 int rk628_control_assert(struct rk628 *rk628, unsigned long id)
533 {
534 	return rk628_rgu_update(rk628, id, 1);
535 }
536 EXPORT_SYMBOL(rk628_control_assert);
537 
rk628_control_deassert(struct rk628 * rk628,unsigned long id)538 int rk628_control_deassert(struct rk628 *rk628, unsigned long id)
539 {
540 	return rk628_rgu_update(rk628, id, 0);
541 }
542 EXPORT_SYMBOL(rk628_control_deassert);
543 
rk628_cru_initialize(struct rk628 * rk628)544 void rk628_cru_initialize(struct rk628 *rk628)
545 {
546 	u32 val;
547 	u8 mcu_mode;
548 
549 	rk628_i2c_read(rk628, GRF_SYSTEM_STATUS0, &val);
550 	mcu_mode = (val & I2C_ONLY_FLAG) ? 0 : 1;
551 	if (mcu_mode) {
552 		dev_info(rk628->dev, "RK628 MCU + I2C Mode\n");
553 		return;
554 	}
555 
556 	dev_info(rk628->dev, "RK628 I2C Mode Only\n");
557 	rk628_i2c_write(rk628, CRU_GPLL_CON0, 0xffff701d);
558 	mdelay(1);
559 	rk628_i2c_write(rk628, CRU_MODE_CON00, 0xffff0004);
560 	mdelay(1);
561 	rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff0080);
562 	rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff0083);
563 	rk628_i2c_write(rk628, CRU_CPLL_CON0, 0xffff3063);
564 	mdelay(1);
565 	rk628_i2c_write(rk628, CRU_MODE_CON00, 0xffff0005);
566 	rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff0003);
567 	rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff000b);
568 	rk628_i2c_write(rk628, CRU_GPLL_CON0, 0xffff1028);
569 	mdelay(1);
570 	rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff008b);
571 	rk628_i2c_write(rk628, CRU_CPLL_CON0, 0xffff1063);
572 	mdelay(1);
573 	rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff000b);
574 }
575 EXPORT_SYMBOL(rk628_cru_initialize);
576