2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2017 Kyle Evans <kevans@FreeBSD.org>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
33 #include <sys/param.h>
34 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/module.h>
39 #include <machine/bus.h>
41 #include <dev/fdt/simplebus.h>
43 #include <dev/ofw/ofw_bus.h>
44 #include <dev/ofw/ofw_bus_subr.h>
46 #include <dev/extres/clk/clk_div.h>
47 #include <dev/extres/clk/clk_fixed.h>
48 #include <dev/extres/clk/clk_mux.h>
50 #include <arm/allwinner/clkng/aw_ccung.h>
52 #include <gnu/dts/include/dt-bindings/clock/sun8i-a83t-ccu.h>
53 #include <gnu/dts/include/dt-bindings/reset/sun8i-a83t-ccu.h>
55 /* Non-exported clocks */
57 #define CLK_PLL_C0CPUX 0
58 #define CLK_PLL_C1CPUX 1
59 #define CLK_PLL_AUDIO 2
60 #define CLK_PLL_VIDEO0 3
65 #define CLK_PLL_HSIC 8
66 #define CLK_PLL_VIDEO1 10
81 /* Non-exported fixed clocks */
82 #define CLK_OSC_12M 150
85 static struct aw_ccung_reset a83t_ccu_resets[] = {
86 CCU_RESET(RST_USB_PHY0, 0xcc, 0)
87 CCU_RESET(RST_USB_PHY1, 0xcc, 1)
88 CCU_RESET(RST_USB_HSIC, 0xcc, 2)
90 CCU_RESET(RST_DRAM, 0xf4, 31)
91 CCU_RESET(RST_MBUS, 0xfc, 31)
93 CCU_RESET(RST_BUS_MIPI_DSI, 0x2c0, 1)
94 CCU_RESET(RST_BUS_SS, 0x2c0, 5)
95 CCU_RESET(RST_BUS_DMA, 0x2c0, 6)
96 CCU_RESET(RST_BUS_MMC0, 0x2c0, 8)
97 CCU_RESET(RST_BUS_MMC1, 0x2c0, 9)
98 CCU_RESET(RST_BUS_MMC2, 0x2c0, 10)
99 CCU_RESET(RST_BUS_NAND, 0x2c0, 13)
100 CCU_RESET(RST_BUS_DRAM, 0x2c0, 14)
101 CCU_RESET(RST_BUS_EMAC, 0x2c0, 17)
102 CCU_RESET(RST_BUS_HSTIMER, 0x2c0, 19)
103 CCU_RESET(RST_BUS_SPI0, 0x2c0, 20)
104 CCU_RESET(RST_BUS_SPI1, 0x2c0, 21)
105 CCU_RESET(RST_BUS_OTG, 0x2c0, 24)
106 CCU_RESET(RST_BUS_EHCI0, 0x2c0, 26)
107 CCU_RESET(RST_BUS_EHCI1, 0x2c0, 27)
108 CCU_RESET(RST_BUS_OHCI0, 0x2c0, 29)
110 CCU_RESET(RST_BUS_VE, 0x2c4, 0)
111 CCU_RESET(RST_BUS_TCON0, 0x2c4, 4)
112 CCU_RESET(RST_BUS_TCON1, 0x2c4, 5)
113 CCU_RESET(RST_BUS_CSI, 0x2c4, 8)
114 CCU_RESET(RST_BUS_HDMI0, 0x2c4, 10)
115 CCU_RESET(RST_BUS_HDMI1, 0x2c4, 11)
116 CCU_RESET(RST_BUS_DE, 0x2c4, 12)
117 CCU_RESET(RST_BUS_GPU, 0x2c4, 20)
118 CCU_RESET(RST_BUS_MSGBOX, 0x2c4, 21)
119 CCU_RESET(RST_BUS_SPINLOCK, 0x2c4, 22)
121 CCU_RESET(RST_BUS_LVDS, 0x2c8, 0)
123 CCU_RESET(RST_BUS_SPDIF, 0x2d0, 1)
124 CCU_RESET(RST_BUS_I2S0, 0x2d0, 12)
125 CCU_RESET(RST_BUS_I2S1, 0x2d0, 13)
126 CCU_RESET(RST_BUS_I2S2, 0x2d0, 14)
127 CCU_RESET(RST_BUS_TDM, 0x2d0, 15)
129 CCU_RESET(RST_BUS_I2C0, 0x2d8, 0)
130 CCU_RESET(RST_BUS_I2C1, 0x2d8, 1)
131 CCU_RESET(RST_BUS_I2C2, 0x2d8, 2)
132 CCU_RESET(RST_BUS_UART0, 0x2d8, 16)
133 CCU_RESET(RST_BUS_UART1, 0x2d8, 17)
134 CCU_RESET(RST_BUS_UART2, 0x2d8, 18)
135 CCU_RESET(RST_BUS_UART3, 0x2d8, 19)
136 CCU_RESET(RST_BUS_UART4, 0x2d8, 20)
139 static struct aw_ccung_gate a83t_ccu_gates[] = {
140 CCU_GATE(CLK_BUS_MIPI_DSI, "bus-mipi-dsi", "ahb1", 0x60, 1)
141 CCU_GATE(CLK_BUS_SS, "bus-ss", "ahb1", 0x60, 5)
142 CCU_GATE(CLK_BUS_DMA, "bus-dma", "ahb1", 0x60, 6)
143 CCU_GATE(CLK_BUS_MMC0, "bus-mmc0", "ahb1", 0x60, 8)
144 CCU_GATE(CLK_BUS_MMC1, "bus-mmc1", "ahb1", 0x60, 9)
145 CCU_GATE(CLK_BUS_MMC2, "bus-mmc2", "ahb1", 0x60, 10)
146 CCU_GATE(CLK_BUS_NAND, "bus-nand", "ahb1", 0x60, 13)
147 CCU_GATE(CLK_BUS_DRAM, "bus-dram", "ahb1", 0x60, 14)
148 CCU_GATE(CLK_BUS_EMAC, "bus-emac", "ahb1", 0x60, 17)
149 CCU_GATE(CLK_BUS_HSTIMER, "bus-hstimer", "ahb1", 0x60, 19)
150 CCU_GATE(CLK_BUS_SPI0, "bus-spi0", "ahb1", 0x60, 20)
151 CCU_GATE(CLK_BUS_SPI1, "bus-spi1", "ahb1", 0x60, 21)
152 CCU_GATE(CLK_BUS_OTG, "bus-otg", "ahb1", 0x60, 24)
153 CCU_GATE(CLK_BUS_EHCI0, "bus-ehci0", "ahb2", 0x60, 26)
154 CCU_GATE(CLK_BUS_EHCI1, "bus-ehci1", "ahb2", 0x60, 27)
155 CCU_GATE(CLK_BUS_OHCI0, "bus-ohci0", "ahb2", 0x60, 29)
157 CCU_GATE(CLK_BUS_VE, "bus-ve", "ahb1", 0x64, 0)
158 CCU_GATE(CLK_BUS_TCON0, "bus-tcon0", "ahb1", 0x64, 4)
159 CCU_GATE(CLK_BUS_TCON1, "bus-tcon1", "ahb1", 0x64, 5)
160 CCU_GATE(CLK_BUS_CSI, "bus-csi", "ahb1", 0x64, 8)
161 CCU_GATE(CLK_BUS_HDMI, "bus-hdmi", "ahb1", 0x64, 11)
162 CCU_GATE(CLK_BUS_DE, "bus-de", "ahb1", 0x64, 12)
163 CCU_GATE(CLK_BUS_GPU, "bus-gpu", "ahb1", 0x64, 20)
164 CCU_GATE(CLK_BUS_MSGBOX, "bus-msgbox", "ahb1", 0x64, 21)
165 CCU_GATE(CLK_BUS_SPINLOCK, "bus-spinlock", "ahb1", 0x64, 22)
167 CCU_GATE(CLK_BUS_SPDIF, "bus-spdif", "apb1", 0x68, 1)
168 CCU_GATE(CLK_BUS_PIO, "bus-pio", "apb1", 0x68, 5)
169 CCU_GATE(CLK_BUS_I2S0, "bus-i2s0", "apb1", 0x68, 12)
170 CCU_GATE(CLK_BUS_I2S1, "bus-i2s1", "apb1", 0x68, 13)
171 CCU_GATE(CLK_BUS_I2S2, "bus-i2s2", "apb1", 0x68, 14)
172 CCU_GATE(CLK_BUS_TDM, "bus-tdm", "apb1", 0x68, 15)
174 CCU_GATE(CLK_BUS_I2C0, "bus-i2c0", "apb2", 0x6c, 0)
175 CCU_GATE(CLK_BUS_I2C1, "bus-i2c1", "apb2", 0x6c, 1)
176 CCU_GATE(CLK_BUS_I2C2, "bus-i2c2", "apb2", 0x6c, 2)
177 CCU_GATE(CLK_BUS_UART0, "bus-uart0", "apb2", 0x6c, 16)
178 CCU_GATE(CLK_BUS_UART1, "bus-uart1", "apb2", 0x6c, 17)
179 CCU_GATE(CLK_BUS_UART2, "bus-uart2", "apb2", 0x6c, 18)
180 CCU_GATE(CLK_BUS_UART3, "bus-uart3", "apb2", 0x6c, 19)
181 CCU_GATE(CLK_BUS_UART4, "bus-uart4", "apb2", 0x6c, 20)
183 CCU_GATE(CLK_USB_PHY0, "usb-phy0", "osc24M", 0xcc, 8)
184 CCU_GATE(CLK_USB_PHY1, "usb-phy1", "osc24M", 0xcc, 9)
185 CCU_GATE(CLK_USB_HSIC, "usb-hsic", "pll_hsic", 0xcc, 10)
186 CCU_GATE(CLK_USB_HSIC_12M, "usb-hsic-12M", "osc12M", 0xcc, 11)
187 CCU_GATE(CLK_USB_OHCI0, "usb-ohci0", "osc12M", 0xcc, 16)
189 CCU_GATE(CLK_DRAM_VE, "dram-ve", "dram", 0x100, 0)
190 CCU_GATE(CLK_DRAM_CSI, "dram-csi", "dram", 0x100, 1)
192 CCU_GATE(CLK_CSI_MISC, "csi-misc", "osc24M", 0x130, 16)
193 CCU_GATE(CLK_MIPI_CSI, "mipi-csi", "osc24M", 0x130, 31)
195 CCU_GATE(CLK_AVS, "avs", "osc24M", 0x144, 31)
197 CCU_GATE(CLK_HDMI_SLOW, "hdmi-ddc", "osc24M", 0x154, 31)
200 static const char *osc12m_parents[] = {"osc24M"};
201 FIXED_CLK(osc12m_clk,
202 CLK_OSC_12M, /* id */
203 "osc12M", osc12m_parents, /* name, parents */
209 /* CPU PLL are 24Mhz * N / P */
210 static const char *pll_c0cpux_parents[] = {"osc24M"};
211 static const char *pll_c1cpux_parents[] = {"osc24M"};
212 NKMP_CLK(pll_c0cpux_clk,
213 CLK_PLL_C0CPUX, /* id */
214 "pll_c0cpux", pll_c0cpux_parents, /* name, parents */
216 8, 8, 0, AW_CLK_FACTOR_ZERO_BASED, /* n factor */
217 0, 0, 1, AW_CLK_FACTOR_FIXED, /* k factor (fake) */
218 0, 0, 1, AW_CLK_FACTOR_FIXED, /* m factor */
219 0, 0, 1, AW_CLK_FACTOR_FIXED, /* p factor (fake) */
222 AW_CLK_HAS_GATE | AW_CLK_SCALE_CHANGE); /* flags */
223 NKMP_CLK(pll_c1cpux_clk,
224 CLK_PLL_C1CPUX, /* id */
225 "pll_c1cpux", pll_c1cpux_parents, /* name, parents */
227 8, 8, 0, AW_CLK_FACTOR_ZERO_BASED, /* n factor */
228 0, 0, 1, AW_CLK_FACTOR_FIXED, /* k factor (fake) */
229 0, 0, 1, AW_CLK_FACTOR_FIXED, /* m factor */
230 0, 0, 1, AW_CLK_FACTOR_FIXED, /* p factor (fake) */
233 AW_CLK_HAS_GATE | AW_CLK_SCALE_CHANGE); /* flags */
235 static const char *pll_audio_parents[] = {"osc24M"};
236 NKMP_CLK(pll_audio_clk,
237 CLK_PLL_AUDIO, /* id */
238 "pll_audio", pll_audio_parents, /* name, parents */
240 8, 8, 0, AW_CLK_FACTOR_ZERO_BASED, /* n factor */
241 0, 0, 1, AW_CLK_FACTOR_FIXED, /* k factor (fake) */
242 16, 1, 0, 0, /* m factor */
243 18, 1, 0, 0, /* p factor */
246 AW_CLK_HAS_GATE); /* flags */
248 static const char *pll_video0_parents[] = {"osc24M"};
249 NKMP_CLK(pll_video0_clk,
250 CLK_PLL_VIDEO0, /* id */
251 "pll_video0", pll_video0_parents, /* name, parents */
253 8, 8, 0, AW_CLK_FACTOR_ZERO_BASED, /* n factor */
254 0, 0, 1, AW_CLK_FACTOR_FIXED, /* k factor (fake) */
255 16, 1, 0, 0, /* m factor */
256 0, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* p factor */
259 AW_CLK_HAS_GATE); /* flags */
261 static const char *pll_ve_parents[] = {"osc24M"};
264 "pll_ve", pll_ve_parents, /* name, parents */
266 8, 8, 0, AW_CLK_FACTOR_ZERO_BASED, /* n factor */
267 0, 0, 1, AW_CLK_FACTOR_FIXED, /* k factor (fake) */
268 16, 1, 0, 0, /* m factor */
269 18, 1, 0, 0, /* p factor */
272 AW_CLK_HAS_GATE); /* flags */
274 static const char *pll_ddr_parents[] = {"osc24M"};
275 NKMP_CLK(pll_ddr_clk,
276 CLK_PLL_DDR, /* id */
277 "pll_ddr", pll_ddr_parents, /* name, parents */
279 8, 5, 0, 0, /* n factor */
280 0, 0, 1, AW_CLK_FACTOR_FIXED, /* k factor (fake) */
281 16, 1, 0, 0, /* m factor */
282 18, 1, 0, 0, /* p factor */
285 AW_CLK_HAS_GATE); /* flags */
287 static const char *pll_periph_parents[] = {"osc24M"};
288 NKMP_CLK(pll_periph_clk,
289 CLK_PLL_PERIPH, /* id */
290 "pll_periph", pll_periph_parents, /* name, parents */
292 8, 8, 0, AW_CLK_FACTOR_ZERO_BASED, /* n factor */
293 0, 0, 1, AW_CLK_FACTOR_FIXED, /* k factor (fake) */
294 16, 1, 1, 0, /* m factor */
295 18, 1, 1, 0, /* p factor */
298 AW_CLK_HAS_GATE); /* flags */
300 static const char *pll_gpu_parents[] = {"osc24M"};
301 NKMP_CLK(pll_gpu_clk,
302 CLK_PLL_GPU, /* id */
303 "pll_gpu", pll_gpu_parents, /* name, parents */
305 8, 8, 0, AW_CLK_FACTOR_ZERO_BASED, /* n factor */
306 0, 0, 1, AW_CLK_FACTOR_FIXED, /* k factor (fake) */
307 16, 1, 1, 0, /* m factor */
308 18, 1, 1, 0, /* p factor */
311 AW_CLK_HAS_GATE); /* flags */
313 static const char *pll_hsic_parents[] = {"osc24M"};
314 NKMP_CLK(pll_hsic_clk,
315 CLK_PLL_HSIC, /* id */
316 "pll_hsic", pll_hsic_parents, /* name, parents */
318 8, 8, 0, AW_CLK_FACTOR_ZERO_BASED, /* n factor */
319 0, 0, 1, AW_CLK_FACTOR_FIXED, /* k factor (fake) */
320 16, 1, 1, 0, /* m factor */
321 18, 1, 1, 0, /* p factor */
324 AW_CLK_HAS_GATE); /* flags */
326 static const char *pll_de_parents[] = {"osc24M"};
329 "pll_de", pll_de_parents, /* name, parents */
331 8, 8, 0, AW_CLK_FACTOR_ZERO_BASED, /* n factor */
332 0, 0, 1, AW_CLK_FACTOR_FIXED, /* k factor (fake) */
333 16, 1, 1, 0, /* m factor */
334 18, 1, 1, 0, /* p factor */
337 AW_CLK_HAS_GATE); /* flags */
339 static const char *pll_video1_parents[] = {"osc24M"};
340 NKMP_CLK(pll_video1_clk,
341 CLK_PLL_VIDEO1, /* id */
342 "pll_video1", pll_video1_parents, /* name, parents */
344 8, 8, 0, AW_CLK_FACTOR_ZERO_BASED, /* n factor */
345 0, 0, 1, AW_CLK_FACTOR_FIXED, /* k factor (fake) */
346 16, 1, 1, 0, /* m factor */
347 0, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* p factor */
350 AW_CLK_HAS_GATE); /* flags */
352 static const char *c0cpux_parents[] = {"osc24M", "pll_c0cpux"};
355 "c0cpux", c0cpux_parents, /* name, parents */
356 0x50, 12, 1); /* offset, shift, width */
358 static const char *c1cpux_parents[] = {"osc24M", "pll_c1cpux"};
361 "c1cpux", c1cpux_parents, /* name, parents */
362 0x50, 28, 1); /* offset, shift, width */
364 static const char *axi0_parents[] = {"c0cpux"};
367 "axi0", axi0_parents, /* name, parents */
369 0, 2, /* shift, width */
370 0, NULL); /* flags, div table */
372 static const char *axi1_parents[] = {"c1cpux"};
375 "axi1", axi1_parents, /* name, parents */
377 16, 2, /* shift, width */
378 0, NULL); /* flags, div table */
380 static const char *ahb1_parents[] = {"osc16M-d512", "osc24M", "pll_periph", "pll_periph"};
381 PREDIV_CLK_WITH_MASK(ahb1_clk,
383 "ahb1", ahb1_parents, /* name, parents */
386 4, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* div */
387 6, 2, 0, AW_CLK_FACTOR_HAS_COND, /* prediv */
388 (2 << 12), (2 << 12)); /* prediv condition */
390 static const char *apb1_parents[] = {"ahb1"};
393 "apb1", apb1_parents, /* name, parents */
395 8, 2, /* shift, width */
396 0, NULL); /* flags, div table */
398 static const char *apb2_parents[] = {"osc16M-d512", "osc24M", "pll_periph", "pll_periph"};
401 "apb2", apb2_parents, /* name, parents */
403 16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
404 0, 5, 0, 0, /* m factor */
409 static const char *ahb2_parents[] = {"ahb1", "pll_periph"};
412 "ahb2", ahb2_parents, /* name, parents */
415 0, 0, 1, AW_CLK_FACTOR_FIXED, /* div (fake) */
416 0, 0, 2, AW_CLK_FACTOR_HAS_COND | AW_CLK_FACTOR_FIXED, /* prediv */
417 0, 2, 1); /* prediv cond */
419 /* Actually has a divider, but we don't use it */
420 static const char *cci400_parents[] = {"osc24M", "pll_periph", "pll_hsic"};
423 "cci400", cci400_parents, /* name, parents */
424 0x78, 24, 2); /* offset, shift, width */
426 static const char *mod_parents[] = {"osc24M", "pll_periph"};
430 "nand", mod_parents, /* name, parents */
432 16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
433 0, 4, 0, 0, /* m factor */
436 AW_CLK_HAS_GATE | AW_CLK_HAS_MUX);
440 "mmc0", mod_parents, /* name, parents */
442 16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
443 0, 4, 0, 0, /* m factor */
446 AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
450 "mmc1", mod_parents, /* name, parents */
452 16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
453 0, 4, 0, 0, /* m factor */
456 AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
460 "mmc2", mod_parents, /* name, parents */
462 16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
463 0, 4, 0, 0, /* m factor */
466 AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
471 "ss", mod_parents, /* name, parents */
473 16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
474 0, 4, 0, 0, /* m factor */
477 AW_CLK_HAS_GATE | AW_CLK_HAS_MUX);
481 "spi0", mod_parents, /* name, parents */
483 16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
484 0, 4, 0, 0, /* m factor */
487 AW_CLK_HAS_GATE | AW_CLK_HAS_MUX);
490 "spi1", mod_parents, /* name, parents */
492 16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
493 0, 4, 0, 0, /* m factor */
496 AW_CLK_HAS_GATE | AW_CLK_HAS_MUX);
498 static const char *daudio_parents[] = {"pll_audio"};
501 "i2s0", daudio_parents, /* name, parents */
503 0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
504 0, 4, 0, 0, /* m factor */
510 "i2s1", daudio_parents, /* name, parents */
512 0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
513 0, 4, 0, 0, /* m factor */
519 "i2s2", daudio_parents, /* name, parents */
521 0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
522 0, 4, 0, 0, /* m factor */
527 static const char *tdm_parents[] = {"pll_audio"};
530 "tdm", tdm_parents, /* name, parents */
532 0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
533 0, 4, 0, 0, /* m factor */
538 static const char *spdif_parents[] = {"pll_audio"};
541 "spdif", spdif_parents, /* name, parents */
543 0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
544 0, 4, 0, 0, /* m factor */
549 static const char *dram_parents[] = {"pll_ddr"};
552 "dram", dram_parents, /* name, parents */
554 0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
555 0, 4, 0, 0, /* m factor */
560 static const char *tcon0_parents[] = {"pll_video0"};
563 "tcon0", tcon0_parents, /* name, parents */
564 0x118, 24, 2); /* offset, shift, width */
566 static const char *tcon1_parents[] = {"pll_video1"};
569 "tcon1", tcon1_parents, /* name, parents */
571 0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
572 0, 4, 0, 0, /* m factor */
577 static const char *csi_mclk_parents[] = {"pll_de", "osc24M"};
579 CLK_CSI_MCLK, /* id */
580 "csi-mclk", csi_mclk_parents, /* name, parents */
582 0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
583 0, 4, 0, 0, /* m factor */
586 AW_CLK_HAS_MUX | AW_CLK_HAS_GATE);
588 static const char *csi_sclk_parents[] = {"pll_periph", "pll_ve"};
590 CLK_CSI_SCLK, /* id */
591 "csi-sclk", csi_sclk_parents, /* name, parents */
593 0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
594 16, 4, 0, 0, /* m factor */
597 AW_CLK_HAS_MUX | AW_CLK_HAS_GATE);
599 static const char *ve_parents[] = {"pll_ve"};
602 "ve", ve_parents, /* name, parents */
604 0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
605 16, 3, 0, 0, /* m factor */
610 static const char *hdmi_parents[] = {"pll_video1"};
613 "hdmi", hdmi_parents, /* name, parents */
615 0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
616 0, 4, 0, 0, /* m factor */
619 AW_CLK_HAS_MUX | AW_CLK_HAS_GATE);
621 static const char *mbus_parents[] = {"osc24M", "pll_periph", "pll_ddr"};
624 "mbus", mbus_parents, /* name, parents */
626 0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
627 0, 3, 0, 0, /* m factor */
630 AW_CLK_HAS_MUX | AW_CLK_HAS_GATE);
632 static const char *mipi_dsi0_parents[] = {"pll_video0"};
633 NM_CLK(mipi_dsi0_clk,
634 CLK_MIPI_DSI0, /* id */
635 "mipi-dsi0", mipi_dsi0_parents, /* name, parents */
637 0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
638 0, 4, 0, 0, /* m factor */
641 AW_CLK_HAS_MUX | AW_CLK_HAS_GATE);
643 static const char *mipi_dsi1_parents[] = {"osc24M", "pll_video0"};
644 NM_CLK(mipi_dsi1_clk,
645 CLK_MIPI_DSI1, /* id */
646 "mipi-dsi1", mipi_dsi1_parents, /* name, parents */
648 0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
649 0, 4, 0, 0, /* m factor */
652 AW_CLK_HAS_MUX | AW_CLK_HAS_GATE);
654 static const char *gpu_core_parents[] = {"pll_gpu"};
656 CLK_GPU_CORE, /* id */
657 "gpu-core", gpu_core_parents, /* name, parents */
659 0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
660 0, 3, 0, 0, /* m factor */
665 static const char *gpu_memory_parents[] = {"pll_gpu", "pll_periph"};
666 NM_CLK(gpu_memory_clk,
667 CLK_GPU_MEMORY, /* id */
668 "gpu-memory", gpu_memory_parents, /* name, parents */
670 0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
671 0, 3, 0, 0, /* m factor */
674 AW_CLK_HAS_MUX | AW_CLK_HAS_GATE);
676 static const char *gpu_hyd_parents[] = {"pll_gpu"};
678 CLK_GPU_HYD, /* id */
679 "gpu-hyd", gpu_hyd_parents, /* name, parents */
681 0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
682 0, 3, 0, 0, /* m factor */
687 static struct aw_ccung_clk a83t_clks[] = {
688 { .type = AW_CLK_NKMP, .clk.nkmp = &pll_audio_clk},
689 { .type = AW_CLK_NKMP, .clk.nkmp = &pll_video0_clk},
690 { .type = AW_CLK_NKMP, .clk.nkmp = &pll_ve_clk},
691 { .type = AW_CLK_NKMP, .clk.nkmp = &pll_ddr_clk},
692 { .type = AW_CLK_NKMP, .clk.nkmp = &pll_periph_clk},
693 { .type = AW_CLK_NKMP, .clk.nkmp = &pll_gpu_clk},
694 { .type = AW_CLK_NKMP, .clk.nkmp = &pll_hsic_clk},
695 { .type = AW_CLK_NKMP, .clk.nkmp = &pll_de_clk},
696 { .type = AW_CLK_NKMP, .clk.nkmp = &pll_video1_clk},
697 { .type = AW_CLK_NKMP, .clk.nkmp = &pll_c0cpux_clk},
698 { .type = AW_CLK_NKMP, .clk.nkmp = &pll_c1cpux_clk},
699 { .type = AW_CLK_NM, .clk.nm = &apb2_clk},
700 { .type = AW_CLK_NM, .clk.nm = &nand_clk},
701 { .type = AW_CLK_NM, .clk.nm = &mmc0_clk},
702 { .type = AW_CLK_NM, .clk.nm = &mmc1_clk},
703 { .type = AW_CLK_NM, .clk.nm = &mmc2_clk},
704 { .type = AW_CLK_NM, .clk.nm = &ss_clk},
705 { .type = AW_CLK_NM, .clk.nm = &spi0_clk},
706 { .type = AW_CLK_NM, .clk.nm = &spi1_clk},
707 { .type = AW_CLK_NM, .clk.nm = &i2s0_clk},
708 { .type = AW_CLK_NM, .clk.nm = &i2s1_clk},
709 { .type = AW_CLK_NM, .clk.nm = &i2s2_clk},
710 { .type = AW_CLK_NM, .clk.nm = &tdm_clk},
711 { .type = AW_CLK_NM, .clk.nm = &spdif_clk},
712 { .type = AW_CLK_NM, .clk.nm = &dram_clk},
713 { .type = AW_CLK_NM, .clk.nm = &tcon1_clk},
714 { .type = AW_CLK_NM, .clk.nm = &csi_mclk_clk},
715 { .type = AW_CLK_NM, .clk.nm = &csi_sclk_clk},
716 { .type = AW_CLK_NM, .clk.nm = &ve_clk},
717 { .type = AW_CLK_NM, .clk.nm = &hdmi_clk},
718 { .type = AW_CLK_NM, .clk.nm = &mbus_clk},
719 { .type = AW_CLK_NM, .clk.nm = &mipi_dsi0_clk},
720 { .type = AW_CLK_NM, .clk.nm = &mipi_dsi1_clk},
721 { .type = AW_CLK_NM, .clk.nm = &gpu_core_clk},
722 { .type = AW_CLK_NM, .clk.nm = &gpu_memory_clk},
723 { .type = AW_CLK_NM, .clk.nm = &gpu_hyd_clk},
724 { .type = AW_CLK_PREDIV_MUX, .clk.prediv_mux = &ahb1_clk},
725 { .type = AW_CLK_PREDIV_MUX, .clk.prediv_mux = &ahb2_clk},
726 { .type = AW_CLK_MUX, .clk.mux = &c0cpux_clk},
727 { .type = AW_CLK_MUX, .clk.mux = &c1cpux_clk},
728 { .type = AW_CLK_MUX, .clk.mux = &cci400_clk},
729 { .type = AW_CLK_MUX, .clk.mux = &tcon0_clk},
730 { .type = AW_CLK_DIV, .clk.div = &axi0_clk},
731 { .type = AW_CLK_DIV, .clk.div = &axi1_clk},
732 { .type = AW_CLK_DIV, .clk.div = &apb1_clk},
733 { .type = AW_CLK_FIXED, .clk.fixed = &osc12m_clk},
736 static struct aw_clk_init a83t_init_clks[] = {
737 {"ahb1", "pll_periph", 0, false},
738 {"ahb2", "ahb1", 0, false},
739 {"dram", "pll_ddr", 0, false},
743 ccu_a83t_probe(device_t dev)
746 if (!ofw_bus_status_okay(dev))
749 if (!ofw_bus_is_compatible(dev, "allwinner,sun8i-a83t-ccu"))
752 device_set_desc(dev, "Allwinner A83T Clock Control Unit NG");
753 return (BUS_PROBE_DEFAULT);
757 ccu_a83t_attach(device_t dev)
759 struct aw_ccung_softc *sc;
761 sc = device_get_softc(dev);
763 sc->resets = a83t_ccu_resets;
764 sc->nresets = nitems(a83t_ccu_resets);
765 sc->gates = a83t_ccu_gates;
766 sc->ngates = nitems(a83t_ccu_gates);
767 sc->clks = a83t_clks;
768 sc->nclks = nitems(a83t_clks);
769 sc->clk_init = a83t_init_clks;
770 sc->n_clk_init = nitems(a83t_init_clks);
772 return (aw_ccung_attach(dev));
775 static device_method_t ccu_a83tng_methods[] = {
776 /* Device interface */
777 DEVMETHOD(device_probe, ccu_a83t_probe),
778 DEVMETHOD(device_attach, ccu_a83t_attach),
783 static devclass_t ccu_a83tng_devclass;
785 DEFINE_CLASS_1(ccu_a83tng, ccu_a83tng_driver, ccu_a83tng_methods,
786 sizeof(struct aw_ccung_softc), aw_ccung_driver);
788 EARLY_DRIVER_MODULE(ccu_a83tng, simplebus, ccu_a83tng_driver,
789 ccu_a83tng_devclass, 0, 0, BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);