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
ccu_d1_probe(device_t dev)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
ccu_d1_attach(device_t dev)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