1*245cdec7STom Jones /*-
2*245cdec7STom Jones * SPDX-License-Identifier: BSD-2-Clause
3*245cdec7STom Jones *
4*245cdec7STom Jones * Copyright (c) 2019 Emmanuel Vadot <manu@freebsd.org>
5*245cdec7STom Jones * Copyright (c) 2025 The FreeBSD Foundation
6*245cdec7STom Jones *
7*245cdec7STom Jones * Portions of this file were written by Tom Jones <thj@freebsd.org> under
8*245cdec7STom Jones * sponsorship from The FreeBSD Foundation.
9*245cdec7STom Jones *
10*245cdec7STom Jones */
11*245cdec7STom Jones
12*245cdec7STom Jones #include <sys/param.h>
13*245cdec7STom Jones #include <sys/systm.h>
14*245cdec7STom Jones #include <sys/bus.h>
15*245cdec7STom Jones #include <sys/rman.h>
16*245cdec7STom Jones #include <sys/kernel.h>
17*245cdec7STom Jones #include <sys/module.h>
18*245cdec7STom Jones #include <machine/bus.h>
19*245cdec7STom Jones
20*245cdec7STom Jones #include <dev/fdt/simplebus.h>
21*245cdec7STom Jones
22*245cdec7STom Jones #include <dev/ofw/ofw_bus.h>
23*245cdec7STom Jones #include <dev/ofw/ofw_bus_subr.h>
24*245cdec7STom Jones
25*245cdec7STom Jones #include <dev/clk/clk_div.h>
26*245cdec7STom Jones #include <dev/clk/clk_fixed.h>
27*245cdec7STom Jones #include <dev/clk/clk_mux.h>
28*245cdec7STom Jones
29*245cdec7STom Jones #include <dev/clk/allwinner/aw_ccung.h>
30*245cdec7STom Jones
31*245cdec7STom Jones #include <dt-bindings/clock/sun50i-h616-ccu.h>
32*245cdec7STom Jones #include <dt-bindings/reset/sun50i-h616-ccu.h>
33*245cdec7STom Jones
34*245cdec7STom Jones /* Non-exported clocks */
35*245cdec7STom Jones #define CLK_OSC_24M 0
36*245cdec7STom Jones #define CLK_PLL_CPUX 1
37*245cdec7STom Jones #define CLK_PLL_AUDIO 2
38*245cdec7STom Jones #define CLK_PLL_PERIPH0_2X 4
39*245cdec7STom Jones #define CLK_PLL_PERIPH1_2X 5
40*245cdec7STom Jones #define CLK_PLL_PERIPH1 6
41*245cdec7STom Jones #define CLK_PLL_VIDEO0_4X 8
42*245cdec7STom Jones #define CLK_PLL_VIDEO1_4X 9
43*245cdec7STom Jones #define CLK_PLL_VIDEO0 10
44*245cdec7STom Jones #define CLK_PLL_VIDEO1 12
45*245cdec7STom Jones #define CLK_PLL_VIDEO2 12
46*245cdec7STom Jones #define CLK_PLL_VE 14
47*245cdec7STom Jones #define CLK_PLL_DDR0 9
48*245cdec7STom Jones #define CLK_PLL_DDR1 9
49*245cdec7STom Jones #define CLK_PLL_DE 14
50*245cdec7STom Jones #define CLK_PLL_GPU 16
51*245cdec7STom Jones
52*245cdec7STom Jones #define CLK_PSI_AHB1_AHB2 24
53*245cdec7STom Jones #define CLK_AHB3 25
54*245cdec7STom Jones #define CLK_APB2 27
55*245cdec7STom Jones
56*245cdec7STom Jones static struct aw_ccung_reset h616_ccu_resets[] = {
57*245cdec7STom Jones /* PSI_BGR_REG */
58*245cdec7STom Jones CCU_RESET(RST_BUS_PSI, 0x79c, 16)
59*245cdec7STom Jones
60*245cdec7STom Jones /* SMHC_BGR_REG */
61*245cdec7STom Jones CCU_RESET(RST_BUS_MMC0, 0x84c, 16)
62*245cdec7STom Jones CCU_RESET(RST_BUS_MMC1, 0x84c, 17)
63*245cdec7STom Jones CCU_RESET(RST_BUS_MMC2, 0x84c, 18)
64*245cdec7STom Jones
65*245cdec7STom Jones /* UART_BGR_REG */
66*245cdec7STom Jones CCU_RESET(RST_BUS_UART0, 0x90c, 16)
67*245cdec7STom Jones CCU_RESET(RST_BUS_UART1, 0x90c, 17)
68*245cdec7STom Jones CCU_RESET(RST_BUS_UART2, 0x90c, 18)
69*245cdec7STom Jones CCU_RESET(RST_BUS_UART3, 0x90c, 19)
70*245cdec7STom Jones CCU_RESET(RST_BUS_UART4, 0x90c, 20)
71*245cdec7STom Jones CCU_RESET(RST_BUS_UART5, 0x90c, 21)
72*245cdec7STom Jones
73*245cdec7STom Jones /* TWI_BGR_REG */
74*245cdec7STom Jones CCU_RESET(RST_BUS_I2C0, 0x91c, 16)
75*245cdec7STom Jones CCU_RESET(RST_BUS_I2C1, 0x91c, 17)
76*245cdec7STom Jones CCU_RESET(RST_BUS_I2C2, 0x91c, 18)
77*245cdec7STom Jones CCU_RESET(RST_BUS_I2C3, 0x91c, 19)
78*245cdec7STom Jones CCU_RESET(RST_BUS_I2C4, 0x91c, 20)
79*245cdec7STom Jones
80*245cdec7STom Jones /* EMAC_BGR_REG */
81*245cdec7STom Jones CCU_RESET(RST_BUS_EMAC0, 0x97c, 16)
82*245cdec7STom Jones CCU_RESET(RST_BUS_EMAC1, 0x97c, 17)
83*245cdec7STom Jones
84*245cdec7STom Jones /* USB0_CLK_REG */
85*245cdec7STom Jones CCU_RESET(RST_USB_PHY0, 0xa70, 30)
86*245cdec7STom Jones
87*245cdec7STom Jones /* USB1_CLK_REG */
88*245cdec7STom Jones CCU_RESET(RST_USB_PHY1, 0xa74, 30)
89*245cdec7STom Jones
90*245cdec7STom Jones /* USB2_CLK_REG */
91*245cdec7STom Jones CCU_RESET(RST_USB_PHY2, 0xa78, 30)
92*245cdec7STom Jones
93*245cdec7STom Jones /* USB2_CLK_REG */
94*245cdec7STom Jones CCU_RESET(RST_USB_PHY3, 0xa7c, 30)
95*245cdec7STom Jones
96*245cdec7STom Jones /* USB_BGR_REG */
97*245cdec7STom Jones CCU_RESET(RST_BUS_OHCI0, 0xa8c, 16)
98*245cdec7STom Jones CCU_RESET(RST_BUS_OHCI1, 0xa8c, 17)
99*245cdec7STom Jones CCU_RESET(RST_BUS_OHCI2, 0xa8c, 18)
100*245cdec7STom Jones CCU_RESET(RST_BUS_OHCI3, 0xa8c, 19)
101*245cdec7STom Jones CCU_RESET(RST_BUS_EHCI0, 0xa8c, 20)
102*245cdec7STom Jones CCU_RESET(RST_BUS_EHCI1, 0xa8c, 21)
103*245cdec7STom Jones CCU_RESET(RST_BUS_EHCI2, 0xa8c, 22)
104*245cdec7STom Jones CCU_RESET(RST_BUS_EHCI3, 0xa8c, 23)
105*245cdec7STom Jones CCU_RESET(RST_BUS_OTG, 0xa8c, 24)
106*245cdec7STom Jones };
107*245cdec7STom Jones
108*245cdec7STom Jones static struct aw_ccung_gate h616_ccu_gates[] = {
109*245cdec7STom Jones /* PSI_BGR_REG */
110*245cdec7STom Jones CCU_GATE(CLK_BUS_PSI, "bus-psi", "psi_ahb1_ahb2", 0x79c, 0)
111*245cdec7STom Jones
112*245cdec7STom Jones /* SMHC_BGR_REG */
113*245cdec7STom Jones CCU_GATE(CLK_BUS_MMC0, "bus-mmc0", "ahb3", 0x84c, 0)
114*245cdec7STom Jones CCU_GATE(CLK_BUS_MMC1, "bus-mmc1", "ahb3", 0x84c, 1)
115*245cdec7STom Jones CCU_GATE(CLK_BUS_MMC2, "bus-mmc2", "ahb3", 0x84c, 2)
116*245cdec7STom Jones
117*245cdec7STom Jones /*
118*245cdec7STom Jones * XXX-THJ: Inheritied comment from H6:
119*245cdec7STom Jones * UART_BGR_REG Enabling the gate enable weird behavior ...
120*245cdec7STom Jones */
121*245cdec7STom Jones /* CCU_GATE(CLK_BUS_UART0, "bus-uart0", "apb2", 0x90c, 0) */
122*245cdec7STom Jones /* CCU_GATE(CLK_BUS_UART1, "bus-uart1", "apb2", 0x90c, 1) */
123*245cdec7STom Jones /* CCU_GATE(CLK_BUS_UART2, "bus-uart2", "apb2", 0x90c, 2) */
124*245cdec7STom Jones /* CCU_GATE(CLK_BUS_UART3, "bus-uart3", "apb2", 0x90c, 3) */
125*245cdec7STom Jones /* CCU_GATE(CLK_BUS_UART4, "bus-uart4", "apb2", 0x90c, 4) */
126*245cdec7STom Jones /* CCU_GATE(CLK_BUS_UART5, "bus-uart5", "apb2", 0x90c, 5) */
127*245cdec7STom Jones
128*245cdec7STom Jones /* TWI_BGR_REG */
129*245cdec7STom Jones CCU_GATE(CLK_BUS_I2C0, "bus-i2c0", "apb2", 0x91c, 0)
130*245cdec7STom Jones CCU_GATE(CLK_BUS_I2C1, "bus-i2c1", "apb2", 0x91c, 1)
131*245cdec7STom Jones CCU_GATE(CLK_BUS_I2C2, "bus-i2c2", "apb2", 0x91c, 2)
132*245cdec7STom Jones CCU_GATE(CLK_BUS_I2C3, "bus-i2c3", "apb2", 0x91c, 3)
133*245cdec7STom Jones
134*245cdec7STom Jones /* EMAC_BGR_REG */
135*245cdec7STom Jones CCU_GATE(CLK_BUS_EMAC0, "bus-emac0", "ahb3", 0x97c, 0)
136*245cdec7STom Jones CCU_GATE(CLK_BUS_EMAC1, "bus-emac1", "ahb3", 0x97c, 1)
137*245cdec7STom Jones
138*245cdec7STom Jones /* USB0_CLK_REG */
139*245cdec7STom Jones CCU_GATE(CLK_USB_PHY0, "usb-phy0", "ahb3", 0xa70, 29)
140*245cdec7STom Jones CCU_GATE(CLK_USB_OHCI0, "usb-ohci0", "ahb3", 0xa70, 31)
141*245cdec7STom Jones
142*245cdec7STom Jones /* USB1_CLK_REG */
143*245cdec7STom Jones CCU_GATE(CLK_USB_PHY1, "usb-phy1", "ahb3", 0xa74, 29)
144*245cdec7STom Jones CCU_GATE(CLK_USB_OHCI1, "usb-ohci1", "ahb3", 0xa74, 31)
145*245cdec7STom Jones
146*245cdec7STom Jones /* USB2_CLK_REG */
147*245cdec7STom Jones CCU_GATE(CLK_USB_PHY2, "usb-phy2", "ahb3", 0xa78, 29)
148*245cdec7STom Jones CCU_GATE(CLK_USB_OHCI2, "usb-ohci2", "ahb3", 0xa78, 31)
149*245cdec7STom Jones
150*245cdec7STom Jones /* USB3_CLK_REG */
151*245cdec7STom Jones CCU_GATE(CLK_USB_PHY3, "usb-phy3", "ahb3", 0xa7c, 29)
152*245cdec7STom Jones CCU_GATE(CLK_USB_OHCI3, "usb-ohci3", "ahb3", 0xa7c, 31)
153*245cdec7STom Jones
154*245cdec7STom Jones /* USB_BGR_REG */
155*245cdec7STom Jones CCU_GATE(CLK_BUS_OHCI0, "bus-ohchi0", "ahb3", 0xa8c, 0)
156*245cdec7STom Jones CCU_GATE(CLK_BUS_OHCI1, "bus-ohchi1", "ahb3", 0xa8c, 1)
157*245cdec7STom Jones CCU_GATE(CLK_BUS_OHCI2, "bus-ohchi2", "ahb3", 0xa8c, 2)
158*245cdec7STom Jones CCU_GATE(CLK_BUS_OHCI3, "bus-ohchi3", "ahb3", 0xa8c, 3)
159*245cdec7STom Jones CCU_GATE(CLK_BUS_EHCI0, "bus-ehchi0", "ahb3", 0xa8c, 4)
160*245cdec7STom Jones CCU_GATE(CLK_BUS_EHCI1, "bus-ehchi1", "ahb3", 0xa8c, 5)
161*245cdec7STom Jones CCU_GATE(CLK_BUS_EHCI2, "bus-ehchi2", "ahb3", 0xa8c, 6)
162*245cdec7STom Jones CCU_GATE(CLK_BUS_EHCI3, "bus-ehchi3", "ahb3", 0xa8c, 7)
163*245cdec7STom Jones CCU_GATE(CLK_BUS_OTG, "bus-otg", "ahb3", 0xa8c, 8)
164*245cdec7STom Jones };
165*245cdec7STom Jones
166*245cdec7STom Jones static const char *pll_cpux_parents[] = {"osc24M"};
167*245cdec7STom Jones NP_CLK(pll_cpux_clk,
168*245cdec7STom Jones CLK_PLL_CPUX, /* id */
169*245cdec7STom Jones "pll_cpux", pll_cpux_parents, /* name, parents */
170*245cdec7STom Jones 0x00, /* offset */
171*245cdec7STom Jones 8, 8, 0, 0, /* n factor */
172*245cdec7STom Jones 16, 2, 0, 0, /* p factor */
173*245cdec7STom Jones 31, /* gate */
174*245cdec7STom Jones 28, 1000, /* lock */
175*245cdec7STom Jones AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
176*245cdec7STom Jones
177*245cdec7STom Jones static const char *pll_ddr0_parents[] = {"osc24M"};
178*245cdec7STom Jones NMM_CLK(pll_ddr0_clk,
179*245cdec7STom Jones CLK_PLL_DDR0, /* id */
180*245cdec7STom Jones "pll_ddr0", pll_ddr0_parents, /* name, parents */
181*245cdec7STom Jones 0x10, /* offset */
182*245cdec7STom Jones 8, 8, 0, 0, /* n factor */
183*245cdec7STom Jones 0, 1, 0, 0, /* m0 factor */
184*245cdec7STom Jones 1, 1, 0, 0, /* m1 factor */
185*245cdec7STom Jones 31, /* gate */
186*245cdec7STom Jones 28, 1000, /* lock */
187*245cdec7STom Jones AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
188*245cdec7STom Jones
189*245cdec7STom Jones static const char *pll_ddr1_parents[] = {"osc24M"};
190*245cdec7STom Jones NMM_CLK(pll_ddr1_clk,
191*245cdec7STom Jones CLK_PLL_DDR1, /* id */
192*245cdec7STom Jones "pll_ddr1", pll_ddr1_parents, /* name, parents */
193*245cdec7STom Jones 0x18, /* offset */
194*245cdec7STom Jones 8, 8, 0, 0, /* n factor */
195*245cdec7STom Jones 0, 1, 0, 0, /* m0 factor */
196*245cdec7STom Jones 1, 1, 0, 0, /* m1 factor */
197*245cdec7STom Jones 31, /* gate */
198*245cdec7STom Jones 28, 1000, /* lock */
199*245cdec7STom Jones AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
200*245cdec7STom Jones
201*245cdec7STom Jones static const char *pll_peri0_2x_parents[] = {"osc24M"};
202*245cdec7STom Jones NMM_CLK(pll_peri0_2x_clk,
203*245cdec7STom Jones CLK_PLL_PERIPH0_2X, /* id */
204*245cdec7STom Jones "pll_periph0_2x", pll_peri0_2x_parents, /* name, parents */
205*245cdec7STom Jones 0x20, /* offset */
206*245cdec7STom Jones 8, 8, 0, 0, /* n factor */
207*245cdec7STom Jones 0, 1, 0, 0, /* m0 factor */
208*245cdec7STom Jones 1, 1, 0, 0, /* m1 factor */
209*245cdec7STom Jones 31, /* gate */
210*245cdec7STom Jones 28, 1000, /* lock */
211*245cdec7STom Jones AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
212*245cdec7STom Jones static const char *pll_peri0_parents[] = {"pll_periph0_2x"};
213*245cdec7STom Jones FIXED_CLK(pll_peri0_clk,
214*245cdec7STom Jones CLK_PLL_PERIPH0, /* id */
215*245cdec7STom Jones "pll_periph0", /* name */
216*245cdec7STom Jones pll_peri0_parents, /* parent */
217*245cdec7STom Jones 0, /* freq */
218*245cdec7STom Jones 1, /* mult */
219*245cdec7STom Jones 2, /* div */
220*245cdec7STom Jones 0); /* flags */
221*245cdec7STom Jones
222*245cdec7STom Jones static const char *pll_peri1_2x_parents[] = {"osc24M"};
223*245cdec7STom Jones NMM_CLK(pll_peri1_2x_clk,
224*245cdec7STom Jones CLK_PLL_PERIPH1_2X, /* id */
225*245cdec7STom Jones "pll_periph1_2x", pll_peri1_2x_parents, /* name, parents */
226*245cdec7STom Jones 0x28, /* offset */
227*245cdec7STom Jones 8, 8, 0, 0, /* n factor */
228*245cdec7STom Jones 0, 1, 0, 0, /* m0 factor */
229*245cdec7STom Jones 1, 1, 0, 0, /* m1 factor */
230*245cdec7STom Jones 31, /* gate */
231*245cdec7STom Jones 28, 1000, /* lock */
232*245cdec7STom Jones AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
233*245cdec7STom Jones static const char *pll_peri1_parents[] = {"pll_periph1_2x"};
234*245cdec7STom Jones FIXED_CLK(pll_peri1_clk,
235*245cdec7STom Jones CLK_PLL_PERIPH1, /* id */
236*245cdec7STom Jones "pll_periph1", /* name */
237*245cdec7STom Jones pll_peri1_parents, /* parent */
238*245cdec7STom Jones 0, /* freq */
239*245cdec7STom Jones 1, /* mult */
240*245cdec7STom Jones 2, /* div */
241*245cdec7STom Jones 0); /* flags */
242*245cdec7STom Jones
243*245cdec7STom Jones static const char *pll_gpu_parents[] = {"osc24M"};
244*245cdec7STom Jones NMM_CLK(pll_gpu_clk,
245*245cdec7STom Jones CLK_PLL_GPU, /* id */
246*245cdec7STom Jones "pll_gpu", pll_gpu_parents, /* name, parents */
247*245cdec7STom Jones 0x30, /* offset */
248*245cdec7STom Jones 8, 8, 0, 0, /* n factor */
249*245cdec7STom Jones 0, 1, 0, 0, /* m0 factor */
250*245cdec7STom Jones 1, 1, 0, 0, /* m1 factor */
251*245cdec7STom Jones 31, /* gate */
252*245cdec7STom Jones 28, 1000, /* lock */
253*245cdec7STom Jones AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
254*245cdec7STom Jones
255*245cdec7STom Jones static const char *pll_video0_4x_parents[] = {"osc24M"};
256*245cdec7STom Jones NMM_CLK(pll_video0_4x_clk,
257*245cdec7STom Jones CLK_PLL_VIDEO0_4X, /* id */
258*245cdec7STom Jones "pll_video0_4x", pll_video0_4x_parents, /* name, parents */
259*245cdec7STom Jones 0x40, /* offset */
260*245cdec7STom Jones 8, 8, 0, 0, /* n factor */
261*245cdec7STom Jones 0, 1, 0, 0, /* m0 factor */
262*245cdec7STom Jones 1, 1, 0, 0, /* m1 factor */
263*245cdec7STom Jones 31, /* gate */
264*245cdec7STom Jones 28, 1000, /* lock */
265*245cdec7STom Jones AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
266*245cdec7STom Jones static const char *pll_video0_parents[] = {"pll_video0_4x"};
267*245cdec7STom Jones FIXED_CLK(pll_video0_clk,
268*245cdec7STom Jones CLK_PLL_VIDEO0, /* id */
269*245cdec7STom Jones "pll_video0", /* name */
270*245cdec7STom Jones pll_video0_parents, /* parent */
271*245cdec7STom Jones 0, /* freq */
272*245cdec7STom Jones 1, /* mult */
273*245cdec7STom Jones 4, /* div */
274*245cdec7STom Jones 0); /* flags */
275*245cdec7STom Jones
276*245cdec7STom Jones static const char *pll_video1_4x_parents[] = {"osc24M"};
277*245cdec7STom Jones NMM_CLK(pll_video1_4x_clk,
278*245cdec7STom Jones CLK_PLL_VIDEO1_4X, /* id */
279*245cdec7STom Jones "pll_video1_4x", pll_video1_4x_parents, /* name, parents */
280*245cdec7STom Jones 0x48, /* offset */
281*245cdec7STom Jones 8, 8, 0, 0, /* n factor */
282*245cdec7STom Jones 0, 1, 0, 0, /* m0 factor */
283*245cdec7STom Jones 1, 1, 0, 0, /* m1 factor */
284*245cdec7STom Jones 31, /* gate */
285*245cdec7STom Jones 28, 1000, /* lock */
286*245cdec7STom Jones AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
287*245cdec7STom Jones static const char *pll_video1_parents[] = {"pll_video1_4x"};
288*245cdec7STom Jones FIXED_CLK(pll_video1_clk,
289*245cdec7STom Jones CLK_PLL_VIDEO1, /* id */
290*245cdec7STom Jones "pll_video1", /* name */
291*245cdec7STom Jones pll_video1_parents, /* parent */
292*245cdec7STom Jones 0, /* freq */
293*245cdec7STom Jones 1, /* mult */
294*245cdec7STom Jones 4, /* div */
295*245cdec7STom Jones 0); /* flags */
296*245cdec7STom Jones
297*245cdec7STom Jones static const char *pll_video2_4x_parents[] = {"osc24M"};
298*245cdec7STom Jones NMM_CLK(pll_video2_4x_clk,
299*245cdec7STom Jones CLK_PLL_VIDEO1_4X, /* id */
300*245cdec7STom Jones "pll_video2_4x", pll_video2_4x_parents, /* name, parents */
301*245cdec7STom Jones 0x50, /* offset */
302*245cdec7STom Jones 8, 8, 0, 0, /* n factor */
303*245cdec7STom Jones 0, 1, 0, 0, /* m0 factor */
304*245cdec7STom Jones 1, 1, 0, 0, /* m1 factor */
305*245cdec7STom Jones 31, /* gate */
306*245cdec7STom Jones 28, 1000, /* lock */
307*245cdec7STom Jones AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
308*245cdec7STom Jones static const char *pll_video2_parents[] = {"pll_video2_4x"};
309*245cdec7STom Jones FIXED_CLK(pll_video2_clk,
310*245cdec7STom Jones CLK_PLL_VIDEO1, /* id */
311*245cdec7STom Jones "pll_video2", /* name */
312*245cdec7STom Jones pll_video2_parents, /* parent */
313*245cdec7STom Jones 0, /* freq */
314*245cdec7STom Jones 1, /* mult */
315*245cdec7STom Jones 4, /* div */
316*245cdec7STom Jones 0); /* flags */
317*245cdec7STom Jones
318*245cdec7STom Jones static const char *pll_ve_parents[] = {"osc24M"};
319*245cdec7STom Jones NMM_CLK(pll_ve_clk,
320*245cdec7STom Jones CLK_PLL_VE, /* id */
321*245cdec7STom Jones "pll_ve", pll_ve_parents, /* name, parents */
322*245cdec7STom Jones 0x58, /* offset */
323*245cdec7STom Jones 8, 8, 0, 0, /* n factor */
324*245cdec7STom Jones 0, 1, 0, 0, /* m0 factor */
325*245cdec7STom Jones 1, 1, 0, 0, /* m1 factor */
326*245cdec7STom Jones 31, /* gate */
327*245cdec7STom Jones 28, 1000, /* lock */
328*245cdec7STom Jones AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
329*245cdec7STom Jones
330*245cdec7STom Jones static const char *pll_de_parents[] = {"osc24M"};
331*245cdec7STom Jones NMM_CLK(pll_de_clk,
332*245cdec7STom Jones CLK_PLL_DE, /* id */
333*245cdec7STom Jones "pll_de", pll_de_parents, /* name, parents */
334*245cdec7STom Jones 0x60, /* offset */
335*245cdec7STom Jones 8, 8, 0, 0, /* n factor */
336*245cdec7STom Jones 0, 1, 0, 0, /* m0 factor */
337*245cdec7STom Jones 1, 1, 0, 0, /* m1 factor */
338*245cdec7STom Jones 31, /* gate */
339*245cdec7STom Jones 28, 1000, /* lock */
340*245cdec7STom Jones AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
341*245cdec7STom Jones
342*245cdec7STom Jones /* PLL_AUDIO missing */
343*245cdec7STom Jones // in h616 datasheet
344*245cdec7STom Jones
345*245cdec7STom Jones /* CPUX_AXI missing */
346*245cdec7STom Jones // in h616 datasheet
347*245cdec7STom Jones
348*245cdec7STom Jones static const char *psi_ahb1_ahb2_parents[] = {"osc24M", "osc32k", "iosc", "pll_periph0"};
349*245cdec7STom Jones NM_CLK(psi_ahb1_ahb2_clk,
350*245cdec7STom Jones CLK_PSI_AHB1_AHB2, "psi_ahb1_ahb2", psi_ahb1_ahb2_parents, /* id, name, parents */
351*245cdec7STom Jones 0x510, /* offset */
352*245cdec7STom Jones 8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
353*245cdec7STom Jones 0, 2, 0, 0, /* m factor */
354*245cdec7STom Jones 24, 2, /* mux */
355*245cdec7STom Jones 0, /* gate */
356*245cdec7STom Jones AW_CLK_HAS_MUX | AW_CLK_REPARENT); /* flags */
357*245cdec7STom Jones
358*245cdec7STom Jones static const char *ahb3_parents[] = {"osc24M", "osc32k", "psi_ahb1_ahb2", "pll_periph0"};
359*245cdec7STom Jones NM_CLK(ahb3_clk,
360*245cdec7STom Jones CLK_AHB3, "ahb3", ahb3_parents, /* id, name, parents */
361*245cdec7STom Jones 0x51C, /* offset */
362*245cdec7STom Jones 8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
363*245cdec7STom Jones 0, 2, 0, 0, /* m factor */
364*245cdec7STom Jones 24, 2, /* mux */
365*245cdec7STom Jones 0, /* gate */
366*245cdec7STom Jones AW_CLK_HAS_MUX | AW_CLK_REPARENT); /* flags */
367*245cdec7STom Jones
368*245cdec7STom Jones static const char *apb1_parents[] = {"osc24M", "osc32k", "psi_ahb1_ahb2", "pll_periph0"};
369*245cdec7STom Jones NM_CLK(apb1_clk,
370*245cdec7STom Jones CLK_APB1, "apb1", apb1_parents, /* id, name, parents */
371*245cdec7STom Jones 0x520, /* offset */
372*245cdec7STom Jones 8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
373*245cdec7STom Jones 0, 2, 0, 0, /* m factor */
374*245cdec7STom Jones 24, 2, /* mux */
375*245cdec7STom Jones 0, /* gate */
376*245cdec7STom Jones AW_CLK_HAS_MUX | AW_CLK_REPARENT); /* flags */
377*245cdec7STom Jones
378*245cdec7STom Jones static const char *apb2_parents[] = {"osc24M", "osc32k", "psi_ahb1_ahb2", "pll_periph0"};
379*245cdec7STom Jones NM_CLK(apb2_clk,
380*245cdec7STom Jones CLK_APB2, "apb2", apb2_parents, /* id, name, parents */
381*245cdec7STom Jones 0x524, /* offset */
382*245cdec7STom Jones 8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
383*245cdec7STom Jones 0, 2, 0, 0, /* m factor */
384*245cdec7STom Jones 24, 2, /* mux */
385*245cdec7STom Jones 0, /* gate */
386*245cdec7STom Jones AW_CLK_HAS_MUX | AW_CLK_REPARENT); /* flags */
387*245cdec7STom Jones
388*245cdec7STom Jones /* Missing MBUS clock */
389*245cdec7STom Jones
390*245cdec7STom Jones static const char *mod_parents[] = {"osc24M", "pll_periph0_2x", "pll_periph1_2x"};
391*245cdec7STom Jones NM_CLK(mmc0_clk,
392*245cdec7STom Jones CLK_MMC0, "mmc0", mod_parents, /* id, name, parents */
393*245cdec7STom Jones 0x830, /* offset */
394*245cdec7STom Jones 8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
395*245cdec7STom Jones 0, 4, 0, 0, /* m factor */
396*245cdec7STom Jones 24, 2, /* mux */
397*245cdec7STom Jones 31, /* gate */
398*245cdec7STom Jones AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
399*245cdec7STom Jones AW_CLK_REPARENT); /* flags */
400*245cdec7STom Jones
401*245cdec7STom Jones NM_CLK(mmc1_clk,
402*245cdec7STom Jones CLK_MMC1, "mmc1", mod_parents, /* id, name, parents */
403*245cdec7STom Jones 0x834, /* offset */
404*245cdec7STom Jones 8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
405*245cdec7STom Jones 0, 4, 0, 0, /* m factor */
406*245cdec7STom Jones 24, 2, /* mux */
407*245cdec7STom Jones 31, /* gate */
408*245cdec7STom Jones AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
409*245cdec7STom Jones AW_CLK_REPARENT); /* flags */
410*245cdec7STom Jones
411*245cdec7STom Jones NM_CLK(mmc2_clk,
412*245cdec7STom Jones CLK_MMC2, "mmc2", mod_parents, /* id, name, parents */
413*245cdec7STom Jones 0x838, /* offset */
414*245cdec7STom Jones 8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
415*245cdec7STom Jones 0, 4, 0, 0, /* m factor */
416*245cdec7STom Jones 24, 2, /* mux */
417*245cdec7STom Jones 31, /* gate */
418*245cdec7STom Jones AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
419*245cdec7STom Jones AW_CLK_REPARENT); /* flags */
420*245cdec7STom Jones
421*245cdec7STom Jones static struct aw_ccung_clk h616_ccu_clks[] = {
422*245cdec7STom Jones { .type = AW_CLK_NP, .clk.np = &pll_cpux_clk},
423*245cdec7STom Jones { .type = AW_CLK_NMM, .clk.nmm = &pll_ddr0_clk},
424*245cdec7STom Jones { .type = AW_CLK_NMM, .clk.nmm = &pll_ddr1_clk},
425*245cdec7STom Jones { .type = AW_CLK_NMM, .clk.nmm = &pll_peri0_2x_clk},
426*245cdec7STom Jones { .type = AW_CLK_NMM, .clk.nmm = &pll_peri1_2x_clk},
427*245cdec7STom Jones { .type = AW_CLK_NMM, .clk.nmm = &pll_gpu_clk},
428*245cdec7STom Jones { .type = AW_CLK_NMM, .clk.nmm = &pll_video0_4x_clk},
429*245cdec7STom Jones { .type = AW_CLK_NMM, .clk.nmm = &pll_video1_4x_clk},
430*245cdec7STom Jones { .type = AW_CLK_NMM, .clk.nmm = &pll_video2_4x_clk},
431*245cdec7STom Jones { .type = AW_CLK_NMM, .clk.nmm = &pll_ve_clk},
432*245cdec7STom Jones { .type = AW_CLK_NMM, .clk.nmm = &pll_de_clk},
433*245cdec7STom Jones
434*245cdec7STom Jones { .type = AW_CLK_NM, .clk.nm = &psi_ahb1_ahb2_clk},
435*245cdec7STom Jones { .type = AW_CLK_NM, .clk.nm = &ahb3_clk},
436*245cdec7STom Jones { .type = AW_CLK_NM, .clk.nm = &apb1_clk},
437*245cdec7STom Jones { .type = AW_CLK_NM, .clk.nm = &apb2_clk},
438*245cdec7STom Jones
439*245cdec7STom Jones { .type = AW_CLK_NM, .clk.nm = &mmc0_clk},
440*245cdec7STom Jones { .type = AW_CLK_NM, .clk.nm = &mmc1_clk},
441*245cdec7STom Jones { .type = AW_CLK_NM, .clk.nm = &mmc2_clk},
442*245cdec7STom Jones
443*245cdec7STom Jones { .type = AW_CLK_FIXED, .clk.fixed = &pll_peri0_clk},
444*245cdec7STom Jones { .type = AW_CLK_FIXED, .clk.fixed = &pll_peri1_clk},
445*245cdec7STom Jones { .type = AW_CLK_FIXED, .clk.fixed = &pll_video0_clk},
446*245cdec7STom Jones { .type = AW_CLK_FIXED, .clk.fixed = &pll_video1_clk},
447*245cdec7STom Jones { .type = AW_CLK_FIXED, .clk.fixed = &pll_video2_clk},
448*245cdec7STom Jones };
449*245cdec7STom Jones
450*245cdec7STom Jones static int
ccu_h616_probe(device_t dev)451*245cdec7STom Jones ccu_h616_probe(device_t dev)
452*245cdec7STom Jones {
453*245cdec7STom Jones
454*245cdec7STom Jones if (!ofw_bus_status_okay(dev))
455*245cdec7STom Jones return (ENXIO);
456*245cdec7STom Jones
457*245cdec7STom Jones if (!ofw_bus_is_compatible(dev, "allwinner,sun50i-h616-ccu"))
458*245cdec7STom Jones return (ENXIO);
459*245cdec7STom Jones
460*245cdec7STom Jones device_set_desc(dev, "Allwinner H616 Clock Control Unit");
461*245cdec7STom Jones return (BUS_PROBE_DEFAULT);
462*245cdec7STom Jones }
463*245cdec7STom Jones
464*245cdec7STom Jones static int
ccu_h616_attach(device_t dev)465*245cdec7STom Jones ccu_h616_attach(device_t dev)
466*245cdec7STom Jones {
467*245cdec7STom Jones struct aw_ccung_softc *sc;
468*245cdec7STom Jones
469*245cdec7STom Jones sc = device_get_softc(dev);
470*245cdec7STom Jones
471*245cdec7STom Jones sc->resets = h616_ccu_resets;
472*245cdec7STom Jones sc->nresets = nitems(h616_ccu_resets);
473*245cdec7STom Jones sc->gates = h616_ccu_gates;
474*245cdec7STom Jones sc->ngates = nitems(h616_ccu_gates);
475*245cdec7STom Jones sc->clks = h616_ccu_clks;
476*245cdec7STom Jones sc->nclks = nitems(h616_ccu_clks);
477*245cdec7STom Jones
478*245cdec7STom Jones return (aw_ccung_attach(dev));
479*245cdec7STom Jones }
480*245cdec7STom Jones
481*245cdec7STom Jones static device_method_t ccu_h616ng_methods[] = {
482*245cdec7STom Jones /* Device interface */
483*245cdec7STom Jones DEVMETHOD(device_probe, ccu_h616_probe),
484*245cdec7STom Jones DEVMETHOD(device_attach, ccu_h616_attach),
485*245cdec7STom Jones
486*245cdec7STom Jones DEVMETHOD_END
487*245cdec7STom Jones };
488*245cdec7STom Jones
489*245cdec7STom Jones DEFINE_CLASS_1(ccu_h616ng, ccu_h616ng_driver, ccu_h616ng_methods,
490*245cdec7STom Jones sizeof(struct aw_ccung_softc), aw_ccung_driver);
491*245cdec7STom Jones
492*245cdec7STom Jones EARLY_DRIVER_MODULE(ccu_h616ng, simplebus, ccu_h616ng_driver, 0, 0,
493*245cdec7STom Jones BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);
494