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