xref: /freebsd/sys/dev/clk/allwinner/ccu_a10.c (revision f126890a)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2018 Kyle Evans <kevans@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 
28 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/bus.h>
31 #include <sys/rman.h>
32 #include <sys/kernel.h>
33 #include <sys/module.h>
34 #include <machine/bus.h>
35 
36 #include <dev/fdt/simplebus.h>
37 
38 #include <dev/ofw/ofw_bus.h>
39 #include <dev/ofw/ofw_bus_subr.h>
40 
41 #include <dev/clk/clk_div.h>
42 #include <dev/clk/clk_fixed.h>
43 #include <dev/clk/clk_mux.h>
44 
45 #include <dev/clk/allwinner/aw_ccung.h>
46 
47 #include <dt-bindings/clock/sun4i-a10-ccu.h>
48 #include <dt-bindings/clock/sun7i-a20-ccu.h>
49 #include <dt-bindings/reset/sun4i-a10-ccu.h>
50 
51 /* Non-exported resets */
52 /* Non-exported clocks */
53 #define	CLK_PLL_CORE		2
54 #define	CLK_AXI			3
55 #define	CLK_AHB			4
56 #define	CLK_APB0		5
57 #define	CLK_APB1		6
58 #define	CLK_PLL_VIDEO0		8
59 #define	CLK_PLL_DDR		12
60 #define	CLK_PLL_DDR_OTHER	13
61 #define	CLK_PLL6		14
62 #define	CLK_PLL_PERIPH		15
63 #define	CLK_PLL_SATA		16
64 #define	CLK_PLL_VIDEO1		17
65 
66 /* Non-exported fixed clocks */
67 
68 static struct aw_ccung_reset a10_ccu_resets[] = {
69 	CCU_RESET(RST_USB_PHY0, 0xcc, 0)
70 	CCU_RESET(RST_USB_PHY1, 0xcc, 1)
71 	CCU_RESET(RST_USB_PHY2, 0xcc, 2)
72 
73 	CCU_RESET(RST_GPS, 0xd0, 0)
74 
75 	CCU_RESET(RST_DE_BE0, 0x104, 30)
76 	CCU_RESET(RST_DE_BE1, 0x108, 30)
77 	CCU_RESET(RST_DE_FE0, 0x10c, 30)
78 	CCU_RESET(RST_DE_FE1, 0x110, 30)
79 	CCU_RESET(RST_DE_MP, 0x114, 30)
80 
81 	CCU_RESET(RST_TVE0, 0x118, 29)
82 	CCU_RESET(RST_TCON0, 0x118, 30)
83 
84 	CCU_RESET(RST_TVE1, 0x11c, 29)
85 	CCU_RESET(RST_TCON1, 0x11c, 30)
86 
87 	CCU_RESET(RST_CSI0, 0x134, 30)
88 	CCU_RESET(RST_CSI1, 0x138, 30)
89 
90 	CCU_RESET(RST_VE, 0x13c, 0)
91 
92 	CCU_RESET(RST_ACE, 0x148, 16)
93 
94 	CCU_RESET(RST_LVDS, 0x14c, 0)
95 
96 	CCU_RESET(RST_GPU, 0x154, 30)
97 
98 	CCU_RESET(RST_HDMI_H, 0x170, 0)
99 	CCU_RESET(RST_HDMI_SYS, 0x170, 1)
100 	CCU_RESET(RST_HDMI_AUDIO_DMA, 0x170, 2)
101 };
102 
103 static struct aw_ccung_gate a10_ccu_gates[] = {
104 	CCU_GATE(CLK_HOSC, "hosc", "osc24M", 0x50, 0)
105 
106 	CCU_GATE(CLK_AHB_OTG, "ahb-otg", "ahb", 0x60, 0)
107 	CCU_GATE(CLK_AHB_EHCI0, "ahb-ehci0", "ahb", 0x60, 1)
108 	CCU_GATE(CLK_AHB_OHCI0, "ahb-ohci0", "ahb", 0x60, 2)
109 	CCU_GATE(CLK_AHB_EHCI1, "ahb-ehci1", "ahb", 0x60, 3)
110 	CCU_GATE(CLK_AHB_OHCI1, "ahb-ohci1", "ahb", 0x60, 4)
111 	CCU_GATE(CLK_AHB_SS, "ahb-ss", "ahb", 0x60, 5)
112 	CCU_GATE(CLK_AHB_DMA, "ahb-dma", "ahb", 0x60, 6)
113 	CCU_GATE(CLK_AHB_BIST, "ahb-bist", "ahb", 0x60, 7)
114 	CCU_GATE(CLK_AHB_MMC0, "ahb-mmc0", "ahb", 0x60, 8)
115 	CCU_GATE(CLK_AHB_MMC1, "ahb-mmc1", "ahb", 0x60, 9)
116 	CCU_GATE(CLK_AHB_MMC2, "ahb-mmc2", "ahb", 0x60, 10)
117 	CCU_GATE(CLK_AHB_MMC3, "ahb-mmc3", "ahb", 0x60, 11)
118 	CCU_GATE(CLK_AHB_MS, "ahb-ms", "ahb", 0x60, 12)
119 	CCU_GATE(CLK_AHB_NAND, "ahb-nand", "ahb", 0x60, 13)
120 	CCU_GATE(CLK_AHB_SDRAM, "ahb-sdram", "ahb", 0x60, 14)
121 	CCU_GATE(CLK_AHB_ACE, "ahb-ace", "ahb", 0x60, 16)
122 	CCU_GATE(CLK_AHB_EMAC, "ahb-emac", "ahb", 0x60, 17)
123 	CCU_GATE(CLK_AHB_TS, "ahb-ts", "ahb", 0x60, 18)
124 	CCU_GATE(CLK_AHB_SPI0, "ahb-spi0", "ahb", 0x60, 20)
125 	CCU_GATE(CLK_AHB_SPI1, "ahb-spi1", "ahb", 0x60, 21)
126 	CCU_GATE(CLK_AHB_SPI2, "ahb-spi2", "ahb", 0x60, 22)
127 	CCU_GATE(CLK_AHB_SPI3, "ahb-spi3", "ahb", 0x60, 23)
128 	CCU_GATE(CLK_AHB_SATA, "ahb-sata", "ahb", 0x60, 25)
129 
130 	CCU_GATE(CLK_AHB_VE, "ahb-ve", "ahb", 0x64, 0)
131 	CCU_GATE(CLK_AHB_TVD, "ahb-tvd", "ahb", 0x64, 1)
132 	CCU_GATE(CLK_AHB_TVE0, "ahb-tve0", "ahb", 0x64, 2)
133 	CCU_GATE(CLK_AHB_TVE1, "ahb-tve1", "ahb", 0x64, 3)
134 	CCU_GATE(CLK_AHB_LCD0, "ahb-lcd0", "ahb", 0x64, 4)
135 	CCU_GATE(CLK_AHB_LCD1, "ahb-lcd1", "ahb", 0x64, 5)
136 	CCU_GATE(CLK_AHB_CSI0, "ahb-csi0", "ahb", 0x64, 8)
137 	CCU_GATE(CLK_AHB_CSI1, "ahb-csi1", "ahb", 0x64, 9)
138 	CCU_GATE(CLK_AHB_HDMI1, "ahb-hdmi1", "ahb", 0x64, 10)
139 	CCU_GATE(CLK_AHB_HDMI0, "ahb-hdmi0", "ahb", 0x64, 11)
140 	CCU_GATE(CLK_AHB_DE_BE0, "ahb-de_be0", "ahb", 0x64, 12)
141 	CCU_GATE(CLK_AHB_DE_BE1, "ahb-de_be1", "ahb", 0x64, 13)
142 	CCU_GATE(CLK_AHB_DE_FE0, "ahb-de_fe0", "ahb", 0x64, 14)
143 	CCU_GATE(CLK_AHB_DE_FE1, "ahb-de_fe1", "ahb", 0x64, 15)
144 	CCU_GATE(CLK_AHB_GMAC, "ahb-gmac", "ahb", 0x64, 17)
145 	CCU_GATE(CLK_AHB_MP, "ahb-mp", "ahb", 0x64, 18)
146 	CCU_GATE(CLK_AHB_GPU, "ahb-gpu", "ahb", 0x64, 20)
147 
148 	CCU_GATE(CLK_APB0_CODEC, "apb0-codec", "apb0", 0x68, 0)
149 	CCU_GATE(CLK_APB0_SPDIF, "apb0-spdif", "apb0", 0x68, 1)
150 	CCU_GATE(CLK_APB0_AC97, "apb0-ac97", "apb0", 0x68, 2)
151 	CCU_GATE(CLK_APB0_I2S0, "apb0-i2s0", "apb0", 0x68, 3)
152 	CCU_GATE(CLK_APB0_I2S1, "apb0-i2s1", "apb0", 0x68, 4)
153 	CCU_GATE(CLK_APB0_PIO, "apb0-pi0", "apb0", 0x68, 5)
154 	CCU_GATE(CLK_APB0_IR0, "apb0-ir0", "apb0", 0x68, 6)
155 	CCU_GATE(CLK_APB0_IR1, "apb0-ir1", "apb0", 0x68, 7)
156 	CCU_GATE(CLK_APB0_I2S2, "apb0-i2s2", "apb0",0x68, 8)
157 	CCU_GATE(CLK_APB0_KEYPAD, "apb0-keypad", "apb0", 0x68, 10)
158 
159 	CCU_GATE(CLK_APB1_I2C0, "apb1-i2c0", "apb1", 0x6c, 0)
160 	CCU_GATE(CLK_APB1_I2C1, "apb1-i2c1", "apb1",0x6c, 1)
161 	CCU_GATE(CLK_APB1_I2C2, "apb1-i2c2", "apb1",0x6c, 2)
162 	CCU_GATE(CLK_APB1_I2C3, "apb1-i2c3", "apb1",0x6c, 3)
163 	CCU_GATE(CLK_APB1_CAN, "apb1-can", "apb1",0x6c, 4)
164 	CCU_GATE(CLK_APB1_SCR, "apb1-scr", "apb1",0x6c, 5)
165 	CCU_GATE(CLK_APB1_PS20, "apb1-ps20", "apb1",0x6c, 6)
166 	CCU_GATE(CLK_APB1_PS21, "apb1-ps21", "apb1",0x6c, 7)
167 	CCU_GATE(CLK_APB1_I2C4, "apb1-i2c4", "apb1", 0x6c, 15)
168 	CCU_GATE(CLK_APB1_UART0, "apb1-uart0", "apb1",0x6c, 16)
169 	CCU_GATE(CLK_APB1_UART1, "apb1-uart1", "apb1",0x6c, 17)
170 	CCU_GATE(CLK_APB1_UART2, "apb1-uart2", "apb1",0x6c, 18)
171 	CCU_GATE(CLK_APB1_UART3, "apb1-uart3", "apb1",0x6c, 19)
172 	CCU_GATE(CLK_APB1_UART4, "apb1-uart4", "apb1",0x6c, 20)
173 	CCU_GATE(CLK_APB1_UART5, "apb1-uart5", "apb1",0x6c, 21)
174 	CCU_GATE(CLK_APB1_UART6, "apb1-uart6", "apb1",0x6c, 22)
175 	CCU_GATE(CLK_APB1_UART7, "apb1-uart7", "apb1",0x6c, 23)
176 
177 	CCU_GATE(CLK_USB_OHCI0, "usb-ohci0", "ahb", 0xcc, 6)
178 	CCU_GATE(CLK_USB_OHCI1, "usb-ohci1", "ahb", 0xcc, 7)
179 	CCU_GATE(CLK_USB_PHY, "usb-phy", "ahb", 0xcc, 8)
180 
181 	CCU_GATE(CLK_DRAM_VE, "dram-ve", "pll_ddr", 0x100, 0)
182 	CCU_GATE(CLK_DRAM_CSI0, "dram-csi0", "pll_ddr", 0x100, 1)
183 	CCU_GATE(CLK_DRAM_CSI1, "dram-csi1", "pll_ddr", 0x100, 2)
184 	CCU_GATE(CLK_DRAM_TS, "dram-ts", "pll_ddr", 0x100, 3)
185 	CCU_GATE(CLK_DRAM_TVD, "dram-tvd", "pll_ddr", 0x100, 4)
186 	CCU_GATE(CLK_DRAM_TVE0, "dram-tve0", "pll_ddr", 0x100, 5)
187 	CCU_GATE(CLK_DRAM_TVE1, "dram-tve1", "pll_ddr", 0x100, 6)
188 	CCU_GATE(CLK_DRAM_OUT, "dram-out", "pll_ddr", 0x100, 15)
189 	CCU_GATE(CLK_DRAM_DE_FE1, "dram-de_fe1", "pll_ddr", 0x100, 24)
190 	CCU_GATE(CLK_DRAM_DE_FE0, "dram-de_fe0", "pll_ddr", 0x100, 25)
191 	CCU_GATE(CLK_DRAM_DE_BE0, "dram-de_be0", "pll_ddr", 0x100, 26)
192 	CCU_GATE(CLK_DRAM_DE_BE1, "dram-de_be1", "pll_ddr", 0x100, 27)
193 	CCU_GATE(CLK_DRAM_MP, "dram-de_mp", "pll_ddr", 0x100, 28)
194 	CCU_GATE(CLK_DRAM_ACE, "dram-ace", "pll_ddr", 0x100, 29)
195 };
196 
197 static const char *pll_parents[] = {"osc24M"};
198 NKMP_CLK(pll_core_clk,
199     CLK_PLL_CORE,				/* id */
200     "pll_core", pll_parents,			/* name, parents */
201     0x00,					/* offset */
202     8, 5, 0, AW_CLK_FACTOR_ZERO_IS_ONE,		/* n factor */
203     4, 2, 0, 0,					/* k factor */
204     0, 2, 0, 0,					/* m factor */
205     16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* p factor */
206     31,						/* gate */
207     0, 0,					/* lock */
208     AW_CLK_HAS_GATE);				/* flags */
209 
210 FRAC_CLK(pll_video0_clk,
211     CLK_PLL_VIDEO0,				/* id */
212     "pll_video0", pll_parents,			/* name, parents */
213     0x10,					/* offset */
214     0, 7, 0, 0,					/* n factor */
215     0, 0, 1, AW_CLK_FACTOR_FIXED,		/* m factor (fake) */
216     31, 0, 0,					/* gate, lock, lock retries */
217     AW_CLK_HAS_GATE,				/* flags */
218     270000000, 297000000,			/* freq0, freq1 */
219     15, 14,					/* mode sel, freq sel */
220     27000000, 381000000);			/* min freq, max freq */
221 static const char *pll_video0_2x_parents[] = {"pll_video0"};
222 FIXED_CLK(pll_video0_2x_clk,
223     CLK_PLL_VIDEO0_2X,				/* id */
224     "pll_video0-2x", pll_video0_2x_parents,	/* name, parents */
225     0,						/* freq */
226     2,						/* mult */
227     1,						/* div */
228     0);						/* flags */
229 
230 FRAC_CLK(pll_video1_clk,
231     CLK_PLL_VIDEO1,				/* id */
232     "pll_video1", pll_parents,			/* name, parents */
233     0x30,					/* offset */
234     0, 7, 0, 0,					/* n factor */
235     0, 0, 1, AW_CLK_FACTOR_FIXED,		/* m factor (fake) */
236     31, 0, 0,					/* gate, lock, lock retries */
237     AW_CLK_HAS_GATE,				/* flags */
238     270000000, 297000000,			/* freq0, freq1 */
239     15, 14,					/* mode sel, freq sel */
240     27000000, 381000000);			/* min freq, max freq */
241 static const char *pll_video1_2x_parents[] = {"pll_video1"};
242 FIXED_CLK(pll_video1_2x_clk,
243     CLK_PLL_VIDEO1_2X,				/* id */
244     "pll_video1-2x", pll_video1_2x_parents,	/* name, parents */
245     0,						/* freq */
246     2,						/* mult */
247     1,						/* div */
248     0);						/* flags */
249 
250 static const char *cpu_parents[] = {"osc32k", "osc24M", "pll_core", "pll_periph"};
251 static const char *axi_parents[] = {"cpu"};
252 static const char *ahb_parents[] = {"axi", "pll_periph", "pll6"};
253 static const char *apb0_parents[] = {"ahb"};
254 static const char *apb1_parents[] = {"osc24M", "pll_periph", "osc32k"};
255 MUX_CLK(cpu_clk,
256     CLK_CPU,					/* id */
257     "cpu", cpu_parents,				/* name, parents */
258     0x54, 16, 2);				/* offset, shift, width */
259 NM_CLK(axi_clk,
260     CLK_AXI,					/* id */
261     "axi", axi_parents,				/* name, parents */
262     0x54,					/* offset */
263     0, 0, 1, AW_CLK_FACTOR_FIXED,		/* n factor (fake) */
264     0, 2, 0, 0,					/* m factor */
265     0, 0,					/* mux */
266     0,						/* gate */
267     0);						/* flags */
268 NM_CLK(ahb_clk,
269     CLK_AHB,					/* id */
270     "ahb", ahb_parents,				/* name, parents */
271     0x54,					/* offset */
272     0, 0, 1, AW_CLK_FACTOR_FIXED,		/* n factor (fake) */
273     4, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* m factor */
274     6, 2,					/* mux */
275     0,						/* gate */
276     AW_CLK_HAS_MUX);				/* flags */
277 NM_CLK(apb0_clk,
278     CLK_APB0,					/* id */
279     "apb0", apb0_parents,			/* name, parents */
280     0x54,					/* offset */
281     0, 0, 1, AW_CLK_FACTOR_FIXED,		/* n factor (fake) */
282     8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO |
283     AW_CLK_FACTOR_ZERO_IS_ONE,			/* m factor */
284     0, 0,					/* mux */
285     0,						/* gate */
286     0);						/* flags */
287 
288 NM_CLK(apb1_clk,
289     CLK_APB1,					/* id */
290     "apb1", apb1_parents,			/* name, parents */
291     0x58,					/* offset */
292     16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
293     0, 5, 0, 0,					/* m factor */
294     24, 2,					/* mux */
295     0,						/* gate */
296     AW_CLK_HAS_MUX);				/* flags */
297 
298 NKMP_CLK(pll_ddr_other_clk,
299     CLK_PLL_DDR_OTHER,				/* id */
300     "pll_ddr_other", pll_parents,		/* name, parents */
301     0x20,					/* offset */
302     8, 5, 0, AW_CLK_FACTOR_ZERO_BASED,		/* n factor */
303     4, 2, 0, 0,					/* k factor */
304     0, 0, 1, AW_CLK_FACTOR_FIXED,		/* m factor (fake) */
305     2, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* p factor */
306     31,						/* gate */
307     0, 0,					/* lock */
308     AW_CLK_HAS_GATE);				/* flags */
309 NKMP_CLK(pll_ddr_clk,
310     CLK_PLL_DDR,				/* id */
311     "pll_ddr", pll_parents,			/* name, parents */
312     0x20,					/* offset */
313     8, 5, 0, AW_CLK_FACTOR_ZERO_BASED,		/* n factor */
314     4, 2, 0, 0,					/* k factor */
315     0, 2, 0, 0,					/* m factor */
316     0, 0, 1, AW_CLK_FACTOR_FIXED,		/* p factor (fake) */
317     31,						/* gate */
318     0, 0,					/* lock */
319     AW_CLK_HAS_GATE);				/* flags */
320 
321 NKMP_CLK(pll6_clk,
322     CLK_PLL6,					/* id */
323     "pll6", pll_parents,			/* name, parents */
324     0x28,					/* offset */
325     8, 5, 0, AW_CLK_FACTOR_ZERO_BASED,		/* n factor */
326     4, 2, 0, 0,					/* k factor */
327     0, 0, 1, AW_CLK_FACTOR_FIXED,		/* m factor (fake) */
328     0, 0, 1, AW_CLK_FACTOR_FIXED,		/* p factor (fake) */
329     31,						/* gate */
330     0, 0,					/* lock */
331     AW_CLK_HAS_GATE);				/* flags */
332 
333 static const char *pll6_parents[] = {"pll6"};
334 FIXED_CLK(pll_periph_clk,
335     CLK_PLL_PERIPH,				/* id */
336     "pll_periph", pll6_parents,			/* name, parents */
337     0,						/* freq */
338     1,						/* mult */
339     2,						/* div */
340     0);						/* flags */
341 NKMP_CLK(pll_periph_sata_clk,
342     CLK_PLL_SATA,				/* id */
343     "pll_periph_sata", pll6_parents,		/* name, parents */
344     0x28,					/* offset */
345     0, 0, 1, AW_CLK_FACTOR_FIXED,		/* n factor (fake) */
346     0, 0, 1, AW_CLK_FACTOR_FIXED,		/* k factor (fake) */
347     0, 2, 0, 0,					/* m factor */
348     0, 0, 6, AW_CLK_FACTOR_FIXED,		/* p factor (fake, 6) */
349     14,						/* gate */
350     0, 0,					/* lock */
351     AW_CLK_HAS_GATE);				/* flags */
352 
353 static const char *mod_parents[] = {"osc24M", "pll_periph", "pll_ddr_other"};
354 NM_CLK(nand_clk,
355     CLK_NAND,					/* id */
356     "nand", mod_parents,			/* name, parents */
357     0x80,					/* offset */
358     16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
359     0, 4, 0, 0,					/* m factor */
360     24, 2,					/* mux */
361     31,						/* gate */
362     AW_CLK_HAS_MUX | AW_CLK_HAS_GATE);		/* flags */
363 
364 NM_CLK(ms_clk,
365     CLK_MS,					/* id */
366     "ms", mod_parents,				/* name, parents */
367     0x84,					/* offset */
368     16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
369     0, 4, 0, 0,					/* m factor */
370     24, 2,					/* mux */
371     31,						/* gate */
372     AW_CLK_HAS_MUX | AW_CLK_HAS_GATE);		/* flags */
373 
374 NM_CLK(mmc0_clk,
375     CLK_MMC0,					/* id */
376     "mmc0", mod_parents,			/* name, parents */
377     0x88,					/* offset */
378     16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
379     0, 4, 0, 0,					/* m factor */
380     24, 2,					/* mux */
381     31,						/* gate */
382     AW_CLK_HAS_MUX | AW_CLK_HAS_GATE |
383     AW_CLK_REPARENT);				/* flags */
384 
385 NM_CLK(mmc1_clk,
386     CLK_MMC1,					/* id */
387     "mmc1", mod_parents,			/* name, parents */
388     0x8c,					/* offset */
389     16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
390     0, 4, 0, 0,					/* m factor */
391     24, 2,					/* mux */
392     31,						/* gate */
393     AW_CLK_HAS_MUX | AW_CLK_HAS_GATE |
394     AW_CLK_REPARENT);				/* flags */
395 
396 NM_CLK(mmc2_clk,
397     CLK_MMC2,					/* id */
398     "mmc2", mod_parents,			/* name, parents */
399     0x90,					/* offset */
400     16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
401     0, 4, 0, 0,					/* m factor */
402     24, 2,					/* mux */
403     31,						/* gate */
404     AW_CLK_HAS_MUX | AW_CLK_HAS_GATE |
405     AW_CLK_REPARENT);				/* flags */
406 
407 NM_CLK(mmc3_clk,
408     CLK_MMC3,					/* id */
409     "mmc3", mod_parents,			/* name, parents */
410     0x94,					/* offset */
411     16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
412     0, 4, 0, 0,					/* m factor */
413     24, 2,					/* mux */
414     31,						/* gate */
415     AW_CLK_HAS_MUX | AW_CLK_HAS_GATE |
416     AW_CLK_REPARENT);				/* flags */
417 
418 NM_CLK(ts_clk,
419     CLK_TS,					/* id */
420     "ts", mod_parents,				/* name, parents */
421     0x94,					/* offset */
422     16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
423     0, 4, 0, 0,					/* m factor */
424     24, 2,					/* mux */
425     31,						/* gate */
426     AW_CLK_HAS_MUX | AW_CLK_HAS_GATE);		/* flags */
427 
428 NM_CLK(ss_clk,
429     CLK_SS,					/* id */
430     "ss", mod_parents,				/* name, parents */
431     0x9c,					/* offset */
432     16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
433     0, 4, 0, 0,					/* m factor */
434     24, 2,					/* mux */
435     31,						/* gate */
436     AW_CLK_HAS_MUX | AW_CLK_HAS_GATE);		/* flags */
437 
438 NM_CLK(spi0_clk,
439     CLK_SPI0,					/* id */
440     "spi0", mod_parents,			/* name, parents */
441     0xa0,					/* offset */
442     16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
443     0, 4, 0, 0,					/* m factor */
444     24, 2,					/* mux */
445     31,						/* gate */
446     AW_CLK_HAS_MUX | AW_CLK_HAS_GATE);		/* flags */
447 
448 NM_CLK(spi1_clk,
449     CLK_SPI1,					/* id */
450     "spi1", mod_parents,			/* name, parents */
451     0xa4,					/* offset */
452     16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
453     0, 4, 0, 0,					/* m factor */
454     24, 2,					/* mux */
455     31,						/* gate */
456     AW_CLK_HAS_MUX | AW_CLK_HAS_GATE);		/* flags */
457 
458 NM_CLK(spi2_clk,
459     CLK_SPI2,					/* id */
460     "spi2", mod_parents,			/* name, parents */
461     0xa8,					/* offset */
462     16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
463     0, 4, 0, 0,					/* m factor */
464     24, 2,					/* mux */
465     31,						/* gate */
466     AW_CLK_HAS_MUX | AW_CLK_HAS_GATE);		/* flags */
467 
468 /* MISSING CLK_PATA */
469 
470 NM_CLK(ir0_clk,
471     CLK_IR0,					/* id */
472     "ir0", mod_parents,				/* name, parents */
473     0xb0,					/* offset */
474     16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
475     0, 4, 0, 0,					/* m factor */
476     24, 2,					/* mux */
477     31,						/* gate */
478     AW_CLK_HAS_MUX | AW_CLK_HAS_GATE);		/* flags */
479 
480 NM_CLK(ir1_clk,
481     CLK_IR1,					/* id */
482     "ir1", mod_parents,				/* name, parents */
483     0xb4,					/* offset */
484     16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
485     0, 4, 0, 0,					/* m factor */
486     24, 2,					/* mux */
487     31,						/* gate */
488     AW_CLK_HAS_MUX | AW_CLK_HAS_GATE);		/* flags */
489 
490 /* MISSING CLK_I2S0, CLK_AC97, CLK_SPDIF */
491 
492 static const char *keypad_parents[] = {"osc24M", "osc24M", "osc32k"};
493 NM_CLK(keypad_clk,
494     CLK_KEYPAD,					/* id */
495     "keypad", keypad_parents,			/* name, parents */
496     0xc4,					/* offset */
497     16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
498     0, 5, 0, 0,					/* m factor */
499     24, 2,					/* mux */
500     31,						/* gate */
501     AW_CLK_HAS_MUX | AW_CLK_HAS_GATE);		/* flags */
502 
503 static const char *sata_parents[] = {"pll_periph_sata", "osc32k"};
504 NM_CLK(sata_clk,
505     CLK_SATA,					/* id */
506     "sata", sata_parents,			/* name, parents */
507     0xc8,					/* offset */
508     0, 0, 1, AW_CLK_FACTOR_FIXED,		/* n factor (fake) */
509     0, 0, 1, AW_CLK_FACTOR_FIXED,		/* m factor (fake) */
510     24, 1,					/* mux */
511     31,						/* gate */
512     AW_CLK_HAS_MUX | AW_CLK_HAS_GATE);		/* flags */
513 
514 NM_CLK(spi3_clk,
515     CLK_SPI3,					/* id */
516     "spi3", mod_parents,				/* name, parents */
517     0xd4,					/* offset */
518     16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
519     0, 4, 0, 0,					/* m factor */
520     24, 2,					/* mux */
521     31,						/* gate */
522     AW_CLK_HAS_MUX | AW_CLK_HAS_GATE);		/* flags */
523 
524 /* MISSING CLK_I2S1, CLK_I2S2, DE Clocks */
525 
526 static struct aw_ccung_clk a10_ccu_clks[] = {
527 	{ .type = AW_CLK_NKMP, .clk.nkmp = &pll_core_clk},
528 	{ .type = AW_CLK_NKMP, .clk.nkmp = &pll_ddr_other_clk},
529 	{ .type = AW_CLK_NKMP, .clk.nkmp = &pll_ddr_clk},
530 	{ .type = AW_CLK_NKMP, .clk.nkmp = &pll6_clk},
531 	{ .type = AW_CLK_NKMP, .clk.nkmp = &pll_periph_sata_clk},
532 	{ .type = AW_CLK_NM, .clk.nm = &axi_clk},
533 	{ .type = AW_CLK_NM, .clk.nm = &ahb_clk},
534 	{ .type = AW_CLK_NM, .clk.nm = &apb0_clk},
535 	{ .type = AW_CLK_NM, .clk.nm = &apb1_clk},
536 	{ .type = AW_CLK_FRAC, .clk.frac = &pll_video0_clk},
537 	{ .type = AW_CLK_FRAC, .clk.frac = &pll_video1_clk},
538 	{ .type = AW_CLK_NM, .clk.nm = &nand_clk},
539 	{ .type = AW_CLK_NM, .clk.nm = &ms_clk},
540 	{ .type = AW_CLK_NM, .clk.nm = &mmc0_clk},
541 	{ .type = AW_CLK_NM, .clk.nm = &mmc1_clk},
542 	{ .type = AW_CLK_NM, .clk.nm = &mmc2_clk},
543 	{ .type = AW_CLK_NM, .clk.nm = &mmc3_clk},
544 	{ .type = AW_CLK_NM, .clk.nm = &ts_clk},
545 	{ .type = AW_CLK_NM, .clk.nm = &ss_clk},
546 	{ .type = AW_CLK_NM, .clk.nm = &spi0_clk},
547 	{ .type = AW_CLK_NM, .clk.nm = &spi1_clk},
548 	{ .type = AW_CLK_NM, .clk.nm = &spi2_clk},
549 	{ .type = AW_CLK_NM, .clk.nm = &ir0_clk},
550 	{ .type = AW_CLK_NM, .clk.nm = &ir1_clk},
551 	{ .type = AW_CLK_NM, .clk.nm = &keypad_clk},
552 	{ .type = AW_CLK_NM, .clk.nm = &sata_clk},
553 	{ .type = AW_CLK_NM, .clk.nm = &spi3_clk},
554 	{ .type = AW_CLK_MUX, .clk.mux = &cpu_clk},
555 	{ .type = AW_CLK_FIXED, .clk.fixed = &pll_periph_clk},
556 	{ .type = AW_CLK_FIXED, .clk.fixed = &pll_video0_2x_clk},
557 	{ .type = AW_CLK_FIXED, .clk.fixed = &pll_video1_2x_clk},
558 };
559 
560 static struct aw_clk_init a10_init_clks[] = {
561 };
562 
563 static struct ofw_compat_data compat_data[] = {
564 #if defined(SOC_ALLWINNER_A10)
565 	{ "allwinner,sun4i-a10-ccu", 1 },
566 #endif
567 #if defined(SOC_ALLWINNER_A20)
568 	{ "allwinner,sun7i-a20-ccu", 1 },
569 #endif
570 	{ NULL, 0},
571 };
572 
573 static int
574 ccu_a10_probe(device_t dev)
575 {
576 
577 	if (!ofw_bus_status_okay(dev))
578 		return (ENXIO);
579 
580 	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
581 		return (ENXIO);
582 
583 	device_set_desc(dev, "Allwinner A10/A20 Clock Control Unit NG");
584 	return (BUS_PROBE_DEFAULT);
585 }
586 
587 static int
588 ccu_a10_attach(device_t dev)
589 {
590 	struct aw_ccung_softc *sc;
591 
592 	sc = device_get_softc(dev);
593 
594 	sc->resets = a10_ccu_resets;
595 	sc->nresets = nitems(a10_ccu_resets);
596 	sc->gates = a10_ccu_gates;
597 	sc->ngates = nitems(a10_ccu_gates);
598 	sc->clks = a10_ccu_clks;
599 	sc->nclks = nitems(a10_ccu_clks);
600 	sc->clk_init = a10_init_clks;
601 	sc->n_clk_init = nitems(a10_init_clks);
602 
603 	return (aw_ccung_attach(dev));
604 }
605 
606 static device_method_t ccu_a10ng_methods[] = {
607 	/* Device interface */
608 	DEVMETHOD(device_probe,		ccu_a10_probe),
609 	DEVMETHOD(device_attach,	ccu_a10_attach),
610 
611 	DEVMETHOD_END
612 };
613 
614 DEFINE_CLASS_1(ccu_a10ng, ccu_a10ng_driver, ccu_a10ng_methods,
615   sizeof(struct aw_ccung_softc), aw_ccung_driver);
616 
617 EARLY_DRIVER_MODULE(ccu_a10ng, simplebus, ccu_a10ng_driver, 0, 0,
618     BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);
619