1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2018 Emmanuel Vadot <[email protected]>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
20 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
22 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include <sys/cdefs.h>
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/bus.h>
32
33 #include <dev/extres/clk/clk.h>
34
35 #include <arm64/rockchip/clk/rk_clk_pll.h>
36
37 #include "clkdev_if.h"
38
39 struct rk_clk_pll_sc {
40 uint32_t base_offset;
41
42 uint32_t gate_offset;
43 uint32_t gate_shift;
44
45 uint32_t mode_reg;
46 uint32_t mode_shift;
47
48 uint32_t flags;
49
50 struct rk_clk_pll_rate *rates;
51 struct rk_clk_pll_rate *frac_rates;
52 };
53
54 #define WRITE4(_clk, off, val) \
55 CLKDEV_WRITE_4(clknode_get_device(_clk), off, val)
56 #define READ4(_clk, off, val) \
57 CLKDEV_READ_4(clknode_get_device(_clk), off, val)
58 #define DEVICE_LOCK(_clk) \
59 CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))
60 #define DEVICE_UNLOCK(_clk) \
61 CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
62
63 #define RK_CLK_PLL_MASK_SHIFT 16
64
65 #if 0
66 #define dprintf(format, arg...) \
67 printf("%s:(%s)" format, __func__, clknode_get_name(clk), arg)
68 #else
69 #define dprintf(format, arg...)
70 #endif
71
72 static int
rk_clk_pll_set_gate(struct clknode * clk,bool enable)73 rk_clk_pll_set_gate(struct clknode *clk, bool enable)
74 {
75 struct rk_clk_pll_sc *sc;
76 uint32_t val = 0;
77
78 sc = clknode_get_softc(clk);
79
80 if ((sc->flags & RK_CLK_PLL_HAVE_GATE) == 0)
81 return (0);
82
83 dprintf("%sabling gate\n", enable ? "En" : "Dis");
84 if (!enable)
85 val |= 1 << sc->gate_shift;
86 dprintf("sc->gate_shift: %x\n", sc->gate_shift);
87 val |= (1 << sc->gate_shift) << RK_CLK_PLL_MASK_SHIFT;
88 dprintf("Write: gate_offset=%x, val=%x\n", sc->gate_offset, val);
89 DEVICE_LOCK(clk);
90 WRITE4(clk, sc->gate_offset, val);
91 DEVICE_UNLOCK(clk);
92
93 return (0);
94 }
95
96 /* CON0 */
97 #define RK3066_CLK_PLL_REFDIV_SHIFT 8
98 #define RK3066_CLK_PLL_REFDIV_MASK 0x3F00
99 #define RK3066_CLK_PLL_POSTDIV_SHIFT 0
100 #define RK3066_CLK_PLL_POSTDIV_MASK 0x000F
101 /* CON1 */
102 #define RK3066_CLK_PLL_LOCK_MASK (1U << 31)
103 #define RK3066_CLK_PLL_FBDIV_SHIFT 0
104 #define RK3066_CLK_PLL_FBDIV_MASK 0x0FFF
105 /* CON2 */
106
107 /* CON3 */
108 #define RK3066_CLK_PLL_RESET (1 << 5)
109 #define RK3066_CLK_PLL_TEST (1 << 4)
110 #define RK3066_CLK_PLL_ENSAT (1 << 3)
111 #define RK3066_CLK_PLL_FASTEN (1 << 2)
112 #define RK3066_CLK_PLL_POWER_DOWN (1 << 1)
113 #define RK3066_CLK_PLL_BYPASS (1 << 0)
114
115 #define RK3066_CLK_PLL_MODE_SLOW 0
116 #define RK3066_CLK_PLL_MODE_NORMAL 1
117 #define RK3066_CLK_PLL_MODE_DEEP_SLOW 2
118 #define RK3066_CLK_PLL_MODE_MASK 0x3
119
120 static int
rk3066_clk_pll_init(struct clknode * clk,device_t dev)121 rk3066_clk_pll_init(struct clknode *clk, device_t dev)
122 {
123 struct rk_clk_pll_sc *sc;
124 uint32_t reg;
125
126 sc = clknode_get_softc(clk);
127
128 DEVICE_LOCK(clk);
129 READ4(clk, sc->mode_reg, ®);
130 DEVICE_UNLOCK(clk);
131
132 reg = (reg >> sc->mode_shift) & RK3066_CLK_PLL_MODE_MASK;
133 clknode_init_parent_idx(clk, reg);
134
135 return (0);
136 }
137
138 static int
rk3066_clk_pll_set_mux(struct clknode * clk,int idx)139 rk3066_clk_pll_set_mux(struct clknode *clk, int idx)
140 {
141 uint32_t reg;
142 struct rk_clk_pll_sc *sc;
143
144 sc = clknode_get_softc(clk);
145
146 reg = (idx & RK3066_CLK_PLL_MODE_MASK) << sc->mode_shift;
147 reg |= (RK3066_CLK_PLL_MODE_MASK << sc->mode_shift) <<
148 RK_CLK_PLL_MASK_SHIFT;
149
150 DEVICE_LOCK(clk);
151 WRITE4(clk, sc->mode_reg, reg);
152 DEVICE_UNLOCK(clk);
153 return(0);
154 }
155
156 static int
rk3066_clk_pll_recalc(struct clknode * clk,uint64_t * freq)157 rk3066_clk_pll_recalc(struct clknode *clk, uint64_t *freq)
158 {
159 struct rk_clk_pll_sc *sc;
160 uint64_t rate;
161 uint32_t refdiv, fbdiv, postdiv;
162 uint32_t raw0, raw1, raw2, reg;
163
164 sc = clknode_get_softc(clk);
165
166 DEVICE_LOCK(clk);
167
168 READ4(clk, sc->base_offset, &raw0);
169 READ4(clk, sc->base_offset + 4, &raw1);
170 READ4(clk, sc->base_offset + 8, &raw2);
171 READ4(clk, sc->mode_reg, ®);
172
173 DEVICE_UNLOCK(clk);
174
175 reg = (reg >> sc->mode_shift) & RK3066_CLK_PLL_MODE_MASK;
176
177 if (reg != RK3066_CLK_PLL_MODE_NORMAL)
178 return (0);
179
180 if (!(raw1 & RK3066_CLK_PLL_LOCK_MASK)) {
181 *freq = 0;
182 return (0);
183 }
184
185 /* TODO MUX */
186 refdiv = (raw0 & RK3066_CLK_PLL_REFDIV_MASK) >>
187 RK3066_CLK_PLL_REFDIV_SHIFT;
188 refdiv += 1;
189 postdiv = (raw0 & RK3066_CLK_PLL_POSTDIV_MASK) >>
190 RK3066_CLK_PLL_POSTDIV_SHIFT;
191 postdiv += 1;
192 fbdiv = (raw1 & RK3066_CLK_PLL_FBDIV_MASK) >>
193 RK3066_CLK_PLL_FBDIV_SHIFT;
194 fbdiv += 1;
195
196 rate = *freq * fbdiv;
197 rate /= refdiv;
198 *freq = rate / postdiv;
199
200 return (0);
201 }
202
203 static int
rk3066_clk_pll_set_freq(struct clknode * clk,uint64_t fparent,uint64_t * fout,int flags,int * stop)204 rk3066_clk_pll_set_freq(struct clknode *clk, uint64_t fparent, uint64_t *fout,
205 int flags, int *stop)
206 {
207 struct rk_clk_pll_rate *rates;
208 struct rk_clk_pll_sc *sc;
209 uint32_t reg;
210 int rv, timeout;
211
212 sc = clknode_get_softc(clk);
213
214 if (sc->rates == NULL)
215 return (EINVAL);
216
217 for (rates = sc->rates; rates->freq; rates++) {
218 if (rates->freq == *fout)
219 break;
220 }
221 if (rates->freq == 0) {
222 *stop = 1;
223 return (EINVAL);
224 }
225
226 DEVICE_LOCK(clk);
227
228 /* Setting to slow mode during frequency change */
229 reg = (RK3066_CLK_PLL_MODE_MASK << sc->mode_shift) <<
230 RK_CLK_PLL_MASK_SHIFT;
231 dprintf("Set PLL_MODEREG to %x\n", reg);
232 WRITE4(clk, sc->mode_reg, reg);
233
234 /* Reset PLL */
235 WRITE4(clk, sc->base_offset + 12, RK3066_CLK_PLL_RESET |
236 RK3066_CLK_PLL_RESET << RK_CLK_PLL_MASK_SHIFT);
237
238 /* Setting postdiv and refdiv */
239 reg = 0;
240 reg |= RK3066_CLK_PLL_POSTDIV_MASK << 16;
241 reg |= (rates->postdiv1 - 1) << RK3066_CLK_PLL_POSTDIV_SHIFT;
242
243 reg |= RK3066_CLK_PLL_REFDIV_MASK << 16;
244 reg |= (rates->refdiv - 1)<< RK3066_CLK_PLL_REFDIV_SHIFT;
245
246 dprintf("Set PLL_CON0 to %x\n", reg);
247 WRITE4(clk, sc->base_offset, reg);
248
249
250 /* Setting fbdiv (no write mask)*/
251 READ4(clk, sc->base_offset + 4, ®);
252 reg &= ~RK3066_CLK_PLL_FBDIV_MASK;
253 reg |= RK3066_CLK_PLL_FBDIV_MASK << 16;
254 reg = (rates->fbdiv - 1) << RK3066_CLK_PLL_FBDIV_SHIFT;
255
256 dprintf("Set PLL_CON1 to %x\n", reg);
257 WRITE4(clk, sc->base_offset + 0x4, reg);
258
259 /* PLL loop bandwidth adjust */
260 reg = rates->bwadj - 1;
261 dprintf("Set PLL_CON2 to %x (%x)\n", reg, rates->bwadj);
262 WRITE4(clk, sc->base_offset + 0x8, reg);
263
264 /* Clear reset */
265 WRITE4(clk, sc->base_offset + 12,
266 RK3066_CLK_PLL_RESET << RK_CLK_PLL_MASK_SHIFT);
267 DELAY(100000);
268
269 /* Reading lock */
270 for (timeout = 1000; timeout >= 0; timeout--) {
271 READ4(clk, sc->base_offset + 0x4, ®);
272 if ((reg & RK3066_CLK_PLL_LOCK_MASK) != 0)
273 break;
274 DELAY(1);
275 }
276
277 rv = 0;
278 if (timeout < 0) {
279 device_printf(clknode_get_device(clk),
280 "%s - Timedout while waiting for lock.\n",
281 clknode_get_name(clk));
282 dprintf("PLL_CON1: %x\n", reg);
283 rv = ETIMEDOUT;
284 }
285
286 /* Set back to normal mode */
287 reg = (RK3066_CLK_PLL_MODE_NORMAL << sc->mode_shift);
288 reg |= (RK3066_CLK_PLL_MODE_MASK << sc->mode_shift) <<
289 RK_CLK_PLL_MASK_SHIFT;
290 dprintf("Set PLL_MODEREG to %x\n", reg);
291 WRITE4(clk, sc->mode_reg, reg);
292
293 DEVICE_UNLOCK(clk);
294 *stop = 1;
295 rv = clknode_set_parent_by_idx(clk, 1);
296 return (rv);
297 }
298
299 static clknode_method_t rk3066_clk_pll_clknode_methods[] = {
300 /* Device interface */
301 CLKNODEMETHOD(clknode_init, rk3066_clk_pll_init),
302 CLKNODEMETHOD(clknode_set_gate, rk_clk_pll_set_gate),
303 CLKNODEMETHOD(clknode_recalc_freq, rk3066_clk_pll_recalc),
304 CLKNODEMETHOD(clknode_set_freq, rk3066_clk_pll_set_freq),
305 CLKNODEMETHOD(clknode_set_mux, rk3066_clk_pll_set_mux),
306 CLKNODEMETHOD_END
307 };
308
309 DEFINE_CLASS_1(rk3066_clk_pll_clknode, rk3066_clk_pll_clknode_class,
310 rk3066_clk_pll_clknode_methods, sizeof(struct rk_clk_pll_sc), clknode_class);
311
312 int
rk3066_clk_pll_register(struct clkdom * clkdom,struct rk_clk_pll_def * clkdef)313 rk3066_clk_pll_register(struct clkdom *clkdom, struct rk_clk_pll_def *clkdef)
314 {
315 struct clknode *clk;
316 struct rk_clk_pll_sc *sc;
317
318 clk = clknode_create(clkdom, &rk3066_clk_pll_clknode_class,
319 &clkdef->clkdef);
320 if (clk == NULL)
321 return (1);
322
323 sc = clknode_get_softc(clk);
324
325 sc->base_offset = clkdef->base_offset;
326 sc->gate_offset = clkdef->gate_offset;
327 sc->gate_shift = clkdef->gate_shift;
328 sc->mode_reg = clkdef->mode_reg;
329 sc->mode_shift = clkdef->mode_shift;
330 sc->flags = clkdef->flags;
331 sc->rates = clkdef->rates;
332 sc->frac_rates = clkdef->frac_rates;
333
334 clknode_register(clkdom, clk);
335
336 return (0);
337 }
338
339 #define RK3328_CLK_PLL_FBDIV_OFFSET 0
340 #define RK3328_CLK_PLL_FBDIV_SHIFT 0
341 #define RK3328_CLK_PLL_FBDIV_MASK 0xFFF
342
343 #define RK3328_CLK_PLL_POSTDIV1_OFFSET 0
344 #define RK3328_CLK_PLL_POSTDIV1_SHIFT 12
345 #define RK3328_CLK_PLL_POSTDIV1_MASK 0x7000
346
347 #define RK3328_CLK_PLL_DSMPD_OFFSET 4
348 #define RK3328_CLK_PLL_DSMPD_SHIFT 12
349 #define RK3328_CLK_PLL_DSMPD_MASK 0x1000
350
351 #define RK3328_CLK_PLL_REFDIV_OFFSET 4
352 #define RK3328_CLK_PLL_REFDIV_SHIFT 0
353 #define RK3328_CLK_PLL_REFDIV_MASK 0x3F
354
355 #define RK3328_CLK_PLL_POSTDIV2_OFFSET 4
356 #define RK3328_CLK_PLL_POSTDIV2_SHIFT 6
357 #define RK3328_CLK_PLL_POSTDIV2_MASK 0x1C0
358
359 #define RK3328_CLK_PLL_FRAC_OFFSET 8
360 #define RK3328_CLK_PLL_FRAC_SHIFT 0
361 #define RK3328_CLK_PLL_FRAC_MASK 0xFFFFFF
362
363 #define RK3328_CLK_PLL_LOCK_MASK 0x400
364
365 #define RK3328_CLK_PLL_MODE_SLOW 0
366 #define RK3328_CLK_PLL_MODE_NORMAL 1
367 #define RK3328_CLK_PLL_MODE_MASK 0x1
368
369 static int
rk3328_clk_pll_init(struct clknode * clk,device_t dev)370 rk3328_clk_pll_init(struct clknode *clk, device_t dev)
371 {
372 clknode_init_parent_idx(clk, 0);
373
374 return (0);
375 }
376
377 static int
rk3328_clk_pll_recalc(struct clknode * clk,uint64_t * freq)378 rk3328_clk_pll_recalc(struct clknode *clk, uint64_t *freq)
379 {
380 struct rk_clk_pll_sc *sc;
381 uint64_t rate;
382 uint32_t dsmpd, refdiv, fbdiv;
383 uint32_t postdiv1, postdiv2, frac;
384 uint32_t raw1, raw2, raw3;
385
386 sc = clknode_get_softc(clk);
387
388 DEVICE_LOCK(clk);
389
390 READ4(clk, sc->base_offset, &raw1);
391 READ4(clk, sc->base_offset + 4, &raw2);
392 READ4(clk, sc->base_offset + 8, &raw3);
393
394 fbdiv = (raw1 & RK3328_CLK_PLL_FBDIV_MASK) >> RK3328_CLK_PLL_FBDIV_SHIFT;
395 postdiv1 = (raw1 & RK3328_CLK_PLL_POSTDIV1_MASK) >> RK3328_CLK_PLL_POSTDIV1_SHIFT;
396
397 dsmpd = (raw2 & RK3328_CLK_PLL_DSMPD_MASK) >> RK3328_CLK_PLL_DSMPD_SHIFT;
398 refdiv = (raw2 & RK3328_CLK_PLL_REFDIV_MASK) >> RK3328_CLK_PLL_REFDIV_SHIFT;
399 postdiv2 = (raw2 & RK3328_CLK_PLL_POSTDIV2_MASK) >> RK3328_CLK_PLL_POSTDIV2_SHIFT;
400
401 frac = (raw3 & RK3328_CLK_PLL_FRAC_MASK) >> RK3328_CLK_PLL_FRAC_SHIFT;
402
403 DEVICE_UNLOCK(clk);
404
405 rate = *freq * fbdiv / refdiv;
406 if (dsmpd == 0) {
407 /* Fractional mode */
408 uint64_t frac_rate;
409
410 frac_rate = *freq * frac / refdiv;
411 rate += frac_rate >> 24;
412 }
413
414 *freq = rate / postdiv1 / postdiv2;
415
416 if (*freq % 2)
417 *freq = *freq + 1;
418
419 return (0);
420 }
421
422 static int
rk3328_clk_pll_set_freq(struct clknode * clk,uint64_t fparent,uint64_t * fout,int flags,int * stop)423 rk3328_clk_pll_set_freq(struct clknode *clk, uint64_t fparent, uint64_t *fout,
424 int flags, int *stop)
425 {
426 struct rk_clk_pll_rate *rates;
427 struct rk_clk_pll_sc *sc;
428 uint32_t reg;
429 int timeout;
430
431 sc = clknode_get_softc(clk);
432
433 if (sc->rates)
434 rates = sc->rates;
435 else if (sc->frac_rates)
436 rates = sc->frac_rates;
437 else
438 return (EINVAL);
439
440 for (; rates->freq; rates++) {
441 if (rates->freq == *fout)
442 break;
443 }
444 if (rates->freq == 0) {
445 *stop = 1;
446 return (EINVAL);
447 }
448
449 DEVICE_LOCK(clk);
450
451 /* Setting to slow mode during frequency change */
452 reg = (RK3328_CLK_PLL_MODE_MASK << sc->mode_shift) <<
453 RK_CLK_PLL_MASK_SHIFT;
454 dprintf("Set PLL_MODEREG to %x\n", reg);
455 WRITE4(clk, sc->mode_reg, reg);
456
457 /* Setting postdiv1 and fbdiv */
458 reg = (rates->postdiv1 << RK3328_CLK_PLL_POSTDIV1_SHIFT) |
459 (rates->fbdiv << RK3328_CLK_PLL_FBDIV_SHIFT);
460 reg |= (RK3328_CLK_PLL_POSTDIV1_MASK | RK3328_CLK_PLL_FBDIV_MASK) << 16;
461 dprintf("Set PLL_CON0 to %x\n", reg);
462 WRITE4(clk, sc->base_offset, reg);
463
464 /* Setting dsmpd, postdiv2 and refdiv */
465 reg = (rates->dsmpd << RK3328_CLK_PLL_DSMPD_SHIFT) |
466 (rates->postdiv2 << RK3328_CLK_PLL_POSTDIV2_SHIFT) |
467 (rates->refdiv << RK3328_CLK_PLL_REFDIV_SHIFT);
468 reg |= (RK3328_CLK_PLL_DSMPD_MASK |
469 RK3328_CLK_PLL_POSTDIV2_MASK |
470 RK3328_CLK_PLL_REFDIV_MASK) << RK_CLK_PLL_MASK_SHIFT;
471 dprintf("Set PLL_CON1 to %x\n", reg);
472 WRITE4(clk, sc->base_offset + 0x4, reg);
473
474 /* Setting frac */
475 READ4(clk, sc->base_offset + 0x8, ®);
476 reg &= ~RK3328_CLK_PLL_FRAC_MASK;
477 reg |= rates->frac << RK3328_CLK_PLL_FRAC_SHIFT;
478 dprintf("Set PLL_CON2 to %x\n", reg);
479 WRITE4(clk, sc->base_offset + 0x8, reg);
480
481 /* Reading lock */
482 for (timeout = 1000; timeout; timeout--) {
483 READ4(clk, sc->base_offset + 0x4, ®);
484 if ((reg & RK3328_CLK_PLL_LOCK_MASK) == 0)
485 break;
486 DELAY(1);
487 }
488
489 /* Set back to normal mode */
490 reg = (RK3328_CLK_PLL_MODE_NORMAL << sc->mode_shift);
491 reg |= (RK3328_CLK_PLL_MODE_MASK << sc->mode_shift) <<
492 RK_CLK_PLL_MASK_SHIFT;
493 dprintf("Set PLL_MODEREG to %x\n", reg);
494 WRITE4(clk, sc->mode_reg, reg);
495
496 DEVICE_UNLOCK(clk);
497
498 *stop = 1;
499 return (0);
500 }
501
502 static clknode_method_t rk3328_clk_pll_clknode_methods[] = {
503 /* Device interface */
504 CLKNODEMETHOD(clknode_init, rk3328_clk_pll_init),
505 CLKNODEMETHOD(clknode_set_gate, rk_clk_pll_set_gate),
506 CLKNODEMETHOD(clknode_recalc_freq, rk3328_clk_pll_recalc),
507 CLKNODEMETHOD(clknode_set_freq, rk3328_clk_pll_set_freq),
508 CLKNODEMETHOD_END
509 };
510
511 DEFINE_CLASS_1(rk3328_clk_pll_clknode, rk3328_clk_pll_clknode_class,
512 rk3328_clk_pll_clknode_methods, sizeof(struct rk_clk_pll_sc), clknode_class);
513
514 int
rk3328_clk_pll_register(struct clkdom * clkdom,struct rk_clk_pll_def * clkdef)515 rk3328_clk_pll_register(struct clkdom *clkdom, struct rk_clk_pll_def *clkdef)
516 {
517 struct clknode *clk;
518 struct rk_clk_pll_sc *sc;
519
520 clk = clknode_create(clkdom, &rk3328_clk_pll_clknode_class,
521 &clkdef->clkdef);
522 if (clk == NULL)
523 return (1);
524
525 sc = clknode_get_softc(clk);
526
527 sc->base_offset = clkdef->base_offset;
528 sc->gate_offset = clkdef->gate_offset;
529 sc->gate_shift = clkdef->gate_shift;
530 sc->mode_reg = clkdef->mode_reg;
531 sc->mode_shift = clkdef->mode_shift;
532 sc->flags = clkdef->flags;
533 sc->rates = clkdef->rates;
534 sc->frac_rates = clkdef->frac_rates;
535
536 clknode_register(clkdom, clk);
537
538 return (0);
539 }
540
541 #define RK3399_CLK_PLL_FBDIV_OFFSET 0
542 #define RK3399_CLK_PLL_FBDIV_SHIFT 0
543 #define RK3399_CLK_PLL_FBDIV_MASK 0xFFF
544
545 #define RK3399_CLK_PLL_POSTDIV2_OFFSET 4
546 #define RK3399_CLK_PLL_POSTDIV2_SHIFT 12
547 #define RK3399_CLK_PLL_POSTDIV2_MASK 0x7000
548
549 #define RK3399_CLK_PLL_POSTDIV1_OFFSET 4
550 #define RK3399_CLK_PLL_POSTDIV1_SHIFT 8
551 #define RK3399_CLK_PLL_POSTDIV1_MASK 0x700
552
553 #define RK3399_CLK_PLL_REFDIV_OFFSET 4
554 #define RK3399_CLK_PLL_REFDIV_SHIFT 0
555 #define RK3399_CLK_PLL_REFDIV_MASK 0x3F
556
557 #define RK3399_CLK_PLL_FRAC_OFFSET 8
558 #define RK3399_CLK_PLL_FRAC_SHIFT 0
559 #define RK3399_CLK_PLL_FRAC_MASK 0xFFFFFF
560
561 #define RK3399_CLK_PLL_DSMPD_OFFSET 0xC
562 #define RK3399_CLK_PLL_DSMPD_SHIFT 3
563 #define RK3399_CLK_PLL_DSMPD_MASK 0x8
564
565 #define RK3399_CLK_PLL_LOCK_OFFSET 8
566 #define RK3399_CLK_PLL_LOCK_MASK 0x400
567
568 #define RK3399_CLK_PLL_MODE_OFFSET 0xC
569 #define RK3399_CLK_PLL_MODE_MASK 0x300
570 #define RK3399_CLK_PLL_MODE_SLOW 0
571 #define RK3399_CLK_PLL_MODE_NORMAL 1
572 #define RK3399_CLK_PLL_MODE_DEEPSLOW 2
573 #define RK3399_CLK_PLL_MODE_SHIFT 8
574
575 #define RK3399_CLK_PLL_WRITE_MASK 0xFFFF0000
576
577 static int
rk3399_clk_pll_init(struct clknode * clk,device_t dev)578 rk3399_clk_pll_init(struct clknode *clk, device_t dev)
579 {
580 clknode_init_parent_idx(clk, 0);
581
582 return (0);
583 }
584
585 static int
rk3399_clk_pll_recalc(struct clknode * clk,uint64_t * freq)586 rk3399_clk_pll_recalc(struct clknode *clk, uint64_t *freq)
587 {
588 struct rk_clk_pll_sc *sc;
589 uint32_t dsmpd, refdiv, fbdiv;
590 uint32_t postdiv1, postdiv2, fracdiv;
591 uint32_t con1, con2, con3, con4;
592 uint64_t foutvco;
593 uint32_t mode;
594 sc = clknode_get_softc(clk);
595
596 DEVICE_LOCK(clk);
597 READ4(clk, sc->base_offset, &con1);
598 READ4(clk, sc->base_offset + 4, &con2);
599 READ4(clk, sc->base_offset + 8, &con3);
600 READ4(clk, sc->base_offset + 0xC, &con4);
601 DEVICE_UNLOCK(clk);
602
603 /*
604 * if we are in slow mode the output freq
605 * is the parent one, the 24Mhz external oscillator
606 * if we are in deep mode the output freq is 32.768khz
607 */
608 mode = (con4 & RK3399_CLK_PLL_MODE_MASK) >> RK3399_CLK_PLL_MODE_SHIFT;
609 if (mode == RK3399_CLK_PLL_MODE_SLOW) {
610 dprintf("pll in slow mode, con4=%x\n", con4);
611 return (0);
612 } else if (mode == RK3399_CLK_PLL_MODE_DEEPSLOW) {
613 dprintf("pll in deep slow, con4=%x\n", con4);
614 *freq = 32768;
615 return (0);
616 }
617
618 dprintf("con0: %x\n", con1);
619 dprintf("con1: %x\n", con2);
620 dprintf("con2: %x\n", con3);
621 dprintf("con3: %x\n", con4);
622
623 fbdiv = (con1 & RK3399_CLK_PLL_FBDIV_MASK)
624 >> RK3399_CLK_PLL_FBDIV_SHIFT;
625
626 postdiv1 = (con2 & RK3399_CLK_PLL_POSTDIV1_MASK)
627 >> RK3399_CLK_PLL_POSTDIV1_SHIFT;
628 postdiv2 = (con2 & RK3399_CLK_PLL_POSTDIV2_MASK)
629 >> RK3399_CLK_PLL_POSTDIV2_SHIFT;
630 refdiv = (con2 & RK3399_CLK_PLL_REFDIV_MASK)
631 >> RK3399_CLK_PLL_REFDIV_SHIFT;
632
633 fracdiv = (con3 & RK3399_CLK_PLL_FRAC_MASK)
634 >> RK3399_CLK_PLL_FRAC_SHIFT;
635 fracdiv >>= 24;
636
637 dsmpd = (con4 & RK3399_CLK_PLL_DSMPD_MASK) >> RK3399_CLK_PLL_DSMPD_SHIFT;
638
639 dprintf("fbdiv: %d\n", fbdiv);
640 dprintf("postdiv1: %d\n", postdiv1);
641 dprintf("postdiv2: %d\n", postdiv2);
642 dprintf("refdiv: %d\n", refdiv);
643 dprintf("fracdiv: %d\n", fracdiv);
644 dprintf("dsmpd: %d\n", dsmpd);
645
646 dprintf("parent freq=%ju\n", *freq);
647
648 if (dsmpd == 0) {
649 /* Fractional mode */
650 foutvco = *freq / refdiv * (fbdiv + fracdiv);
651 } else {
652 /* Integer mode */
653 foutvco = *freq / refdiv * fbdiv;
654 }
655 dprintf("foutvco: %ju\n", foutvco);
656
657 *freq = foutvco / postdiv1 / postdiv2;
658 dprintf("freq: %ju\n", *freq);
659
660 return (0);
661 }
662
663 static int
rk3399_clk_pll_set_freq(struct clknode * clk,uint64_t fparent,uint64_t * fout,int flags,int * stop)664 rk3399_clk_pll_set_freq(struct clknode *clk, uint64_t fparent, uint64_t *fout,
665 int flags, int *stop)
666 {
667 struct rk_clk_pll_rate *rates;
668 struct rk_clk_pll_sc *sc;
669 uint32_t reg;
670 int timeout;
671
672 sc = clknode_get_softc(clk);
673
674 if (sc->rates)
675 rates = sc->rates;
676 else if (sc->frac_rates)
677 rates = sc->frac_rates;
678 else
679 return (EINVAL);
680
681 for (; rates->freq; rates++) {
682 if (rates->freq == *fout)
683 break;
684 }
685 if (rates->freq == 0) {
686 *stop = 1;
687 return (EINVAL);
688 }
689
690 DEVICE_LOCK(clk);
691
692 /* Set to slow mode during frequency change */
693 reg = RK3399_CLK_PLL_MODE_SLOW << RK3399_CLK_PLL_MODE_SHIFT;
694 reg |= RK3399_CLK_PLL_MODE_MASK << RK_CLK_PLL_MASK_SHIFT;
695 WRITE4(clk, sc->base_offset + 0xC, reg);
696
697 /* Setting fbdiv */
698 reg = rates->fbdiv << RK3399_CLK_PLL_FBDIV_SHIFT;
699 reg |= RK3399_CLK_PLL_FBDIV_MASK << RK_CLK_PLL_MASK_SHIFT;
700 WRITE4(clk, sc->base_offset, reg);
701
702 /* Setting postdiv1, postdiv2 and refdiv */
703 reg = rates->postdiv1 << RK3399_CLK_PLL_POSTDIV1_SHIFT;
704 reg |= rates->postdiv2 << RK3399_CLK_PLL_POSTDIV2_SHIFT;
705 reg |= rates->refdiv << RK3399_CLK_PLL_REFDIV_SHIFT;
706 reg |= (RK3399_CLK_PLL_POSTDIV1_MASK | RK3399_CLK_PLL_POSTDIV2_MASK |
707 RK3399_CLK_PLL_REFDIV_MASK) << RK_CLK_PLL_MASK_SHIFT;
708 WRITE4(clk, sc->base_offset + 0x4, reg);
709
710 /* Setting frac */
711 READ4(clk, sc->base_offset + 0x8, ®);
712 reg &= ~RK3399_CLK_PLL_FRAC_MASK;
713 reg |= rates->frac << RK3399_CLK_PLL_FRAC_SHIFT;
714 WRITE4(clk, sc->base_offset + 0x8, reg | RK3399_CLK_PLL_WRITE_MASK);
715
716 /* Set dsmpd */
717 reg = rates->dsmpd << RK3399_CLK_PLL_DSMPD_SHIFT;
718 reg |= RK3399_CLK_PLL_DSMPD_MASK << RK_CLK_PLL_MASK_SHIFT;
719 WRITE4(clk, sc->base_offset + 0xC, reg);
720
721 /* Reading lock */
722 for (timeout = 1000; timeout; timeout--) {
723 READ4(clk, sc->base_offset + RK3399_CLK_PLL_LOCK_OFFSET, ®);
724 if ((reg & RK3399_CLK_PLL_LOCK_MASK) == 0)
725 break;
726 DELAY(1);
727 }
728
729 /* Set back to normal mode */
730 reg = RK3399_CLK_PLL_MODE_NORMAL << RK3399_CLK_PLL_MODE_SHIFT;
731 reg |= RK3399_CLK_PLL_MODE_MASK << RK_CLK_PLL_MASK_SHIFT;
732 WRITE4(clk, sc->base_offset + 0xC, reg);
733
734 DEVICE_UNLOCK(clk);
735
736 *stop = 1;
737 return (0);
738 }
739
740 static clknode_method_t rk3399_clk_pll_clknode_methods[] = {
741 /* Device interface */
742 CLKNODEMETHOD(clknode_init, rk3399_clk_pll_init),
743 CLKNODEMETHOD(clknode_set_gate, rk_clk_pll_set_gate),
744 CLKNODEMETHOD(clknode_recalc_freq, rk3399_clk_pll_recalc),
745 CLKNODEMETHOD(clknode_set_freq, rk3399_clk_pll_set_freq),
746 CLKNODEMETHOD_END
747 };
748
749 DEFINE_CLASS_1(rk3399_clk_pll_clknode, rk3399_clk_pll_clknode_class,
750 rk3399_clk_pll_clknode_methods, sizeof(struct rk_clk_pll_sc), clknode_class);
751
752 int
rk3399_clk_pll_register(struct clkdom * clkdom,struct rk_clk_pll_def * clkdef)753 rk3399_clk_pll_register(struct clkdom *clkdom, struct rk_clk_pll_def *clkdef)
754 {
755 struct clknode *clk;
756 struct rk_clk_pll_sc *sc;
757
758 clk = clknode_create(clkdom, &rk3399_clk_pll_clknode_class,
759 &clkdef->clkdef);
760 if (clk == NULL)
761 return (1);
762
763 sc = clknode_get_softc(clk);
764
765 sc->base_offset = clkdef->base_offset;
766 sc->gate_offset = clkdef->gate_offset;
767 sc->gate_shift = clkdef->gate_shift;
768 sc->flags = clkdef->flags;
769 sc->rates = clkdef->rates;
770 sc->frac_rates = clkdef->frac_rates;
771
772 clknode_register(clkdom, clk);
773
774 return (0);
775 }
776