xref: /freebsd/sys/dev/clk/allwinner/ccu_a13.c (revision be82b3a0bf72ed3b5f01ac9fcd8dcd3802e3c742)
1e37e8677SEmmanuel Vadot /*-
2e37e8677SEmmanuel Vadot  * SPDX-License-Identifier: BSD-2-Clause
3e37e8677SEmmanuel Vadot  *
4e37e8677SEmmanuel Vadot  * Copyright (c) 2017,2018 Emmanuel Vadot <manu@freebsd.org>
5e37e8677SEmmanuel Vadot  *
6e37e8677SEmmanuel Vadot  * Redistribution and use in source and binary forms, with or without
7e37e8677SEmmanuel Vadot  * modification, are permitted provided that the following conditions
8e37e8677SEmmanuel Vadot  * are met:
9e37e8677SEmmanuel Vadot  * 1. Redistributions of source code must retain the above copyright
10e37e8677SEmmanuel Vadot  *    notice, this list of conditions and the following disclaimer.
11e37e8677SEmmanuel Vadot  * 2. Redistributions in binary form must reproduce the above copyright
12e37e8677SEmmanuel Vadot  *    notice, this list of conditions and the following disclaimer in the
13e37e8677SEmmanuel Vadot  *    documentation and/or other materials provided with the distribution.
14e37e8677SEmmanuel Vadot  *
15e37e8677SEmmanuel Vadot  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16e37e8677SEmmanuel Vadot  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17e37e8677SEmmanuel Vadot  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18e37e8677SEmmanuel Vadot  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19e37e8677SEmmanuel Vadot  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
20e37e8677SEmmanuel Vadot  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21e37e8677SEmmanuel Vadot  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
22e37e8677SEmmanuel Vadot  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23e37e8677SEmmanuel Vadot  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24e37e8677SEmmanuel Vadot  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25e37e8677SEmmanuel Vadot  * SUCH DAMAGE.
26e37e8677SEmmanuel Vadot  */
27e37e8677SEmmanuel Vadot 
28e37e8677SEmmanuel Vadot #include <sys/param.h>
29e37e8677SEmmanuel Vadot #include <sys/systm.h>
30e37e8677SEmmanuel Vadot #include <sys/bus.h>
31e37e8677SEmmanuel Vadot #include <sys/rman.h>
32e37e8677SEmmanuel Vadot #include <sys/kernel.h>
33e37e8677SEmmanuel Vadot #include <sys/module.h>
34e37e8677SEmmanuel Vadot #include <machine/bus.h>
35e37e8677SEmmanuel Vadot 
36e37e8677SEmmanuel Vadot #include <dev/fdt/simplebus.h>
37e37e8677SEmmanuel Vadot 
38e37e8677SEmmanuel Vadot #include <dev/ofw/ofw_bus.h>
39e37e8677SEmmanuel Vadot #include <dev/ofw/ofw_bus_subr.h>
40e37e8677SEmmanuel Vadot 
41*be82b3a0SEmmanuel Vadot #include <dev/clk/clk_div.h>
42*be82b3a0SEmmanuel Vadot #include <dev/clk/clk_fixed.h>
43*be82b3a0SEmmanuel Vadot #include <dev/clk/clk_mux.h>
44e37e8677SEmmanuel Vadot 
45e37e8677SEmmanuel Vadot #include <dev/clk/allwinner/aw_ccung.h>
46e37e8677SEmmanuel Vadot 
47e37e8677SEmmanuel Vadot #include <dt-bindings/clock/sun5i-ccu.h>
48e37e8677SEmmanuel Vadot #include <dt-bindings/reset/sun5i-ccu.h>
49e37e8677SEmmanuel Vadot 
50e37e8677SEmmanuel Vadot /* Non-exported clocks */
51e37e8677SEmmanuel Vadot 
52e37e8677SEmmanuel Vadot #define	CLK_PLL_CORE		2
53e37e8677SEmmanuel Vadot #define	CLK_PLL_AUDIO_BASE	3
54e37e8677SEmmanuel Vadot #define	CLK_PLL_AUDIO		4
55e37e8677SEmmanuel Vadot #define	CLK_PLL_AUDIO_2X	5
56e37e8677SEmmanuel Vadot #define	CLK_PLL_AUDIO_4X	6
57e37e8677SEmmanuel Vadot #define	CLK_PLL_AUDIO_8X	7
58e37e8677SEmmanuel Vadot #define	CLK_PLL_VIDEO0		8
59e37e8677SEmmanuel Vadot 
60e37e8677SEmmanuel Vadot #define	CLK_PLL_VE		10
61e37e8677SEmmanuel Vadot #define	CLK_PLL_DDR_BASE	11
62e37e8677SEmmanuel Vadot #define	CLK_PLL_DDR		12
63e37e8677SEmmanuel Vadot #define	CLK_PLL_DDR_OTHER	13
64e37e8677SEmmanuel Vadot #define	CLK_PLL_PERIPH		14
65e37e8677SEmmanuel Vadot #define	CLK_PLL_VIDEO1		15
66e37e8677SEmmanuel Vadot 
67e37e8677SEmmanuel Vadot #define	CLK_AXI			18
68e37e8677SEmmanuel Vadot #define	CLK_AHB			19
69e37e8677SEmmanuel Vadot #define	CLK_APB0		20
70e37e8677SEmmanuel Vadot #define	CLK_APB1		21
71e37e8677SEmmanuel Vadot #define	CLK_DRAM_AXI		22
72e37e8677SEmmanuel Vadot 
73e37e8677SEmmanuel Vadot #define	CLK_TCON_CH1_SCLK	91
74e37e8677SEmmanuel Vadot 
75e37e8677SEmmanuel Vadot #define	CLK_MBUS		99
76e37e8677SEmmanuel Vadot 
77e37e8677SEmmanuel Vadot static struct aw_ccung_reset a13_ccu_resets[] = {
78e37e8677SEmmanuel Vadot 	CCU_RESET(RST_USB_PHY0, 0xcc, 0)
79e37e8677SEmmanuel Vadot 	CCU_RESET(RST_USB_PHY1, 0xcc, 1)
80e37e8677SEmmanuel Vadot 
81e37e8677SEmmanuel Vadot 	CCU_RESET(RST_GPS, 0xd0, 30)
82e37e8677SEmmanuel Vadot 
83e37e8677SEmmanuel Vadot 	CCU_RESET(RST_DE_BE, 0x104, 30)
84e37e8677SEmmanuel Vadot 
85e37e8677SEmmanuel Vadot 	CCU_RESET(RST_DE_FE, 0x10c, 30)
86e37e8677SEmmanuel Vadot 
87e37e8677SEmmanuel Vadot 	CCU_RESET(RST_TVE, 0x118, 29)
88e37e8677SEmmanuel Vadot 	CCU_RESET(RST_LCD, 0x118, 30)
89e37e8677SEmmanuel Vadot 
90e37e8677SEmmanuel Vadot 	CCU_RESET(RST_CSI, 0x134, 30)
91e37e8677SEmmanuel Vadot 
92e37e8677SEmmanuel Vadot 	CCU_RESET(RST_VE, 0x13c, 0)
93e37e8677SEmmanuel Vadot 	CCU_RESET(RST_GPU, 0x154, 30)
94e37e8677SEmmanuel Vadot 	CCU_RESET(RST_IEP, 0x160, 30)
95e37e8677SEmmanuel Vadot 
96e37e8677SEmmanuel Vadot };
97e37e8677SEmmanuel Vadot 
98e37e8677SEmmanuel Vadot static struct aw_ccung_gate a13_ccu_gates[] = {
99e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_HOSC, "hosc", "osc24M", 0x50, 0)
100e37e8677SEmmanuel Vadot 
101e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_DRAM_AXI, "axi-dram", "axi", 0x5c, 0)
102e37e8677SEmmanuel Vadot 
103e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_AHB_OTG, "ahb-otg", "ahb", 0x60, 0)
104e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_AHB_EHCI, "ahb-ehci", "ahb", 0x60, 1)
105e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_AHB_OHCI, "ahb-ohci", "ahb", 0x60, 2)
106e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_AHB_SS, "ahb-ss", "ahb", 0x60, 5)
107e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_AHB_DMA, "ahb-dma", "ahb", 0x60, 6)
108e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_AHB_BIST, "ahb-bist", "ahb", 0x60, 7)
109e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_AHB_MMC0, "ahb-mmc0", "ahb", 0x60, 8)
110e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_AHB_MMC1, "ahb-mmc1", "ahb", 0x60, 9)
111e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_AHB_MMC2, "ahb-mmc2", "ahb", 0x60, 10)
112e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_AHB_NAND, "ahb-nand", "ahb", 0x60, 13)
113e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_AHB_SDRAM, "ahb-sdram", "ahb", 0x60, 14)
114e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_AHB_SPI0, "ahb-spi0", "ahb", 0x60, 20)
115e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_AHB_SPI1, "ahb-spi1", "ahb", 0x60, 21)
116e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_AHB_SPI2, "ahb-spi2", "ahb", 0x60, 22)
117e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_AHB_GPS, "ahb-gps", "ahb", 0x60, 26)
118e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_AHB_HSTIMER, "ahb-hstimer", "ahb", 0x60, 28)
119e37e8677SEmmanuel Vadot 
120e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_AHB_VE, "ahb-ve", "ahb", 0x64, 0)
121e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_AHB_LCD, "ahb-lcd", "ahb", 0x64, 4)
122e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_AHB_CSI, "ahb-csi", "ahb", 0x64, 8)
123e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_AHB_DE_BE, "ahb-de-be", "ahb", 0x64, 12)
124e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_AHB_DE_FE, "ahb-de-fe", "ahb", 0x64, 14)
125e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_AHB_IEP, "ahb-iep", "ahb", 0x64, 19)
126e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_AHB_GPU, "ahb-gpu", "ahb", 0x64, 20)
127e37e8677SEmmanuel Vadot 
128e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_APB0_CODEC, "apb0-codec", "apb0", 0x68, 0)
129e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_APB0_PIO, "apb0-pio", "apb0", 0x68, 5)
130e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_APB0_IR, "apb0-ir", "apb0", 0x68, 6)
131e37e8677SEmmanuel Vadot 
132e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_APB1_I2C0, "apb1-i2c0", "apb1", 0x6c, 0)
133e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_APB1_I2C1, "apb1-i2c1", "apb1", 0x6c, 1)
134e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_APB1_I2C2, "apb1-i2c2", "apb1", 0x6c, 2)
135e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_APB1_UART1, "apb1-uart1", "apb1", 0x6c, 17)
136e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_APB1_UART3, "apb1-uart3", "apb1", 0x6c, 19)
137e37e8677SEmmanuel Vadot 
138e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_DRAM_VE, "dram-ve", "pll-ddr", 0x100, 0)
139e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_DRAM_CSI, "dram-csi", "pll-ddr", 0x100, 1)
140e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_DRAM_DE_FE, "dram-de-fe", "pll-ddr", 0x100, 25)
141e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_DRAM_DE_BE, "dram-de-be", "pll-ddr", 0x100, 26)
142e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_DRAM_ACE, "dram-ace", "pll-ddr", 0x100, 29)
143e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_DRAM_IEP, "dram-iep", "pll-ddr", 0x100, 31)
144e37e8677SEmmanuel Vadot 
145e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_CODEC, "codec", "pll-audio", 0x140, 31)
146e37e8677SEmmanuel Vadot 
147e37e8677SEmmanuel Vadot 	CCU_GATE(CLK_AVS, "avs", "hosc", 0x144, 31)
148e37e8677SEmmanuel Vadot };
149e37e8677SEmmanuel Vadot 
150e37e8677SEmmanuel Vadot static const char *pll_parents[] = {"hosc"};
151e37e8677SEmmanuel Vadot static struct aw_clk_nkmp_def pll_core = {
152e37e8677SEmmanuel Vadot 	.clkdef = {
153e37e8677SEmmanuel Vadot 		.id = CLK_PLL_CORE,
154e37e8677SEmmanuel Vadot 		.name = "pll-core",
155e37e8677SEmmanuel Vadot 		.parent_names = pll_parents,
156e37e8677SEmmanuel Vadot 		.parent_cnt = nitems(pll_parents),
157e37e8677SEmmanuel Vadot 	},
158e37e8677SEmmanuel Vadot 	.offset = 0x00,
159e37e8677SEmmanuel Vadot 	.n = {.shift = 8, .width = 5},
160e37e8677SEmmanuel Vadot 	.k = {.shift = 4, .width = 2},
161e37e8677SEmmanuel Vadot 	.m = {.shift = 0, .width = 2},
162e37e8677SEmmanuel Vadot 	.p = {.shift = 16, .width = 2},
163e37e8677SEmmanuel Vadot 	.gate_shift = 31,
164e37e8677SEmmanuel Vadot 	.flags = AW_CLK_HAS_GATE,
165e37e8677SEmmanuel Vadot };
166e37e8677SEmmanuel Vadot 
167e37e8677SEmmanuel Vadot /*
168e37e8677SEmmanuel Vadot  * We only implement pll-audio for now
169e37e8677SEmmanuel Vadot  * For pll-audio-2/4/8 x we need a way to change the frequency
170e37e8677SEmmanuel Vadot  * of the parent clocks
171e37e8677SEmmanuel Vadot  */
172e37e8677SEmmanuel Vadot static struct aw_clk_nkmp_def pll_audio = {
173e37e8677SEmmanuel Vadot 	.clkdef = {
174e37e8677SEmmanuel Vadot 		.id = CLK_PLL_AUDIO,
175e37e8677SEmmanuel Vadot 		.name = "pll-audio",
176e37e8677SEmmanuel Vadot 		.parent_names = pll_parents,
177e37e8677SEmmanuel Vadot 		.parent_cnt = nitems(pll_parents),
178e37e8677SEmmanuel Vadot 	},
179e37e8677SEmmanuel Vadot 	.offset = 0x08,
180e37e8677SEmmanuel Vadot 	.n = {.shift = 8, .width = 7},
181e37e8677SEmmanuel Vadot 	.k = {.value = 1, .flags = AW_CLK_FACTOR_FIXED},
182e37e8677SEmmanuel Vadot 	.m = {.shift = 0, .width = 5},
183e37e8677SEmmanuel Vadot 	.p = {.shift = 26, .width = 4},
184e37e8677SEmmanuel Vadot 	.gate_shift = 31,
185e37e8677SEmmanuel Vadot 	.flags = AW_CLK_HAS_GATE,
186e37e8677SEmmanuel Vadot };
187e37e8677SEmmanuel Vadot 
188e37e8677SEmmanuel Vadot /* Missing PLL3-Video */
189e37e8677SEmmanuel Vadot /* Missing PLL4-VE */
190e37e8677SEmmanuel Vadot 
191e37e8677SEmmanuel Vadot static struct aw_clk_nkmp_def pll_ddr_base = {
192e37e8677SEmmanuel Vadot 	.clkdef = {
193e37e8677SEmmanuel Vadot 		.id = CLK_PLL_DDR_BASE,
194e37e8677SEmmanuel Vadot 		.name = "pll-ddr-base",
195e37e8677SEmmanuel Vadot 		.parent_names = pll_parents,
196e37e8677SEmmanuel Vadot 		.parent_cnt = nitems(pll_parents),
197e37e8677SEmmanuel Vadot 	},
198e37e8677SEmmanuel Vadot 	.offset = 0x20,
199e37e8677SEmmanuel Vadot 	.n = {.shift = 8, .width = 5},
200e37e8677SEmmanuel Vadot 	.k = {.shift = 4, .width = 2},
201e37e8677SEmmanuel Vadot 	.m = {.value = 1, .flags = AW_CLK_FACTOR_FIXED},
202e37e8677SEmmanuel Vadot 	.p = {.value = 1, .flags = AW_CLK_FACTOR_FIXED},
203e37e8677SEmmanuel Vadot 	.gate_shift = 31,
204e37e8677SEmmanuel Vadot 	.flags = AW_CLK_HAS_GATE,
205e37e8677SEmmanuel Vadot };
206e37e8677SEmmanuel Vadot 
207e37e8677SEmmanuel Vadot static const char *pll_ddr_parents[] = {"pll-ddr-base"};
208e37e8677SEmmanuel Vadot static struct clk_div_def pll_ddr = {
209e37e8677SEmmanuel Vadot 	.clkdef = {
210e37e8677SEmmanuel Vadot 		.id = CLK_PLL_DDR,
211e37e8677SEmmanuel Vadot 		.name = "pll-ddr",
212e37e8677SEmmanuel Vadot 		.parent_names = pll_ddr_parents,
213e37e8677SEmmanuel Vadot 		.parent_cnt = nitems(pll_ddr_parents),
214e37e8677SEmmanuel Vadot 	},
215e37e8677SEmmanuel Vadot 	.offset = 0x20,
216e37e8677SEmmanuel Vadot 	.i_shift = 0,
217e37e8677SEmmanuel Vadot 	.i_width = 2,
218e37e8677SEmmanuel Vadot };
219e37e8677SEmmanuel Vadot 
220e37e8677SEmmanuel Vadot static const char *pll_ddr_other_parents[] = {"pll-ddr-base"};
221e37e8677SEmmanuel Vadot static struct clk_div_def pll_ddr_other = {
222e37e8677SEmmanuel Vadot 	.clkdef = {
223e37e8677SEmmanuel Vadot 		.id = CLK_PLL_DDR_OTHER,
224e37e8677SEmmanuel Vadot 		.name = "pll-ddr-other",
225e37e8677SEmmanuel Vadot 		.parent_names = pll_ddr_other_parents,
226e37e8677SEmmanuel Vadot 		.parent_cnt = nitems(pll_ddr_other_parents),
227e37e8677SEmmanuel Vadot 	},
228e37e8677SEmmanuel Vadot 	.offset = 0x20,
229e37e8677SEmmanuel Vadot 	.i_shift = 16,
230e37e8677SEmmanuel Vadot 	.i_width = 2,
231e37e8677SEmmanuel Vadot };
232e37e8677SEmmanuel Vadot 
233e37e8677SEmmanuel Vadot static struct aw_clk_nkmp_def pll_periph = {
234e37e8677SEmmanuel Vadot 	.clkdef = {
235e37e8677SEmmanuel Vadot 		.id = CLK_PLL_PERIPH,
236e37e8677SEmmanuel Vadot 		.name = "pll-periph",
237e37e8677SEmmanuel Vadot 		.parent_names = pll_parents,
238e37e8677SEmmanuel Vadot 		.parent_cnt = nitems(pll_parents),
239e37e8677SEmmanuel Vadot 	},
240e37e8677SEmmanuel Vadot 	.offset = 0x28,
241e37e8677SEmmanuel Vadot 	.n = {.shift = 8, .width = 5},
242e37e8677SEmmanuel Vadot 	.k = {.shift = 4, .width = 2},
243e37e8677SEmmanuel Vadot 	.m = {.shift = 0, .width = 2},
244e37e8677SEmmanuel Vadot 	.p = {.value = 2, .flags = AW_CLK_FACTOR_FIXED},
245e37e8677SEmmanuel Vadot 	.gate_shift = 31,
246e37e8677SEmmanuel Vadot 	.flags = AW_CLK_HAS_GATE,
247e37e8677SEmmanuel Vadot };
248e37e8677SEmmanuel Vadot 
249e37e8677SEmmanuel Vadot /* Missing PLL7-VIDEO1 */
250e37e8677SEmmanuel Vadot 
251e37e8677SEmmanuel Vadot static const char *cpu_parents[] = {"osc32k", "hosc", "pll-core", "pll-periph"};
252e37e8677SEmmanuel Vadot static struct aw_clk_prediv_mux_def cpu_clk = {
253e37e8677SEmmanuel Vadot 	.clkdef = {
254e37e8677SEmmanuel Vadot 		.id = CLK_CPU,
255e37e8677SEmmanuel Vadot 		.name = "cpu",
256e37e8677SEmmanuel Vadot 		.parent_names = cpu_parents,
257e37e8677SEmmanuel Vadot 		.parent_cnt = nitems(cpu_parents),
258e37e8677SEmmanuel Vadot 	},
259e37e8677SEmmanuel Vadot 	.offset = 0x54,
260e37e8677SEmmanuel Vadot 	.mux_shift = 16, .mux_width = 2,
261e37e8677SEmmanuel Vadot 	.prediv = {
262e37e8677SEmmanuel Vadot 		.value = 6,
263e37e8677SEmmanuel Vadot 		.flags = AW_CLK_FACTOR_FIXED,
264e37e8677SEmmanuel Vadot 		.cond_shift = 16,
265e37e8677SEmmanuel Vadot 		.cond_width = 2,
266e37e8677SEmmanuel Vadot 		.cond_value = 3,
267e37e8677SEmmanuel Vadot 	},
268e37e8677SEmmanuel Vadot };
269e37e8677SEmmanuel Vadot 
270e37e8677SEmmanuel Vadot static const char *axi_parents[] = {"cpu"};
271e37e8677SEmmanuel Vadot static struct clk_div_def axi_clk = {
272e37e8677SEmmanuel Vadot 	.clkdef = {
273e37e8677SEmmanuel Vadot 		.id = CLK_AXI,
274e37e8677SEmmanuel Vadot 		.name = "axi",
275e37e8677SEmmanuel Vadot 		.parent_names = axi_parents,
276e37e8677SEmmanuel Vadot 		.parent_cnt = nitems(axi_parents),
277e37e8677SEmmanuel Vadot 	},
278e37e8677SEmmanuel Vadot 	.offset = 0x50,
279e37e8677SEmmanuel Vadot 	.i_shift = 0, .i_width = 2,
280e37e8677SEmmanuel Vadot };
281e37e8677SEmmanuel Vadot 
282e37e8677SEmmanuel Vadot static const char *ahb_parents[] = {"axi", "cpu", "pll-periph"};
283e37e8677SEmmanuel Vadot static struct aw_clk_prediv_mux_def ahb_clk = {
284e37e8677SEmmanuel Vadot 	.clkdef = {
285e37e8677SEmmanuel Vadot 		.id = CLK_AHB,
286e37e8677SEmmanuel Vadot 		.name = "ahb",
287e37e8677SEmmanuel Vadot 		.parent_names = ahb_parents,
288e37e8677SEmmanuel Vadot 		.parent_cnt = nitems(ahb_parents),
289e37e8677SEmmanuel Vadot 	},
290e37e8677SEmmanuel Vadot 	.offset = 0x54,
291e37e8677SEmmanuel Vadot 	.mux_shift = 6,
292e37e8677SEmmanuel Vadot 	.mux_width = 2,
293e37e8677SEmmanuel Vadot 	.div = {
294e37e8677SEmmanuel Vadot 		.shift = 4,
295e37e8677SEmmanuel Vadot 		.width = 2,
296e37e8677SEmmanuel Vadot 		.flags = AW_CLK_FACTOR_POWER_OF_TWO
297e37e8677SEmmanuel Vadot 	},
298e37e8677SEmmanuel Vadot 	.prediv = {
299e37e8677SEmmanuel Vadot 		.value = 2,
300e37e8677SEmmanuel Vadot 		.flags = AW_CLK_FACTOR_FIXED,
301e37e8677SEmmanuel Vadot 		.cond_shift = 6,
302e37e8677SEmmanuel Vadot 		.cond_width = 2,
303e37e8677SEmmanuel Vadot 		.cond_value = 2,
304e37e8677SEmmanuel Vadot 	},
305e37e8677SEmmanuel Vadot };
306e37e8677SEmmanuel Vadot 
307e37e8677SEmmanuel Vadot static const char *apb0_parents[] = {"ahb"};
308e37e8677SEmmanuel Vadot static struct clk_div_table apb0_div_table[] = {
309e37e8677SEmmanuel Vadot 	{ .value = 0, .divider = 2, },
310e37e8677SEmmanuel Vadot 	{ .value = 1, .divider = 2, },
311e37e8677SEmmanuel Vadot 	{ .value = 2, .divider = 4, },
312e37e8677SEmmanuel Vadot 	{ .value = 3, .divider = 8, },
313e37e8677SEmmanuel Vadot 	{ },
314e37e8677SEmmanuel Vadot };
315e37e8677SEmmanuel Vadot static struct clk_div_def apb0_clk = {
316e37e8677SEmmanuel Vadot 	.clkdef = {
317e37e8677SEmmanuel Vadot 		.id = CLK_APB0,
318e37e8677SEmmanuel Vadot 		.name = "apb0",
319e37e8677SEmmanuel Vadot 		.parent_names = apb0_parents,
320e37e8677SEmmanuel Vadot 		.parent_cnt = nitems(apb0_parents),
321e37e8677SEmmanuel Vadot 	},
322e37e8677SEmmanuel Vadot 	.offset = 0x54,
323e37e8677SEmmanuel Vadot 	.i_shift = 8, .i_width = 2,
324e37e8677SEmmanuel Vadot 	.div_flags = CLK_DIV_WITH_TABLE,
325e37e8677SEmmanuel Vadot 	.div_table = apb0_div_table,
326e37e8677SEmmanuel Vadot };
327e37e8677SEmmanuel Vadot 
328e37e8677SEmmanuel Vadot static const char *apb1_parents[] = {"hosc", "pll-periph", "osc32k"};
329e37e8677SEmmanuel Vadot static struct aw_clk_nm_def apb1_clk = {
330e37e8677SEmmanuel Vadot 	.clkdef = {
331e37e8677SEmmanuel Vadot 		.id = CLK_APB1,
332e37e8677SEmmanuel Vadot 		.name = "apb1",
333e37e8677SEmmanuel Vadot 		.parent_names = apb1_parents,
334e37e8677SEmmanuel Vadot 		.parent_cnt = nitems(apb1_parents),
335e37e8677SEmmanuel Vadot 	},
336e37e8677SEmmanuel Vadot 	.offset = 0x58,
337e37e8677SEmmanuel Vadot 	.n = {.shift = 16, .width = 2, .flags = AW_CLK_FACTOR_POWER_OF_TWO, },
338e37e8677SEmmanuel Vadot 	.m = {.shift = 0, .width = 5},
339e37e8677SEmmanuel Vadot 	.mux_shift = 24,
340e37e8677SEmmanuel Vadot 	.mux_width = 2,
341e37e8677SEmmanuel Vadot 	.flags = AW_CLK_HAS_MUX,
342e37e8677SEmmanuel Vadot };
343e37e8677SEmmanuel Vadot 
344e37e8677SEmmanuel Vadot static const char *mod_parents[] = {"hosc", "pll-periph", "pll-ddr-other"};
345e37e8677SEmmanuel Vadot 
346e37e8677SEmmanuel Vadot static struct aw_clk_nm_def nand_clk = {
347e37e8677SEmmanuel Vadot 	.clkdef = {
348e37e8677SEmmanuel Vadot 		.id = CLK_NAND,
349e37e8677SEmmanuel Vadot 		.name = "nand",
350e37e8677SEmmanuel Vadot 		.parent_names = mod_parents,
351e37e8677SEmmanuel Vadot 		.parent_cnt = nitems(mod_parents),
352e37e8677SEmmanuel Vadot 	},
353e37e8677SEmmanuel Vadot 	.offset = 0x80,
354e37e8677SEmmanuel Vadot 	.n = {.shift = 16, .width = 2, .flags = AW_CLK_FACTOR_POWER_OF_TWO, },
355e37e8677SEmmanuel Vadot 	.m = {.shift = 0, .width = 4},
356e37e8677SEmmanuel Vadot 	.mux_shift = 24,
357e37e8677SEmmanuel Vadot 	.mux_width = 2,
358e37e8677SEmmanuel Vadot 	.gate_shift = 31,
359e37e8677SEmmanuel Vadot 	.flags = AW_CLK_HAS_MUX | AW_CLK_HAS_GATE | AW_CLK_REPARENT
360e37e8677SEmmanuel Vadot };
361e37e8677SEmmanuel Vadot 
362e37e8677SEmmanuel Vadot static struct aw_clk_nm_def mmc0_clk = {
363e37e8677SEmmanuel Vadot 	.clkdef = {
364e37e8677SEmmanuel Vadot 		.id = CLK_MMC0,
365e37e8677SEmmanuel Vadot 		.name = "mmc0",
366e37e8677SEmmanuel Vadot 		.parent_names = mod_parents,
367e37e8677SEmmanuel Vadot 		.parent_cnt = nitems(mod_parents),
368e37e8677SEmmanuel Vadot 	},
369e37e8677SEmmanuel Vadot 	.offset = 0x88,
370e37e8677SEmmanuel Vadot 	.n = {.shift = 16, .width = 2, .flags = AW_CLK_FACTOR_POWER_OF_TWO, },
371e37e8677SEmmanuel Vadot 	.m = {.shift = 0, .width = 4},
372e37e8677SEmmanuel Vadot 	.mux_shift = 24,
373e37e8677SEmmanuel Vadot 	.mux_width = 2,
374e37e8677SEmmanuel Vadot 	.gate_shift = 31,
375e37e8677SEmmanuel Vadot 	.flags = AW_CLK_HAS_MUX | AW_CLK_HAS_GATE | AW_CLK_REPARENT
376e37e8677SEmmanuel Vadot };
377e37e8677SEmmanuel Vadot 
378e37e8677SEmmanuel Vadot static struct aw_clk_nm_def mmc1_clk = {
379e37e8677SEmmanuel Vadot 	.clkdef = {
380e37e8677SEmmanuel Vadot 		.id = CLK_MMC1,
381e37e8677SEmmanuel Vadot 		.name = "mmc1",
382e37e8677SEmmanuel Vadot 		.parent_names = mod_parents,
383e37e8677SEmmanuel Vadot 		.parent_cnt = nitems(mod_parents),
384e37e8677SEmmanuel Vadot 	},
385e37e8677SEmmanuel Vadot 	.offset = 0x8C,
386e37e8677SEmmanuel Vadot 	.n = {.shift = 16, .width = 2, .flags = AW_CLK_FACTOR_POWER_OF_TWO, },
387e37e8677SEmmanuel Vadot 	.m = {.shift = 0, .width = 4},
388e37e8677SEmmanuel Vadot 	.mux_shift = 24,
389e37e8677SEmmanuel Vadot 	.mux_width = 2,
390e37e8677SEmmanuel Vadot 	.gate_shift = 31,
391e37e8677SEmmanuel Vadot 	.flags = AW_CLK_HAS_MUX | AW_CLK_HAS_GATE | AW_CLK_REPARENT
392e37e8677SEmmanuel Vadot };
393e37e8677SEmmanuel Vadot 
394e37e8677SEmmanuel Vadot static struct aw_clk_nm_def mmc2_clk = {
395e37e8677SEmmanuel Vadot 	.clkdef = {
396e37e8677SEmmanuel Vadot 		.id = CLK_MMC2,
397e37e8677SEmmanuel Vadot 		.name = "mmc2",
398e37e8677SEmmanuel Vadot 		.parent_names = mod_parents,
399e37e8677SEmmanuel Vadot 		.parent_cnt = nitems(mod_parents),
400e37e8677SEmmanuel Vadot 	},
401e37e8677SEmmanuel Vadot 	.offset = 0x90,
402e37e8677SEmmanuel Vadot 	.n = {.shift = 16, .width = 2, .flags = AW_CLK_FACTOR_POWER_OF_TWO, },
403e37e8677SEmmanuel Vadot 	.m = {.shift = 0, .width = 4},
404e37e8677SEmmanuel Vadot 	.mux_shift = 24,
405e37e8677SEmmanuel Vadot 	.mux_width = 2,
406e37e8677SEmmanuel Vadot 	.gate_shift = 31,
407e37e8677SEmmanuel Vadot 	.flags = AW_CLK_HAS_MUX | AW_CLK_HAS_GATE | AW_CLK_REPARENT
408e37e8677SEmmanuel Vadot };
409e37e8677SEmmanuel Vadot 
410e37e8677SEmmanuel Vadot static struct aw_clk_nm_def ss_clk = {
411e37e8677SEmmanuel Vadot 	.clkdef = {
412e37e8677SEmmanuel Vadot 		.id = CLK_SS,
413e37e8677SEmmanuel Vadot 		.name = "ss",
414e37e8677SEmmanuel Vadot 		.parent_names = mod_parents,
415e37e8677SEmmanuel Vadot 		.parent_cnt = nitems(mod_parents),
416e37e8677SEmmanuel Vadot 	},
417e37e8677SEmmanuel Vadot 	.offset = 0x9C,
418e37e8677SEmmanuel Vadot 	.n = {.shift = 16, .width = 2, .flags = AW_CLK_FACTOR_POWER_OF_TWO, },
419e37e8677SEmmanuel Vadot 	.m = {.shift = 0, .width = 4},
420e37e8677SEmmanuel Vadot 	.mux_shift = 24,
421e37e8677SEmmanuel Vadot 	.mux_width = 2,
422e37e8677SEmmanuel Vadot 	.gate_shift = 31,
423e37e8677SEmmanuel Vadot 	.flags = AW_CLK_HAS_MUX | AW_CLK_HAS_GATE | AW_CLK_REPARENT
424e37e8677SEmmanuel Vadot };
425e37e8677SEmmanuel Vadot 
426e37e8677SEmmanuel Vadot static struct aw_clk_nm_def spi0_clk = {
427e37e8677SEmmanuel Vadot 	.clkdef = {
428e37e8677SEmmanuel Vadot 		.id = CLK_SPI0,
429e37e8677SEmmanuel Vadot 		.name = "spi0",
430e37e8677SEmmanuel Vadot 		.parent_names = mod_parents,
431e37e8677SEmmanuel Vadot 		.parent_cnt = nitems(mod_parents),
432e37e8677SEmmanuel Vadot 	},
433e37e8677SEmmanuel Vadot 	.offset = 0xA0,
434e37e8677SEmmanuel Vadot 	.n = {.shift = 16, .width = 2, .flags = AW_CLK_FACTOR_POWER_OF_TWO, },
435e37e8677SEmmanuel Vadot 	.m = {.shift = 0, .width = 4},
436e37e8677SEmmanuel Vadot 	.mux_shift = 24,
437e37e8677SEmmanuel Vadot 	.mux_width = 2,
438e37e8677SEmmanuel Vadot 	.gate_shift = 31,
439e37e8677SEmmanuel Vadot 	.flags = AW_CLK_HAS_MUX | AW_CLK_HAS_GATE | AW_CLK_REPARENT
440e37e8677SEmmanuel Vadot };
441e37e8677SEmmanuel Vadot 
442e37e8677SEmmanuel Vadot static struct aw_clk_nm_def spi1_clk = {
443e37e8677SEmmanuel Vadot 	.clkdef = {
444e37e8677SEmmanuel Vadot 		.id = CLK_SPI1,
445e37e8677SEmmanuel Vadot 		.name = "spi1",
446e37e8677SEmmanuel Vadot 		.parent_names = mod_parents,
447e37e8677SEmmanuel Vadot 		.parent_cnt = nitems(mod_parents),
448e37e8677SEmmanuel Vadot 	},
449e37e8677SEmmanuel Vadot 	.offset = 0xA4,
450e37e8677SEmmanuel Vadot 	.n = {.shift = 16, .width = 2, .flags = AW_CLK_FACTOR_POWER_OF_TWO, },
451e37e8677SEmmanuel Vadot 	.m = {.shift = 0, .width = 4},
452e37e8677SEmmanuel Vadot 	.mux_shift = 24,
453e37e8677SEmmanuel Vadot 	.mux_width = 2,
454e37e8677SEmmanuel Vadot 	.gate_shift = 31,
455e37e8677SEmmanuel Vadot 	.flags = AW_CLK_HAS_MUX | AW_CLK_HAS_GATE | AW_CLK_REPARENT
456e37e8677SEmmanuel Vadot };
457e37e8677SEmmanuel Vadot 
458e37e8677SEmmanuel Vadot static struct aw_clk_nm_def spi2_clk = {
459e37e8677SEmmanuel Vadot 	.clkdef = {
460e37e8677SEmmanuel Vadot 		.id = CLK_SPI2,
461e37e8677SEmmanuel Vadot 		.name = "spi2",
462e37e8677SEmmanuel Vadot 		.parent_names = mod_parents,
463e37e8677SEmmanuel Vadot 		.parent_cnt = nitems(mod_parents),
464e37e8677SEmmanuel Vadot 	},
465e37e8677SEmmanuel Vadot 	.offset = 0xA8,
466e37e8677SEmmanuel Vadot 	.n = {.shift = 16, .width = 2, .flags = AW_CLK_FACTOR_POWER_OF_TWO, },
467e37e8677SEmmanuel Vadot 	.m = {.shift = 0, .width = 4},
468e37e8677SEmmanuel Vadot 	.mux_shift = 24,
469e37e8677SEmmanuel Vadot 	.mux_width = 2,
470e37e8677SEmmanuel Vadot 	.gate_shift = 31,
471e37e8677SEmmanuel Vadot 	.flags = AW_CLK_HAS_MUX | AW_CLK_HAS_GATE | AW_CLK_REPARENT
472e37e8677SEmmanuel Vadot };
473e37e8677SEmmanuel Vadot 
474e37e8677SEmmanuel Vadot static struct aw_clk_nm_def ir_clk = {
475e37e8677SEmmanuel Vadot 	.clkdef = {
476e37e8677SEmmanuel Vadot 		.id = CLK_IR,
477e37e8677SEmmanuel Vadot 		.name = "ir",
478e37e8677SEmmanuel Vadot 		.parent_names = mod_parents,
479e37e8677SEmmanuel Vadot 		.parent_cnt = nitems(mod_parents),
480e37e8677SEmmanuel Vadot 	},
481e37e8677SEmmanuel Vadot 	.offset = 0xB0,
482e37e8677SEmmanuel Vadot 	.n = {.shift = 16, .width = 2, .flags = AW_CLK_FACTOR_POWER_OF_TWO, },
483e37e8677SEmmanuel Vadot 	.m = {.shift = 0, .width = 4},
484e37e8677SEmmanuel Vadot 	.mux_shift = 24,
485e37e8677SEmmanuel Vadot 	.mux_width = 2,
486e37e8677SEmmanuel Vadot 	.gate_shift = 31,
487e37e8677SEmmanuel Vadot 	.flags = AW_CLK_HAS_MUX | AW_CLK_HAS_GATE | AW_CLK_REPARENT
488e37e8677SEmmanuel Vadot };
489e37e8677SEmmanuel Vadot 
490e37e8677SEmmanuel Vadot /* Missing DE-BE clock */
491e37e8677SEmmanuel Vadot /* Missing DE-FE clock */
492e37e8677SEmmanuel Vadot /* Missing LCD CH1 clock */
493e37e8677SEmmanuel Vadot /* Missing CSI clock */
494e37e8677SEmmanuel Vadot /* Missing VE clock */
495e37e8677SEmmanuel Vadot 
496e37e8677SEmmanuel Vadot /* Clocks list */
497e37e8677SEmmanuel Vadot static struct aw_ccung_clk a13_ccu_clks[] = {
498e37e8677SEmmanuel Vadot 	{ .type = AW_CLK_NKMP, .clk.nkmp = &pll_core},
499e37e8677SEmmanuel Vadot 	{ .type = AW_CLK_NKMP, .clk.nkmp = &pll_audio},
500e37e8677SEmmanuel Vadot 	{ .type = AW_CLK_NKMP, .clk.nkmp = &pll_ddr_base},
501e37e8677SEmmanuel Vadot 	{ .type = AW_CLK_NKMP, .clk.nkmp = &pll_periph},
502e37e8677SEmmanuel Vadot 	{ .type = AW_CLK_NM, .clk.nm = &apb1_clk},
503e37e8677SEmmanuel Vadot 	{ .type = AW_CLK_NM, .clk.nm = &nand_clk},
504e37e8677SEmmanuel Vadot 	{ .type = AW_CLK_NM, .clk.nm = &mmc0_clk},
505e37e8677SEmmanuel Vadot 	{ .type = AW_CLK_NM, .clk.nm = &mmc1_clk},
506e37e8677SEmmanuel Vadot 	{ .type = AW_CLK_NM, .clk.nm = &mmc2_clk},
507e37e8677SEmmanuel Vadot 	{ .type = AW_CLK_NM, .clk.nm = &ss_clk},
508e37e8677SEmmanuel Vadot 	{ .type = AW_CLK_NM, .clk.nm = &spi0_clk},
509e37e8677SEmmanuel Vadot 	{ .type = AW_CLK_NM, .clk.nm = &spi1_clk},
510e37e8677SEmmanuel Vadot 	{ .type = AW_CLK_NM, .clk.nm = &spi2_clk},
511e37e8677SEmmanuel Vadot 	{ .type = AW_CLK_NM, .clk.nm = &ir_clk},
512e37e8677SEmmanuel Vadot 	{ .type = AW_CLK_PREDIV_MUX, .clk.prediv_mux = &cpu_clk},
513e37e8677SEmmanuel Vadot 	{ .type = AW_CLK_PREDIV_MUX, .clk.prediv_mux = &ahb_clk},
514e37e8677SEmmanuel Vadot 	{ .type = AW_CLK_DIV, .clk.div = &pll_ddr},
515e37e8677SEmmanuel Vadot 	{ .type = AW_CLK_DIV, .clk.div = &pll_ddr_other},
516e37e8677SEmmanuel Vadot 	{ .type = AW_CLK_DIV, .clk.div = &axi_clk},
517e37e8677SEmmanuel Vadot 	{ .type = AW_CLK_DIV, .clk.div = &apb0_clk},
518e37e8677SEmmanuel Vadot };
519e37e8677SEmmanuel Vadot 
520e37e8677SEmmanuel Vadot static int
ccu_a13_probe(device_t dev)521e37e8677SEmmanuel Vadot ccu_a13_probe(device_t dev)
522e37e8677SEmmanuel Vadot {
523e37e8677SEmmanuel Vadot 
524e37e8677SEmmanuel Vadot 	if (!ofw_bus_status_okay(dev))
525e37e8677SEmmanuel Vadot 		return (ENXIO);
526e37e8677SEmmanuel Vadot 
527e37e8677SEmmanuel Vadot 	if (!ofw_bus_is_compatible(dev, "allwinner,sun5i-a13-ccu"))
528e37e8677SEmmanuel Vadot 		return (ENXIO);
529e37e8677SEmmanuel Vadot 
530e37e8677SEmmanuel Vadot 	device_set_desc(dev, "Allwinner A13 Clock Control Unit NG");
531e37e8677SEmmanuel Vadot 	return (BUS_PROBE_DEFAULT);
532e37e8677SEmmanuel Vadot }
533e37e8677SEmmanuel Vadot 
534e37e8677SEmmanuel Vadot static int
ccu_a13_attach(device_t dev)535e37e8677SEmmanuel Vadot ccu_a13_attach(device_t dev)
536e37e8677SEmmanuel Vadot {
537e37e8677SEmmanuel Vadot 	struct aw_ccung_softc *sc;
538e37e8677SEmmanuel Vadot 
539e37e8677SEmmanuel Vadot 	sc = device_get_softc(dev);
540e37e8677SEmmanuel Vadot 
541e37e8677SEmmanuel Vadot 	sc->resets = a13_ccu_resets;
542e37e8677SEmmanuel Vadot 	sc->nresets = nitems(a13_ccu_resets);
543e37e8677SEmmanuel Vadot 	sc->gates = a13_ccu_gates;
544e37e8677SEmmanuel Vadot 	sc->ngates = nitems(a13_ccu_gates);
545e37e8677SEmmanuel Vadot 	sc->clks = a13_ccu_clks;
546e37e8677SEmmanuel Vadot 	sc->nclks = nitems(a13_ccu_clks);
547e37e8677SEmmanuel Vadot 
548e37e8677SEmmanuel Vadot 	return (aw_ccung_attach(dev));
549e37e8677SEmmanuel Vadot }
550e37e8677SEmmanuel Vadot 
551e37e8677SEmmanuel Vadot static device_method_t ccu_a13ng_methods[] = {
552e37e8677SEmmanuel Vadot 	/* Device interface */
553e37e8677SEmmanuel Vadot 	DEVMETHOD(device_probe,		ccu_a13_probe),
554e37e8677SEmmanuel Vadot 	DEVMETHOD(device_attach,	ccu_a13_attach),
555e37e8677SEmmanuel Vadot 
556e37e8677SEmmanuel Vadot 	DEVMETHOD_END
557e37e8677SEmmanuel Vadot };
558e37e8677SEmmanuel Vadot 
559e37e8677SEmmanuel Vadot DEFINE_CLASS_1(ccu_a13ng, ccu_a13ng_driver, ccu_a13ng_methods,
560e37e8677SEmmanuel Vadot   sizeof(struct aw_ccung_softc), aw_ccung_driver);
561e37e8677SEmmanuel Vadot 
562e37e8677SEmmanuel Vadot EARLY_DRIVER_MODULE(ccu_a13ng, simplebus, ccu_a13ng_driver, 0, 0,
563e37e8677SEmmanuel Vadot     BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);
564