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