1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2016 Icenowy Zheng <icenowy@aosc.io> 4 * 5 */ 6 7 #include <linux/clk-provider.h> 8 #include <linux/io.h> 9 #include <linux/of_address.h> 10 11 #include "ccu_common.h" 12 #include "ccu_reset.h" 13 14 #include "ccu_div.h" 15 #include "ccu_gate.h" 16 #include "ccu_mp.h" 17 #include "ccu_mult.h" 18 #include "ccu_nk.h" 19 #include "ccu_nkm.h" 20 #include "ccu_nkmp.h" 21 #include "ccu_nm.h" 22 #include "ccu_phase.h" 23 24 #include "ccu-suniv-f1c100s.h" 25 26 static struct ccu_nkmp pll_cpu_clk = { 27 .enable = BIT(31), 28 .lock = BIT(28), 29 30 .n = _SUNXI_CCU_MULT(8, 5), 31 .k = _SUNXI_CCU_MULT(4, 2), 32 .m = _SUNXI_CCU_DIV(0, 2), 33 /* MAX is guessed by the BSP table */ 34 .p = _SUNXI_CCU_DIV_MAX(16, 2, 4), 35 36 .common = { 37 .reg = 0x000, 38 .hw.init = CLK_HW_INIT("pll-cpu", "osc24M", 39 &ccu_nkmp_ops, 40 CLK_SET_RATE_UNGATE), 41 }, 42 }; 43 44 /* 45 * The Audio PLL is supposed to have 4 outputs: 3 fixed factors from 46 * the base (2x, 4x and 8x), and one variable divider (the one true 47 * pll audio). 48 * 49 * We don't have any need for the variable divider for now, so we just 50 * hardcode it to match with the clock names 51 */ 52 #define SUNIV_PLL_AUDIO_REG 0x008 53 54 static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", 55 "osc24M", 0x008, 56 8, 7, /* N */ 57 0, 5, /* M */ 58 BIT(31), /* gate */ 59 BIT(28), /* lock */ 60 CLK_SET_RATE_UNGATE); 61 62 static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video_clk, "pll-video", 63 "osc24M", 0x010, 64 8, 7, /* N */ 65 0, 4, /* M */ 66 BIT(24), /* frac enable */ 67 BIT(25), /* frac select */ 68 270000000, /* frac rate 0 */ 69 297000000, /* frac rate 1 */ 70 BIT(31), /* gate */ 71 BIT(28), /* lock */ 72 CLK_SET_RATE_UNGATE); 73 74 static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve", 75 "osc24M", 0x018, 76 8, 7, /* N */ 77 0, 4, /* M */ 78 BIT(24), /* frac enable */ 79 BIT(25), /* frac select */ 80 270000000, /* frac rate 0 */ 81 297000000, /* frac rate 1 */ 82 BIT(31), /* gate */ 83 BIT(28), /* lock */ 84 CLK_SET_RATE_UNGATE); 85 86 static SUNXI_CCU_NKM_WITH_GATE_LOCK(pll_ddr0_clk, "pll-ddr", 87 "osc24M", 0x020, 88 8, 5, /* N */ 89 4, 2, /* K */ 90 0, 2, /* M */ 91 BIT(31), /* gate */ 92 BIT(28), /* lock */ 93 CLK_IS_CRITICAL); 94 95 static struct ccu_nk pll_periph_clk = { 96 .enable = BIT(31), 97 .lock = BIT(28), 98 .k = _SUNXI_CCU_MULT(4, 2), 99 .n = _SUNXI_CCU_MULT(8, 5), 100 .common = { 101 .reg = 0x028, 102 .hw.init = CLK_HW_INIT("pll-periph", "osc24M", 103 &ccu_nk_ops, 0), 104 }, 105 }; 106 107 static const char * const cpu_parents[] = { "osc32k", "osc24M", 108 "pll-cpu", "pll-cpu" }; 109 static SUNXI_CCU_MUX(cpu_clk, "cpu", cpu_parents, 110 0x050, 16, 2, CLK_IS_CRITICAL | CLK_SET_RATE_PARENT); 111 112 static const char * const ahb_parents[] = { "osc32k", "osc24M", 113 "cpu", "pll-periph" }; 114 static const struct ccu_mux_var_prediv ahb_predivs[] = { 115 { .index = 3, .shift = 6, .width = 2 }, 116 }; 117 static struct ccu_div ahb_clk = { 118 .div = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO), 119 120 .mux = { 121 .shift = 12, 122 .width = 2, 123 124 .var_predivs = ahb_predivs, 125 .n_var_predivs = ARRAY_SIZE(ahb_predivs), 126 }, 127 128 .common = { 129 .reg = 0x054, 130 .features = CCU_FEATURE_VARIABLE_PREDIV, 131 .hw.init = CLK_HW_INIT_PARENTS("ahb", 132 ahb_parents, 133 &ccu_div_ops, 134 0), 135 }, 136 }; 137 138 static struct clk_div_table apb_div_table[] = { 139 { .val = 0, .div = 2 }, 140 { .val = 1, .div = 2 }, 141 { .val = 2, .div = 4 }, 142 { .val = 3, .div = 8 }, 143 { /* Sentinel */ }, 144 }; 145 static SUNXI_CCU_DIV_TABLE(apb_clk, "apb", "ahb", 146 0x054, 8, 2, apb_div_table, 0); 147 148 static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma", "ahb", 149 0x060, BIT(6), 0); 150 static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb", 151 0x060, BIT(8), 0); 152 static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb", 153 0x060, BIT(9), 0); 154 static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram", "ahb", 155 0x060, BIT(14), 0); 156 static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb", 157 0x060, BIT(20), 0); 158 static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1", "ahb", 159 0x060, BIT(21), 0); 160 static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg", "ahb", 161 0x060, BIT(24), 0); 162 163 static SUNXI_CCU_GATE(bus_ve_clk, "bus-ve", "ahb", 164 0x064, BIT(0), 0); 165 static SUNXI_CCU_GATE(bus_lcd_clk, "bus-lcd", "ahb", 166 0x064, BIT(4), 0); 167 static SUNXI_CCU_GATE(bus_deinterlace_clk, "bus-deinterlace", "ahb", 168 0x064, BIT(5), 0); 169 static SUNXI_CCU_GATE(bus_csi_clk, "bus-csi", "ahb", 170 0x064, BIT(8), 0); 171 static SUNXI_CCU_GATE(bus_tvd_clk, "bus-tvd", "ahb", 172 0x064, BIT(9), 0); 173 static SUNXI_CCU_GATE(bus_tve_clk, "bus-tve", "ahb", 174 0x064, BIT(10), 0); 175 static SUNXI_CCU_GATE(bus_de_be_clk, "bus-de-be", "ahb", 176 0x064, BIT(12), 0); 177 static SUNXI_CCU_GATE(bus_de_fe_clk, "bus-de-fe", "ahb", 178 0x064, BIT(14), 0); 179 180 static SUNXI_CCU_GATE(bus_codec_clk, "bus-codec", "apb", 181 0x068, BIT(0), 0); 182 static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif", "apb", 183 0x068, BIT(1), 0); 184 static SUNXI_CCU_GATE(bus_ir_clk, "bus-ir", "apb", 185 0x068, BIT(2), 0); 186 static SUNXI_CCU_GATE(bus_rsb_clk, "bus-rsb", "apb", 187 0x068, BIT(3), 0); 188 static SUNXI_CCU_GATE(bus_i2s0_clk, "bus-i2s0", "apb", 189 0x068, BIT(12), 0); 190 static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb", 191 0x068, BIT(16), 0); 192 static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb", 193 0x068, BIT(17), 0); 194 static SUNXI_CCU_GATE(bus_i2c2_clk, "bus-i2c2", "apb", 195 0x068, BIT(18), 0); 196 static SUNXI_CCU_GATE(bus_pio_clk, "bus-pio", "apb", 197 0x068, BIT(19), 0); 198 static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0", "apb", 199 0x068, BIT(20), 0); 200 static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1", "apb", 201 0x068, BIT(21), 0); 202 static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2", "apb", 203 0x068, BIT(22), 0); 204 205 static const char * const mod0_default_parents[] = { "osc24M", "pll-periph" }; 206 static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mod0_default_parents, 0x088, 207 0, 4, /* M */ 208 16, 2, /* P */ 209 24, 2, /* mux */ 210 BIT(31), /* gate */ 211 0); 212 213 static SUNXI_CCU_PHASE(mmc0_sample_clk, "mmc0_sample", "mmc0", 214 0x088, 20, 3, 0); 215 static SUNXI_CCU_PHASE(mmc0_output_clk, "mmc0_output", "mmc0", 216 0x088, 8, 3, 0); 217 218 static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mod0_default_parents, 0x08c, 219 0, 4, /* M */ 220 16, 2, /* P */ 221 24, 2, /* mux */ 222 BIT(31), /* gate */ 223 0); 224 225 static SUNXI_CCU_PHASE(mmc1_sample_clk, "mmc1_sample", "mmc1", 226 0x08c, 20, 3, 0); 227 static SUNXI_CCU_PHASE(mmc1_output_clk, "mmc1_output", "mmc1", 228 0x08c, 8, 3, 0); 229 230 static const char * const i2s_spdif_parents[] = { "pll-audio-8x", 231 "pll-audio-4x", 232 "pll-audio-2x", 233 "pll-audio" }; 234 235 static SUNXI_CCU_MUX_WITH_GATE(i2s_clk, "i2s", i2s_spdif_parents, 236 0x0b0, 16, 2, BIT(31), 0); 237 238 static SUNXI_CCU_MUX_WITH_GATE(spdif_clk, "spdif", i2s_spdif_parents, 239 0x0b4, 16, 2, BIT(31), 0); 240 241 /* The BSP header file has a CIR_CFG, but no mod clock uses this definition */ 242 243 static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M", 244 0x0cc, BIT(1), 0); 245 246 static SUNXI_CCU_GATE(dram_ve_clk, "dram-ve", "pll-ddr", 247 0x100, BIT(0), 0); 248 static SUNXI_CCU_GATE(dram_csi_clk, "dram-csi", "pll-ddr", 249 0x100, BIT(1), 0); 250 static SUNXI_CCU_GATE(dram_deinterlace_clk, "dram-deinterlace", 251 "pll-ddr", 0x100, BIT(2), 0); 252 static SUNXI_CCU_GATE(dram_tvd_clk, "dram-tvd", "pll-ddr", 253 0x100, BIT(3), 0); 254 static SUNXI_CCU_GATE(dram_de_fe_clk, "dram-de-fe", "pll-ddr", 255 0x100, BIT(24), 0); 256 static SUNXI_CCU_GATE(dram_de_be_clk, "dram-de-be", "pll-ddr", 257 0x100, BIT(26), 0); 258 259 static const char * const de_parents[] = { "pll-video", "pll-periph" }; 260 static const u8 de_table[] = { 0, 2, }; 261 static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(de_be_clk, "de-be", 262 de_parents, de_table, 263 0x104, 0, 4, 24, 3, BIT(31), 0); 264 265 static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(de_fe_clk, "de-fe", 266 de_parents, de_table, 267 0x10c, 0, 4, 24, 3, BIT(31), 0); 268 269 static const char * const tcon_parents[] = { "pll-video", "pll-video-2x" }; 270 static const u8 tcon_table[] = { 0, 2, }; 271 static SUNXI_CCU_MUX_TABLE_WITH_GATE(tcon_clk, "tcon", 272 tcon_parents, tcon_table, 273 0x118, 24, 3, BIT(31), 274 CLK_SET_RATE_PARENT); 275 276 static const char * const deinterlace_parents[] = { "pll-video", 277 "pll-video-2x" }; 278 static const u8 deinterlace_table[] = { 0, 2, }; 279 static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(deinterlace_clk, "deinterlace", 280 deinterlace_parents, deinterlace_table, 281 0x11c, 0, 4, 24, 3, BIT(31), 0); 282 283 static const char * const tve_clk2_parents[] = { "pll-video", 284 "pll-video-2x" }; 285 static const u8 tve_clk2_table[] = { 0, 2, }; 286 static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(tve_clk2_clk, "tve-clk2", 287 tve_clk2_parents, tve_clk2_table, 288 0x120, 0, 4, 24, 3, BIT(31), 0); 289 static SUNXI_CCU_M_WITH_GATE(tve_clk1_clk, "tve-clk1", "tve-clk2", 290 0x120, 8, 1, BIT(15), 0); 291 292 static const char * const tvd_parents[] = { "pll-video", "osc24M", 293 "pll-video-2x" }; 294 static SUNXI_CCU_M_WITH_MUX_GATE(tvd_clk, "tvd", tvd_parents, 295 0x124, 0, 4, 24, 3, BIT(31), 0); 296 297 static const char * const csi_parents[] = { "pll-video", "osc24M" }; 298 static const u8 csi_table[] = { 0, 5, }; 299 static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi_clk, "csi", csi_parents, csi_table, 300 0x120, 0, 4, 8, 3, BIT(15), 0); 301 302 /* 303 * TODO: BSP says the parent is pll-audio, however common sense and experience 304 * told us it should be pll-ve. pll-ve is totally not used in BSP code. 305 */ 306 static SUNXI_CCU_GATE(ve_clk, "ve", "pll-audio", 0x13c, BIT(31), 0); 307 308 static SUNXI_CCU_GATE(codec_clk, "codec", "pll-audio", 0x140, BIT(31), 0); 309 310 static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", 0x144, BIT(31), 0); 311 312 static struct ccu_common *suniv_ccu_clks[] = { 313 &pll_cpu_clk.common, 314 &pll_audio_base_clk.common, 315 &pll_video_clk.common, 316 &pll_ve_clk.common, 317 &pll_ddr0_clk.common, 318 &pll_periph_clk.common, 319 &cpu_clk.common, 320 &ahb_clk.common, 321 &apb_clk.common, 322 &bus_dma_clk.common, 323 &bus_mmc0_clk.common, 324 &bus_mmc1_clk.common, 325 &bus_dram_clk.common, 326 &bus_spi0_clk.common, 327 &bus_spi1_clk.common, 328 &bus_otg_clk.common, 329 &bus_ve_clk.common, 330 &bus_lcd_clk.common, 331 &bus_deinterlace_clk.common, 332 &bus_csi_clk.common, 333 &bus_tve_clk.common, 334 &bus_tvd_clk.common, 335 &bus_de_be_clk.common, 336 &bus_de_fe_clk.common, 337 &bus_codec_clk.common, 338 &bus_spdif_clk.common, 339 &bus_ir_clk.common, 340 &bus_rsb_clk.common, 341 &bus_i2s0_clk.common, 342 &bus_i2c0_clk.common, 343 &bus_i2c1_clk.common, 344 &bus_i2c2_clk.common, 345 &bus_pio_clk.common, 346 &bus_uart0_clk.common, 347 &bus_uart1_clk.common, 348 &bus_uart2_clk.common, 349 &mmc0_clk.common, 350 &mmc0_sample_clk.common, 351 &mmc0_output_clk.common, 352 &mmc1_clk.common, 353 &mmc1_sample_clk.common, 354 &mmc1_output_clk.common, 355 &i2s_clk.common, 356 &spdif_clk.common, 357 &usb_phy0_clk.common, 358 &dram_ve_clk.common, 359 &dram_csi_clk.common, 360 &dram_deinterlace_clk.common, 361 &dram_tvd_clk.common, 362 &dram_de_fe_clk.common, 363 &dram_de_be_clk.common, 364 &de_be_clk.common, 365 &de_fe_clk.common, 366 &tcon_clk.common, 367 &deinterlace_clk.common, 368 &tve_clk2_clk.common, 369 &tve_clk1_clk.common, 370 &tvd_clk.common, 371 &csi_clk.common, 372 &ve_clk.common, 373 &codec_clk.common, 374 &avs_clk.common, 375 }; 376 377 static const struct clk_hw *clk_parent_pll_audio[] = { 378 &pll_audio_base_clk.common.hw 379 }; 380 381 static CLK_FIXED_FACTOR_HWS(pll_audio_clk, "pll-audio", 382 clk_parent_pll_audio, 383 4, 1, CLK_SET_RATE_PARENT); 384 static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x", 385 clk_parent_pll_audio, 386 2, 1, CLK_SET_RATE_PARENT); 387 static CLK_FIXED_FACTOR_HWS(pll_audio_4x_clk, "pll-audio-4x", 388 clk_parent_pll_audio, 389 1, 1, CLK_SET_RATE_PARENT); 390 static CLK_FIXED_FACTOR_HWS(pll_audio_8x_clk, "pll-audio-8x", 391 clk_parent_pll_audio, 392 1, 2, CLK_SET_RATE_PARENT); 393 static CLK_FIXED_FACTOR_HW(pll_video_2x_clk, "pll-video-2x", 394 &pll_video_clk.common.hw, 395 1, 2, 0); 396 397 static struct clk_hw_onecell_data suniv_hw_clks = { 398 .hws = { 399 [CLK_PLL_CPU] = &pll_cpu_clk.common.hw, 400 [CLK_PLL_AUDIO_BASE] = &pll_audio_base_clk.common.hw, 401 [CLK_PLL_AUDIO] = &pll_audio_clk.hw, 402 [CLK_PLL_AUDIO_2X] = &pll_audio_2x_clk.hw, 403 [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.hw, 404 [CLK_PLL_AUDIO_8X] = &pll_audio_8x_clk.hw, 405 [CLK_PLL_VIDEO] = &pll_video_clk.common.hw, 406 [CLK_PLL_VIDEO_2X] = &pll_video_2x_clk.hw, 407 [CLK_PLL_VE] = &pll_ve_clk.common.hw, 408 [CLK_PLL_DDR0] = &pll_ddr0_clk.common.hw, 409 [CLK_PLL_PERIPH] = &pll_periph_clk.common.hw, 410 [CLK_CPU] = &cpu_clk.common.hw, 411 [CLK_AHB] = &ahb_clk.common.hw, 412 [CLK_APB] = &apb_clk.common.hw, 413 [CLK_BUS_DMA] = &bus_dma_clk.common.hw, 414 [CLK_BUS_MMC0] = &bus_mmc0_clk.common.hw, 415 [CLK_BUS_MMC1] = &bus_mmc1_clk.common.hw, 416 [CLK_BUS_DRAM] = &bus_dram_clk.common.hw, 417 [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw, 418 [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw, 419 [CLK_BUS_OTG] = &bus_otg_clk.common.hw, 420 [CLK_BUS_VE] = &bus_ve_clk.common.hw, 421 [CLK_BUS_LCD] = &bus_lcd_clk.common.hw, 422 [CLK_BUS_DEINTERLACE] = &bus_deinterlace_clk.common.hw, 423 [CLK_BUS_CSI] = &bus_csi_clk.common.hw, 424 [CLK_BUS_TVD] = &bus_tvd_clk.common.hw, 425 [CLK_BUS_TVE] = &bus_tve_clk.common.hw, 426 [CLK_BUS_DE_BE] = &bus_de_be_clk.common.hw, 427 [CLK_BUS_DE_FE] = &bus_de_fe_clk.common.hw, 428 [CLK_BUS_CODEC] = &bus_codec_clk.common.hw, 429 [CLK_BUS_SPDIF] = &bus_spdif_clk.common.hw, 430 [CLK_BUS_IR] = &bus_ir_clk.common.hw, 431 [CLK_BUS_RSB] = &bus_rsb_clk.common.hw, 432 [CLK_BUS_I2S0] = &bus_i2s0_clk.common.hw, 433 [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw, 434 [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw, 435 [CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw, 436 [CLK_BUS_PIO] = &bus_pio_clk.common.hw, 437 [CLK_BUS_UART0] = &bus_uart0_clk.common.hw, 438 [CLK_BUS_UART1] = &bus_uart1_clk.common.hw, 439 [CLK_BUS_UART2] = &bus_uart2_clk.common.hw, 440 [CLK_MMC0] = &mmc0_clk.common.hw, 441 [CLK_MMC0_SAMPLE] = &mmc0_sample_clk.common.hw, 442 [CLK_MMC0_OUTPUT] = &mmc0_output_clk.common.hw, 443 [CLK_MMC1] = &mmc1_clk.common.hw, 444 [CLK_MMC1_SAMPLE] = &mmc1_sample_clk.common.hw, 445 [CLK_MMC1_OUTPUT] = &mmc1_output_clk.common.hw, 446 [CLK_I2S] = &i2s_clk.common.hw, 447 [CLK_SPDIF] = &spdif_clk.common.hw, 448 [CLK_USB_PHY0] = &usb_phy0_clk.common.hw, 449 [CLK_DRAM_VE] = &dram_ve_clk.common.hw, 450 [CLK_DRAM_CSI] = &dram_csi_clk.common.hw, 451 [CLK_DRAM_DEINTERLACE] = &dram_deinterlace_clk.common.hw, 452 [CLK_DRAM_TVD] = &dram_tvd_clk.common.hw, 453 [CLK_DRAM_DE_FE] = &dram_de_fe_clk.common.hw, 454 [CLK_DRAM_DE_BE] = &dram_de_be_clk.common.hw, 455 [CLK_DE_BE] = &de_be_clk.common.hw, 456 [CLK_DE_FE] = &de_fe_clk.common.hw, 457 [CLK_TCON] = &tcon_clk.common.hw, 458 [CLK_DEINTERLACE] = &deinterlace_clk.common.hw, 459 [CLK_TVE2_CLK] = &tve_clk2_clk.common.hw, 460 [CLK_TVE1_CLK] = &tve_clk1_clk.common.hw, 461 [CLK_TVD] = &tvd_clk.common.hw, 462 [CLK_CSI] = &csi_clk.common.hw, 463 [CLK_VE] = &ve_clk.common.hw, 464 [CLK_CODEC] = &codec_clk.common.hw, 465 [CLK_AVS] = &avs_clk.common.hw, 466 }, 467 .num = CLK_NUMBER, 468 }; 469 470 static struct ccu_reset_map suniv_ccu_resets[] = { 471 [RST_USB_PHY0] = { 0x0cc, BIT(0) }, 472 473 [RST_BUS_DMA] = { 0x2c0, BIT(6) }, 474 [RST_BUS_MMC0] = { 0x2c0, BIT(8) }, 475 [RST_BUS_MMC1] = { 0x2c0, BIT(9) }, 476 [RST_BUS_DRAM] = { 0x2c0, BIT(14) }, 477 [RST_BUS_SPI0] = { 0x2c0, BIT(20) }, 478 [RST_BUS_SPI1] = { 0x2c0, BIT(21) }, 479 [RST_BUS_OTG] = { 0x2c0, BIT(24) }, 480 [RST_BUS_VE] = { 0x2c4, BIT(0) }, 481 [RST_BUS_LCD] = { 0x2c4, BIT(4) }, 482 [RST_BUS_DEINTERLACE] = { 0x2c4, BIT(5) }, 483 [RST_BUS_CSI] = { 0x2c4, BIT(8) }, 484 [RST_BUS_TVD] = { 0x2c4, BIT(9) }, 485 [RST_BUS_TVE] = { 0x2c4, BIT(10) }, 486 [RST_BUS_DE_BE] = { 0x2c4, BIT(12) }, 487 [RST_BUS_DE_FE] = { 0x2c4, BIT(14) }, 488 [RST_BUS_CODEC] = { 0x2d0, BIT(0) }, 489 [RST_BUS_SPDIF] = { 0x2d0, BIT(1) }, 490 [RST_BUS_IR] = { 0x2d0, BIT(2) }, 491 [RST_BUS_RSB] = { 0x2d0, BIT(3) }, 492 [RST_BUS_I2S0] = { 0x2d0, BIT(12) }, 493 [RST_BUS_I2C0] = { 0x2d0, BIT(16) }, 494 [RST_BUS_I2C1] = { 0x2d0, BIT(17) }, 495 [RST_BUS_I2C2] = { 0x2d0, BIT(18) }, 496 [RST_BUS_UART0] = { 0x2d0, BIT(20) }, 497 [RST_BUS_UART1] = { 0x2d0, BIT(21) }, 498 [RST_BUS_UART2] = { 0x2d0, BIT(22) }, 499 }; 500 501 static const struct sunxi_ccu_desc suniv_ccu_desc = { 502 .ccu_clks = suniv_ccu_clks, 503 .num_ccu_clks = ARRAY_SIZE(suniv_ccu_clks), 504 505 .hw_clks = &suniv_hw_clks, 506 507 .resets = suniv_ccu_resets, 508 .num_resets = ARRAY_SIZE(suniv_ccu_resets), 509 }; 510 511 static struct ccu_pll_nb suniv_pll_cpu_nb = { 512 .common = &pll_cpu_clk.common, 513 /* copy from pll_cpu_clk */ 514 .enable = BIT(31), 515 .lock = BIT(28), 516 }; 517 518 static struct ccu_mux_nb suniv_cpu_nb = { 519 .common = &cpu_clk.common, 520 .cm = &cpu_clk.mux, 521 .delay_us = 1, /* > 8 clock cycles at 24 MHz */ 522 .bypass_index = 1, /* index of 24 MHz oscillator */ 523 }; 524 525 static void __init suniv_f1c100s_ccu_setup(struct device_node *node) 526 { 527 void __iomem *reg; 528 u32 val; 529 530 reg = of_io_request_and_map(node, 0, of_node_full_name(node)); 531 if (IS_ERR(reg)) { 532 pr_err("%pOF: Could not map the clock registers\n", node); 533 return; 534 } 535 536 /* Force the PLL-Audio-1x divider to 4 */ 537 val = readl(reg + SUNIV_PLL_AUDIO_REG); 538 val &= ~GENMASK(19, 16); 539 writel(val | (3 << 16), reg + SUNIV_PLL_AUDIO_REG); 540 541 of_sunxi_ccu_probe(node, reg, &suniv_ccu_desc); 542 543 /* Gate then ungate PLL CPU after any rate changes */ 544 ccu_pll_notifier_register(&suniv_pll_cpu_nb); 545 546 /* Reparent CPU during PLL CPU rate changes */ 547 ccu_mux_notifier_register(pll_cpu_clk.common.hw.clk, 548 &suniv_cpu_nb); 549 } 550 CLK_OF_DECLARE(suniv_f1c100s_ccu, "allwinner,suniv-f1c100s-ccu", 551 suniv_f1c100s_ccu_setup); 552