1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2020 Rockchip Electronics Co. Ltd.
4 *
5 * Author: Wyon Bi <bivvy.bi@rock-chips.com>
6 */
7
8 #include "rk628.h"
9 #include "rk628_cru.h"
10
11 #define REFCLK_RATE 24000000UL
12 #define MIN_FREF_RATE 10000000UL
13 #define MAX_FREF_RATE 800000000UL
14 #define MIN_FREFDIV_RATE 1000000UL
15 #define MAX_FREFDIV_RATE 100000000UL
16 #define MIN_FVCO_RATE 600000000UL
17 #define MAX_FVCO_RATE 1600000000UL
18 #define MIN_FOUTPOSTDIV_RATE 12000000UL
19 #define MAX_FOUTPOSTDIV_RATE 1600000000UL
20
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)21 static void rational_best_approximation(unsigned long given_numerator,
22 unsigned long given_denominator,
23 unsigned long max_numerator,
24 unsigned long max_denominator,
25 unsigned long *best_numerator,
26 unsigned long *best_denominator)
27 {
28 unsigned long n, d, n0, d0, n1, d1;
29
30 n = given_numerator;
31 d = given_denominator;
32 n0 = d1 = 0;
33 n1 = d0 = 1;
34 for (;;) {
35 unsigned long t, a;
36
37 if ((n1 > max_numerator) || (d1 > max_denominator)) {
38 n1 = n0;
39 d1 = d0;
40 break;
41 }
42 if (d == 0)
43 break;
44 t = d;
45 a = n / d;
46 d = n % d;
47 n = t;
48 t = n0 + a * n1;
49 n0 = n1;
50 n1 = t;
51 t = d0 + a * d1;
52 d0 = d1;
53 d1 = t;
54 }
55 *best_numerator = n1;
56 *best_denominator = d1;
57 }
58
rk628_cru_clk_get_rate_pll(struct rk628 * rk628,unsigned int id)59 static unsigned long rk628_cru_clk_get_rate_pll(struct rk628 *rk628,
60 unsigned int id)
61 {
62 unsigned long parent_rate = REFCLK_RATE;
63 u32 postdiv1, fbdiv, dsmpd, postdiv2, refdiv, frac, bypass;
64 u32 con0, con1, con2;
65 u64 foutvco, foutpostdiv;
66 u32 offset, val;
67
68 rk628_i2c_read(rk628, CRU_MODE_CON00, &val);
69 if (id == CGU_CLK_CPLL) {
70 val &= CLK_CPLL_MODE_MASK;
71 val >>= CLK_CPLL_MODE_SHIFT;
72 if (val == CLK_CPLL_MODE_OSC)
73 return parent_rate;
74
75 offset = 0x00;
76 } else {
77 val &= CLK_GPLL_MODE_MASK;
78 val >>= CLK_GPLL_MODE_SHIFT;
79 if (val == CLK_GPLL_MODE_OSC)
80 return parent_rate;
81
82 offset = 0x20;
83 }
84
85 rk628_i2c_read(rk628, offset + CRU_CPLL_CON0, &con0);
86 rk628_i2c_read(rk628, offset + CRU_CPLL_CON1, &con1);
87 rk628_i2c_read(rk628, offset + CRU_CPLL_CON2, &con2);
88
89 bypass = (con0 & PLL_BYPASS_MASK) >> PLL_BYPASS_SHIFT;
90 postdiv1 = (con0 & PLL_POSTDIV1_MASK) >> PLL_POSTDIV1_SHIFT;
91 fbdiv = (con0 & PLL_FBDIV_MASK) >> PLL_FBDIV_SHIFT;
92 dsmpd = (con1 & PLL_DSMPD_MASK) >> PLL_DSMPD_SHIFT;
93 postdiv2 = (con1 & PLL_POSTDIV2_MASK) >> PLL_POSTDIV2_SHIFT;
94 refdiv = (con1 & PLL_REFDIV_MASK) >> PLL_REFDIV_SHIFT;
95 frac = (con2 & PLL_FRAC_MASK) >> PLL_FRAC_SHIFT;
96
97 if (bypass)
98 return parent_rate;
99
100 foutvco = parent_rate * fbdiv;
101 do_div(foutvco, refdiv);
102
103 if (!dsmpd) {
104 u64 frac_rate = (u64)parent_rate * frac;
105
106 do_div(frac_rate, refdiv);
107 foutvco += frac_rate >> 24;
108 }
109
110 foutpostdiv = foutvco;
111 do_div(foutpostdiv, postdiv1);
112 do_div(foutpostdiv, postdiv2);
113
114 return foutpostdiv;
115 }
116
rk628_cru_clk_set_rate_pll(struct rk628 * rk628,unsigned int id,unsigned long rate)117 static unsigned long rk628_cru_clk_set_rate_pll(struct rk628 *rk628,
118 unsigned int id,
119 unsigned long rate)
120 {
121 unsigned long fin = REFCLK_RATE, fout = rate;
122 u8 min_refdiv, max_refdiv, postdiv;
123 u8 dsmpd = 1, postdiv1 = 0, postdiv2 = 0, refdiv = 0;
124 u16 fbdiv = 0;
125 u32 frac = 0;
126 u64 foutvco, foutpostdiv;
127 u32 offset, val;
128
129 /*
130 * FREF : 10MHz ~ 800MHz
131 * FREFDIV : 1MHz ~ 40MHz
132 * FOUTVCO : 400MHz ~ 1.6GHz
133 * FOUTPOSTDIV : 8MHz ~ 1.6GHz
134 */
135 if (fin < MIN_FREF_RATE || fin > MAX_FREF_RATE)
136 return 0;
137
138 if (fout < MIN_FOUTPOSTDIV_RATE || fout > MAX_FOUTPOSTDIV_RATE)
139 return 0;
140
141 if (id == CGU_CLK_CPLL)
142 offset = 0x00;
143 else
144 offset = 0x20;
145
146 rk628_i2c_write(rk628, offset + CRU_CPLL_CON1, PLL_PD(1));
147
148 if (fin == fout) {
149 rk628_i2c_write(rk628, offset + CRU_CPLL_CON0, PLL_BYPASS(1));
150 rk628_i2c_write(rk628, offset + CRU_CPLL_CON1, PLL_PD(0));
151 while (1) {
152 rk628_i2c_read(rk628, offset + CRU_CPLL_CON1, &val);
153 if (val & PLL_LOCK)
154 break;
155 }
156 return fin;
157 }
158
159 min_refdiv = fin / MAX_FREFDIV_RATE + 1;
160 max_refdiv = fin / MIN_FREFDIV_RATE;
161 if (max_refdiv > 64)
162 max_refdiv = 64;
163
164 if (fout < MIN_FVCO_RATE) {
165 postdiv = MIN_FVCO_RATE / fout + 1;
166
167 for (postdiv2 = 1; postdiv2 < 8; postdiv2++) {
168 if (postdiv % postdiv2)
169 continue;
170
171 postdiv1 = postdiv / postdiv2;
172
173 if (postdiv1 > 0 && postdiv1 < 8)
174 break;
175 }
176
177 if (postdiv2 > 7)
178 return 0;
179
180 fout *= postdiv1 * postdiv2;
181 } else {
182 postdiv1 = 1;
183 postdiv2 = 1;
184 }
185
186 for (refdiv = min_refdiv; refdiv <= max_refdiv; refdiv++) {
187 u64 tmp, frac_rate;
188
189 if (fin % refdiv)
190 continue;
191
192 tmp = (u64)fout * refdiv;
193 do_div(tmp, fin);
194 fbdiv = tmp;
195 if (fbdiv < 10 || fbdiv > 1600)
196 continue;
197
198 tmp = (u64)fbdiv * fin;
199 do_div(tmp, refdiv);
200 if (fout < MIN_FVCO_RATE || fout > MAX_FVCO_RATE)
201 continue;
202
203 frac_rate = fout - tmp;
204
205 if (frac_rate) {
206 tmp = (u64)frac_rate * refdiv;
207 tmp <<= 24;
208 do_div(tmp, fin);
209 frac = tmp;
210 dsmpd = 0;
211 }
212
213 break;
214 }
215
216 /*
217 * If DSMPD = 1 (DSM is disabled, "integer mode")
218 * FOUTVCO = FREF / REFDIV * FBDIV
219 * FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2
220 *
221 * If DSMPD = 0 (DSM is enabled, "fractional mode")
222 * FOUTVCO = FREF / REFDIV * (FBDIV + FRAC / 2^24)
223 * FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2
224 */
225 foutvco = fin * fbdiv;
226 do_div(foutvco, refdiv);
227
228 if (!dsmpd) {
229 u64 frac_rate = (u64)fin * frac;
230
231 do_div(frac_rate, refdiv);
232 foutvco += frac_rate >> 24;
233 }
234
235 foutpostdiv = foutvco;
236 do_div(foutpostdiv, postdiv1);
237 do_div(foutpostdiv, postdiv2);
238
239 rk628_i2c_write(rk628, offset + CRU_CPLL_CON0,
240 PLL_BYPASS(0) | PLL_POSTDIV1(postdiv1) |
241 PLL_FBDIV(fbdiv));
242 rk628_i2c_write(rk628, offset + CRU_CPLL_CON1,
243 PLL_DSMPD(dsmpd) | PLL_POSTDIV2(postdiv2) |
244 PLL_REFDIV(refdiv));
245 rk628_i2c_write(rk628, offset + CRU_CPLL_CON2, PLL_FRAC(frac));
246
247 rk628_i2c_write(rk628, offset + CRU_CPLL_CON1, PLL_PD(0));
248 while (1) {
249 rk628_i2c_read(rk628, offset + CRU_CPLL_CON1, &val);
250 if (val & PLL_LOCK)
251 break;
252 }
253
254 return (unsigned long)foutpostdiv;
255 }
256
rk628_cru_clk_set_rate_sclk_vop(struct rk628 * rk628,unsigned long rate)257 static unsigned long rk628_cru_clk_set_rate_sclk_vop(struct rk628 *rk628,
258 unsigned long rate)
259 {
260 unsigned long m, n, parent_rate;
261 u32 val;
262
263 rk628_i2c_read(rk628, CRU_CLKSEL_CON02, &val);
264 val &= SCLK_VOP_SEL_MASK;
265 val >>= SCLK_VOP_SEL_SHIFT;
266 if (val == SCLK_VOP_SEL_GPLL)
267 parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_GPLL);
268 else
269 parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_CPLL);
270
271 rational_best_approximation(rate, parent_rate,
272 GENMASK(15, 0), GENMASK(15, 0),
273 &m, &n);
274 rk628_i2c_write(rk628, CRU_CLKSEL_CON13, m << 16 | n);
275
276 return rate;
277 }
278
rk628_cru_clk_get_rate_sclk_vop(struct rk628 * rk628)279 static unsigned long rk628_cru_clk_get_rate_sclk_vop(struct rk628 *rk628)
280 {
281 unsigned long rate, parent_rate, m, n;
282 u32 mux, div;
283
284 rk628_i2c_read(rk628, CRU_CLKSEL_CON02, &mux);
285 mux &= CLK_UART_SRC_SEL_MASK;
286 mux >>= SCLK_VOP_SEL_SHIFT;
287 if (mux == SCLK_VOP_SEL_GPLL)
288 parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_GPLL);
289 else
290 parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_CPLL);
291
292 rk628_i2c_read(rk628, CRU_CLKSEL_CON13, &div);
293 m = div >> 16 & 0xffff;
294 n = div & 0xffff;
295 rate = parent_rate * m / n;
296
297 return rate;
298 }
299
rk628_cru_clk_set_rate_rx_read(struct rk628 * rk628,unsigned long rate)300 static unsigned long rk628_cru_clk_set_rate_rx_read(struct rk628 *rk628,
301 unsigned long rate)
302 {
303 unsigned long m, n, parent_rate;
304 u32 val;
305
306 rk628_i2c_read(rk628, CRU_CLKSEL_CON02, &val);
307 val &= CLK_RX_READ_SEL_MASK;
308 val >>= CLK_RX_READ_SEL_SHIFT;
309 if (val == CLK_RX_READ_SEL_GPLL)
310 parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_GPLL);
311 else
312 parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_CPLL);
313
314 rational_best_approximation(rate, parent_rate,
315 GENMASK(15, 0), GENMASK(15, 0),
316 &m, &n);
317 rk628_i2c_write(rk628, CRU_CLKSEL_CON14, m << 16 | n);
318
319 return rate;
320 }
321
rk628_cru_clk_get_rate_uart_src(struct rk628 * rk628)322 static unsigned long rk628_cru_clk_get_rate_uart_src(struct rk628 *rk628)
323 {
324 unsigned long rate, parent_rate;
325 u32 mux, div;
326
327 rk628_i2c_read(rk628, CRU_CLKSEL_CON21, &mux);
328 mux &= SCLK_VOP_SEL_MASK;
329 if (mux == CLK_UART_SRC_SEL_GPLL)
330 parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_GPLL);
331 else
332 parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_CPLL);
333
334 rk628_i2c_read(rk628, CRU_CLKSEL_CON21, &div);
335 div &= CLK_UART_SRC_DIV_MASK;
336 div >>= CLK_UART_SRC_DIV_SHIFT;
337 rate = parent_rate / (div + 1);
338
339 return rate;
340 }
341
rk628_cru_clk_set_rate_sclk_uart(struct rk628 * rk628,unsigned long rate)342 static unsigned long rk628_cru_clk_set_rate_sclk_uart(struct rk628 *rk628,
343 unsigned long rate)
344 {
345 unsigned long m, n, parent_rate;
346
347 parent_rate = rk628_cru_clk_get_rate_uart_src(rk628);
348
349 if (rate == REFCLK_RATE) {
350 rk628_i2c_write(rk628, CRU_CLKSEL_CON06,
351 SCLK_UART_SEL(SCLK_UART_SEL_OSC));
352 return rate;
353 } else if (rate == parent_rate) {
354 rk628_i2c_write(rk628, CRU_CLKSEL_CON06,
355 SCLK_UART_SEL(SCLK_UART_SEL_UART_SRC));
356 return rate;
357 }
358
359 rk628_i2c_write(rk628, CRU_CLKSEL_CON06,
360 SCLK_UART_SEL(SCLK_UART_SEL_UART_FRAC));
361
362 rational_best_approximation(rate, parent_rate,
363 GENMASK(15, 0), GENMASK(15, 0),
364 &m, &n);
365 rk628_i2c_write(rk628, CRU_CLKSEL_CON20, m << 16 | n);
366
367 return rate;
368 }
369
370 static unsigned long
rk628_cru_clk_get_rate_bt1120_dec_parent(struct rk628 * rk628)371 rk628_cru_clk_get_rate_bt1120_dec_parent(struct rk628 *rk628)
372 {
373 unsigned long parent_rate;
374 u32 mux;
375
376 rk628_i2c_read(rk628, CRU_CLKSEL_CON02, &mux);
377 mux &= CLK_BT1120DEC_SEL_MASK;
378 if (mux == CLK_BT1120DEC_SEL_GPLL)
379 parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_GPLL);
380 else
381 parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_CPLL);
382
383 return parent_rate;
384 }
385
rk628_cru_clk_set_rate_bt1120_dec(struct rk628 * rk628,unsigned long rate)386 static unsigned long rk628_cru_clk_set_rate_bt1120_dec(struct rk628 *rk628,
387 unsigned long rate)
388 {
389 unsigned long parent_rate;
390 u32 div;
391
392 parent_rate = rk628_cru_clk_get_rate_bt1120_dec_parent(rk628);
393 div = DIV_ROUND_UP(parent_rate, rate);
394 rk628_i2c_write(rk628, CRU_CLKSEL_CON02, CLK_BT1120DEC_DIV(div-1));
395
396 return parent_rate / div;
397 }
398
rk628_cru_clk_set_rate(struct rk628 * rk628,unsigned int id,unsigned long rate)399 int rk628_cru_clk_set_rate(struct rk628 *rk628, unsigned int id,
400 unsigned long rate)
401 {
402 switch (id) {
403 case CGU_CLK_CPLL:
404 case CGU_CLK_GPLL:
405 rk628_cru_clk_set_rate_pll(rk628, id, rate);
406 break;
407 case CGU_CLK_RX_READ:
408 rk628_cru_clk_set_rate_rx_read(rk628, rate);
409 break;
410 case CGU_SCLK_VOP:
411 rk628_cru_clk_set_rate_sclk_vop(rk628, rate);
412 break;
413 case CGU_SCLK_UART:
414 rk628_cru_clk_set_rate_sclk_uart(rk628, rate);
415 break;
416 case CGU_BT1120DEC:
417 rk628_cru_clk_set_rate_bt1120_dec(rk628, rate);
418 break;
419 default:
420 return -1;
421 }
422
423 return 0;
424 }
425
rk628_cru_clk_get_rate(struct rk628 * rk628,unsigned int id)426 unsigned long rk628_cru_clk_get_rate(struct rk628 *rk628, unsigned int id)
427 {
428 unsigned long rate;
429
430 switch (id) {
431 case CGU_CLK_CPLL:
432 case CGU_CLK_GPLL:
433 rate = rk628_cru_clk_get_rate_pll(rk628, id);
434 break;
435 case CGU_SCLK_VOP:
436 rate = rk628_cru_clk_get_rate_sclk_vop(rk628);
437 break;
438 default:
439 return 0;
440 }
441
442 return rate;
443 }
444
rk628_cru_init(struct rk628 * rk628)445 void rk628_cru_init(struct rk628 *rk628)
446 {
447 u32 val;
448 u8 mcu_mode;
449
450 rk628_i2c_read(rk628, GRF_SYSTEM_STATUS0, &val);
451 mcu_mode = (val & I2C_ONLY_FLAG) ? 0 : 1;
452 if (mcu_mode)
453 return;
454
455 rk628_i2c_write(rk628, CRU_GPLL_CON0, 0xffff701d);
456 mdelay(1);
457 rk628_i2c_write(rk628, CRU_MODE_CON00, 0xffff0004);
458 mdelay(1);
459 rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff0080);
460 rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff0083);
461 rk628_i2c_write(rk628, CRU_CPLL_CON0, 0xffff3063);
462 mdelay(1);
463 rk628_i2c_write(rk628, CRU_MODE_CON00, 0xffff0005);
464 rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff0003);
465 rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff000b);
466 rk628_i2c_write(rk628, CRU_GPLL_CON0, 0xffff1028);
467 mdelay(1);
468 rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff008b);
469 rk628_i2c_write(rk628, CRU_CPLL_CON0, 0xffff1063);
470 mdelay(1);
471 rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff000b);
472 }
473