1/*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2017 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/sun8i-a83t-ccu.h>
48#include <dt-bindings/reset/sun8i-a83t-ccu.h>
49
50/* Non-exported clocks */
51
52#define	CLK_PLL_C0CPUX		0
53#define	CLK_PLL_C1CPUX		1
54#define	CLK_PLL_AUDIO		2
55#define	CLK_PLL_VIDEO0		3
56#define	CLK_PLL_VE		4
57#define	CLK_PLL_DDR		5
58
59#define	CLK_PLL_GPU		7
60#define	CLK_PLL_HSIC		8
61#define	CLK_PLL_VIDEO1		10
62
63#define	CLK_AXI0		13
64#define	CLK_AXI1		14
65#define	CLK_AHB1		15
66#define	CLK_APB1		16
67#define	CLK_APB2		17
68#define	CLK_AHB2		18
69
70#define	CLK_CCI400		58
71
72#define CLK_DRAM		82
73
74#define	CLK_MBUS		95
75
76/* Non-exported fixed clocks */
77#define CLK_OSC_12M		150
78
79static struct aw_ccung_reset a83t_ccu_resets[] = {
80	CCU_RESET(RST_USB_PHY0, 0xcc, 0)
81	CCU_RESET(RST_USB_PHY1, 0xcc, 1)
82	CCU_RESET(RST_USB_HSIC, 0xcc, 2)
83
84	CCU_RESET(RST_DRAM, 0xf4, 31)
85	CCU_RESET(RST_MBUS, 0xfc, 31)
86
87	CCU_RESET(RST_BUS_MIPI_DSI, 0x2c0, 1)
88	CCU_RESET(RST_BUS_SS, 0x2c0, 5)
89	CCU_RESET(RST_BUS_DMA, 0x2c0, 6)
90	CCU_RESET(RST_BUS_MMC0, 0x2c0, 8)
91	CCU_RESET(RST_BUS_MMC1, 0x2c0, 9)
92	CCU_RESET(RST_BUS_MMC2, 0x2c0, 10)
93	CCU_RESET(RST_BUS_NAND, 0x2c0, 13)
94	CCU_RESET(RST_BUS_DRAM, 0x2c0, 14)
95	CCU_RESET(RST_BUS_EMAC, 0x2c0, 17)
96	CCU_RESET(RST_BUS_HSTIMER, 0x2c0, 19)
97	CCU_RESET(RST_BUS_SPI0, 0x2c0, 20)
98	CCU_RESET(RST_BUS_SPI1, 0x2c0, 21)
99	CCU_RESET(RST_BUS_OTG, 0x2c0, 24)
100	CCU_RESET(RST_BUS_EHCI0, 0x2c0, 26)
101	CCU_RESET(RST_BUS_EHCI1, 0x2c0, 27)
102	CCU_RESET(RST_BUS_OHCI0, 0x2c0, 29)
103
104	CCU_RESET(RST_BUS_VE, 0x2c4, 0)
105	CCU_RESET(RST_BUS_TCON0, 0x2c4, 4)
106	CCU_RESET(RST_BUS_TCON1, 0x2c4, 5)
107	CCU_RESET(RST_BUS_CSI, 0x2c4, 8)
108	CCU_RESET(RST_BUS_HDMI0, 0x2c4, 10)
109	CCU_RESET(RST_BUS_HDMI1, 0x2c4, 11)
110	CCU_RESET(RST_BUS_DE, 0x2c4, 12)
111	CCU_RESET(RST_BUS_GPU, 0x2c4, 20)
112	CCU_RESET(RST_BUS_MSGBOX, 0x2c4, 21)
113	CCU_RESET(RST_BUS_SPINLOCK, 0x2c4, 22)
114
115	CCU_RESET(RST_BUS_LVDS, 0x2c8, 0)
116
117	CCU_RESET(RST_BUS_SPDIF, 0x2d0, 1)
118	CCU_RESET(RST_BUS_I2S0, 0x2d0, 12)
119	CCU_RESET(RST_BUS_I2S1, 0x2d0, 13)
120	CCU_RESET(RST_BUS_I2S2, 0x2d0, 14)
121	CCU_RESET(RST_BUS_TDM, 0x2d0, 15)
122
123	CCU_RESET(RST_BUS_I2C0, 0x2d8, 0)
124	CCU_RESET(RST_BUS_I2C1, 0x2d8, 1)
125	CCU_RESET(RST_BUS_I2C2, 0x2d8, 2)
126	CCU_RESET(RST_BUS_UART0, 0x2d8, 16)
127	CCU_RESET(RST_BUS_UART1, 0x2d8, 17)
128	CCU_RESET(RST_BUS_UART2, 0x2d8, 18)
129	CCU_RESET(RST_BUS_UART3, 0x2d8, 19)
130	CCU_RESET(RST_BUS_UART4, 0x2d8, 20)
131};
132
133static struct aw_ccung_gate a83t_ccu_gates[] = {
134	CCU_GATE(CLK_BUS_MIPI_DSI, "bus-mipi-dsi", "ahb1", 0x60, 1)
135	CCU_GATE(CLK_BUS_SS, "bus-ss", "ahb1", 0x60, 5)
136	CCU_GATE(CLK_BUS_DMA, "bus-dma", "ahb1", 0x60, 6)
137	CCU_GATE(CLK_BUS_MMC0, "bus-mmc0", "ahb1", 0x60, 8)
138	CCU_GATE(CLK_BUS_MMC1, "bus-mmc1", "ahb1", 0x60, 9)
139	CCU_GATE(CLK_BUS_MMC2, "bus-mmc2", "ahb1", 0x60, 10)
140	CCU_GATE(CLK_BUS_NAND, "bus-nand", "ahb1", 0x60, 13)
141	CCU_GATE(CLK_BUS_DRAM, "bus-dram", "ahb1", 0x60, 14)
142	CCU_GATE(CLK_BUS_EMAC, "bus-emac", "ahb1", 0x60, 17)
143	CCU_GATE(CLK_BUS_HSTIMER, "bus-hstimer", "ahb1", 0x60, 19)
144	CCU_GATE(CLK_BUS_SPI0, "bus-spi0", "ahb1", 0x60, 20)
145	CCU_GATE(CLK_BUS_SPI1, "bus-spi1", "ahb1", 0x60, 21)
146	CCU_GATE(CLK_BUS_OTG, "bus-otg", "ahb1", 0x60, 24)
147	CCU_GATE(CLK_BUS_EHCI0, "bus-ehci0", "ahb2", 0x60, 26)
148	CCU_GATE(CLK_BUS_EHCI1, "bus-ehci1", "ahb2", 0x60, 27)
149	CCU_GATE(CLK_BUS_OHCI0, "bus-ohci0", "ahb2", 0x60, 29)
150
151	CCU_GATE(CLK_BUS_VE, "bus-ve", "ahb1", 0x64, 0)
152	CCU_GATE(CLK_BUS_TCON0, "bus-tcon0", "ahb1", 0x64, 4)
153	CCU_GATE(CLK_BUS_TCON1, "bus-tcon1", "ahb1", 0x64, 5)
154	CCU_GATE(CLK_BUS_CSI, "bus-csi", "ahb1", 0x64, 8)
155	CCU_GATE(CLK_BUS_HDMI, "bus-hdmi", "ahb1", 0x64, 11)
156	CCU_GATE(CLK_BUS_DE, "bus-de", "ahb1", 0x64, 12)
157	CCU_GATE(CLK_BUS_GPU, "bus-gpu", "ahb1", 0x64, 20)
158	CCU_GATE(CLK_BUS_MSGBOX, "bus-msgbox", "ahb1", 0x64, 21)
159	CCU_GATE(CLK_BUS_SPINLOCK, "bus-spinlock", "ahb1", 0x64, 22)
160
161	CCU_GATE(CLK_BUS_SPDIF, "bus-spdif", "apb1", 0x68, 1)
162	CCU_GATE(CLK_BUS_PIO, "bus-pio", "apb1", 0x68, 5)
163	CCU_GATE(CLK_BUS_I2S0, "bus-i2s0", "apb1", 0x68, 12)
164	CCU_GATE(CLK_BUS_I2S1, "bus-i2s1", "apb1", 0x68, 13)
165	CCU_GATE(CLK_BUS_I2S2, "bus-i2s2", "apb1", 0x68, 14)
166	CCU_GATE(CLK_BUS_TDM, "bus-tdm", "apb1", 0x68, 15)
167
168	CCU_GATE(CLK_BUS_I2C0, "bus-i2c0", "apb2", 0x6c, 0)
169	CCU_GATE(CLK_BUS_I2C1, "bus-i2c1", "apb2", 0x6c, 1)
170	CCU_GATE(CLK_BUS_I2C2, "bus-i2c2", "apb2", 0x6c, 2)
171	CCU_GATE(CLK_BUS_UART0, "bus-uart0", "apb2", 0x6c, 16)
172	CCU_GATE(CLK_BUS_UART1, "bus-uart1", "apb2", 0x6c, 17)
173	CCU_GATE(CLK_BUS_UART2, "bus-uart2", "apb2", 0x6c, 18)
174	CCU_GATE(CLK_BUS_UART3, "bus-uart3", "apb2", 0x6c, 19)
175	CCU_GATE(CLK_BUS_UART4, "bus-uart4", "apb2", 0x6c, 20)
176
177	CCU_GATE(CLK_USB_PHY0, "usb-phy0", "osc24M", 0xcc, 8)
178	CCU_GATE(CLK_USB_PHY1, "usb-phy1", "osc24M", 0xcc, 9)
179	CCU_GATE(CLK_USB_HSIC, "usb-hsic", "pll_hsic", 0xcc, 10)
180	CCU_GATE(CLK_USB_HSIC_12M, "usb-hsic-12M", "osc12M", 0xcc, 11)
181	CCU_GATE(CLK_USB_OHCI0, "usb-ohci0", "osc12M", 0xcc, 16)
182
183	CCU_GATE(CLK_DRAM_VE, "dram-ve", "dram", 0x100, 0)
184	CCU_GATE(CLK_DRAM_CSI, "dram-csi", "dram", 0x100, 1)
185
186	CCU_GATE(CLK_CSI_MISC, "csi-misc", "osc24M", 0x130, 16)
187	CCU_GATE(CLK_MIPI_CSI, "mipi-csi", "osc24M", 0x130, 31)
188
189	CCU_GATE(CLK_AVS, "avs", "osc24M", 0x144, 31)
190
191	CCU_GATE(CLK_HDMI_SLOW, "hdmi-ddc", "osc24M", 0x154, 31)
192};
193
194static const char *osc12m_parents[] = {"osc24M"};
195FIXED_CLK(osc12m_clk,
196    CLK_OSC_12M,				/* id */
197    "osc12M", osc12m_parents,			/* name, parents */
198    0,						/* freq */
199    1,						/* mult */
200    2,						/* div */
201    0);						/* flags */
202
203/* CPU PLL are 24Mhz * N / P */
204static const char *pll_c0cpux_parents[] = {"osc24M"};
205static const char *pll_c1cpux_parents[] = {"osc24M"};
206NKMP_CLK(pll_c0cpux_clk,
207    CLK_PLL_C0CPUX,				/* id */
208    "pll_c0cpux", pll_c0cpux_parents,		/* name, parents */
209    0x00,					/* offset */
210    8, 8, 0, AW_CLK_FACTOR_ZERO_BASED,		/* n factor */
211    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* k factor (fake) */
212    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* m factor */
213    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* p factor (fake) */
214    0, 0,					/* lock */
215    31,						/* gate */
216    AW_CLK_HAS_GATE | AW_CLK_SCALE_CHANGE);	/* flags */
217NKMP_CLK(pll_c1cpux_clk,
218    CLK_PLL_C1CPUX,				/* id */
219    "pll_c1cpux", pll_c1cpux_parents,		/* name, parents */
220    0x04,					/* offset */
221    8, 8, 0, AW_CLK_FACTOR_ZERO_BASED,		/* n factor */
222    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* k factor (fake) */
223    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* m factor */
224    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* p factor (fake) */
225    0, 0,					/* lock */
226    31,						/* gate */
227    AW_CLK_HAS_GATE | AW_CLK_SCALE_CHANGE);	/* flags */
228
229static const char *pll_audio_parents[] = {"osc24M"};
230NKMP_CLK(pll_audio_clk,
231    CLK_PLL_AUDIO,				/* id */
232    "pll_audio", pll_audio_parents,		/* name, parents */
233    0x08,					/* offset */
234    8, 8, 0, AW_CLK_FACTOR_ZERO_BASED,		/* n factor */
235    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* k factor (fake) */
236    16, 1, 0, 0,				/* m factor */
237    18, 1, 0, 0,				/* p factor */
238    31,						/* gate */
239    0, 0,					/* lock */
240    AW_CLK_HAS_GATE);				/* flags */
241
242static const char *pll_video0_parents[] = {"osc24M"};
243NKMP_CLK(pll_video0_clk,
244    CLK_PLL_VIDEO0,				/* id */
245    "pll_video0", pll_video0_parents,		/* name, parents */
246    0x10,					/* offset */
247    8, 8, 0, AW_CLK_FACTOR_ZERO_BASED,		/* n factor */
248    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* k factor (fake) */
249    16, 1, 0, 0,				/* m factor */
250    0, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* p factor */
251    31,						/* gate */
252    0, 0,					/* lock */
253    AW_CLK_HAS_GATE);				/* flags */
254
255static const char *pll_ve_parents[] = {"osc24M"};
256NKMP_CLK(pll_ve_clk,
257    CLK_PLL_VE,					/* id */
258    "pll_ve", pll_ve_parents,			/* name, parents */
259    0x18,					/* offset */
260    8, 8, 0, AW_CLK_FACTOR_ZERO_BASED,		/* n factor */
261    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* k factor (fake) */
262    16, 1, 0, 0,				/* m factor */
263    18, 1, 0, 0,				/* p factor */
264    31,						/* gate */
265    0, 0,					/* lock */
266    AW_CLK_HAS_GATE);				/* flags */
267
268static const char *pll_ddr_parents[] = {"osc24M"};
269NKMP_CLK(pll_ddr_clk,
270    CLK_PLL_DDR,				/* id */
271    "pll_ddr", pll_ddr_parents,			/* name, parents */
272    0x20,					/* offset */
273    8, 5, 0, 0,					/* n factor */
274    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* k factor (fake) */
275    16, 1, 0, 0,				/* m factor */
276    18, 1, 0, 0,				/* p factor */
277    31,						/* gate */
278    0, 0,					/* lock */
279    AW_CLK_HAS_GATE);				/* flags */
280
281static const char *pll_periph_parents[] = {"osc24M"};
282NKMP_CLK(pll_periph_clk,
283    CLK_PLL_PERIPH,				/* id */
284    "pll_periph", pll_periph_parents,		/* name, parents */
285    0x28,					/* offset */
286    8, 8, 0, AW_CLK_FACTOR_ZERO_BASED,		/* n factor */
287    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* k factor (fake) */
288    16, 1, 1, 0,				/* m factor */
289    18, 1, 1, 0,				/* p factor */
290    31,						/* gate */
291    0, 0,					/* lock */
292    AW_CLK_HAS_GATE);				/* flags */
293
294static const char *pll_gpu_parents[] = {"osc24M"};
295NKMP_CLK(pll_gpu_clk,
296    CLK_PLL_GPU,				/* id */
297    "pll_gpu", pll_gpu_parents,			/* name, parents */
298    0x38,					/* offset */
299    8, 8, 0, AW_CLK_FACTOR_ZERO_BASED,		/* n factor */
300    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* k factor (fake) */
301    16, 1, 1, 0,				/* m factor */
302    18, 1, 1, 0,				/* p factor */
303    31,						/* gate */
304    0, 0,					/* lock */
305    AW_CLK_HAS_GATE);				/* flags */
306
307static const char *pll_hsic_parents[] = {"osc24M"};
308NKMP_CLK(pll_hsic_clk,
309    CLK_PLL_HSIC,				/* id */
310    "pll_hsic", pll_hsic_parents,		/* name, parents */
311    0x44,					/* offset */
312    8, 8, 0, AW_CLK_FACTOR_ZERO_BASED,		/* n factor */
313    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* k factor (fake) */
314    16, 1, 1, 0,				/* m factor */
315    18, 1, 1, 0,				/* p factor */
316    31,						/* gate */
317    0, 0,					/* lock */
318    AW_CLK_HAS_GATE);				/* flags */
319
320static const char *pll_de_parents[] = {"osc24M"};
321NKMP_CLK(pll_de_clk,
322    CLK_PLL_DE,					/* id */
323    "pll_de", pll_de_parents,			/* name, parents */
324    0x48,					/* offset */
325    8, 8, 0, AW_CLK_FACTOR_ZERO_BASED,		/* n factor */
326    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* k factor (fake) */
327    16, 1, 1, 0,				/* m factor */
328    18, 1, 1, 0,				/* p factor */
329    31,						/* gate */
330    0, 0,					/* lock */
331    AW_CLK_HAS_GATE);				/* flags */
332
333static const char *pll_video1_parents[] = {"osc24M"};
334NKMP_CLK(pll_video1_clk,
335    CLK_PLL_VIDEO1,				/* id */
336    "pll_video1", pll_video1_parents,		/* name, parents */
337    0x4c,					/* offset */
338    8, 8, 0, AW_CLK_FACTOR_ZERO_BASED,		/* n factor */
339    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* k factor (fake) */
340    16, 1, 1, 0,				/* m factor */
341    0, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* p factor */
342    31,						/* gate */
343    0, 0,					/* lock */
344    AW_CLK_HAS_GATE);				/* flags */
345
346static const char *c0cpux_parents[] = {"osc24M", "pll_c0cpux"};
347MUX_CLK(c0cpux_clk,
348    CLK_C0CPUX,					/* id */
349    "c0cpux", c0cpux_parents,			/* name, parents */
350    0x50, 12, 1);				/* offset, shift, width */
351
352static const char *c1cpux_parents[] = {"osc24M", "pll_c1cpux"};
353MUX_CLK(c1cpux_clk,
354    CLK_C1CPUX,					/* id */
355    "c1cpux", c1cpux_parents,			/* name, parents */
356    0x50, 28, 1);				/* offset, shift, width */
357
358static const char *axi0_parents[] = {"c0cpux"};
359DIV_CLK(axi0_clk,
360    CLK_AXI0,					/* id */
361    "axi0", axi0_parents,			/* name, parents */
362    0x50,					/* offset */
363    0, 2,					/* shift, width */
364    0, NULL);					/* flags, div table */
365
366static const char *axi1_parents[] = {"c1cpux"};
367DIV_CLK(axi1_clk,
368    CLK_AXI1,					/* id */
369    "axi1", axi1_parents,			/* name, parents */
370    0x50,					/* offset */
371    16, 2,					/* shift, width */
372    0, NULL);					/* flags, div table */
373
374static const char *ahb1_parents[] = {"osc16M-d512", "osc24M", "pll_periph", "pll_periph"};
375PREDIV_CLK_WITH_MASK(ahb1_clk,
376    CLK_AHB1,					/* id */
377    "ahb1", ahb1_parents,			/* name, parents */
378    0x54,					/* offset */
379    12, 2,					/* mux */
380    4, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* div */
381    6, 2, 0, AW_CLK_FACTOR_HAS_COND,		/* prediv */
382    (2 << 12), (2 << 12));			/* prediv condition */
383
384static const char *apb1_parents[] = {"ahb1"};
385DIV_CLK(apb1_clk,
386    CLK_APB1,					/* id */
387    "apb1", apb1_parents,			/* name, parents */
388    0x54,					/* offset */
389    8, 2,					/* shift, width */
390    0, NULL);					/* flags, div table */
391
392static const char *apb2_parents[] = {"osc16M-d512", "osc24M", "pll_periph", "pll_periph"};
393NM_CLK(apb2_clk,
394    CLK_APB2,					/* id */
395    "apb2", apb2_parents,			/* name, parents */
396    0x58,					/* offset */
397    16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
398    0, 5, 0, 0,					/* m factor */
399    24, 2,					/* mux */
400    0,						/* gate */
401    AW_CLK_HAS_MUX);
402
403static const char *ahb2_parents[] = {"ahb1", "pll_periph"};
404PREDIV_CLK(ahb2_clk,
405    CLK_AHB2,							/* id */
406    "ahb2", ahb2_parents,					/* name, parents */
407    0x5c,
408    0, 2,							/* mux */
409    0, 0, 1, AW_CLK_FACTOR_FIXED,				/* div (fake) */
410    0, 0, 2, AW_CLK_FACTOR_HAS_COND | AW_CLK_FACTOR_FIXED,	/* prediv */
411    0, 2, 1);							/* prediv cond */
412
413/* Actually has a divider, but we don't use it */
414static const char *cci400_parents[] = {"osc24M", "pll_periph", "pll_hsic"};
415MUX_CLK(cci400_clk,
416    CLK_CCI400,					/* id */
417    "cci400", cci400_parents,			/* name, parents */
418    0x78, 24, 2);				/* offset, shift, width */
419
420static const char *mod_parents[] = {"osc24M", "pll_periph"};
421
422NM_CLK(nand_clk,
423    CLK_NAND,					/* id */
424    "nand", mod_parents,			/* name, parents */
425    0x80,					/* offset */
426    16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
427    0, 4, 0, 0,					/* m factor */
428    24, 2,					/* mux */
429    31,						/* gate */
430    AW_CLK_HAS_GATE | AW_CLK_HAS_MUX);
431
432NM_CLK(mmc0_clk,
433    CLK_MMC0,					/* id */
434    "mmc0", mod_parents,			/* name, parents */
435    0x88,					/* offset */
436    16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
437    0, 4, 0, 0,					/* m factor */
438    24, 2,					/* mux */
439    31,						/* gate */
440    AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
441    AW_CLK_REPARENT);
442NM_CLK(mmc1_clk,
443    CLK_MMC1,					/* id */
444    "mmc1", mod_parents,			/* name, parents */
445    0x8c,					/* offset */
446    16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
447    0, 4, 0, 0,					/* m factor */
448    24, 2,					/* mux */
449    31,						/* gate */
450    AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
451    AW_CLK_REPARENT);
452NM_CLK(mmc2_clk,
453    CLK_MMC2,					/* id */
454    "mmc2", mod_parents,			/* name, parents */
455    0x90,					/* offset */
456    16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
457    0, 4, 0, 0,					/* m factor */
458    24, 2,					/* mux */
459    31,						/* gate */
460    AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
461    AW_CLK_REPARENT);
462
463NM_CLK(ss_clk,
464    CLK_SS,					/* id */
465    "ss", mod_parents,				/* name, parents */
466    0x9c,					/* offset */
467    16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
468    0, 4, 0, 0,					/* m factor */
469    24, 2,					/* mux */
470    31,						/* gate */
471    AW_CLK_HAS_GATE | AW_CLK_HAS_MUX);
472
473NM_CLK(spi0_clk,
474    CLK_SPI0,					/* id */
475    "spi0", mod_parents,			/* name, parents */
476    0xa0,					/* offset */
477    16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
478    0, 4, 0, 0,					/* m factor */
479    24, 2,					/* mux */
480    31,						/* gate */
481    AW_CLK_HAS_GATE | AW_CLK_HAS_MUX);
482NM_CLK(spi1_clk,
483    CLK_SPI1,					/* id */
484    "spi1", mod_parents,			/* name, parents */
485    0xa4,					/* offset */
486    16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
487    0, 4, 0, 0,					/* m factor */
488    24, 2,					/* mux */
489    31,						/* gate */
490    AW_CLK_HAS_GATE | AW_CLK_HAS_MUX);
491
492static const char *daudio_parents[] = {"pll_audio"};
493NM_CLK(i2s0_clk,
494    CLK_I2S0,					/* id */
495    "i2s0", daudio_parents,			/* name, parents */
496    0xb0,					/* offset */
497    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* n factor (fake) */
498    0, 4, 0, 0,					/* m factor */
499    0, 0,					/* mux */
500    31,						/* gate */
501    AW_CLK_HAS_GATE);
502NM_CLK(i2s1_clk,
503    CLK_I2S1,					/* id */
504    "i2s1", daudio_parents,			/* name, parents */
505    0xb4,					/* offset */
506    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* n factor (fake) */
507    0, 4, 0, 0,					/* m factor */
508    0, 0,					/* mux */
509    31,						/* gate */
510    AW_CLK_HAS_GATE);
511NM_CLK(i2s2_clk,
512    CLK_I2S2,					/* id */
513    "i2s2", daudio_parents,			/* name, parents */
514    0xb8,					/* offset */
515    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* n factor (fake) */
516    0, 4, 0, 0,					/* m factor */
517    0, 0,					/* mux */
518    31,						/* gate */
519    AW_CLK_HAS_GATE);
520
521static const char *tdm_parents[] = {"pll_audio"};
522NM_CLK(tdm_clk,
523    CLK_TDM,					/* id */
524    "tdm", tdm_parents,				/* name, parents */
525    0xbc,					/* offset */
526    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* n factor (fake) */
527    0, 4, 0, 0,					/* m factor */
528    0, 0,					/* mux */
529    31,						/* gate */
530    AW_CLK_HAS_GATE);
531
532static const char *spdif_parents[] = {"pll_audio"};
533NM_CLK(spdif_clk,
534    CLK_SPDIF,					/* id */
535    "spdif", spdif_parents,			/* name, parents */
536    0xc0,					/* offset */
537    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* n factor (fake) */
538    0, 4, 0, 0,					/* m factor */
539    0, 0,					/* mux */
540    31,						/* gate */
541    AW_CLK_HAS_GATE);
542
543static const char *dram_parents[] = {"pll_ddr"};
544NM_CLK(dram_clk,
545    CLK_DRAM,					/* id */
546    "dram", dram_parents,			/* name, parents */
547    0xf4,					/* offset */
548    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* n factor (fake) */
549    0, 4, 0, 0,					/* m factor */
550    0, 0,					/* mux */
551    0,						/* gate */
552    0);
553
554static const char *tcon0_parents[] = {"pll_video0"};
555MUX_CLK(tcon0_clk,
556    CLK_TCON0,					/* id */
557    "tcon0", tcon0_parents,			/* name, parents */
558    0x118, 24, 2);				/* offset, shift, width */
559
560static const char *tcon1_parents[] = {"pll_video1"};
561NM_CLK(tcon1_clk,
562    CLK_TCON1,					/* id */
563    "tcon1", tcon1_parents,			/* name, parents */
564    0x11c,					/* offset */
565    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* n factor (fake) */
566    0, 4, 0, 0,					/* m factor */
567    0, 0,					/* mux */
568    31,						/* gate */
569    AW_CLK_HAS_GATE);
570
571static const char *csi_mclk_parents[] = {"pll_de", "osc24M"};
572NM_CLK(csi_mclk_clk,
573    CLK_CSI_MCLK,				/* id */
574    "csi-mclk", csi_mclk_parents,		/* name, parents */
575    0x134,					/* offset */
576    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* n factor (fake) */
577    0, 4, 0, 0,					/* m factor */
578    8, 3,					/* mux */
579    15,						/* gate */
580    AW_CLK_HAS_MUX | AW_CLK_HAS_GATE);
581
582static const char *csi_sclk_parents[] = {"pll_periph", "pll_ve"};
583NM_CLK(csi_sclk_clk,
584    CLK_CSI_SCLK,				/* id */
585    "csi-sclk", csi_sclk_parents,		/* name, parents */
586    0x134,					/* offset */
587    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* n factor (fake) */
588    16, 4, 0, 0,				/* m factor */
589    24, 3,					/* mux */
590    31,						/* gate */
591    AW_CLK_HAS_MUX | AW_CLK_HAS_GATE);
592
593static const char *ve_parents[] = {"pll_ve"};
594NM_CLK(ve_clk,
595    CLK_VE,					/* id */
596    "ve", ve_parents,				/* name, parents */
597    0x13c,					/* offset */
598    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* n factor (fake) */
599    16, 3, 0, 0,				/* m factor */
600    0, 0,					/* mux */
601    31,						/* gate */
602    AW_CLK_HAS_GATE);
603
604static const char *hdmi_parents[] = {"pll_video1"};
605NM_CLK(hdmi_clk,
606    CLK_HDMI,					/* id */
607    "hdmi", hdmi_parents,			/* name, parents */
608    0x150,					/* offset */
609    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* n factor (fake) */
610    0, 4, 0, 0,					/* m factor */
611    24, 2,					/* mux */
612    31,						/* gate */
613    AW_CLK_HAS_MUX | AW_CLK_HAS_GATE);
614
615static const char *mbus_parents[] = {"osc24M", "pll_periph", "pll_ddr"};
616NM_CLK(mbus_clk,
617    CLK_MBUS,					/* id */
618    "mbus", mbus_parents,			/* name, parents */
619    0x15c,					/* offset */
620    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* n factor (fake) */
621    0, 3, 0, 0,					/* m factor */
622    24, 2,					/* mux */
623    31,						/* gate */
624    AW_CLK_HAS_MUX | AW_CLK_HAS_GATE);
625
626static const char *mipi_dsi0_parents[] = {"pll_video0"};
627NM_CLK(mipi_dsi0_clk,
628    CLK_MIPI_DSI0,				/* id */
629    "mipi-dsi0", mipi_dsi0_parents,		/* name, parents */
630    0x168,					/* offset */
631    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* n factor (fake) */
632    0, 4, 0, 0,					/* m factor */
633    24, 4,					/* mux */
634    31,						/* gate */
635    AW_CLK_HAS_MUX | AW_CLK_HAS_GATE);
636
637static const char *mipi_dsi1_parents[] = {"osc24M", "pll_video0"};
638NM_CLK(mipi_dsi1_clk,
639    CLK_MIPI_DSI1,				/* id */
640    "mipi-dsi1", mipi_dsi1_parents,		/* name, parents */
641    0x16c,					/* offset */
642    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* n factor (fake) */
643    0, 4, 0, 0,					/* m factor */
644    24, 4,					/* mux */
645    31,						/* gate */
646    AW_CLK_HAS_MUX | AW_CLK_HAS_GATE);
647
648static const char *gpu_core_parents[] = {"pll_gpu"};
649NM_CLK(gpu_core_clk,
650    CLK_GPU_CORE,				/* id */
651    "gpu-core", gpu_core_parents,		/* name, parents */
652    0x1a0,					/* offset */
653    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* n factor (fake) */
654    0, 3, 0, 0,					/* m factor */
655    0, 0,					/* mux */
656    31,						/* gate */
657    AW_CLK_HAS_GATE);
658
659static const char *gpu_memory_parents[] = {"pll_gpu", "pll_periph"};
660NM_CLK(gpu_memory_clk,
661    CLK_GPU_MEMORY,				/* id */
662    "gpu-memory", gpu_memory_parents,		/* name, parents */
663    0x1a4,					/* offset */
664    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* n factor (fake) */
665    0, 3, 0, 0,					/* m factor */
666    24, 1,					/* mux */
667    31,						/* gate */
668    AW_CLK_HAS_MUX | AW_CLK_HAS_GATE);
669
670static const char *gpu_hyd_parents[] = {"pll_gpu"};
671NM_CLK(gpu_hyd_clk,
672    CLK_GPU_HYD,				/* id */
673    "gpu-hyd", gpu_hyd_parents,			/* name, parents */
674    0x1a0,					/* offset */
675    0, 0, 1, AW_CLK_FACTOR_FIXED,		/* n factor (fake) */
676    0, 3, 0, 0,					/* m factor */
677    0, 0,					/* mux */
678    31,						/* gate */
679    AW_CLK_HAS_GATE);
680
681static struct aw_ccung_clk a83t_clks[] = {
682	{ .type = AW_CLK_NKMP, .clk.nkmp = &pll_audio_clk},
683	{ .type = AW_CLK_NKMP, .clk.nkmp = &pll_video0_clk},
684	{ .type = AW_CLK_NKMP, .clk.nkmp = &pll_ve_clk},
685	{ .type = AW_CLK_NKMP, .clk.nkmp = &pll_ddr_clk},
686	{ .type = AW_CLK_NKMP, .clk.nkmp = &pll_periph_clk},
687	{ .type = AW_CLK_NKMP, .clk.nkmp = &pll_gpu_clk},
688	{ .type = AW_CLK_NKMP, .clk.nkmp = &pll_hsic_clk},
689	{ .type = AW_CLK_NKMP, .clk.nkmp = &pll_de_clk},
690	{ .type = AW_CLK_NKMP, .clk.nkmp = &pll_video1_clk},
691	{ .type = AW_CLK_NKMP, .clk.nkmp = &pll_c0cpux_clk},
692	{ .type = AW_CLK_NKMP, .clk.nkmp = &pll_c1cpux_clk},
693	{ .type = AW_CLK_NM, .clk.nm = &apb2_clk},
694	{ .type = AW_CLK_NM, .clk.nm = &nand_clk},
695	{ .type = AW_CLK_NM, .clk.nm = &mmc0_clk},
696	{ .type = AW_CLK_NM, .clk.nm = &mmc1_clk},
697	{ .type = AW_CLK_NM, .clk.nm = &mmc2_clk},
698	{ .type = AW_CLK_NM, .clk.nm = &ss_clk},
699	{ .type = AW_CLK_NM, .clk.nm = &spi0_clk},
700	{ .type = AW_CLK_NM, .clk.nm = &spi1_clk},
701	{ .type = AW_CLK_NM, .clk.nm = &i2s0_clk},
702	{ .type = AW_CLK_NM, .clk.nm = &i2s1_clk},
703	{ .type = AW_CLK_NM, .clk.nm = &i2s2_clk},
704	{ .type = AW_CLK_NM, .clk.nm = &tdm_clk},
705	{ .type = AW_CLK_NM, .clk.nm = &spdif_clk},
706	{ .type = AW_CLK_NM, .clk.nm = &dram_clk},
707	{ .type = AW_CLK_NM, .clk.nm = &tcon1_clk},
708	{ .type = AW_CLK_NM, .clk.nm = &csi_mclk_clk},
709	{ .type = AW_CLK_NM, .clk.nm = &csi_sclk_clk},
710	{ .type = AW_CLK_NM, .clk.nm = &ve_clk},
711	{ .type = AW_CLK_NM, .clk.nm = &hdmi_clk},
712	{ .type = AW_CLK_NM, .clk.nm = &mbus_clk},
713	{ .type = AW_CLK_NM, .clk.nm = &mipi_dsi0_clk},
714	{ .type = AW_CLK_NM, .clk.nm = &mipi_dsi1_clk},
715	{ .type = AW_CLK_NM, .clk.nm = &gpu_core_clk},
716	{ .type = AW_CLK_NM, .clk.nm = &gpu_memory_clk},
717	{ .type = AW_CLK_NM, .clk.nm = &gpu_hyd_clk},
718	{ .type = AW_CLK_PREDIV_MUX, .clk.prediv_mux = &ahb1_clk},
719	{ .type = AW_CLK_PREDIV_MUX, .clk.prediv_mux = &ahb2_clk},
720	{ .type = AW_CLK_MUX, .clk.mux = &c0cpux_clk},
721	{ .type = AW_CLK_MUX, .clk.mux = &c1cpux_clk},
722	{ .type = AW_CLK_MUX, .clk.mux = &cci400_clk},
723	{ .type = AW_CLK_MUX, .clk.mux = &tcon0_clk},
724	{ .type = AW_CLK_DIV, .clk.div = &axi0_clk},
725	{ .type = AW_CLK_DIV, .clk.div = &axi1_clk},
726	{ .type = AW_CLK_DIV, .clk.div = &apb1_clk},
727	{ .type = AW_CLK_FIXED, .clk.fixed = &osc12m_clk},
728};
729
730static struct aw_clk_init a83t_init_clks[] = {
731	{"ahb1", "pll_periph", 0, false},
732	{"ahb2", "ahb1", 0, false},
733	{"dram", "pll_ddr", 0, false},
734};
735
736static int
737ccu_a83t_probe(device_t dev)
738{
739
740	if (!ofw_bus_status_okay(dev))
741		return (ENXIO);
742
743	if (!ofw_bus_is_compatible(dev, "allwinner,sun8i-a83t-ccu"))
744		return (ENXIO);
745
746	device_set_desc(dev, "Allwinner A83T Clock Control Unit NG");
747	return (BUS_PROBE_DEFAULT);
748}
749
750static int
751ccu_a83t_attach(device_t dev)
752{
753	struct aw_ccung_softc *sc;
754
755	sc = device_get_softc(dev);
756
757	sc->resets = a83t_ccu_resets;
758	sc->nresets = nitems(a83t_ccu_resets);
759	sc->gates = a83t_ccu_gates;
760	sc->ngates = nitems(a83t_ccu_gates);
761	sc->clks = a83t_clks;
762	sc->nclks = nitems(a83t_clks);
763	sc->clk_init = a83t_init_clks;
764	sc->n_clk_init = nitems(a83t_init_clks);
765
766	return (aw_ccung_attach(dev));
767}
768
769static device_method_t ccu_a83tng_methods[] = {
770	/* Device interface */
771	DEVMETHOD(device_probe,		ccu_a83t_probe),
772	DEVMETHOD(device_attach,	ccu_a83t_attach),
773
774	DEVMETHOD_END
775};
776
777DEFINE_CLASS_1(ccu_a83tng, ccu_a83tng_driver, ccu_a83tng_methods,
778  sizeof(struct aw_ccung_softc), aw_ccung_driver);
779
780EARLY_DRIVER_MODULE(ccu_a83tng, simplebus, ccu_a83tng_driver, 0, 0,
781    BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);
782