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