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/clk/clk_div.h>
43#include <dev/clk/clk_fixed.h>
44#include <dev/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 */
90static 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
138static 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
758PLIST(xin24m_p) = {"xin24m"};
759PLIST(xin24m_xin32k_p) = {"xin24m", "xin32k"};
760PLIST(xin24m_ppll_p) = {"xin24m", "ppll"};
761PLIST(uart4_p) = {"clk_uart4_c", "clk_uart4_frac", "xin24m"};
762PLIST(wifi_p) = {"clk_wifi_c", "clk_wifi_frac"};
763
764static 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
776static 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
826static int
827rk3399_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
841static int
842rk3399_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
861static 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
869DEFINE_CLASS_1(rk3399_pmucru, rk3399_pmucru_driver, rk3399_pmucru_methods,
870  sizeof(struct rk_cru_softc), rk_cru_driver);
871
872EARLY_DRIVER_MODULE(rk3399_pmucru, simplebus, rk3399_pmucru_driver, 0, 0,
873    BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
874