xref: /freebsd/sys/dev/clk/rockchip/rk3399_pmucru.c (revision fe75646a0234a261c0013bf1840fdac4acaf0cec)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2018 Emmanuel Vadot <manu@freebsd.org>
5  * Copyright (c) 2018 Val Packett <val@packett.cool>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/bus.h>
32 #include <sys/rman.h>
33 #include <sys/kernel.h>
34 #include <sys/module.h>
35 #include <machine/bus.h>
36 
37 #include <dev/fdt/simplebus.h>
38 
39 #include <dev/ofw/ofw_bus.h>
40 #include <dev/ofw/ofw_bus_subr.h>
41 
42 #include <dev/extres/clk/clk_div.h>
43 #include <dev/extres/clk/clk_fixed.h>
44 #include <dev/extres/clk/clk_mux.h>
45 
46 #include <dev/clk/rockchip/rk_cru.h>
47 
48 #define	CRU_CLKSEL_CON(x)	(0x80 + (x) * 0x4)
49 #define	CRU_CLKGATE_CON(x)	(0x100 + (x) * 0x4)
50 
51 #define	PLL_PPLL		1
52 #define	SCLK_32K_SUSPEND_PMU	2
53 #define	SCLK_SPI3_PMU		3
54 #define	SCLK_TIMER12_PMU	4
55 #define	SCLK_TIMER13_PMU	5
56 #define	SCLK_UART4_PMU		6
57 #define	SCLK_PVTM_PMU		7
58 #define	SCLK_WIFI_PMU		8
59 #define	SCLK_I2C0_PMU		9
60 #define	SCLK_I2C4_PMU		10
61 #define	SCLK_I2C8_PMU		11
62 
63 #define	PCLK_PMU_SRC		19
64 #define	PCLK_PMU		20
65 #define	PCLK_PMUGRF_PMU		21
66 #define	PCLK_INTMEM1_PMU	22
67 #define	PCLK_GPIO0_PMU		23
68 #define	PCLK_GPIO1_PMU		24
69 #define	PCLK_SGRF_PMU		25
70 #define	PCLK_NOC_PMU		26
71 #define	PCLK_I2C0_PMU		27
72 #define	PCLK_I2C4_PMU		28
73 #define	PCLK_I2C8_PMU		29
74 #define	PCLK_RKPWM_PMU		30
75 #define	PCLK_SPI3_PMU		31
76 #define	PCLK_TIMER_PMU		32
77 #define	PCLK_MAILBOX_PMU	33
78 #define	PCLK_UART4_PMU		34
79 #define	PCLK_WDT_M0_PMU		35
80 
81 #define	FCLK_CM0S_SRC_PMU	44
82 #define	FCLK_CM0S_PMU		45
83 #define	SCLK_CM0S_PMU		46
84 #define	HCLK_CM0S_PMU		47
85 #define	DCLK_CM0S_PMU		48
86 #define	PCLK_INTR_ARB_PMU	49
87 #define	HCLK_NOC_PMU		50
88 
89 /* GATES */
90 static struct rk_cru_gate rk3399_pmu_gates[] = {
91 	/* PMUCRU_CLKGATE_CON0 */
92 	/* 0 Reserved */
93 	/* 1 fclk_cm0s_pmu_ppll_src_en */
94 	GATE(SCLK_SPI3_PMU, "clk_spi3_pmu", "clk_spi3_c", 0, 2),
95 	GATE(SCLK_TIMER12_PMU, "clk_timer0_pmu", "clk_timer_sel", 0, 3),
96 	GATE(SCLK_TIMER13_PMU, "clk_timer1_pmu", "clk_timer_sel", 0, 4),
97 	GATE(SCLK_UART4_PMU, "clk_uart4_pmu", "clk_uart4_sel", 0, 5),
98 	GATE(0, "clk_uart4_frac", "clk_uart4_frac_frac", 0, 6),
99 	/* 7 clk_pvtm_pmu_en */
100 	GATE(SCLK_WIFI_PMU, "clk_wifi_pmu", "clk_wifi_sel", 0, 8),
101 	GATE(SCLK_I2C0_PMU, "clk_i2c0_src", "clk_i2c0_div", 0, 9),
102 	GATE(SCLK_I2C4_PMU, "clk_i2c4_src", "clk_i2c4_div", 0, 10),
103 	GATE(SCLK_I2C8_PMU, "clk_i2c8_src", "clk_i2c8_div", 0, 11),
104 	/* 12:15 Reserved */
105 
106 	/* PMUCRU_CLKGATE_CON1 */
107 	GATE(PCLK_PMU, "pclk_pmu", "pclk_pmu_src", 1, 0),
108 	/* 1 pclk_pmugrf_en */
109 	/* 2 pclk_intmem1_en */
110 	GATE(PCLK_GPIO0_PMU, "pclk_gpio0_pmu", "pclk_pmu_src", 1, 3),
111 	GATE(PCLK_GPIO1_PMU, "pclk_gpio1_pmu", "pclk_pmu_src", 1, 4),
112 	/* 5 pclk_sgrf_en */
113 	/* 6 pclk_noc_pmu_en */
114 	GATE(PCLK_I2C0_PMU, "pclk_i2c0_pmu", "pclk_pmu_src", 1, 7),
115 	GATE(PCLK_I2C4_PMU, "pclk_i2c4_pmu", "pclk_pmu_src", 1, 8),
116 	GATE(PCLK_I2C8_PMU, "pclk_i2c8_pmu", "pclk_pmu_src", 1, 9),
117 	GATE(PCLK_RKPWM_PMU, "pclk_rkpwm_pmu", "pclk_pmu_src", 1, 10),
118 	GATE(PCLK_SPI3_PMU, "pclk_spi3_pmu", "pclk_pmu_src", 1, 11),
119 	GATE(PCLK_TIMER_PMU, "pclk_timer_pmu", "pclk_pmu_src", 1, 12),
120 	GATE(PCLK_MAILBOX_PMU, "pclk_mailbox_pmu", "pclk_pmu_src", 1, 13),
121 	/* 14 pclk_uartm0_en */
122 	/* 15 pclk_wdt_m0_pmu_en */
123 
124 	/* PMUCRU_CLKGATE_CON2 */
125 	/* 0 fclk_cm0s_en */
126 	/* 1 sclk_cm0s_en */
127 	/* 2 hclk_cm0s_en */
128 	/* 3 dclk_cm0s_en */
129 	/* 4 Reserved */
130 	/* 5 hclk_noc_pmu_en */
131 	/* 6:15 Reserved */
132 };
133 
134 /*
135  * PLLs
136  */
137 
138 static struct rk_clk_pll_rate rk3399_pll_rates[] = {
139 	{
140 		.freq = 2208000000,
141 		.refdiv = 1,
142 		.fbdiv = 92,
143 		.postdiv1 = 1,
144 		.postdiv2 = 1,
145 		.dsmpd = 1,
146 	},
147 	{
148 		.freq = 2184000000,
149 		.refdiv = 1,
150 		.fbdiv = 91,
151 		.postdiv1 = 1,
152 		.postdiv2 = 1,
153 		.dsmpd = 1,
154 	},
155 	{
156 		.freq = 2160000000,
157 		.refdiv = 1,
158 		.fbdiv = 90,
159 		.postdiv1 = 1,
160 		.postdiv2 = 1,
161 		.dsmpd = 1,
162 	},
163 	{
164 		.freq = 2136000000,
165 		.refdiv = 1,
166 		.fbdiv = 89,
167 		.postdiv1 = 1,
168 		.postdiv2 = 1,
169 		.dsmpd = 1,
170 	},
171 	{
172 		.freq = 2112000000,
173 		.refdiv = 1,
174 		.fbdiv = 88,
175 		.postdiv1 = 1,
176 		.postdiv2 = 1,
177 		.dsmpd = 1,
178 	},
179 	{
180 		.freq = 2088000000,
181 		.refdiv = 1,
182 		.fbdiv = 87,
183 		.postdiv1 = 1,
184 		.postdiv2 = 1,
185 		.dsmpd = 1,
186 	},
187 	{
188 		.freq = 2064000000,
189 		.refdiv = 1,
190 		.fbdiv = 86,
191 		.postdiv1 = 1,
192 		.postdiv2 = 1,
193 		.dsmpd = 1,
194 	},
195 	{
196 		.freq = 2040000000,
197 		.refdiv = 1,
198 		.fbdiv = 85,
199 		.postdiv1 = 1,
200 		.postdiv2 = 1,
201 		.dsmpd = 1,
202 	},
203 	{
204 		.freq = 2016000000,
205 		.refdiv = 1,
206 		.fbdiv = 84,
207 		.postdiv1 = 1,
208 		.postdiv2 = 1,
209 		.dsmpd = 1,
210 	},
211 	{
212 		.freq = 1992000000,
213 		.refdiv = 1,
214 		.fbdiv = 83,
215 		.postdiv1 = 1,
216 		.postdiv2 = 1,
217 		.dsmpd = 1,
218 	},
219 	{
220 		.freq = 1968000000,
221 		.refdiv = 1,
222 		.fbdiv = 82,
223 		.postdiv1 = 1,
224 		.postdiv2 = 1,
225 		.dsmpd = 1,
226 	},
227 	{
228 		.freq = 1944000000,
229 		.refdiv = 1,
230 		.fbdiv = 81,
231 		.postdiv1 = 1,
232 		.postdiv2 = 1,
233 		.dsmpd = 1,
234 	},
235 	{
236 		.freq = 1920000000,
237 		.refdiv = 1,
238 		.fbdiv = 80,
239 		.postdiv1 = 1,
240 		.postdiv2 = 1,
241 		.dsmpd = 1,
242 	},
243 	{
244 		.freq = 1896000000,
245 		.refdiv = 1,
246 		.fbdiv = 79,
247 		.postdiv1 = 1,
248 		.postdiv2 = 1,
249 		.dsmpd = 1,
250 	},
251 	{
252 		.freq = 1872000000,
253 		.refdiv = 1,
254 		.fbdiv = 78,
255 		.postdiv1 = 1,
256 		.postdiv2 = 1,
257 		.dsmpd = 1,
258 	},
259 	{
260 		.freq = 1848000000,
261 		.refdiv = 1,
262 		.fbdiv = 77,
263 		.postdiv1 = 1,
264 		.postdiv2 = 1,
265 		.dsmpd = 1,
266 	},
267 	{
268 		.freq = 1824000000,
269 		.refdiv = 1,
270 		.fbdiv = 76,
271 		.postdiv1 = 1,
272 		.postdiv2 = 1,
273 		.dsmpd = 1,
274 	},
275 	{
276 		.freq = 1800000000,
277 		.refdiv = 1,
278 		.fbdiv = 75,
279 		.postdiv1 = 1,
280 		.postdiv2 = 1,
281 		.dsmpd = 1,
282 	},
283 	{
284 		.freq = 1776000000,
285 		.refdiv = 1,
286 		.fbdiv = 74,
287 		.postdiv1 = 1,
288 		.postdiv2 = 1,
289 		.dsmpd = 1,
290 	},
291 	{
292 		.freq = 1752000000,
293 		.refdiv = 1,
294 		.fbdiv = 73,
295 		.postdiv1 = 1,
296 		.postdiv2 = 1,
297 		.dsmpd = 1,
298 	},
299 	{
300 		.freq = 1728000000,
301 		.refdiv = 1,
302 		.fbdiv = 72,
303 		.postdiv1 = 1,
304 		.postdiv2 = 1,
305 		.dsmpd = 1,
306 	},
307 	{
308 		.freq = 1704000000,
309 		.refdiv = 1,
310 		.fbdiv = 71,
311 		.postdiv1 = 1,
312 		.postdiv2 = 1,
313 		.dsmpd = 1,
314 	},
315 	{
316 		.freq = 1680000000,
317 		.refdiv = 1,
318 		.fbdiv = 70,
319 		.postdiv1 = 1,
320 		.postdiv2 = 1,
321 		.dsmpd = 1,
322 	},
323 	{
324 		.freq = 1656000000,
325 		.refdiv = 1,
326 		.fbdiv = 69,
327 		.postdiv1 = 1,
328 		.postdiv2 = 1,
329 		.dsmpd = 1,
330 	},
331 	{
332 		.freq = 1632000000,
333 		.refdiv = 1,
334 		.fbdiv = 68,
335 		.postdiv1 = 1,
336 		.postdiv2 = 1,
337 		.dsmpd = 1,
338 	},
339 	{
340 		.freq = 1608000000,
341 		.refdiv = 1,
342 		.fbdiv = 67,
343 		.postdiv1 = 1,
344 		.postdiv2 = 1,
345 		.dsmpd = 1,
346 	},
347 	{
348 		.freq = 1600000000,
349 		.refdiv = 3,
350 		.fbdiv = 200,
351 		.postdiv1 = 1,
352 		.postdiv2 = 1,
353 		.dsmpd = 1,
354 	},
355 	{
356 		.freq = 1584000000,
357 		.refdiv = 1,
358 		.fbdiv = 66,
359 		.postdiv1 = 1,
360 		.postdiv2 = 1,
361 		.dsmpd = 1,
362 	},
363 	{
364 		.freq = 1560000000,
365 		.refdiv = 1,
366 		.fbdiv = 65,
367 		.postdiv1 = 1,
368 		.postdiv2 = 1,
369 		.dsmpd = 1,
370 	},
371 	{
372 		.freq = 1536000000,
373 		.refdiv = 1,
374 		.fbdiv = 64,
375 		.postdiv1 = 1,
376 		.postdiv2 = 1,
377 		.dsmpd = 1,
378 	},
379 	{
380 		.freq = 1512000000,
381 		.refdiv = 1,
382 		.fbdiv = 63,
383 		.postdiv1 = 1,
384 		.postdiv2 = 1,
385 		.dsmpd = 1,
386 	},
387 	{
388 		.freq = 1488000000,
389 		.refdiv = 1,
390 		.fbdiv = 62,
391 		.postdiv1 = 1,
392 		.postdiv2 = 1,
393 		.dsmpd = 1,
394 	},
395 	{
396 		.freq = 1464000000,
397 		.refdiv = 1,
398 		.fbdiv = 61,
399 		.postdiv1 = 1,
400 		.postdiv2 = 1,
401 		.dsmpd = 1,
402 	},
403 	{
404 		.freq = 1440000000,
405 		.refdiv = 1,
406 		.fbdiv = 60,
407 		.postdiv1 = 1,
408 		.postdiv2 = 1,
409 		.dsmpd = 1,
410 	},
411 	{
412 		.freq = 1416000000,
413 		.refdiv = 1,
414 		.fbdiv = 59,
415 		.postdiv1 = 1,
416 		.postdiv2 = 1,
417 		.dsmpd = 1,
418 	},
419 	{
420 		.freq = 1392000000,
421 		.refdiv = 1,
422 		.fbdiv = 58,
423 		.postdiv1 = 1,
424 		.postdiv2 = 1,
425 		.dsmpd = 1,
426 	},
427 	{
428 		.freq = 1368000000,
429 		.refdiv = 1,
430 		.fbdiv = 57,
431 		.postdiv1 = 1,
432 		.postdiv2 = 1,
433 		.dsmpd = 1,
434 	},
435 	{
436 		.freq = 1344000000,
437 		.refdiv = 1,
438 		.fbdiv = 56,
439 		.postdiv1 = 1,
440 		.postdiv2 = 1,
441 		.dsmpd = 1,
442 	},
443 	{
444 		.freq = 1320000000,
445 		.refdiv = 1,
446 		.fbdiv = 55,
447 		.postdiv1 = 1,
448 		.postdiv2 = 1,
449 		.dsmpd = 1,
450 	},
451 	{
452 		.freq = 1296000000,
453 		.refdiv = 1,
454 		.fbdiv = 54,
455 		.postdiv1 = 1,
456 		.postdiv2 = 1,
457 		.dsmpd = 1,
458 	},
459 	{
460 		.freq = 1272000000,
461 		.refdiv = 1,
462 		.fbdiv = 53,
463 		.postdiv1 = 1,
464 		.postdiv2 = 1,
465 		.dsmpd = 1,
466 	},
467 	{
468 		.freq = 1248000000,
469 		.refdiv = 1,
470 		.fbdiv = 52,
471 		.postdiv1 = 1,
472 		.postdiv2 = 1,
473 		.dsmpd = 1,
474 	},
475 	{
476 		.freq = 1200000000,
477 		.refdiv = 1,
478 		.fbdiv = 50,
479 		.postdiv1 = 1,
480 		.postdiv2 = 1,
481 		.dsmpd = 1,
482 	},
483 	{
484 		.freq = 1188000000,
485 		.refdiv = 2,
486 		.fbdiv = 99,
487 		.postdiv1 = 1,
488 		.postdiv2 = 1,
489 		.dsmpd = 1,
490 	},
491 	{
492 		.freq = 1104000000,
493 		.refdiv = 1,
494 		.fbdiv = 46,
495 		.postdiv1 = 1,
496 		.postdiv2 = 1,
497 		.dsmpd = 1,
498 	},
499 	{
500 		.freq = 1100000000,
501 		.refdiv = 12,
502 		.fbdiv = 550,
503 		.postdiv1 = 1,
504 		.postdiv2 = 1,
505 		.dsmpd = 1,
506 	},
507 	{
508 		.freq = 1008000000,
509 		.refdiv = 1,
510 		.fbdiv = 84,
511 		.postdiv1 = 2,
512 		.postdiv2 = 1,
513 		.dsmpd = 1,
514 	},
515 	{
516 		.freq = 1000000000,
517 		.refdiv = 1,
518 		.fbdiv = 125,
519 		.postdiv1 = 3,
520 		.postdiv2 = 1,
521 		.dsmpd = 1,
522 	},
523 	{
524 		.freq = 984000000,
525 		.refdiv = 1,
526 		.fbdiv = 82,
527 		.postdiv1 = 2,
528 		.postdiv2 = 1,
529 		.dsmpd = 1,
530 	},
531 	{
532 		.freq = 960000000,
533 		.refdiv = 1,
534 		.fbdiv = 80,
535 		.postdiv1 = 2,
536 		.postdiv2 = 1,
537 		.dsmpd = 1,
538 	},
539 	{
540 		.freq = 936000000,
541 		.refdiv = 1,
542 		.fbdiv = 78,
543 		.postdiv1 = 2,
544 		.postdiv2 = 1,
545 		.dsmpd = 1,
546 	},
547 	{
548 		.freq = 912000000,
549 		.refdiv = 1,
550 		.fbdiv = 76,
551 		.postdiv1 = 2,
552 		.postdiv2 = 1,
553 		.dsmpd = 1,
554 	},
555 	{
556 		.freq = 900000000,
557 		.refdiv = 4,
558 		.fbdiv = 300,
559 		.postdiv1 = 2,
560 		.postdiv2 = 1,
561 		.dsmpd = 1,
562 	},
563 	{
564 		.freq = 888000000,
565 		.refdiv = 1,
566 		.fbdiv = 74,
567 		.postdiv1 = 2,
568 		.postdiv2 = 1,
569 		.dsmpd = 1,
570 	},
571 	{
572 		.freq = 864000000,
573 		.refdiv = 1,
574 		.fbdiv = 72,
575 		.postdiv1 = 2,
576 		.postdiv2 = 1,
577 		.dsmpd = 1,
578 	},
579 	{
580 		.freq = 840000000,
581 		.refdiv = 1,
582 		.fbdiv = 70,
583 		.postdiv1 = 2,
584 		.postdiv2 = 1,
585 		.dsmpd = 1,
586 	},
587 	{
588 		.freq = 816000000,
589 		.refdiv = 1,
590 		.fbdiv = 68,
591 		.postdiv1 = 2,
592 		.postdiv2 = 1,
593 		.dsmpd = 1,
594 	},
595 	{
596 		.freq = 800000000,
597 		.refdiv = 1,
598 		.fbdiv = 100,
599 		.postdiv1 = 3,
600 		.postdiv2 = 1,
601 		.dsmpd = 1,
602 	},
603 	{
604 		.freq = 700000000,
605 		.refdiv = 6,
606 		.fbdiv = 350,
607 		.postdiv1 = 2,
608 		.postdiv2 = 1,
609 		.dsmpd = 1,
610 	},
611 	{
612 		.freq = 696000000,
613 		.refdiv = 1,
614 		.fbdiv = 58,
615 		.postdiv1 = 2,
616 		.postdiv2 = 1,
617 		.dsmpd = 1,
618 	},
619 	{
620 		.freq = 676000000,
621 		.refdiv = 3,
622 		.fbdiv = 169,
623 		.postdiv1 = 2,
624 		.postdiv2 = 1,
625 		.dsmpd = 1,
626 	},
627 	{
628 		.freq = 600000000,
629 		.refdiv = 1,
630 		.fbdiv = 75,
631 		.postdiv1 = 3,
632 		.postdiv2 = 1,
633 		.dsmpd = 1,
634 	},
635 	{
636 		.freq = 594000000,
637 		.refdiv = 1,
638 		.fbdiv = 99,
639 		.postdiv1 = 4,
640 		.postdiv2 = 1,
641 		.dsmpd = 1,
642 	},
643 	{
644 		.freq = 533250000,
645 		.refdiv = 8,
646 		.fbdiv = 711,
647 		.postdiv1 = 4,
648 		.postdiv2 = 1,
649 		.dsmpd = 1,
650 	},
651 	{
652 		.freq = 504000000,
653 		.refdiv = 1,
654 		.fbdiv = 63,
655 		.postdiv1 = 3,
656 		.postdiv2 = 1,
657 		.dsmpd = 1,
658 	},
659 	{
660 		.freq = 500000000,
661 		.refdiv = 6,
662 		.fbdiv = 250,
663 		.postdiv1 = 2,
664 		.postdiv2 = 1,
665 		.dsmpd = 1,
666 	},
667 	{
668 		.freq = 408000000,
669 		.refdiv = 1,
670 		.fbdiv = 68,
671 		.postdiv1 = 2,
672 		.postdiv2 = 2,
673 		.dsmpd = 1,
674 	},
675 	{
676 		.freq = 312000000,
677 		.refdiv = 1,
678 		.fbdiv = 52,
679 		.postdiv1 = 2,
680 		.postdiv2 = 2,
681 		.dsmpd = 1,
682 	},
683 	{
684 		.freq = 297000000,
685 		.refdiv = 1,
686 		.fbdiv = 99,
687 		.postdiv1 = 4,
688 		.postdiv2 = 2,
689 		.dsmpd = 1,
690 	},
691 	{
692 		.freq = 216000000,
693 		.refdiv = 1,
694 		.fbdiv = 72,
695 		.postdiv1 = 4,
696 		.postdiv2 = 2,
697 		.dsmpd = 1,
698 	},
699 	{
700 		.freq = 148500000,
701 		.refdiv = 1,
702 		.fbdiv = 99,
703 		.postdiv1 = 4,
704 		.postdiv2 = 4,
705 		.dsmpd = 1,
706 	},
707 	{
708 		.freq = 106500000,
709 		.refdiv = 1,
710 		.fbdiv = 71,
711 		.postdiv1 = 4,
712 		.postdiv2 = 4,
713 		.dsmpd = 1,
714 	},
715 	{
716 		.freq = 96000000,
717 		.refdiv = 1,
718 		.fbdiv = 64,
719 		.postdiv1 = 4,
720 		.postdiv2 = 4,
721 		.dsmpd = 1,
722 	},
723 	{
724 		.freq = 74250000,
725 		.refdiv = 2,
726 		.fbdiv = 99,
727 		.postdiv1 = 4,
728 		.postdiv2 = 4,
729 		.dsmpd = 1,
730 	},
731 	{
732 		.freq = 65000000,
733 		.refdiv = 1,
734 		.fbdiv = 65,
735 		.postdiv1 = 6,
736 		.postdiv2 = 4,
737 		.dsmpd = 1,
738 	},
739 	{
740 		.freq = 54000000,
741 		.refdiv = 1,
742 		.fbdiv = 54,
743 		.postdiv1 = 6,
744 		.postdiv2 = 4,
745 		.dsmpd = 1,
746 	},
747 	{
748 		.freq = 27000000,
749 		.refdiv = 1,
750 		.fbdiv = 27,
751 		.postdiv1 = 6,
752 		.postdiv2 = 4,
753 		.dsmpd = 1,
754 	},
755 	{},
756 };
757 
758 PLIST(xin24m_p) = {"xin24m"};
759 PLIST(xin24m_xin32k_p) = {"xin24m", "xin32k"};
760 PLIST(xin24m_ppll_p) = {"xin24m", "ppll"};
761 PLIST(uart4_p) = {"clk_uart4_c", "clk_uart4_frac", "xin24m"};
762 PLIST(wifi_p) = {"clk_wifi_c", "clk_wifi_frac"};
763 
764 static struct rk_clk_pll_def ppll = {
765 	.clkdef = {
766 		.id = PLL_PPLL,
767 		.name = "ppll",
768 		.parent_names = xin24m_p,
769 		.parent_cnt = nitems(xin24m_p),
770 	},
771 	.base_offset = 0x00,
772 
773 	.rates = rk3399_pll_rates,
774 };
775 
776 static struct rk_clk rk3399_pmu_clks[] = {
777 	/* Linked clocks */
778 	LINK("xin32k"),
779 
780 	{
781 		.type = RK3399_CLK_PLL,
782 		.clk.pll = &ppll
783 	},
784 
785 	/* PMUCRU_CLKSEL_CON0 */
786 	CDIV(PCLK_PMU_SRC, "pclk_pmu_src", "ppll", 0, 0, 0, 5),
787 	/* 5:7 Reserved */
788 	/* 8:12 cm0s_div */
789 	/* 13:14 Reserved */
790 	/* 15 cm0s_clk_pll_sel */
791 
792 	/* PMUCRU_CLKSEL_CON1 */
793 	COMP(0, "clk_spi3_c", xin24m_ppll_p, 0, 1, 0, 7, 7, 1),
794 	COMP(0, "clk_wifi_c", xin24m_ppll_p, 0, 1, 8, 5, 13, 1),
795 	MUX(0, "clk_wifi_sel", wifi_p, 0, 1, 14, 1),
796 	MUX(0, "clk_timer_sel", xin24m_xin32k_p, 0, 1, 15, 1),
797 
798 	/* PMUCRU_CLKSEL_CON2 */
799 	CDIV(0, "clk_i2c0_div", "ppll", 0, 2, 0, 7),
800 	/* 7 Reserved */
801 	CDIV(0, "clk_i2c8_div", "ppll", 0, 2, 8, 7),
802 	/* 15 Reserved */
803 
804 	/* PMUCRU_CLKSEL_CON3 */
805 	CDIV(0, "clk_i2c4_div", "ppll", 0, 3, 0, 7),
806 	/* 7:15 Reserved */
807 
808 	/* PMUCRU_CLKSEL_CON4 */
809 	/* 0:9 clk_32k_suspend_div */
810 	/* 10:14 Reserved */
811 	/* 15 clk_32k_suspend_sel */
812 
813 	/* PMUCRU_CLKSEL_CON5 */
814 	COMP(0, "clk_uart4_c", xin24m_ppll_p, 0, 5, 0, 7, 10, 1),
815 	/* 7 Reserved */
816 	MUX(0, "clk_uart4_sel", uart4_p, 0, 5, 8, 2),
817 	/* 11:15 Reserved */
818 
819 	/* PMUCRU_CLKFRAC_CON0 / PMUCRU_CLKSEL_CON6 */
820 	FRACT(0, "clk_uart4_frac_frac", "clk_uart4_sel", 0, 6),
821 
822 	/* PMUCRU_CLKFRAC_CON1 / PMUCRU_CLKSEL_CON7 */
823 	FRACT(0, "clk_wifi_frac", "clk_wifi_c", 0, 7),
824 };
825 
826 static int
827 rk3399_pmucru_probe(device_t dev)
828 {
829 
830 	if (!ofw_bus_status_okay(dev))
831 		return (ENXIO);
832 
833 	if (ofw_bus_is_compatible(dev, "rockchip,rk3399-pmucru")) {
834 		device_set_desc(dev, "Rockchip RK3399 PMU Clock and Reset Unit");
835 		return (BUS_PROBE_DEFAULT);
836 	}
837 
838 	return (ENXIO);
839 }
840 
841 static int
842 rk3399_pmucru_attach(device_t dev)
843 {
844 	struct rk_cru_softc *sc;
845 
846 	sc = device_get_softc(dev);
847 	sc->dev = dev;
848 
849 	sc->gates = rk3399_pmu_gates;
850 	sc->ngates = nitems(rk3399_pmu_gates);
851 
852 	sc->clks = rk3399_pmu_clks;
853 	sc->nclks = nitems(rk3399_pmu_clks);
854 
855 	sc->reset_offset = 0x110;
856 	sc->reset_num = 30;
857 
858 	return (rk_cru_attach(dev));
859 }
860 
861 static device_method_t rk3399_pmucru_methods[] = {
862 	/* Device interface */
863 	DEVMETHOD(device_probe,		rk3399_pmucru_probe),
864 	DEVMETHOD(device_attach,	rk3399_pmucru_attach),
865 
866 	DEVMETHOD_END
867 };
868 
869 DEFINE_CLASS_1(rk3399_pmucru, rk3399_pmucru_driver, rk3399_pmucru_methods,
870   sizeof(struct rk_cru_softc), rk_cru_driver);
871 
872 EARLY_DRIVER_MODULE(rk3399_pmucru, simplebus, rk3399_pmucru_driver, 0, 0,
873     BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
874