1*6e54367aSthorpej /* $NetBSD: sun4i_a10_ccu.c,v 1.16 2021/01/27 03:10:20 thorpej Exp $ */
26dec99e3Sjmcneill
36dec99e3Sjmcneill /*-
46dec99e3Sjmcneill * Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
56dec99e3Sjmcneill * All rights reserved.
66dec99e3Sjmcneill *
76dec99e3Sjmcneill * Redistribution and use in source and binary forms, with or without
86dec99e3Sjmcneill * modification, are permitted provided that the following conditions
96dec99e3Sjmcneill * are met:
106dec99e3Sjmcneill * 1. Redistributions of source code must retain the above copyright
116dec99e3Sjmcneill * notice, this list of conditions and the following disclaimer.
126dec99e3Sjmcneill * 2. Redistributions in binary form must reproduce the above copyright
136dec99e3Sjmcneill * notice, this list of conditions and the following disclaimer in the
146dec99e3Sjmcneill * documentation and/or other materials provided with the distribution.
156dec99e3Sjmcneill *
166dec99e3Sjmcneill * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
176dec99e3Sjmcneill * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
186dec99e3Sjmcneill * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
196dec99e3Sjmcneill * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
206dec99e3Sjmcneill * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
216dec99e3Sjmcneill * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
226dec99e3Sjmcneill * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
236dec99e3Sjmcneill * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
246dec99e3Sjmcneill * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
256dec99e3Sjmcneill * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
266dec99e3Sjmcneill * SUCH DAMAGE.
276dec99e3Sjmcneill */
286dec99e3Sjmcneill
296dec99e3Sjmcneill #include <sys/cdefs.h>
306dec99e3Sjmcneill
31*6e54367aSthorpej __KERNEL_RCSID(1, "$NetBSD: sun4i_a10_ccu.c,v 1.16 2021/01/27 03:10:20 thorpej Exp $");
326dec99e3Sjmcneill
336dec99e3Sjmcneill #include <sys/param.h>
346dec99e3Sjmcneill #include <sys/bus.h>
356dec99e3Sjmcneill #include <sys/device.h>
366dec99e3Sjmcneill #include <sys/systm.h>
376dec99e3Sjmcneill
386dec99e3Sjmcneill #include <dev/fdt/fdtvar.h>
396dec99e3Sjmcneill
406dec99e3Sjmcneill #include <arm/sunxi/sunxi_ccu.h>
416dec99e3Sjmcneill #include <arm/sunxi/sun4i_a10_ccu.h>
426dec99e3Sjmcneill #include <arm/sunxi/sun7i_a20_ccu.h>
436dec99e3Sjmcneill
446dec99e3Sjmcneill #define PLL1_CFG_REG 0x000
456dec99e3Sjmcneill #define PLL2_CFG_REG 0x008
46a1f84860Sbouyer #define PLL3_CFG_REG 0x010
47a1f84860Sbouyer #define PLL5_CFG_REG 0x020
486dec99e3Sjmcneill #define PLL6_CFG_REG 0x028
49a1f84860Sbouyer #define PLL7_CFG_REG 0x030
506dec99e3Sjmcneill #define OSC24M_CFG_REG 0x050
516dec99e3Sjmcneill #define CPU_AHB_APB0_CFG_REG 0x054
526dec99e3Sjmcneill #define APB1_CLK_DIV_REG 0x058
536dec99e3Sjmcneill #define AHB_GATING_REG0 0x060
546dec99e3Sjmcneill #define AHB_GATING_REG1 0x064
556dec99e3Sjmcneill #define APB0_GATING_REG 0x068
566dec99e3Sjmcneill #define APB1_GATING_REG 0x06c
57901d1d46Sjmcneill #define NAND_SCLK_CFG_REG 0x080
586dec99e3Sjmcneill #define SD0_SCLK_CFG_REG 0x088
596dec99e3Sjmcneill #define SD1_SCLK_CFG_REG 0x08c
606dec99e3Sjmcneill #define SD2_SCLK_CFG_REG 0x090
616dec99e3Sjmcneill #define SD3_SCLK_CFG_REG 0x094
629da73d56Stnn #define SPI0_CLK_CFG_REG 0x0a0
639da73d56Stnn #define SPI1_CLK_CFG_REG 0x0a4
649da73d56Stnn #define SPI2_CLK_CFG_REG 0x0a8
65ccbe7c43Sjmcneill #define SATA_CFG_REG 0x0c8
666dec99e3Sjmcneill #define USBPHY_CFG_REG 0x0cc
679da73d56Stnn #define SPI3_CLK_CFG_REG 0x0d4
68a1f84860Sbouyer #define DRAM_GATING_REG 0x100
69a1f84860Sbouyer #define BE0_CFG_REG 0x104
70a1f84860Sbouyer #define BE1_CFG_REG 0x108
71a1f84860Sbouyer #define FE0_CFG_REG 0x10c
72a1f84860Sbouyer #define FE1_CFG_REG 0x110
73a1f84860Sbouyer #define MP_CFG_REG 0x114
74a1f84860Sbouyer #define LCD0CH0_CFG_REG 0x118
75a1f84860Sbouyer #define LCD1CH0_CFG_REG 0x11c
76a1f84860Sbouyer #define LCD0CH1_CFG_REG 0x12c
77a1f84860Sbouyer #define LCD1CH1_CFG_REG 0x130
786dec99e3Sjmcneill #define CSI_CFG_REG 0x134
796dec99e3Sjmcneill #define VE_CFG_REG 0x13c
806dec99e3Sjmcneill #define AUDIO_CODEC_SCLK_CFG_REG 0x140
812ddb30cbSbouyer #define LVDS_CFG_REG 0x14c
82a1f84860Sbouyer #define HDMI_CLOCK_CFG_REG 0x150
836dec99e3Sjmcneill #define MALI_CLOCK_CFG_REG 0x154
846dec99e3Sjmcneill #define IEP_SCLK_CFG_REG 0x160
856a3493dbSjmcneill #define CLK_OUTA_REG 0x1f0
866a3493dbSjmcneill #define CLK_OUTB_REG 0x1f4
876dec99e3Sjmcneill
886dec99e3Sjmcneill static int sun4i_a10_ccu_match(device_t, cfdata_t, void *);
896dec99e3Sjmcneill static void sun4i_a10_ccu_attach(device_t, device_t, void *);
906dec99e3Sjmcneill
916dec99e3Sjmcneill enum sun4i_a10_ccu_type {
926dec99e3Sjmcneill CCU_A10 = 1,
936dec99e3Sjmcneill CCU_A20,
946dec99e3Sjmcneill };
956dec99e3Sjmcneill
96646c0f59Sthorpej static const struct device_compatible_entry compat_data[] = {
97646c0f59Sthorpej { .compat = "allwinner,sun4i-a10-ccu", .value = CCU_A10 },
98646c0f59Sthorpej { .compat = "allwinner,sun7i-a20-ccu", .value = CCU_A20 },
99ec189949Sthorpej DEVICE_COMPAT_EOL
1006dec99e3Sjmcneill };
1016dec99e3Sjmcneill
1026dec99e3Sjmcneill CFATTACH_DECL_NEW(sunxi_a10_ccu, sizeof(struct sunxi_ccu_softc),
1036dec99e3Sjmcneill sun4i_a10_ccu_match, sun4i_a10_ccu_attach, NULL, NULL);
1046dec99e3Sjmcneill
1056dec99e3Sjmcneill static struct sunxi_ccu_reset sun4i_a10_ccu_resets[] = {
1066dec99e3Sjmcneill SUNXI_CCU_RESET(A10_RST_USB_PHY0, USBPHY_CFG_REG, 0),
1076dec99e3Sjmcneill SUNXI_CCU_RESET(A10_RST_USB_PHY1, USBPHY_CFG_REG, 1),
1086dec99e3Sjmcneill SUNXI_CCU_RESET(A10_RST_USB_PHY2, USBPHY_CFG_REG, 2),
109a1f84860Sbouyer SUNXI_CCU_RESET(A10_RST_DE_BE0, BE0_CFG_REG, 30),
110a1f84860Sbouyer SUNXI_CCU_RESET(A10_RST_DE_BE1, BE1_CFG_REG, 30),
111a1f84860Sbouyer SUNXI_CCU_RESET(A10_RST_DE_FE0, FE0_CFG_REG, 30),
112a1f84860Sbouyer SUNXI_CCU_RESET(A10_RST_DE_FE1, FE1_CFG_REG, 30),
113a1f84860Sbouyer SUNXI_CCU_RESET(A10_RST_DE_MP, MP_CFG_REG, 30),
114a1f84860Sbouyer SUNXI_CCU_RESET(A10_RST_TCON0, LCD0CH0_CFG_REG, 30),
115a1f84860Sbouyer SUNXI_CCU_RESET(A10_RST_TCON1, LCD1CH0_CFG_REG, 30),
1162ddb30cbSbouyer SUNXI_CCU_RESET(A10_RST_LVDS, LVDS_CFG_REG, 0),
1176dec99e3Sjmcneill };
1186dec99e3Sjmcneill
1196dec99e3Sjmcneill static const char *cpu_parents[] = { "losc", "osc24m", "pll_core", "pll_periph" };
1206dec99e3Sjmcneill static const char *axi_parents[] = { "cpu" };
1216dec99e3Sjmcneill static const char *ahb_parents[] = { "axi", "pll_periph", "pll_periph_base" };
1226dec99e3Sjmcneill static const char *apb0_parents[] = { "ahb" };
1236dec99e3Sjmcneill static const char *apb1_parents[] = { "osc24m", "pll_periph", "losc" };
124a1f84860Sbouyer static const char *mod_parents[] = { "osc24m", "pll_periph", "pll_ddr_other" };
125ccbe7c43Sjmcneill static const char *sata_parents[] = { "pll6_periph_sata", "external" };
126a1f84860Sbouyer static const char *de_parents[] = { "pll_video0", "pll_video1", "pll_ddr_other" };
127db6d41fbSbouyer static const char *lcd_parents[] = { "pll_video0", "pll_video1", "pll_video0x2", "pll_video1x2" };
1286a3493dbSjmcneill static const char *out_parents[] = { "losc" /* really OSC24MHz/750 */, "losc", "osc24m" };
1296dec99e3Sjmcneill
130df83149aSjmcneill static const struct sunxi_ccu_nkmp_tbl sun4i_a10_pll1_table[] = {
131df83149aSjmcneill { 1008000000, 21, 1, 0, 0 },
132df83149aSjmcneill { 960000000, 20, 1, 0, 0 },
133df83149aSjmcneill { 912000000, 19, 1, 0, 0 },
134df83149aSjmcneill { 864000000, 18, 1, 0, 0 },
135df83149aSjmcneill { 720000000, 30, 0, 0, 0 },
136d00a64efSjmcneill { 624000000, 26, 0, 0, 0 },
137df83149aSjmcneill { 528000000, 22, 0, 0, 0 },
138df83149aSjmcneill { 312000000, 13, 0, 0, 0 },
139df83149aSjmcneill { 144000000, 12, 0, 0, 1 },
140df83149aSjmcneill { 0 }
141df83149aSjmcneill };
142df83149aSjmcneill
1436dec99e3Sjmcneill static const struct sunxi_ccu_nkmp_tbl sun4i_a10_ac_dig_table[] = {
1442ddb30cbSbouyer { 24576000, 86, 0, 21, 4 },
1456dec99e3Sjmcneill { 0 }
1466dec99e3Sjmcneill };
1476dec99e3Sjmcneill
148db6d41fbSbouyer /*
149db6d41fbSbouyer * some special cases
150db6d41fbSbouyer * hardcode lcd0 (tcon0) to pll3 and lcd1 (tcon1) to pll7.
151db6d41fbSbouyer * compute pll rate based on desired pixel clock
152db6d41fbSbouyer */
153db6d41fbSbouyer
154db6d41fbSbouyer static int sun4i_a10_ccu_lcd0ch0_set_rate(struct sunxi_ccu_softc *,
155db6d41fbSbouyer struct sunxi_ccu_clk *, u_int);
156db6d41fbSbouyer static int sun4i_a10_ccu_lcd1ch0_set_rate(struct sunxi_ccu_softc *,
157db6d41fbSbouyer struct sunxi_ccu_clk *, u_int);
158db6d41fbSbouyer static u_int sun4i_a10_ccu_lcd0ch0_round_rate(struct sunxi_ccu_softc *,
159db6d41fbSbouyer struct sunxi_ccu_clk *, u_int);
160db6d41fbSbouyer static u_int sun4i_a10_ccu_lcd1ch0_round_rate(struct sunxi_ccu_softc *,
161db6d41fbSbouyer struct sunxi_ccu_clk *, u_int);
162db6d41fbSbouyer static int sun4i_a10_ccu_lcd0ch1_set_rate(struct sunxi_ccu_softc *,
163db6d41fbSbouyer struct sunxi_ccu_clk *, u_int);
164db6d41fbSbouyer static int sun4i_a10_ccu_lcd1ch1_set_rate(struct sunxi_ccu_softc *,
165db6d41fbSbouyer struct sunxi_ccu_clk *, u_int);
166db6d41fbSbouyer
1676dec99e3Sjmcneill static struct sunxi_ccu_clk sun4i_a10_ccu_clks[] = {
1686dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_HOSC, "osc24m", "hosc",
1696dec99e3Sjmcneill OSC24M_CFG_REG, 0),
1706dec99e3Sjmcneill
171df83149aSjmcneill SUNXI_CCU_NKMP_TABLE(A10_CLK_PLL_CORE, "pll_core", "osc24m",
1726dec99e3Sjmcneill PLL1_CFG_REG, /* reg */
1736dec99e3Sjmcneill __BITS(12,8), /* n */
1746dec99e3Sjmcneill __BITS(5,4), /* k */
1756dec99e3Sjmcneill __BITS(1,0), /* m */
1766dec99e3Sjmcneill __BITS(17,16), /* p */
1776dec99e3Sjmcneill __BIT(31), /* enable */
178df83149aSjmcneill 0, /* lock */
179df83149aSjmcneill sun4i_a10_pll1_table, /* table */
1806dec99e3Sjmcneill SUNXI_CCU_NKMP_FACTOR_P_POW2 | SUNXI_CCU_NKMP_FACTOR_N_EXACT |
181df83149aSjmcneill SUNXI_CCU_NKMP_FACTOR_N_ZERO_IS_ONE | SUNXI_CCU_NKMP_SCALE_CLOCK),
1826dec99e3Sjmcneill
1836dec99e3Sjmcneill SUNXI_CCU_NKMP_TABLE(A10_CLK_PLL_AUDIO_BASE, "pll_audio", "osc24m",
1846dec99e3Sjmcneill PLL2_CFG_REG, /* reg */
1856dec99e3Sjmcneill __BITS(14,8), /* n */
1866dec99e3Sjmcneill 0, /* k */
1876dec99e3Sjmcneill __BITS(4,0), /* m */
1886dec99e3Sjmcneill __BITS(29,26), /* p */
1896dec99e3Sjmcneill __BIT(31), /* enable */
1906dec99e3Sjmcneill 0, /* lock */
1916dec99e3Sjmcneill sun4i_a10_ac_dig_table, /* table */
1926dec99e3Sjmcneill 0),
1936dec99e3Sjmcneill
1946dec99e3Sjmcneill SUNXI_CCU_NKMP(A10_CLK_PLL_PERIPH_BASE, "pll_periph_base", "osc24m",
1956dec99e3Sjmcneill PLL6_CFG_REG, /* reg */
1966dec99e3Sjmcneill __BITS(12,8), /* n */
1976dec99e3Sjmcneill __BITS(5,4), /* k */
1986dec99e3Sjmcneill 0, /* m */
1996dec99e3Sjmcneill 0, /* p */
2006dec99e3Sjmcneill __BIT(31), /* enable */
2016dec99e3Sjmcneill SUNXI_CCU_NKMP_FACTOR_N_EXACT),
2026dec99e3Sjmcneill
2036dec99e3Sjmcneill SUNXI_CCU_FIXED_FACTOR(A10_CLK_PLL_PERIPH, "pll_periph", "pll_periph_base",
2046dec99e3Sjmcneill 2, 1),
2056dec99e3Sjmcneill
2066dec99e3Sjmcneill SUNXI_CCU_NKMP(A10_CLK_PLL_PERIPH_SATA, "pll_periph_sata", "pll_periph_base",
2076dec99e3Sjmcneill PLL6_CFG_REG, /* reg */
2086dec99e3Sjmcneill 0, /* n */
2096dec99e3Sjmcneill 0, /* k */
2106dec99e3Sjmcneill __BITS(1,0), /* m */
2116dec99e3Sjmcneill 0, /* p */
2126dec99e3Sjmcneill __BIT(14), /* enable */
2136dec99e3Sjmcneill 0),
2146dec99e3Sjmcneill
215ccbe7c43Sjmcneill SUNXI_CCU_DIV_GATE(A10_CLK_SATA, "sata", sata_parents,
216ccbe7c43Sjmcneill SATA_CFG_REG, /* reg */
217ccbe7c43Sjmcneill 0, /* div */
218ccbe7c43Sjmcneill __BIT(24), /* sel */
219ccbe7c43Sjmcneill __BIT(31), /* enable */
220ccbe7c43Sjmcneill 0),
221ccbe7c43Sjmcneill
222a1f84860Sbouyer SUNXI_CCU_NKMP(A10_CLK_PLL_DDR_BASE, "pll_ddr_other", "osc24m",
223a1f84860Sbouyer PLL5_CFG_REG, /* reg */
224a1f84860Sbouyer __BITS(12, 8), /* n */
225a1f84860Sbouyer __BITS(5,4), /* k */
226a1f84860Sbouyer 0, /* m */
227a1f84860Sbouyer __BITS(17,16), /* p */
228a1f84860Sbouyer __BIT(31), /* enable */
229a1f84860Sbouyer SUNXI_CCU_NKMP_FACTOR_N_EXACT | SUNXI_CCU_NKMP_FACTOR_P_POW2),
230a1f84860Sbouyer
231a1f84860Sbouyer SUNXI_CCU_NKMP(A10_CLK_PLL_DDR, "pll_ddr", "osc24m",
232a1f84860Sbouyer PLL5_CFG_REG, /* reg */
233a1f84860Sbouyer __BITS(12, 8), /* n */
234a1f84860Sbouyer __BITS(5,4), /* k */
235a1f84860Sbouyer __BITS(1,0), /* m */
236a1f84860Sbouyer 0, /* p */
237a1f84860Sbouyer __BIT(31), /* enable */
238a1f84860Sbouyer SUNXI_CCU_NKMP_FACTOR_N_EXACT),
239a1f84860Sbouyer
2406dec99e3Sjmcneill SUNXI_CCU_DIV(A10_CLK_CPU, "cpu", cpu_parents,
2416dec99e3Sjmcneill CPU_AHB_APB0_CFG_REG, /* reg */
2426dec99e3Sjmcneill 0, /* div */
2436dec99e3Sjmcneill __BITS(17,16), /* sel */
244df83149aSjmcneill SUNXI_CCU_DIV_SET_RATE_PARENT),
2456dec99e3Sjmcneill
2466dec99e3Sjmcneill SUNXI_CCU_DIV(A10_CLK_AXI, "axi", axi_parents,
2476dec99e3Sjmcneill CPU_AHB_APB0_CFG_REG, /* reg */
2486dec99e3Sjmcneill __BITS(1,0), /* div */
2496dec99e3Sjmcneill 0, /* sel */
2506dec99e3Sjmcneill 0),
2516dec99e3Sjmcneill
2526dec99e3Sjmcneill SUNXI_CCU_DIV(A10_CLK_AHB, "ahb", ahb_parents,
2536dec99e3Sjmcneill CPU_AHB_APB0_CFG_REG, /* reg */
2546dec99e3Sjmcneill __BITS(5,4), /* div */
2556dec99e3Sjmcneill __BITS(7,6), /* sel */
2566dec99e3Sjmcneill SUNXI_CCU_DIV_POWER_OF_TWO),
2576dec99e3Sjmcneill
2586dec99e3Sjmcneill SUNXI_CCU_DIV(A10_CLK_APB0, "apb0", apb0_parents,
2596dec99e3Sjmcneill CPU_AHB_APB0_CFG_REG, /* reg */
2606dec99e3Sjmcneill __BITS(9,8), /* div */
2616dec99e3Sjmcneill 0, /* sel */
2626dec99e3Sjmcneill SUNXI_CCU_DIV_ZERO_IS_ONE | SUNXI_CCU_DIV_POWER_OF_TWO),
2636dec99e3Sjmcneill
2646dec99e3Sjmcneill SUNXI_CCU_NM(A10_CLK_APB1, "apb1", apb1_parents,
2656dec99e3Sjmcneill APB1_CLK_DIV_REG, /* reg */
2666dec99e3Sjmcneill __BITS(17,16), /* n */
2676dec99e3Sjmcneill __BITS(4,0), /* m */
2686dec99e3Sjmcneill __BITS(25,24), /* sel */
2696dec99e3Sjmcneill 0, /* enable */
2706dec99e3Sjmcneill SUNXI_CCU_NM_POWER_OF_TWO),
2716dec99e3Sjmcneill
272901d1d46Sjmcneill SUNXI_CCU_NM(A10_CLK_NAND, "nand", mod_parents,
273901d1d46Sjmcneill NAND_SCLK_CFG_REG, /* reg */
274901d1d46Sjmcneill __BITS(17,16), /* n */
275901d1d46Sjmcneill __BITS(3,0), /* m */
276901d1d46Sjmcneill __BITS(25,24), /* sel */
277901d1d46Sjmcneill __BIT(31), /* enable */
278901d1d46Sjmcneill SUNXI_CCU_NM_POWER_OF_TWO),
279901d1d46Sjmcneill
2809da73d56Stnn SUNXI_CCU_NM(A10_CLK_SPI0, "spi0", mod_parents,
2819da73d56Stnn SPI0_CLK_CFG_REG, /* reg */
2829da73d56Stnn __BITS(17,16), /* n */
2839da73d56Stnn __BITS(3,0), /* m */
2849da73d56Stnn __BITS(25,24), /* sel */
2859da73d56Stnn __BIT(31), /* enable */
2869da73d56Stnn SUNXI_CCU_NM_POWER_OF_TWO),
2879da73d56Stnn
2889da73d56Stnn SUNXI_CCU_NM(A10_CLK_SPI1, "spi1", mod_parents,
2899da73d56Stnn SPI1_CLK_CFG_REG, /* reg */
2909da73d56Stnn __BITS(17,16), /* n */
2919da73d56Stnn __BITS(3,0), /* m */
2929da73d56Stnn __BITS(25,24), /* sel */
2939da73d56Stnn __BIT(31), /* enable */
2949da73d56Stnn SUNXI_CCU_NM_POWER_OF_TWO),
2959da73d56Stnn
2969da73d56Stnn SUNXI_CCU_NM(A10_CLK_SPI2, "spi2", mod_parents,
2979da73d56Stnn SPI2_CLK_CFG_REG, /* reg */
2989da73d56Stnn __BITS(17,16), /* n */
2999da73d56Stnn __BITS(3,0), /* m */
3009da73d56Stnn __BITS(25,24), /* sel */
3019da73d56Stnn __BIT(31), /* enable */
3029da73d56Stnn SUNXI_CCU_NM_POWER_OF_TWO),
3039da73d56Stnn
3049da73d56Stnn SUNXI_CCU_NM(A10_CLK_SPI3, "spi3", mod_parents,
3059da73d56Stnn SPI3_CLK_CFG_REG, /* reg */
3069da73d56Stnn __BITS(17,16), /* n */
3079da73d56Stnn __BITS(3,0), /* m */
3089da73d56Stnn __BITS(25,24), /* sel */
3099da73d56Stnn __BIT(31), /* enable */
3109da73d56Stnn SUNXI_CCU_NM_POWER_OF_TWO),
3119da73d56Stnn
3126dec99e3Sjmcneill SUNXI_CCU_NM(A10_CLK_MMC0, "mmc0", mod_parents,
3136dec99e3Sjmcneill SD0_SCLK_CFG_REG, /* reg */
3146dec99e3Sjmcneill __BITS(17,16), /* n */
3156dec99e3Sjmcneill __BITS(3,0), /* m */
3166dec99e3Sjmcneill __BITS(25,24), /* sel */
3176dec99e3Sjmcneill __BIT(31), /* enable */
3186dec99e3Sjmcneill SUNXI_CCU_NM_POWER_OF_TWO),
319ebb3c3a1Sjmcneill SUNXI_CCU_PHASE(A10_CLK_MMC0_SAMPLE, "mmc0_sample", "mmc0",
320ebb3c3a1Sjmcneill SD0_SCLK_CFG_REG, __BITS(22,20)),
321ebb3c3a1Sjmcneill SUNXI_CCU_PHASE(A10_CLK_MMC0_OUTPUT, "mmc0_output", "mmc0",
322ebb3c3a1Sjmcneill SD0_SCLK_CFG_REG, __BITS(10,8)),
3236dec99e3Sjmcneill SUNXI_CCU_NM(A10_CLK_MMC1, "mmc1", mod_parents,
3246dec99e3Sjmcneill SD1_SCLK_CFG_REG, /* reg */
3256dec99e3Sjmcneill __BITS(17,16), /* n */
3266dec99e3Sjmcneill __BITS(3,0), /* m */
3276dec99e3Sjmcneill __BITS(25,24), /* sel */
3286dec99e3Sjmcneill __BIT(31), /* enable */
3296dec99e3Sjmcneill SUNXI_CCU_NM_POWER_OF_TWO),
330ebb3c3a1Sjmcneill SUNXI_CCU_PHASE(A10_CLK_MMC1_SAMPLE, "mmc1_sample", "mmc1",
331ebb3c3a1Sjmcneill SD1_SCLK_CFG_REG, __BITS(22,20)),
332ebb3c3a1Sjmcneill SUNXI_CCU_PHASE(A10_CLK_MMC1_OUTPUT, "mmc1_output", "mmc1",
333ebb3c3a1Sjmcneill SD1_SCLK_CFG_REG, __BITS(10,8)),
3346dec99e3Sjmcneill SUNXI_CCU_NM(A10_CLK_MMC2, "mmc2", mod_parents,
3356dec99e3Sjmcneill SD2_SCLK_CFG_REG, /* reg */
3366dec99e3Sjmcneill __BITS(17,16), /* n */
3376dec99e3Sjmcneill __BITS(3,0), /* m */
3386dec99e3Sjmcneill __BITS(25,24), /* sel */
3396dec99e3Sjmcneill __BIT(31), /* enable */
3406dec99e3Sjmcneill SUNXI_CCU_NM_POWER_OF_TWO),
341ebb3c3a1Sjmcneill SUNXI_CCU_PHASE(A10_CLK_MMC2_SAMPLE, "mmc2_sample", "mmc2",
342ebb3c3a1Sjmcneill SD2_SCLK_CFG_REG, __BITS(22,20)),
343ebb3c3a1Sjmcneill SUNXI_CCU_PHASE(A10_CLK_MMC2_OUTPUT, "mmc2_output", "mmc2",
344ebb3c3a1Sjmcneill SD2_SCLK_CFG_REG, __BITS(10,8)),
3456dec99e3Sjmcneill SUNXI_CCU_NM(A10_CLK_MMC3, "mmc3", mod_parents,
3466dec99e3Sjmcneill SD3_SCLK_CFG_REG, /* reg */
3476dec99e3Sjmcneill __BITS(17,16), /* n */
3486dec99e3Sjmcneill __BITS(3,0), /* m */
3496dec99e3Sjmcneill __BITS(25,24), /* sel */
3506dec99e3Sjmcneill __BIT(31), /* enable */
3516dec99e3Sjmcneill SUNXI_CCU_NM_POWER_OF_TWO),
352ebb3c3a1Sjmcneill SUNXI_CCU_PHASE(A10_CLK_MMC3_SAMPLE, "mmc3_sample", "mmc3",
353ebb3c3a1Sjmcneill SD3_SCLK_CFG_REG, __BITS(22,20)),
354ebb3c3a1Sjmcneill SUNXI_CCU_PHASE(A10_CLK_MMC3_OUTPUT, "mmc3_output", "mmc3",
355ebb3c3a1Sjmcneill SD3_SCLK_CFG_REG, __BITS(10,8)),
3566dec99e3Sjmcneill
357a1f84860Sbouyer SUNXI_CCU_FRACTIONAL(A10_CLK_PLL_VIDEO0, "pll_video0", "osc24m",
358a1f84860Sbouyer PLL3_CFG_REG, /* reg */
359a1f84860Sbouyer __BITS(7,0), /* m */
360a1f84860Sbouyer 9, /* m_min */
361a1f84860Sbouyer 127, /* m_max */
362db6d41fbSbouyer __BIT(15), /* div_en */
363a1f84860Sbouyer __BIT(14), /* frac_sel */
364a1f84860Sbouyer 270000000, 297000000, /* frac values */
365cf80abdeSjmcneill 0, /* prediv */
366cf80abdeSjmcneill 8, /* prediv_val */
367cf80abdeSjmcneill __BIT(31), /* enable */
368cf80abdeSjmcneill 0),
369a1f84860Sbouyer SUNXI_CCU_FRACTIONAL(A10_CLK_PLL_VIDEO1, "pll_video1", "osc24m",
370a1f84860Sbouyer PLL7_CFG_REG, /* reg */
371a1f84860Sbouyer __BITS(7,0), /* m */
372a1f84860Sbouyer 9, /* m_min */
373a1f84860Sbouyer 127, /* m_max */
374db6d41fbSbouyer __BIT(15), /* div_en */
375a1f84860Sbouyer __BIT(14), /* frac_sel */
376a1f84860Sbouyer 270000000, 297000000, /* frac values */
377cf80abdeSjmcneill 0, /* prediv */
378cf80abdeSjmcneill 8, /* prediv_val */
379cf80abdeSjmcneill __BIT(31), /* enable */
380cf80abdeSjmcneill 0),
381a1f84860Sbouyer SUNXI_CCU_FIXED_FACTOR(A10_CLK_PLL_VIDEO0_2X,
382a1f84860Sbouyer "pll_video0x2", "pll_video0",
383a1f84860Sbouyer 1, 2),
384a1f84860Sbouyer SUNXI_CCU_FIXED_FACTOR(A10_CLK_PLL_VIDEO1_2X,
385a1f84860Sbouyer "pll_video1x2", "pll_video1",
386a1f84860Sbouyer 1, 2),
387a1f84860Sbouyer
388a1f84860Sbouyer SUNXI_CCU_DIV_GATE(A10_CLK_DE_BE0, "debe0-mod", de_parents,
389a1f84860Sbouyer BE0_CFG_REG, /* reg */
390a1f84860Sbouyer __BITS(3,0), /* div */
391a1f84860Sbouyer __BITS(25,24), /* sel */
392a1f84860Sbouyer __BIT(31), /* enable */
393a1f84860Sbouyer 0 /* flags */
394a1f84860Sbouyer ),
395a1f84860Sbouyer SUNXI_CCU_DIV_GATE(A10_CLK_DE_BE1, "debe1-mod", de_parents,
396a1f84860Sbouyer BE1_CFG_REG, /* reg */
397a1f84860Sbouyer __BITS(3,0), /* div */
398a1f84860Sbouyer __BITS(25,24), /* sel */
399a1f84860Sbouyer __BIT(31), /* enable */
400a1f84860Sbouyer 0 /* flags */
401a1f84860Sbouyer ),
402a1f84860Sbouyer SUNXI_CCU_DIV_GATE(A10_CLK_DE_FE0, "defe0-mod", de_parents,
403a1f84860Sbouyer FE0_CFG_REG, /* reg */
404a1f84860Sbouyer __BITS(3,0), /* div */
405a1f84860Sbouyer __BITS(25,24), /* sel */
406a1f84860Sbouyer __BIT(31), /* enable */
407a1f84860Sbouyer 0 /* flags */
408a1f84860Sbouyer ),
409a1f84860Sbouyer SUNXI_CCU_DIV_GATE(A10_CLK_DE_FE1, "defe1-mod", de_parents,
410a1f84860Sbouyer FE1_CFG_REG, /* reg */
411a1f84860Sbouyer __BITS(3,0), /* div */
412a1f84860Sbouyer __BITS(25,24), /* sel */
413a1f84860Sbouyer __BIT(31), /* enable */
414a1f84860Sbouyer 0 /* flags */
415a1f84860Sbouyer ),
416db6d41fbSbouyer [A10_CLK_TCON0_CH0] = {
417db6d41fbSbouyer .type = SUNXI_CCU_DIV,
418db6d41fbSbouyer .base.name = "tcon0-ch0",
419db6d41fbSbouyer .u.div.reg = LCD0CH0_CFG_REG,
420db6d41fbSbouyer .u.div.parents = lcd_parents,
421db6d41fbSbouyer .u.div.nparents = __arraycount(lcd_parents),
422db6d41fbSbouyer .u.div.div = 0,
423db6d41fbSbouyer .u.div.sel = __BITS(25,24),
424db6d41fbSbouyer .u.div.enable = __BIT(31),
425db6d41fbSbouyer .u.div.flags = 0,
426db6d41fbSbouyer .enable = sunxi_ccu_div_enable,
427db6d41fbSbouyer .get_rate = sunxi_ccu_div_get_rate,
428db6d41fbSbouyer .set_rate = sun4i_a10_ccu_lcd0ch0_set_rate,
429db6d41fbSbouyer .round_rate = sun4i_a10_ccu_lcd0ch0_round_rate,
430db6d41fbSbouyer .set_parent = sunxi_ccu_div_set_parent,
431db6d41fbSbouyer .get_parent = sunxi_ccu_div_get_parent,
432db6d41fbSbouyer },
433db6d41fbSbouyer [A10_CLK_TCON1_CH0] = {
434db6d41fbSbouyer .type = SUNXI_CCU_DIV,
435db6d41fbSbouyer .base.name = "tcon1-ch0",
436db6d41fbSbouyer .u.div.reg = LCD1CH0_CFG_REG,
437db6d41fbSbouyer .u.div.parents = lcd_parents,
438db6d41fbSbouyer .u.div.nparents = __arraycount(lcd_parents),
439db6d41fbSbouyer .u.div.div = 0,
440db6d41fbSbouyer .u.div.sel = __BITS(25,24),
441db6d41fbSbouyer .u.div.enable = __BIT(31),
442db6d41fbSbouyer .u.div.flags = 0,
443db6d41fbSbouyer .enable = sunxi_ccu_div_enable,
444db6d41fbSbouyer .get_rate = sunxi_ccu_div_get_rate,
445db6d41fbSbouyer .set_rate = sun4i_a10_ccu_lcd1ch0_set_rate,
446db6d41fbSbouyer .round_rate = sun4i_a10_ccu_lcd1ch0_round_rate,
447db6d41fbSbouyer .set_parent = sunxi_ccu_div_set_parent,
448db6d41fbSbouyer .get_parent = sunxi_ccu_div_get_parent,
449db6d41fbSbouyer },
450db6d41fbSbouyer [A10_CLK_TCON0_CH1] = {
451db6d41fbSbouyer .type = SUNXI_CCU_DIV,
452db6d41fbSbouyer .base.name = "tcon0-ch1",
453db6d41fbSbouyer .u.div.reg = LCD0CH1_CFG_REG,
454db6d41fbSbouyer .u.div.parents = lcd_parents,
455db6d41fbSbouyer .u.div.nparents = __arraycount(lcd_parents),
456db6d41fbSbouyer .u.div.div = __BITS(3,0),
457db6d41fbSbouyer .u.div.sel = __BITS(25,24),
458db6d41fbSbouyer .u.div.enable = __BIT(15) | __BIT(31),
459db6d41fbSbouyer .u.div.flags = 0,
460db6d41fbSbouyer .enable = sunxi_ccu_div_enable,
461db6d41fbSbouyer .get_rate = sunxi_ccu_div_get_rate,
462db6d41fbSbouyer .set_rate = sun4i_a10_ccu_lcd0ch1_set_rate,
463db6d41fbSbouyer .set_parent = sunxi_ccu_div_set_parent,
464db6d41fbSbouyer .get_parent = sunxi_ccu_div_get_parent,
465db6d41fbSbouyer },
466db6d41fbSbouyer [A10_CLK_TCON1_CH1] = {
467db6d41fbSbouyer .type = SUNXI_CCU_DIV,
468db6d41fbSbouyer .base.name = "tcon1-ch1",
469db6d41fbSbouyer .u.div.reg = LCD1CH1_CFG_REG,
470db6d41fbSbouyer .u.div.parents = lcd_parents,
471db6d41fbSbouyer .u.div.nparents = __arraycount(lcd_parents),
472db6d41fbSbouyer .u.div.div = __BITS(3,0),
473db6d41fbSbouyer .u.div.sel = __BITS(25,24),
474db6d41fbSbouyer .u.div.enable = __BIT(15) | __BIT(31),
475db6d41fbSbouyer .u.div.flags = 0,
476db6d41fbSbouyer .enable = sunxi_ccu_div_enable,
477db6d41fbSbouyer .get_rate = sunxi_ccu_div_get_rate,
478db6d41fbSbouyer .set_rate = sun4i_a10_ccu_lcd1ch1_set_rate,
479db6d41fbSbouyer .set_parent = sunxi_ccu_div_set_parent,
480db6d41fbSbouyer .get_parent = sunxi_ccu_div_get_parent,
481db6d41fbSbouyer },
482db6d41fbSbouyer SUNXI_CCU_DIV_GATE(A10_CLK_HDMI, "hdmi-mod", lcd_parents,
483a1f84860Sbouyer HDMI_CLOCK_CFG_REG, /* reg */
484a1f84860Sbouyer __BITS(3,0), /* div */
485a1f84860Sbouyer __BITS(25,24), /* sel */
486a1f84860Sbouyer __BIT(31), /* enable */
487a1f84860Sbouyer 0 /* flags */
488a1f84860Sbouyer ),
489a1f84860Sbouyer
4906a3493dbSjmcneill /* A20 specific */
4916a3493dbSjmcneill SUNXI_CCU_NM(A20_CLK_OUT_A, "outa", out_parents,
4926a3493dbSjmcneill CLK_OUTA_REG, /* reg */
4936a3493dbSjmcneill __BITS(21,20), /* n */
4946a3493dbSjmcneill __BITS(12,8), /* m */
4956a3493dbSjmcneill __BITS(25,24), /* sel */
4966a3493dbSjmcneill __BIT(31), /* enable */
4976a3493dbSjmcneill SUNXI_CCU_NM_POWER_OF_TWO),
4986a3493dbSjmcneill
4996a3493dbSjmcneill SUNXI_CCU_NM(A20_CLK_OUT_B, "outb", out_parents,
5006a3493dbSjmcneill CLK_OUTB_REG, /* reg */
5016a3493dbSjmcneill __BITS(21,20), /* n */
5026a3493dbSjmcneill __BITS(12,8), /* m */
5036a3493dbSjmcneill __BITS(25,24), /* sel */
5046a3493dbSjmcneill __BIT(31), /* enable */
5056a3493dbSjmcneill SUNXI_CCU_NM_POWER_OF_TWO),
5066a3493dbSjmcneill
5076dec99e3Sjmcneill /* AHB_GATING_REG0 */
5086dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_OTG, "ahb-otg", "ahb",
5096dec99e3Sjmcneill AHB_GATING_REG0, 0),
5106dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_EHCI0, "ahb-ehci0", "ahb",
5116dec99e3Sjmcneill AHB_GATING_REG0, 1),
5126dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_OHCI0, "ahb-ohci0", "ahb",
5136dec99e3Sjmcneill AHB_GATING_REG0, 2),
5146dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_EHCI1, "ahb-ehci1", "ahb",
5156dec99e3Sjmcneill AHB_GATING_REG0, 3),
5166dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_OHCI1, "ahb-ohci1", "ahb",
5176dec99e3Sjmcneill AHB_GATING_REG0, 4),
5186dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_SS, "ahb-ss", "ahb",
5196dec99e3Sjmcneill AHB_GATING_REG0, 5),
5206dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_DMA, "ahb-dma", "ahb",
5216dec99e3Sjmcneill AHB_GATING_REG0, 6),
5226dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_BIST, "ahb-bist", "ahb",
5236dec99e3Sjmcneill AHB_GATING_REG0, 7),
5246dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_MMC0, "ahb-mmc0", "ahb",
5256dec99e3Sjmcneill AHB_GATING_REG0, 8),
5266dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_MMC1, "ahb-mmc1", "ahb",
5276dec99e3Sjmcneill AHB_GATING_REG0, 9),
5286dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_MMC2, "ahb-mmc2", "ahb",
5296dec99e3Sjmcneill AHB_GATING_REG0, 10),
5306dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_MMC3, "ahb-mmc3", "ahb",
5316dec99e3Sjmcneill AHB_GATING_REG0, 11),
5326dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_MS, "ahb-ms", "ahb",
5336dec99e3Sjmcneill AHB_GATING_REG0, 12),
5346dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_NAND, "ahb-nand", "ahb",
5356dec99e3Sjmcneill AHB_GATING_REG0, 13),
5366dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_SDRAM, "ahb-sdram", "ahb",
5376dec99e3Sjmcneill AHB_GATING_REG0, 14),
5386dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_ACE, "ahb-ace", "ahb",
5396dec99e3Sjmcneill AHB_GATING_REG0, 16),
5406dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_EMAC, "ahb-emac", "ahb",
5416dec99e3Sjmcneill AHB_GATING_REG0, 17),
5426dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_TS, "ahb-ts", "ahb",
5436dec99e3Sjmcneill AHB_GATING_REG0, 18),
5446dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_SPI0, "ahb-spi0", "ahb",
5456dec99e3Sjmcneill AHB_GATING_REG0, 20),
5466dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_SPI1, "ahb-spi1", "ahb",
5476dec99e3Sjmcneill AHB_GATING_REG0, 21),
5486dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_SPI2, "ahb-spi2", "ahb",
5496dec99e3Sjmcneill AHB_GATING_REG0, 22),
5506dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_SPI3, "ahb-spi3", "ahb",
5516dec99e3Sjmcneill AHB_GATING_REG0, 23),
5526dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_SATA, "ahb-sata", "ahb",
5536dec99e3Sjmcneill AHB_GATING_REG0, 25),
5546dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_HSTIMER, "ahb-hstimer", "ahb",
5556dec99e3Sjmcneill AHB_GATING_REG0, 28),
5566dec99e3Sjmcneill
5576dec99e3Sjmcneill /* AHB_GATING_REG1. Missing: TVE, HDMI */
5586dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_VE, "ahb-ve", "ahb",
5596dec99e3Sjmcneill AHB_GATING_REG1, 0),
5606dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_TVD, "ahb-tvd", "ahb",
5616dec99e3Sjmcneill AHB_GATING_REG1, 1),
5626dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_TVE0, "ahb-tve0", "ahb",
5636dec99e3Sjmcneill AHB_GATING_REG1, 2),
5646dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_TVE1, "ahb-tve1", "ahb",
5656dec99e3Sjmcneill AHB_GATING_REG1, 3),
5666dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_LCD0, "ahb-lcd0", "ahb",
5676dec99e3Sjmcneill AHB_GATING_REG1, 4),
5686dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_LCD1, "ahb-lcd1", "ahb",
5696dec99e3Sjmcneill AHB_GATING_REG1, 5),
5706dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_CSI0, "ahb-csi0", "ahb",
5716dec99e3Sjmcneill AHB_GATING_REG1, 8),
5726dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_CSI1, "ahb-csi1", "ahb",
5736dec99e3Sjmcneill AHB_GATING_REG1, 9),
5746dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_HDMI1, "ahb-hdmi1", "ahb",
5756dec99e3Sjmcneill AHB_GATING_REG1, 10),
5766dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_HDMI0, "ahb-hdmi0", "ahb",
5776dec99e3Sjmcneill AHB_GATING_REG1, 11),
5786dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_DE_BE0, "ahb-de_be0", "ahb",
5796dec99e3Sjmcneill AHB_GATING_REG1, 12),
5806dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_DE_BE1, "ahb-de_be1", "ahb",
5816dec99e3Sjmcneill AHB_GATING_REG1, 13),
5826dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_DE_FE0, "ahb-de_fe0", "ahb",
5836dec99e3Sjmcneill AHB_GATING_REG1, 14),
5846dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_DE_FE1, "ahb-de_fe1", "ahb",
5856dec99e3Sjmcneill AHB_GATING_REG1, 15),
5866dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_GMAC, "ahb-gmac", "ahb",
5876dec99e3Sjmcneill AHB_GATING_REG1, 17),
5886dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_MP, "ahb-mp", "ahb",
5896dec99e3Sjmcneill AHB_GATING_REG1, 18),
5906dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_AHB_GPU, "ahb-gpu", "ahb",
5916dec99e3Sjmcneill AHB_GATING_REG1, 20),
5926dec99e3Sjmcneill
5936dec99e3Sjmcneill /* APB0_GATING_REG */
5946dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_APB0_CODEC, "apb0-codec", "apb0",
5956dec99e3Sjmcneill APB0_GATING_REG, 0),
5966dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_APB0_SPDIF, "apb0-spdif", "apb0",
5976dec99e3Sjmcneill APB0_GATING_REG, 1),
5986dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_APB0_AC97, "apb0-ac97", "apb0",
5996dec99e3Sjmcneill APB0_GATING_REG, 2),
6006dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_APB0_I2S0, "apb0-i2s0", "apb0",
6016dec99e3Sjmcneill APB0_GATING_REG, 3),
6026dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_APB0_I2S1, "apb0-i2s1", "apb0",
6036dec99e3Sjmcneill APB0_GATING_REG, 4),
6046dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_APB0_PIO, "apb0-pio", "apb0",
6056dec99e3Sjmcneill APB0_GATING_REG, 5),
6066dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_APB0_IR0, "apb0-ir0", "apb0",
6076dec99e3Sjmcneill APB0_GATING_REG, 6),
6086dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_APB0_IR1, "apb0-ir1", "apb0",
6096dec99e3Sjmcneill APB0_GATING_REG, 7),
6106dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_APB0_I2S2, "apb0-i2s2", "apb0",
6116dec99e3Sjmcneill APB0_GATING_REG, 8),
6126dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_APB0_KEYPAD, "apb0-keypad", "apb0",
6136dec99e3Sjmcneill APB0_GATING_REG, 10),
6146dec99e3Sjmcneill
6156dec99e3Sjmcneill /* APB1_GATING_REG */
6166dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_APB1_I2C0, "apb1-i2c0", "apb1",
6176dec99e3Sjmcneill APB1_GATING_REG, 0),
6186dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_APB1_I2C1, "apb1-i2c1", "apb1",
6196dec99e3Sjmcneill APB1_GATING_REG, 1),
6206dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_APB1_I2C2, "apb1-i2c2", "apb1",
6216dec99e3Sjmcneill APB1_GATING_REG, 2),
6226dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_APB1_I2C3, "apb1-i2c3", "apb1",
6236dec99e3Sjmcneill APB1_GATING_REG, 3),
6246dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_APB1_CAN, "apb1-can", "apb1",
6256dec99e3Sjmcneill APB1_GATING_REG, 4),
6266dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_APB1_SCR, "apb1-scr", "apb1",
6276dec99e3Sjmcneill APB1_GATING_REG, 5),
6286dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_APB1_PS20, "apb1-ps20", "apb1",
6296dec99e3Sjmcneill APB1_GATING_REG, 6),
6306dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_APB1_PS21, "apb1-ps21", "apb1",
6316dec99e3Sjmcneill APB1_GATING_REG, 7),
6326dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_APB1_I2C4, "apb1-i2c4", "apb1",
6336dec99e3Sjmcneill APB1_GATING_REG, 15),
6346dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_APB1_UART0, "apb1-uart0", "apb1",
6356dec99e3Sjmcneill APB1_GATING_REG, 16),
6366dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_APB1_UART1, "apb1-uart1", "apb1",
6376dec99e3Sjmcneill APB1_GATING_REG, 17),
6386dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_APB1_UART2, "apb1-uart2", "apb1",
6396dec99e3Sjmcneill APB1_GATING_REG, 18),
6406dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_APB1_UART3, "apb1-uart3", "apb1",
6416dec99e3Sjmcneill APB1_GATING_REG, 19),
6426dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_APB1_UART4, "apb1-uart4", "apb1",
6436dec99e3Sjmcneill APB1_GATING_REG, 20),
6446dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_APB1_UART5, "apb1-uart5", "apb1",
6456dec99e3Sjmcneill APB1_GATING_REG, 21),
6466dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_APB1_UART6, "apb1-uart6", "apb1",
6476dec99e3Sjmcneill APB1_GATING_REG, 22),
6486dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_APB1_UART7, "apb1-uart7", "apb1",
6496dec99e3Sjmcneill APB1_GATING_REG, 23),
6506dec99e3Sjmcneill
651a1f84860Sbouyer /* DRAM GATING */
652a1f84860Sbouyer SUNXI_CCU_GATE(A10_CLK_DRAM_DE_BE0, "dram-de-be0", "pll_ddr_other",
653a1f84860Sbouyer DRAM_GATING_REG, 26),
654a1f84860Sbouyer SUNXI_CCU_GATE(A10_CLK_DRAM_DE_BE1, "dram-de-be1", "pll_ddr_other",
655a1f84860Sbouyer DRAM_GATING_REG, 27),
656a1f84860Sbouyer SUNXI_CCU_GATE(A10_CLK_DRAM_DE_FE0, "dram-de-fe0", "pll_ddr_other",
657a1f84860Sbouyer DRAM_GATING_REG, 25),
658a1f84860Sbouyer SUNXI_CCU_GATE(A10_CLK_DRAM_DE_FE1, "dram-de-fe1", "pll_ddr_other",
659a1f84860Sbouyer DRAM_GATING_REG, 24),
660a1f84860Sbouyer
6616dec99e3Sjmcneill /* AUDIO_CODEC_SCLK_CFG_REG */
6626dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_CODEC, "codec", "pll_audio",
6636dec99e3Sjmcneill AUDIO_CODEC_SCLK_CFG_REG, 31),
6646dec99e3Sjmcneill
6656dec99e3Sjmcneill /* USBPHY_CFG_REG */
6666dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_USB_OHCI0, "usb-ohci0", "osc24m",
6676dec99e3Sjmcneill USBPHY_CFG_REG, 6),
6686dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_USB_OHCI1, "usb-ohci1", "osc24m",
6696dec99e3Sjmcneill USBPHY_CFG_REG, 7),
6706dec99e3Sjmcneill SUNXI_CCU_GATE(A10_CLK_USB_PHY, "usb-phy", "osc24m",
6716dec99e3Sjmcneill USBPHY_CFG_REG, 8),
6726dec99e3Sjmcneill };
6736dec99e3Sjmcneill
674db6d41fbSbouyer /*
675db6d41fbSbouyer * some special cases
676db6d41fbSbouyer * hardcode lcd0 (tcon0) to pll3 and lcd1 (tcon1) to pll7.
677db6d41fbSbouyer * compute pll rate based on desired pixel clock
678db6d41fbSbouyer */
679db6d41fbSbouyer
680db6d41fbSbouyer static int
sun4i_a10_ccu_lcd0ch0_set_rate(struct sunxi_ccu_softc * sc,struct sunxi_ccu_clk * clk,u_int rate)681db6d41fbSbouyer sun4i_a10_ccu_lcd0ch0_set_rate(struct sunxi_ccu_softc *sc,
682db6d41fbSbouyer struct sunxi_ccu_clk * clk, u_int rate)
683db6d41fbSbouyer {
684db6d41fbSbouyer int error;
685db6d41fbSbouyer error = sunxi_ccu_lcdxch0_set_rate(sc, clk,
686db6d41fbSbouyer &sun4i_a10_ccu_clks[A10_CLK_PLL_VIDEO0],
687db6d41fbSbouyer &sun4i_a10_ccu_clks[A10_CLK_PLL_VIDEO0_2X],
688db6d41fbSbouyer rate);
689db6d41fbSbouyer return error;
690db6d41fbSbouyer }
691db6d41fbSbouyer
692db6d41fbSbouyer static int
sun4i_a10_ccu_lcd1ch0_set_rate(struct sunxi_ccu_softc * sc,struct sunxi_ccu_clk * clk,u_int rate)693db6d41fbSbouyer sun4i_a10_ccu_lcd1ch0_set_rate(struct sunxi_ccu_softc *sc,
694db6d41fbSbouyer struct sunxi_ccu_clk * clk, u_int rate)
695db6d41fbSbouyer {
696db6d41fbSbouyer return sunxi_ccu_lcdxch0_set_rate(sc, clk,
697db6d41fbSbouyer &sun4i_a10_ccu_clks[A10_CLK_PLL_VIDEO1],
698db6d41fbSbouyer &sun4i_a10_ccu_clks[A10_CLK_PLL_VIDEO1_2X],
699db6d41fbSbouyer rate);
700db6d41fbSbouyer }
701db6d41fbSbouyer
702db6d41fbSbouyer static u_int
sun4i_a10_ccu_lcd0ch0_round_rate(struct sunxi_ccu_softc * sc,struct sunxi_ccu_clk * clk,u_int rate)703db6d41fbSbouyer sun4i_a10_ccu_lcd0ch0_round_rate(struct sunxi_ccu_softc *sc,
704db6d41fbSbouyer struct sunxi_ccu_clk * clk, u_int rate)
705db6d41fbSbouyer {
706db6d41fbSbouyer return sunxi_ccu_lcdxch0_round_rate(sc, clk,
707db6d41fbSbouyer &sun4i_a10_ccu_clks[A10_CLK_PLL_VIDEO0],
708db6d41fbSbouyer &sun4i_a10_ccu_clks[A10_CLK_PLL_VIDEO0_2X],
709db6d41fbSbouyer rate);
710db6d41fbSbouyer }
711db6d41fbSbouyer
712db6d41fbSbouyer static u_int
sun4i_a10_ccu_lcd1ch0_round_rate(struct sunxi_ccu_softc * sc,struct sunxi_ccu_clk * clk,u_int rate)713db6d41fbSbouyer sun4i_a10_ccu_lcd1ch0_round_rate(struct sunxi_ccu_softc *sc,
714db6d41fbSbouyer struct sunxi_ccu_clk * clk, u_int rate)
715db6d41fbSbouyer {
716db6d41fbSbouyer return sunxi_ccu_lcdxch0_round_rate(sc, clk,
717db6d41fbSbouyer &sun4i_a10_ccu_clks[A10_CLK_PLL_VIDEO1],
718db6d41fbSbouyer &sun4i_a10_ccu_clks[A10_CLK_PLL_VIDEO1_2X],
719db6d41fbSbouyer rate);
720db6d41fbSbouyer }
721db6d41fbSbouyer
722db6d41fbSbouyer static int
sun4i_a10_ccu_lcd0ch1_set_rate(struct sunxi_ccu_softc * sc,struct sunxi_ccu_clk * clk,u_int rate)723db6d41fbSbouyer sun4i_a10_ccu_lcd0ch1_set_rate(struct sunxi_ccu_softc *sc,
724db6d41fbSbouyer struct sunxi_ccu_clk * clk, u_int rate)
725db6d41fbSbouyer {
726db6d41fbSbouyer return sunxi_ccu_lcdxch1_set_rate(sc, clk,
727db6d41fbSbouyer &sun4i_a10_ccu_clks[A10_CLK_PLL_VIDEO0],
728db6d41fbSbouyer &sun4i_a10_ccu_clks[A10_CLK_PLL_VIDEO0_2X],
729db6d41fbSbouyer rate);
730db6d41fbSbouyer }
731db6d41fbSbouyer
732db6d41fbSbouyer static int
sun4i_a10_ccu_lcd1ch1_set_rate(struct sunxi_ccu_softc * sc,struct sunxi_ccu_clk * clk,u_int rate)733db6d41fbSbouyer sun4i_a10_ccu_lcd1ch1_set_rate(struct sunxi_ccu_softc *sc,
734db6d41fbSbouyer struct sunxi_ccu_clk * clk, u_int rate)
735db6d41fbSbouyer {
736db6d41fbSbouyer return sunxi_ccu_lcdxch1_set_rate(sc, clk,
737db6d41fbSbouyer &sun4i_a10_ccu_clks[A10_CLK_PLL_VIDEO1],
738db6d41fbSbouyer &sun4i_a10_ccu_clks[A10_CLK_PLL_VIDEO1_2X],
739db6d41fbSbouyer rate);
740db6d41fbSbouyer }
741db6d41fbSbouyer
742db6d41fbSbouyer #if 0
743db6d41fbSbouyer static int
744db6d41fbSbouyer sun4i_a10_ccu_lcdxch0_set_rate(struct sunxi_ccu_softc *sc,
745db6d41fbSbouyer struct sunxi_ccu_clk * clk, u_int rate, int unit)
746db6d41fbSbouyer {
747db6d41fbSbouyer int parent_index;
748db6d41fbSbouyer struct clk *clkp;
749db6d41fbSbouyer int error;
750db6d41fbSbouyer
751db6d41fbSbouyer parent_index = (unit == 0) ? A10_CLK_PLL_VIDEO0 : A10_CLK_PLL_VIDEO1;
752db6d41fbSbouyer clkp = &sun4i_a10_ccu_clks[parent_index].base;
753db6d41fbSbouyer error = clk_set_rate(clkp, rate);
754db6d41fbSbouyer if (error) {
755db6d41fbSbouyer error = clk_set_rate(clkp, rate / 2);
756db6d41fbSbouyer if (error != 0)
757db6d41fbSbouyer return error;
758db6d41fbSbouyer parent_index =
759db6d41fbSbouyer (unit == 0) ? A10_CLK_PLL_VIDEO0_2X : A10_CLK_PLL_VIDEO1_2X;
760db6d41fbSbouyer clkp = &sun4i_a10_ccu_clks[parent_index].base;
761db6d41fbSbouyer }
762db6d41fbSbouyer error = clk_set_parent(&clk->base, clkp);
763db6d41fbSbouyer KASSERT(error == 0);
764db6d41fbSbouyer return error;
765db6d41fbSbouyer }
766db6d41fbSbouyer
767db6d41fbSbouyer static u_int
768db6d41fbSbouyer sun4i_a10_ccu_lcdxch0_round_rate(struct sunxi_ccu_softc *sc,
769db6d41fbSbouyer struct sunxi_ccu_clk * clk, u_int try_rate, int unit)
770db6d41fbSbouyer {
771db6d41fbSbouyer int parent_index;
772db6d41fbSbouyer struct clk *clkp;
773db6d41fbSbouyer int diff, diff_x2;
774db6d41fbSbouyer int rate, rate_x2;
775db6d41fbSbouyer
776db6d41fbSbouyer parent_index = (unit == 0) ? A10_CLK_PLL_VIDEO0 : A10_CLK_PLL_VIDEO1;
777db6d41fbSbouyer clkp = &sun4i_a10_ccu_clks[parent_index].base;
778db6d41fbSbouyer rate = clk_round_rate(clkp, try_rate);
779db6d41fbSbouyer diff = abs(try_rate - rate);
780db6d41fbSbouyer
781db6d41fbSbouyer rate_x2 = (clk_round_rate(clkp, try_rate / 2) * 2);
782db6d41fbSbouyer diff_x2 = abs(try_rate - rate_x2);
783db6d41fbSbouyer
784db6d41fbSbouyer if (diff_x2 < diff)
785db6d41fbSbouyer return rate_x2;
786db6d41fbSbouyer return rate;
787db6d41fbSbouyer }
788db6d41fbSbouyer
789db6d41fbSbouyer static void
790db6d41fbSbouyer sun4i_a10_tcon_calc_pll(int f_ref, int f_out, int *pm, int *pn, int *pd)
791db6d41fbSbouyer {
792db6d41fbSbouyer int best = INT_MAX;
793db6d41fbSbouyer for (int d = 1; d <= 2 && best != 0; d++) {
794db6d41fbSbouyer for (int m = 1; m <= 16 && best != 0; m++) {
795db6d41fbSbouyer for (int n = 9; n <= 127 && best != 0; n++) {
796db6d41fbSbouyer int f_cur = (n * f_ref * d) / m;
797db6d41fbSbouyer int diff = abs(f_out - f_cur);
798db6d41fbSbouyer if (diff < best) {
799db6d41fbSbouyer best = diff;
800db6d41fbSbouyer *pm = m;
801db6d41fbSbouyer *pn = n;
802db6d41fbSbouyer *pd = d;
803db6d41fbSbouyer if (diff == 0)
804db6d41fbSbouyer return;
805db6d41fbSbouyer }
806db6d41fbSbouyer }
807db6d41fbSbouyer }
808db6d41fbSbouyer }
809db6d41fbSbouyer }
810db6d41fbSbouyer
811db6d41fbSbouyer static int
812db6d41fbSbouyer sun4i_a10_ccu_lcdxch1_set_rate(struct sunxi_ccu_softc *sc,
813db6d41fbSbouyer struct sunxi_ccu_clk *clk, u_int rate, int unit)
814db6d41fbSbouyer {
815db6d41fbSbouyer int parent_index;
816db6d41fbSbouyer struct clk *clkp, *pllclk;
817db6d41fbSbouyer int error;
818db6d41fbSbouyer int n = 0, m = 0, d = 0;
819db6d41fbSbouyer
820db6d41fbSbouyer parent_index = (unit == 0) ? A10_CLK_PLL_VIDEO0 : A10_CLK_PLL_VIDEO1;
821db6d41fbSbouyer clkp = &sun4i_a10_ccu_clks[parent_index].base;
822db6d41fbSbouyer pllclk = clkp;
823db6d41fbSbouyer
824db6d41fbSbouyer sun4i_a10_tcon_calc_pll(3000000, rate, &m, &n, &d);
825db6d41fbSbouyer
826db6d41fbSbouyer if (n == 0 || m == 0 || d == 0)
827db6d41fbSbouyer return ERANGE;
828db6d41fbSbouyer
829db6d41fbSbouyer if (d == 2) {
830db6d41fbSbouyer parent_index =
831db6d41fbSbouyer (unit == 0) ? A10_CLK_PLL_VIDEO0_2X : A10_CLK_PLL_VIDEO1_2X;
832db6d41fbSbouyer clkp = &sun4i_a10_ccu_clks[parent_index].base;
833db6d41fbSbouyer }
834db6d41fbSbouyer
835db6d41fbSbouyer error = clk_set_rate(pllclk, 3000000 * n);
836db6d41fbSbouyer KASSERT(error == 0);
837db6d41fbSbouyer error = clk_set_parent(&clk->base, clkp);
838db6d41fbSbouyer KASSERT(error == 0);
839db6d41fbSbouyer error = sunxi_ccu_div_set_rate(sc, clk, rate);
840db6d41fbSbouyer KASSERT(error == 0);
841db6d41fbSbouyer return error;
842db6d41fbSbouyer }
843db6d41fbSbouyer #endif
844db6d41fbSbouyer
8456dec99e3Sjmcneill static int
sun4i_a10_ccu_match(device_t parent,cfdata_t cf,void * aux)8466dec99e3Sjmcneill sun4i_a10_ccu_match(device_t parent, cfdata_t cf, void *aux)
8476dec99e3Sjmcneill {
8486dec99e3Sjmcneill struct fdt_attach_args * const faa = aux;
8496dec99e3Sjmcneill
850*6e54367aSthorpej return of_compatible_match(faa->faa_phandle, compat_data);
8516dec99e3Sjmcneill }
8526dec99e3Sjmcneill
853db6d41fbSbouyer static struct sunxi_ccu_softc *sc0;
8546dec99e3Sjmcneill static void
sun4i_a10_ccu_attach(device_t parent,device_t self,void * aux)8556dec99e3Sjmcneill sun4i_a10_ccu_attach(device_t parent, device_t self, void *aux)
8566dec99e3Sjmcneill {
8576dec99e3Sjmcneill struct sunxi_ccu_softc * const sc = device_private(self);
8586dec99e3Sjmcneill struct fdt_attach_args * const faa = aux;
8596dec99e3Sjmcneill enum sun4i_a10_ccu_type type;
860db6d41fbSbouyer struct clk *clk, *clkp;
861db6d41fbSbouyer int error;
8626dec99e3Sjmcneill
8636dec99e3Sjmcneill sc->sc_dev = self;
8646dec99e3Sjmcneill sc->sc_phandle = faa->faa_phandle;
8656dec99e3Sjmcneill sc->sc_bst = faa->faa_bst;
8666dec99e3Sjmcneill
8676dec99e3Sjmcneill sc->sc_resets = sun4i_a10_ccu_resets;
8686dec99e3Sjmcneill sc->sc_nresets = __arraycount(sun4i_a10_ccu_resets);
8696dec99e3Sjmcneill
8706dec99e3Sjmcneill sc->sc_clks = sun4i_a10_ccu_clks;
8716dec99e3Sjmcneill sc->sc_nclks = __arraycount(sun4i_a10_ccu_clks);
8726dec99e3Sjmcneill
8736dec99e3Sjmcneill if (sunxi_ccu_attach(sc) != 0)
8746dec99e3Sjmcneill return;
8756dec99e3Sjmcneill
8766dec99e3Sjmcneill aprint_naive("\n");
8776dec99e3Sjmcneill
878*6e54367aSthorpej type = of_compatible_lookup(faa->faa_phandle, compat_data)->value;
8796dec99e3Sjmcneill
8806dec99e3Sjmcneill switch (type) {
8816dec99e3Sjmcneill case CCU_A10:
8826dec99e3Sjmcneill aprint_normal(": A10 CCU\n");
8836dec99e3Sjmcneill break;
8846dec99e3Sjmcneill case CCU_A20:
8856dec99e3Sjmcneill aprint_normal(": A20 CCU\n");
8866dec99e3Sjmcneill break;
8876dec99e3Sjmcneill }
888db6d41fbSbouyer /* hardcode debe clocks parent to PLL5 */
889db6d41fbSbouyer clkp = &sun4i_a10_ccu_clks[A10_CLK_PLL_DDR_BASE].base;
890db6d41fbSbouyer clk = &sun4i_a10_ccu_clks[A10_CLK_DE_BE0].base;
891db6d41fbSbouyer error = clk_set_parent(clk, clkp);
892db6d41fbSbouyer KASSERT(error == 0);
893db6d41fbSbouyer clk = &sun4i_a10_ccu_clks[A10_CLK_DE_BE1].base;
894db6d41fbSbouyer error = clk_set_parent(clk, clkp);
895db6d41fbSbouyer KASSERT(error == 0);
8966dec99e3Sjmcneill
897db6d41fbSbouyer (void)error;
8986dec99e3Sjmcneill sunxi_ccu_print(sc);
899db6d41fbSbouyer sc0 = sc;
900db6d41fbSbouyer }
901db6d41fbSbouyer
902db6d41fbSbouyer void sun4i_ccu_print(void);
903db6d41fbSbouyer void
sun4i_ccu_print(void)904db6d41fbSbouyer sun4i_ccu_print(void)
905db6d41fbSbouyer {
906db6d41fbSbouyer sunxi_ccu_print(sc0);
9076dec99e3Sjmcneill }
908