1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2014 MundoReader S.L.
4 * Author: Heiko Stuebner <heiko@sntech.de>
5 *
6 * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
7 * Author: Xing Zheng <zhengxing@rock-chips.com>
8 */
9
10 #include <asm/div64.h>
11 #include <linux/slab.h>
12 #include <linux/io.h>
13 #include <linux/delay.h>
14 #include <linux/clk-provider.h>
15 #include <linux/iopoll.h>
16 #include <linux/regmap.h>
17 #include <linux/clk.h>
18 #include <linux/gcd.h>
19 #include <linux/clk/rockchip.h>
20 #include <linux/mfd/syscon.h>
21 #include "clk.h"
22
23 #define PLL_MODE_MASK 0x3
24 #define PLL_MODE_SLOW 0x0
25 #define PLL_MODE_NORM 0x1
26 #define PLL_MODE_DEEP 0x2
27 #define PLL_RK3328_MODE_MASK 0x1
28
29 #define BOOTST_FILE_READ 0444
30
31 struct rockchip_clk_pll {
32 struct clk_hw hw;
33
34 struct clk_mux pll_mux;
35 const struct clk_ops *pll_mux_ops;
36
37 struct notifier_block clk_nb;
38
39 void __iomem *reg_base;
40 int lock_offset;
41 unsigned int lock_shift;
42 enum rockchip_pll_type type;
43 u8 flags;
44 const struct rockchip_pll_rate_table *rate_table;
45 unsigned int rate_count;
46 int sel;
47 unsigned long scaling;
48 spinlock_t *lock;
49
50 struct rockchip_clk_provider *ctx;
51
52 bool boost_enabled;
53 u32 boost_backup_pll_usage;
54 unsigned long boost_backup_pll_rate;
55 unsigned long boost_low_rate;
56 unsigned long boost_high_rate;
57 struct regmap *boost;
58 #ifdef CONFIG_DEBUG_FS
59 struct hlist_node debug_node;
60 #endif
61 };
62
63 #define to_rockchip_clk_pll(_hw) container_of(_hw, struct rockchip_clk_pll, hw)
64 #define to_rockchip_clk_pll_nb(nb) container_of(nb, struct rockchip_clk_pll, clk_nb)
65
66 static void rockchip_boost_disable_low(struct rockchip_clk_pll *pll);
67
68 #define MHZ (1000UL * 1000UL)
69 #define KHZ (1000UL)
70
71 /* CLK_PLL_TYPE_RK3066_AUTO type ops */
72 #define PLL_FREF_MIN (269 * KHZ)
73 #define PLL_FREF_MAX (2200 * MHZ)
74
75 #define PLL_FVCO_MIN (440 * MHZ)
76 #define PLL_FVCO_MAX (2200 * MHZ)
77
78 #define PLL_FOUT_MIN (27500 * KHZ)
79 #define PLL_FOUT_MAX (2200 * MHZ)
80
81 #define PLL_NF_MAX (4096)
82 #define PLL_NR_MAX (64)
83 #define PLL_NO_MAX (16)
84
85 /* CLK_PLL_TYPE_RK3036/3366/3399_AUTO type ops */
86 #define MIN_FOUTVCO_FREQ (800 * MHZ)
87 #define MAX_FOUTVCO_FREQ (2000 * MHZ)
88
89 static struct rockchip_pll_rate_table auto_table;
90 #ifdef CONFIG_DEBUG_FS
91 static HLIST_HEAD(clk_boost_list);
92 static DEFINE_MUTEX(clk_boost_lock);
93 #endif
94
rockchip_pll_clk_adaptive_scaling(struct clk * clk,int sel)95 int rockchip_pll_clk_adaptive_scaling(struct clk *clk, int sel)
96 {
97 struct clk *parent = clk_get_parent(clk);
98 struct rockchip_clk_pll *pll;
99
100 if (IS_ERR_OR_NULL(parent)) {
101 return -EINVAL;
102 }
103
104 pll = to_rockchip_clk_pll(__clk_get_hw(parent));
105 if (!pll) {
106 return -EINVAL;
107 }
108
109 pll->sel = sel;
110
111 return 0;
112 }
113 EXPORT_SYMBOL(rockchip_pll_clk_adaptive_scaling);
114
rockchip_pll_clk_rate_to_scale(struct clk * clk,unsigned long rate)115 int rockchip_pll_clk_rate_to_scale(struct clk *clk, unsigned long rate)
116 {
117 const struct rockchip_pll_rate_table *rate_table;
118 struct clk *parent = clk_get_parent(clk);
119 struct rockchip_clk_pll *pll;
120 unsigned int i;
121
122 if (IS_ERR_OR_NULL(parent)) {
123 return -EINVAL;
124 }
125
126 pll = to_rockchip_clk_pll(__clk_get_hw(parent));
127 if (!pll) {
128 return -EINVAL;
129 }
130
131 rate_table = pll->rate_table;
132 for (i = 0; i < pll->rate_count; i++) {
133 if (rate >= rate_table[i].rate) {
134 return i;
135 }
136 }
137
138 return -EINVAL;
139 }
140 EXPORT_SYMBOL(rockchip_pll_clk_rate_to_scale);
141
rockchip_pll_clk_scale_to_rate(struct clk * clk,unsigned int scale)142 int rockchip_pll_clk_scale_to_rate(struct clk *clk, unsigned int scale)
143 {
144 const struct rockchip_pll_rate_table *rate_table;
145 struct clk *parent = clk_get_parent(clk);
146 struct rockchip_clk_pll *pll;
147 unsigned int i;
148
149 if (IS_ERR_OR_NULL(parent)) {
150 return -EINVAL;
151 }
152
153 pll = to_rockchip_clk_pll(__clk_get_hw(parent));
154 if (!pll) {
155 return -EINVAL;
156 }
157
158 rate_table = pll->rate_table;
159 for (i = 0; i < pll->rate_count; i++) {
160 if (i == scale) {
161 return rate_table[i].rate;
162 }
163 }
164
165 return -EINVAL;
166 }
167 EXPORT_SYMBOL(rockchip_pll_clk_scale_to_rate);
168
rk_pll_rate_table_get(void)169 static struct rockchip_pll_rate_table *rk_pll_rate_table_get(void)
170 {
171 return &auto_table;
172 }
173
rockchip_pll_clk_set_postdiv(unsigned long fout_hz,u32 * postdiv1,u32 * postdiv2,u32 * foutvco)174 static int rockchip_pll_clk_set_postdiv(unsigned long fout_hz, u32 *postdiv1, u32 *postdiv2, u32 *foutvco)
175 {
176 unsigned long freq;
177
178 if (fout_hz < MIN_FOUTVCO_FREQ) {
179 for (*postdiv1 = 1; *postdiv1 <= 0x7; (*postdiv1)++) {
180 for (*postdiv2 = 1; *postdiv2 <= 0x7; (*postdiv2)++) {
181 freq = fout_hz * (*postdiv1) * (*postdiv2);
182 if (freq >= MIN_FOUTVCO_FREQ && freq <= MAX_FOUTVCO_FREQ) {
183 *foutvco = freq;
184 return 0;
185 }
186 }
187 }
188 pr_err("CANNOT FIND postdiv1/2 to make fout in range from 800M to 2000M,fout = %lu\n", fout_hz);
189 } else {
190 *postdiv1 = 1;
191 *postdiv2 = 1;
192 }
193 return 0;
194 }
195
rockchip_pll_clk_set_by_auto(struct rockchip_clk_pll * pll,unsigned long fin_hz,unsigned long fout_hz)196 static struct rockchip_pll_rate_table *rockchip_pll_clk_set_by_auto(struct rockchip_clk_pll *pll, unsigned long fin_hz,
197 unsigned long fout_hz)
198 {
199 struct rockchip_pll_rate_table *rate_table = rk_pll_rate_table_get();
200 /* set postdiv1/2 always 1 */
201 u32 foutvco = fout_hz;
202 u64 fin_64, frac_64;
203 u32 f_frac, postdiv1, postdiv2;
204 unsigned long clk_gcd = 0;
205
206 if (fin_hz == 0 || fout_hz == 0 || fout_hz == fin_hz) {
207 return NULL;
208 }
209
210 rockchip_pll_clk_set_postdiv(fout_hz, &postdiv1, &postdiv2, &foutvco);
211 rate_table->postdiv1 = postdiv1;
212 rate_table->postdiv2 = postdiv2;
213 rate_table->dsmpd = 1;
214
215 if (fin_hz / MHZ * MHZ == fin_hz && fout_hz / MHZ * MHZ == fout_hz) {
216 fin_hz /= MHZ;
217 foutvco /= MHZ;
218 clk_gcd = gcd(fin_hz, foutvco);
219 if (clk_gcd == 0) {
220 return -1;
221 }
222 rate_table->refdiv = fin_hz / clk_gcd;
223 rate_table->fbdiv = foutvco / clk_gcd;
224
225 rate_table->frac = 0;
226
227 pr_debug(
228 "fin = %lu, fout = %lu, clk_gcd = %lu, refdiv = %u, fbdiv = %u, postdiv1 = %u, postdiv2 = %u, frac = %u\n",
229 fin_hz, fout_hz, clk_gcd, rate_table->refdiv, rate_table->fbdiv, rate_table->postdiv1, rate_table->postdiv2,
230 rate_table->frac);
231 } else {
232 pr_debug("frac div running, fin_hz = %lu, fout_hz = %lu, fin_INT_mhz = %lu, fout_INT_mhz = %lu\n", fin_hz,
233 fout_hz, fin_hz / MHZ * MHZ, fout_hz / MHZ * MHZ);
234 pr_debug("frac get postdiv1 = %u, postdiv2 = %u, foutvco = %u\n", rate_table->postdiv1, rate_table->postdiv2,
235 foutvco);
236 clk_gcd = gcd(fin_hz / MHZ, foutvco / MHZ);
237 rate_table->refdiv = fin_hz / MHZ / clk_gcd;
238 rate_table->fbdiv = foutvco / MHZ / clk_gcd;
239 pr_debug("frac get refdiv = %u, fbdiv = %u\n", rate_table->refdiv, rate_table->fbdiv);
240
241 rate_table->frac = 0;
242
243 f_frac = (foutvco % MHZ);
244 fin_64 = fin_hz;
245 do_div(fin_64, (u64)rate_table->refdiv);
246 frac_64 = (u64)f_frac << 0x18;
247 do_div(frac_64, fin_64);
248 rate_table->frac = (u32)frac_64;
249 if (rate_table->frac > 0) {
250 rate_table->dsmpd = 0;
251 }
252 pr_debug("frac = %x\n", rate_table->frac);
253 }
254 return rate_table;
255 }
256
rockchip_rk3066_pll_clk_set_by_auto(struct rockchip_clk_pll * pll,unsigned long fin_hz,unsigned long fout_hz)257 static struct rockchip_pll_rate_table *rockchip_rk3066_pll_clk_set_by_auto(struct rockchip_clk_pll *pll,
258 unsigned long fin_hz, unsigned long fout_hz)
259 {
260 struct rockchip_pll_rate_table *rate_table = rk_pll_rate_table_get();
261 u32 nr, nf, no, nonr;
262 u32 nr_out, nf_out, no_out;
263 u32 n;
264 u32 numerator, denominator;
265 u64 fref, fvco, fout;
266 unsigned long clk_gcd = 0;
267
268 nr_out = PLL_NR_MAX + 1;
269 no_out = 0;
270 nf_out = 0;
271
272 if (fin_hz == 0 || fout_hz == 0 || fout_hz == fin_hz) {
273 return NULL;
274 }
275
276 clk_gcd = gcd(fin_hz, fout_hz);
277 if (clk_gcd == 0) {
278 return NULL;
279 }
280 numerator = fout_hz / clk_gcd;
281 denominator = fin_hz / clk_gcd;
282
283 for (n = 1;; n++) {
284 nf = numerator * n;
285 nonr = denominator * n;
286 if (nf > PLL_NF_MAX || nonr > (PLL_NO_MAX * PLL_NR_MAX)) {
287 break;
288 }
289
290 for (no = 1; no <= PLL_NO_MAX; no++) {
291 if (!(no == 1 || !(no % 0x2))) {
292 continue;
293 }
294
295 if (nonr % no) {
296 continue;
297 }
298 nr = nonr / no;
299
300 if (nr > PLL_NR_MAX) {
301 continue;
302 }
303
304 fref = fin_hz / nr;
305 if (fref < PLL_FREF_MIN || fref > PLL_FREF_MAX) {
306 continue;
307 }
308
309 fvco = fref * nf;
310 if (fvco < PLL_FVCO_MIN || fvco > PLL_FVCO_MAX) {
311 continue;
312 }
313
314 fout = fvco / no;
315 if (fout < PLL_FOUT_MIN || fout > PLL_FOUT_MAX) {
316 continue;
317 }
318
319 /* select the best from all available PLL settings */
320 if ((no > no_out) || ((no == no_out) && (nr < nr_out))) {
321 nr_out = nr;
322 nf_out = nf;
323 no_out = no;
324 }
325 }
326 }
327
328 /* output the best PLL setting */
329 if ((nr_out <= PLL_NR_MAX) && (no_out > 0)) {
330 rate_table->nr = nr_out;
331 rate_table->nf = nf_out;
332 rate_table->no = no_out;
333 } else {
334 return NULL;
335 }
336
337 return rate_table;
338 }
339
rockchip_get_pll_settings(struct rockchip_clk_pll * pll,unsigned long rate)340 static const struct rockchip_pll_rate_table *rockchip_get_pll_settings(struct rockchip_clk_pll *pll, unsigned long rate)
341 {
342 const struct rockchip_pll_rate_table *rate_table = pll->rate_table;
343 int i;
344
345 for (i = 0; i < pll->rate_count; i++) {
346 if (rate == rate_table[i].rate) {
347 if (i < pll->sel) {
348 pll->scaling = rate;
349 return &rate_table[pll->sel];
350 }
351 pll->scaling = 0;
352 return &rate_table[i];
353 }
354 }
355 pll->scaling = 0;
356
357 if (pll->type == pll_rk3066) {
358 return rockchip_rk3066_pll_clk_set_by_auto(pll, 0x18 * MHZ, rate);
359 } else {
360 return rockchip_pll_clk_set_by_auto(pll, 0x18 * MHZ, rate);
361 }
362 }
363
rockchip_pll_round_rate(struct clk_hw * hw,unsigned long drate,unsigned long * prate)364 static long rockchip_pll_round_rate(struct clk_hw *hw, unsigned long drate, unsigned long *prate)
365 {
366 return drate;
367 }
368
369 /*
370 * Wait for the pll to reach the locked state.
371 * The calling set_rate function is responsible for making sure the
372 * grf regmap is available.
373 */
rockchip_pll_wait_lock(struct rockchip_clk_pll * pll)374 static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll)
375 {
376 struct regmap *grf = pll->ctx->grf;
377 unsigned int val;
378 int ret;
379
380 ret = regmap_read_poll_timeout(grf, pll->lock_offset, val, val & BIT(pll->lock_shift), 0, 0x3e8);
381 if (ret) {
382 pr_err("%s: timeout waiting for pll to lock\n", __func__);
383 }
384
385 return ret;
386 }
387
388 /**
389 * PLL used in RK3036
390 */
391
392 #define RK3036_PLLCON(i) ((i)*0x4)
393 #define RK3036_PLLCON0_FBDIV_MASK 0xfff
394 #define RK3036_PLLCON0_FBDIV_SHIFT 0
395 #define RK3036_PLLCON0_POSTDIV1_MASK 0x7
396 #define RK3036_PLLCON0_POSTDIV1_SHIFT 12
397 #define RK3036_PLLCON1_REFDIV_MASK 0x3f
398 #define RK3036_PLLCON1_REFDIV_SHIFT 0
399 #define RK3036_PLLCON1_POSTDIV2_MASK 0x7
400 #define RK3036_PLLCON1_POSTDIV2_SHIFT 6
401 #define RK3036_PLLCON1_LOCK_STATUS BIT(10)
402 #define RK3036_PLLCON1_DSMPD_MASK 0x1
403 #define RK3036_PLLCON1_DSMPD_SHIFT 12
404 #define RK3036_PLLCON1_PWRDOWN BIT(13)
405 #define RK3036_PLLCON2_FRAC_MASK 0xffffff
406 #define RK3036_PLLCON2_FRAC_SHIFT 0
407
rockchip_rk3036_pll_wait_lock(struct rockchip_clk_pll * pll)408 static int rockchip_rk3036_pll_wait_lock(struct rockchip_clk_pll *pll)
409 {
410 u32 pllcon;
411 int ret;
412
413 /*
414 * Lock time typical 250, max 500 input clock cycles @24MHz
415 * So define a very safe maximum of 1000us, meaning 24000 cycles.
416 */
417 ret = readl_relaxed_poll_timeout(pll->reg_base + RK3036_PLLCON(1), pllcon, pllcon & RK3036_PLLCON1_LOCK_STATUS, 0,
418 0x3e8);
419 if (ret) {
420 pr_err("%s: timeout waiting for pll to lock\n", __func__);
421 }
422
423 return ret;
424 }
425
rockchip_rk3036_pll_con_to_rate(struct rockchip_clk_pll * pll,u32 con0,u32 con1)426 static unsigned long rockchip_rk3036_pll_con_to_rate(struct rockchip_clk_pll *pll, u32 con0, u32 con1)
427 {
428 unsigned int fbdiv, postdiv1, refdiv, postdiv2;
429 u64 rate64 = 24000000;
430
431 fbdiv = ((con0 >> RK3036_PLLCON0_FBDIV_SHIFT) & RK3036_PLLCON0_FBDIV_MASK);
432 postdiv1 = ((con0 >> RK3036_PLLCON0_POSTDIV1_SHIFT) & RK3036_PLLCON0_POSTDIV1_MASK);
433 refdiv = ((con1 >> RK3036_PLLCON1_REFDIV_SHIFT) & RK3036_PLLCON1_REFDIV_MASK);
434 postdiv2 = ((con1 >> RK3036_PLLCON1_POSTDIV2_SHIFT) & RK3036_PLLCON1_POSTDIV2_MASK);
435
436 rate64 *= fbdiv;
437 do_div(rate64, refdiv);
438 do_div(rate64, postdiv1);
439 do_div(rate64, postdiv2);
440
441 return (unsigned long)rate64;
442 }
443
rockchip_rk3036_pll_get_params(struct rockchip_clk_pll * pll,struct rockchip_pll_rate_table * rate)444 static void rockchip_rk3036_pll_get_params(struct rockchip_clk_pll *pll, struct rockchip_pll_rate_table *rate)
445 {
446 u32 pllcon;
447
448 pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(0));
449 rate->fbdiv = ((pllcon >> RK3036_PLLCON0_FBDIV_SHIFT) & RK3036_PLLCON0_FBDIV_MASK);
450 rate->postdiv1 = ((pllcon >> RK3036_PLLCON0_POSTDIV1_SHIFT) & RK3036_PLLCON0_POSTDIV1_MASK);
451
452 pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(1));
453 rate->refdiv = ((pllcon >> RK3036_PLLCON1_REFDIV_SHIFT) & RK3036_PLLCON1_REFDIV_MASK);
454 rate->postdiv2 = ((pllcon >> RK3036_PLLCON1_POSTDIV2_SHIFT) & RK3036_PLLCON1_POSTDIV2_MASK);
455 rate->dsmpd = ((pllcon >> RK3036_PLLCON1_DSMPD_SHIFT) & RK3036_PLLCON1_DSMPD_MASK);
456
457 pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(2));
458 rate->frac = ((pllcon >> RK3036_PLLCON2_FRAC_SHIFT) & RK3036_PLLCON2_FRAC_MASK);
459 }
460
rockchip_rk3036_pll_recalc_rate(struct clk_hw * hw,unsigned long prate)461 static unsigned long rockchip_rk3036_pll_recalc_rate(struct clk_hw *hw, unsigned long prate)
462 {
463 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
464 struct rockchip_pll_rate_table cur;
465 u64 rate64 = prate, frac_rate64 = prate;
466
467 if (pll->sel && pll->scaling) {
468 return pll->scaling;
469 }
470
471 rockchip_rk3036_pll_get_params(pll, &cur);
472
473 rate64 *= cur.fbdiv;
474 do_div(rate64, cur.refdiv);
475
476 if (cur.dsmpd == 0) {
477 /* fractional mode */
478 frac_rate64 *= cur.frac;
479
480 do_div(frac_rate64, cur.refdiv);
481 rate64 += frac_rate64 >> 0x18;
482 }
483
484 do_div(rate64, cur.postdiv1);
485 do_div(rate64, cur.postdiv2);
486
487 return (unsigned long)rate64;
488 }
489
rockchip_rk3036_pll_set_params(struct rockchip_clk_pll * pll,const struct rockchip_pll_rate_table * rate)490 static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll, const struct rockchip_pll_rate_table *rate)
491 {
492 const struct clk_ops *pll_mux_ops = pll->pll_mux_ops;
493 struct clk_mux *pll_mux = &pll->pll_mux;
494 struct rockchip_pll_rate_table cur;
495 u32 pllcon;
496 int rate_change_remuxed = 0;
497 int cur_parent;
498 int ret;
499
500 pr_debug("%s: rate settings for %lu fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",
501 __func__, rate->rate, rate->fbdiv, rate->postdiv1, rate->refdiv, rate->postdiv2, rate->dsmpd, rate->frac);
502
503 rockchip_rk3036_pll_get_params(pll, &cur);
504 cur.rate = 0;
505
506 cur_parent = pll_mux_ops->get_parent(&pll_mux->hw);
507 if (cur_parent == PLL_MODE_NORM) {
508 pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW);
509 rate_change_remuxed = 1;
510 }
511
512 /* update pll values */
513 writel_relaxed(HIWORD_UPDATE(rate->fbdiv, RK3036_PLLCON0_FBDIV_MASK, RK3036_PLLCON0_FBDIV_SHIFT) |
514 HIWORD_UPDATE(rate->postdiv1, RK3036_PLLCON0_POSTDIV1_MASK, RK3036_PLLCON0_POSTDIV1_SHIFT),
515 pll->reg_base + RK3036_PLLCON(0));
516
517 writel_relaxed(HIWORD_UPDATE(rate->refdiv, RK3036_PLLCON1_REFDIV_MASK, RK3036_PLLCON1_REFDIV_SHIFT) |
518 HIWORD_UPDATE(rate->postdiv2, RK3036_PLLCON1_POSTDIV2_MASK, RK3036_PLLCON1_POSTDIV2_SHIFT) |
519 HIWORD_UPDATE(rate->dsmpd, RK3036_PLLCON1_DSMPD_MASK, RK3036_PLLCON1_DSMPD_SHIFT),
520 pll->reg_base + RK3036_PLLCON(1));
521
522 /* GPLL CON2 is not HIWORD_MASK */
523 pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(0x2));
524 pllcon &= ~(RK3036_PLLCON2_FRAC_MASK << RK3036_PLLCON2_FRAC_SHIFT);
525 pllcon |= rate->frac << RK3036_PLLCON2_FRAC_SHIFT;
526 writel_relaxed(pllcon, pll->reg_base + RK3036_PLLCON(0x2));
527
528 rockchip_boost_disable_low(pll);
529
530 /* wait for the pll to lock */
531 ret = rockchip_rk3036_pll_wait_lock(pll);
532 if (ret) {
533 pr_warn("%s: pll update unsuccessful, trying to restore old params\n", __func__);
534 rockchip_rk3036_pll_set_params(pll, &cur);
535 }
536
537 if (rate_change_remuxed) {
538 pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM);
539 }
540
541 return ret;
542 }
543
rockchip_rk3036_pll_set_rate(struct clk_hw * hw,unsigned long drate,unsigned long prate)544 static int rockchip_rk3036_pll_set_rate(struct clk_hw *hw, unsigned long drate, unsigned long prate)
545 {
546 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
547 const struct rockchip_pll_rate_table *rate;
548
549 pr_debug("%s: changing %s to %lu with a parent rate of %lu\n", __func__, __clk_get_name(hw->clk), drate, prate);
550
551 /* Get required rate settings from table */
552 rate = rockchip_get_pll_settings(pll, drate);
553 if (!rate) {
554 pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, drate, __clk_get_name(hw->clk));
555 return -EINVAL;
556 }
557
558 return rockchip_rk3036_pll_set_params(pll, rate);
559 }
560
rockchip_rk3036_pll_enable(struct clk_hw * hw)561 static int rockchip_rk3036_pll_enable(struct clk_hw *hw)
562 {
563 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
564
565 writel(HIWORD_UPDATE(0, RK3036_PLLCON1_PWRDOWN, 0), pll->reg_base + RK3036_PLLCON(1));
566 rockchip_rk3036_pll_wait_lock(pll);
567
568 return 0;
569 }
570
rockchip_rk3036_pll_disable(struct clk_hw * hw)571 static void rockchip_rk3036_pll_disable(struct clk_hw *hw)
572 {
573 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
574
575 writel(HIWORD_UPDATE(RK3036_PLLCON1_PWRDOWN, RK3036_PLLCON1_PWRDOWN, 0), pll->reg_base + RK3036_PLLCON(1));
576 }
577
rockchip_rk3036_pll_is_enabled(struct clk_hw * hw)578 static int rockchip_rk3036_pll_is_enabled(struct clk_hw *hw)
579 {
580 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
581 u32 pllcon = readl(pll->reg_base + RK3036_PLLCON(1));
582
583 return !(pllcon & RK3036_PLLCON1_PWRDOWN);
584 }
585
rockchip_rk3036_pll_init(struct clk_hw * hw)586 static int rockchip_rk3036_pll_init(struct clk_hw *hw)
587 {
588 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
589 const struct rockchip_pll_rate_table *rate;
590 struct rockchip_pll_rate_table cur;
591 unsigned long drate;
592
593 if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE)) {
594 return 0;
595 }
596
597 drate = clk_hw_get_rate(hw);
598 rate = rockchip_get_pll_settings(pll, drate);
599 /* when no rate setting for the current rate, rely on clk_set_rate */
600 if (!rate) {
601 return 0;
602 }
603
604 rockchip_rk3036_pll_get_params(pll, &cur);
605
606 pr_debug("%s: pll %s@%lu: Hz\n", __func__, __clk_get_name(hw->clk), drate);
607 pr_debug("old - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n", cur.fbdiv, cur.postdiv1,
608 cur.refdiv, cur.postdiv2, cur.dsmpd, cur.frac);
609 pr_debug("new - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n", rate->fbdiv,
610 rate->postdiv1, rate->refdiv, rate->postdiv2, rate->dsmpd, rate->frac);
611
612 if (rate->fbdiv != cur.fbdiv || rate->postdiv1 != cur.postdiv1 || rate->refdiv != cur.refdiv ||
613 rate->postdiv2 != cur.postdiv2 || rate->dsmpd != cur.dsmpd || (!cur.dsmpd && (rate->frac != cur.frac))) {
614 struct clk *parent = clk_get_parent(hw->clk);
615
616 if (!parent) {
617 pr_warn("%s: parent of %s not available\n", __func__, __clk_get_name(hw->clk));
618 return 0;
619 }
620
621 pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n", __func__, __clk_get_name(hw->clk));
622 rockchip_rk3036_pll_set_params(pll, rate);
623 }
624
625 return 0;
626 }
627
628 static const struct clk_ops rockchip_rk3036_pll_clk_norate_ops = {
629 .recalc_rate = rockchip_rk3036_pll_recalc_rate,
630 .enable = rockchip_rk3036_pll_enable,
631 .disable = rockchip_rk3036_pll_disable,
632 .is_enabled = rockchip_rk3036_pll_is_enabled,
633 };
634
635 static const struct clk_ops rockchip_rk3036_pll_clk_ops = {
636 .recalc_rate = rockchip_rk3036_pll_recalc_rate,
637 .round_rate = rockchip_pll_round_rate,
638 .set_rate = rockchip_rk3036_pll_set_rate,
639 .enable = rockchip_rk3036_pll_enable,
640 .disable = rockchip_rk3036_pll_disable,
641 .is_enabled = rockchip_rk3036_pll_is_enabled,
642 .init = rockchip_rk3036_pll_init,
643 };
644
645 /**
646 * PLL used in RK3066, RK3188 and RK3288
647 */
648
649 #define RK3066_PLL_RESET_DELAY(nr) (((nr)*500) / 24 + 1)
650
651 #define RK3066_PLLCON(i) ((i)*0x4)
652 #define RK3066_PLLCON0_OD_MASK 0xf
653 #define RK3066_PLLCON0_OD_SHIFT 0
654 #define RK3066_PLLCON0_NR_MASK 0x3f
655 #define RK3066_PLLCON0_NR_SHIFT 8
656 #define RK3066_PLLCON1_NF_MASK 0x1fff
657 #define RK3066_PLLCON1_NF_SHIFT 0
658 #define RK3066_PLLCON2_NB_MASK 0xfff
659 #define RK3066_PLLCON2_NB_SHIFT 0
660 #define RK3066_PLLCON3_RESET (1 << 5)
661 #define RK3066_PLLCON3_PWRDOWN (1 << 1)
662 #define RK3066_PLLCON3_BYPASS (1 << 0)
663
rockchip_rk3066_pll_get_params(struct rockchip_clk_pll * pll,struct rockchip_pll_rate_table * rate)664 static void rockchip_rk3066_pll_get_params(struct rockchip_clk_pll *pll, struct rockchip_pll_rate_table *rate)
665 {
666 u32 pllcon;
667
668 pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(0));
669 rate->nr = ((pllcon >> RK3066_PLLCON0_NR_SHIFT) & RK3066_PLLCON0_NR_MASK) + 1;
670 rate->no = ((pllcon >> RK3066_PLLCON0_OD_SHIFT) & RK3066_PLLCON0_OD_MASK) + 1;
671
672 pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(1));
673 rate->nf = ((pllcon >> RK3066_PLLCON1_NF_SHIFT) & RK3066_PLLCON1_NF_MASK) + 1;
674
675 pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(2));
676 rate->nb = ((pllcon >> RK3066_PLLCON2_NB_SHIFT) & RK3066_PLLCON2_NB_MASK) + 1;
677 }
678
rockchip_rk3066_pll_recalc_rate(struct clk_hw * hw,unsigned long prate)679 static unsigned long rockchip_rk3066_pll_recalc_rate(struct clk_hw *hw, unsigned long prate)
680 {
681 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
682 struct rockchip_pll_rate_table cur;
683 u64 rate64 = prate;
684 u32 pllcon;
685
686 pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(3));
687 if (pllcon & RK3066_PLLCON3_BYPASS) {
688 pr_debug("%s: pll %s is bypassed\n", __func__, clk_hw_get_name(hw));
689 return prate;
690 }
691
692 if (pll->sel && pll->scaling) {
693 return pll->scaling;
694 }
695
696 rockchip_rk3066_pll_get_params(pll, &cur);
697
698 rate64 *= cur.nf;
699 do_div(rate64, cur.nr);
700 do_div(rate64, cur.no);
701
702 return (unsigned long)rate64;
703 }
704
rockchip_rk3066_pll_set_params(struct rockchip_clk_pll * pll,const struct rockchip_pll_rate_table * rate)705 static int rockchip_rk3066_pll_set_params(struct rockchip_clk_pll *pll, const struct rockchip_pll_rate_table *rate)
706 {
707 const struct clk_ops *pll_mux_ops = pll->pll_mux_ops;
708 struct clk_mux *pll_mux = &pll->pll_mux;
709 struct rockchip_pll_rate_table cur;
710 int rate_change_remuxed = 0;
711 int cur_parent;
712 int ret;
713
714 pr_debug("%s: rate settings for %lu (nr, no, nf): (%d, %d, %d)\n", __func__, rate->rate, rate->nr, rate->no,
715 rate->nf);
716
717 rockchip_rk3066_pll_get_params(pll, &cur);
718 cur.rate = 0;
719
720 cur_parent = pll_mux_ops->get_parent(&pll_mux->hw);
721 if (cur_parent == PLL_MODE_NORM) {
722 pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW);
723 rate_change_remuxed = 1;
724 }
725
726 /* enter reset mode */
727 writel(HIWORD_UPDATE(RK3066_PLLCON3_RESET, RK3066_PLLCON3_RESET, 0), pll->reg_base + RK3066_PLLCON(3));
728
729 /* update pll values */
730 writel(HIWORD_UPDATE(rate->nr - 1, RK3066_PLLCON0_NR_MASK, RK3066_PLLCON0_NR_SHIFT) |
731 HIWORD_UPDATE(rate->no - 1, RK3066_PLLCON0_OD_MASK, RK3066_PLLCON0_OD_SHIFT),
732 pll->reg_base + RK3066_PLLCON(0));
733
734 writel_relaxed(HIWORD_UPDATE(rate->nf - 1, RK3066_PLLCON1_NF_MASK, RK3066_PLLCON1_NF_SHIFT),
735 pll->reg_base + RK3066_PLLCON(1));
736 writel_relaxed(HIWORD_UPDATE(rate->nb - 1, RK3066_PLLCON2_NB_MASK, RK3066_PLLCON2_NB_SHIFT),
737 pll->reg_base + RK3066_PLLCON(2));
738
739 /* leave reset and wait the reset_delay */
740 writel(HIWORD_UPDATE(0, RK3066_PLLCON3_RESET, 0), pll->reg_base + RK3066_PLLCON(3));
741 udelay(RK3066_PLL_RESET_DELAY(rate->nr));
742
743 /* wait for the pll to lock */
744 ret = rockchip_pll_wait_lock(pll);
745 if (ret) {
746 pr_warn("%s: pll update unsuccessful, trying to restore old params\n", __func__);
747 rockchip_rk3066_pll_set_params(pll, &cur);
748 }
749
750 if (rate_change_remuxed) {
751 pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM);
752 }
753
754 return ret;
755 }
756
rockchip_rk3066_pll_set_rate(struct clk_hw * hw,unsigned long drate,unsigned long prate)757 static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate, unsigned long prate)
758 {
759 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
760 const struct rockchip_pll_rate_table *rate;
761 unsigned long old_rate = rockchip_rk3066_pll_recalc_rate(hw, prate);
762 struct regmap *grf = pll->ctx->grf;
763 int ret;
764
765 if (IS_ERR(grf)) {
766 pr_debug("%s: grf regmap not available, aborting rate change\n", __func__);
767 return PTR_ERR(grf);
768 }
769
770 pr_debug("%s: changing %s from %lu to %lu with a parent rate of %lu\n", __func__, clk_hw_get_name(hw), old_rate,
771 drate, prate);
772
773 /* Get required rate settings from table */
774 rate = rockchip_get_pll_settings(pll, drate);
775 if (!rate) {
776 pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, drate, clk_hw_get_name(hw));
777 return -EINVAL;
778 }
779
780 ret = rockchip_rk3066_pll_set_params(pll, rate);
781 if (ret) {
782 pll->scaling = 0;
783 }
784
785 return ret;
786 }
787
rockchip_rk3066_pll_enable(struct clk_hw * hw)788 static int rockchip_rk3066_pll_enable(struct clk_hw *hw)
789 {
790 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
791
792 writel(HIWORD_UPDATE(0, RK3066_PLLCON3_PWRDOWN, 0), pll->reg_base + RK3066_PLLCON(3));
793 rockchip_pll_wait_lock(pll);
794
795 return 0;
796 }
797
rockchip_rk3066_pll_disable(struct clk_hw * hw)798 static void rockchip_rk3066_pll_disable(struct clk_hw *hw)
799 {
800 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
801
802 writel(HIWORD_UPDATE(RK3066_PLLCON3_PWRDOWN, RK3066_PLLCON3_PWRDOWN, 0), pll->reg_base + RK3066_PLLCON(3));
803 }
804
rockchip_rk3066_pll_is_enabled(struct clk_hw * hw)805 static int rockchip_rk3066_pll_is_enabled(struct clk_hw *hw)
806 {
807 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
808 u32 pllcon = readl(pll->reg_base + RK3066_PLLCON(3));
809
810 return !(pllcon & RK3066_PLLCON3_PWRDOWN);
811 }
812
rockchip_rk3066_pll_init(struct clk_hw * hw)813 static int rockchip_rk3066_pll_init(struct clk_hw *hw)
814 {
815 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
816 const struct rockchip_pll_rate_table *rate;
817 struct rockchip_pll_rate_table cur;
818 unsigned long drate;
819
820 if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE)) {
821 return 0;
822 }
823
824 drate = clk_hw_get_rate(hw);
825 rate = rockchip_get_pll_settings(pll, drate);
826 /* when no rate setting for the current rate, rely on clk_set_rate */
827 if (!rate) {
828 return 0;
829 }
830
831 rockchip_rk3066_pll_get_params(pll, &cur);
832
833 pr_debug("%s: pll %s@%lu: nr (%d:%d); no (%d:%d); nf(%d:%d), nb(%d:%d)\n", __func__, clk_hw_get_name(hw), drate,
834 rate->nr, cur.nr, rate->no, cur.no, rate->nf, cur.nf, rate->nb, cur.nb);
835 if (rate->nr != cur.nr || rate->no != cur.no || rate->nf != cur.nf || rate->nb != cur.nb) {
836 pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n", __func__, clk_hw_get_name(hw));
837 rockchip_rk3066_pll_set_params(pll, rate);
838 }
839
840 return 0;
841 }
842
843 static const struct clk_ops rockchip_rk3066_pll_clk_norate_ops = {
844 .recalc_rate = rockchip_rk3066_pll_recalc_rate,
845 .enable = rockchip_rk3066_pll_enable,
846 .disable = rockchip_rk3066_pll_disable,
847 .is_enabled = rockchip_rk3066_pll_is_enabled,
848 };
849
850 static const struct clk_ops rockchip_rk3066_pll_clk_ops = {
851 .recalc_rate = rockchip_rk3066_pll_recalc_rate,
852 .round_rate = rockchip_pll_round_rate,
853 .set_rate = rockchip_rk3066_pll_set_rate,
854 .enable = rockchip_rk3066_pll_enable,
855 .disable = rockchip_rk3066_pll_disable,
856 .is_enabled = rockchip_rk3066_pll_is_enabled,
857 .init = rockchip_rk3066_pll_init,
858 };
859
860 /**
861 * PLL used in RK3399
862 */
863
864 #define RK3399_PLLCON(i) ((i)*0x4)
865 #define RK3399_PLLCON0_FBDIV_MASK 0xfff
866 #define RK3399_PLLCON0_FBDIV_SHIFT 0
867 #define RK3399_PLLCON1_REFDIV_MASK 0x3f
868 #define RK3399_PLLCON1_REFDIV_SHIFT 0
869 #define RK3399_PLLCON1_POSTDIV1_MASK 0x7
870 #define RK3399_PLLCON1_POSTDIV1_SHIFT 8
871 #define RK3399_PLLCON1_POSTDIV2_MASK 0x7
872 #define RK3399_PLLCON1_POSTDIV2_SHIFT 12
873 #define RK3399_PLLCON2_FRAC_MASK 0xffffff
874 #define RK3399_PLLCON2_FRAC_SHIFT 0
875 #define RK3399_PLLCON2_LOCK_STATUS BIT(31)
876 #define RK3399_PLLCON3_PWRDOWN BIT(0)
877 #define RK3399_PLLCON3_DSMPD_MASK 0x1
878 #define RK3399_PLLCON3_DSMPD_SHIFT 3
879
rockchip_rk3399_pll_wait_lock(struct rockchip_clk_pll * pll)880 static int rockchip_rk3399_pll_wait_lock(struct rockchip_clk_pll *pll)
881 {
882 u32 pllcon;
883 int ret;
884
885 /*
886 * Lock time typical 250, max 500 input clock cycles @24MHz
887 * So define a very safe maximum of 1000us, meaning 24000 cycles.
888 */
889 ret = readl_relaxed_poll_timeout(pll->reg_base + RK3399_PLLCON(2), pllcon, pllcon & RK3399_PLLCON2_LOCK_STATUS, 0,
890 0x3e8);
891 if (ret) {
892 pr_err("%s: timeout waiting for pll to lock\n", __func__);
893 }
894
895 return ret;
896 }
897
rockchip_rk3399_pll_get_params(struct rockchip_clk_pll * pll,struct rockchip_pll_rate_table * rate)898 static void rockchip_rk3399_pll_get_params(struct rockchip_clk_pll *pll, struct rockchip_pll_rate_table *rate)
899 {
900 u32 pllcon;
901
902 pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(0));
903 rate->fbdiv = ((pllcon >> RK3399_PLLCON0_FBDIV_SHIFT) & RK3399_PLLCON0_FBDIV_MASK);
904
905 pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(1));
906 rate->refdiv = ((pllcon >> RK3399_PLLCON1_REFDIV_SHIFT) & RK3399_PLLCON1_REFDIV_MASK);
907 rate->postdiv1 = ((pllcon >> RK3399_PLLCON1_POSTDIV1_SHIFT) & RK3399_PLLCON1_POSTDIV1_MASK);
908 rate->postdiv2 = ((pllcon >> RK3399_PLLCON1_POSTDIV2_SHIFT) & RK3399_PLLCON1_POSTDIV2_MASK);
909
910 pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(2));
911 rate->frac = ((pllcon >> RK3399_PLLCON2_FRAC_SHIFT) & RK3399_PLLCON2_FRAC_MASK);
912
913 pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(3));
914 rate->dsmpd = ((pllcon >> RK3399_PLLCON3_DSMPD_SHIFT) & RK3399_PLLCON3_DSMPD_MASK);
915 }
916
rockchip_rk3399_pll_recalc_rate(struct clk_hw * hw,unsigned long prate)917 static unsigned long rockchip_rk3399_pll_recalc_rate(struct clk_hw *hw, unsigned long prate)
918 {
919 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
920 struct rockchip_pll_rate_table cur;
921 u64 rate64 = prate;
922
923 if (pll->sel && pll->scaling) {
924 return pll->scaling;
925 }
926
927 rockchip_rk3399_pll_get_params(pll, &cur);
928
929 rate64 *= cur.fbdiv;
930 do_div(rate64, cur.refdiv);
931
932 if (cur.dsmpd == 0) {
933 /* fractional mode */
934 u64 frac_rate64 = prate * cur.frac;
935
936 do_div(frac_rate64, cur.refdiv);
937 rate64 += frac_rate64 >> 0x18;
938 }
939
940 do_div(rate64, cur.postdiv1);
941 do_div(rate64, cur.postdiv2);
942
943 return (unsigned long)rate64;
944 }
945
rockchip_rk3399_pll_set_params(struct rockchip_clk_pll * pll,const struct rockchip_pll_rate_table * rate)946 static int rockchip_rk3399_pll_set_params(struct rockchip_clk_pll *pll, const struct rockchip_pll_rate_table *rate)
947 {
948 const struct clk_ops *pll_mux_ops = pll->pll_mux_ops;
949 struct clk_mux *pll_mux = &pll->pll_mux;
950 struct rockchip_pll_rate_table cur;
951 u32 pllcon;
952 int rate_change_remuxed = 0;
953 int cur_parent;
954 int ret;
955
956 pr_debug("%s: rate settings for %lu fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",
957 __func__, rate->rate, rate->fbdiv, rate->postdiv1, rate->refdiv, rate->postdiv2, rate->dsmpd, rate->frac);
958
959 rockchip_rk3399_pll_get_params(pll, &cur);
960 cur.rate = 0;
961
962 cur_parent = pll_mux_ops->get_parent(&pll_mux->hw);
963 if (cur_parent == PLL_MODE_NORM) {
964 pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW);
965 rate_change_remuxed = 1;
966 }
967
968 /* set pll power down */
969 writel(HIWORD_UPDATE(RK3399_PLLCON3_PWRDOWN, RK3399_PLLCON3_PWRDOWN, 0), pll->reg_base + RK3399_PLLCON(0x3));
970
971 /* update pll values */
972 writel_relaxed(HIWORD_UPDATE(rate->fbdiv, RK3399_PLLCON0_FBDIV_MASK, RK3399_PLLCON0_FBDIV_SHIFT),
973 pll->reg_base + RK3399_PLLCON(0));
974
975 writel_relaxed(HIWORD_UPDATE(rate->refdiv, RK3399_PLLCON1_REFDIV_MASK, RK3399_PLLCON1_REFDIV_SHIFT) |
976 HIWORD_UPDATE(rate->postdiv1, RK3399_PLLCON1_POSTDIV1_MASK, RK3399_PLLCON1_POSTDIV1_SHIFT) |
977 HIWORD_UPDATE(rate->postdiv2, RK3399_PLLCON1_POSTDIV2_MASK, RK3399_PLLCON1_POSTDIV2_SHIFT),
978 pll->reg_base + RK3399_PLLCON(1));
979
980 /* xPLL CON2 is not HIWORD_MASK */
981 pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(0x2));
982 pllcon &= ~(RK3399_PLLCON2_FRAC_MASK << RK3399_PLLCON2_FRAC_SHIFT);
983 pllcon |= rate->frac << RK3399_PLLCON2_FRAC_SHIFT;
984 writel_relaxed(pllcon, pll->reg_base + RK3399_PLLCON(0x2));
985
986 writel_relaxed(HIWORD_UPDATE(rate->dsmpd, RK3399_PLLCON3_DSMPD_MASK, RK3399_PLLCON3_DSMPD_SHIFT),
987 pll->reg_base + RK3399_PLLCON(0x3));
988
989 /* set pll power up */
990 writel(HIWORD_UPDATE(0, RK3399_PLLCON3_PWRDOWN, 0), pll->reg_base + RK3399_PLLCON(0x3));
991
992 /* wait for the pll to lock */
993 ret = rockchip_rk3399_pll_wait_lock(pll);
994 if (ret) {
995 pr_warn("%s: pll update unsuccessful, trying to restore old params\n", __func__);
996 rockchip_rk3399_pll_set_params(pll, &cur);
997 }
998
999 if (rate_change_remuxed) {
1000 pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM);
1001 }
1002
1003 return ret;
1004 }
1005
rockchip_rk3399_pll_set_rate(struct clk_hw * hw,unsigned long drate,unsigned long prate)1006 static int rockchip_rk3399_pll_set_rate(struct clk_hw *hw, unsigned long drate, unsigned long prate)
1007 {
1008 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
1009 const struct rockchip_pll_rate_table *rate;
1010 unsigned long old_rate = rockchip_rk3399_pll_recalc_rate(hw, prate);
1011 int ret;
1012
1013 pr_debug("%s: changing %s from %lu to %lu with a parent rate of %lu\n", __func__, __clk_get_name(hw->clk), old_rate,
1014 drate, prate);
1015
1016 /* Get required rate settings from table */
1017 rate = rockchip_get_pll_settings(pll, drate);
1018 if (!rate) {
1019 pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, drate, __clk_get_name(hw->clk));
1020 return -EINVAL;
1021 }
1022
1023 ret = rockchip_rk3399_pll_set_params(pll, rate);
1024 if (ret) {
1025 pll->scaling = 0;
1026 }
1027
1028 return ret;
1029 }
1030
rockchip_rk3399_pll_enable(struct clk_hw * hw)1031 static int rockchip_rk3399_pll_enable(struct clk_hw *hw)
1032 {
1033 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
1034
1035 writel(HIWORD_UPDATE(0, RK3399_PLLCON3_PWRDOWN, 0), pll->reg_base + RK3399_PLLCON(0x3));
1036 rockchip_rk3399_pll_wait_lock(pll);
1037
1038 return 0;
1039 }
1040
rockchip_rk3399_pll_disable(struct clk_hw * hw)1041 static void rockchip_rk3399_pll_disable(struct clk_hw *hw)
1042 {
1043 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
1044
1045 writel(HIWORD_UPDATE(RK3399_PLLCON3_PWRDOWN, RK3399_PLLCON3_PWRDOWN, 0), pll->reg_base + RK3399_PLLCON(0x3));
1046 }
1047
rockchip_rk3399_pll_is_enabled(struct clk_hw * hw)1048 static int rockchip_rk3399_pll_is_enabled(struct clk_hw *hw)
1049 {
1050 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
1051 u32 pllcon = readl(pll->reg_base + RK3399_PLLCON(0x3));
1052
1053 return !(pllcon & RK3399_PLLCON3_PWRDOWN);
1054 }
1055
rockchip_rk3399_pll_init(struct clk_hw * hw)1056 static int rockchip_rk3399_pll_init(struct clk_hw *hw)
1057 {
1058 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
1059 const struct rockchip_pll_rate_table *rate;
1060 struct rockchip_pll_rate_table cur;
1061 unsigned long drate;
1062
1063 if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE)) {
1064 return 0;
1065 }
1066
1067 drate = clk_hw_get_rate(hw);
1068 rate = rockchip_get_pll_settings(pll, drate);
1069 /* when no rate setting for the current rate, rely on clk_set_rate */
1070 if (!rate) {
1071 return 0;
1072 }
1073
1074 rockchip_rk3399_pll_get_params(pll, &cur);
1075
1076 pr_debug("%s: pll %s@%lu: Hz\n", __func__, __clk_get_name(hw->clk), drate);
1077 pr_debug("old - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n", cur.fbdiv, cur.postdiv1,
1078 cur.refdiv, cur.postdiv2, cur.dsmpd, cur.frac);
1079 pr_debug("new - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n", rate->fbdiv,
1080 rate->postdiv1, rate->refdiv, rate->postdiv2, rate->dsmpd, rate->frac);
1081
1082 if (rate->fbdiv != cur.fbdiv || rate->postdiv1 != cur.postdiv1 || rate->refdiv != cur.refdiv ||
1083 rate->postdiv2 != cur.postdiv2 || rate->dsmpd != cur.dsmpd || (!cur.dsmpd && (rate->frac != cur.frac))) {
1084 struct clk *parent = clk_get_parent(hw->clk);
1085
1086 if (!parent) {
1087 pr_warn("%s: parent of %s not available\n", __func__, __clk_get_name(hw->clk));
1088 return 0;
1089 }
1090
1091 pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n", __func__, __clk_get_name(hw->clk));
1092 rockchip_rk3399_pll_set_params(pll, rate);
1093 }
1094
1095 return 0;
1096 }
1097
1098 static const struct clk_ops rockchip_rk3399_pll_clk_norate_ops = {
1099 .recalc_rate = rockchip_rk3399_pll_recalc_rate,
1100 .enable = rockchip_rk3399_pll_enable,
1101 .disable = rockchip_rk3399_pll_disable,
1102 .is_enabled = rockchip_rk3399_pll_is_enabled,
1103 };
1104
1105 static const struct clk_ops rockchip_rk3399_pll_clk_ops = {
1106 .recalc_rate = rockchip_rk3399_pll_recalc_rate,
1107 .round_rate = rockchip_pll_round_rate,
1108 .set_rate = rockchip_rk3399_pll_set_rate,
1109 .enable = rockchip_rk3399_pll_enable,
1110 .disable = rockchip_rk3399_pll_disable,
1111 .is_enabled = rockchip_rk3399_pll_is_enabled,
1112 .init = rockchip_rk3399_pll_init,
1113 };
1114
1115 #ifdef CONFIG_ROCKCHIP_CLK_COMPENSATION
rockchip_pll_clk_compensation(struct clk * clk,int ppm)1116 int rockchip_pll_clk_compensation(struct clk *clk, int ppm)
1117 {
1118 struct clk *parent = clk_get_parent(clk);
1119 struct rockchip_clk_pll *pll;
1120 static u32 frac, fbdiv;
1121 bool negative;
1122 u32 pllcon, pllcon0, pllcon2, fbdiv_mask, frac_mask, frac_shift;
1123 u64 fracdiv, m, n;
1124
1125 if ((ppm > 0x3e8) || (ppm < -0x3e8)) {
1126 return -EINVAL;
1127 }
1128
1129 if (IS_ERR_OR_NULL(parent)) {
1130 return -EINVAL;
1131 }
1132
1133 pll = to_rockchip_clk_pll(__clk_get_hw(parent));
1134 if (!pll) {
1135 return -EINVAL;
1136 }
1137
1138 switch (pll->type) {
1139 case pll_rk3036:
1140 case pll_rk3328:
1141 pllcon0 = RK3036_PLLCON(0);
1142 pllcon2 = RK3036_PLLCON(0x2);
1143 fbdiv_mask = RK3036_PLLCON0_FBDIV_MASK;
1144 frac_mask = RK3036_PLLCON2_FRAC_MASK;
1145 frac_shift = RK3036_PLLCON2_FRAC_SHIFT;
1146 break;
1147 case pll_rk3066:
1148 return -EINVAL;
1149 case pll_rk3399:
1150 pllcon0 = RK3399_PLLCON(0);
1151 pllcon2 = RK3399_PLLCON(2);
1152 fbdiv_mask = RK3399_PLLCON0_FBDIV_MASK;
1153 frac_mask = RK3399_PLLCON2_FRAC_MASK;
1154 frac_shift = RK3399_PLLCON2_FRAC_SHIFT;
1155 break;
1156 default:
1157 return -EINVAL;
1158 }
1159
1160 negative = !!(ppm & BIT(0x1f));
1161 ppm = negative ? ~ppm + 1 : ppm;
1162
1163 if (!frac) {
1164 frac = readl_relaxed(pll->reg_base + pllcon2) & frac_mask;
1165 fbdiv = readl_relaxed(pll->reg_base + pllcon0) & fbdiv_mask;
1166 }
1167
1168 /*
1169 * delta frac frac ppm
1170 * -------------- = (fbdiv + ----------) * ---------
1171 * 1 << 24 1 << 24 1000000
1172 *
1173 */
1174 m = div64_u64((uint64_t)frac * ppm, 0xf4240);
1175 n = div64_u64((uint64_t)ppm << 0x18, 0xf4240) * fbdiv;
1176
1177 fracdiv = negative ? frac - (m + n) : frac + (m + n);
1178
1179 if (!frac || fracdiv > frac_mask) {
1180 return -EINVAL;
1181 }
1182
1183 pllcon = readl_relaxed(pll->reg_base + pllcon2);
1184 pllcon &= ~(frac_mask << frac_shift);
1185 pllcon |= fracdiv << frac_shift;
1186 writel_relaxed(pllcon, pll->reg_base + pllcon2);
1187
1188 return 0;
1189 }
1190 EXPORT_SYMBOL(rockchip_pll_clk_compensation);
1191 #endif
1192
1193 /*
1194 * Common registering of pll clocks
1195 */
1196
rockchip_clk_register_pll(struct rockchip_clk_provider * ctx,enum rockchip_pll_type pll_type,const char * name,const char * const * parent_names,u8 num_parents,int con_offset,int grf_lock_offset,int lock_shift,int mode_offset,int mode_shift,struct rockchip_pll_rate_table * rate_table,unsigned long flags,u8 clk_pll_flags)1197 struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx, enum rockchip_pll_type pll_type,
1198 const char *name, const char *const *parent_names, u8 num_parents, int con_offset,
1199 int grf_lock_offset, int lock_shift, int mode_offset, int mode_shift,
1200 struct rockchip_pll_rate_table *rate_table, unsigned long flags, u8 clk_pll_flags)
1201 {
1202 const char *pll_parents[3];
1203 struct clk_init_data init;
1204 struct rockchip_clk_pll *pll;
1205 struct clk_mux *pll_mux;
1206 struct clk *pll_clk, *mux_clk;
1207 char pll_name[20];
1208 int ret = 0;
1209
1210 if ((pll_type != pll_rk3328 && num_parents != 0x2) || (pll_type == pll_rk3328 && num_parents != 0x1)) {
1211 pr_err("%s: needs two parent clocks\n", __func__);
1212 return ERR_PTR(-EINVAL);
1213 }
1214
1215 /* name the actual pll */
1216 ret = snprintf(pll_name, sizeof(pll_name), "pll_%s", name);
1217
1218 pll = kzalloc(sizeof(*pll), GFP_KERNEL);
1219 if (!pll) {
1220 return ERR_PTR(-ENOMEM);
1221 }
1222
1223 /* create the mux on top of the real pll */
1224 pll->pll_mux_ops = &clk_mux_ops;
1225 pll_mux = &pll->pll_mux;
1226 pll_mux->reg = ctx->reg_base + mode_offset;
1227 pll_mux->shift = mode_shift;
1228 if (pll_type == pll_rk3328) {
1229 pll_mux->mask = PLL_RK3328_MODE_MASK;
1230 } else {
1231 pll_mux->mask = PLL_MODE_MASK;
1232 }
1233 pll_mux->flags = 0;
1234 pll_mux->lock = &ctx->lock;
1235 pll_mux->hw.init = &init;
1236
1237 if (pll_type == pll_rk3036 || pll_type == pll_rk3066 || pll_type == pll_rk3328 || pll_type == pll_rk3399) {
1238 pll_mux->flags |= CLK_MUX_HIWORD_MASK;
1239 }
1240
1241 /* the actual muxing is xin24m, pll-output, xin32k */
1242 pll_parents[0x0] = parent_names[0x0];
1243 pll_parents[0x1] = pll_name;
1244 pll_parents[0x2] = parent_names[0x1];
1245
1246 init.name = name;
1247 init.flags = CLK_SET_RATE_PARENT;
1248 init.ops = pll->pll_mux_ops;
1249 init.parent_names = pll_parents;
1250 if (pll_type == pll_rk3328) {
1251 init.num_parents = 0x2;
1252 } else {
1253 init.num_parents = ARRAY_SIZE(pll_parents);
1254 }
1255
1256 mux_clk = clk_register(NULL, &pll_mux->hw);
1257 if (IS_ERR(mux_clk)) {
1258 goto err_mux;
1259 }
1260
1261 /* now create the actual pll */
1262 init.name = pll_name;
1263
1264 #ifndef CONFIG_ROCKCHIP_LOW_PERFORMANCE
1265 /* keep all plls untouched for now */
1266 init.flags = flags | CLK_IGNORE_UNUSED;
1267 #else
1268 init.flags = flags;
1269 #endif
1270
1271 init.parent_names = &parent_names[0];
1272 init.num_parents = 1;
1273
1274 if (rate_table) {
1275 int len;
1276
1277 /* find count of rates in rate_table */
1278 for (len = 0; rate_table[len].rate != 0;) {
1279 len++;
1280 }
1281
1282 pll->rate_count = len;
1283 pll->rate_table = kmemdup(rate_table, pll->rate_count * sizeof(struct rockchip_pll_rate_table), GFP_KERNEL);
1284 WARN(!pll->rate_table, "%s: could not allocate rate table for %s\n", __func__, name);
1285 }
1286
1287 switch (pll_type) {
1288 case pll_rk3036:
1289 case pll_rk3328:
1290 if (!pll->rate_table || IS_ERR(ctx->grf)) {
1291 init.ops = &rockchip_rk3036_pll_clk_norate_ops;
1292 } else {
1293 init.ops = &rockchip_rk3036_pll_clk_ops;
1294 }
1295 break;
1296 case pll_rk3066:
1297 if (!pll->rate_table || IS_ERR(ctx->grf)) {
1298 init.ops = &rockchip_rk3066_pll_clk_norate_ops;
1299 } else {
1300 init.ops = &rockchip_rk3066_pll_clk_ops;
1301 }
1302 break;
1303 case pll_rk3399:
1304 if (!pll->rate_table) {
1305 init.ops = &rockchip_rk3399_pll_clk_norate_ops;
1306 } else {
1307 init.ops = &rockchip_rk3399_pll_clk_ops;
1308 }
1309 break;
1310 default:
1311 pr_warn("%s: Unknown pll type for pll clk %s\n", __func__, name);
1312 }
1313
1314 pll->hw.init = &init;
1315 pll->type = pll_type;
1316 pll->reg_base = ctx->reg_base + con_offset;
1317 pll->lock_offset = grf_lock_offset;
1318 pll->lock_shift = lock_shift;
1319 pll->flags = clk_pll_flags;
1320 pll->lock = &ctx->lock;
1321 pll->ctx = ctx;
1322
1323 pll_clk = clk_register(NULL, &pll->hw);
1324 if (IS_ERR(pll_clk)) {
1325 pr_err("%s: failed to register pll clock %s : %ld\n", __func__, name, PTR_ERR(pll_clk));
1326 goto err_pll;
1327 }
1328
1329 return mux_clk;
1330
1331 err_pll:
1332 clk_unregister(mux_clk);
1333 mux_clk = pll_clk;
1334 err_mux:
1335 kfree(pll);
1336 return mux_clk;
1337 }
1338
rockchip_pll_con_to_rate(struct rockchip_clk_pll * pll,u32 con0,u32 con1)1339 static unsigned long rockchip_pll_con_to_rate(struct rockchip_clk_pll *pll, u32 con0, u32 con1)
1340 {
1341 switch (pll->type) {
1342 case pll_rk3036:
1343 case pll_rk3328:
1344 return rockchip_rk3036_pll_con_to_rate(pll, con0, con1);
1345 case pll_rk3066:
1346 break;
1347 case pll_rk3399:
1348 break;
1349 default:
1350 pr_warn("%s: Unknown pll type\n", __func__);
1351 }
1352
1353 return 0;
1354 }
1355
rockchip_boost_init(struct clk_hw * hw)1356 void rockchip_boost_init(struct clk_hw *hw)
1357 {
1358 struct rockchip_clk_pll *pll;
1359 struct device_node *np;
1360 u32 value, con0, con1;
1361
1362 if (!hw) {
1363 return;
1364 }
1365 pll = to_rockchip_clk_pll(hw);
1366 np = of_parse_phandle(pll->ctx->cru_node, "rockchip,boost", 0);
1367 if (!np) {
1368 pr_debug("%s: failed to get boost np\n", __func__);
1369 return;
1370 }
1371 pll->boost = syscon_node_to_regmap(np);
1372 if (IS_ERR(pll->boost)) {
1373 pr_debug("%s: failed to get boost regmap\n", __func__);
1374 return;
1375 }
1376
1377 if (!of_property_read_u32(np, "rockchip,boost-low-con0", &con0) &&
1378 !of_property_read_u32(np, "rockchip,boost-low-con1", &con1)) {
1379 pr_debug("boost-low-con=0x%x 0x%x\n", con0, con1);
1380 regmap_write(pll->boost, BOOST_PLL_L_CON(0), HIWORD_UPDATE(con0, BOOST_PLL_CON_MASK, 0));
1381 regmap_write(pll->boost, BOOST_PLL_L_CON(1), HIWORD_UPDATE(con1, BOOST_PLL_CON_MASK, 0));
1382 pll->boost_low_rate = rockchip_pll_con_to_rate(pll, con0, con1);
1383 pr_debug("boost-low-rate=%lu\n", pll->boost_low_rate);
1384 }
1385 if (!of_property_read_u32(np, "rockchip,boost-high-con0", &con0) &&
1386 !of_property_read_u32(np, "rockchip,boost-high-con1", &con1)) {
1387 pr_debug("boost-high-con=0x%x 0x%x\n", con0, con1);
1388 regmap_write(pll->boost, BOOST_PLL_H_CON(0), HIWORD_UPDATE(con0, BOOST_PLL_CON_MASK, 0));
1389 regmap_write(pll->boost, BOOST_PLL_H_CON(1), HIWORD_UPDATE(con1, BOOST_PLL_CON_MASK, 0));
1390 pll->boost_high_rate = rockchip_pll_con_to_rate(pll, con0, con1);
1391 pr_debug("boost-high-rate=%lu\n", pll->boost_high_rate);
1392 }
1393 if (!of_property_read_u32(np, "rockchip,boost-backup-pll", &value)) {
1394 pr_debug("boost-backup-pll=0x%x\n", value);
1395 regmap_write(pll->boost, BOOST_CLK_CON, HIWORD_UPDATE(value, BOOST_BACKUP_PLL_MASK, BOOST_BACKUP_PLL_SHIFT));
1396 }
1397 if (!of_property_read_u32(np, "rockchip,boost-backup-pll-usage", &pll->boost_backup_pll_usage)) {
1398 pr_debug("boost-backup-pll-usage=0x%x\n", pll->boost_backup_pll_usage);
1399 regmap_write(
1400 pll->boost, BOOST_CLK_CON,
1401 HIWORD_UPDATE(pll->boost_backup_pll_usage, BOOST_BACKUP_PLL_USAGE_MASK, BOOST_BACKUP_PLL_USAGE_SHIFT));
1402 }
1403 if (!of_property_read_u32(np, "rockchip,boost-switch-threshold", &value)) {
1404 pr_debug("boost-switch-threshold=0x%x\n", value);
1405 regmap_write(pll->boost, BOOST_SWITCH_THRESHOLD, value);
1406 }
1407 if (!of_property_read_u32(np, "rockchip,boost-statis-threshold", &value)) {
1408 pr_debug("boost-statis-threshold=0x%x\n", value);
1409 regmap_write(pll->boost, BOOST_STATIS_THRESHOLD, value);
1410 }
1411 if (!of_property_read_u32(np, "rockchip,boost-statis-enable", &value)) {
1412 pr_debug("boost-statis-enable=0x%x\n", value);
1413 regmap_write(pll->boost, BOOST_BOOST_CON,
1414 HIWORD_UPDATE(value, BOOST_STATIS_ENABLE_MASK, BOOST_STATIS_ENABLE_SHIFT));
1415 }
1416 if (!of_property_read_u32(np, "rockchip,boost-enable", &value)) {
1417 pr_debug("boost-enable=0x%x\n", value);
1418 regmap_write(pll->boost, BOOST_BOOST_CON, HIWORD_UPDATE(value, BOOST_ENABLE_MASK, BOOST_ENABLE_SHIFT));
1419 if (value) {
1420 pll->boost_enabled = true;
1421 }
1422 }
1423 #ifdef CONFIG_DEBUG_FS
1424 if (pll->boost_enabled) {
1425 mutex_lock(&clk_boost_lock);
1426 hlist_add_head(&pll->debug_node, &clk_boost_list);
1427 mutex_unlock(&clk_boost_lock);
1428 }
1429 #endif
1430 }
1431
rockchip_boost_enable_recovery_sw_low(struct clk_hw * hw)1432 void rockchip_boost_enable_recovery_sw_low(struct clk_hw *hw)
1433 {
1434 struct rockchip_clk_pll *pll;
1435 unsigned int val;
1436
1437 if (!hw) {
1438 return;
1439 }
1440 pll = to_rockchip_clk_pll(hw);
1441 if (!pll->boost_enabled) {
1442 return;
1443 }
1444
1445 regmap_write(pll->boost, BOOST_BOOST_CON, HIWORD_UPDATE(1, BOOST_RECOVERY_MASK, BOOST_RECOVERY_SHIFT));
1446 do {
1447 regmap_read(pll->boost, BOOST_FSM_STATUS, &val);
1448 } while (!(val & BOOST_BUSY_STATE));
1449
1450 regmap_write(pll->boost, BOOST_BOOST_CON,
1451 HIWORD_UPDATE(1, BOOST_SW_CTRL_MASK, BOOST_SW_CTRL_SHIFT) |
1452 HIWORD_UPDATE(1, BOOST_LOW_FREQ_EN_MASK, BOOST_LOW_FREQ_EN_SHIFT));
1453 }
1454
rockchip_boost_disable_low(struct rockchip_clk_pll * pll)1455 static void rockchip_boost_disable_low(struct rockchip_clk_pll *pll)
1456 {
1457 if (!pll->boost_enabled) {
1458 return;
1459 }
1460
1461 regmap_write(pll->boost, BOOST_BOOST_CON, HIWORD_UPDATE(0, BOOST_LOW_FREQ_EN_MASK, BOOST_LOW_FREQ_EN_SHIFT));
1462 }
1463
rockchip_boost_disable_recovery_sw(struct clk_hw * hw)1464 void rockchip_boost_disable_recovery_sw(struct clk_hw *hw)
1465 {
1466 struct rockchip_clk_pll *pll;
1467
1468 if (!hw) {
1469 return;
1470 }
1471 pll = to_rockchip_clk_pll(hw);
1472 if (!pll->boost_enabled) {
1473 return;
1474 }
1475
1476 regmap_write(pll->boost, BOOST_BOOST_CON, HIWORD_UPDATE(0, BOOST_RECOVERY_MASK, BOOST_RECOVERY_SHIFT));
1477 regmap_write(pll->boost, BOOST_BOOST_CON, HIWORD_UPDATE(0, BOOST_SW_CTRL_MASK, BOOST_SW_CTRL_SHIFT));
1478 }
1479
rockchip_boost_add_core_div(struct clk_hw * hw,unsigned long prate)1480 void rockchip_boost_add_core_div(struct clk_hw *hw, unsigned long prate)
1481 {
1482 struct rockchip_clk_pll *pll;
1483 unsigned int div;
1484
1485 if (!hw) {
1486 return;
1487 }
1488 pll = to_rockchip_clk_pll(hw);
1489 if (!pll->boost_enabled || pll->boost_backup_pll_rate == prate) {
1490 return;
1491 }
1492
1493 /* todo */
1494 if (pll->boost_backup_pll_usage == BOOST_BACKUP_PLL_USAGE_TARGET) {
1495 return;
1496 }
1497 /*
1498 * cpu clock rate should be less than or equal to
1499 * low rate when change pll rate in boost module
1500 */
1501 if (pll->boost_low_rate && prate > pll->boost_low_rate) {
1502 div = DIV_ROUND_UP(prate, pll->boost_low_rate) - 1;
1503 regmap_write(pll->boost, BOOST_CLK_CON, HIWORD_UPDATE(div, BOOST_CORE_DIV_MASK, BOOST_CORE_DIV_SHIFT));
1504 pll->boost_backup_pll_rate = prate;
1505 }
1506 }
1507
1508 #ifdef CONFIG_DEBUG_FS
1509 #include <linux/debugfs.h>
1510
1511 #ifndef MODULE
boost_summary_show(struct seq_file * s,void * data)1512 static int boost_summary_show(struct seq_file *s, void *data)
1513 {
1514 struct rockchip_clk_pll *pll = (struct rockchip_clk_pll *)s->private;
1515 u32 boost_count = 0;
1516 u32 freq_cnt0 = 0, freq_cnt1 = 0;
1517 u64 freq_cnt = 0, high_freq_time = 0;
1518 u32 short_count = 0, short_threshold = 0;
1519 u32 interval_time = 0;
1520
1521 seq_puts(
1522 s, " device boost_count high_freq_count high_freq_time short_count short_threshold interval_count\n");
1523 seq_puts(
1524 s, "------------------------------------------------------------------------------------------------------\n");
1525 seq_printf(s, " %s\n", clk_hw_get_name(&pll->hw));
1526
1527 regmap_read(pll->boost, BOOST_SWITCH_CNT, &boost_count);
1528
1529 regmap_read(pll->boost, BOOST_HIGH_PERF_CNT0, &freq_cnt0);
1530 regmap_read(pll->boost, BOOST_HIGH_PERF_CNT1, &freq_cnt1);
1531 freq_cnt = ((u64)freq_cnt1 << 0x20) + (u64)freq_cnt0;
1532 high_freq_time = freq_cnt;
1533 do_div(high_freq_time, 0x18);
1534
1535 regmap_read(pll->boost, BOOST_SHORT_SWITCH_CNT, &short_count);
1536 regmap_read(pll->boost, BOOST_STATIS_THRESHOLD, &short_threshold);
1537 regmap_read(pll->boost, BOOST_SWITCH_THRESHOLD, &interval_time);
1538
1539 seq_printf(s, "%22u %17llu %15llu %12u %16u %15u\n", boost_count, freq_cnt, high_freq_time, short_count,
1540 short_threshold, interval_time);
1541
1542 return 0;
1543 }
1544
boost_summary_open(struct inode * inode,struct file * file)1545 static int boost_summary_open(struct inode *inode, struct file *file)
1546 {
1547 return single_open(file, boost_summary_show, inode->i_private);
1548 }
1549
1550 static const struct file_operations boost_summary_fops = {
1551 .open = boost_summary_open,
1552 .read = seq_read,
1553 .llseek = seq_lseek,
1554 .release = single_release,
1555 };
1556
boost_config_show(struct seq_file * s,void * data)1557 static int boost_config_show(struct seq_file *s, void *data)
1558 {
1559 struct rockchip_clk_pll *pll = (struct rockchip_clk_pll *)s->private;
1560
1561 seq_printf(s, "boost_enabled: %d\n", pll->boost_enabled);
1562 seq_printf(s, "boost_low_rate: %lu\n", pll->boost_low_rate);
1563 seq_printf(s, "boost_high_rate: %lu\n", pll->boost_high_rate);
1564
1565 return 0;
1566 }
1567
boost_config_open(struct inode * inode,struct file * file)1568 static int boost_config_open(struct inode *inode, struct file *file)
1569 {
1570 return single_open(file, boost_config_show, inode->i_private);
1571 }
1572
1573 static const struct file_operations boost_config_fops = {
1574 .open = boost_config_open,
1575 .read = seq_read,
1576 .llseek = seq_lseek,
1577 .release = single_release,
1578 };
1579
boost_debug_create_one(struct rockchip_clk_pll * pll,struct dentry * rootdir)1580 static int boost_debug_create_one(struct rockchip_clk_pll *pll, struct dentry *rootdir)
1581 {
1582 struct dentry *pdentry, *d;
1583
1584 pdentry = debugfs_lookup(clk_hw_get_name(&pll->hw), rootdir);
1585 if (!pdentry) {
1586 pr_err("%s: failed to lookup %s dentry\n", __func__, clk_hw_get_name(&pll->hw));
1587 return -ENOMEM;
1588 }
1589
1590 d = debugfs_create_file("boost_summary", BOOTST_FILE_READ, pdentry, pll, &boost_summary_fops);
1591 if (!d) {
1592 pr_err("%s: failed to create boost_summary file\n", __func__);
1593 return -ENOMEM;
1594 }
1595
1596 d = debugfs_create_file("boost_config", BOOTST_FILE_READ, pdentry, pll, &boost_config_fops);
1597 if (!d) {
1598 pr_err("%s: failed to create boost config file\n", __func__);
1599 return -ENOMEM;
1600 }
1601
1602 return 0;
1603 }
1604
boost_debug_init(void)1605 static int __init boost_debug_init(void)
1606 {
1607 struct rockchip_clk_pll *pll;
1608 struct dentry *rootdir;
1609
1610 rootdir = debugfs_lookup("clk", NULL);
1611 if (!rootdir) {
1612 pr_err("%s: failed to lookup clk dentry\n", __func__);
1613 return -ENOMEM;
1614 }
1615
1616 mutex_lock(&clk_boost_lock);
1617
1618 hlist_for_each_entry(pll, &clk_boost_list, debug_node) boost_debug_create_one(pll, rootdir);
1619
1620 mutex_unlock(&clk_boost_lock);
1621
1622 return 0;
1623 }
1624 late_initcall(boost_debug_init);
1625 #endif /* MODULE */
1626 #endif /* CONFIG_DEBUG_FS */
1627