1 /* $NetBSD: sun8i_v3s_ccu.c,v 1.1 2021/05/05 10:24:04 jmcneill Exp $ */ 2 3 /*- 4 * Copyright (c) 2021 Rui-Xiang Guo 5 * Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca> 6 * Copyright (c) 2017 Emmanuel Vadot <manu@freebsd.org> 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 33 __KERNEL_RCSID(1, "$NetBSD: sun8i_v3s_ccu.c,v 1.1 2021/05/05 10:24:04 jmcneill Exp $"); 34 35 #include <sys/param.h> 36 #include <sys/bus.h> 37 #include <sys/device.h> 38 #include <sys/systm.h> 39 40 #include <dev/fdt/fdtvar.h> 41 42 #include <arm/sunxi/sunxi_ccu.h> 43 #include <arm/sunxi/sun8i_v3s_ccu.h> 44 45 #define PLL_CPU_CTRL_REG 0x000 46 #define PLL_AUDIO_CTRL_REG 0x008 47 #define PLL_VIDEO_CTRL_REG 0x010 48 #define PLL_PERIPH0_CTRL_REG 0x028 49 #define AHB1_APB1_CFG_REG 0x054 50 #define APB2_CFG_REG 0x058 51 #define AHB2_CFG_REG 0x05c 52 #define AHB2_CLK_CFG __BITS(1,0) 53 #define AHB2_CLK_CFG_PLL_PERIPH0_2 1 54 #define BUS_CLK_GATING_REG0 0x060 55 #define BUS_CLK_GATING_REG1 0x064 56 #define BUS_CLK_GATING_REG2 0x068 57 #define BUS_CLK_GATING_REG3 0x06c 58 #define BUS_CLK_GATING_REG4 0x070 59 #define SDMMC0_CLK_REG 0x088 60 #define SDMMC1_CLK_REG 0x08c 61 #define SDMMC2_CLK_REG 0x090 62 #define SPI_CLK_REG 0x0a0 63 #define USBPHY_CFG_REG 0x0cc 64 #define MBUS_RST_REG 0x0fc 65 #define DE_CLK_REG 0x104 66 #define TCON_CLK_REG 0x118 67 #define AC_DIG_CLK_REG 0x140 68 #define BUS_SOFT_RST_REG0 0x2c0 69 #define BUS_SOFT_RST_REG1 0x2c4 70 #define BUS_SOFT_RST_REG2 0x2c8 71 #define BUS_SOFT_RST_REG3 0x2d0 72 #define BUS_SOFT_RST_REG4 0x2d8 73 74 static int sun8i_v3s_ccu_match(device_t, cfdata_t, void *); 75 static void sun8i_v3s_ccu_attach(device_t, device_t, void *); 76 77 static const struct device_compatible_entry compat_data[] = { 78 { .compat = "allwinner,sun8i-v3s-ccu" }, 79 DEVICE_COMPAT_EOL 80 }; 81 82 CFATTACH_DECL_NEW(sunxi_v3s_ccu, sizeof(struct sunxi_ccu_softc), 83 sun8i_v3s_ccu_match, sun8i_v3s_ccu_attach, NULL, NULL); 84 85 static struct sunxi_ccu_reset sun8i_v3s_ccu_resets[] = { 86 SUNXI_CCU_RESET(V3S_RST_USBPHY, USBPHY_CFG_REG, 0), 87 88 SUNXI_CCU_RESET(V3S_RST_MBUS, MBUS_RST_REG, 31), 89 90 SUNXI_CCU_RESET(V3S_RST_BUS_CE, BUS_SOFT_RST_REG0, 5), 91 SUNXI_CCU_RESET(V3S_RST_BUS_DMA, BUS_SOFT_RST_REG0, 6), 92 SUNXI_CCU_RESET(V3S_RST_BUS_MMC0, BUS_SOFT_RST_REG0, 8), 93 SUNXI_CCU_RESET(V3S_RST_BUS_MMC1, BUS_SOFT_RST_REG0, 9), 94 SUNXI_CCU_RESET(V3S_RST_BUS_MMC2, BUS_SOFT_RST_REG0, 10), 95 SUNXI_CCU_RESET(V3S_RST_BUS_DRAM, BUS_SOFT_RST_REG0, 14), 96 SUNXI_CCU_RESET(V3S_RST_BUS_EMAC, BUS_SOFT_RST_REG0, 17), 97 SUNXI_CCU_RESET(V3S_RST_BUS_HSTIMER, BUS_SOFT_RST_REG0, 19), 98 SUNXI_CCU_RESET(V3S_RST_BUS_SPI, BUS_SOFT_RST_REG0, 20), 99 SUNXI_CCU_RESET(V3S_RST_BUS_OTG, BUS_SOFT_RST_REG0, 24), 100 SUNXI_CCU_RESET(V3S_RST_BUS_EHCI, BUS_SOFT_RST_REG0, 26), 101 SUNXI_CCU_RESET(V3S_RST_BUS_OHCI, BUS_SOFT_RST_REG0, 29), 102 103 SUNXI_CCU_RESET(V3S_RST_BUS_VE, BUS_SOFT_RST_REG1, 0), 104 SUNXI_CCU_RESET(V3S_RST_BUS_TCON, BUS_SOFT_RST_REG1, 4), 105 SUNXI_CCU_RESET(V3S_RST_BUS_CSI, BUS_SOFT_RST_REG1, 8), 106 SUNXI_CCU_RESET(V3S_RST_BUS_DE, BUS_SOFT_RST_REG1, 12), 107 SUNXI_CCU_RESET(V3S_RST_BUS_DBG, BUS_SOFT_RST_REG1, 31), 108 109 SUNXI_CCU_RESET(V3S_RST_BUS_EPHY, BUS_SOFT_RST_REG2, 2), 110 111 SUNXI_CCU_RESET(V3S_RST_BUS_CODEC, BUS_SOFT_RST_REG3, 0), 112 113 SUNXI_CCU_RESET(V3S_RST_BUS_I2C0, BUS_SOFT_RST_REG4, 0), 114 SUNXI_CCU_RESET(V3S_RST_BUS_I2C1, BUS_SOFT_RST_REG4, 1), 115 SUNXI_CCU_RESET(V3S_RST_BUS_UART0, BUS_SOFT_RST_REG4, 16), 116 SUNXI_CCU_RESET(V3S_RST_BUS_UART1, BUS_SOFT_RST_REG4, 17), 117 SUNXI_CCU_RESET(V3S_RST_BUS_UART2, BUS_SOFT_RST_REG4, 18), 118 }; 119 120 static const char *ahb1_parents[] = { "losc", "hosc", "axi", "pll_periph0" }; 121 static const char *ahb2_parents[] = { "ahb1", "pll_periph0" }; 122 static const char *apb1_parents[] = { "ahb1" }; 123 static const char *apb2_parents[] = { "losc", "hosc", "pll_periph0" }; 124 static const char *mod_parents[] = { "hosc", "pll_periph0", "pll_periph1" }; 125 static const char *tcon_parents[] = { "pll_video" }; 126 127 static const struct sunxi_ccu_nkmp_tbl sun8i_v3s_cpu_table[] = { 128 { 60000000, 9, 0, 0, 2 }, 129 { 66000000, 10, 0, 0, 2 }, 130 { 72000000, 11, 0, 0, 2 }, 131 { 78000000, 12, 0, 0, 2 }, 132 { 84000000, 13, 0, 0, 2 }, 133 { 90000000, 14, 0, 0, 2 }, 134 { 96000000, 15, 0, 0, 2 }, 135 { 102000000, 16, 0, 0, 2 }, 136 { 108000000, 17, 0, 0, 2 }, 137 { 114000000, 18, 0, 0, 2 }, 138 { 120000000, 9, 0, 0, 1 }, 139 { 132000000, 10, 0, 0, 1 }, 140 { 144000000, 11, 0, 0, 1 }, 141 { 156000000, 12, 0, 0, 1 }, 142 { 168000000, 13, 0, 0, 1 }, 143 { 180000000, 14, 0, 0, 1 }, 144 { 192000000, 15, 0, 0, 1 }, 145 { 204000000, 16, 0, 0, 1 }, 146 { 216000000, 17, 0, 0, 1 }, 147 { 228000000, 18, 0, 0, 1 }, 148 { 240000000, 9, 0, 0, 0 }, 149 { 264000000, 10, 0, 0, 0 }, 150 { 288000000, 11, 0, 0, 0 }, 151 { 312000000, 12, 0, 0, 0 }, 152 { 336000000, 13, 0, 0, 0 }, 153 { 360000000, 14, 0, 0, 0 }, 154 { 384000000, 15, 0, 0, 0 }, 155 { 408000000, 16, 0, 0, 0 }, 156 { 432000000, 17, 0, 0, 0 }, 157 { 456000000, 18, 0, 0, 0 }, 158 { 480000000, 19, 0, 0, 0 }, 159 { 504000000, 20, 0, 0, 0 }, 160 { 528000000, 21, 0, 0, 0 }, 161 { 552000000, 22, 0, 0, 0 }, 162 { 576000000, 23, 0, 0, 0 }, 163 { 600000000, 24, 0, 0, 0 }, 164 { 624000000, 25, 0, 0, 0 }, 165 { 648000000, 26, 0, 0, 0 }, 166 { 672000000, 27, 0, 0, 0 }, 167 { 696000000, 28, 0, 0, 0 }, 168 { 720000000, 29, 0, 0, 0 }, 169 { 768000000, 15, 1, 0, 0 }, 170 { 792000000, 10, 2, 0, 0 }, 171 { 816000000, 16, 1, 0, 0 }, 172 { 864000000, 17, 1, 0, 0 }, 173 { 912000000, 18, 1, 0, 0 }, 174 { 936000000, 12, 2, 0, 0 }, 175 { 960000000, 19, 1, 0, 0 }, 176 { 1008000000, 20, 1, 0, 0 }, 177 { 1056000000, 21, 1, 0, 0 }, 178 { 1080000000, 14, 2, 0, 0 }, 179 { 1104000000, 22, 1, 0, 0 }, 180 { 1152000000, 23, 1, 0, 0 }, 181 { 1200000000, 24, 1, 0, 0 }, 182 { 1224000000, 16, 2, 0, 0 }, 183 { 1248000000, 25, 1, 0, 0 }, 184 { 1296000000, 26, 1, 0, 0 }, 185 { 1344000000, 27, 1, 0, 0 }, 186 { 1368000000, 18, 2, 0, 0 }, 187 { 1392000000, 28, 1, 0, 0 }, 188 { 1440000000, 29, 1, 0, 0 }, 189 { 1512000000, 20, 2, 0, 0 }, 190 { 1536000000, 15, 3, 0, 0 }, 191 { 1584000000, 21, 2, 0, 0 }, 192 { 1632000000, 16, 3, 0, 0 }, 193 { 1656000000, 22, 2, 0, 0 }, 194 { 1728000000, 23, 2, 0, 0 }, 195 { 1800000000, 24, 2, 0, 0 }, 196 { 1824000000, 18, 3, 0, 0 }, 197 { 1872000000, 25, 2, 0, 0 }, 198 { 0 } 199 }; 200 201 static const struct sunxi_ccu_nkmp_tbl sun8i_v3s_ac_dig_table[] = { 202 { 24576000, 13, 0, 0, 13 }, 203 { 0 } 204 }; 205 206 static struct sunxi_ccu_clk sun8i_v3s_ccu_clks[] = { 207 SUNXI_CCU_NKMP_TABLE(V3S_CLK_CPU, "pll_cpu", "hosc", 208 PLL_CPU_CTRL_REG, /* reg */ 209 __BITS(12,8), /* n */ 210 __BITS(5,4), /* k */ 211 __BITS(1,0), /* m */ 212 __BITS(17,16), /* p */ 213 __BIT(31), /* enable */ 214 __BIT(28), /* lock */ 215 sun8i_v3s_cpu_table, /* table */ 216 SUNXI_CCU_NKMP_SCALE_CLOCK | SUNXI_CCU_NKMP_FACTOR_P_POW2), 217 218 SUNXI_CCU_NKMP(V3S_CLK_PLL_PERIPH0, "pll_periph0", "hosc", 219 PLL_PERIPH0_CTRL_REG, /* reg */ 220 __BITS(12,8), /* n */ 221 __BITS(5,4), /* k */ 222 0, /* m */ 223 __BITS(17,16), /* p */ 224 __BIT(31), /* enable */ 225 SUNXI_CCU_NKMP_DIVIDE_BY_TWO), 226 227 SUNXI_CCU_FIXED_FACTOR(V3S_CLK_PLL_PERIPH0_2X, "pll_periph0_2x", "pll_periph0", 1, 2), 228 229 SUNXI_CCU_FRACTIONAL(V3S_CLK_PLL_VIDEO, "pll_video", "hosc", 230 PLL_VIDEO_CTRL_REG, /* reg */ 231 __BITS(14,8), /* m */ 232 16, /* m_min */ 233 50, /* m_max */ 234 __BIT(24), /* div_en */ 235 __BIT(25), /* frac_sel */ 236 270000000, 297000000, /* frac values */ 237 __BITS(3,0), /* prediv */ 238 4, /* prediv_val */ 239 __BIT(31), /* enable */ 240 SUNXI_CCU_FRACTIONAL_PLUSONE | SUNXI_CCU_FRACTIONAL_SET_ENABLE), 241 242 SUNXI_CCU_NKMP_TABLE(V3S_CLK_PLL_AUDIO_BASE, "pll_audio", "hosc", 243 PLL_AUDIO_CTRL_REG, /* reg */ 244 __BITS(14,8), /* n */ 245 0, /* k */ 246 __BITS(4,0), /* m */ 247 __BITS(19,16), /* p */ 248 __BIT(31), /* enable */ 249 __BIT(28), /* lock */ 250 sun8i_v3s_ac_dig_table, /* table */ 251 0), 252 253 SUNXI_CCU_PREDIV(V3S_CLK_AHB1, "ahb1", ahb1_parents, 254 AHB1_APB1_CFG_REG, /* reg */ 255 __BITS(7,6), /* prediv */ 256 __BIT(3), /* prediv_sel */ 257 __BITS(5,4), /* div */ 258 __BITS(13,12), /* sel */ 259 SUNXI_CCU_PREDIV_POWER_OF_TWO), 260 261 SUNXI_CCU_PREDIV(V3S_CLK_AHB2, "ahb2", ahb2_parents, 262 AHB2_CFG_REG, /* reg */ 263 0, /* prediv */ 264 __BIT(1), /* prediv_sel */ 265 0, /* div */ 266 __BITS(1,0), /* sel */ 267 SUNXI_CCU_PREDIV_DIVIDE_BY_TWO), 268 269 SUNXI_CCU_DIV(V3S_CLK_APB1, "apb1", apb1_parents, 270 AHB1_APB1_CFG_REG, /* reg */ 271 __BITS(9,8), /* div */ 272 0, /* sel */ 273 SUNXI_CCU_DIV_POWER_OF_TWO|SUNXI_CCU_DIV_ZERO_IS_ONE), 274 275 SUNXI_CCU_NM(V3S_CLK_APB2, "apb2", apb2_parents, 276 APB2_CFG_REG, /* reg */ 277 __BITS(17,16), /* n */ 278 __BITS(4,0), /* m */ 279 __BITS(25,24), /* sel */ 280 0, /* enable */ 281 SUNXI_CCU_NM_POWER_OF_TWO), 282 283 SUNXI_CCU_NM(V3S_CLK_MMC0, "mmc0", mod_parents, 284 SDMMC0_CLK_REG, __BITS(17, 16), __BITS(3,0), __BITS(25, 24), __BIT(31), 285 SUNXI_CCU_NM_POWER_OF_TWO|SUNXI_CCU_NM_ROUND_DOWN), 286 SUNXI_CCU_PHASE(V3S_CLK_MMC0_SAMPLE, "mmc0_sample", "mmc0", 287 SDMMC0_CLK_REG, __BITS(22,20)), 288 SUNXI_CCU_PHASE(V3S_CLK_MMC0_OUTPUT, "mmc0_output", "mmc0", 289 SDMMC0_CLK_REG, __BITS(10,8)), 290 SUNXI_CCU_NM(V3S_CLK_MMC1, "mmc1", mod_parents, 291 SDMMC1_CLK_REG, __BITS(17, 16), __BITS(3,0), __BITS(25, 24), __BIT(31), 292 SUNXI_CCU_NM_POWER_OF_TWO|SUNXI_CCU_NM_ROUND_DOWN), 293 SUNXI_CCU_PHASE(V3S_CLK_MMC1_SAMPLE, "mmc1_sample", "mmc1", 294 SDMMC1_CLK_REG, __BITS(22,20)), 295 SUNXI_CCU_PHASE(V3S_CLK_MMC1_OUTPUT, "mmc1_output", "mmc1", 296 SDMMC1_CLK_REG, __BITS(10,8)), 297 SUNXI_CCU_NM(V3S_CLK_MMC2, "mmc2", mod_parents, 298 SDMMC2_CLK_REG, __BITS(17, 16), __BITS(3,0), __BITS(25, 24), __BIT(31), 299 SUNXI_CCU_NM_POWER_OF_TWO|SUNXI_CCU_NM_ROUND_DOWN), 300 SUNXI_CCU_PHASE(V3S_CLK_MMC2_SAMPLE, "mmc2_sample", "mmc2", 301 SDMMC2_CLK_REG, __BITS(22,20)), 302 SUNXI_CCU_PHASE(V3S_CLK_MMC2_OUTPUT, "mmc2_output", "mmc2", 303 SDMMC2_CLK_REG, __BITS(10,8)), 304 305 SUNXI_CCU_NM(V3S_CLK_SPI, "spi", mod_parents, 306 SPI_CLK_REG, /* reg */ 307 __BITS(17,16), /* n */ 308 __BITS(3,0), /* m */ 309 __BITS(25,24), /* sel */ 310 __BIT(31), /* enable */ 311 SUNXI_CCU_NM_ROUND_DOWN), 312 313 SUNXI_CCU_GATE(V3S_CLK_AC_DIG, "ac_dig", "pll_audio", 314 AC_DIG_CLK_REG, 31), 315 316 SUNXI_CCU_DIV_GATE(V3S_CLK_TCON, "tcon", tcon_parents, 317 TCON_CLK_REG, /* reg */ 318 __BITS(3,0), /* div */ 319 __BITS(26,24), /* sel */ 320 __BIT(31), /* enable */ 321 0), 322 323 SUNXI_CCU_GATE(V3S_CLK_BUS_DMA, "bus-dma", "ahb1", 324 BUS_CLK_GATING_REG0, 6), 325 SUNXI_CCU_GATE(V3S_CLK_BUS_MMC0, "bus-mmc0", "ahb1", 326 BUS_CLK_GATING_REG0, 8), 327 SUNXI_CCU_GATE(V3S_CLK_BUS_MMC1, "bus-mmc1", "ahb1", 328 BUS_CLK_GATING_REG0, 9), 329 SUNXI_CCU_GATE(V3S_CLK_BUS_MMC2, "bus-mmc2", "ahb1", 330 BUS_CLK_GATING_REG0, 10), 331 SUNXI_CCU_GATE(V3S_CLK_BUS_EMAC, "bus-emac", "ahb2", 332 BUS_CLK_GATING_REG0, 17), 333 SUNXI_CCU_GATE(V3S_CLK_BUS_SPI, "bus-spi", "ahb1", 334 BUS_CLK_GATING_REG0, 20), 335 SUNXI_CCU_GATE(V3S_CLK_BUS_OTG, "bus-otg", "ahb1", 336 BUS_CLK_GATING_REG0, 24), 337 SUNXI_CCU_GATE(V3S_CLK_BUS_EHCI, "bus-ehci", "ahb1", 338 BUS_CLK_GATING_REG0, 26), 339 SUNXI_CCU_GATE(V3S_CLK_BUS_OHCI, "bus-ohci", "ahb1", 340 BUS_CLK_GATING_REG0, 29), 341 342 SUNXI_CCU_GATE(V3S_CLK_BUS_TCON, "bus-tcon", "ahb1", 343 BUS_CLK_GATING_REG1, 4), 344 SUNXI_CCU_GATE(V3S_CLK_BUS_DE, "bus-de", "ahb1", 345 BUS_CLK_GATING_REG1, 12), 346 347 SUNXI_CCU_GATE(V3S_CLK_BUS_CODEC, "bus-codec", "apb1", 348 BUS_CLK_GATING_REG2, 0), 349 SUNXI_CCU_GATE(V3S_CLK_BUS_PIO, "bus-pio", "apb1", 350 BUS_CLK_GATING_REG2, 5), 351 352 SUNXI_CCU_GATE(V3S_CLK_BUS_I2C0, "bus-i2c0", "apb2", 353 BUS_CLK_GATING_REG3, 0), 354 SUNXI_CCU_GATE(V3S_CLK_BUS_I2C1, "bus-i2c1", "apb2", 355 BUS_CLK_GATING_REG3, 1), 356 SUNXI_CCU_GATE(V3S_CLK_BUS_UART0, "bus-uart0", "apb2", 357 BUS_CLK_GATING_REG3, 16), 358 SUNXI_CCU_GATE(V3S_CLK_BUS_UART1, "bus-uart1", "apb2", 359 BUS_CLK_GATING_REG3, 17), 360 SUNXI_CCU_GATE(V3S_CLK_BUS_UART2, "bus-uart2", "apb2", 361 BUS_CLK_GATING_REG3, 18), 362 363 SUNXI_CCU_GATE(V3S_CLK_BUS_EPHY, "bus-ephy", "ahb1", 364 BUS_CLK_GATING_REG4, 0), 365 366 SUNXI_CCU_GATE(V3S_CLK_USBPHY, "usb-phy", "hosc", 367 USBPHY_CFG_REG, 8), 368 SUNXI_CCU_GATE(V3S_CLK_USBOHCI, "usb-ohci", "hosc", 369 USBPHY_CFG_REG, 16), 370 }; 371 372 static void 373 sun8i_v3s_ccu_init(struct sunxi_ccu_softc *sc) 374 { 375 uint32_t val; 376 377 /* Set AHB2 source to PLL_PERIPH/2 */ 378 val = CCU_READ(sc, AHB2_CFG_REG); 379 val &= ~AHB2_CLK_CFG; 380 val |= __SHIFTIN(AHB2_CLK_CFG_PLL_PERIPH0_2, AHB2_CLK_CFG); 381 CCU_WRITE(sc, AHB2_CFG_REG, val); 382 } 383 384 static int 385 sun8i_v3s_ccu_match(device_t parent, cfdata_t cf, void *aux) 386 { 387 struct fdt_attach_args * const faa = aux; 388 389 return of_compatible_match(faa->faa_phandle, compat_data); 390 } 391 392 static void 393 sun8i_v3s_ccu_attach(device_t parent, device_t self, void *aux) 394 { 395 struct sunxi_ccu_softc * const sc = device_private(self); 396 struct fdt_attach_args * const faa = aux; 397 398 sc->sc_dev = self; 399 sc->sc_phandle = faa->faa_phandle; 400 sc->sc_bst = faa->faa_bst; 401 402 sc->sc_resets = sun8i_v3s_ccu_resets; 403 sc->sc_nresets = __arraycount(sun8i_v3s_ccu_resets); 404 405 sc->sc_clks = sun8i_v3s_ccu_clks; 406 sc->sc_nclks = __arraycount(sun8i_v3s_ccu_clks); 407 408 if (sunxi_ccu_attach(sc) != 0) 409 return; 410 411 aprint_naive("\n"); 412 aprint_normal(": V3s CCU\n"); 413 414 sun8i_v3s_ccu_init(sc); 415 416 sunxi_ccu_print(sc); 417 } 418