xref: /netbsd-src/sys/arch/arm/sunxi/sun4i_a10_ccu.c (revision 6e54367a22fbc89a1139d033e95bec0c0cf0975b)
1 /* $NetBSD: sun4i_a10_ccu.c,v 1.16 2021/01/27 03:10:20 thorpej Exp $ */
2 
3 /*-
4  * Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 
31 __KERNEL_RCSID(1, "$NetBSD: sun4i_a10_ccu.c,v 1.16 2021/01/27 03:10:20 thorpej Exp $");
32 
33 #include <sys/param.h>
34 #include <sys/bus.h>
35 #include <sys/device.h>
36 #include <sys/systm.h>
37 
38 #include <dev/fdt/fdtvar.h>
39 
40 #include <arm/sunxi/sunxi_ccu.h>
41 #include <arm/sunxi/sun4i_a10_ccu.h>
42 #include <arm/sunxi/sun7i_a20_ccu.h>
43 
44 #define	PLL1_CFG_REG		0x000
45 #define	PLL2_CFG_REG		0x008
46 #define	PLL3_CFG_REG		0x010
47 #define	PLL5_CFG_REG		0x020
48 #define	PLL6_CFG_REG		0x028
49 #define	PLL7_CFG_REG		0x030
50 #define	OSC24M_CFG_REG		0x050
51 #define	CPU_AHB_APB0_CFG_REG	0x054
52 #define	APB1_CLK_DIV_REG	0x058
53 #define	AHB_GATING_REG0		0x060
54 #define	AHB_GATING_REG1		0x064
55 #define	APB0_GATING_REG		0x068
56 #define	APB1_GATING_REG		0x06c
57 #define	NAND_SCLK_CFG_REG	0x080
58 #define	SD0_SCLK_CFG_REG        0x088
59 #define	SD1_SCLK_CFG_REG        0x08c
60 #define	SD2_SCLK_CFG_REG        0x090
61 #define	SD3_SCLK_CFG_REG	0x094
62 #define	SPI0_CLK_CFG_REG	0x0a0
63 #define	SPI1_CLK_CFG_REG	0x0a4
64 #define	SPI2_CLK_CFG_REG	0x0a8
65 #define	SATA_CFG_REG		0x0c8
66 #define	USBPHY_CFG_REG		0x0cc
67 #define	SPI3_CLK_CFG_REG	0x0d4
68 #define	DRAM_GATING_REG		0x100
69 #define	BE0_CFG_REG		0x104
70 #define	BE1_CFG_REG		0x108
71 #define	FE0_CFG_REG		0x10c
72 #define	FE1_CFG_REG		0x110
73 #define	MP_CFG_REG		0x114
74 #define	LCD0CH0_CFG_REG		0x118
75 #define	LCD1CH0_CFG_REG		0x11c
76 #define LCD0CH1_CFG_REG		0x12c
77 #define LCD1CH1_CFG_REG		0x130
78 #define	CSI_CFG_REG		0x134
79 #define	VE_CFG_REG		0x13c
80 #define	AUDIO_CODEC_SCLK_CFG_REG 0x140
81 #define	LVDS_CFG_REG 		0x14c
82 #define	HDMI_CLOCK_CFG_REG	0x150
83 #define	MALI_CLOCK_CFG_REG	0x154
84 #define	IEP_SCLK_CFG_REG	0x160
85 #define	CLK_OUTA_REG		0x1f0
86 #define	CLK_OUTB_REG		0x1f4
87 
88 static int sun4i_a10_ccu_match(device_t, cfdata_t, void *);
89 static void sun4i_a10_ccu_attach(device_t, device_t, void *);
90 
91 enum sun4i_a10_ccu_type {
92 	CCU_A10 = 1,
93 	CCU_A20,
94 };
95 
96 static const struct device_compatible_entry compat_data[] = {
97 	{ .compat = "allwinner,sun4i-a10-ccu",	.value = CCU_A10 },
98 	{ .compat = "allwinner,sun7i-a20-ccu",	.value = CCU_A20 },
99 	DEVICE_COMPAT_EOL
100 };
101 
102 CFATTACH_DECL_NEW(sunxi_a10_ccu, sizeof(struct sunxi_ccu_softc),
103 	sun4i_a10_ccu_match, sun4i_a10_ccu_attach, NULL, NULL);
104 
105 static struct sunxi_ccu_reset sun4i_a10_ccu_resets[] = {
106 	SUNXI_CCU_RESET(A10_RST_USB_PHY0, USBPHY_CFG_REG, 0),
107 	SUNXI_CCU_RESET(A10_RST_USB_PHY1, USBPHY_CFG_REG, 1),
108 	SUNXI_CCU_RESET(A10_RST_USB_PHY2, USBPHY_CFG_REG, 2),
109 	SUNXI_CCU_RESET(A10_RST_DE_BE0, BE0_CFG_REG, 30),
110 	SUNXI_CCU_RESET(A10_RST_DE_BE1, BE1_CFG_REG, 30),
111 	SUNXI_CCU_RESET(A10_RST_DE_FE0, FE0_CFG_REG, 30),
112 	SUNXI_CCU_RESET(A10_RST_DE_FE1, FE1_CFG_REG, 30),
113 	SUNXI_CCU_RESET(A10_RST_DE_MP, MP_CFG_REG, 30),
114 	SUNXI_CCU_RESET(A10_RST_TCON0, LCD0CH0_CFG_REG, 30),
115 	SUNXI_CCU_RESET(A10_RST_TCON1, LCD1CH0_CFG_REG, 30),
116 	SUNXI_CCU_RESET(A10_RST_LVDS, LVDS_CFG_REG, 0),
117 };
118 
119 static const char *cpu_parents[] = { "losc", "osc24m", "pll_core", "pll_periph" };
120 static const char *axi_parents[] = { "cpu" };
121 static const char *ahb_parents[] = { "axi", "pll_periph", "pll_periph_base" };
122 static const char *apb0_parents[] = { "ahb" };
123 static const char *apb1_parents[] = { "osc24m", "pll_periph", "losc" };
124 static const char *mod_parents[] = { "osc24m", "pll_periph", "pll_ddr_other" };
125 static const char *sata_parents[] = { "pll6_periph_sata", "external" };
126 static const char *de_parents[] = { "pll_video0", "pll_video1", "pll_ddr_other" };
127 static const char *lcd_parents[] = { "pll_video0", "pll_video1", "pll_video0x2", "pll_video1x2" };
128 static const char *out_parents[] = { "losc" /* really OSC24MHz/750 */, "losc", "osc24m" };
129 
130 static const struct sunxi_ccu_nkmp_tbl sun4i_a10_pll1_table[] = {
131 	{ 1008000000, 21, 1, 0, 0 },
132 	{  960000000, 20, 1, 0, 0 },
133 	{  912000000, 19, 1, 0, 0 },
134 	{  864000000, 18, 1, 0, 0 },
135 	{  720000000, 30, 0, 0, 0 },
136 	{  624000000, 26, 0, 0, 0 },
137 	{  528000000, 22, 0, 0, 0 },
138 	{  312000000, 13, 0, 0, 0 },
139 	{  144000000, 12, 0, 0, 1 },
140 	{          0 }
141 };
142 
143 static const struct sunxi_ccu_nkmp_tbl sun4i_a10_ac_dig_table[] = {
144 	{ 24576000, 86, 0, 21, 4 },
145 	{ 0 }
146 };
147 
148 /*
149  * some special cases
150  * hardcode lcd0 (tcon0) to pll3 and lcd1 (tcon1) to pll7.
151  * compute pll rate based on desired pixel clock
152  */
153 
154 static int sun4i_a10_ccu_lcd0ch0_set_rate(struct sunxi_ccu_softc *,
155     struct sunxi_ccu_clk *, u_int);
156 static int sun4i_a10_ccu_lcd1ch0_set_rate(struct sunxi_ccu_softc *,
157     struct sunxi_ccu_clk *, u_int);
158 static u_int sun4i_a10_ccu_lcd0ch0_round_rate(struct sunxi_ccu_softc *,
159     struct sunxi_ccu_clk *, u_int);
160 static u_int sun4i_a10_ccu_lcd1ch0_round_rate(struct sunxi_ccu_softc *,
161     struct sunxi_ccu_clk *, u_int);
162 static int sun4i_a10_ccu_lcd0ch1_set_rate(struct sunxi_ccu_softc *,
163     struct sunxi_ccu_clk *, u_int);
164 static int sun4i_a10_ccu_lcd1ch1_set_rate(struct sunxi_ccu_softc *,
165     struct sunxi_ccu_clk *, u_int);
166 
167 static struct sunxi_ccu_clk sun4i_a10_ccu_clks[] = {
168 	SUNXI_CCU_GATE(A10_CLK_HOSC, "osc24m", "hosc",
169 	    OSC24M_CFG_REG, 0),
170 
171 	SUNXI_CCU_NKMP_TABLE(A10_CLK_PLL_CORE, "pll_core", "osc24m",
172 	    PLL1_CFG_REG,		/* reg */
173 	    __BITS(12,8),		/* n */
174 	    __BITS(5,4), 		/* k */
175 	    __BITS(1,0),		/* m */
176 	    __BITS(17,16),		/* p */
177 	    __BIT(31),			/* enable */
178 	    0,				/* lock */
179 	    sun4i_a10_pll1_table,	/* table */
180 	    SUNXI_CCU_NKMP_FACTOR_P_POW2 | SUNXI_CCU_NKMP_FACTOR_N_EXACT |
181 	    SUNXI_CCU_NKMP_FACTOR_N_ZERO_IS_ONE | SUNXI_CCU_NKMP_SCALE_CLOCK),
182 
183 	SUNXI_CCU_NKMP_TABLE(A10_CLK_PLL_AUDIO_BASE, "pll_audio", "osc24m",
184 	    PLL2_CFG_REG,		/* reg */
185 	    __BITS(14,8),		/* n */
186 	    0,				/* k */
187 	    __BITS(4,0),		/* m */
188 	    __BITS(29,26),		/* p */
189 	    __BIT(31),			/* enable */
190 	    0,				/* lock */
191 	    sun4i_a10_ac_dig_table,	/* table */
192 	    0),
193 
194 	SUNXI_CCU_NKMP(A10_CLK_PLL_PERIPH_BASE, "pll_periph_base", "osc24m",
195 	    PLL6_CFG_REG,		/* reg */
196 	    __BITS(12,8),		/* n */
197 	    __BITS(5,4), 		/* k */
198 	    0,				/* m */
199 	    0,				/* p */
200 	    __BIT(31),			/* enable */
201 	    SUNXI_CCU_NKMP_FACTOR_N_EXACT),
202 
203 	SUNXI_CCU_FIXED_FACTOR(A10_CLK_PLL_PERIPH, "pll_periph", "pll_periph_base",
204 	    2, 1),
205 
206 	SUNXI_CCU_NKMP(A10_CLK_PLL_PERIPH_SATA, "pll_periph_sata", "pll_periph_base",
207 	    PLL6_CFG_REG,		/* reg */
208 	    0,				/* n */
209 	    0,				/* k */
210 	    __BITS(1,0),		/* m */
211 	    0,				/* p */
212 	    __BIT(14),			/* enable */
213 	    0),
214 
215 	SUNXI_CCU_DIV_GATE(A10_CLK_SATA, "sata", sata_parents,
216 	    SATA_CFG_REG,		/* reg */
217 	    0,				/* div */
218 	    __BIT(24),			/* sel */
219 	    __BIT(31),			/* enable */
220 	    0),
221 
222 	SUNXI_CCU_NKMP(A10_CLK_PLL_DDR_BASE, "pll_ddr_other", "osc24m",
223 	    PLL5_CFG_REG,		/* reg */
224 	    __BITS(12, 8),		/* n */
225 	    __BITS(5,4),		/* k */
226 	    0,				/* m */
227 	    __BITS(17,16),		/* p */
228 	    __BIT(31),			/* enable */
229 	    SUNXI_CCU_NKMP_FACTOR_N_EXACT | SUNXI_CCU_NKMP_FACTOR_P_POW2),
230 
231 	SUNXI_CCU_NKMP(A10_CLK_PLL_DDR, "pll_ddr", "osc24m",
232 	    PLL5_CFG_REG,		/* reg */
233 	    __BITS(12, 8),		/* n */
234 	    __BITS(5,4),		/* k */
235 	    __BITS(1,0),		/* m */
236 	    0,				/* p */
237 	    __BIT(31),			/* enable */
238 	    SUNXI_CCU_NKMP_FACTOR_N_EXACT),
239 
240 	SUNXI_CCU_DIV(A10_CLK_CPU, "cpu", cpu_parents,
241 	    CPU_AHB_APB0_CFG_REG,	/* reg */
242 	    0,				/* div */
243 	    __BITS(17,16),		/* sel */
244 	    SUNXI_CCU_DIV_SET_RATE_PARENT),
245 
246 	SUNXI_CCU_DIV(A10_CLK_AXI, "axi", axi_parents,
247 	    CPU_AHB_APB0_CFG_REG,	/* reg */
248 	    __BITS(1,0),		/* div */
249 	    0,				/* sel */
250 	    0),
251 
252 	SUNXI_CCU_DIV(A10_CLK_AHB, "ahb", ahb_parents,
253 	    CPU_AHB_APB0_CFG_REG,	/* reg */
254 	    __BITS(5,4),		/* div */
255 	    __BITS(7,6),		/* sel */
256 	    SUNXI_CCU_DIV_POWER_OF_TWO),
257 
258 	SUNXI_CCU_DIV(A10_CLK_APB0, "apb0", apb0_parents,
259 	    CPU_AHB_APB0_CFG_REG,	/* reg */
260 	    __BITS(9,8),		/* div */
261 	    0,				/* sel */
262 	    SUNXI_CCU_DIV_ZERO_IS_ONE | SUNXI_CCU_DIV_POWER_OF_TWO),
263 
264 	SUNXI_CCU_NM(A10_CLK_APB1, "apb1", apb1_parents,
265 	    APB1_CLK_DIV_REG,		/* reg */
266 	    __BITS(17,16),		/* n */
267 	    __BITS(4,0),		/* m */
268 	    __BITS(25,24),		/* sel */
269 	    0,				/* enable */
270 	    SUNXI_CCU_NM_POWER_OF_TWO),
271 
272 	SUNXI_CCU_NM(A10_CLK_NAND, "nand", mod_parents,
273 	    NAND_SCLK_CFG_REG,		/* reg */
274 	    __BITS(17,16),		/* n */
275 	    __BITS(3,0),		/* m */
276 	    __BITS(25,24),		/* sel */
277 	    __BIT(31),			/* enable */
278 	    SUNXI_CCU_NM_POWER_OF_TWO),
279 
280 	SUNXI_CCU_NM(A10_CLK_SPI0, "spi0", mod_parents,
281 	    SPI0_CLK_CFG_REG,		/* reg */
282 	    __BITS(17,16),		/* n */
283 	    __BITS(3,0),		/* m */
284 	    __BITS(25,24),		/* sel */
285 	    __BIT(31),			/* enable */
286 	    SUNXI_CCU_NM_POWER_OF_TWO),
287 
288 	SUNXI_CCU_NM(A10_CLK_SPI1, "spi1", mod_parents,
289 	    SPI1_CLK_CFG_REG,		/* reg */
290 	    __BITS(17,16),		/* n */
291 	    __BITS(3,0),		/* m */
292 	    __BITS(25,24),		/* sel */
293 	    __BIT(31),			/* enable */
294 	    SUNXI_CCU_NM_POWER_OF_TWO),
295 
296 	SUNXI_CCU_NM(A10_CLK_SPI2, "spi2", mod_parents,
297 	    SPI2_CLK_CFG_REG,		/* reg */
298 	    __BITS(17,16),		/* n */
299 	    __BITS(3,0),		/* m */
300 	    __BITS(25,24),		/* sel */
301 	    __BIT(31),			/* enable */
302 	    SUNXI_CCU_NM_POWER_OF_TWO),
303 
304 	SUNXI_CCU_NM(A10_CLK_SPI3, "spi3", mod_parents,
305 	    SPI3_CLK_CFG_REG,		/* reg */
306 	    __BITS(17,16),		/* n */
307 	    __BITS(3,0),		/* m */
308 	    __BITS(25,24),		/* sel */
309 	    __BIT(31),			/* enable */
310 	    SUNXI_CCU_NM_POWER_OF_TWO),
311 
312 	SUNXI_CCU_NM(A10_CLK_MMC0, "mmc0", mod_parents,
313 	    SD0_SCLK_CFG_REG,		/* reg */
314 	    __BITS(17,16),		/* n */
315 	    __BITS(3,0),		/* m */
316 	    __BITS(25,24),		/* sel */
317 	    __BIT(31),			/* enable */
318 	    SUNXI_CCU_NM_POWER_OF_TWO),
319 	SUNXI_CCU_PHASE(A10_CLK_MMC0_SAMPLE, "mmc0_sample", "mmc0",
320 	    SD0_SCLK_CFG_REG, __BITS(22,20)),
321 	SUNXI_CCU_PHASE(A10_CLK_MMC0_OUTPUT, "mmc0_output", "mmc0",
322 	    SD0_SCLK_CFG_REG, __BITS(10,8)),
323 	SUNXI_CCU_NM(A10_CLK_MMC1, "mmc1", mod_parents,
324 	    SD1_SCLK_CFG_REG,		/* reg */
325 	    __BITS(17,16),		/* n */
326 	    __BITS(3,0),		/* m */
327 	    __BITS(25,24),		/* sel */
328 	    __BIT(31),			/* enable */
329 	    SUNXI_CCU_NM_POWER_OF_TWO),
330 	SUNXI_CCU_PHASE(A10_CLK_MMC1_SAMPLE, "mmc1_sample", "mmc1",
331 	    SD1_SCLK_CFG_REG, __BITS(22,20)),
332 	SUNXI_CCU_PHASE(A10_CLK_MMC1_OUTPUT, "mmc1_output", "mmc1",
333 	    SD1_SCLK_CFG_REG, __BITS(10,8)),
334 	SUNXI_CCU_NM(A10_CLK_MMC2, "mmc2", mod_parents,
335 	    SD2_SCLK_CFG_REG,		/* reg */
336 	    __BITS(17,16),		/* n */
337 	    __BITS(3,0),		/* m */
338 	    __BITS(25,24),		/* sel */
339 	    __BIT(31),			/* enable */
340 	    SUNXI_CCU_NM_POWER_OF_TWO),
341 	SUNXI_CCU_PHASE(A10_CLK_MMC2_SAMPLE, "mmc2_sample", "mmc2",
342 	    SD2_SCLK_CFG_REG, __BITS(22,20)),
343 	SUNXI_CCU_PHASE(A10_CLK_MMC2_OUTPUT, "mmc2_output", "mmc2",
344 	    SD2_SCLK_CFG_REG, __BITS(10,8)),
345 	SUNXI_CCU_NM(A10_CLK_MMC3, "mmc3", mod_parents,
346 	    SD3_SCLK_CFG_REG,		/* reg */
347 	    __BITS(17,16),		/* n */
348 	    __BITS(3,0),		/* m */
349 	    __BITS(25,24),		/* sel */
350 	    __BIT(31),			/* enable */
351 	    SUNXI_CCU_NM_POWER_OF_TWO),
352 	SUNXI_CCU_PHASE(A10_CLK_MMC3_SAMPLE, "mmc3_sample", "mmc3",
353 	    SD3_SCLK_CFG_REG, __BITS(22,20)),
354 	SUNXI_CCU_PHASE(A10_CLK_MMC3_OUTPUT, "mmc3_output", "mmc3",
355 	    SD3_SCLK_CFG_REG, __BITS(10,8)),
356 
357 	SUNXI_CCU_FRACTIONAL(A10_CLK_PLL_VIDEO0, "pll_video0", "osc24m",
358 	    PLL3_CFG_REG,		/* reg */
359 	    __BITS(7,0),		/* m */
360 	    9,				/* m_min */
361 	    127,			/* m_max */
362 	    __BIT(15),			/* div_en */
363 	    __BIT(14),			/* frac_sel */
364 	    270000000, 297000000,	/* frac values */
365 	    0,				/* prediv */
366 	    8,				/* prediv_val */
367 	    __BIT(31),			/* enable */
368 	    0),
369 	SUNXI_CCU_FRACTIONAL(A10_CLK_PLL_VIDEO1, "pll_video1", "osc24m",
370 	    PLL7_CFG_REG,		/* reg */
371 	    __BITS(7,0),		/* m */
372 	    9,				/* m_min */
373 	    127,			/* m_max */
374 	    __BIT(15),			/* div_en */
375 	    __BIT(14),			/* frac_sel */
376 	    270000000, 297000000,	/* frac values */
377 	    0,				/* prediv */
378 	    8,				/* prediv_val */
379 	    __BIT(31),			/* enable */
380 	    0),
381 	SUNXI_CCU_FIXED_FACTOR(A10_CLK_PLL_VIDEO0_2X,
382 	    "pll_video0x2", "pll_video0",
383 	    1, 2),
384 	SUNXI_CCU_FIXED_FACTOR(A10_CLK_PLL_VIDEO1_2X,
385 	    "pll_video1x2", "pll_video1",
386 	    1, 2),
387 
388 	SUNXI_CCU_DIV_GATE(A10_CLK_DE_BE0, "debe0-mod", de_parents,
389 	    BE0_CFG_REG,		/* reg */
390 	    __BITS(3,0),		/* div */
391 	    __BITS(25,24),		/* sel */
392 	    __BIT(31),			/* enable */
393 	    0				/* flags */
394 	    ),
395 	SUNXI_CCU_DIV_GATE(A10_CLK_DE_BE1, "debe1-mod", de_parents,
396 	    BE1_CFG_REG,		/* reg */
397 	    __BITS(3,0),		/* div */
398 	    __BITS(25,24),		/* sel */
399 	    __BIT(31),			/* enable */
400 	    0				/* flags */
401 	    ),
402 	SUNXI_CCU_DIV_GATE(A10_CLK_DE_FE0, "defe0-mod", de_parents,
403 	    FE0_CFG_REG,		/* reg */
404 	    __BITS(3,0),		/* div */
405 	    __BITS(25,24),		/* sel */
406 	    __BIT(31),			/* enable */
407 	    0				/* flags */
408 	    ),
409 	SUNXI_CCU_DIV_GATE(A10_CLK_DE_FE1, "defe1-mod", de_parents,
410 	    FE1_CFG_REG,		/* reg */
411 	    __BITS(3,0),		/* div */
412 	    __BITS(25,24),		/* sel */
413 	    __BIT(31),			/* enable */
414 	    0				/* flags */
415 	    ),
416 	[A10_CLK_TCON0_CH0] = {
417 	    .type = SUNXI_CCU_DIV,
418 	    .base.name = "tcon0-ch0",
419 	    .u.div.reg = LCD0CH0_CFG_REG,
420 	    .u.div.parents = lcd_parents,
421 	    .u.div.nparents = __arraycount(lcd_parents),
422 	    .u.div.div = 0,
423 	    .u.div.sel = __BITS(25,24),
424 	    .u.div.enable = __BIT(31),
425 	    .u.div.flags = 0,
426 	    .enable = sunxi_ccu_div_enable,
427 	    .get_rate = sunxi_ccu_div_get_rate,
428 	    .set_rate = sun4i_a10_ccu_lcd0ch0_set_rate,
429 	    .round_rate = sun4i_a10_ccu_lcd0ch0_round_rate,
430 	    .set_parent = sunxi_ccu_div_set_parent,
431 	    .get_parent = sunxi_ccu_div_get_parent,
432 	    },
433 	[A10_CLK_TCON1_CH0] = {
434 	    .type = SUNXI_CCU_DIV,
435 	    .base.name = "tcon1-ch0",
436 	    .u.div.reg = LCD1CH0_CFG_REG,
437 	    .u.div.parents = lcd_parents,
438 	    .u.div.nparents = __arraycount(lcd_parents),
439 	    .u.div.div = 0,
440 	    .u.div.sel = __BITS(25,24),
441 	    .u.div.enable = __BIT(31),
442 	    .u.div.flags = 0,
443 	    .enable = sunxi_ccu_div_enable,
444 	    .get_rate = sunxi_ccu_div_get_rate,
445 	    .set_rate = sun4i_a10_ccu_lcd1ch0_set_rate,
446 	    .round_rate = sun4i_a10_ccu_lcd1ch0_round_rate,
447 	    .set_parent = sunxi_ccu_div_set_parent,
448 	    .get_parent = sunxi_ccu_div_get_parent,
449 	    },
450 	[A10_CLK_TCON0_CH1] = {
451 	    .type = SUNXI_CCU_DIV,
452 	    .base.name = "tcon0-ch1",
453 	    .u.div.reg = LCD0CH1_CFG_REG,
454 	    .u.div.parents = lcd_parents,
455 	    .u.div.nparents = __arraycount(lcd_parents),
456 	    .u.div.div = __BITS(3,0),
457 	    .u.div.sel = __BITS(25,24),
458 	    .u.div.enable = __BIT(15) | __BIT(31),
459 	    .u.div.flags = 0,
460 	    .enable = sunxi_ccu_div_enable,
461 	    .get_rate = sunxi_ccu_div_get_rate,
462 	    .set_rate = sun4i_a10_ccu_lcd0ch1_set_rate,
463 	    .set_parent = sunxi_ccu_div_set_parent,
464 	    .get_parent = sunxi_ccu_div_get_parent,
465 	    },
466 	[A10_CLK_TCON1_CH1] = {
467 	    .type = SUNXI_CCU_DIV,
468 	    .base.name = "tcon1-ch1",
469 	    .u.div.reg = LCD1CH1_CFG_REG,
470 	    .u.div.parents = lcd_parents,
471 	    .u.div.nparents = __arraycount(lcd_parents),
472 	    .u.div.div = __BITS(3,0),
473 	    .u.div.sel = __BITS(25,24),
474 	    .u.div.enable = __BIT(15) | __BIT(31),
475 	    .u.div.flags = 0,
476 	    .enable = sunxi_ccu_div_enable,
477 	    .get_rate = sunxi_ccu_div_get_rate,
478 	    .set_rate = sun4i_a10_ccu_lcd1ch1_set_rate,
479 	    .set_parent = sunxi_ccu_div_set_parent,
480 	    .get_parent = sunxi_ccu_div_get_parent,
481 	    },
482 	SUNXI_CCU_DIV_GATE(A10_CLK_HDMI, "hdmi-mod", lcd_parents,
483 	    HDMI_CLOCK_CFG_REG,		/* reg */
484 	    __BITS(3,0),		/* div */
485 	    __BITS(25,24),		/* sel */
486 	    __BIT(31),			/* enable */
487 	    0				/* flags */
488 	    ),
489 
490 	/* A20 specific */
491 	SUNXI_CCU_NM(A20_CLK_OUT_A, "outa", out_parents,
492 	    CLK_OUTA_REG,		/* reg */
493 	    __BITS(21,20),		/* n */
494 	    __BITS(12,8),		/* m */
495 	    __BITS(25,24),		/* sel */
496 	    __BIT(31),			/* enable */
497 	    SUNXI_CCU_NM_POWER_OF_TWO),
498 
499 	SUNXI_CCU_NM(A20_CLK_OUT_B, "outb", out_parents,
500 	    CLK_OUTB_REG,		/* reg */
501 	    __BITS(21,20),		/* n */
502 	    __BITS(12,8),		/* m */
503 	    __BITS(25,24),		/* sel */
504 	    __BIT(31),			/* enable */
505 	    SUNXI_CCU_NM_POWER_OF_TWO),
506 
507 	/* AHB_GATING_REG0 */
508 	SUNXI_CCU_GATE(A10_CLK_AHB_OTG, "ahb-otg", "ahb",
509 	    AHB_GATING_REG0, 0),
510 	SUNXI_CCU_GATE(A10_CLK_AHB_EHCI0, "ahb-ehci0", "ahb",
511 	    AHB_GATING_REG0, 1),
512 	SUNXI_CCU_GATE(A10_CLK_AHB_OHCI0, "ahb-ohci0", "ahb",
513 	    AHB_GATING_REG0, 2),
514 	SUNXI_CCU_GATE(A10_CLK_AHB_EHCI1, "ahb-ehci1", "ahb",
515 	    AHB_GATING_REG0, 3),
516 	SUNXI_CCU_GATE(A10_CLK_AHB_OHCI1, "ahb-ohci1", "ahb",
517 	    AHB_GATING_REG0, 4),
518 	SUNXI_CCU_GATE(A10_CLK_AHB_SS, "ahb-ss", "ahb",
519 	    AHB_GATING_REG0, 5),
520 	SUNXI_CCU_GATE(A10_CLK_AHB_DMA, "ahb-dma", "ahb",
521 	    AHB_GATING_REG0, 6),
522 	SUNXI_CCU_GATE(A10_CLK_AHB_BIST, "ahb-bist", "ahb",
523 	    AHB_GATING_REG0, 7),
524 	SUNXI_CCU_GATE(A10_CLK_AHB_MMC0, "ahb-mmc0", "ahb",
525 	    AHB_GATING_REG0, 8),
526 	SUNXI_CCU_GATE(A10_CLK_AHB_MMC1, "ahb-mmc1", "ahb",
527 	    AHB_GATING_REG0, 9),
528 	SUNXI_CCU_GATE(A10_CLK_AHB_MMC2, "ahb-mmc2", "ahb",
529 	    AHB_GATING_REG0, 10),
530 	SUNXI_CCU_GATE(A10_CLK_AHB_MMC3, "ahb-mmc3", "ahb",
531 	    AHB_GATING_REG0, 11),
532 	SUNXI_CCU_GATE(A10_CLK_AHB_MS, "ahb-ms", "ahb",
533 	    AHB_GATING_REG0, 12),
534 	SUNXI_CCU_GATE(A10_CLK_AHB_NAND, "ahb-nand", "ahb",
535 	    AHB_GATING_REG0, 13),
536 	SUNXI_CCU_GATE(A10_CLK_AHB_SDRAM, "ahb-sdram", "ahb",
537 	    AHB_GATING_REG0, 14),
538 	SUNXI_CCU_GATE(A10_CLK_AHB_ACE, "ahb-ace", "ahb",
539 	    AHB_GATING_REG0, 16),
540 	SUNXI_CCU_GATE(A10_CLK_AHB_EMAC, "ahb-emac", "ahb",
541 	    AHB_GATING_REG0, 17),
542 	SUNXI_CCU_GATE(A10_CLK_AHB_TS, "ahb-ts", "ahb",
543 	    AHB_GATING_REG0, 18),
544 	SUNXI_CCU_GATE(A10_CLK_AHB_SPI0, "ahb-spi0", "ahb",
545 	    AHB_GATING_REG0, 20),
546 	SUNXI_CCU_GATE(A10_CLK_AHB_SPI1, "ahb-spi1", "ahb",
547 	    AHB_GATING_REG0, 21),
548 	SUNXI_CCU_GATE(A10_CLK_AHB_SPI2, "ahb-spi2", "ahb",
549 	    AHB_GATING_REG0, 22),
550 	SUNXI_CCU_GATE(A10_CLK_AHB_SPI3, "ahb-spi3", "ahb",
551 	    AHB_GATING_REG0, 23),
552 	SUNXI_CCU_GATE(A10_CLK_AHB_SATA, "ahb-sata", "ahb",
553 	    AHB_GATING_REG0, 25),
554 	SUNXI_CCU_GATE(A10_CLK_AHB_HSTIMER, "ahb-hstimer", "ahb",
555 	    AHB_GATING_REG0, 28),
556 
557 	/* AHB_GATING_REG1. Missing: TVE, HDMI */
558 	SUNXI_CCU_GATE(A10_CLK_AHB_VE, "ahb-ve", "ahb",
559 	    AHB_GATING_REG1, 0),
560 	SUNXI_CCU_GATE(A10_CLK_AHB_TVD, "ahb-tvd", "ahb",
561 	    AHB_GATING_REG1, 1),
562 	SUNXI_CCU_GATE(A10_CLK_AHB_TVE0, "ahb-tve0", "ahb",
563 	    AHB_GATING_REG1, 2),
564 	SUNXI_CCU_GATE(A10_CLK_AHB_TVE1, "ahb-tve1", "ahb",
565 	    AHB_GATING_REG1, 3),
566 	SUNXI_CCU_GATE(A10_CLK_AHB_LCD0, "ahb-lcd0", "ahb",
567 	    AHB_GATING_REG1, 4),
568 	SUNXI_CCU_GATE(A10_CLK_AHB_LCD1, "ahb-lcd1", "ahb",
569 	    AHB_GATING_REG1, 5),
570 	SUNXI_CCU_GATE(A10_CLK_AHB_CSI0, "ahb-csi0", "ahb",
571 	    AHB_GATING_REG1, 8),
572 	SUNXI_CCU_GATE(A10_CLK_AHB_CSI1, "ahb-csi1", "ahb",
573 	    AHB_GATING_REG1, 9),
574 	SUNXI_CCU_GATE(A10_CLK_AHB_HDMI1, "ahb-hdmi1", "ahb",
575 	    AHB_GATING_REG1, 10),
576 	SUNXI_CCU_GATE(A10_CLK_AHB_HDMI0, "ahb-hdmi0", "ahb",
577 	    AHB_GATING_REG1, 11),
578 	SUNXI_CCU_GATE(A10_CLK_AHB_DE_BE0, "ahb-de_be0", "ahb",
579 	    AHB_GATING_REG1, 12),
580 	SUNXI_CCU_GATE(A10_CLK_AHB_DE_BE1, "ahb-de_be1", "ahb",
581 	    AHB_GATING_REG1, 13),
582 	SUNXI_CCU_GATE(A10_CLK_AHB_DE_FE0, "ahb-de_fe0", "ahb",
583 	    AHB_GATING_REG1, 14),
584 	SUNXI_CCU_GATE(A10_CLK_AHB_DE_FE1, "ahb-de_fe1", "ahb",
585 	    AHB_GATING_REG1, 15),
586 	SUNXI_CCU_GATE(A10_CLK_AHB_GMAC, "ahb-gmac", "ahb",
587 	    AHB_GATING_REG1, 17),
588 	SUNXI_CCU_GATE(A10_CLK_AHB_MP, "ahb-mp", "ahb",
589 	    AHB_GATING_REG1, 18),
590 	SUNXI_CCU_GATE(A10_CLK_AHB_GPU, "ahb-gpu", "ahb",
591 	    AHB_GATING_REG1, 20),
592 
593 	/* APB0_GATING_REG */
594 	SUNXI_CCU_GATE(A10_CLK_APB0_CODEC, "apb0-codec", "apb0",
595 	    APB0_GATING_REG, 0),
596 	SUNXI_CCU_GATE(A10_CLK_APB0_SPDIF, "apb0-spdif", "apb0",
597 	    APB0_GATING_REG, 1),
598 	SUNXI_CCU_GATE(A10_CLK_APB0_AC97, "apb0-ac97", "apb0",
599 	    APB0_GATING_REG, 2),
600 	SUNXI_CCU_GATE(A10_CLK_APB0_I2S0, "apb0-i2s0", "apb0",
601 	    APB0_GATING_REG, 3),
602 	SUNXI_CCU_GATE(A10_CLK_APB0_I2S1, "apb0-i2s1", "apb0",
603 	    APB0_GATING_REG, 4),
604 	SUNXI_CCU_GATE(A10_CLK_APB0_PIO, "apb0-pio", "apb0",
605 	    APB0_GATING_REG, 5),
606 	SUNXI_CCU_GATE(A10_CLK_APB0_IR0, "apb0-ir0", "apb0",
607 	    APB0_GATING_REG, 6),
608 	SUNXI_CCU_GATE(A10_CLK_APB0_IR1, "apb0-ir1", "apb0",
609 	    APB0_GATING_REG, 7),
610 	SUNXI_CCU_GATE(A10_CLK_APB0_I2S2, "apb0-i2s2", "apb0",
611 	    APB0_GATING_REG, 8),
612 	SUNXI_CCU_GATE(A10_CLK_APB0_KEYPAD, "apb0-keypad", "apb0",
613 	    APB0_GATING_REG, 10),
614 
615 	/* APB1_GATING_REG */
616 	SUNXI_CCU_GATE(A10_CLK_APB1_I2C0, "apb1-i2c0", "apb1",
617 	    APB1_GATING_REG, 0),
618 	SUNXI_CCU_GATE(A10_CLK_APB1_I2C1, "apb1-i2c1", "apb1",
619 	    APB1_GATING_REG, 1),
620 	SUNXI_CCU_GATE(A10_CLK_APB1_I2C2, "apb1-i2c2", "apb1",
621 	    APB1_GATING_REG, 2),
622 	SUNXI_CCU_GATE(A10_CLK_APB1_I2C3, "apb1-i2c3", "apb1",
623 	    APB1_GATING_REG, 3),
624 	SUNXI_CCU_GATE(A10_CLK_APB1_CAN, "apb1-can", "apb1",
625 	    APB1_GATING_REG, 4),
626 	SUNXI_CCU_GATE(A10_CLK_APB1_SCR, "apb1-scr", "apb1",
627 	    APB1_GATING_REG, 5),
628 	SUNXI_CCU_GATE(A10_CLK_APB1_PS20, "apb1-ps20", "apb1",
629 	    APB1_GATING_REG, 6),
630 	SUNXI_CCU_GATE(A10_CLK_APB1_PS21, "apb1-ps21", "apb1",
631 	    APB1_GATING_REG, 7),
632 	SUNXI_CCU_GATE(A10_CLK_APB1_I2C4, "apb1-i2c4", "apb1",
633 	    APB1_GATING_REG, 15),
634 	SUNXI_CCU_GATE(A10_CLK_APB1_UART0, "apb1-uart0", "apb1",
635 	    APB1_GATING_REG, 16),
636 	SUNXI_CCU_GATE(A10_CLK_APB1_UART1, "apb1-uart1", "apb1",
637 	    APB1_GATING_REG, 17),
638 	SUNXI_CCU_GATE(A10_CLK_APB1_UART2, "apb1-uart2", "apb1",
639 	    APB1_GATING_REG, 18),
640 	SUNXI_CCU_GATE(A10_CLK_APB1_UART3, "apb1-uart3", "apb1",
641 	    APB1_GATING_REG, 19),
642 	SUNXI_CCU_GATE(A10_CLK_APB1_UART4, "apb1-uart4", "apb1",
643 	    APB1_GATING_REG, 20),
644 	SUNXI_CCU_GATE(A10_CLK_APB1_UART5, "apb1-uart5", "apb1",
645 	    APB1_GATING_REG, 21),
646 	SUNXI_CCU_GATE(A10_CLK_APB1_UART6, "apb1-uart6", "apb1",
647 	    APB1_GATING_REG, 22),
648 	SUNXI_CCU_GATE(A10_CLK_APB1_UART7, "apb1-uart7", "apb1",
649 	    APB1_GATING_REG, 23),
650 
651 	/* DRAM GATING */
652 	SUNXI_CCU_GATE(A10_CLK_DRAM_DE_BE0, "dram-de-be0", "pll_ddr_other",
653 	    DRAM_GATING_REG, 26),
654 	SUNXI_CCU_GATE(A10_CLK_DRAM_DE_BE1, "dram-de-be1", "pll_ddr_other",
655 	    DRAM_GATING_REG, 27),
656 	SUNXI_CCU_GATE(A10_CLK_DRAM_DE_FE0, "dram-de-fe0", "pll_ddr_other",
657 	    DRAM_GATING_REG, 25),
658 	SUNXI_CCU_GATE(A10_CLK_DRAM_DE_FE1, "dram-de-fe1", "pll_ddr_other",
659 	    DRAM_GATING_REG, 24),
660 
661 	/* AUDIO_CODEC_SCLK_CFG_REG */
662 	SUNXI_CCU_GATE(A10_CLK_CODEC, "codec", "pll_audio",
663 	    AUDIO_CODEC_SCLK_CFG_REG, 31),
664 
665 	/* USBPHY_CFG_REG */
666 	SUNXI_CCU_GATE(A10_CLK_USB_OHCI0, "usb-ohci0", "osc24m",
667 	    USBPHY_CFG_REG, 6),
668 	SUNXI_CCU_GATE(A10_CLK_USB_OHCI1, "usb-ohci1", "osc24m",
669 	    USBPHY_CFG_REG, 7),
670 	SUNXI_CCU_GATE(A10_CLK_USB_PHY, "usb-phy", "osc24m",
671 	    USBPHY_CFG_REG, 8),
672 };
673 
674 /*
675  * some special cases
676  * hardcode lcd0 (tcon0) to pll3 and lcd1 (tcon1) to pll7.
677  * compute pll rate based on desired pixel clock
678  */
679 
680 static int
sun4i_a10_ccu_lcd0ch0_set_rate(struct sunxi_ccu_softc * sc,struct sunxi_ccu_clk * clk,u_int rate)681 sun4i_a10_ccu_lcd0ch0_set_rate(struct sunxi_ccu_softc *sc,
682     struct sunxi_ccu_clk * clk, u_int rate)
683 {
684 	int error;
685 	error = sunxi_ccu_lcdxch0_set_rate(sc, clk,
686 	    &sun4i_a10_ccu_clks[A10_CLK_PLL_VIDEO0],
687 	    &sun4i_a10_ccu_clks[A10_CLK_PLL_VIDEO0_2X],
688 	    rate);
689 	return error;
690 }
691 
692 static int
sun4i_a10_ccu_lcd1ch0_set_rate(struct sunxi_ccu_softc * sc,struct sunxi_ccu_clk * clk,u_int rate)693 sun4i_a10_ccu_lcd1ch0_set_rate(struct sunxi_ccu_softc *sc,
694     struct sunxi_ccu_clk * clk, u_int rate)
695 {
696 	return sunxi_ccu_lcdxch0_set_rate(sc, clk,
697 	    &sun4i_a10_ccu_clks[A10_CLK_PLL_VIDEO1],
698 	    &sun4i_a10_ccu_clks[A10_CLK_PLL_VIDEO1_2X],
699 	    rate);
700 }
701 
702 static u_int
sun4i_a10_ccu_lcd0ch0_round_rate(struct sunxi_ccu_softc * sc,struct sunxi_ccu_clk * clk,u_int rate)703 sun4i_a10_ccu_lcd0ch0_round_rate(struct sunxi_ccu_softc *sc,
704     struct sunxi_ccu_clk * clk, u_int rate)
705 {
706 	return sunxi_ccu_lcdxch0_round_rate(sc, clk,
707 	    &sun4i_a10_ccu_clks[A10_CLK_PLL_VIDEO0],
708 	    &sun4i_a10_ccu_clks[A10_CLK_PLL_VIDEO0_2X],
709 	    rate);
710 }
711 
712 static u_int
sun4i_a10_ccu_lcd1ch0_round_rate(struct sunxi_ccu_softc * sc,struct sunxi_ccu_clk * clk,u_int rate)713 sun4i_a10_ccu_lcd1ch0_round_rate(struct sunxi_ccu_softc *sc,
714     struct sunxi_ccu_clk * clk, u_int rate)
715 {
716 	return sunxi_ccu_lcdxch0_round_rate(sc, clk,
717 	    &sun4i_a10_ccu_clks[A10_CLK_PLL_VIDEO1],
718 	    &sun4i_a10_ccu_clks[A10_CLK_PLL_VIDEO1_2X],
719 	    rate);
720 }
721 
722 static int
sun4i_a10_ccu_lcd0ch1_set_rate(struct sunxi_ccu_softc * sc,struct sunxi_ccu_clk * clk,u_int rate)723 sun4i_a10_ccu_lcd0ch1_set_rate(struct sunxi_ccu_softc *sc,
724     struct sunxi_ccu_clk * clk, u_int rate)
725 {
726 	return sunxi_ccu_lcdxch1_set_rate(sc, clk,
727 	    &sun4i_a10_ccu_clks[A10_CLK_PLL_VIDEO0],
728 	    &sun4i_a10_ccu_clks[A10_CLK_PLL_VIDEO0_2X],
729 	    rate);
730 }
731 
732 static int
sun4i_a10_ccu_lcd1ch1_set_rate(struct sunxi_ccu_softc * sc,struct sunxi_ccu_clk * clk,u_int rate)733 sun4i_a10_ccu_lcd1ch1_set_rate(struct sunxi_ccu_softc *sc,
734     struct sunxi_ccu_clk * clk, u_int rate)
735 {
736 	return sunxi_ccu_lcdxch1_set_rate(sc, clk,
737 	    &sun4i_a10_ccu_clks[A10_CLK_PLL_VIDEO1],
738 	    &sun4i_a10_ccu_clks[A10_CLK_PLL_VIDEO1_2X],
739 	    rate);
740 }
741 
742 #if 0
743 static int
744 sun4i_a10_ccu_lcdxch0_set_rate(struct sunxi_ccu_softc *sc,
745     struct sunxi_ccu_clk * clk, u_int rate, int unit)
746 {
747 	int parent_index;
748 	struct clk *clkp;
749 	int error;
750 
751 	parent_index = (unit == 0) ? A10_CLK_PLL_VIDEO0 : A10_CLK_PLL_VIDEO1;
752 	clkp = &sun4i_a10_ccu_clks[parent_index].base;
753 	error = clk_set_rate(clkp, rate);
754 	if (error) {
755 		error = clk_set_rate(clkp, rate / 2);
756 		if (error != 0)
757 			return error;
758 		parent_index =
759 		    (unit == 0) ? A10_CLK_PLL_VIDEO0_2X : A10_CLK_PLL_VIDEO1_2X;
760 		clkp = &sun4i_a10_ccu_clks[parent_index].base;
761 	}
762 	error = clk_set_parent(&clk->base, clkp);
763 	KASSERT(error == 0);
764 	return error;
765 }
766 
767 static u_int
768 sun4i_a10_ccu_lcdxch0_round_rate(struct sunxi_ccu_softc *sc,
769     struct sunxi_ccu_clk * clk, u_int try_rate, int unit)
770 {
771 	int parent_index;
772 	struct clk *clkp;
773 	int diff, diff_x2;
774 	int rate, rate_x2;
775 
776 	parent_index = (unit == 0) ? A10_CLK_PLL_VIDEO0 : A10_CLK_PLL_VIDEO1;
777 	clkp = &sun4i_a10_ccu_clks[parent_index].base;
778 	rate = clk_round_rate(clkp, try_rate);
779 	diff = abs(try_rate - rate);
780 
781 	rate_x2 = (clk_round_rate(clkp, try_rate / 2) * 2);
782 	diff_x2 = abs(try_rate - rate_x2);
783 
784 	if (diff_x2 < diff)
785 		return rate_x2;
786 	return rate;
787 }
788 
789 static void
790 sun4i_a10_tcon_calc_pll(int f_ref, int f_out, int *pm, int *pn, int *pd)
791 {
792 	int best = INT_MAX;
793 	for (int d = 1; d <= 2 && best != 0; d++) {
794 		for (int m = 1; m <= 16 && best != 0; m++) {
795 			for (int n = 9; n <= 127 && best != 0; n++) {
796 				int f_cur = (n * f_ref * d) / m;
797 				int diff = abs(f_out - f_cur);
798 				if (diff < best) {
799 					best = diff;
800 					*pm = m;
801 					*pn = n;
802 					*pd = d;
803 					if (diff == 0)
804 						return;
805 				}
806 			}
807 		}
808 	}
809 }
810 
811 static int
812 sun4i_a10_ccu_lcdxch1_set_rate(struct sunxi_ccu_softc *sc,
813     struct sunxi_ccu_clk *clk, u_int rate, int unit)
814 {
815 	int parent_index;
816 	struct clk *clkp, *pllclk;
817 	int error;
818         int n = 0, m = 0, d = 0;
819 
820 	parent_index = (unit == 0) ? A10_CLK_PLL_VIDEO0 : A10_CLK_PLL_VIDEO1;
821 	clkp = &sun4i_a10_ccu_clks[parent_index].base;
822 	pllclk = clkp;
823 
824         sun4i_a10_tcon_calc_pll(3000000, rate, &m, &n, &d);
825 
826         if (n == 0 || m == 0 || d == 0)
827 		return ERANGE;
828 
829         if (d == 2) {
830 		parent_index =
831 		    (unit == 0) ? A10_CLK_PLL_VIDEO0_2X : A10_CLK_PLL_VIDEO1_2X;
832 		clkp = &sun4i_a10_ccu_clks[parent_index].base;
833         }
834 
835 	error = clk_set_rate(pllclk, 3000000 * n);
836 	KASSERT(error == 0);
837 	error = clk_set_parent(&clk->base, clkp);
838 	KASSERT(error == 0);
839 	error = sunxi_ccu_div_set_rate(sc, clk, rate);
840 	KASSERT(error == 0);
841 	return error;
842 }
843 #endif
844 
845 static int
sun4i_a10_ccu_match(device_t parent,cfdata_t cf,void * aux)846 sun4i_a10_ccu_match(device_t parent, cfdata_t cf, void *aux)
847 {
848 	struct fdt_attach_args * const faa = aux;
849 
850 	return of_compatible_match(faa->faa_phandle, compat_data);
851 }
852 
853 static struct sunxi_ccu_softc *sc0;
854 static void
sun4i_a10_ccu_attach(device_t parent,device_t self,void * aux)855 sun4i_a10_ccu_attach(device_t parent, device_t self, void *aux)
856 {
857 	struct sunxi_ccu_softc * const sc = device_private(self);
858 	struct fdt_attach_args * const faa = aux;
859 	enum sun4i_a10_ccu_type type;
860 	struct clk *clk, *clkp;
861 	int error;
862 
863 	sc->sc_dev = self;
864 	sc->sc_phandle = faa->faa_phandle;
865 	sc->sc_bst = faa->faa_bst;
866 
867 	sc->sc_resets = sun4i_a10_ccu_resets;
868 	sc->sc_nresets = __arraycount(sun4i_a10_ccu_resets);
869 
870 	sc->sc_clks = sun4i_a10_ccu_clks;
871 	sc->sc_nclks = __arraycount(sun4i_a10_ccu_clks);
872 
873 	if (sunxi_ccu_attach(sc) != 0)
874 		return;
875 
876 	aprint_naive("\n");
877 
878 	type = of_compatible_lookup(faa->faa_phandle, compat_data)->value;
879 
880 	switch (type) {
881 	case CCU_A10:
882 		aprint_normal(": A10 CCU\n");
883 		break;
884 	case CCU_A20:
885 		aprint_normal(": A20 CCU\n");
886 		break;
887 	}
888 	/* hardcode debe clocks parent to PLL5 */
889 	clkp = &sun4i_a10_ccu_clks[A10_CLK_PLL_DDR_BASE].base;
890 	clk =  &sun4i_a10_ccu_clks[A10_CLK_DE_BE0].base;
891 	error = clk_set_parent(clk, clkp);
892 	KASSERT(error == 0);
893 	clk =  &sun4i_a10_ccu_clks[A10_CLK_DE_BE1].base;
894 	error = clk_set_parent(clk, clkp);
895 	KASSERT(error == 0);
896 
897 	(void)error;
898 	sunxi_ccu_print(sc);
899 	sc0 = sc;
900 }
901 
902 void sun4i_ccu_print(void);
903 void
sun4i_ccu_print(void)904 sun4i_ccu_print(void)
905 {
906 	sunxi_ccu_print(sc0);
907 }
908