xref: /freebsd/sys/dev/clk/allwinner/ccu_d1.c (revision 35c0a8c449fd2b7f75029ebed5e10852240f0865)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2022 Julien Cassette <julien.cassette@gmail.com>
5  * Copyright (c) 2024 The FreeBSD Foundation
6  *
7  * Portions of this software were developed by Mitchell Horne
8  * <mhorne@FreeBSD.org> under sponsorship from the FreeBSD Foundation.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/bus.h>
35 #include <sys/rman.h>
36 #include <sys/kernel.h>
37 #include <sys/module.h>
38 
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/clk/clk_div.h>
47 #include <dev/clk/clk_fixed.h>
48 #include <dev/clk/clk_mux.h>
49 
50 #include <dev/clk/allwinner/aw_ccung.h>
51 
52 #include <dt-bindings/clock/sun20i-d1-ccu.h>
53 #include <dt-bindings/reset/sun20i-d1-ccu.h>
54 
55 static struct aw_ccung_reset ccu_d1_resets[] = {
56 	CCU_RESET(RST_MBUS,		0x540,	30)
57 	CCU_RESET(RST_BUS_DE,		0x60C,	16)
58 	CCU_RESET(RST_BUS_DI,		0x62C,	16)
59 	CCU_RESET(RST_BUS_G2D,		0x63C,	16)
60 	CCU_RESET(RST_BUS_CE,		0x68C,	16)
61 	CCU_RESET(RST_BUS_VE,		0x69C,	16)
62 	CCU_RESET(RST_BUS_DMA,		0x70C,	16)
63 	CCU_RESET(RST_BUS_MSGBOX0,	0x71C,	16)
64 	CCU_RESET(RST_BUS_MSGBOX1,	0x71C,	17)
65 	CCU_RESET(RST_BUS_MSGBOX2,	0x71C,	18)
66 	CCU_RESET(RST_BUS_SPINLOCK,	0x72C,	16)
67 	CCU_RESET(RST_BUS_HSTIMER,	0x73C,	16)
68 	CCU_RESET(RST_BUS_DBG,		0x78C,	16)
69 	CCU_RESET(RST_BUS_PWM,		0x7AC,	16)
70 	CCU_RESET(RST_BUS_DRAM,		0x80C,	16)
71 	CCU_RESET(RST_BUS_MMC0,		0x84C,	16)
72 	CCU_RESET(RST_BUS_MMC1,		0x84C,	17)
73 	CCU_RESET(RST_BUS_MMC2,		0x84C,	18)
74 	CCU_RESET(RST_BUS_UART0,	0x90C,	16)
75 	CCU_RESET(RST_BUS_UART1,	0x90C,	17)
76 	CCU_RESET(RST_BUS_UART2,	0x90C,	18)
77 	CCU_RESET(RST_BUS_UART3,	0x90C,	19)
78 	CCU_RESET(RST_BUS_UART4,	0x90C,	20)
79 	CCU_RESET(RST_BUS_UART5,	0x90C,	21)
80 	CCU_RESET(RST_BUS_I2C0,		0x91C,	16)
81 	CCU_RESET(RST_BUS_I2C1,		0x91C,	17)
82 	CCU_RESET(RST_BUS_I2C2,		0x91C,	18)
83 	CCU_RESET(RST_BUS_I2C3,		0x91C,	19)
84 	CCU_RESET(RST_BUS_SPI0,		0x96C,	16)
85 	CCU_RESET(RST_BUS_SPI1,		0x96C,	17)
86 	CCU_RESET(RST_BUS_EMAC,		0x97C,	16)
87 	CCU_RESET(RST_BUS_IR_TX,	0x9CC,	16)
88 	CCU_RESET(RST_BUS_GPADC,	0x9EC,	16)
89 	CCU_RESET(RST_BUS_THS,		0x9FC,	16)
90 	CCU_RESET(RST_BUS_I2S0,		0xA20,	16)
91 	CCU_RESET(RST_BUS_I2S1,		0xA20,	17)
92 	CCU_RESET(RST_BUS_I2S2,		0xA20,	18)
93 	CCU_RESET(RST_BUS_SPDIF,	0xA2C,	16)
94 	CCU_RESET(RST_BUS_DMIC,		0xA4C,	16)
95 	CCU_RESET(RST_BUS_AUDIO,	0xA5C,	16)
96 	CCU_RESET(RST_USB_PHY0,		0xA70,	30)
97 	CCU_RESET(RST_USB_PHY1,		0xA74,	30)
98 	CCU_RESET(RST_BUS_OHCI0,	0xA8C,	16)
99 	CCU_RESET(RST_BUS_OHCI1,	0xA8C,	17)
100 	CCU_RESET(RST_BUS_EHCI0,	0xA8C,	20)
101 	CCU_RESET(RST_BUS_EHCI1,	0xA8C,	21)
102 	CCU_RESET(RST_BUS_OTG,		0xA8C,	24)
103 	CCU_RESET(RST_BUS_LRADC,	0xA9C,	16)
104 	CCU_RESET(RST_BUS_DPSS_TOP,	0xABC,	16)
105 	CCU_RESET(RST_BUS_MIPI_DSI,	0xB4C,	16)
106 	CCU_RESET(RST_BUS_TCON_LCD0,	0xB7C,	16)
107 	CCU_RESET(RST_BUS_TCON_TV,	0xB9C,	16)
108 	CCU_RESET(RST_BUS_LVDS0,	0xBAC,	16)
109 	CCU_RESET(RST_BUS_TVE,		0xBBC,	17)
110 	CCU_RESET(RST_BUS_TVE_TOP,	0xBBC,	16)
111 	CCU_RESET(RST_BUS_TVD,		0xBDC,	17)
112 	CCU_RESET(RST_BUS_TVD_TOP,	0xBDC,	16)
113 	CCU_RESET(RST_BUS_LEDC,		0xBFC,	16)
114 	CCU_RESET(RST_BUS_CSI,		0xC1C,	16)
115 	CCU_RESET(RST_BUS_TPADC,	0xC5C,	16)
116 	CCU_RESET(RST_DSP,		0xC7C,	16)
117 	CCU_RESET(RST_BUS_DSP_CFG,	0xC7C,	17)
118 	CCU_RESET(RST_BUS_DSP_DBG,	0xC7C,	18)
119 	CCU_RESET(RST_BUS_RISCV_CFG,	0xD0C,	16)
120 	CCU_RESET(RST_BUS_CAN0,		0x92C,	16)
121 	CCU_RESET(RST_BUS_CAN1,		0x92C,	17)
122 };
123 
124 static struct aw_ccung_gate ccu_d1_gates[] = {
125 	CCU_GATE(CLK_BUS_DE,		"bus-de",	"psi-ahb",	0x60C,	0)
126 	CCU_GATE(CLK_BUS_DI,		"bus-di",	"psi-ahb",	0x62C,	0)
127 	CCU_GATE(CLK_BUS_G2D,		"bus-g2d",	"psi-ahb",	0x63C,	0)
128 	CCU_GATE(CLK_BUS_CE,		"bus-ce",	"psi-ahb",	0x68C,	0)
129 	CCU_GATE(CLK_BUS_VE,		"bus-ve",	"psi-ahb",	0x690,	0)
130 	CCU_GATE(CLK_BUS_DMA,		"bus-dma",	"psi-ahb",	0x70C,	0)
131 	CCU_GATE(CLK_BUS_MSGBOX0,	"bus-msgbox0",	"psi-ahb",	0x71C,	0)
132 	CCU_GATE(CLK_BUS_MSGBOX1,	"bus-msgbox1",	"psi-ahb",	0x71C,	1)
133 	CCU_GATE(CLK_BUS_MSGBOX2,	"bus-msgbox2",	"psi-ahb",	0x71C,	2)
134 	CCU_GATE(CLK_BUS_SPINLOCK,	"bus-spinlock",	"psi-ahb",	0x72C,	0)
135 	CCU_GATE(CLK_BUS_HSTIMER,	"bus-hstimer",	"psi-ahb",	0x73C,	0)
136 	CCU_GATE(CLK_AVS,		"avs",		"dcxo",		0x740,	31)
137 	CCU_GATE(CLK_BUS_DBG,		"bus-dbg",	"psi-ahb",	0x78C,	0)
138 	CCU_GATE(CLK_BUS_PWM,		"bus-pwm",	"psi-ahb",	0x7AC,	0)
139 	CCU_GATE(CLK_BUS_IOMMU,		"bus-iommu",	"apb0",		0x7BC,	0)
140 	CCU_GATE(CLK_MBUS_DMA,		"mbus-dma",	"mbus",		0x804,	0)
141 	CCU_GATE(CLK_MBUS_VE,		"mbus-ve",	"mbus",		0x804,	1)
142 	CCU_GATE(CLK_MBUS_CE,		"mbus-ce",	"mbus",		0x804,	2)
143 	CCU_GATE(CLK_MBUS_TVIN,		"mbus-tvin",	"mbus",		0x804,	7)
144 	CCU_GATE(CLK_MBUS_CSI,		"mbus-csi",	"mbus",		0x804,	8)
145 	CCU_GATE(CLK_MBUS_G2D,		"mbus-g2d",	"mbus",		0x804,	10)
146 	CCU_GATE(CLK_MBUS_RISCV,	"mbus-riscv",	"mbus",		0x804,	11)
147 	CCU_GATE(CLK_BUS_DRAM,		"bus-dram",	"psi-ahb",	0x80C,	0)
148 	CCU_GATE(CLK_BUS_MMC0,		"bus-mmc0",	"psi-ahb",	0x84C,	0)
149 	CCU_GATE(CLK_BUS_MMC1,		"bus-mmc1",	"psi-ahb",	0x84C,	1)
150 	CCU_GATE(CLK_BUS_MMC2,		"bus-mmc2",	"psi-ahb",	0x84C,	2)
151 	CCU_GATE(CLK_BUS_UART0,		"bus-uart0",	"apb1",		0x90C,	0)
152 	CCU_GATE(CLK_BUS_UART1,		"bus-uart1",	"apb1",		0x90C,	1)
153 	CCU_GATE(CLK_BUS_UART2,		"bus-uart2",	"apb1",		0x90C,	2)
154 	CCU_GATE(CLK_BUS_UART3,		"bus-uart3",	"apb1",		0x90C,	3)
155 	CCU_GATE(CLK_BUS_UART4,		"bus-uart4",	"apb1",		0x90C,	4)
156 	CCU_GATE(CLK_BUS_UART5,		"bus-uart5",	"apb1",		0x90C,	5)
157 	CCU_GATE(CLK_BUS_I2C0,		"bus-i2c0",	"apb1",		0x91C,	0)
158 	CCU_GATE(CLK_BUS_I2C1,		"bus-i2c1",	"apb1",		0x91C,	1)
159 	CCU_GATE(CLK_BUS_I2C2,		"bus-i2c2",	"apb1",		0x91C,	2)
160 	CCU_GATE(CLK_BUS_I2C3,		"bus-i2c3",	"apb1",		0x91C,	3)
161 	CCU_GATE(CLK_BUS_SPI0,		"bus-spi0",	"psi-ahb",	0x96C,	0)
162 	CCU_GATE(CLK_BUS_SPI1,		"bus-spi1",	"psi-ahb",	0x96C,	1)
163 	CCU_GATE(CLK_BUS_EMAC,		"bus-emac",	"psi-ahb",	0x97C,	0)
164 	CCU_GATE(CLK_BUS_IR_TX,		"bus-ir-tx",	"apb0",		0x9CC,	0)
165 	CCU_GATE(CLK_BUS_GPADC,		"bus-gpadc",	"apb0",		0x9EC,	0)
166 	CCU_GATE(CLK_BUS_THS,		"bus-ths",	"apb0",		0x9FC,	0)
167 	CCU_GATE(CLK_BUS_I2S0,		"bus-i2s0",	"apb0",		0xA10,	0)
168 	CCU_GATE(CLK_BUS_I2S1,		"bus-i2s1",	"apb0",		0xA10,	1)
169 	CCU_GATE(CLK_BUS_I2S2,		"bus-i2s2",	"apb0",		0xA10,	2)
170 	CCU_GATE(CLK_BUS_SPDIF,		"bus-spdif",	"apb0",		0xA2C,	0)
171 	CCU_GATE(CLK_BUS_DMIC,		"bus-dmic",	"apb0",		0xA4C,	0)
172 	CCU_GATE(CLK_BUS_AUDIO,		"bus-audio",	"apb0",		0xA5C,	0)
173 	CCU_GATE(CLK_BUS_OHCI0,		"bus-ohci0",	"psi-ahb",	0xA8C,	0)
174 	CCU_GATE(CLK_BUS_OHCI1,		"bus-ohci1",	"psi-ahb",	0xA8C,	1)
175 	CCU_GATE(CLK_BUS_EHCI0,		"bus-ehci0",	"psi-ahb",	0xA8C,	4)
176 	CCU_GATE(CLK_BUS_EHCI1,		"bus-ehci1",	"psi-ahb",	0xA8C,	5)
177 	CCU_GATE(CLK_BUS_OTG,		"bus-otg",	"psi-ahb",	0xA8C,	8)
178 	CCU_GATE(CLK_BUS_LRADC,		"bus-lradc",	"apb0",		0xA9C,	0)
179 	CCU_GATE(CLK_BUS_DPSS_TOP,	"bus-dpss-top",	"psi-ahb",	0xABC,	0)
180 	CCU_GATE(CLK_BUS_MIPI_DSI,	"bus-mipi-dsi",	"psi-ahb",	0xB4C,	0)
181 	CCU_GATE(CLK_BUS_TCON_LCD0,	"bus-tcon-lcd0", "psi-ahb",	0xB7C,	0)
182 	CCU_GATE(CLK_BUS_TCON_TV,	"bus-tcon-tv",	"psi-ahb",	0xB9C,	0)
183 	CCU_GATE(CLK_BUS_TVE_TOP,	"bus-tve-top",	"psi-ahb",	0xBBC,	0)
184 	CCU_GATE(CLK_BUS_TVE,		"bus-tve",	"psi-ahb",	0xBBC,	1)
185 	CCU_GATE(CLK_BUS_TVD_TOP,	"bus-tvd-top",	"psi-ahb",	0xBDC,	0)
186 	CCU_GATE(CLK_BUS_TVD,		"bus-tvd",	"psi-ahb",	0xBDC,	1)
187 	CCU_GATE(CLK_BUS_LEDC,		"bus-ledc",	"psi-ahb",	0xBFC,	0)
188 	CCU_GATE(CLK_BUS_CSI,		"bus-csi",	"psi-ahb",	0xC1C,	0)
189 	CCU_GATE(CLK_BUS_TPADC,		"bus-tpadc",	"apb0",		0xC5C,	0)
190 	CCU_GATE(CLK_BUS_TZMA,		"bus-tzma",	"apb0",		0xC6C,	0)
191 	CCU_GATE(CLK_BUS_DSP_CFG,	"bus-dsp-cfg",	"psi-ahb",	0xC7C,	1)
192 	CCU_GATE(CLK_BUS_RISCV_CFG,	"bus-riscv-cfg", "psi-ahb",	0xD0C,	0)
193 	CCU_GATE(CLK_BUS_CAN0,		"bus-can0",	"apb1",		0x92C,	0)
194 	CCU_GATE(CLK_BUS_CAN1,		"bus-can1",	"apb1",		0x92C,	1)
195 };
196 
197 static const char *pll_cpux_parents[] = { "dcxo" };
198 NP_CLK(pll_cpux_clk,
199     CLK_PLL_CPUX,				/* id */
200     "pll_cpux",					/* name */
201     pll_cpux_parents,				/* parents */
202     0x0,					/* offset */
203     8, 8, 0, 0,					/* n factor */
204     0, 2, 0, 0,					/* p factor */
205     27,						/* gate */
206     28, 1000,					/* lock */
207     AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK);		/* flags */
208 
209 static const char *pll_ddr0_parents[] = { "dcxo" };
210 NMM_CLK(pll_ddr0_clk,
211     CLK_PLL_DDR0,				/* id */
212     "pll_ddr0",					/* name */
213      pll_ddr0_parents,				/* parents */
214     0x10,					/* offset */
215     8, 7, 0, 0,					/* n factor */
216     0, 1, 0, 0,					/* m0 factor */
217     1, 1, 0, 0,					/* m1 factor */
218     27,						/* gate */
219     28, 1000,					/* lock */
220     AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK);		/* flags */
221 
222 /* PLL_PERIPH(4X) = 24 MHz * N / M1 / M0 */
223 static const char *pll_periph0_4x_parents[] = { "dcxo" };
224 NMM_CLK(pll_periph0_4x_clk,
225     CLK_PLL_PERIPH0_4X,				/* id */
226     "pll_periph0_4x",				/* name */
227     pll_periph0_4x_parents,			/* parents */
228     0x20,					/* offset */
229     8, 8, 0, 0,					/* n factor */
230     0, 1, 0, 0,					/* m0 factor */
231     1, 1, 0, 0,					/* m1 factor */
232     27,						/* gate */
233     28, 1000,					/* lock */
234     AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK);		/* flags */
235 
236 /* PLL_PERIPH0(2X) = 24 MHz * N / M / P0 */
237 static const char *pll_periph0_2x_parents[] = { "pll_periph0_4x" };
238 M_CLK(pll_periph0_2x_clk,
239     CLK_PLL_PERIPH0_2X,				/* id */
240     "pll_periph0_2x",				/* name */
241     pll_periph0_2x_parents,			/* parents */
242     0x20,					/* offset */
243     16, 3, 0, 0,				/* m factor */
244     0, 0,					/* mux */
245     0,						/* gate */
246     0);						/* flags */
247 
248 /* PLL_PERIPH0(800M) = 24 MHz * N / M / P1 */
249 static const char *pll_periph0_800m_parents[] = { "pll_periph0_4x" };
250 M_CLK(pll_periph0_800m_clk,
251     CLK_PLL_PERIPH0_800M,			/* id */
252     "pll_periph0_800m",				/* name */
253     pll_periph0_800m_parents,			/* parents */
254     0x20,					/* offset */
255     20, 3, 0, 0,				/* m factor */
256     0, 0,					/* mux */
257     0,						/* gate */
258     0);						/* flags */
259 
260 /* PLL_PERIPH0(1X) = 24 MHz * N / M / P0 / 2 */
261 static const char *pll_periph0_parents[] = { "pll_periph0_2x" };
262 FIXED_CLK(pll_periph0_clk,
263     CLK_PLL_PERIPH0,				/* id */
264     "pll_periph0",				/* name */
265     pll_periph0_parents,			/* parents */
266     0,						/* freq */
267     1,						/* mult */
268     2,						/* div */
269     0);						/* flags */
270 
271 /* For child clocks: InputFreq * N / M */
272 static const char *pll_video0_parents[] = { "dcxo" };
273 NP_CLK(pll_video0_clk,
274     CLK_PLL_VIDEO0,				/* id */
275     "pll_video0",				/* name */
276     pll_video0_parents,				/* parents */
277     0x40,					/* offset */
278     8, 7, 0, 0,					/* n factor */
279     1, 1, 0, 0,					/* p factor */
280     27,						/* gate */
281     28, 1000,					/* lock */
282     AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK);		/* flags */
283 
284 /* PLL_VIDEO0(4X) = InputFreq * N / M / D */
285 /* D is only for testing */
286 static const char *pll_video0_4x_parents[] = { "pll_video0" };
287 M_CLK(pll_video0_4x_clk,
288     CLK_PLL_VIDEO0_4X,				/* id */
289     "pll_video0_4x",				/* name */
290     pll_video0_4x_parents,			/* parents */
291     0x40,					/* offset */
292     0, 1, 0, 0,					/* m factor */
293     0, 0,					/* mux */
294     0,						/* gate */
295     0);						/* flags */
296 
297 /* PLL_VIDEO0(2X) = InputFreq * N / M / 2 */
298 static const char *pll_video0_2x_parents[] = { "pll_video0" };
299 FIXED_CLK(pll_video0_2x_clk,
300     CLK_PLL_VIDEO0_2X,				/* id */
301     "pll_video0_2x",				/* name */
302     pll_video0_2x_parents,			/* parents */
303     0,						/* freq */
304     1,						/* mult */
305     2,						/* div */
306     0);						/* flags */
307 
308 /* For child clocks: InputFreq * N / M */
309 static const char *pll_video1_parents[] = { "dcxo" };
310 NP_CLK(pll_video1_clk,
311     CLK_PLL_VIDEO1,				/* id */
312     "pll_video1", 				/* name */
313     pll_video1_parents,				/* parents */
314     0x48,					/* offset */
315     8, 7, 0, 0,					/* n factor */
316     1, 1, 0, 0,					/* p factor */
317     27,						/* gate */
318     28, 1000,					/* lock */
319     AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK);		/* flags */
320 
321 /* PLL_VIDEO1(4X) = InputFreq * N / M / D */
322 /* D is only for testing */
323 static const char *pll_video1_4x_parents[] = { "pll_video1" };
324 M_CLK(pll_video1_4x_clk,
325     CLK_PLL_VIDEO1_4X,				/* id */
326     "pll_video1_4x",				/* name */
327     pll_video1_4x_parents,			/* parents */
328     0x48,					/* offset */
329     0, 1, 0, 0,					/* m factor */
330     0, 0,					/* mux */
331     0,						/* gate */
332     0);						/* flags */
333 
334 /* PLL_VIDEO1(2X) = InputFreq * N / M / 2 */
335 static const char *pll_video1_2x_parents[] = { "pll_video1" };
336 FIXED_CLK(pll_video1_2x_clk,
337     CLK_PLL_VIDEO1_2X,				/* id */
338     "pll_video1_2x",				/* name */
339     pll_video1_2x_parents,			/* parents */
340     0,						/* freq */
341     1,						/* mult */
342     2,						/* div */
343     0);						/* flags */
344 
345 static const char *pll_ve_parents[] = { "dcxo" };
346 NMM_CLK(pll_ve_clk,
347     CLK_PLL_VE,					/* id */
348     "pll_ve",					/* name */
349     pll_ve_parents,				/* parents */
350     0x58,					/* offset */
351     8, 7, 0, 0,					/* n factor */
352     0, 1, 0, 0,					/* m0 factor */
353     1, 1, 0, 0,					/* m1 factor */
354     27,						/* gate */
355     28, 1000,					/* lock */
356     AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK);		/* flags */
357 
358 /* For child clocks: 24MHz * N / M1 / M0 */
359 static const char *pll_audio0_4x_parents[] = { "dcxo" };
360 NMM_CLK(pll_audio0_4x_clk,
361     CLK_PLL_AUDIO0_4X,				/* id */
362     "pll_audio0_4x",				/* name */
363     pll_audio0_4x_parents,			/* parents */
364     0x78,					/* offset */
365     8, 7, 0, 0,					/* n factor */
366     0, 1, 0, 0,					/* m0 factor */
367     1, 1, 0, 0,					/* m1 factor */
368     27,						/* gate */
369     28, 1000,					/* lock */
370     AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK);		/* flags */
371 
372 /* PLL_AUDIO0(2X) = (24MHz * N / M1 / M0) / P / 2 */
373 static const char *pll_audio0_2x_parents[] = { "pll_audio0_4x" };
374 FIXED_CLK(pll_audio0_2x_clk,
375     CLK_PLL_AUDIO0_2X,				/* id */
376     "pll_audio0_2x",				/* name */
377     pll_audio0_2x_parents,			/* parents */
378     0,						/* freq */
379     1,						/* mult */
380     2,						/* div */
381     0);						/* flags */
382 
383 /* PLL_AUDIO0(1X) = 24MHz * N / M1 / M0 / P / 2 */
384 static const char *pll_audio0_parents[] = { "pll_audio0_2x" };
385 FIXED_CLK(pll_audio0_clk,
386     CLK_PLL_AUDIO0,				/* id */
387     "pll_audio0",				/* name */
388     pll_audio0_parents,			/* parents */
389     0,						/* freq */
390     1,						/* mult */
391     2,						/* div */
392     0);						/* flags */
393 
394 /* For child clocks: 24MHz * N / M */
395 static const char *pll_audio1_parents[] = { "dcxo" };
396 NP_CLK(pll_audio1_clk,
397     CLK_PLL_AUDIO1,				/* id */
398     "pll_audio1", 				/* name */
399     pll_audio1_parents,				/* parents */
400     0x80,					/* offset */
401     8, 7, 0, 0,					/* n factor */
402     1, 1, 0, 0,					/* p factor */
403     27,						/* gate */
404     28, 1000,					/* lock */
405     AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK);		/* flags */
406 
407 /* PLL_AUDIO1(DIV2) = 24MHz * N / M / P0 */
408 static const char *pll_audio1_div2_parents[] = { "pll_audio1" };
409 M_CLK(pll_audio1_div2_clk,
410     CLK_PLL_AUDIO1_DIV2,			/* id */
411     "pll_audio1_div2",				/* name */
412     pll_audio1_div2_parents,			/* parents */
413     0x80,					/* offset */
414     16, 3, 0, 0,				/* m factor */
415     0, 0,					/* mux */
416     0,						/* gate */
417     0);						/* flags */
418 
419 /* PLL_AUDIO1(DIV5) = 24MHz * N / M / P1 */
420 static const char *pll_audio1_div5_parents[] = { "pll_audio1" };
421 M_CLK(pll_audio1_div5_clk,
422     CLK_PLL_AUDIO1_DIV5,			/* id */
423     "pll_audio1_div5",				/* name */
424     pll_audio1_div5_parents,			/* parents */
425     0x80,					/* offset */
426     20, 3, 0, 0,				/* m factor */
427     0, 0,					/* mux */
428     0,						/* gate */
429     0);						/* flags */
430 
431 static const char *cpux_parents[] = { "dcxo", "osc32k", "iosc", "pll_cpux",
432     "pll_periph0", "pll_periph0_2x", "pll_periph0_800m" };
433 M_CLK(cpux_clk,
434     CLK_CPUX,					/* id */
435     "cpux",					 /* name */
436     cpux_parents,				/* parents */
437     0x500,					/* offset */
438     16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* m factor */
439     24, 3,					/* mux */
440     0,						/* gate */
441     AW_CLK_HAS_MUX | AW_CLK_SET_PARENT);	/* flags */
442 
443 static const char *cpux_axi_parents[] = { "cpux" };
444 M_CLK(cpux_axi_clk,
445     CLK_CPUX_AXI,				/* id */
446     "cpux_axi",					/* name */
447     cpux_axi_parents,				/* parents */
448     0x500,					/* offset */
449     0, 2, 0, 0,					/* m factor */
450     0, 0,					/* mux */
451     0,						/* gate */
452     0);						/* flags */
453 
454 static const char *cpux_apb_parents[] = { "cpux" };
455 M_CLK(cpux_apb_clk,
456     CLK_CPUX_APB,				/* id */
457     "cpux_apb",					/* name */
458     cpux_apb_parents,				/* parents */
459     0x500,					/* offset */
460     8, 2, 0, 0,					/* m factor */
461     0, 0,					/* mux */
462     0,						/* gate */
463     0);						/* flags */
464 
465 static const char *psi_ahb_parents[] = { "dcxo", "osc32k", "iosc",
466     "pll_periph0" };
467 NM_CLK(psi_ahb_clk,
468     CLK_PSI_AHB, "psi-ahb", psi_ahb_parents,	/* id, name, parents */
469     0x510,					/* offset */
470     8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
471     0, 2, 0, 0,					/* m factor */
472     24, 2,					/* mux */
473     0,						/* gate */
474     AW_CLK_HAS_MUX | AW_CLK_REPARENT);		/* flags */
475 
476 static const char *apb0_parents[] = { "dcxo", "osc32k", "psi-ahb", "pll_periph0" };
477 NM_CLK(apb0_clk,
478     CLK_APB0, "apb0", apb0_parents,		/* id, name, parents */
479     0x520,					/* offset */
480     8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
481     0, 2, 0, 0,					/* m factor */
482     24, 2,					/* mux */
483     0,						/* gate */
484     AW_CLK_HAS_MUX | AW_CLK_REPARENT);		/* flags */
485 
486 static const char *apb1_parents[] = { "dcxo", "osc32k", "psi-ahb", "pll_periph0" };
487 NM_CLK(apb1_clk,
488     CLK_APB1, "apb1", apb1_parents,		/* id, name, parents */
489     0x524,					/* offset */
490     8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
491     0, 2, 0, 0,					/* m factor */
492     24, 2,					/* mux */
493     0,						/* gate */
494     AW_CLK_HAS_MUX | AW_CLK_REPARENT);		/* flags */
495 
496 static const char *mbus_parents[] = { "dram" };
497 FIXED_CLK(mbus_clk,
498     CLK_MBUS, "mbus", mbus_parents,		/* id, name, parents */
499     0,						/* freq */
500     1,						/* mult */
501     4,						/* div */
502     0);						/* flags */
503 
504 static const char *de_parents[] = { "pll_periph0_2x", "pll_video0_4x",
505     "pll_video1_4x", "pll_audio1_div2" };
506 M_CLK(de_clk,
507     CLK_DE, "de", de_parents,			/* id, name, parents */
508     0x600,					/* offset */
509     0, 5, 0, 0,					/* m factor */
510     24, 3,					/* mux */
511     31,						/* gate */
512     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
513     AW_CLK_REPARENT);				/* flags */
514 
515 static const char *di_parents[] = { "pll_periph0_2x", "pll_video0_4x",
516     "pll_video1_4x", "pll_audio1_div2" };
517 M_CLK(di_clk,
518     CLK_DI, "di", di_parents,			/* id, name, parents */
519     0x620,					/* offset */
520     0, 5, 0, 0,					/* m factor */
521     24, 3,					/* mux */
522     31,						/* gate */
523     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
524     AW_CLK_REPARENT);				/* flags */
525 
526 static const char *g2d_parents[] = { "pll_periph0_2x", "pll_video0_4x",
527     "pll_video1_4x", "pll_audio1_div2" };
528 M_CLK(g2d_clk,
529     CLK_G2D, "g2d", g2d_parents,		/* id, name, parents */
530     0x630,					/* offset */
531     0, 5, 0, 0,					/* m factor */
532     24, 3,					/* mux */
533     31,						/* gate */
534     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
535     AW_CLK_REPARENT);				/* flags */
536 
537 static const char *ce_parents[] = { "dcxo", "pll_periph0_2x", "pll_periph0" };
538 NM_CLK(ce_clk,
539     CLK_CE, "ce", ce_parents,			/* id, name, parents */
540     0x680,					/* offset */
541     8, 2, 0, 0,					/* n factor */
542     0, 4, 0, 0,					/* m factor */
543     24, 3,					/* mux */
544     31,						/* gate */
545     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
546     AW_CLK_REPARENT);				/* flags */
547 
548 static const char *ve_parents[] = { "pll_ve", "pll_periph0_2x" };
549 M_CLK(ve_clk,
550     CLK_VE, "ve", ve_parents,			/* id, name, parents */
551     0x690,					/* offset */
552     0, 5, 0, 0,					/* m factor */
553     24, 1,					/* mux */
554     31,						/* gate */
555     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |		/* flags */
556     AW_CLK_REPARENT);
557 
558 static const char *dram_parents[] = { "pll_ddr0", "pll_audio1_div2",
559     "pll_periph0_2x", "pll_periph0_800m" };
560 NM_CLK(dram_clk,
561     CLK_DRAM, "dram", dram_parents,		/* id, name, parents */
562     0x800,					/* offset */
563     8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
564     0, 2, 0, 0,					/* m factor */
565     24, 3,					/* mux */
566     31,						/* gate */
567     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |		/* flags */
568     AW_CLK_REPARENT);
569 
570 /* SMHC0 */
571 static const char *mmc0_parents[] = { "dcxo", "pll_periph0", "pll_periph0_2x",
572     "pll_audio1_div2" };
573 NM_CLK(mmc0_clk,
574     CLK_MMC0, "mmc0", mmc0_parents,		/* id, name, parents */
575     0x830,					/* offset */
576     8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
577     0, 4, 0, 0,					/* m factor */
578     24, 3,					/* mux */
579     31,						/* gate */
580     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
581     AW_CLK_REPARENT);				/* flags */
582 
583 /* SMHC1 */
584 static const char *mmc1_parents[] = { "dcxo", "pll_periph0", "pll_periph0_2x",
585     "pll_audio1_div2" };
586 NM_CLK(mmc1_clk,
587     CLK_MMC1, "mmc1", mmc1_parents,		/* id, name, parents */
588     0x834,					/* offset */
589     8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
590     0, 4, 0, 0,					/* m factor */
591     24, 3,					/* mux */
592     31,						/* gate */
593     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
594     AW_CLK_REPARENT);				/* flags */
595 
596 /* SMHC2 */
597 static const char *mmc2_parents[] = { "dcxo", "pll_periph0", "pll_periph0_2x",
598     "pll_periph0_800m", "pll_audio1_div2" };
599 NM_CLK(mmc2_clk,
600     CLK_MMC2, "mmc2", mmc2_parents,		/* id, name, parents */
601     0x838,					/* offset */
602     8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
603     0, 4, 0, 0,					/* m factor */
604     24, 3,					/* mux */
605     31,						/* gate */
606     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
607     AW_CLK_REPARENT);				/* flags */
608 
609 static const char *spi0_parents[] = { "dcxo", "pll_periph0", "pll_periph0_2x",
610     "pll_audio1_div2", "pll_audio1_div5" };
611 NM_CLK(spi0_clk,
612     CLK_SPI0, "spi0", spi0_parents,		/* id, name, parents */
613     0x940,					/* offset */
614     8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
615     0, 4, 0, 0,					/* m factor */
616     24, 3,					/* mux */
617     31,						/* gate */
618     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
619     AW_CLK_REPARENT);				/* flags */
620 
621 static const char *spi1_parents[] = { "dcxo", "pll_periph0", "pll_periph0_2x",
622     "pll_audio1_div2", "pll_audio1_div5" };
623 NM_CLK(spi1_clk,
624     CLK_SPI1, "spi1", spi1_parents,		/* id, name, parents */
625     0x944,					/* offset */
626     8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
627     0, 4, 0, 0,					/* m factor */
628     24, 3,					/* mux */
629     31,						/* gate */
630     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
631     AW_CLK_REPARENT);				/* flags */
632 
633 /* Use M_CLK to have gate */
634 static const char *emac_25m_parents[] = { "pll_periph0" };
635 M_CLK(emac_25m_clk,
636     CLK_EMAC_25M,				/* id */
637     "emac_25m",					/* name */
638     emac_25m_parents,				/* parents */
639     0x970,					/* offset */
640     0, 0, 24, AW_CLK_FACTOR_FIXED,		/* m factor */
641     0, 0,					/* mux */
642     31,						/* gate */
643     AW_CLK_HAS_GATE | AW_CLK_REPARENT);		/* flags */
644 
645 static const char *irtx_parents[] = { "dcxo", "pll_periph0" };
646 NM_CLK(irtx_clk,
647     CLK_IR_TX, "irtx", irtx_parents,		/* id, name, parents */
648     0x9C0,					/* offset */
649     8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
650     0, 4, 0, 0,					/* m factor */
651     24, 3,					/* mux */
652     31,						/* gate */
653     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
654     AW_CLK_REPARENT);				/* flags */
655 
656 static const char *i2s0_parents[] = { "pll_audio0", "pll_audio0_4x",
657     "pll_audio1_div2", "pll_audio1_div5" };
658 NM_CLK(i2s0_clk,
659     CLK_I2S0, "i2s0", i2s0_parents,		/* id, name, parents */
660     0xA10,					/* offset */
661     8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
662     0, 5, 0, 0,					/* m factor */
663     24, 3,					/* mux */
664     31,						/* gate */
665     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
666     AW_CLK_REPARENT);				/* flags */
667 
668 static const char *i2s1_parents[] = { "pll_audio0", "pll_audio0_4x",
669     "pll_audio1_div2", "pll_audio1_div5" };
670 NM_CLK(i2s1_clk,
671     CLK_I2S1, "i2s1", i2s1_parents,		/* id, name, parents */
672     0xA14,					/* offset */
673     8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
674     0, 5, 0, 0,					/* m factor */
675     24, 3,					/* mux */
676     31,						/* gate */
677     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
678     AW_CLK_REPARENT);				/* flags */
679 
680 static const char *i2s2_parents[] = { "pll_audio0", "pll_audio0_4x",
681     "pll_audio1_div2", "pll_audio1_div5" };
682 NM_CLK(i2s2_clk,
683     CLK_I2S2, "i2s2", i2s2_parents,		/* id, name, parents */
684     0xA18,					/* offset */
685     8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
686     0, 5, 0, 0,					/* m factor */
687     24, 3,					/* mux */
688     31,						/* gate */
689     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
690     AW_CLK_REPARENT);				/* flags */
691 
692 static const char *i2s2_asrc_parents[] = { "pll_audio0_4x", "pll_periph0",
693     "pll_audio1_div2", "pll_audio1_div5" };
694 NM_CLK(i2s2_asrc_clk,
695     CLK_I2S2_ASRC,				/* id */
696     "i2s2_asrc",				/* name */
697     i2s2_asrc_parents,				/* parents */
698     0xA1C,					/* offset */
699     8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
700     0, 5, 0, 0,					/* m factor */
701     24, 3,					/* mux */
702     31,						/* gate */
703     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
704     AW_CLK_REPARENT);				/* flags */
705 
706 /* OWA_TX */
707 static const char *spdif_tx_parents[] = { "pll_audio0", "pll_audio0_4x",
708     "pll_audio1_div2", "pll_audio1_div5" };
709 NM_CLK(spdif_tx_clk,
710     CLK_SPDIF_TX, "spdif_tx", spdif_tx_parents,	/* id, name, parents */
711     0xA24,					/* offset */
712     8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
713     0, 5, 0, 0,					/* m factor */
714     24, 3,					/* mux */
715     31,						/* gate */
716     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
717     AW_CLK_REPARENT);				/* flags */
718 
719 /* OWA_RX */
720 static const char *spdif_rx_parents[] = { "pll_periph0", "pll_audio1_div2",
721     "pll_audio1_div5" };
722 NM_CLK(spdif_rx_clk,
723     CLK_SPDIF_RX, "spdif_rx", spdif_rx_parents,	/* id, name, parents */
724     0xA28,					/* offset */
725     8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
726     0, 5, 0, 0,					/* m factor */
727     24, 3,					/* mux */
728     31,						/* gate */
729     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
730     AW_CLK_REPARENT);				/* flags */
731 
732 static const char *dmic_parents[] = { "pll_audio0", "pll_audio1_div2",
733     "pll_audio1_div5" };
734 NM_CLK(dmic_clk,
735     CLK_DMIC, "dmic", dmic_parents,		/* id, name, parents */
736     0xA40,					/* offset */
737     8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
738     0, 5, 0, 0,					/* m factor */
739     24, 3,					/* mux */
740     31,						/* gate */
741     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
742     AW_CLK_REPARENT);				/* flags */
743 
744 static const char *audio_dac_parents[] = { "pll_audio0", "pll_audio1_div2",
745     "pll_audio1_div5" };
746 NM_CLK(audio_dac_clk,
747     CLK_AUDIO_DAC,				/* id */
748     "audio_dac",				/* name */
749     audio_dac_parents,				/* parents */
750     0xA50,					/* offset */
751     8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
752     0, 5, 0, 0,					/* m factor */
753     24, 3,					/* mux */
754     31,						/* gate */
755     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
756     AW_CLK_REPARENT);				/* flags */
757 
758 static const char *audio_adc_parents[] = { "pll_audio0", "pll_audio1_div2",
759     "pll_audio1_div5" };
760 NM_CLK(audio_adc_clk,
761     CLK_AUDIO_ADC,				/* id */
762     "audio_adc",				/* name */
763     audio_adc_parents,				/* parents */
764     0xA54,					/* offset */
765     8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
766     0, 5, 0, 0,					/* m factor */
767     24, 3,					/* mux */
768     31,						/* gate */
769     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
770     AW_CLK_REPARENT);				/* flags */
771 
772 /*
773  * XXX: These USB clocks are unusual, and can't be modeled fully with any of
774  * our existing clk classes.
775  *
776  * The clocks have three parents; they output 12M when assigned to the first
777  * two, and the third is direct (32K).
778  *
779  * Thus a divider table like the following would be needed:
780  *   struct clk_div_table usb_ohci_div_table[] = {
781  *      { .value = 0, .divider = 50 },
782  *      { .value = 1, .divider = 2 },
783  *      { .value = 2, .divider = 1 },
784  *      { },
785  *   };
786  *
787  * But we also require a gate.
788  *
789  * To work around this, model the clocks as if they had only one parent.
790  */
791 static const char *usb_ohci_parents[] = { "pll_periph0",
792     /*"dcxo", "osc32k"*/ };
793 M_CLK(usb_ohci0_clk,
794     CLK_USB_OHCI0,				/* id */
795     "usb_ohci0",				/* name */
796     usb_ohci_parents,				/* parents */
797     0xA70,					/* offset */
798     0, 0, 50, AW_CLK_FACTOR_FIXED,		/* m factor */
799     24, 2,					/* mux */
800     31,						/* gate */
801     AW_CLK_HAS_GATE /* | AW_CLK_HAS_MUX */);	/* flags */
802 
803 M_CLK(usb_ohci1_clk,
804     CLK_USB_OHCI1,				/* id */
805     "usb_ohci1",				/* name */
806     usb_ohci_parents,				/* parents */
807     0xA74,					/* offset */
808     0, 0, 50, AW_CLK_FACTOR_FIXED,		/* m factor */
809     24, 2,					/* mux */
810     31,						/* gate */
811     AW_CLK_HAS_GATE /* | AW_CLK_HAS_MUX */);	/* flags */
812 
813 
814 static const char *dsi_parents[] = { "dcxo", "pll_periph0", "pll_video0_2x",
815     "pll_video1_2x", "pll_audio1_div2" };
816 M_CLK(dsi_clk,
817     CLK_MIPI_DSI, "mipi-dsi", dsi_parents,	/* id, name, parents */
818     0xB24,					/* offset */
819     0, 4, 0, 0,					/* m factor */
820     24, 3,					/* mux */
821     31,						/* gate */
822     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
823     AW_CLK_REPARENT);				/* flags */
824 
825 static const char *tconlcd_parents[] = { "pll_video0", "pll_video0_4x",
826     "pll_video1", "pll_video1_4x", "pll_periph0_2x", "pll_audio1_div2" };
827 NM_CLK(tconlcd_clk,
828     CLK_TCON_LCD0, "tcon-lcd0", tconlcd_parents,	/* id, name, parents */
829     0xB60,					/* offset */
830     8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
831     0, 4, 0, 0,					/* m factor */
832     24, 3,					/* mux */
833     31,						/* gate */
834     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
835     AW_CLK_REPARENT);				/* flags */
836 
837 static const char *tcontv_parents[] = { "pll_video0", "pll_video0_4x",
838     "pll_video1", "pll_video1_4x", "pll_periph0_2x", "pll_audio1_div2" };
839 NM_CLK(tcontv_clk,
840     CLK_TCON_TV, "tcon-tv", tcontv_parents,	/* id, name, parents */
841     0xB80,					/* offset */
842     8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
843     0, 4, 0, 0,					/* m factor */
844     24, 3,					/* mux */
845     31,						/* gate */
846     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
847     AW_CLK_REPARENT);				/* flags */
848 
849 static const char *tve_parents[] = { "pll_video0", "pll_video0_4x",
850     "pll_video1", "pll_video1_4x", "pll_periph0_2x", "pll_audio1_div2" };
851 NM_CLK(tve_clk,
852     CLK_TVE, "tve", tve_parents,		/* id, name, parents */
853     0xBB0,					/* offset */
854     8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
855     0, 4, 0, 0,					/* m factor */
856     24, 3,					/* mux */
857     31,						/* gate */
858     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
859     AW_CLK_REPARENT);				/* flags */
860 
861 static const char *tvd_parents[] = { "dcxo", "pll_video0", "pll_video1",
862     "pll_periph0" };
863 M_CLK(tvd_clk,
864     CLK_TVD, "tvd", tvd_parents,		/* id, name, parents */
865     0xBC0,					/* offset */
866     0, 5, 0, 0,					/* m factor */
867     24, 3,					/* mux */
868     31,						/* gate */
869     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
870     AW_CLK_REPARENT);				/* flags */
871 
872 static const char *ledc_parents[] = { "dcxo", "pll_periph0" };
873 NM_CLK(ledc_clk,
874     CLK_LEDC, "ledc", ledc_parents,		/* id, name, parents */
875     0xBF0,					/* offset */
876     8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO,	/* n factor */
877     0, 4, 0, 0,					/* m factor */
878     24, 1,					/* mux */
879     31,						/* gate */
880     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
881     AW_CLK_REPARENT);				/* flags */
882 
883 static const char *csi_top_parents[] = { "pll_periph0_2x", "pll_video0_2x",
884     "pll_video1_2x" };
885 M_CLK(csi_top_clk,
886     CLK_CSI_TOP, "csi-top", csi_top_parents,	/* id, name, parents */
887     0xC04,					/* offset */
888     0, 4, 0, 0,					/* m factor */
889     24, 3,					/* mux */
890     31,						/* gate */
891     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
892     AW_CLK_REPARENT);				/* flags */
893 
894 static const char *csi_mclk_parents[] = { "dcxo", "pll_periph0",
895     "pll_video0", "pll_video1", "pll_audio1_div2", "pll_audio1_div5" };
896 M_CLK(csi_mclk,
897     CLK_CSI_MCLK,				/* id */
898     "csi-mclk",					/* name */
899     csi_mclk_parents,				/* parents */
900     0xC08,					/* offset */
901     0, 5, 0, 0,					/* m factor */
902     24, 3,					/* mux */
903     31,						/* gate */
904     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
905     AW_CLK_REPARENT);				/* flags */
906 
907 /* Use M_CLK to have mux and gate */
908 static const char *tpadc_parents[] = { "dcxo", "pll_audio0" };
909 M_CLK(tpadc_clk,
910     CLK_TPADC, "tpadc", tpadc_parents,		/* id, name, parents */
911     0xC50,					/* offset */
912     0, 0, 1, AW_CLK_FACTOR_FIXED,		/* m factor */
913     24, 2,					/* mux */
914     31,						/* gate */
915     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
916     AW_CLK_REPARENT);				/* flags */
917 
918 static const char *dsp_parents[] = { "dcxo", "osc32k", "iosc",
919     "pll_periph0_2x", "pll_audio1_div2" };
920 M_CLK(dsp_clk,
921     CLK_DSP, "dsp", dsp_parents,		/* id, name, parents */
922     0xC70,					/* offset */
923     0, 5, 0, 0,					/* m factor */
924     24, 3,					/* mux */
925     31,						/* gate */
926     AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
927     AW_CLK_REPARENT);				/* flags */
928 
929 static const char *riscv_parents[] = { "dcxo", "osc32k", "iosc",
930     "pll_periph0_800m", "pll_periph0", "pll_cpux", "pll_audio1_div2" };
931 M_CLK(riscv_clk,
932     CLK_RISCV, "riscv", riscv_parents,		/* id, name, parents */
933     0xD00,					/* offset */
934     0, 5, 0, 0,					/* m factor */
935     24, 3,					/* mux */
936     0,						/* gate */
937     AW_CLK_HAS_MUX | AW_CLK_SET_PARENT);	/* flags */
938 
939 static const char *riscv_axi_parents[] = { "riscv" };
940 static struct clk_div_table riscv_axi_div_table[] = {
941 	{ .value = 1, .divider = 2 },
942 	{ .value = 2, .divider = 3 },
943 	{ .value = 3, .divider = 4 },
944 	{ },
945 };
946 DIV_CLK(riscv_axi_clk,
947     CLK_RISCV_AXI,				/* id */
948     "riscv_axi", riscv_axi_parents,		/* name, parents */
949     0xD00,					/* offset */
950     8, 2,					/* shift, width */
951     CLK_DIV_WITH_TABLE,				/* flags */
952     riscv_axi_div_table);			/* table */
953 
954 /* TODO FANOUT */
955 
956 static struct aw_ccung_clk ccu_d1_clks[] = {
957 	{ .type = AW_CLK_NP,	.clk.np		= &pll_cpux_clk },
958 	{ .type = AW_CLK_NMM,	.clk.nmm	= &pll_ddr0_clk },
959 	{ .type = AW_CLK_NMM,	.clk.nmm	= &pll_periph0_4x_clk },
960 	{ .type = AW_CLK_M,	.clk.m		= &pll_periph0_2x_clk },
961 	{ .type = AW_CLK_M,	.clk.m		= &pll_periph0_800m_clk },
962 	{ .type = AW_CLK_FIXED,	.clk.fixed	= &pll_periph0_clk },
963 	{ .type = AW_CLK_NP,	.clk.np		= &pll_video0_clk },
964 	{ .type = AW_CLK_M,	.clk.m		= &pll_video0_4x_clk },
965 	{ .type = AW_CLK_FIXED,	.clk.fixed	= &pll_video0_2x_clk },
966 	{ .type = AW_CLK_NP,	.clk.np		= &pll_video1_clk },
967 	{ .type = AW_CLK_M,	.clk.m		= &pll_video1_4x_clk },
968 	{ .type = AW_CLK_FIXED,	.clk.fixed	= &pll_video1_2x_clk },
969 	{ .type = AW_CLK_NMM,	.clk.nmm	= &pll_ve_clk },
970 	{ .type = AW_CLK_NMM,	.clk.nmm	= &pll_audio0_4x_clk },
971 	{ .type = AW_CLK_FIXED,	.clk.fixed	= &pll_audio0_2x_clk },
972 	{ .type = AW_CLK_FIXED,	.clk.fixed	= &pll_audio0_clk },
973 	{ .type = AW_CLK_NP,	.clk.np		= &pll_audio1_clk },
974 	{ .type = AW_CLK_M,	.clk.m		= &pll_audio1_div2_clk },
975 	{ .type = AW_CLK_M,	.clk.m		= &pll_audio1_div5_clk },
976 	{ .type = AW_CLK_M,	.clk.m		= &cpux_clk },
977 	{ .type = AW_CLK_M,	.clk.m		= &cpux_axi_clk },
978 	{ .type = AW_CLK_M,	.clk.m		= &cpux_apb_clk },
979 	{ .type = AW_CLK_NM,	.clk.nm		= &psi_ahb_clk },
980 	{ .type = AW_CLK_NM,	.clk.nm		= &apb0_clk },
981 	{ .type = AW_CLK_NM,	.clk.nm		= &apb1_clk },
982 	{ .type = AW_CLK_FIXED,	.clk.fixed	= &mbus_clk },
983 	{ .type = AW_CLK_M,	.clk.m		= &de_clk },
984 	{ .type = AW_CLK_M,	.clk.m		= &di_clk },
985 	{ .type = AW_CLK_M,	.clk.m		= &g2d_clk },
986 	{ .type = AW_CLK_NM,	.clk.nm		= &ce_clk },
987 	{ .type = AW_CLK_M,	.clk.m		= &ve_clk },
988 	{ .type = AW_CLK_NM,	.clk.nm		= &dram_clk },
989 	{ .type = AW_CLK_NM,	.clk.nm		= &mmc0_clk },
990 	{ .type = AW_CLK_NM,	.clk.nm		= &mmc1_clk },
991 	{ .type = AW_CLK_NM,	.clk.nm		= &mmc2_clk },
992 	{ .type = AW_CLK_NM,	.clk.nm		= &spi0_clk },
993 	{ .type = AW_CLK_NM,	.clk.nm		= &spi1_clk },
994 	{ .type = AW_CLK_M,	.clk.m		= &emac_25m_clk },
995 	{ .type = AW_CLK_NM,	.clk.nm		= &irtx_clk },
996 	{ .type = AW_CLK_NM,	.clk.nm		= &i2s0_clk },
997 	{ .type = AW_CLK_NM,	.clk.nm		= &i2s1_clk },
998 	{ .type = AW_CLK_NM,	.clk.nm		= &i2s2_clk },
999 	{ .type = AW_CLK_NM,	.clk.nm		= &i2s2_asrc_clk },
1000 	{ .type = AW_CLK_NM,	.clk.nm		= &spdif_tx_clk },
1001 	{ .type = AW_CLK_NM,	.clk.nm		= &spdif_rx_clk },
1002 	{ .type = AW_CLK_NM,	.clk.nm		= &dmic_clk },
1003 	{ .type = AW_CLK_NM,	.clk.nm		= &audio_dac_clk },
1004 	{ .type = AW_CLK_NM,	.clk.nm		= &audio_adc_clk },
1005 	{ .type = AW_CLK_M,	.clk.m		= &usb_ohci0_clk },
1006 	{ .type = AW_CLK_M,	.clk.m		= &usb_ohci1_clk },
1007 	{ .type = AW_CLK_M,	.clk.m		= &dsi_clk },
1008 	{ .type = AW_CLK_NM,	.clk.nm		= &tconlcd_clk },
1009 	{ .type = AW_CLK_NM,	.clk.nm		= &tcontv_clk },
1010 	{ .type = AW_CLK_NM,	.clk.nm		= &tve_clk },
1011 	{ .type = AW_CLK_M,	.clk.m		= &tvd_clk },
1012 	{ .type = AW_CLK_NM,	.clk.nm		= &ledc_clk },
1013 	{ .type = AW_CLK_M,	.clk.m		= &csi_top_clk },
1014 	{ .type = AW_CLK_M,	.clk.m		= &csi_mclk },
1015 	{ .type = AW_CLK_M,	.clk.m		= &tpadc_clk },
1016 	{ .type = AW_CLK_M,	.clk.m		= &dsp_clk },
1017 	{ .type = AW_CLK_M,	.clk.m		= &riscv_clk },
1018 	{ .type = AW_CLK_DIV,	.clk.div	= &riscv_axi_clk},
1019 };
1020 
1021 static int
1022 ccu_d1_probe(device_t dev)
1023 {
1024 	if (!ofw_bus_status_okay(dev))
1025 		return (ENXIO);
1026 
1027 	if (!ofw_bus_is_compatible(dev, "allwinner,sun20i-d1-ccu"))
1028 		return (ENXIO);
1029 
1030 	device_set_desc(dev, "Allwinner D1 Clock Controller Unit");
1031 	return (BUS_PROBE_DEFAULT);
1032 }
1033 
1034 static int
1035 ccu_d1_attach(device_t dev)
1036 {
1037 	struct aw_ccung_softc *sc;
1038 
1039 	sc = device_get_softc(dev);
1040 
1041 	sc->resets = ccu_d1_resets;
1042 	sc->nresets = nitems(ccu_d1_resets);
1043 	sc->gates = ccu_d1_gates;
1044 	sc->ngates = nitems(ccu_d1_gates);
1045 	sc->clks = ccu_d1_clks;
1046 	sc->nclks = nitems(ccu_d1_clks);
1047 
1048 	return (aw_ccung_attach(dev));
1049 }
1050 
1051 static device_method_t ccu_d1_methods[] = {
1052 	DEVMETHOD(device_probe,		ccu_d1_probe),
1053 	DEVMETHOD(device_attach,	ccu_d1_attach),
1054 
1055 	DEVMETHOD_END
1056 };
1057 
1058 DEFINE_CLASS_1(ccu_d1, ccu_d1_driver, ccu_d1_methods,
1059   sizeof(struct aw_ccung_softc), aw_ccung_driver);
1060 
1061 EARLY_DRIVER_MODULE(ccu_d1, simplebus, ccu_d1_driver, 0, 0,
1062     BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);
1063