1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2018 Emmanuel Vadot <manu@freebsd.org>
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 * $FreeBSD$
28 */
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD$");
32
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/bus.h>
36#include <sys/rman.h>
37#include <sys/kernel.h>
38#include <sys/module.h>
39#include <machine/bus.h>
40
41#include <dev/fdt/simplebus.h>
42
43#include <dev/ofw/ofw_bus.h>
44#include <dev/ofw/ofw_bus_subr.h>
45
46#include <dev/extres/clk/clk_div.h>
47#include <dev/extres/clk/clk_fixed.h>
48#include <dev/extres/clk/clk_mux.h>
49
50#include <arm64/rockchip/clk/rk_cru.h>
51
52/* Registers */
53#define	RK3328_GRF_SOC_CON4	0x410
54#define	RK3328_GRF_MAC_CON1	0x904
55#define	RK3328_GRF_MAC_CON2	0x908
56
57/* GATES */
58
59#define	SCLK_I2S0		41
60#define	SCLK_I2S1		42
61#define	SCLK_I2S2		43
62#define	SCLK_I2S1_OUT		44
63#define	SCLK_I2S2_OUT		45
64#define	SCLK_MAC2PHY_RXTX	83
65#define	SCLK_MAC2PHY_SRC	84
66#define	SCLK_MAC2PHY_REF	85
67#define	SCLK_MAC2PHY_OUT	86
68#define	SCLK_MAC2IO_RX		87
69#define	SCLK_MAC2IO_TX		88
70#define	SCLK_MAC2IO_REFOUT	89
71#define	SCLK_MAC2IO_REF		90
72#define	SCLK_MAC2IO_OUT		91
73#define	SCLK_USB3OTG_REF	96
74#define	SCLK_MAC2IO_SRC		99
75#define	SCLK_MAC2IO		100
76#define	SCLK_MAC2PHY		101
77#define	SCLK_MAC2IO_EXT		102
78#define	ACLK_USB3OTG		132
79#define ACLK_GMAC		146
80#define ACLK_MAC2PHY		149
81#define ACLK_MAC2IO		150
82#define	ACLK_PERI		153
83#define	PCLK_GPIO0		200
84#define	PCLK_GPIO1		201
85#define	PCLK_GPIO2		202
86#define	PCLK_GPIO3		203
87#define	PCLK_I2C0		205
88#define	PCLK_I2C1		206
89#define	PCLK_I2C2		207
90#define	PCLK_I2C3		208
91#define	PCLK_TSADC		213
92#define PCLK_GMAC		220
93#define PCLK_MAC2PHY		222
94#define PCLK_MAC2IO		223
95#define	PCLK_USB3PHY_OTG	224
96#define	PCLK_USB3PHY_PIPE	225
97#define	PCLK_USB3_GRF		226
98#define	PCLK_ACODECPHY		235
99#define	HCLK_I2S0_8CH		311
100#define	HCLK_I2S1_8CH		312
101#define	HCLK_I2S2_2CH		313
102#define	HCLK_SDMMC		317
103#define	HCLK_SDIO		318
104#define	HCLK_EMMC		319
105#define	HCLK_SDMMC_EXT		320
106
107static struct rk_cru_gate rk3328_gates[] = {
108	/* CRU_CLKGATE_CON0 */
109	CRU_GATE(0, "apll_core", "apll", 0x200, 0)
110	CRU_GATE(0, "dpll_core", "dpll", 0x200, 1)
111	CRU_GATE(0, "gpll_core", "gpll", 0x200, 2)
112	CRU_GATE(0, "npll_core", "npll", 0x200, 12)
113
114	/* CRU_CLKGATE_CON1 */
115	CRU_GATE(SCLK_I2S0, "clk_i2s0", "clk_i2s0_mux", 0x204, 3)
116	CRU_GATE(SCLK_I2S1, "clk_i2s1", "clk_i2s1_mux", 0x204, 6)
117	CRU_GATE(SCLK_I2S2, "clk_i2s2", "clk_i2s2_mux", 0x204, 10)
118
119	/* CRU_CLKGATE_CON4 */
120	CRU_GATE(0, "gpll_peri", "gpll", 0x210, 0)
121	CRU_GATE(0, "cpll_peri", "cpll", 0x210, 1)
122	CRU_GATE(SCLK_USB3OTG_REF, "clk_usb3otg_ref", "xin24m", 0x210, 7)
123
124	/* CRU_CLKGATE_CON8 */
125	CRU_GATE(0, "pclk_bus", "pclk_bus_pre", 0x220, 3)
126	CRU_GATE(0, "pclk_phy_pre", "pclk_bus_pre", 0x220, 4)
127
128	/* CRU_CLKGATE_CON8 */
129	CRU_GATE(SCLK_MAC2IO_REF, "clk_mac2io_ref", "clk_mac2io", 0x224, 7)
130	CRU_GATE(SCLK_MAC2IO_REFOUT, "clk_mac2io_refout", "clk_mac2io", 0x224, 6)
131	CRU_GATE(SCLK_MAC2IO_TX, "clk_mac2io_tx", "clk_mac2io", 0x224, 5)
132	CRU_GATE(SCLK_MAC2IO_RX, "clk_mac2io_rx", "clk_mac2io", 0x224, 4)
133	CRU_GATE(SCLK_MAC2PHY_REF, "clk_mac2phy_ref", "clk_mac2phy", 0x224, 3)
134	CRU_GATE(SCLK_MAC2PHY_RXTX, "clk_mac2phy_rxtx", "clk_mac2phy", 0x224, 1)
135
136	/* CRU_CLKGATE_CON10 */
137	CRU_GATE(ACLK_PERI, "aclk_peri", "aclk_peri_pre", 0x228, 0)
138
139	/* CRU_CLKGATE_CON15*/
140	CRU_GATE(HCLK_I2S0_8CH, "hclk_i2s0_8ch", "hclk_bus_pre", 0x23C, 3)
141	CRU_GATE(HCLK_I2S1_8CH, "hclk_i2s1_8ch", "hclk_bus_pre", 0x23C, 4)
142	CRU_GATE(HCLK_I2S2_2CH, "hclk_i2s2_2ch", "hclk_bus_pre", 0x23C, 5)
143	CRU_GATE(PCLK_I2C0, "pclk_i2c0", "pclk_bus", 0x23C, 10)
144
145	/* CRU_CLKGATE_CON16 */
146	CRU_GATE(PCLK_I2C1, "pclk_i2c1", "pclk_bus", 0x23C, 0)
147	CRU_GATE(PCLK_I2C2, "pclk_i2c2", "pclk_bus", 0x23C, 1)
148	CRU_GATE(PCLK_I2C3, "pclk_i2c3", "pclk_bus", 0x23C, 2)
149	CRU_GATE(PCLK_TSADC, "pclk_tsadc", "pclk_bus", 0x23C, 14)
150
151	CRU_GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_bus", 0x240, 7)
152	CRU_GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_bus", 0x240, 8)
153	CRU_GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_bus", 0x240, 9)
154	CRU_GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_bus", 0x240, 10)
155
156	/* CRU_CLKGATE_CON17 */
157	CRU_GATE(PCLK_USB3_GRF, "pclk_usb3_grf", "pclk_phy_pre", 0x244, 2)
158	CRU_GATE(PCLK_ACODECPHY, "pclk_acodecphy", "pclk_phy_pre", 0x244, 5)
159
160	/* CRU_CLKGATE_CON19 */
161	CRU_GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_peri", 0x24C, 0)
162	CRU_GATE(HCLK_SDIO, "hclk_sdio", "hclk_peri", 0x24C, 1)
163	CRU_GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 0x24C, 2)
164	CRU_GATE(0, "hclk_peri_niu", "hclk_peri", 0x24C, 12)
165	CRU_GATE(0, "pclk_peri_niu", "hclk_peri", 0x24C, 13)
166	CRU_GATE(ACLK_USB3OTG, "aclk_usb3otg", "aclk_peri", 0x24C, 14)
167	CRU_GATE(HCLK_SDMMC_EXT, "hclk_sdmmc_ext", "hclk_peri", 0x24C, 15)
168
169	/* CRU_CLKGATE_CON26 */
170	CRU_GATE(ACLK_MAC2PHY, "aclk_mac2phy", "aclk_gmac", 0x268, 0)
171	CRU_GATE(PCLK_MAC2PHY, "pclk_mac2phy", "pclk_gmac", 0x268, 1)
172	CRU_GATE(ACLK_MAC2IO, "aclk_mac2io", "aclk_gmac", 0x268, 2)
173	CRU_GATE(PCLK_MAC2IO, "pclk_mac2io", "pclk_gmac", 0x268, 3)
174
175	/* CRU_CLKGATE_CON28 */
176	CRU_GATE(PCLK_USB3PHY_OTG, "pclk_usb3phy_otg", "pclk_phy_pre", 0x270, 1)
177	CRU_GATE(PCLK_USB3PHY_PIPE, "pclk_usb3phy_pipe", "pclk_phy_pre", 0x270, 2)
178};
179
180/*
181 * PLLs
182 */
183
184#define PLL_APLL		1
185#define PLL_DPLL		2
186#define PLL_CPLL		3
187#define PLL_GPLL		4
188#define PLL_NPLL		5
189
190static struct rk_clk_pll_rate rk3328_pll_rates[] = {
191	{
192		.freq = 1608000000,
193		.refdiv = 1,
194		.fbdiv = 67,
195		.postdiv1 = 1,
196		.postdiv2 = 1,
197		.dsmpd = 1,
198	},
199	{
200		.freq = 1584000000,
201		.refdiv = 1,
202		.fbdiv = 66,
203		.postdiv1 = 1,
204		.postdiv2 = 1,
205		.dsmpd = 1,
206	},
207	{
208		.freq = 1560000000,
209		.refdiv = 1,
210		.fbdiv = 65,
211		.postdiv1 = 1,
212		.postdiv2 = 1,
213		.dsmpd = 1,
214	},
215	{
216		.freq = 1536000000,
217		.refdiv = 1,
218		.fbdiv = 64,
219		.postdiv1 = 1,
220		.postdiv2 = 1,
221		.dsmpd = 1,
222	},
223	{
224		.freq = 1512000000,
225		.refdiv = 1,
226		.fbdiv = 63,
227		.postdiv1 = 1,
228		.postdiv2 = 1,
229		.dsmpd = 1,
230	},
231	{
232		.freq = 1488000000,
233		.refdiv = 1,
234		.fbdiv = 62,
235		.postdiv1 = 1,
236		.postdiv2 = 1,
237		.dsmpd = 1,
238	},
239	{
240		.freq = 1464000000,
241		.refdiv = 1,
242		.fbdiv = 61,
243		.postdiv1 = 1,
244		.postdiv2 = 1,
245		.dsmpd = 1,
246	},
247	{
248		.freq = 1440000000,
249		.refdiv = 1,
250		.fbdiv = 60,
251		.postdiv1 = 1,
252		.postdiv2 = 1,
253		.dsmpd = 1,
254	},
255	{
256		.freq = 1416000000,
257		.refdiv = 1,
258		.fbdiv = 59,
259		.postdiv1 = 1,
260		.postdiv2 = 1,
261		.dsmpd = 1,
262	},
263	{
264		.freq = 1392000000,
265		.refdiv = 1,
266		.fbdiv = 58,
267		.postdiv1 = 1,
268		.postdiv2 = 1,
269		.dsmpd = 1,
270	},
271	{
272		.freq = 1368000000,
273		.refdiv = 1,
274		.fbdiv = 57,
275		.postdiv1 = 1,
276		.postdiv2 = 1,
277		.dsmpd = 1,
278	},
279	{
280		.freq = 1344000000,
281		.refdiv = 1,
282		.fbdiv = 56,
283		.postdiv1 = 1,
284		.postdiv2 = 1,
285		.dsmpd = 1,
286	},
287	{
288		.freq = 1320000000,
289		.refdiv = 1,
290		.fbdiv = 55,
291		.postdiv1 = 1,
292		.postdiv2 = 1,
293		.dsmpd = 1,
294	},
295	{
296		.freq = 1296000000,
297		.refdiv = 1,
298		.fbdiv = 54,
299		.postdiv1 = 1,
300		.postdiv2 = 1,
301		.dsmpd = 1,
302	},
303	{
304		.freq = 1272000000,
305		.refdiv = 1,
306		.fbdiv = 53,
307		.postdiv1 = 1,
308		.postdiv2 = 1,
309		.dsmpd = 1,
310	},
311	{
312		.freq = 1248000000,
313		.refdiv = 1,
314		.fbdiv = 52,
315		.postdiv1 = 1,
316		.postdiv2 = 1,
317		.dsmpd = 1,
318	},
319	{
320		.freq = 1200000000,
321		.refdiv = 1,
322		.fbdiv = 50,
323		.postdiv1 = 1,
324		.postdiv2 = 1,
325		.dsmpd = 1,
326	},
327	{
328		.freq = 1188000000,
329		.refdiv = 2,
330		.fbdiv = 99,
331		.postdiv1 = 1,
332		.postdiv2 = 1,
333		.dsmpd = 1,
334	},
335	{
336		.freq = 1104000000,
337		.refdiv = 1,
338		.fbdiv = 46,
339		.postdiv1 = 1,
340		.postdiv2 = 1,
341		.dsmpd = 1,
342	},
343	{
344		.freq = 1100000000,
345		.refdiv = 12,
346		.fbdiv = 550,
347		.postdiv1 = 1,
348		.postdiv2 = 1,
349		.dsmpd = 1,
350	},
351	{
352		.freq = 1008000000,
353		.refdiv = 1,
354		.fbdiv = 84,
355		.postdiv1 = 2,
356		.postdiv2 = 1,
357		.dsmpd = 1,
358	},
359	{
360		.freq = 1000000000,
361		.refdiv = 6,
362		.fbdiv = 500,
363		.postdiv1 = 2,
364		.postdiv2 = 1,
365		.dsmpd = 1,
366	},
367	{
368		.freq = 984000000,
369		.refdiv = 1,
370		.fbdiv = 82,
371		.postdiv1 = 2,
372		.postdiv2 = 1,
373		.dsmpd = 1,
374	},
375	{
376		.freq = 960000000,
377		.refdiv = 1,
378		.fbdiv = 80,
379		.postdiv1 = 2,
380		.postdiv2 = 1,
381		.dsmpd = 1,
382	},
383	{
384		.freq = 936000000,
385		.refdiv = 1,
386		.fbdiv = 78,
387		.postdiv1 = 2,
388		.postdiv2 = 1,
389		.dsmpd = 1,
390	},
391	{
392		.freq = 912000000,
393		.refdiv = 1,
394		.fbdiv = 76,
395		.postdiv1 = 2,
396		.postdiv2 = 1,
397		.dsmpd = 1,
398	},
399	{
400		.freq = 900000000,
401		.refdiv = 4,
402		.fbdiv = 300,
403		.postdiv1 = 2,
404		.postdiv2 = 1,
405		.dsmpd = 1,
406	},
407	{
408		.freq = 888000000,
409		.refdiv = 1,
410		.fbdiv = 74,
411		.postdiv1 = 2,
412		.postdiv2 = 1,
413		.dsmpd = 1,
414	},
415	{
416		.freq = 864000000,
417		.refdiv = 1,
418		.fbdiv = 72,
419		.postdiv1 = 2,
420		.postdiv2 = 1,
421		.dsmpd = 1,
422	},
423	{
424		.freq = 840000000,
425		.refdiv = 1,
426		.fbdiv = 70,
427		.postdiv1 = 2,
428		.postdiv2 = 1,
429		.dsmpd = 1,
430	},
431	{
432		.freq = 816000000,
433		.refdiv = 1,
434		.fbdiv = 68,
435		.postdiv1 = 2,
436		.postdiv2 = 1,
437		.dsmpd = 1,
438	},
439	{
440		.freq = 800000000,
441		.refdiv = 6,
442		.fbdiv = 400,
443		.postdiv1 = 2,
444		.postdiv2 = 1,
445		.dsmpd = 1,
446	},
447	{
448		.freq = 700000000,
449		.refdiv = 6,
450		.fbdiv = 350,
451		.postdiv1 = 2,
452		.postdiv2 = 1,
453		.dsmpd = 1,
454	},
455	{
456		.freq = 696000000,
457		.refdiv = 1,
458		.fbdiv = 58,
459		.postdiv1 = 2,
460		.postdiv2 = 1,
461		.dsmpd = 1,
462	},
463	{
464		.freq = 600000000,
465		.refdiv = 1,
466		.fbdiv = 75,
467		.postdiv1 = 3,
468		.postdiv2 = 1,
469		.dsmpd = 1,
470	},
471	{
472		.freq = 594000000,
473		.refdiv = 2,
474		.fbdiv = 99,
475		.postdiv1 = 2,
476		.postdiv2 = 1,
477		.dsmpd = 1,
478	},
479	{
480		.freq = 504000000,
481		.refdiv = 1,
482		.fbdiv = 63,
483		.postdiv1 = 3,
484		.postdiv2 = 1,
485		.dsmpd = 1,
486	},
487	{
488		.freq = 500000000,
489		.refdiv = 6,
490		.fbdiv = 250,
491		.postdiv1 = 2,
492		.postdiv2 = 1,
493		.dsmpd = 1,
494	},
495	{
496		.freq = 408000000,
497		.refdiv = 1,
498		.fbdiv = 68,
499		.postdiv1 = 2,
500		.postdiv2 = 2,
501		.dsmpd = 1,
502	},
503	{
504		.freq = 312000000,
505		.refdiv = 1,
506		.fbdiv = 52,
507		.postdiv1 = 2,
508		.postdiv2 = 2,
509		.dsmpd = 1,
510	},
511	{
512		.freq = 216000000,
513		.refdiv = 1,
514		.fbdiv = 72,
515		.postdiv1 = 4,
516		.postdiv2 = 2,
517		.dsmpd = 1,
518	},
519	{
520		.freq = 96000000,
521		.refdiv = 1,
522		.fbdiv = 64,
523		.postdiv1 = 4,
524		.postdiv2 = 4,
525		.dsmpd = 1,
526	},
527	{},
528};
529
530static struct rk_clk_pll_rate rk3328_pll_frac_rates[] = {
531	{
532		.freq = 1016064000,
533		.refdiv = 3,
534		.fbdiv = 127,
535		.postdiv1 = 1,
536		.postdiv2 = 1,
537		.dsmpd = 0,
538		.frac = 134217,
539	},
540	{
541		.freq = 983040000,
542		.refdiv = 24,
543		.fbdiv = 983,
544		.postdiv1 = 1,
545		.postdiv2 = 1,
546		.dsmpd = 0,
547		.frac = 671088,
548	},
549	{
550		.freq = 491520000,
551		.refdiv = 24,
552		.fbdiv = 983,
553		.postdiv1 = 2,
554		.postdiv2 = 1,
555		.dsmpd = 0,
556		.frac = 671088,
557	},
558	{
559		.freq = 61440000,
560		.refdiv = 6,
561		.fbdiv = 215,
562		.postdiv1 = 7,
563		.postdiv2 = 2,
564		.dsmpd = 0,
565		.frac = 671088,
566	},
567	{
568		.freq = 56448000,
569		.refdiv = 12,
570		.fbdiv = 451,
571		.postdiv1 = 4,
572		.postdiv2 = 4,
573		.dsmpd = 0,
574		.frac = 9797894,
575	},
576	{
577		.freq = 40960000,
578		.refdiv = 12,
579		.fbdiv = 409,
580		.postdiv1 = 4,
581		.postdiv2 = 5,
582		.dsmpd = 0,
583		.frac = 10066329,
584	},
585	{},
586};
587
588static const char *pll_parents[] = {"xin24m"};
589static struct rk_clk_pll_def apll = {
590	.clkdef = {
591		.id = PLL_APLL,
592		.name = "apll",
593		.parent_names = pll_parents,
594		.parent_cnt = nitems(pll_parents),
595	},
596	.base_offset = 0x00,
597	.gate_offset = 0x200,
598	.gate_shift = 0,
599	.mode_reg = 0x80,
600	.mode_shift = 1,
601	.flags = RK_CLK_PLL_HAVE_GATE,
602	.frac_rates = rk3328_pll_frac_rates,
603};
604
605static struct rk_clk_pll_def dpll = {
606	.clkdef = {
607		.id = PLL_DPLL,
608		.name = "dpll",
609		.parent_names = pll_parents,
610		.parent_cnt = nitems(pll_parents),
611	},
612	.base_offset = 0x20,
613	.gate_offset = 0x200,
614	.gate_shift = 1,
615	.mode_reg = 0x80,
616	.mode_shift = 4,
617	.flags = RK_CLK_PLL_HAVE_GATE,
618};
619
620static struct rk_clk_pll_def cpll = {
621	.clkdef = {
622		.id = PLL_CPLL,
623		.name = "cpll",
624		.parent_names = pll_parents,
625		.parent_cnt = nitems(pll_parents),
626	},
627	.base_offset = 0x40,
628	.mode_reg = 0x80,
629	.mode_shift = 8,
630	.rates = rk3328_pll_rates,
631};
632
633static struct rk_clk_pll_def gpll = {
634	.clkdef = {
635		.id = PLL_GPLL,
636		.name = "gpll",
637		.parent_names = pll_parents,
638		.parent_cnt = nitems(pll_parents),
639	},
640	.base_offset = 0x60,
641	.gate_offset = 0x200,
642	.gate_shift = 2,
643	.mode_reg = 0x80,
644	.mode_shift = 12,
645	.flags = RK_CLK_PLL_HAVE_GATE,
646	.frac_rates = rk3328_pll_frac_rates,
647};
648
649static struct rk_clk_pll_def npll = {
650	.clkdef = {
651		.id = PLL_NPLL,
652		.name = "npll",
653		.parent_names = pll_parents,
654		.parent_cnt = nitems(pll_parents),
655	},
656	.base_offset = 0xa0,
657	.gate_offset = 0x200,
658	.gate_shift = 12,
659	.mode_reg = 0x80,
660	.mode_shift = 1,
661	.flags = RK_CLK_PLL_HAVE_GATE,
662	.rates = rk3328_pll_rates,
663};
664
665/* CRU_CLKSEL_CON0 */
666#define ACLK_BUS_PRE		136
667
668/* Needs hdmiphy as parent too*/
669static const char *aclk_bus_pre_parents[] = {"cpll", "gpll"};
670static struct rk_clk_composite_def aclk_bus_pre = {
671	.clkdef = {
672		.id = ACLK_BUS_PRE,
673		.name = "aclk_bus_pre",
674		.parent_names = aclk_bus_pre_parents,
675		.parent_cnt = nitems(aclk_bus_pre_parents),
676	},
677	.muxdiv_offset = 0x100,
678	.mux_shift = 13,
679	.mux_width = 2,
680
681	.div_shift = 8,
682	.div_width = 5,
683
684	.gate_offset = 0x220,
685	.gate_shift = 0,
686
687	.flags = RK_CLK_COMPOSITE_HAVE_MUX | RK_CLK_COMPOSITE_HAVE_GATE,
688};
689
690static struct rk_clk_armclk_rates rk3328_armclk_rates[] = {
691	{
692		.freq = 1296000000,
693		.div = 1,
694	},
695	{
696		.freq = 1200000000,
697		.div = 1,
698	},
699	{
700		.freq = 1104000000,
701		.div = 1,
702	},
703	{
704		.freq = 1008000000,
705		.div = 1,
706	},
707	{
708		.freq = 912000000,
709		.div = 1,
710	},
711	{
712		.freq = 816000000,
713		.div = 1,
714	},
715	{
716		.freq = 696000000,
717		.div = 1,
718	},
719	{
720		.freq = 600000000,
721		.div = 1,
722	},
723	{
724		.freq = 408000000,
725		.div = 1,
726	},
727	{
728		.freq = 312000000,
729		.div = 1,
730	},
731	{
732		.freq = 216000000,
733		.div = 1,
734	},
735	{
736		.freq = 96000000,
737		.div = 1,
738	},
739};
740
741#define	ARMCLK	6
742static const char *armclk_parents[] = {"apll", "gpll", "dpll", "npll" };
743static struct rk_clk_armclk_def armclk = {
744	.clkdef = {
745		.id = ARMCLK,
746		.name = "armclk",
747		.parent_names = armclk_parents,
748		.parent_cnt = nitems(armclk_parents),
749	},
750	.muxdiv_offset = 0x100,
751	.mux_shift = 6,
752	.mux_width = 2,
753
754	.div_shift = 0,
755	.div_width = 5,
756
757	.flags = RK_CLK_COMPOSITE_HAVE_MUX,
758	.main_parent = 3, /* npll */
759	.alt_parent = 0, /* apll */
760
761	.rates = rk3328_armclk_rates,
762	.nrates = nitems(rk3328_armclk_rates),
763};
764
765/* CRU_CLKSEL_CON1 */
766
767#define PCLK_BUS_PRE		216
768#define HCLK_BUS_PRE		328
769
770static const char *hclk_bus_pre_parents[] = {"aclk_bus_pre"};
771static struct rk_clk_composite_def hclk_bus_pre = {
772	.clkdef = {
773		.id = HCLK_BUS_PRE,
774		.name = "hclk_bus_pre",
775		.parent_names = hclk_bus_pre_parents,
776		.parent_cnt = nitems(hclk_bus_pre_parents),
777	},
778	.muxdiv_offset = 0x104,
779
780	.div_shift = 8,
781	.div_width = 2,
782
783	.gate_offset = 0x220,
784	.gate_shift = 1,
785
786	.flags = RK_CLK_COMPOSITE_HAVE_GATE,
787};
788
789static const char *pclk_bus_pre_parents[] = {"aclk_bus_pre"};
790static struct rk_clk_composite_def pclk_bus_pre = {
791	.clkdef = {
792		.id = PCLK_BUS_PRE,
793		.name = "pclk_bus_pre",
794		.parent_names = pclk_bus_pre_parents,
795		.parent_cnt = nitems(pclk_bus_pre_parents),
796	},
797	.muxdiv_offset = 0x104,
798
799	.div_shift = 12,
800	.div_width = 3,
801
802	.gate_offset = 0x220,
803	.gate_shift = 2,
804
805	.flags = RK_CLK_COMPOSITE_HAVE_GATE,
806};
807
808/* CRU_CLKSEL_CON22 */
809
810#define SCLK_TSADC		36
811
812static const char *clk_tsadc_parents[] = {"xin24m"};
813static struct rk_clk_composite_def clk_tsadc = {
814	.clkdef = {
815		.id = SCLK_TSADC,
816		.name = "clk_tsadc",
817		.parent_names = clk_tsadc_parents,
818		.parent_cnt = nitems(clk_tsadc_parents),
819	},
820	.div_shift = 0,
821	.div_width = 9,
822};
823
824/* CRU_CLKSEL_CON28 */
825
826#define ACLK_PERI_PRE		137
827
828static const char *aclk_peri_pre_parents[] = {"cpll", "gpll"/* , "hdmiphy" */};
829static struct rk_clk_composite_def aclk_peri_pre = {
830	.clkdef = {
831		.id = ACLK_PERI_PRE,
832		.name = "aclk_peri_pre",
833		.parent_names = aclk_peri_pre_parents,
834		.parent_cnt = nitems(aclk_peri_pre_parents),
835	},
836	.muxdiv_offset = 0x170,
837
838	.mux_shift = 6,
839	.mux_width = 2,
840
841	.div_shift = 0,
842	.div_width = 5,
843
844	.flags = RK_CLK_COMPOSITE_HAVE_MUX,
845};
846
847/* CRU_CLKSEL_CON29 */
848
849#define PCLK_PERI		230
850#define HCLK_PERI		308
851
852static const char *phclk_peri_parents[] = {"aclk_peri_pre"};
853static struct rk_clk_composite_def pclk_peri = {
854	.clkdef = {
855		.id = PCLK_PERI,
856		.name = "pclk_peri",
857		.parent_names = phclk_peri_parents,
858		.parent_cnt = nitems(phclk_peri_parents),
859	},
860
861	.div_shift = 0,
862	.div_width = 2,
863
864	/* CRU_CLKGATE_CON10 */
865	.gate_offset = 0x228,
866	.gate_shift = 2,
867
868	.flags = RK_CLK_COMPOSITE_HAVE_GATE,
869};
870
871static struct rk_clk_composite_def hclk_peri = {
872	.clkdef = {
873		.id = HCLK_PERI,
874		.name = "hclk_peri",
875		.parent_names = phclk_peri_parents,
876		.parent_cnt = nitems(phclk_peri_parents),
877	},
878
879	.div_shift = 4,
880	.div_width = 3,
881
882	/* CRU_CLKGATE_CON10 */
883	.gate_offset = 0x228,
884	.gate_shift = 1,
885
886	.flags = RK_CLK_COMPOSITE_HAVE_GATE,
887};
888
889/* CRU_CLKSEL_CON30 */
890
891#define SCLK_SDMMC		33
892
893static const char *mmc_parents[] = {"cpll", "gpll", "xin24m"/* , "usb480m" */};
894static struct rk_clk_composite_def sdmmc = {
895	.clkdef = {
896		.id = SCLK_SDMMC,
897		.name = "clk_sdmmc",
898		.parent_names = mmc_parents,
899		.parent_cnt = nitems(mmc_parents),
900	},
901	.muxdiv_offset = 0x178,
902
903	.mux_shift = 8,
904	.mux_width = 2,
905
906	.div_shift = 0,
907	.div_width = 8,
908
909	/* CRU_CLKGATE_CON4 */
910	.gate_offset = 0x210,
911	.gate_shift = 3,
912
913	.flags = RK_CLK_COMPOSITE_HAVE_MUX | RK_CLK_COMPOSITE_HAVE_GATE,
914};
915
916/* CRU_CLKSEL_CON31 */
917#define SCLK_SDIO		34
918
919static struct rk_clk_composite_def sdio = {
920	.clkdef = {
921		.id = SCLK_SDIO,
922		.name = "clk_sdio",
923		.parent_names = mmc_parents,
924		.parent_cnt = nitems(mmc_parents),
925	},
926	.muxdiv_offset = 0x17C,
927
928	.mux_shift = 8,
929	.mux_width = 2,
930
931	.div_shift = 0,
932	.div_width = 8,
933
934	/* CRU_CLKGATE_CON4 */
935	.gate_offset = 0x210,
936	.gate_shift = 4,
937
938	.flags = RK_CLK_COMPOSITE_HAVE_MUX | RK_CLK_COMPOSITE_HAVE_GATE,
939};
940
941/* CRU_CLKSEL_CON32 */
942#define SCLK_EMMC		35
943
944static struct rk_clk_composite_def emmc = {
945	.clkdef = {
946		.id = SCLK_EMMC,
947		.name = "clk_emmc",
948		.parent_names = mmc_parents,
949		.parent_cnt = nitems(mmc_parents),
950	},
951	.muxdiv_offset = 0x180,
952
953	.mux_shift = 8,
954	.mux_width = 2,
955
956	.div_shift = 0,
957	.div_width = 8,
958
959	/* CRU_CLKGATE_CON4 */
960	.gate_offset = 0x210,
961	.gate_shift = 5,
962
963	.flags = RK_CLK_COMPOSITE_HAVE_MUX | RK_CLK_COMPOSITE_HAVE_GATE,
964};
965
966/* CRU_CLKSEL_CON34 */
967#define	SCLK_I2C0	55
968#define	SCLK_I2C1	56
969
970static const char *i2c_parents[] = {"cpll", "gpll"};
971
972static struct rk_clk_composite_def i2c0 = {
973	.clkdef = {
974		.id = SCLK_I2C0,
975		.name = "clk_i2c0",
976		.parent_names = i2c_parents,
977		.parent_cnt = nitems(i2c_parents),
978	},
979	.muxdiv_offset = 0x188,
980
981	.mux_shift = 7,
982	.mux_width = 1,
983
984	.div_shift = 0,
985	.div_width = 6,
986
987	/* CRU_CLKGATE_CON2 */
988	.gate_offset = 0x208,
989	.gate_shift = 9,
990
991	.flags = RK_CLK_COMPOSITE_HAVE_MUX | RK_CLK_COMPOSITE_HAVE_GATE,
992};
993
994static struct rk_clk_composite_def i2c1 = {
995	.clkdef = {
996		.id = SCLK_I2C1,
997		.name = "clk_i2c1",
998		.parent_names = i2c_parents,
999		.parent_cnt = nitems(i2c_parents),
1000	},
1001	.muxdiv_offset = 0x188,
1002
1003	.mux_shift = 15,
1004	.mux_width = 1,
1005
1006	.div_shift = 8,
1007	.div_width = 6,
1008
1009	/* CRU_CLKGATE_CON2 */
1010	.gate_offset = 0x208,
1011	.gate_shift = 10,
1012
1013	.flags = RK_CLK_COMPOSITE_HAVE_MUX | RK_CLK_COMPOSITE_HAVE_GATE,
1014};
1015
1016/* CRU_CLKSEL_CON35 */
1017#define	SCLK_I2C2	57
1018#define	SCLK_I2C3	58
1019
1020static struct rk_clk_composite_def i2c2 = {
1021	.clkdef = {
1022		.id = SCLK_I2C2,
1023		.name = "clk_i2c2",
1024		.parent_names = i2c_parents,
1025		.parent_cnt = nitems(i2c_parents),
1026	},
1027	.muxdiv_offset = 0x18C,
1028
1029	.mux_shift = 7,
1030	.mux_width = 1,
1031
1032	.div_shift = 0,
1033	.div_width = 6,
1034
1035	/* CRU_CLKGATE_CON2 */
1036	.gate_offset = 0x208,
1037	.gate_shift = 11,
1038
1039	.flags = RK_CLK_COMPOSITE_HAVE_MUX | RK_CLK_COMPOSITE_HAVE_GATE,
1040};
1041
1042static struct rk_clk_composite_def i2c3 = {
1043	.clkdef = {
1044		.id = SCLK_I2C3,
1045		.name = "clk_i2c3",
1046		.parent_names = i2c_parents,
1047		.parent_cnt = nitems(i2c_parents),
1048	},
1049	.muxdiv_offset = 0x18C,
1050
1051	.mux_shift = 15,
1052	.mux_width = 1,
1053
1054	.div_shift = 8,
1055	.div_width = 6,
1056
1057	/* CRU_CLKGATE_CON2 */
1058	.gate_offset = 0x208,
1059	.gate_shift = 12,
1060
1061	.flags = RK_CLK_COMPOSITE_HAVE_MUX | RK_CLK_COMPOSITE_HAVE_GATE,
1062};
1063
1064#define	SCLK_USB3_REF		72
1065#define	SCLK_USB3_SUSPEND	73
1066#define	SCLK_USB3PHY_REF	94
1067#define	SCLK_REF_USB3OTG	95
1068#define	SCLK_USB3OTG_SUSPEND	97
1069#define	SCLK_REF_USB3OTG_SRC	98
1070
1071static const char *ref_usb3otg_parents[] = { "xin24m", "clk_usb3otg_ref" };
1072
1073static struct rk_clk_composite_def ref_usb3otg = {
1074	.clkdef = {
1075		.id = SCLK_REF_USB3OTG,
1076		.name = "clk_ref_usb3otg",
1077		.parent_names = ref_usb3otg_parents,
1078		.parent_cnt = nitems(ref_usb3otg_parents),
1079	},
1080	.muxdiv_offset = 0x1B4,
1081
1082	.mux_shift = 8,
1083	.mux_width = 1,
1084
1085	.flags = RK_CLK_COMPOSITE_HAVE_MUX,
1086};
1087
1088static const char *usb3otg_suspend_parents[] = { "xin24m"/*, "clk_rtc32k" */};
1089
1090static struct rk_clk_composite_def usb3otg_suspend = {
1091	.clkdef = {
1092		.id = SCLK_USB3OTG_SUSPEND,
1093		.name = "clk_usb3otg_suspend",
1094		.parent_names = usb3otg_suspend_parents,
1095		.parent_cnt = nitems(usb3otg_suspend_parents),
1096	},
1097	.muxdiv_offset = 0x184,
1098
1099	.mux_shift = 15,
1100	.mux_width = 1,
1101
1102	.div_shift = 0,
1103	.div_width = 10,
1104
1105	/* CRU_CLKGATE_CON4 */
1106	.gate_offset = 0x210,
1107	.gate_shift = 8,
1108
1109	.flags = RK_CLK_COMPOSITE_HAVE_GATE,
1110};
1111
1112static const char *ref_usb3otg_src_parents[] = { "cpll", "gpll" };
1113
1114static struct rk_clk_composite_def ref_usb3otg_src = {
1115	.clkdef = {
1116		.id = SCLK_REF_USB3OTG_SRC,
1117		.name = "clk_ref_usb3otg_src",
1118		.parent_names = ref_usb3otg_src_parents,
1119		.parent_cnt = nitems(ref_usb3otg_src_parents),
1120	},
1121	.muxdiv_offset = 0x1B4,
1122
1123	.mux_shift = 7,
1124	.mux_width = 1,
1125
1126	.div_shift = 0,
1127	.div_width = 7,
1128
1129	/* CRU_CLKGATE_CON4 */
1130	.gate_offset = 0x210,
1131	.gate_shift = 9,
1132
1133	.flags = RK_CLK_COMPOSITE_HAVE_GATE,
1134};
1135
1136/* I2S0 */
1137static const char *i2s0_div_parents[] = { "cpll", "gpll" };
1138static struct rk_clk_composite_def i2s0_div = {
1139	.clkdef = {
1140		.id = 0,
1141		.name = "clk_i2s0_div",
1142		.parent_names = i2s0_div_parents,
1143		.parent_cnt = nitems(i2s0_div_parents),
1144	},
1145	/* CRU_CLKSEL_CON6 */
1146	.muxdiv_offset = 0x118,
1147
1148	.mux_shift = 15,
1149	.mux_width = 1,
1150
1151	.div_shift = 0,
1152	.div_width = 7,
1153
1154	/* CRU_CLKGATE_CON1 */
1155	.gate_offset = 0x204,
1156	.gate_shift = 1,
1157
1158	.flags = RK_CLK_COMPOSITE_HAVE_GATE,
1159};
1160
1161static const char *i2s0_frac_parents[] = { "clk_i2s0_div" };
1162static struct rk_clk_fract_def i2s0_frac = {
1163	.clkdef = {
1164		.id = 0,
1165		.name = "clk_i2s0_frac",
1166		.parent_names = i2s0_frac_parents,
1167		.parent_cnt = nitems(i2s0_frac_parents),
1168	},
1169	/* CRU_CLKSEL_CON7 */
1170	.offset = 0x11c,
1171
1172	/* CRU_CLKGATE_CON1 */
1173	.gate_offset = 0x204,
1174	.gate_shift = 2,
1175
1176	.flags = RK_CLK_FRACT_HAVE_GATE,
1177};
1178
1179static const char *i2s0_mux_parents[] = { "clk_i2s0_div", "clk_i2s0_frac", "xin12m", "xin12m" };
1180static struct rk_clk_mux_def i2s0_mux = {
1181	.clkdef = {
1182		.id = 0,
1183		.name = "clk_i2s0_mux",
1184		.parent_names = i2s0_mux_parents,
1185		.parent_cnt = nitems(i2s0_mux_parents),
1186	},
1187	.offset = 0x118,
1188
1189	.shift = 8,
1190	.width = 2,
1191
1192	.mux_flags = RK_CLK_MUX_REPARENT,
1193};
1194
1195/* I2S1 */
1196static const char *i2s1_div_parents[] = { "cpll", "gpll" };
1197static struct rk_clk_composite_def i2s1_div = {
1198	.clkdef = {
1199		.id = 0,
1200		.name = "clk_i2s1_div",
1201		.parent_names = i2s1_div_parents,
1202		.parent_cnt = nitems(i2s1_div_parents),
1203	},
1204	/* CRU_CLKSEL_CON8 */
1205	.muxdiv_offset = 0x120,
1206
1207	.mux_shift = 15,
1208	.mux_width = 1,
1209
1210	.div_shift = 0,
1211	.div_width = 7,
1212
1213	/* CRU_CLKGATE_CON1 */
1214	.gate_offset = 0x204,
1215	.gate_shift = 4,
1216
1217	.flags = RK_CLK_COMPOSITE_HAVE_GATE,
1218};
1219
1220static const char *i2s1_frac_parents[] = { "clk_i2s1_div" };
1221static struct rk_clk_fract_def i2s1_frac = {
1222	.clkdef = {
1223		.id = 0,
1224		.name = "clk_i2s1_frac",
1225		.parent_names = i2s1_frac_parents,
1226		.parent_cnt = nitems(i2s1_frac_parents),
1227	},
1228	/* CRU_CLKSEL_CON9 */
1229	.offset = 0x124,
1230
1231	/* CRU_CLKGATE_CON1 */
1232	.gate_offset = 0x204,
1233	.gate_shift = 5,
1234
1235	.flags = RK_CLK_FRACT_HAVE_GATE,
1236};
1237
1238static const char *i2s1_mux_parents[] = { "clk_i2s1_div", "clk_i2s1_frac", "clkin_i2s1", "xin12m" };
1239static struct rk_clk_mux_def i2s1_mux = {
1240	.clkdef = {
1241		.id = 0,
1242		.name = "clk_i2s1_mux",
1243		.parent_names = i2s1_mux_parents,
1244		.parent_cnt = nitems(i2s1_mux_parents),
1245	},
1246	.offset = 0x120,
1247
1248	.shift = 8,
1249	.width = 2,
1250	.mux_flags = RK_CLK_MUX_REPARENT,
1251};
1252
1253static struct clk_fixed_def clkin_i2s1 = {
1254	.clkdef = {
1255		.id = 0,
1256		.name = "clkin_i2s1",
1257		.parent_names = NULL,
1258		.parent_cnt = 0
1259	},
1260
1261	.freq = 0,
1262};
1263
1264/* I2S2 */
1265static const char *i2s2_div_parents[] = { "cpll", "gpll" };
1266static struct rk_clk_composite_def i2s2_div = {
1267	.clkdef = {
1268		.id = 0,
1269		.name = "clk_i2s2_div",
1270		.parent_names = i2s2_div_parents,
1271		.parent_cnt = nitems(i2s2_div_parents),
1272	},
1273	/* CRU_CLKSEL_CON10 */
1274	.muxdiv_offset = 0x128,
1275
1276	.mux_shift = 15,
1277	.mux_width = 1,
1278
1279	.div_shift = 0,
1280	.div_width = 7,
1281
1282	/* CRU_CLKGATE_CON1 */
1283	.gate_offset = 0x204,
1284	.gate_shift = 8,
1285
1286	.flags = RK_CLK_COMPOSITE_HAVE_GATE,
1287};
1288
1289static const char *i2s2_frac_parents[] = { "clk_i2s2_div" };
1290static struct rk_clk_fract_def i2s2_frac = {
1291	.clkdef = {
1292		.id = 0,
1293		.name = "clk_i2s2_frac",
1294		.parent_names = i2s2_frac_parents,
1295		.parent_cnt = nitems(i2s2_frac_parents),
1296	},
1297	/* CRU_CLKSEL_CON11 */
1298	.offset = 0x12c,
1299
1300	/* CRU_CLKGATE_CON1 */
1301	.gate_offset = 0x204,
1302	.gate_shift = 9,
1303
1304	.flags = RK_CLK_FRACT_HAVE_GATE,
1305};
1306
1307static const char *i2s2_mux_parents[] = { "clk_i2s2_div", "clk_i2s2_frac", "clkin_i2s2", "xin12m" };
1308static struct rk_clk_mux_def i2s2_mux = {
1309	.clkdef = {
1310		.id = 0,
1311		.name = "clk_i2s2_mux",
1312		.parent_names = i2s2_mux_parents,
1313		.parent_cnt = nitems(i2s2_mux_parents),
1314	},
1315	.offset = 0x128,
1316
1317	.shift = 8,
1318	.width = 2,
1319
1320	.mux_flags = RK_CLK_MUX_REPARENT,
1321};
1322
1323static struct clk_fixed_def clkin_i2s2 = {
1324	.clkdef = {
1325		.id = 0,
1326		.name = "clkin_i2s2",
1327		.parent_names = NULL,
1328		.parent_cnt = 0
1329	},
1330
1331	.freq = 0,
1332};
1333
1334static struct clk_fixed_def xin12m = {
1335	.clkdef = {
1336		.id = 0,
1337		.name = "xin12m",
1338		.parent_names = NULL,
1339		.parent_cnt = 0
1340	},
1341
1342	.freq = 12000000,
1343};
1344
1345static const char *mac2io_src_parents[] = { "cpll", "gpll" };
1346
1347static struct rk_clk_composite_def mac2io_src = {
1348	.clkdef = {
1349		.id = SCLK_MAC2IO_SRC,
1350		.name = "clk_mac2io_src",
1351		.parent_names = mac2io_src_parents,
1352		.parent_cnt = nitems(mac2io_src_parents),
1353	},
1354	/* CRU_CLKSEL_CON27 */
1355	.muxdiv_offset = 0x16c,
1356
1357	.mux_shift = 7,
1358	.mux_width = 1,
1359
1360	.div_shift = 0,
1361	.div_width = 5,
1362
1363	/* CRU_CLKGATE_CON3 */
1364	.gate_offset = 0x20c,
1365	.gate_shift = 1,
1366
1367	.flags = RK_CLK_COMPOSITE_HAVE_GATE | RK_CLK_COMPOSITE_HAVE_MUX,
1368};
1369
1370static const char *mac2io_out_parents[] = { "cpll", "gpll" };
1371
1372static struct rk_clk_composite_def mac2io_out = {
1373	.clkdef = {
1374		.id = SCLK_MAC2IO_OUT,
1375		.name = "clk_mac2io_out",
1376		.parent_names = mac2io_out_parents,
1377		.parent_cnt = nitems(mac2io_out_parents),
1378	},
1379	/* CRU_CLKSEL_CON27 */
1380	.muxdiv_offset = 0x16c,
1381
1382	.mux_shift = 15,
1383	.mux_width = 1,
1384
1385	.div_shift = 8,
1386	.div_width = 5,
1387
1388	/* CRU_CLKGATE_CON3 */
1389	.gate_offset = 0x20c,
1390	.gate_shift = 5,
1391
1392	.flags = RK_CLK_COMPOSITE_HAVE_GATE | RK_CLK_COMPOSITE_HAVE_MUX,
1393};
1394
1395static const char *mac2io_parents[] = { "clk_mac2io_src", "gmac_clkin" };
1396
1397static struct rk_clk_composite_def mac2io = {
1398	.clkdef = {
1399		.id = SCLK_MAC2IO,
1400		.name = "clk_mac2io",
1401		.parent_names = mac2io_parents,
1402		.parent_cnt = nitems(mac2io_parents),
1403	},
1404	.muxdiv_offset = RK3328_GRF_MAC_CON1,
1405
1406	.mux_shift = 10,
1407	.mux_width = 1,
1408
1409	.flags = RK_CLK_COMPOSITE_HAVE_MUX | RK_CLK_COMPOSITE_GRF
1410};
1411
1412static const char *mac2io_ext_parents[] = { "clk_mac2io", "gmac_clkin" };
1413
1414static struct rk_clk_composite_def mac2io_ext = {
1415	.clkdef = {
1416		.id = SCLK_MAC2IO_EXT,
1417		.name = "clk_mac2io_ext",
1418		.parent_names = mac2io_ext_parents,
1419		.parent_cnt = nitems(mac2io_ext_parents),
1420	},
1421	.muxdiv_offset = RK3328_GRF_SOC_CON4,
1422
1423	.mux_shift = 14,
1424	.mux_width = 1,
1425
1426	.flags = RK_CLK_COMPOSITE_HAVE_MUX | RK_CLK_COMPOSITE_GRF
1427};
1428
1429static const char *mac2phy_src_parents[] = { "cpll", "gpll" };
1430
1431static struct rk_clk_composite_def mac2phy_src = {
1432	.clkdef = {
1433		.id = SCLK_MAC2PHY_SRC,
1434		.name = "clk_mac2phy_src",
1435		.parent_names = mac2phy_src_parents,
1436		.parent_cnt = nitems(mac2phy_src_parents),
1437	},
1438	/* CRU_CLKSEL_CON26 */
1439	.muxdiv_offset = 0x168,
1440
1441	.mux_shift = 7,
1442	.mux_width = 1,
1443
1444	.div_shift = 0,
1445	.div_width = 5,
1446
1447	/* CRU_CLKGATE_CON3 */
1448	.gate_offset = 0x20c,
1449	.gate_shift = 0,
1450
1451	.flags = RK_CLK_COMPOSITE_HAVE_GATE | RK_CLK_COMPOSITE_HAVE_MUX,
1452};
1453
1454static const char *mac2phy_parents[] = { "clk_mac2phy_src", "phy_50m_out" };
1455
1456static struct rk_clk_composite_def mac2phy = {
1457	.clkdef = {
1458		.id = SCLK_MAC2PHY,
1459		.name = "clk_mac2phy",
1460		.parent_names = mac2phy_parents,
1461		.parent_cnt = nitems(mac2phy_parents),
1462	},
1463	.muxdiv_offset = RK3328_GRF_MAC_CON2,
1464
1465	.mux_shift = 10,
1466	.mux_width = 1,
1467
1468	.flags = RK_CLK_COMPOSITE_HAVE_MUX | RK_CLK_COMPOSITE_GRF
1469};
1470
1471static const char *mac2phy_out_parents[] = { "clk_mac2phy" };
1472
1473static struct rk_clk_composite_def mac2phy_out = {
1474	.clkdef = {
1475		.id = SCLK_MAC2PHY_OUT,
1476		.name = "clk_mac2phy_out",
1477		.parent_names = mac2phy_out_parents,
1478		.parent_cnt = nitems(mac2phy_out_parents),
1479	},
1480	/* CRU_CLKSEL_CON26 */
1481	.muxdiv_offset = 0x168,
1482
1483	.div_shift = 8,
1484	.div_width = 2,
1485
1486	/* CRU_CLKGATE_CON9 */
1487	.gate_offset = 0x224,
1488	.gate_shift = 2,
1489
1490	.flags = RK_CLK_COMPOSITE_HAVE_GATE
1491};
1492
1493static struct clk_fixed_def phy_50m_out = {
1494	.clkdef.name = "phy_50m_out",
1495	.freq = 50000000,
1496};
1497
1498static struct clk_link_def gmac_clkin = {
1499	.clkdef.name = "gmac_clkin",
1500};
1501
1502static const char *aclk_gmac_parents[] = { "cpll", "gpll" };
1503
1504static struct rk_clk_composite_def aclk_gmac = {
1505	.clkdef = {
1506		.id = ACLK_GMAC,
1507		.name = "aclk_gmac",
1508		.parent_names = aclk_gmac_parents,
1509		.parent_cnt = nitems(aclk_gmac_parents),
1510	},
1511	/* CRU_CLKSEL_CON35 */
1512	.muxdiv_offset = 0x18c,
1513
1514	.mux_shift = 6,
1515	.mux_width = 2,
1516
1517	.div_shift = 0,
1518	.div_width = 5,
1519
1520	/* CRU_CLKGATE_CON3 */
1521	.gate_offset = 0x20c,
1522	.gate_shift = 2,
1523
1524	.flags = RK_CLK_COMPOSITE_HAVE_GATE | RK_CLK_COMPOSITE_HAVE_MUX,
1525};
1526
1527static const char *pclk_gmac_parents[] = { "aclk_gmac" };
1528
1529static struct rk_clk_composite_def pclk_gmac = {
1530	.clkdef = {
1531		.id = PCLK_GMAC,
1532		.name = "pclk_gmac",
1533		.parent_names = pclk_gmac_parents,
1534		.parent_cnt = nitems(pclk_gmac_parents),
1535	},
1536	/* CRU_CLKSEL_CON25 */
1537	.muxdiv_offset = 0x164,
1538
1539	.div_shift = 8,
1540	.div_width = 3,
1541
1542	/* CRU_CLKGATE_CON9 */
1543	.gate_offset = 0x224,
1544	.gate_shift = 0,
1545
1546	.flags = RK_CLK_COMPOSITE_HAVE_GATE
1547};
1548
1549static struct rk_clk rk3328_clks[] = {
1550	{
1551		.type = RK3328_CLK_PLL,
1552		.clk.pll = &apll
1553	},
1554	{
1555		.type = RK3328_CLK_PLL,
1556		.clk.pll = &dpll
1557	},
1558	{
1559		.type = RK3328_CLK_PLL,
1560		.clk.pll = &cpll
1561	},
1562	{
1563		.type = RK3328_CLK_PLL,
1564		.clk.pll = &gpll
1565	},
1566	{
1567		.type = RK3328_CLK_PLL,
1568		.clk.pll = &npll
1569	},
1570
1571	{
1572		.type = RK_CLK_COMPOSITE,
1573		.clk.composite = &aclk_bus_pre
1574	},
1575	{
1576		.type = RK_CLK_COMPOSITE,
1577		.clk.composite = &hclk_bus_pre
1578	},
1579	{
1580		.type = RK_CLK_COMPOSITE,
1581		.clk.composite = &pclk_bus_pre
1582	},
1583
1584	{
1585		.type = RK_CLK_ARMCLK,
1586		.clk.armclk = &armclk,
1587	},
1588
1589	{
1590		.type = RK_CLK_COMPOSITE,
1591		.clk.composite = &clk_tsadc,
1592	},
1593	{
1594		.type = RK_CLK_COMPOSITE,
1595		.clk.composite = &aclk_peri_pre,
1596	},
1597	{
1598		.type = RK_CLK_COMPOSITE,
1599		.clk.composite = &pclk_peri,
1600	},
1601	{
1602		.type = RK_CLK_COMPOSITE,
1603		.clk.composite = &hclk_peri,
1604	},
1605	{
1606		.type = RK_CLK_COMPOSITE,
1607		.clk.composite = &sdmmc
1608	},
1609	{
1610		.type = RK_CLK_COMPOSITE,
1611		.clk.composite = &sdio
1612	},
1613	{
1614		.type = RK_CLK_COMPOSITE,
1615		.clk.composite = &emmc
1616	},
1617
1618	{
1619		.type = RK_CLK_COMPOSITE,
1620		.clk.composite = &i2c0
1621	},
1622	{
1623		.type = RK_CLK_COMPOSITE,
1624		.clk.composite = &i2c1
1625	},
1626	{
1627		.type = RK_CLK_COMPOSITE,
1628		.clk.composite = &i2c2
1629	},
1630	{
1631		.type = RK_CLK_COMPOSITE,
1632		.clk.composite = &i2c3
1633	},
1634
1635	{
1636		.type = RK_CLK_COMPOSITE,
1637		.clk.composite = &ref_usb3otg
1638	},
1639	{
1640		.type = RK_CLK_COMPOSITE,
1641		.clk.composite = &ref_usb3otg_src
1642	},
1643	{
1644		.type = RK_CLK_COMPOSITE,
1645		.clk.composite = &usb3otg_suspend
1646	},
1647	{
1648		.type = RK_CLK_COMPOSITE,
1649		.clk.composite = &i2s0_div
1650	},
1651	{
1652		.type = RK_CLK_FRACT,
1653		.clk.fract = &i2s0_frac
1654	},
1655	{
1656		.type = RK_CLK_MUX,
1657		.clk.mux = &i2s0_mux
1658	},
1659	{
1660		.type = RK_CLK_COMPOSITE,
1661		.clk.composite = &i2s1_div
1662	},
1663	{
1664		.type = RK_CLK_FRACT,
1665		.clk.fract = &i2s1_frac
1666	},
1667	{
1668		.type = RK_CLK_MUX,
1669		.clk.mux = &i2s1_mux
1670	},
1671	{
1672		.type = RK_CLK_FIXED,
1673		.clk.fixed = &clkin_i2s1
1674	},
1675	{
1676		.type = RK_CLK_COMPOSITE,
1677		.clk.composite = &i2s2_div
1678	},
1679	{
1680		.type = RK_CLK_FRACT,
1681		.clk.fract = &i2s2_frac
1682	},
1683	{
1684		.type = RK_CLK_MUX,
1685		.clk.mux = &i2s2_mux
1686	},
1687	{
1688		.type = RK_CLK_FIXED,
1689		.clk.fixed = &clkin_i2s2
1690	},
1691	{
1692		.type = RK_CLK_FIXED,
1693		.clk.fixed = &xin12m
1694	},
1695	{
1696		.type = RK_CLK_COMPOSITE,
1697		.clk.composite = &mac2io_src
1698	},
1699	{
1700		.type = RK_CLK_COMPOSITE,
1701		.clk.composite = &mac2io
1702	},
1703	{
1704		.type = RK_CLK_COMPOSITE,
1705		.clk.composite = &mac2io_out
1706	},
1707	{
1708		.type = RK_CLK_COMPOSITE,
1709		.clk.composite = &mac2io_ext
1710	},
1711	{
1712		.type = RK_CLK_COMPOSITE,
1713		.clk.composite = &mac2phy_src
1714	},
1715	{
1716		.type = RK_CLK_COMPOSITE,
1717		.clk.composite = &mac2phy
1718	},
1719	{
1720		.type = RK_CLK_COMPOSITE,
1721		.clk.composite = &mac2phy_out
1722	},
1723	{
1724		.type = RK_CLK_FIXED,
1725		.clk.fixed = &phy_50m_out
1726	},
1727	{
1728		.type = RK_CLK_LINK,
1729		.clk.link = &gmac_clkin
1730	},
1731	{
1732		.type = RK_CLK_COMPOSITE,
1733		.clk.composite = &aclk_gmac
1734	},
1735	{
1736		.type = RK_CLK_COMPOSITE,
1737		.clk.composite = &pclk_gmac
1738	},
1739};
1740
1741static int
1742rk3328_cru_probe(device_t dev)
1743{
1744
1745	if (!ofw_bus_status_okay(dev))
1746		return (ENXIO);
1747
1748	if (ofw_bus_is_compatible(dev, "rockchip,rk3328-cru")) {
1749		device_set_desc(dev, "Rockchip RK3328 Clock and Reset Unit");
1750		return (BUS_PROBE_DEFAULT);
1751	}
1752
1753	return (ENXIO);
1754}
1755
1756static int
1757rk3328_cru_attach(device_t dev)
1758{
1759	struct rk_cru_softc *sc;
1760
1761	sc = device_get_softc(dev);
1762	sc->dev = dev;
1763
1764	sc->gates = rk3328_gates;
1765	sc->ngates = nitems(rk3328_gates);
1766
1767	sc->clks = rk3328_clks;
1768	sc->nclks = nitems(rk3328_clks);
1769
1770	sc->reset_offset = 0x300;
1771	sc->reset_num = 184;
1772
1773	return (rk_cru_attach(dev));
1774}
1775
1776static device_method_t rk3328_cru_methods[] = {
1777	/* Device interface */
1778	DEVMETHOD(device_probe,		rk3328_cru_probe),
1779	DEVMETHOD(device_attach,	rk3328_cru_attach),
1780
1781	DEVMETHOD_END
1782};
1783
1784static devclass_t rk3328_cru_devclass;
1785
1786DEFINE_CLASS_1(rk3328_cru, rk3328_cru_driver, rk3328_cru_methods,
1787  sizeof(struct rk_cru_softc), rk_cru_driver);
1788
1789EARLY_DRIVER_MODULE(rk3328_cru, simplebus, rk3328_cru_driver,
1790    rk3328_cru_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
1791