Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: sophgo: Add clock support for CV1800 SoC

Add clock definition and driver code for CV1800 SoC.

Signed-off-by: Inochi Amaoto <inochiama@outlook.com>
Link: https://github.com/milkv-duo/duo-files/blob/6f4e9b8ecb459e017cca1a8df248a19ca70837a3/duo/datasheet/CV180X-Clock-v1.xlsx
Link: https://github.com/milkv-duo/duo-files/blob/6f4e9b8ecb459e017cca1a8df248a19ca70837a3/duo/datasheet/CV1800B-CV1801B-Preliminary-Datasheet-full-en.pdf
Link: https://lore.kernel.org/r/IA1PR20MB49534F37F802CAF117364D66BB262@IA1PR20MB4953.namprd20.prod.outlook.com
Signed-off-by: Stephen Boyd <sboyd@kernel.org>

authored by

Inochi Amaoto and committed by
Stephen Boyd
80fd61ec 50e45d3b

+3302
+1
drivers/clk/Kconfig
··· 489 489 source "drivers/clk/samsung/Kconfig" 490 490 source "drivers/clk/sifive/Kconfig" 491 491 source "drivers/clk/socfpga/Kconfig" 492 + source "drivers/clk/sophgo/Kconfig" 492 493 source "drivers/clk/sprd/Kconfig" 493 494 source "drivers/clk/starfive/Kconfig" 494 495 source "drivers/clk/sunxi/Kconfig"
+1
drivers/clk/Makefile
··· 118 118 obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/ 119 119 obj-$(CONFIG_CLK_SIFIVE) += sifive/ 120 120 obj-y += socfpga/ 121 + obj-y += sophgo/ 121 122 obj-$(CONFIG_PLAT_SPEAR) += spear/ 122 123 obj-y += sprd/ 123 124 obj-$(CONFIG_ARCH_STI) += st/
+11
drivers/clk/sophgo/Kconfig
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + # common clock support for SOPHGO SoC family. 3 + 4 + config CLK_SOPHGO_CV1800 5 + tristate "Support for the Sophgo CV1800 series SoCs clock controller" 6 + depends on ARCH_SOPHGO || COMPILE_TEST 7 + help 8 + This driver supports clock controller of Sophgo CV18XX series SoC. 9 + The driver require a 25MHz Oscillator to function generate clock. 10 + It includes PLLs, common clock function and some vendor clock for 11 + IPs of CV18XX series SoC
+7
drivers/clk/sophgo/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + obj-$(CONFIG_CLK_SOPHGO_CV1800) += clk-sophgo-cv1800.o 3 + 4 + clk-sophgo-cv1800-y += clk-cv1800.o 5 + clk-sophgo-cv1800-y += clk-cv18xx-common.o 6 + clk-sophgo-cv1800-y += clk-cv18xx-ip.o 7 + clk-sophgo-cv1800-y += clk-cv18xx-pll.o
+1327
drivers/clk/sophgo/clk-cv1800.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (C) 2023 Inochi Amaoto <inochiama@outlook.com> 4 + */ 5 + 6 + #include <linux/module.h> 7 + #include <linux/clk-provider.h> 8 + #include <linux/platform_device.h> 9 + #include <linux/io.h> 10 + #include <linux/spinlock.h> 11 + 12 + #include "clk-cv1800.h" 13 + 14 + #include "clk-cv18xx-common.h" 15 + #include "clk-cv18xx-ip.h" 16 + #include "clk-cv18xx-pll.h" 17 + 18 + struct cv1800_clk_ctrl; 19 + 20 + struct cv1800_clk_desc { 21 + struct clk_hw_onecell_data *clks_data; 22 + 23 + int (*pre_init)(struct device *dev, void __iomem *base, 24 + struct cv1800_clk_ctrl *ctrl, 25 + const struct cv1800_clk_desc *desc); 26 + }; 27 + 28 + struct cv1800_clk_ctrl { 29 + const struct cv1800_clk_desc *desc; 30 + spinlock_t lock; 31 + }; 32 + 33 + #define CV1800_DIV_FLAG \ 34 + (CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ROUND_CLOSEST) 35 + static const struct clk_parent_data osc_parents[] = { 36 + { .index = 0 }, 37 + }; 38 + 39 + static const struct cv1800_clk_pll_limit pll_limits[] = { 40 + { 41 + .pre_div = _CV1800_PLL_LIMIT(1, 127), 42 + .div = _CV1800_PLL_LIMIT(6, 127), 43 + .post_div = _CV1800_PLL_LIMIT(1, 127), 44 + .ictrl = _CV1800_PLL_LIMIT(0, 7), 45 + .mode = _CV1800_PLL_LIMIT(0, 3), 46 + }, 47 + { 48 + .pre_div = _CV1800_PLL_LIMIT(1, 127), 49 + .div = _CV1800_PLL_LIMIT(6, 127), 50 + .post_div = _CV1800_PLL_LIMIT(1, 127), 51 + .ictrl = _CV1800_PLL_LIMIT(0, 7), 52 + .mode = _CV1800_PLL_LIMIT(0, 3), 53 + }, 54 + }; 55 + 56 + static CV1800_INTEGRAL_PLL(clk_fpll, osc_parents, 57 + REG_FPLL_CSR, 58 + REG_PLL_G6_CTRL, 8, 59 + REG_PLL_G6_STATUS, 2, 60 + pll_limits, 61 + CLK_IS_CRITICAL); 62 + 63 + static CV1800_INTEGRAL_PLL(clk_mipimpll, osc_parents, 64 + REG_MIPIMPLL_CSR, 65 + REG_PLL_G2_CTRL, 0, 66 + REG_PLL_G2_STATUS, 0, 67 + pll_limits, 68 + CLK_IS_CRITICAL); 69 + 70 + static const struct clk_parent_data clk_mipimpll_parents[] = { 71 + { .hw = &clk_mipimpll.common.hw }, 72 + }; 73 + static const struct clk_parent_data clk_bypass_mipimpll_parents[] = { 74 + { .index = 0 }, 75 + { .hw = &clk_mipimpll.common.hw }, 76 + }; 77 + static const struct clk_parent_data clk_bypass_fpll_parents[] = { 78 + { .index = 0 }, 79 + { .hw = &clk_fpll.common.hw }, 80 + }; 81 + 82 + struct cv1800_clk_pll_synthesizer clk_mpll_synthesizer = { 83 + .en = CV1800_CLK_BIT(REG_PLL_G6_SSC_SYN_CTRL, 2), 84 + .clk_half = CV1800_CLK_BIT(REG_PLL_G6_SSC_SYN_CTRL, 0), 85 + .ctrl = REG_MPLL_SSC_SYN_CTRL, 86 + .set = REG_MPLL_SSC_SYN_SET, 87 + }; 88 + static CV1800_FACTIONAL_PLL(clk_mpll, clk_bypass_mipimpll_parents, 89 + REG_MPLL_CSR, 90 + REG_PLL_G6_CTRL, 0, 91 + REG_PLL_G6_STATUS, 0, 92 + pll_limits, 93 + &clk_mpll_synthesizer, 94 + CLK_IS_CRITICAL); 95 + 96 + struct cv1800_clk_pll_synthesizer clk_tpll_synthesizer = { 97 + .en = CV1800_CLK_BIT(REG_PLL_G6_SSC_SYN_CTRL, 3), 98 + .clk_half = CV1800_CLK_BIT(REG_PLL_G6_SSC_SYN_CTRL, 0), 99 + .ctrl = REG_TPLL_SSC_SYN_CTRL, 100 + .set = REG_TPLL_SSC_SYN_SET, 101 + }; 102 + static CV1800_FACTIONAL_PLL(clk_tpll, clk_bypass_mipimpll_parents, 103 + REG_TPLL_CSR, 104 + REG_PLL_G6_CTRL, 4, 105 + REG_PLL_G6_STATUS, 1, 106 + pll_limits, 107 + &clk_tpll_synthesizer, 108 + CLK_IS_CRITICAL); 109 + 110 + struct cv1800_clk_pll_synthesizer clk_a0pll_synthesizer = { 111 + .en = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 2), 112 + .clk_half = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 0), 113 + .ctrl = REG_A0PLL_SSC_SYN_CTRL, 114 + .set = REG_A0PLL_SSC_SYN_SET, 115 + }; 116 + static CV1800_FACTIONAL_PLL(clk_a0pll, clk_bypass_mipimpll_parents, 117 + REG_A0PLL_CSR, 118 + REG_PLL_G2_CTRL, 4, 119 + REG_PLL_G2_STATUS, 1, 120 + pll_limits, 121 + &clk_a0pll_synthesizer, 122 + CLK_IS_CRITICAL); 123 + 124 + struct cv1800_clk_pll_synthesizer clk_disppll_synthesizer = { 125 + .en = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 3), 126 + .clk_half = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 0), 127 + .ctrl = REG_DISPPLL_SSC_SYN_CTRL, 128 + .set = REG_DISPPLL_SSC_SYN_SET, 129 + }; 130 + static CV1800_FACTIONAL_PLL(clk_disppll, clk_bypass_mipimpll_parents, 131 + REG_DISPPLL_CSR, 132 + REG_PLL_G2_CTRL, 8, 133 + REG_PLL_G2_STATUS, 2, 134 + pll_limits, 135 + &clk_disppll_synthesizer, 136 + CLK_IS_CRITICAL); 137 + 138 + struct cv1800_clk_pll_synthesizer clk_cam0pll_synthesizer = { 139 + .en = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 4), 140 + .clk_half = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 0), 141 + .ctrl = REG_CAM0PLL_SSC_SYN_CTRL, 142 + .set = REG_CAM0PLL_SSC_SYN_SET, 143 + }; 144 + static CV1800_FACTIONAL_PLL(clk_cam0pll, clk_bypass_mipimpll_parents, 145 + REG_CAM0PLL_CSR, 146 + REG_PLL_G2_CTRL, 12, 147 + REG_PLL_G2_STATUS, 3, 148 + pll_limits, 149 + &clk_cam0pll_synthesizer, 150 + CLK_IGNORE_UNUSED); 151 + 152 + struct cv1800_clk_pll_synthesizer clk_cam1pll_synthesizer = { 153 + .en = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 5), 154 + .clk_half = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 0), 155 + .ctrl = REG_CAM1PLL_SSC_SYN_CTRL, 156 + .set = REG_CAM1PLL_SSC_SYN_SET, 157 + }; 158 + static CV1800_FACTIONAL_PLL(clk_cam1pll, clk_bypass_mipimpll_parents, 159 + REG_CAM1PLL_CSR, 160 + REG_PLL_G2_CTRL, 16, 161 + REG_PLL_G2_STATUS, 4, 162 + pll_limits, 163 + &clk_cam1pll_synthesizer, 164 + CLK_IS_CRITICAL); 165 + 166 + static const struct clk_parent_data clk_cam0pll_parents[] = { 167 + { .hw = &clk_cam0pll.common.hw }, 168 + }; 169 + 170 + /* G2D */ 171 + static CV1800_FIXED_DIV(clk_cam0pll_d2, clk_cam0pll_parents, 172 + REG_CAM0PLL_CLK_CSR, 1, 173 + 2, 174 + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED); 175 + static CV1800_FIXED_DIV(clk_cam0pll_d3, clk_cam0pll_parents, 176 + REG_CAM0PLL_CLK_CSR, 2, 177 + 3, 178 + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED); 179 + static CV1800_FIXED_DIV(clk_mipimpll_d3, clk_mipimpll_parents, 180 + REG_MIPIMPLL_CLK_CSR, 2, 181 + 3, 182 + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED); 183 + 184 + /* TPU */ 185 + static const struct clk_parent_data clk_tpu_parents[] = { 186 + { .index = 0 }, 187 + { .hw = &clk_tpll.common.hw }, 188 + { .hw = &clk_a0pll.common.hw }, 189 + { .hw = &clk_mipimpll.common.hw }, 190 + { .hw = &clk_fpll.common.hw }, 191 + }; 192 + 193 + static CV1800_BYPASS_MUX(clk_tpu, clk_tpu_parents, 194 + REG_CLK_EN_0, 4, 195 + REG_DIV_CLK_TPU, 16, 4, 3, CV1800_DIV_FLAG, 196 + REG_DIV_CLK_TPU, 8, 2, 197 + REG_CLK_BYP_0, 3, 198 + 0); 199 + static CV1800_GATE(clk_tpu_fab, clk_mipimpll_parents, 200 + REG_CLK_EN_0, 5, 201 + 0); 202 + 203 + /* FABRIC_AXI6 */ 204 + static CV1800_BYPASS_DIV(clk_axi6, clk_bypass_fpll_parents, 205 + REG_CLK_EN_2, 2, 206 + REG_DIV_CLK_AXI6, 16, 4, 15, CV1800_DIV_FLAG, 207 + REG_CLK_BYP_0, 20, 208 + CLK_IS_CRITICAL); 209 + 210 + static const struct clk_parent_data clk_axi6_bus_parents[] = { 211 + { .hw = &clk_axi6.div.common.hw }, 212 + }; 213 + static const struct clk_parent_data clk_bypass_axi6_bus_parents[] = { 214 + { .index = 0 }, 215 + { .hw = &clk_axi6.div.common.hw }, 216 + }; 217 + 218 + /* FABRIC_AXI4 */ 219 + static const struct clk_parent_data clk_axi4_parents[] = { 220 + { .index = 0 }, 221 + { .hw = &clk_fpll.common.hw }, 222 + { .hw = &clk_disppll.common.hw }, 223 + }; 224 + 225 + static CV1800_BYPASS_MUX(clk_axi4, clk_axi4_parents, 226 + REG_CLK_EN_2, 1, 227 + REG_DIV_CLK_AXI4, 16, 4, 5, CV1800_DIV_FLAG, 228 + REG_DIV_CLK_AXI4, 8, 2, 229 + REG_CLK_BYP_0, 19, 230 + CLK_IS_CRITICAL); 231 + 232 + static const struct clk_parent_data clk_axi4_bus_parents[] = { 233 + { .hw = &clk_axi4.mux.common.hw }, 234 + }; 235 + 236 + /* XTAL_MISC */ 237 + static CV1800_GATE(clk_xtal_misc, osc_parents, 238 + REG_CLK_EN_0, 14, 239 + CLK_IS_CRITICAL); 240 + 241 + static const struct clk_parent_data clk_timer_parents[] = { 242 + { .hw = &clk_xtal_misc.common.hw }, 243 + }; 244 + 245 + /* TOP */ 246 + static const struct clk_parent_data clk_cam0_200_parents[] = { 247 + { .index = 0 }, 248 + { .index = 0 }, 249 + { .hw = &clk_disppll.common.hw }, 250 + }; 251 + 252 + static CV1800_BYPASS_MUX(clk_cam0_200, clk_cam0_200_parents, 253 + REG_CLK_EN_1, 13, 254 + REG_DIV_CLK_CAM0_200, 16, 4, 1, CV1800_DIV_FLAG, 255 + REG_DIV_CLK_CAM0_200, 8, 2, 256 + REG_CLK_BYP_0, 16, 257 + CLK_IS_CRITICAL); 258 + static CV1800_DIV(clk_1m, osc_parents, 259 + REG_CLK_EN_3, 5, 260 + REG_DIV_CLK_1M, 16, 6, 25, CV1800_DIV_FLAG, 261 + CLK_IS_CRITICAL); 262 + static CV1800_GATE(clk_pm, clk_axi6_bus_parents, 263 + REG_CLK_EN_3, 8, 264 + CLK_IS_CRITICAL); 265 + static CV1800_GATE(clk_timer0, clk_timer_parents, 266 + REG_CLK_EN_3, 9, 267 + CLK_IS_CRITICAL); 268 + static CV1800_GATE(clk_timer1, clk_timer_parents, 269 + REG_CLK_EN_3, 10, 270 + CLK_IS_CRITICAL); 271 + static CV1800_GATE(clk_timer2, clk_timer_parents, 272 + REG_CLK_EN_3, 11, 273 + CLK_IS_CRITICAL); 274 + static CV1800_GATE(clk_timer3, clk_timer_parents, 275 + REG_CLK_EN_3, 12, 276 + CLK_IS_CRITICAL); 277 + static CV1800_GATE(clk_timer4, clk_timer_parents, 278 + REG_CLK_EN_3, 13, 279 + CLK_IS_CRITICAL); 280 + static CV1800_GATE(clk_timer5, clk_timer_parents, 281 + REG_CLK_EN_3, 14, 282 + CLK_IS_CRITICAL); 283 + static CV1800_GATE(clk_timer6, clk_timer_parents, 284 + REG_CLK_EN_3, 15, 285 + CLK_IS_CRITICAL); 286 + static CV1800_GATE(clk_timer7, clk_timer_parents, 287 + REG_CLK_EN_3, 16, 288 + CLK_IS_CRITICAL); 289 + 290 + static const struct clk_parent_data clk_parents_1m[] = { 291 + { .hw = &clk_1m.common.hw }, 292 + }; 293 + static const struct clk_parent_data clk_uart_parents[] = { 294 + { .hw = &clk_cam0_200.mux.common.hw }, 295 + }; 296 + 297 + /* AHB ROM */ 298 + static CV1800_GATE(clk_ahb_rom, clk_axi4_bus_parents, 299 + REG_CLK_EN_0, 6, 300 + 0); 301 + 302 + /* RTC */ 303 + static CV1800_GATE(clk_rtc_25m, osc_parents, 304 + REG_CLK_EN_0, 8, 305 + CLK_IS_CRITICAL); 306 + static CV1800_BYPASS_DIV(clk_src_rtc_sys_0, clk_bypass_fpll_parents, 307 + REG_CLK_EN_4, 6, 308 + REG_DIV_CLK_RTCSYS_SRC_0, 16, 4, 5, CV1800_DIV_FLAG, 309 + REG_CLK_BYP_1, 5, 310 + CLK_IS_CRITICAL); 311 + 312 + /* TEMPSEN */ 313 + static CV1800_GATE(clk_tempsen, osc_parents, 314 + REG_CLK_EN_0, 9, 315 + 0); 316 + 317 + /* SARADC */ 318 + static CV1800_GATE(clk_saradc, osc_parents, 319 + REG_CLK_EN_0, 10, 320 + 0); 321 + 322 + /* EFUSE */ 323 + static CV1800_GATE(clk_efuse, osc_parents, 324 + REG_CLK_EN_0, 11, 325 + 0); 326 + static CV1800_GATE(clk_apb_efuse, osc_parents, 327 + REG_CLK_EN_0, 12, 328 + 0); 329 + 330 + /* WDT */ 331 + static CV1800_GATE(clk_apb_wdt, osc_parents, 332 + REG_CLK_EN_1, 7, 333 + CLK_IS_CRITICAL); 334 + 335 + /* WGN */ 336 + static CV1800_GATE(clk_wgn, osc_parents, 337 + REG_CLK_EN_3, 22, 338 + 0); 339 + static CV1800_GATE(clk_wgn0, osc_parents, 340 + REG_CLK_EN_3, 23, 341 + 0); 342 + static CV1800_GATE(clk_wgn1, osc_parents, 343 + REG_CLK_EN_3, 24, 344 + 0); 345 + static CV1800_GATE(clk_wgn2, osc_parents, 346 + REG_CLK_EN_3, 25, 347 + 0); 348 + 349 + /* KEYSCAN */ 350 + static CV1800_GATE(clk_keyscan, osc_parents, 351 + REG_CLK_EN_3, 26, 352 + 0); 353 + 354 + /* EMMC */ 355 + static CV1800_GATE(clk_axi4_emmc, clk_axi4_bus_parents, 356 + REG_CLK_EN_0, 15, 357 + 0); 358 + static CV1800_BYPASS_MUX(clk_emmc, clk_axi4_parents, 359 + REG_CLK_EN_0, 16, 360 + REG_DIV_CLK_EMMC, 16, 5, 15, CV1800_DIV_FLAG, 361 + REG_DIV_CLK_EMMC, 8, 2, 362 + REG_CLK_BYP_0, 5, 363 + 0); 364 + static CV1800_DIV(clk_emmc_100k, clk_parents_1m, 365 + REG_CLK_EN_0, 17, 366 + REG_DIV_CLK_EMMC_100K, 16, 8, 10, CV1800_DIV_FLAG, 367 + 0); 368 + 369 + /* SD */ 370 + static CV1800_GATE(clk_axi4_sd0, clk_axi4_bus_parents, 371 + REG_CLK_EN_0, 18, 372 + 0); 373 + static CV1800_BYPASS_MUX(clk_sd0, clk_axi4_parents, 374 + REG_CLK_EN_0, 19, 375 + REG_DIV_CLK_SD0, 16, 5, 15, CV1800_DIV_FLAG, 376 + REG_DIV_CLK_SD0, 8, 2, 377 + REG_CLK_BYP_0, 6, 378 + 0); 379 + static CV1800_DIV(clk_sd0_100k, clk_parents_1m, 380 + REG_CLK_EN_0, 20, 381 + REG_DIV_CLK_SD0_100K, 16, 8, 10, CV1800_DIV_FLAG, 382 + 0); 383 + static CV1800_GATE(clk_axi4_sd1, clk_axi4_bus_parents, 384 + REG_CLK_EN_0, 21, 385 + 0); 386 + static CV1800_BYPASS_MUX(clk_sd1, clk_axi4_parents, 387 + REG_CLK_EN_0, 22, 388 + REG_DIV_CLK_SD1, 16, 5, 15, CV1800_DIV_FLAG, 389 + REG_DIV_CLK_SD1, 8, 2, 390 + REG_CLK_BYP_0, 7, 391 + 0); 392 + static CV1800_DIV(clk_sd1_100k, clk_parents_1m, 393 + REG_CLK_EN_0, 23, 394 + REG_DIV_CLK_SD1_100K, 16, 8, 10, CV1800_DIV_FLAG, 395 + 0); 396 + 397 + /* SPI NAND */ 398 + static CV1800_BYPASS_MUX(clk_spi_nand, clk_axi4_parents, 399 + REG_CLK_EN_0, 24, 400 + REG_DIV_CLK_SPI_NAND, 16, 5, 8, CV1800_DIV_FLAG, 401 + REG_DIV_CLK_SPI_NAND, 8, 2, 402 + REG_CLK_BYP_0, 8, 403 + 0); 404 + 405 + /* GPIO */ 406 + static CV1800_DIV(clk_gpio_db, clk_parents_1m, 407 + REG_CLK_EN_0, 31, 408 + REG_DIV_CLK_GPIO_DB, 16, 16, 10, CV1800_DIV_FLAG, 409 + CLK_IS_CRITICAL); 410 + static CV1800_GATE(clk_apb_gpio, clk_axi6_bus_parents, 411 + REG_CLK_EN_0, 29, 412 + CLK_IS_CRITICAL); 413 + static CV1800_GATE(clk_apb_gpio_intr, clk_axi6_bus_parents, 414 + REG_CLK_EN_0, 30, 415 + CLK_IS_CRITICAL); 416 + 417 + /* ETH */ 418 + static CV1800_BYPASS_DIV(clk_eth0_500m, clk_bypass_fpll_parents, 419 + REG_CLK_EN_0, 25, 420 + REG_DIV_CLK_GPIO_DB, 16, 4, 3, CV1800_DIV_FLAG, 421 + REG_CLK_BYP_0, 9, 422 + 0); 423 + static CV1800_GATE(clk_axi4_eth0, clk_axi4_bus_parents, 424 + REG_CLK_EN_0, 26, 425 + 0); 426 + static CV1800_BYPASS_DIV(clk_eth1_500m, clk_bypass_fpll_parents, 427 + REG_CLK_EN_0, 27, 428 + REG_DIV_CLK_GPIO_DB, 16, 4, 3, CV1800_DIV_FLAG, 429 + REG_CLK_BYP_0, 10, 430 + 0); 431 + static CV1800_GATE(clk_axi4_eth1, clk_axi4_bus_parents, 432 + REG_CLK_EN_0, 28, 433 + 0); 434 + 435 + /* SF */ 436 + static CV1800_GATE(clk_ahb_sf, clk_axi4_bus_parents, 437 + REG_CLK_EN_1, 0, 438 + 0); 439 + static CV1800_GATE(clk_ahb_sf1, clk_axi4_bus_parents, 440 + REG_CLK_EN_3, 27, 441 + 0); 442 + 443 + /* AUDSRC */ 444 + static CV1800_ACLK(clk_a24m, clk_mipimpll_parents, 445 + REG_APLL_FRAC_DIV_CTRL, 0, 446 + REG_APLL_FRAC_DIV_CTRL, 3, 447 + REG_APLL_FRAC_DIV_CTRL, 1, 448 + REG_APLL_FRAC_DIV_CTRL, 2, 449 + REG_APLL_FRAC_DIV_M, 0, 22, CV1800_DIV_FLAG, 450 + REG_APLL_FRAC_DIV_N, 0, 22, CV1800_DIV_FLAG, 451 + 24576000, 452 + 0); 453 + 454 + static const struct clk_parent_data clk_aud_parents[] = { 455 + { .index = 0 }, 456 + { .hw = &clk_a0pll.common.hw }, 457 + { .hw = &clk_a24m.common.hw }, 458 + }; 459 + 460 + static CV1800_BYPASS_MUX(clk_audsrc, clk_aud_parents, 461 + REG_CLK_EN_4, 1, 462 + REG_DIV_CLK_AUDSRC, 16, 8, 18, CV1800_DIV_FLAG, 463 + REG_DIV_CLK_AUDSRC, 8, 2, 464 + REG_CLK_BYP_1, 2, 465 + 0); 466 + static CV1800_GATE(clk_apb_audsrc, clk_axi4_bus_parents, 467 + REG_CLK_EN_4, 2, 468 + 0); 469 + 470 + /* SDMA */ 471 + static CV1800_GATE(clk_sdma_axi, clk_axi4_bus_parents, 472 + REG_CLK_EN_1, 1, 473 + 0); 474 + static CV1800_BYPASS_MUX(clk_sdma_aud0, clk_aud_parents, 475 + REG_CLK_EN_1, 2, 476 + REG_DIV_CLK_SDMA_AUD0, 16, 8, 18, CV1800_DIV_FLAG, 477 + REG_DIV_CLK_SDMA_AUD0, 8, 2, 478 + REG_CLK_BYP_0, 11, 479 + 0); 480 + static CV1800_BYPASS_MUX(clk_sdma_aud1, clk_aud_parents, 481 + REG_CLK_EN_1, 3, 482 + REG_DIV_CLK_SDMA_AUD1, 16, 8, 18, CV1800_DIV_FLAG, 483 + REG_DIV_CLK_SDMA_AUD1, 8, 2, 484 + REG_CLK_BYP_0, 12, 485 + 0); 486 + static CV1800_BYPASS_MUX(clk_sdma_aud2, clk_aud_parents, 487 + REG_CLK_EN_1, 3, 488 + REG_DIV_CLK_SDMA_AUD2, 16, 8, 18, CV1800_DIV_FLAG, 489 + REG_DIV_CLK_SDMA_AUD2, 8, 2, 490 + REG_CLK_BYP_0, 13, 491 + 0); 492 + static CV1800_BYPASS_MUX(clk_sdma_aud3, clk_aud_parents, 493 + REG_CLK_EN_1, 3, 494 + REG_DIV_CLK_SDMA_AUD3, 16, 8, 18, CV1800_DIV_FLAG, 495 + REG_DIV_CLK_SDMA_AUD3, 8, 2, 496 + REG_CLK_BYP_0, 14, 497 + 0); 498 + 499 + /* SPI */ 500 + static CV1800_GATE(clk_apb_spi0, clk_axi4_bus_parents, 501 + REG_CLK_EN_1, 9, 502 + 0); 503 + static CV1800_GATE(clk_apb_spi1, clk_axi4_bus_parents, 504 + REG_CLK_EN_1, 10, 505 + 0); 506 + static CV1800_GATE(clk_apb_spi2, clk_axi4_bus_parents, 507 + REG_CLK_EN_1, 11, 508 + 0); 509 + static CV1800_GATE(clk_apb_spi3, clk_axi4_bus_parents, 510 + REG_CLK_EN_1, 12, 511 + 0); 512 + static CV1800_BYPASS_DIV(clk_spi, clk_bypass_fpll_parents, 513 + REG_CLK_EN_3, 6, 514 + REG_DIV_CLK_SPI, 16, 6, 8, CV1800_DIV_FLAG, 515 + REG_CLK_BYP_0, 30, 516 + 0); 517 + 518 + /* UART */ 519 + static CV1800_GATE(clk_uart0, clk_uart_parents, 520 + REG_CLK_EN_1, 14, 521 + CLK_IS_CRITICAL); 522 + static CV1800_GATE(clk_apb_uart0, clk_axi4_bus_parents, 523 + REG_CLK_EN_1, 15, 524 + CLK_IS_CRITICAL); 525 + static CV1800_GATE(clk_uart1, clk_uart_parents, 526 + REG_CLK_EN_1, 16, 527 + 0); 528 + static CV1800_GATE(clk_apb_uart1, clk_axi4_bus_parents, 529 + REG_CLK_EN_1, 17, 530 + 0); 531 + static CV1800_GATE(clk_uart2, clk_uart_parents, 532 + REG_CLK_EN_1, 18, 533 + 0); 534 + static CV1800_GATE(clk_apb_uart2, clk_axi4_bus_parents, 535 + REG_CLK_EN_1, 19, 536 + 0); 537 + static CV1800_GATE(clk_uart3, clk_uart_parents, 538 + REG_CLK_EN_1, 20, 539 + 0); 540 + static CV1800_GATE(clk_apb_uart3, clk_axi4_bus_parents, 541 + REG_CLK_EN_1, 21, 542 + 0); 543 + static CV1800_GATE(clk_uart4, clk_uart_parents, 544 + REG_CLK_EN_1, 22, 545 + 0); 546 + static CV1800_GATE(clk_apb_uart4, clk_axi4_bus_parents, 547 + REG_CLK_EN_1, 23, 548 + 0); 549 + 550 + /* I2S */ 551 + static CV1800_GATE(clk_apb_i2s0, clk_axi4_bus_parents, 552 + REG_CLK_EN_1, 24, 553 + 0); 554 + static CV1800_GATE(clk_apb_i2s1, clk_axi4_bus_parents, 555 + REG_CLK_EN_1, 25, 556 + 0); 557 + static CV1800_GATE(clk_apb_i2s2, clk_axi4_bus_parents, 558 + REG_CLK_EN_1, 26, 559 + 0); 560 + static CV1800_GATE(clk_apb_i2s3, clk_axi4_bus_parents, 561 + REG_CLK_EN_1, 27, 562 + 0); 563 + 564 + /* DEBUG */ 565 + static CV1800_GATE(clk_debug, osc_parents, 566 + REG_CLK_EN_0, 13, 567 + CLK_IS_CRITICAL); 568 + static CV1800_BYPASS_DIV(clk_ap_debug, clk_bypass_fpll_parents, 569 + REG_CLK_EN_4, 5, 570 + REG_DIV_CLK_AP_DEBUG, 16, 4, 5, CV1800_DIV_FLAG, 571 + REG_CLK_BYP_1, 4, 572 + CLK_IS_CRITICAL); 573 + 574 + /* DDR */ 575 + static CV1800_GATE(clk_ddr_axi_reg, clk_axi6_bus_parents, 576 + REG_CLK_EN_0, 7, 577 + CLK_IS_CRITICAL); 578 + 579 + /* I2C */ 580 + static CV1800_GATE(clk_apb_i2c, clk_axi4_bus_parents, 581 + REG_CLK_EN_1, 6, 582 + 0); 583 + static CV1800_BYPASS_DIV(clk_i2c, clk_bypass_axi6_bus_parents, 584 + REG_CLK_EN_3, 7, 585 + REG_DIV_CLK_I2C, 16, 4, 1, CV1800_DIV_FLAG, 586 + REG_CLK_BYP_0, 31, 587 + 0); 588 + static CV1800_GATE(clk_apb_i2c0, clk_axi4_bus_parents, 589 + REG_CLK_EN_3, 17, 590 + 0); 591 + static CV1800_GATE(clk_apb_i2c1, clk_axi4_bus_parents, 592 + REG_CLK_EN_3, 18, 593 + 0); 594 + static CV1800_GATE(clk_apb_i2c2, clk_axi4_bus_parents, 595 + REG_CLK_EN_3, 19, 596 + 0); 597 + static CV1800_GATE(clk_apb_i2c3, clk_axi4_bus_parents, 598 + REG_CLK_EN_3, 20, 599 + 0); 600 + static CV1800_GATE(clk_apb_i2c4, clk_axi4_bus_parents, 601 + REG_CLK_EN_3, 21, 602 + 0); 603 + 604 + /* USB */ 605 + static CV1800_GATE(clk_axi4_usb, clk_axi4_bus_parents, 606 + REG_CLK_EN_1, 28, 607 + 0); 608 + static CV1800_GATE(clk_apb_usb, clk_axi4_bus_parents, 609 + REG_CLK_EN_1, 29, 610 + 0); 611 + static CV1800_BYPASS_FIXED_DIV(clk_usb_125m, clk_bypass_fpll_parents, 612 + REG_CLK_EN_1, 30, 613 + 12, 614 + REG_CLK_BYP_0, 17, 615 + CLK_SET_RATE_PARENT); 616 + static CV1800_FIXED_DIV(clk_usb_33k, clk_parents_1m, 617 + REG_CLK_EN_1, 31, 618 + 3, 619 + 0); 620 + static CV1800_BYPASS_FIXED_DIV(clk_usb_12m, clk_bypass_fpll_parents, 621 + REG_CLK_EN_2, 0, 622 + 125, 623 + REG_CLK_BYP_0, 18, 624 + CLK_SET_RATE_PARENT); 625 + 626 + /* VIP SYS */ 627 + static const struct clk_parent_data clk_vip_sys_parents[] = { 628 + { .index = 0 }, 629 + { .hw = &clk_mipimpll.common.hw }, 630 + { .hw = &clk_cam0pll.common.hw }, 631 + { .hw = &clk_disppll.common.hw }, 632 + { .hw = &clk_fpll.common.hw }, 633 + }; 634 + 635 + static CV1800_BYPASS_DIV(clk_dsi_esc, clk_bypass_axi6_bus_parents, 636 + REG_CLK_EN_2, 3, 637 + REG_DIV_CLK_DSI_ESC, 16, 4, 5, CV1800_DIV_FLAG, 638 + REG_CLK_BYP_0, 21, 639 + 0); 640 + static CV1800_BYPASS_MUX(clk_axi_vip, clk_vip_sys_parents, 641 + REG_CLK_EN_2, 4, 642 + REG_DIV_CLK_AXI_VIP, 16, 4, 3, CV1800_DIV_FLAG, 643 + REG_DIV_CLK_AXI_VIP, 8, 2, 644 + REG_CLK_BYP_0, 22, 645 + 0); 646 + 647 + static const struct clk_parent_data clk_axi_vip_bus_parents[] = { 648 + { .hw = &clk_axi_vip.mux.common.hw }, 649 + }; 650 + 651 + static CV1800_BYPASS_MUX(clk_src_vip_sys_0, clk_vip_sys_parents, 652 + REG_CLK_EN_2, 5, 653 + REG_DIV_CLK_SRC_VIP_SYS_0, 16, 4, 6, CV1800_DIV_FLAG, 654 + REG_DIV_CLK_SRC_VIP_SYS_0, 8, 2, 655 + REG_CLK_BYP_0, 23, 656 + 0); 657 + static CV1800_BYPASS_MUX(clk_src_vip_sys_1, clk_vip_sys_parents, 658 + REG_CLK_EN_2, 6, 659 + REG_DIV_CLK_SRC_VIP_SYS_1, 16, 4, 6, CV1800_DIV_FLAG, 660 + REG_DIV_CLK_SRC_VIP_SYS_1, 8, 2, 661 + REG_CLK_BYP_0, 24, 662 + 0); 663 + static CV1800_BYPASS_MUX(clk_src_vip_sys_2, clk_vip_sys_parents, 664 + REG_CLK_EN_3, 29, 665 + REG_DIV_CLK_SRC_VIP_SYS_2, 16, 4, 2, CV1800_DIV_FLAG, 666 + REG_DIV_CLK_SRC_VIP_SYS_2, 8, 2, 667 + REG_CLK_BYP_1, 1, 668 + 0); 669 + static CV1800_GATE(clk_csi_mac0_vip, clk_axi_vip_bus_parents, 670 + REG_CLK_EN_2, 18, 671 + 0); 672 + static CV1800_GATE(clk_csi_mac1_vip, clk_axi_vip_bus_parents, 673 + REG_CLK_EN_2, 19, 674 + 0); 675 + static CV1800_GATE(clk_isp_top_vip, clk_axi_vip_bus_parents, 676 + REG_CLK_EN_2, 20, 677 + 0); 678 + static CV1800_GATE(clk_img_d_vip, clk_axi_vip_bus_parents, 679 + REG_CLK_EN_2, 21, 680 + 0); 681 + static CV1800_GATE(clk_img_v_vip, clk_axi_vip_bus_parents, 682 + REG_CLK_EN_2, 22, 683 + 0); 684 + static CV1800_GATE(clk_sc_top_vip, clk_axi_vip_bus_parents, 685 + REG_CLK_EN_2, 23, 686 + 0); 687 + static CV1800_GATE(clk_sc_d_vip, clk_axi_vip_bus_parents, 688 + REG_CLK_EN_2, 24, 689 + 0); 690 + static CV1800_GATE(clk_sc_v1_vip, clk_axi_vip_bus_parents, 691 + REG_CLK_EN_2, 25, 692 + 0); 693 + static CV1800_GATE(clk_sc_v2_vip, clk_axi_vip_bus_parents, 694 + REG_CLK_EN_2, 26, 695 + 0); 696 + static CV1800_GATE(clk_sc_v3_vip, clk_axi_vip_bus_parents, 697 + REG_CLK_EN_2, 27, 698 + 0); 699 + static CV1800_GATE(clk_dwa_vip, clk_axi_vip_bus_parents, 700 + REG_CLK_EN_2, 28, 701 + 0); 702 + static CV1800_GATE(clk_bt_vip, clk_axi_vip_bus_parents, 703 + REG_CLK_EN_2, 29, 704 + 0); 705 + static CV1800_GATE(clk_disp_vip, clk_axi_vip_bus_parents, 706 + REG_CLK_EN_2, 30, 707 + 0); 708 + static CV1800_GATE(clk_dsi_mac_vip, clk_axi_vip_bus_parents, 709 + REG_CLK_EN_2, 31, 710 + 0); 711 + static CV1800_GATE(clk_lvds0_vip, clk_axi_vip_bus_parents, 712 + REG_CLK_EN_3, 0, 713 + 0); 714 + static CV1800_GATE(clk_lvds1_vip, clk_axi_vip_bus_parents, 715 + REG_CLK_EN_3, 1, 716 + 0); 717 + static CV1800_GATE(clk_csi0_rx_vip, clk_axi_vip_bus_parents, 718 + REG_CLK_EN_3, 2, 719 + 0); 720 + static CV1800_GATE(clk_csi1_rx_vip, clk_axi_vip_bus_parents, 721 + REG_CLK_EN_3, 3, 722 + 0); 723 + static CV1800_GATE(clk_pad_vi_vip, clk_axi_vip_bus_parents, 724 + REG_CLK_EN_3, 4, 725 + 0); 726 + static CV1800_GATE(clk_pad_vi1_vip, clk_axi_vip_bus_parents, 727 + REG_CLK_EN_3, 30, 728 + 0); 729 + static CV1800_GATE(clk_cfg_reg_vip, clk_axi6_bus_parents, 730 + REG_CLK_EN_3, 31, 731 + 0); 732 + static CV1800_GATE(clk_pad_vi2_vip, clk_axi_vip_bus_parents, 733 + REG_CLK_EN_4, 7, 734 + 0); 735 + static CV1800_GATE(clk_csi_be_vip, clk_axi_vip_bus_parents, 736 + REG_CLK_EN_4, 8, 737 + 0); 738 + static CV1800_GATE(clk_vip_ip0, clk_axi_vip_bus_parents, 739 + REG_CLK_EN_4, 9, 740 + 0); 741 + static CV1800_GATE(clk_vip_ip1, clk_axi_vip_bus_parents, 742 + REG_CLK_EN_4, 10, 743 + 0); 744 + static CV1800_GATE(clk_vip_ip2, clk_axi_vip_bus_parents, 745 + REG_CLK_EN_4, 11, 746 + 0); 747 + static CV1800_GATE(clk_vip_ip3, clk_axi_vip_bus_parents, 748 + REG_CLK_EN_4, 12, 749 + 0); 750 + static CV1800_BYPASS_MUX(clk_src_vip_sys_3, clk_vip_sys_parents, 751 + REG_CLK_EN_4, 15, 752 + REG_DIV_CLK_SRC_VIP_SYS_3, 16, 4, 2, CV1800_DIV_FLAG, 753 + REG_DIV_CLK_SRC_VIP_SYS_3, 8, 2, 754 + REG_CLK_BYP_1, 8, 755 + 0); 756 + static CV1800_BYPASS_MUX(clk_src_vip_sys_4, clk_vip_sys_parents, 757 + REG_CLK_EN_4, 16, 758 + REG_DIV_CLK_SRC_VIP_SYS_4, 16, 4, 3, CV1800_DIV_FLAG, 759 + REG_DIV_CLK_SRC_VIP_SYS_4, 8, 2, 760 + REG_CLK_BYP_1, 9, 761 + 0); 762 + static CV1800_GATE(clk_ive_vip, clk_axi_vip_bus_parents, 763 + REG_CLK_EN_4, 17, 764 + 0); 765 + static CV1800_GATE(clk_raw_vip, clk_axi_vip_bus_parents, 766 + REG_CLK_EN_4, 18, 767 + 0); 768 + static CV1800_GATE(clk_osdc_vip, clk_axi_vip_bus_parents, 769 + REG_CLK_EN_4, 19, 770 + 0); 771 + static CV1800_GATE(clk_csi_mac2_vip, clk_axi_vip_bus_parents, 772 + REG_CLK_EN_4, 20, 773 + 0); 774 + static CV1800_GATE(clk_cam0_vip, clk_axi_vip_bus_parents, 775 + REG_CLK_EN_4, 21, 776 + 0); 777 + 778 + /* CAM OUT */ 779 + static const struct clk_parent_data clk_cam_parents[] = { 780 + { .hw = &clk_cam0pll.common.hw }, 781 + { .hw = &clk_cam0pll_d2.common.hw }, 782 + { .hw = &clk_cam0pll_d3.common.hw }, 783 + { .hw = &clk_mipimpll_d3.common.hw }, 784 + }; 785 + 786 + static CV1800_MUX(clk_cam0, clk_cam_parents, 787 + REG_CLK_EN_2, 16, 788 + REG_CLK_CAM0_SRC_DIV, 16, 6, 0, CV1800_DIV_FLAG, 789 + REG_CLK_CAM0_SRC_DIV, 8, 2, 790 + CLK_IGNORE_UNUSED); 791 + static CV1800_MUX(clk_cam1, clk_cam_parents, 792 + REG_CLK_EN_2, 17, 793 + REG_CLK_CAM1_SRC_DIV, 16, 6, 0, CV1800_DIV_FLAG, 794 + REG_CLK_CAM1_SRC_DIV, 8, 2, 795 + CLK_IGNORE_UNUSED); 796 + 797 + /* VIDEO SUBSYS */ 798 + static const struct clk_parent_data clk_axi_video_codec_parents[] = { 799 + { .index = 0 }, 800 + { .hw = &clk_a0pll.common.hw }, 801 + { .hw = &clk_mipimpll.common.hw }, 802 + { .hw = &clk_cam1pll.common.hw }, 803 + { .hw = &clk_fpll.common.hw }, 804 + }; 805 + static const struct clk_parent_data clk_vc_src0_parents[] = { 806 + { .index = 0 }, 807 + { .hw = &clk_disppll.common.hw }, 808 + { .hw = &clk_mipimpll.common.hw }, 809 + { .hw = &clk_cam1pll.common.hw }, 810 + { .hw = &clk_fpll.common.hw }, 811 + }; 812 + static const struct clk_parent_data clk_vc_src1_parents[] = { 813 + { .index = 0 }, 814 + { .hw = &clk_cam1pll.common.hw }, 815 + }; 816 + 817 + static CV1800_BYPASS_MUX(clk_axi_video_codec, clk_axi_video_codec_parents, 818 + REG_CLK_EN_2, 8, 819 + REG_DIV_CLK_AXI_VIDEO_CODEC, 16, 4, 2, CV1800_DIV_FLAG, 820 + REG_DIV_CLK_AXI_VIDEO_CODEC, 8, 2, 821 + REG_CLK_BYP_0, 26, 822 + 0); 823 + 824 + static const struct clk_parent_data clk_axi_video_codec_bus_parents[] = { 825 + { .hw = &clk_axi_video_codec.mux.common.hw }, 826 + }; 827 + 828 + static CV1800_BYPASS_MUX(clk_vc_src0, clk_vc_src0_parents, 829 + REG_CLK_EN_2, 9, 830 + REG_DIV_CLK_VC_SRC0, 16, 4, 2, CV1800_DIV_FLAG, 831 + REG_DIV_CLK_VC_SRC0, 8, 2, 832 + REG_CLK_BYP_0, 27, 833 + 0); 834 + 835 + static CV1800_GATE(clk_h264c, clk_axi_video_codec_bus_parents, 836 + REG_CLK_EN_2, 10, 837 + 0); 838 + static CV1800_GATE(clk_h265c, clk_axi_video_codec_bus_parents, 839 + REG_CLK_EN_2, 11, 840 + 0); 841 + static CV1800_GATE(clk_jpeg, clk_axi_video_codec_bus_parents, 842 + REG_CLK_EN_2, 12, 843 + CLK_IGNORE_UNUSED); 844 + static CV1800_GATE(clk_apb_jpeg, clk_axi6_bus_parents, 845 + REG_CLK_EN_2, 13, 846 + CLK_IGNORE_UNUSED); 847 + static CV1800_GATE(clk_apb_h264c, clk_axi6_bus_parents, 848 + REG_CLK_EN_2, 14, 849 + 0); 850 + static CV1800_GATE(clk_apb_h265c, clk_axi6_bus_parents, 851 + REG_CLK_EN_2, 15, 852 + 0); 853 + static CV1800_BYPASS_FIXED_DIV(clk_vc_src1, clk_vc_src1_parents, 854 + REG_CLK_EN_3, 28, 855 + 2, 856 + REG_CLK_BYP_1, 0, 857 + CLK_SET_RATE_PARENT); 858 + static CV1800_BYPASS_FIXED_DIV(clk_vc_src2, clk_bypass_fpll_parents, 859 + REG_CLK_EN_4, 3, 860 + 3, 861 + REG_CLK_BYP_1, 3, 862 + CLK_SET_RATE_PARENT); 863 + 864 + /* VC SYS */ 865 + static CV1800_GATE(clk_cfg_reg_vc, clk_axi6_bus_parents, 866 + REG_CLK_EN_4, 0, 867 + CLK_IGNORE_UNUSED); 868 + 869 + /* PWM */ 870 + static CV1800_BYPASS_MUX(clk_pwm_src, clk_axi4_parents, 871 + REG_CLK_EN_4, 4, 872 + REG_DIV_CLK_PWM_SRC_0, 16, 6, 10, CV1800_DIV_FLAG, 873 + REG_DIV_CLK_PWM_SRC_0, 8, 2, 874 + REG_CLK_BYP_0, 15, 875 + CLK_IS_CRITICAL); 876 + 877 + static const struct clk_parent_data clk_pwm_parents[] = { 878 + { .hw = &clk_pwm_src.mux.common.hw }, 879 + }; 880 + 881 + static CV1800_GATE(clk_pwm, clk_pwm_parents, 882 + REG_CLK_EN_1, 8, 883 + CLK_IS_CRITICAL); 884 + 885 + /* C906 */ 886 + static const struct clk_parent_data clk_c906_0_parents[] = { 887 + { .index = 0 }, 888 + { .hw = &clk_tpll.common.hw }, 889 + { .hw = &clk_a0pll.common.hw }, 890 + { .hw = &clk_mipimpll.common.hw }, 891 + { .hw = &clk_mpll.common.hw }, 892 + { .hw = &clk_fpll.common.hw }, 893 + }; 894 + static const struct clk_parent_data clk_c906_1_parents[] = { 895 + { .index = 0 }, 896 + { .hw = &clk_tpll.common.hw }, 897 + { .hw = &clk_a0pll.common.hw }, 898 + { .hw = &clk_disppll.common.hw }, 899 + { .hw = &clk_mpll.common.hw }, 900 + { .hw = &clk_fpll.common.hw }, 901 + }; 902 + 903 + static const s8 clk_c906_parent2sel[] = { 904 + -1, /* osc */ 905 + 0, /* mux 0: clk_tpll(c906_0), clk_tpll(c906_1) */ 906 + 0, /* mux 0: clk_a0pll(c906_0), clk_a0pll(c906_1) */ 907 + 0, /* mux 0: clk_mipimpll(c906_0), clk_disppll(c906_1) */ 908 + 0, /* mux 0: clk_mpll(c906_0), clk_mpll(c906_1) */ 909 + 1 /* mux 1: clk_fpll(c906_0), clk_fpll(c906_1) */ 910 + }; 911 + 912 + static const u8 clk_c906_sel2parent[2][4] = { 913 + [0] = { 914 + 1, 915 + 2, 916 + 3, 917 + 4 918 + }, 919 + [1] = { 920 + 5, 921 + 5, 922 + 5, 923 + 5 924 + }, 925 + }; 926 + 927 + static CV1800_MMUX(clk_c906_0, clk_c906_0_parents, 928 + REG_CLK_EN_4, 13, 929 + REG_DIV_CLK_C906_0_0, 16, 4, 1, CV1800_DIV_FLAG, 930 + REG_DIV_CLK_C906_0_1, 16, 4, 2, CV1800_DIV_FLAG, 931 + REG_DIV_CLK_C906_0_0, 8, 2, 932 + REG_DIV_CLK_C906_0_1, 8, 2, 933 + REG_CLK_BYP_1, 6, 934 + REG_CLK_SEL_0, 23, 935 + clk_c906_parent2sel, 936 + clk_c906_sel2parent[0], clk_c906_sel2parent[1], 937 + CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE); 938 + static CV1800_MMUX(clk_c906_1, clk_c906_1_parents, 939 + REG_CLK_EN_4, 14, 940 + REG_DIV_CLK_C906_1_0, 16, 4, 2, CV1800_DIV_FLAG, 941 + REG_DIV_CLK_C906_1_1, 16, 4, 3, CV1800_DIV_FLAG, 942 + REG_DIV_CLK_C906_1_0, 8, 2, 943 + REG_DIV_CLK_C906_1_1, 8, 2, 944 + REG_CLK_BYP_1, 7, 945 + REG_CLK_SEL_0, 24, 946 + clk_c906_parent2sel, 947 + clk_c906_sel2parent[0], clk_c906_sel2parent[1], 948 + CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE); 949 + 950 + /* A53 */ 951 + static CV1800_BYPASS_DIV(clk_cpu_axi0, clk_axi4_parents, 952 + REG_CLK_EN_0, 1, 953 + REG_DIV_CLK_CPU_AXI0, 16, 4, 3, CV1800_DIV_FLAG, 954 + REG_CLK_BYP_0, 1, 955 + CLK_IS_CRITICAL); 956 + static CV1800_BYPASS_DIV(clk_cpu_gic, clk_bypass_fpll_parents, 957 + REG_CLK_EN_0, 2, 958 + REG_DIV_CLK_CPU_GIC, 16, 4, 5, CV1800_DIV_FLAG, 959 + REG_CLK_BYP_0, 2, 960 + CLK_IS_CRITICAL); 961 + static CV1800_GATE(clk_xtal_ap, osc_parents, 962 + REG_CLK_EN_0, 3, 963 + CLK_IS_CRITICAL); 964 + 965 + static const struct clk_parent_data clk_a53_parents[] = { 966 + { .index = 0 }, 967 + { .hw = &clk_tpll.common.hw }, 968 + { .hw = &clk_a0pll.common.hw }, 969 + { .hw = &clk_mipimpll.common.hw }, 970 + { .hw = &clk_mpll.common.hw }, 971 + { .hw = &clk_fpll.common.hw }, 972 + }; 973 + 974 + static const s8 clk_a53_parent2sel[] = { 975 + -1, /* osc */ 976 + 0, /* mux 0: clk_tpll */ 977 + 0, /* mux 0: clk_a0pll */ 978 + 0, /* mux 0: clk_mipimpll */ 979 + 0, /* mux 0: clk_mpll */ 980 + 1 /* mux 1: clk_fpll */ 981 + }; 982 + 983 + static const u8 clk_a53_sel2parent[2][4] = { 984 + [0] = { 985 + 1, 986 + 2, 987 + 3, 988 + 4 989 + }, 990 + [1] = { 991 + 5, 992 + 5, 993 + 5, 994 + 5 995 + }, 996 + }; 997 + 998 + /* 999 + * Clock for A53 cpu in the CV18XX/SG200X series. 1000 + * For CV180X and CV181X series, this clock is not used, but can not 1001 + * be set to bypass mode, or the SoC will hang. 1002 + */ 1003 + static CV1800_MMUX(clk_a53, clk_a53_parents, 1004 + REG_CLK_EN_0, 0, 1005 + REG_DIV_CLK_A53_0, 16, 4, 1, CV1800_DIV_FLAG, 1006 + REG_DIV_CLK_A53_1, 16, 4, 2, CV1800_DIV_FLAG, 1007 + REG_DIV_CLK_A53_0, 8, 2, 1008 + REG_DIV_CLK_A53_1, 8, 2, 1009 + REG_CLK_BYP_0, 0, 1010 + REG_CLK_SEL_0, 0, 1011 + clk_a53_parent2sel, 1012 + clk_a53_sel2parent[0], clk_a53_sel2parent[1], 1013 + CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE); 1014 + 1015 + static struct clk_hw_onecell_data cv1800_hw_clks = { 1016 + .num = CV1800_CLK_MAX, 1017 + .hws = { 1018 + [CLK_MPLL] = &clk_mpll.common.hw, 1019 + [CLK_TPLL] = &clk_tpll.common.hw, 1020 + [CLK_FPLL] = &clk_fpll.common.hw, 1021 + [CLK_MIPIMPLL] = &clk_mipimpll.common.hw, 1022 + [CLK_A0PLL] = &clk_a0pll.common.hw, 1023 + [CLK_DISPPLL] = &clk_disppll.common.hw, 1024 + [CLK_CAM0PLL] = &clk_cam0pll.common.hw, 1025 + [CLK_CAM1PLL] = &clk_cam1pll.common.hw, 1026 + 1027 + [CLK_MIPIMPLL_D3] = &clk_mipimpll_d3.common.hw, 1028 + [CLK_CAM0PLL_D2] = &clk_cam0pll_d2.common.hw, 1029 + [CLK_CAM0PLL_D3] = &clk_cam0pll_d3.common.hw, 1030 + 1031 + [CLK_TPU] = &clk_tpu.mux.common.hw, 1032 + [CLK_TPU_FAB] = &clk_tpu_fab.common.hw, 1033 + [CLK_AHB_ROM] = &clk_ahb_rom.common.hw, 1034 + [CLK_DDR_AXI_REG] = &clk_ddr_axi_reg.common.hw, 1035 + [CLK_RTC_25M] = &clk_rtc_25m.common.hw, 1036 + [CLK_SRC_RTC_SYS_0] = &clk_src_rtc_sys_0.div.common.hw, 1037 + [CLK_TEMPSEN] = &clk_tempsen.common.hw, 1038 + [CLK_SARADC] = &clk_saradc.common.hw, 1039 + [CLK_EFUSE] = &clk_efuse.common.hw, 1040 + [CLK_APB_EFUSE] = &clk_apb_efuse.common.hw, 1041 + [CLK_DEBUG] = &clk_debug.common.hw, 1042 + [CLK_AP_DEBUG] = &clk_ap_debug.div.common.hw, 1043 + [CLK_XTAL_MISC] = &clk_xtal_misc.common.hw, 1044 + [CLK_AXI4_EMMC] = &clk_axi4_emmc.common.hw, 1045 + [CLK_EMMC] = &clk_emmc.mux.common.hw, 1046 + [CLK_EMMC_100K] = &clk_emmc_100k.common.hw, 1047 + [CLK_AXI4_SD0] = &clk_axi4_sd0.common.hw, 1048 + [CLK_SD0] = &clk_sd0.mux.common.hw, 1049 + [CLK_SD0_100K] = &clk_sd0_100k.common.hw, 1050 + [CLK_AXI4_SD1] = &clk_axi4_sd1.common.hw, 1051 + [CLK_SD1] = &clk_sd1.mux.common.hw, 1052 + [CLK_SD1_100K] = &clk_sd1_100k.common.hw, 1053 + [CLK_SPI_NAND] = &clk_spi_nand.mux.common.hw, 1054 + [CLK_ETH0_500M] = &clk_eth0_500m.div.common.hw, 1055 + [CLK_AXI4_ETH0] = &clk_axi4_eth0.common.hw, 1056 + [CLK_ETH1_500M] = &clk_eth1_500m.div.common.hw, 1057 + [CLK_AXI4_ETH1] = &clk_axi4_eth1.common.hw, 1058 + [CLK_APB_GPIO] = &clk_apb_gpio.common.hw, 1059 + [CLK_APB_GPIO_INTR] = &clk_apb_gpio_intr.common.hw, 1060 + [CLK_GPIO_DB] = &clk_gpio_db.common.hw, 1061 + [CLK_AHB_SF] = &clk_ahb_sf.common.hw, 1062 + [CLK_AHB_SF1] = &clk_ahb_sf1.common.hw, 1063 + [CLK_A24M] = &clk_a24m.common.hw, 1064 + [CLK_AUDSRC] = &clk_audsrc.mux.common.hw, 1065 + [CLK_APB_AUDSRC] = &clk_apb_audsrc.common.hw, 1066 + [CLK_SDMA_AXI] = &clk_sdma_axi.common.hw, 1067 + [CLK_SDMA_AUD0] = &clk_sdma_aud0.mux.common.hw, 1068 + [CLK_SDMA_AUD1] = &clk_sdma_aud1.mux.common.hw, 1069 + [CLK_SDMA_AUD2] = &clk_sdma_aud2.mux.common.hw, 1070 + [CLK_SDMA_AUD3] = &clk_sdma_aud3.mux.common.hw, 1071 + [CLK_I2C] = &clk_i2c.div.common.hw, 1072 + [CLK_APB_I2C] = &clk_apb_i2c.common.hw, 1073 + [CLK_APB_I2C0] = &clk_apb_i2c0.common.hw, 1074 + [CLK_APB_I2C1] = &clk_apb_i2c1.common.hw, 1075 + [CLK_APB_I2C2] = &clk_apb_i2c2.common.hw, 1076 + [CLK_APB_I2C3] = &clk_apb_i2c3.common.hw, 1077 + [CLK_APB_I2C4] = &clk_apb_i2c4.common.hw, 1078 + [CLK_APB_WDT] = &clk_apb_wdt.common.hw, 1079 + [CLK_PWM_SRC] = &clk_pwm_src.mux.common.hw, 1080 + [CLK_PWM] = &clk_pwm.common.hw, 1081 + [CLK_SPI] = &clk_spi.div.common.hw, 1082 + [CLK_APB_SPI0] = &clk_apb_spi0.common.hw, 1083 + [CLK_APB_SPI1] = &clk_apb_spi1.common.hw, 1084 + [CLK_APB_SPI2] = &clk_apb_spi2.common.hw, 1085 + [CLK_APB_SPI3] = &clk_apb_spi3.common.hw, 1086 + [CLK_1M] = &clk_1m.common.hw, 1087 + [CLK_CAM0_200] = &clk_cam0_200.mux.common.hw, 1088 + [CLK_PM] = &clk_pm.common.hw, 1089 + [CLK_TIMER0] = &clk_timer0.common.hw, 1090 + [CLK_TIMER1] = &clk_timer1.common.hw, 1091 + [CLK_TIMER2] = &clk_timer2.common.hw, 1092 + [CLK_TIMER3] = &clk_timer3.common.hw, 1093 + [CLK_TIMER4] = &clk_timer4.common.hw, 1094 + [CLK_TIMER5] = &clk_timer5.common.hw, 1095 + [CLK_TIMER6] = &clk_timer6.common.hw, 1096 + [CLK_TIMER7] = &clk_timer7.common.hw, 1097 + [CLK_UART0] = &clk_uart0.common.hw, 1098 + [CLK_APB_UART0] = &clk_apb_uart0.common.hw, 1099 + [CLK_UART1] = &clk_uart1.common.hw, 1100 + [CLK_APB_UART1] = &clk_apb_uart1.common.hw, 1101 + [CLK_UART2] = &clk_uart2.common.hw, 1102 + [CLK_APB_UART2] = &clk_apb_uart2.common.hw, 1103 + [CLK_UART3] = &clk_uart3.common.hw, 1104 + [CLK_APB_UART3] = &clk_apb_uart3.common.hw, 1105 + [CLK_UART4] = &clk_uart4.common.hw, 1106 + [CLK_APB_UART4] = &clk_apb_uart4.common.hw, 1107 + [CLK_APB_I2S0] = &clk_apb_i2s0.common.hw, 1108 + [CLK_APB_I2S1] = &clk_apb_i2s1.common.hw, 1109 + [CLK_APB_I2S2] = &clk_apb_i2s2.common.hw, 1110 + [CLK_APB_I2S3] = &clk_apb_i2s3.common.hw, 1111 + [CLK_AXI4_USB] = &clk_axi4_usb.common.hw, 1112 + [CLK_APB_USB] = &clk_apb_usb.common.hw, 1113 + [CLK_USB_125M] = &clk_usb_125m.div.common.hw, 1114 + [CLK_USB_33K] = &clk_usb_33k.common.hw, 1115 + [CLK_USB_12M] = &clk_usb_12m.div.common.hw, 1116 + [CLK_AXI4] = &clk_axi4.mux.common.hw, 1117 + [CLK_AXI6] = &clk_axi6.div.common.hw, 1118 + [CLK_DSI_ESC] = &clk_dsi_esc.div.common.hw, 1119 + [CLK_AXI_VIP] = &clk_axi_vip.mux.common.hw, 1120 + [CLK_SRC_VIP_SYS_0] = &clk_src_vip_sys_0.mux.common.hw, 1121 + [CLK_SRC_VIP_SYS_1] = &clk_src_vip_sys_1.mux.common.hw, 1122 + [CLK_SRC_VIP_SYS_2] = &clk_src_vip_sys_2.mux.common.hw, 1123 + [CLK_SRC_VIP_SYS_3] = &clk_src_vip_sys_3.mux.common.hw, 1124 + [CLK_SRC_VIP_SYS_4] = &clk_src_vip_sys_4.mux.common.hw, 1125 + [CLK_CSI_BE_VIP] = &clk_csi_be_vip.common.hw, 1126 + [CLK_CSI_MAC0_VIP] = &clk_csi_mac0_vip.common.hw, 1127 + [CLK_CSI_MAC1_VIP] = &clk_csi_mac1_vip.common.hw, 1128 + [CLK_CSI_MAC2_VIP] = &clk_csi_mac2_vip.common.hw, 1129 + [CLK_CSI0_RX_VIP] = &clk_csi0_rx_vip.common.hw, 1130 + [CLK_CSI1_RX_VIP] = &clk_csi1_rx_vip.common.hw, 1131 + [CLK_ISP_TOP_VIP] = &clk_isp_top_vip.common.hw, 1132 + [CLK_IMG_D_VIP] = &clk_img_d_vip.common.hw, 1133 + [CLK_IMG_V_VIP] = &clk_img_v_vip.common.hw, 1134 + [CLK_SC_TOP_VIP] = &clk_sc_top_vip.common.hw, 1135 + [CLK_SC_D_VIP] = &clk_sc_d_vip.common.hw, 1136 + [CLK_SC_V1_VIP] = &clk_sc_v1_vip.common.hw, 1137 + [CLK_SC_V2_VIP] = &clk_sc_v2_vip.common.hw, 1138 + [CLK_SC_V3_VIP] = &clk_sc_v3_vip.common.hw, 1139 + [CLK_DWA_VIP] = &clk_dwa_vip.common.hw, 1140 + [CLK_BT_VIP] = &clk_bt_vip.common.hw, 1141 + [CLK_DISP_VIP] = &clk_disp_vip.common.hw, 1142 + [CLK_DSI_MAC_VIP] = &clk_dsi_mac_vip.common.hw, 1143 + [CLK_LVDS0_VIP] = &clk_lvds0_vip.common.hw, 1144 + [CLK_LVDS1_VIP] = &clk_lvds1_vip.common.hw, 1145 + [CLK_PAD_VI_VIP] = &clk_pad_vi_vip.common.hw, 1146 + [CLK_PAD_VI1_VIP] = &clk_pad_vi1_vip.common.hw, 1147 + [CLK_PAD_VI2_VIP] = &clk_pad_vi2_vip.common.hw, 1148 + [CLK_CFG_REG_VIP] = &clk_cfg_reg_vip.common.hw, 1149 + [CLK_VIP_IP0] = &clk_vip_ip0.common.hw, 1150 + [CLK_VIP_IP1] = &clk_vip_ip1.common.hw, 1151 + [CLK_VIP_IP2] = &clk_vip_ip2.common.hw, 1152 + [CLK_VIP_IP3] = &clk_vip_ip3.common.hw, 1153 + [CLK_IVE_VIP] = &clk_ive_vip.common.hw, 1154 + [CLK_RAW_VIP] = &clk_raw_vip.common.hw, 1155 + [CLK_OSDC_VIP] = &clk_osdc_vip.common.hw, 1156 + [CLK_CAM0_VIP] = &clk_cam0_vip.common.hw, 1157 + [CLK_AXI_VIDEO_CODEC] = &clk_axi_video_codec.mux.common.hw, 1158 + [CLK_VC_SRC0] = &clk_vc_src0.mux.common.hw, 1159 + [CLK_VC_SRC1] = &clk_vc_src1.div.common.hw, 1160 + [CLK_VC_SRC2] = &clk_vc_src2.div.common.hw, 1161 + [CLK_H264C] = &clk_h264c.common.hw, 1162 + [CLK_APB_H264C] = &clk_apb_h264c.common.hw, 1163 + [CLK_H265C] = &clk_h265c.common.hw, 1164 + [CLK_APB_H265C] = &clk_apb_h265c.common.hw, 1165 + [CLK_JPEG] = &clk_jpeg.common.hw, 1166 + [CLK_APB_JPEG] = &clk_apb_jpeg.common.hw, 1167 + [CLK_CAM0] = &clk_cam0.common.hw, 1168 + [CLK_CAM1] = &clk_cam1.common.hw, 1169 + [CLK_WGN] = &clk_wgn.common.hw, 1170 + [CLK_WGN0] = &clk_wgn0.common.hw, 1171 + [CLK_WGN1] = &clk_wgn1.common.hw, 1172 + [CLK_WGN2] = &clk_wgn2.common.hw, 1173 + [CLK_KEYSCAN] = &clk_keyscan.common.hw, 1174 + [CLK_CFG_REG_VC] = &clk_cfg_reg_vc.common.hw, 1175 + [CLK_C906_0] = &clk_c906_0.common.hw, 1176 + [CLK_C906_1] = &clk_c906_1.common.hw, 1177 + [CLK_A53] = &clk_a53.common.hw, 1178 + [CLK_CPU_AXI0] = &clk_cpu_axi0.div.common.hw, 1179 + [CLK_CPU_GIC] = &clk_cpu_gic.div.common.hw, 1180 + [CLK_XTAL_AP] = &clk_xtal_ap.common.hw, 1181 + }, 1182 + }; 1183 + 1184 + static void cv18xx_clk_disable_auto_pd(void __iomem *base) 1185 + { 1186 + static const u16 CV1800_PD_CLK[] = { 1187 + REG_MIPIMPLL_CLK_CSR, 1188 + REG_A0PLL_CLK_CSR, 1189 + REG_DISPPLL_CLK_CSR, 1190 + REG_CAM0PLL_CLK_CSR, 1191 + REG_CAM1PLL_CLK_CSR, 1192 + }; 1193 + 1194 + u32 val; 1195 + int i; 1196 + 1197 + /* disable auto power down */ 1198 + for (i = 0; i < ARRAY_SIZE(CV1800_PD_CLK); i++) { 1199 + u32 reg = CV1800_PD_CLK[i]; 1200 + 1201 + val = readl(base + reg); 1202 + val |= GENMASK(12, 9); 1203 + val &= ~BIT(8); 1204 + writel(val, base + reg); 1205 + } 1206 + } 1207 + 1208 + static void cv18xx_clk_disable_a53(void __iomem *base) 1209 + { 1210 + u32 val = readl(base + REG_CLK_BYP_0); 1211 + 1212 + /* Set bypass clock for clk_a53 */ 1213 + val |= BIT(0); 1214 + 1215 + /* Set bypass clock for clk_cpu_axi0 */ 1216 + val |= BIT(1); 1217 + 1218 + /* Set bypass clock for clk_cpu_gic */ 1219 + val |= BIT(2); 1220 + 1221 + writel(val, base + REG_CLK_BYP_0); 1222 + } 1223 + 1224 + static int cv1800_pre_init(struct device *dev, void __iomem *base, 1225 + struct cv1800_clk_ctrl *ctrl, 1226 + const struct cv1800_clk_desc *desc) 1227 + { 1228 + u32 val = readl(base + REG_CLK_EN_2); 1229 + 1230 + /* disable unsupported clk_disp_src_vip */ 1231 + val &= ~BIT(7); 1232 + 1233 + writel(val, base + REG_CLK_EN_2); 1234 + 1235 + cv18xx_clk_disable_a53(base); 1236 + cv18xx_clk_disable_auto_pd(base); 1237 + 1238 + return 0; 1239 + } 1240 + 1241 + static const struct cv1800_clk_desc cv1800_desc = { 1242 + .clks_data = &cv1800_hw_clks, 1243 + .pre_init = cv1800_pre_init, 1244 + }; 1245 + 1246 + static int cv1800_clk_init_ctrl(struct device *dev, void __iomem *reg, 1247 + struct cv1800_clk_ctrl *ctrl, 1248 + const struct cv1800_clk_desc *desc) 1249 + { 1250 + int i, ret; 1251 + 1252 + ctrl->desc = desc; 1253 + spin_lock_init(&ctrl->lock); 1254 + 1255 + for (i = 0; i < desc->clks_data->num; i++) { 1256 + struct clk_hw *hw = desc->clks_data->hws[i]; 1257 + struct cv1800_clk_common *common; 1258 + const char *name; 1259 + 1260 + if (!hw) 1261 + continue; 1262 + 1263 + name = hw->init->name; 1264 + 1265 + common = hw_to_cv1800_clk_common(hw); 1266 + common->base = reg; 1267 + common->lock = &ctrl->lock; 1268 + 1269 + ret = devm_clk_hw_register(dev, hw); 1270 + if (ret) { 1271 + dev_err(dev, "Couldn't register clock %d - %s\n", 1272 + i, name); 1273 + return ret; 1274 + } 1275 + } 1276 + 1277 + return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, 1278 + desc->clks_data); 1279 + } 1280 + 1281 + static int cv1800_clk_probe(struct platform_device *pdev) 1282 + { 1283 + struct device *dev = &pdev->dev; 1284 + void __iomem *reg; 1285 + int ret; 1286 + const struct cv1800_clk_desc *desc; 1287 + struct cv1800_clk_ctrl *ctrl; 1288 + 1289 + reg = devm_platform_ioremap_resource(pdev, 0); 1290 + if (IS_ERR(reg)) 1291 + return PTR_ERR(reg); 1292 + 1293 + desc = device_get_match_data(dev); 1294 + if (!desc) { 1295 + dev_err(dev, "no match data for platform\n"); 1296 + return -EINVAL; 1297 + } 1298 + 1299 + ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); 1300 + if (!ctrl) 1301 + return -ENOMEM; 1302 + 1303 + if (desc->pre_init) { 1304 + ret = desc->pre_init(dev, reg, ctrl, desc); 1305 + if (ret) 1306 + return ret; 1307 + } 1308 + 1309 + return cv1800_clk_init_ctrl(dev, reg, ctrl, desc); 1310 + } 1311 + 1312 + static const struct of_device_id cv1800_clk_ids[] = { 1313 + { .compatible = "sophgo,cv1800-clk", .data = &cv1800_desc }, 1314 + { } 1315 + }; 1316 + MODULE_DEVICE_TABLE(of, cv1800_clk_ids); 1317 + 1318 + static struct platform_driver cv1800_clk_driver = { 1319 + .probe = cv1800_clk_probe, 1320 + .driver = { 1321 + .name = "cv1800-clk", 1322 + .suppress_bind_attrs = true, 1323 + .of_match_table = cv1800_clk_ids, 1324 + }, 1325 + }; 1326 + module_platform_driver(cv1800_clk_driver); 1327 + MODULE_LICENSE("GPL");
+122
drivers/clk/sophgo/clk-cv1800.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (C) 2023 Inochi Amaoto <inochiama@outlook.com> 4 + */ 5 + 6 + #ifndef _CLK_SOPHGO_CV1800_H_ 7 + #define _CLK_SOPHGO_CV1800_H_ 8 + 9 + #include <dt-bindings/clock/sophgo,cv1800.h> 10 + 11 + #define CV1800_CLK_MAX (CLK_XTAL_AP + 1) 12 + 13 + #define REG_PLL_G2_CTRL 0x800 14 + #define REG_PLL_G2_STATUS 0x804 15 + #define REG_MIPIMPLL_CSR 0x808 16 + #define REG_A0PLL_CSR 0x80C 17 + #define REG_DISPPLL_CSR 0x810 18 + #define REG_CAM0PLL_CSR 0x814 19 + #define REG_CAM1PLL_CSR 0x818 20 + #define REG_PLL_G2_SSC_SYN_CTRL 0x840 21 + #define REG_A0PLL_SSC_SYN_CTRL 0x850 22 + #define REG_A0PLL_SSC_SYN_SET 0x854 23 + #define REG_A0PLL_SSC_SYN_SPAN 0x858 24 + #define REG_A0PLL_SSC_SYN_STEP 0x85C 25 + #define REG_DISPPLL_SSC_SYN_CTRL 0x860 26 + #define REG_DISPPLL_SSC_SYN_SET 0x864 27 + #define REG_DISPPLL_SSC_SYN_SPAN 0x868 28 + #define REG_DISPPLL_SSC_SYN_STEP 0x86C 29 + #define REG_CAM0PLL_SSC_SYN_CTRL 0x870 30 + #define REG_CAM0PLL_SSC_SYN_SET 0x874 31 + #define REG_CAM0PLL_SSC_SYN_SPAN 0x878 32 + #define REG_CAM0PLL_SSC_SYN_STEP 0x87C 33 + #define REG_CAM1PLL_SSC_SYN_CTRL 0x880 34 + #define REG_CAM1PLL_SSC_SYN_SET 0x884 35 + #define REG_CAM1PLL_SSC_SYN_SPAN 0x888 36 + #define REG_CAM1PLL_SSC_SYN_STEP 0x88C 37 + #define REG_APLL_FRAC_DIV_CTRL 0x890 38 + #define REG_APLL_FRAC_DIV_M 0x894 39 + #define REG_APLL_FRAC_DIV_N 0x898 40 + #define REG_MIPIMPLL_CLK_CSR 0x8A0 41 + #define REG_A0PLL_CLK_CSR 0x8A4 42 + #define REG_DISPPLL_CLK_CSR 0x8A8 43 + #define REG_CAM0PLL_CLK_CSR 0x8AC 44 + #define REG_CAM1PLL_CLK_CSR 0x8B0 45 + #define REG_CLK_CAM0_SRC_DIV 0x8C0 46 + #define REG_CLK_CAM1_SRC_DIV 0x8C4 47 + 48 + /* top_pll_g6 */ 49 + #define REG_PLL_G6_CTRL 0x900 50 + #define REG_PLL_G6_STATUS 0x904 51 + #define REG_MPLL_CSR 0x908 52 + #define REG_TPLL_CSR 0x90C 53 + #define REG_FPLL_CSR 0x910 54 + #define REG_PLL_G6_SSC_SYN_CTRL 0x940 55 + #define REG_DPLL_SSC_SYN_CTRL 0x950 56 + #define REG_DPLL_SSC_SYN_SET 0x954 57 + #define REG_DPLL_SSC_SYN_SPAN 0x958 58 + #define REG_DPLL_SSC_SYN_STEP 0x95C 59 + #define REG_MPLL_SSC_SYN_CTRL 0x960 60 + #define REG_MPLL_SSC_SYN_SET 0x964 61 + #define REG_MPLL_SSC_SYN_SPAN 0x968 62 + #define REG_MPLL_SSC_SYN_STEP 0x96C 63 + #define REG_TPLL_SSC_SYN_CTRL 0x970 64 + #define REG_TPLL_SSC_SYN_SET 0x974 65 + #define REG_TPLL_SSC_SYN_SPAN 0x978 66 + #define REG_TPLL_SSC_SYN_STEP 0x97C 67 + 68 + /* clkgen */ 69 + #define REG_CLK_EN_0 0x000 70 + #define REG_CLK_EN_1 0x004 71 + #define REG_CLK_EN_2 0x008 72 + #define REG_CLK_EN_3 0x00C 73 + #define REG_CLK_EN_4 0x010 74 + #define REG_CLK_SEL_0 0x020 75 + #define REG_CLK_BYP_0 0x030 76 + #define REG_CLK_BYP_1 0x034 77 + 78 + #define REG_DIV_CLK_A53_0 0x040 79 + #define REG_DIV_CLK_A53_1 0x044 80 + #define REG_DIV_CLK_CPU_AXI0 0x048 81 + #define REG_DIV_CLK_CPU_GIC 0x050 82 + #define REG_DIV_CLK_TPU 0x054 83 + #define REG_DIV_CLK_EMMC 0x064 84 + #define REG_DIV_CLK_EMMC_100K 0x06C 85 + #define REG_DIV_CLK_SD0 0x070 86 + #define REG_DIV_CLK_SD0_100K 0x078 87 + #define REG_DIV_CLK_SD1 0x07C 88 + #define REG_DIV_CLK_SD1_100K 0x084 89 + #define REG_DIV_CLK_SPI_NAND 0x088 90 + #define REG_DIV_CLK_ETH0_500M 0x08C 91 + #define REG_DIV_CLK_ETH1_500M 0x090 92 + #define REG_DIV_CLK_GPIO_DB 0x094 93 + #define REG_DIV_CLK_SDMA_AUD0 0x098 94 + #define REG_DIV_CLK_SDMA_AUD1 0x09C 95 + #define REG_DIV_CLK_SDMA_AUD2 0x0A0 96 + #define REG_DIV_CLK_SDMA_AUD3 0x0A4 97 + #define REG_DIV_CLK_CAM0_200 0x0A8 98 + #define REG_DIV_CLK_AXI4 0x0B8 99 + #define REG_DIV_CLK_AXI6 0x0BC 100 + #define REG_DIV_CLK_DSI_ESC 0x0C4 101 + #define REG_DIV_CLK_AXI_VIP 0x0C8 102 + #define REG_DIV_CLK_SRC_VIP_SYS_0 0x0D0 103 + #define REG_DIV_CLK_SRC_VIP_SYS_1 0x0D8 104 + #define REG_DIV_CLK_DISP_SRC_VIP 0x0E0 105 + #define REG_DIV_CLK_AXI_VIDEO_CODEC 0x0E4 106 + #define REG_DIV_CLK_VC_SRC0 0x0EC 107 + #define REG_DIV_CLK_1M 0x0FC 108 + #define REG_DIV_CLK_SPI 0x100 109 + #define REG_DIV_CLK_I2C 0x104 110 + #define REG_DIV_CLK_SRC_VIP_SYS_2 0x110 111 + #define REG_DIV_CLK_AUDSRC 0x118 112 + #define REG_DIV_CLK_PWM_SRC_0 0x120 113 + #define REG_DIV_CLK_AP_DEBUG 0x128 114 + #define REG_DIV_CLK_RTCSYS_SRC_0 0x12C 115 + #define REG_DIV_CLK_C906_0_0 0x130 116 + #define REG_DIV_CLK_C906_0_1 0x134 117 + #define REG_DIV_CLK_C906_1_0 0x138 118 + #define REG_DIV_CLK_C906_1_1 0x13C 119 + #define REG_DIV_CLK_SRC_VIP_SYS_3 0x140 120 + #define REG_DIV_CLK_SRC_VIP_SYS_4 0x144 121 + 122 + #endif /* _CLK_SOPHGO_CV1800_H_ */
+66
drivers/clk/sophgo/clk-cv18xx-common.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (C) 2023 Inochi Amaoto <inochiama@outlook.com> 4 + */ 5 + 6 + #include <linux/io.h> 7 + #include <linux/iopoll.h> 8 + #include <linux/spinlock.h> 9 + #include <linux/bug.h> 10 + 11 + #include "clk-cv18xx-common.h" 12 + 13 + int cv1800_clk_setbit(struct cv1800_clk_common *common, 14 + struct cv1800_clk_regbit *field) 15 + { 16 + u32 mask = BIT(field->shift); 17 + u32 value; 18 + unsigned long flags; 19 + 20 + spin_lock_irqsave(common->lock, flags); 21 + 22 + value = readl(common->base + field->reg); 23 + writel(value | mask, common->base + field->reg); 24 + 25 + spin_unlock_irqrestore(common->lock, flags); 26 + 27 + return 0; 28 + } 29 + 30 + int cv1800_clk_clearbit(struct cv1800_clk_common *common, 31 + struct cv1800_clk_regbit *field) 32 + { 33 + u32 mask = BIT(field->shift); 34 + u32 value; 35 + unsigned long flags; 36 + 37 + spin_lock_irqsave(common->lock, flags); 38 + 39 + value = readl(common->base + field->reg); 40 + writel(value & ~mask, common->base + field->reg); 41 + 42 + spin_unlock_irqrestore(common->lock, flags); 43 + 44 + return 0; 45 + } 46 + 47 + int cv1800_clk_checkbit(struct cv1800_clk_common *common, 48 + struct cv1800_clk_regbit *field) 49 + { 50 + return readl(common->base + field->reg) & BIT(field->shift); 51 + } 52 + 53 + #define PLL_LOCK_TIMEOUT_US (200 * 1000) 54 + 55 + void cv1800_clk_wait_for_lock(struct cv1800_clk_common *common, 56 + u32 reg, u32 lock) 57 + { 58 + void __iomem *addr = common->base + reg; 59 + u32 regval; 60 + 61 + if (!lock) 62 + return; 63 + 64 + WARN_ON(readl_relaxed_poll_timeout(addr, regval, regval & lock, 65 + 100, PLL_LOCK_TIMEOUT_US)); 66 + }
+81
drivers/clk/sophgo/clk-cv18xx-common.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (C) 2023 Inochi Amaoto <inochiama@outlook.com> 4 + */ 5 + 6 + #ifndef _CLK_SOPHGO_CV18XX_IP_H_ 7 + #define _CLK_SOPHGO_CV18XX_IP_H_ 8 + 9 + #include <linux/compiler.h> 10 + #include <linux/clk-provider.h> 11 + #include <linux/bitfield.h> 12 + 13 + struct cv1800_clk_common { 14 + void __iomem *base; 15 + spinlock_t *lock; 16 + struct clk_hw hw; 17 + unsigned long features; 18 + }; 19 + 20 + #define CV1800_CLK_COMMON(_name, _parents, _op, _flags) \ 21 + { \ 22 + .hw.init = CLK_HW_INIT_PARENTS_DATA(_name, _parents, \ 23 + _op, _flags), \ 24 + } 25 + 26 + static inline struct cv1800_clk_common * 27 + hw_to_cv1800_clk_common(struct clk_hw *hw) 28 + { 29 + return container_of(hw, struct cv1800_clk_common, hw); 30 + } 31 + 32 + struct cv1800_clk_regbit { 33 + u16 reg; 34 + s8 shift; 35 + }; 36 + 37 + struct cv1800_clk_regfield { 38 + u16 reg; 39 + u8 shift; 40 + u8 width; 41 + s16 initval; 42 + unsigned long flags; 43 + }; 44 + 45 + #define CV1800_CLK_BIT(_reg, _shift) \ 46 + { \ 47 + .reg = _reg, \ 48 + .shift = _shift, \ 49 + } 50 + 51 + #define CV1800_CLK_REG(_reg, _shift, _width, _initval, _flags) \ 52 + { \ 53 + .reg = _reg, \ 54 + .shift = _shift, \ 55 + .width = _width, \ 56 + .initval = _initval, \ 57 + .flags = _flags, \ 58 + } 59 + 60 + #define cv1800_clk_regfield_genmask(_reg) \ 61 + GENMASK((_reg)->shift + (_reg)->width - 1, (_reg)->shift) 62 + #define cv1800_clk_regfield_get(_val, _reg) \ 63 + (((_val) >> (_reg)->shift) & GENMASK((_reg)->width - 1, 0)) 64 + #define cv1800_clk_regfield_set(_val, _new, _reg) \ 65 + (((_val) & ~cv1800_clk_regfield_genmask((_reg))) | \ 66 + (((_new) & GENMASK((_reg)->width - 1, 0)) << (_reg)->shift)) 67 + 68 + #define _CV1800_SET_FIELD(_reg, _val, _field) \ 69 + (((_reg) & ~(_field)) | FIELD_PREP((_field), (_val))) 70 + 71 + int cv1800_clk_setbit(struct cv1800_clk_common *common, 72 + struct cv1800_clk_regbit *field); 73 + int cv1800_clk_clearbit(struct cv1800_clk_common *common, 74 + struct cv1800_clk_regbit *field); 75 + int cv1800_clk_checkbit(struct cv1800_clk_common *common, 76 + struct cv1800_clk_regbit *field); 77 + 78 + void cv1800_clk_wait_for_lock(struct cv1800_clk_common *common, 79 + u32 reg, u32 lock); 80 + 81 + #endif // _CLK_SOPHGO_CV18XX_IP_H_
+887
drivers/clk/sophgo/clk-cv18xx-ip.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (C) 2023 Inochi Amaoto <inochiama@outlook.com> 4 + */ 5 + 6 + #include <linux/clk-provider.h> 7 + #include <linux/io.h> 8 + #include <linux/gcd.h> 9 + #include <linux/spinlock.h> 10 + 11 + #include "clk-cv18xx-ip.h" 12 + 13 + /* GATE */ 14 + static inline struct cv1800_clk_gate *hw_to_cv1800_clk_gate(struct clk_hw *hw) 15 + { 16 + struct cv1800_clk_common *common = hw_to_cv1800_clk_common(hw); 17 + 18 + return container_of(common, struct cv1800_clk_gate, common); 19 + } 20 + 21 + static int gate_enable(struct clk_hw *hw) 22 + { 23 + struct cv1800_clk_gate *gate = hw_to_cv1800_clk_gate(hw); 24 + 25 + return cv1800_clk_setbit(&gate->common, &gate->gate); 26 + } 27 + 28 + static void gate_disable(struct clk_hw *hw) 29 + { 30 + struct cv1800_clk_gate *gate = hw_to_cv1800_clk_gate(hw); 31 + 32 + cv1800_clk_clearbit(&gate->common, &gate->gate); 33 + } 34 + 35 + static int gate_is_enabled(struct clk_hw *hw) 36 + { 37 + struct cv1800_clk_gate *gate = hw_to_cv1800_clk_gate(hw); 38 + 39 + return cv1800_clk_checkbit(&gate->common, &gate->gate); 40 + } 41 + 42 + static unsigned long gate_recalc_rate(struct clk_hw *hw, 43 + unsigned long parent_rate) 44 + { 45 + return parent_rate; 46 + } 47 + 48 + static long gate_round_rate(struct clk_hw *hw, unsigned long rate, 49 + unsigned long *parent_rate) 50 + { 51 + return *parent_rate; 52 + } 53 + 54 + static int gate_set_rate(struct clk_hw *hw, unsigned long rate, 55 + unsigned long parent_rate) 56 + { 57 + return 0; 58 + } 59 + 60 + const struct clk_ops cv1800_clk_gate_ops = { 61 + .disable = gate_disable, 62 + .enable = gate_enable, 63 + .is_enabled = gate_is_enabled, 64 + 65 + .recalc_rate = gate_recalc_rate, 66 + .round_rate = gate_round_rate, 67 + .set_rate = gate_set_rate, 68 + }; 69 + 70 + /* DIV */ 71 + #define _DIV_EN_CLK_DIV_FACTOR_FIELD BIT(3) 72 + 73 + #define DIV_GET_EN_CLK_DIV_FACTOR(_reg) \ 74 + FIELD_GET(_DIV_EN_CLK_DIV_FACTOR_FIELD, _reg) 75 + 76 + #define DIV_SET_EN_DIV_FACTOR(_reg) \ 77 + _CV1800_SET_FIELD(_reg, 1, _DIV_EN_CLK_DIV_FACTOR_FIELD) 78 + 79 + static inline struct cv1800_clk_div *hw_to_cv1800_clk_div(struct clk_hw *hw) 80 + { 81 + struct cv1800_clk_common *common = hw_to_cv1800_clk_common(hw); 82 + 83 + return container_of(common, struct cv1800_clk_div, common); 84 + } 85 + 86 + static int div_enable(struct clk_hw *hw) 87 + { 88 + struct cv1800_clk_div *div = hw_to_cv1800_clk_div(hw); 89 + 90 + return cv1800_clk_setbit(&div->common, &div->gate); 91 + } 92 + 93 + static void div_disable(struct clk_hw *hw) 94 + { 95 + struct cv1800_clk_div *div = hw_to_cv1800_clk_div(hw); 96 + 97 + cv1800_clk_clearbit(&div->common, &div->gate); 98 + } 99 + 100 + static int div_is_enabled(struct clk_hw *hw) 101 + { 102 + struct cv1800_clk_div *div = hw_to_cv1800_clk_div(hw); 103 + 104 + return cv1800_clk_checkbit(&div->common, &div->gate); 105 + } 106 + 107 + static int div_helper_set_rate(struct cv1800_clk_common *common, 108 + struct cv1800_clk_regfield *div, 109 + unsigned long val) 110 + { 111 + unsigned long flags; 112 + u32 reg; 113 + 114 + if (div->width == 0) 115 + return 0; 116 + 117 + spin_lock_irqsave(common->lock, flags); 118 + 119 + reg = readl(common->base + div->reg); 120 + reg = cv1800_clk_regfield_set(reg, val, div); 121 + if (div->initval > 0) 122 + reg = DIV_SET_EN_DIV_FACTOR(reg); 123 + 124 + writel(reg, common->base + div->reg); 125 + 126 + spin_unlock_irqrestore(common->lock, flags); 127 + 128 + return 0; 129 + } 130 + 131 + static u32 div_helper_get_clockdiv(struct cv1800_clk_common *common, 132 + struct cv1800_clk_regfield *div) 133 + { 134 + u32 clockdiv = 1; 135 + u32 reg; 136 + 137 + if (!div || div->initval < 0 || (div->width == 0 && div->initval <= 0)) 138 + return 1; 139 + 140 + if (div->width == 0 && div->initval > 0) 141 + return div->initval; 142 + 143 + reg = readl(common->base + div->reg); 144 + 145 + if (div->initval == 0 || DIV_GET_EN_CLK_DIV_FACTOR(reg)) 146 + clockdiv = cv1800_clk_regfield_get(reg, div); 147 + else if (div->initval > 0) 148 + clockdiv = div->initval; 149 + 150 + return clockdiv; 151 + } 152 + 153 + static u32 div_helper_round_rate(struct cv1800_clk_regfield *div, 154 + struct clk_hw *hw, struct clk_hw *parent, 155 + unsigned long rate, unsigned long *prate) 156 + { 157 + if (div->width == 0) { 158 + if (div->initval <= 0) 159 + return DIV_ROUND_UP_ULL(*prate, 1); 160 + else 161 + return DIV_ROUND_UP_ULL(*prate, div->initval); 162 + } 163 + 164 + return divider_round_rate_parent(hw, parent, rate, prate, NULL, 165 + div->width, div->flags); 166 + } 167 + 168 + static long div_round_rate(struct clk_hw *parent, unsigned long *parent_rate, 169 + unsigned long rate, int id, void *data) 170 + { 171 + struct cv1800_clk_div *div = data; 172 + 173 + return div_helper_round_rate(&div->div, &div->common.hw, parent, 174 + rate, parent_rate); 175 + } 176 + 177 + static bool div_is_better_rate(struct cv1800_clk_common *common, 178 + unsigned long target, unsigned long now, 179 + unsigned long best) 180 + { 181 + if (common->features & CLK_DIVIDER_ROUND_CLOSEST) 182 + return abs_diff(target, now) < abs_diff(target, best); 183 + 184 + return now <= target && now > best; 185 + } 186 + 187 + static int mux_helper_determine_rate(struct cv1800_clk_common *common, 188 + struct clk_rate_request *req, 189 + long (*round)(struct clk_hw *, 190 + unsigned long *, 191 + unsigned long, 192 + int, 193 + void *), 194 + void *data) 195 + { 196 + unsigned long best_parent_rate = 0, best_rate = 0; 197 + struct clk_hw *best_parent, *hw = &common->hw; 198 + unsigned int i; 199 + 200 + if (clk_hw_get_flags(hw) & CLK_SET_RATE_NO_REPARENT) { 201 + unsigned long adj_parent_rate; 202 + 203 + best_parent = clk_hw_get_parent(hw); 204 + best_parent_rate = clk_hw_get_rate(best_parent); 205 + 206 + best_rate = round(best_parent, &adj_parent_rate, 207 + req->rate, -1, data); 208 + 209 + goto find; 210 + } 211 + 212 + for (i = 0; i < clk_hw_get_num_parents(hw); i++) { 213 + unsigned long tmp_rate, parent_rate; 214 + struct clk_hw *parent; 215 + 216 + parent = clk_hw_get_parent_by_index(hw, i); 217 + if (!parent) 218 + continue; 219 + 220 + parent_rate = clk_hw_get_rate(parent); 221 + 222 + tmp_rate = round(parent, &parent_rate, req->rate, i, data); 223 + 224 + if (tmp_rate == req->rate) { 225 + best_parent = parent; 226 + best_parent_rate = parent_rate; 227 + best_rate = tmp_rate; 228 + goto find; 229 + } 230 + 231 + if (div_is_better_rate(common, req->rate, 232 + tmp_rate, best_rate)) { 233 + best_parent = parent; 234 + best_parent_rate = parent_rate; 235 + best_rate = tmp_rate; 236 + } 237 + } 238 + 239 + if (best_rate == 0) 240 + return -EINVAL; 241 + 242 + find: 243 + req->best_parent_hw = best_parent; 244 + req->best_parent_rate = best_parent_rate; 245 + req->rate = best_rate; 246 + return 0; 247 + } 248 + 249 + static int div_determine_rate(struct clk_hw *hw, 250 + struct clk_rate_request *req) 251 + { 252 + struct cv1800_clk_div *div = hw_to_cv1800_clk_div(hw); 253 + 254 + return mux_helper_determine_rate(&div->common, req, 255 + div_round_rate, div); 256 + } 257 + 258 + static unsigned long div_recalc_rate(struct clk_hw *hw, 259 + unsigned long parent_rate) 260 + { 261 + struct cv1800_clk_div *div = hw_to_cv1800_clk_div(hw); 262 + unsigned long val; 263 + 264 + val = div_helper_get_clockdiv(&div->common, &div->div); 265 + if (val == 0) 266 + return 0; 267 + 268 + return divider_recalc_rate(hw, parent_rate, val, NULL, 269 + div->div.flags, div->div.width); 270 + } 271 + 272 + static int div_set_rate(struct clk_hw *hw, unsigned long rate, 273 + unsigned long parent_rate) 274 + { 275 + struct cv1800_clk_div *div = hw_to_cv1800_clk_div(hw); 276 + unsigned long val; 277 + 278 + val = divider_get_val(rate, parent_rate, NULL, 279 + div->div.width, div->div.flags); 280 + 281 + return div_helper_set_rate(&div->common, &div->div, val); 282 + } 283 + 284 + const struct clk_ops cv1800_clk_div_ops = { 285 + .disable = div_disable, 286 + .enable = div_enable, 287 + .is_enabled = div_is_enabled, 288 + 289 + .determine_rate = div_determine_rate, 290 + .recalc_rate = div_recalc_rate, 291 + .set_rate = div_set_rate, 292 + }; 293 + 294 + static inline struct cv1800_clk_bypass_div * 295 + hw_to_cv1800_clk_bypass_div(struct clk_hw *hw) 296 + { 297 + struct cv1800_clk_div *div = hw_to_cv1800_clk_div(hw); 298 + 299 + return container_of(div, struct cv1800_clk_bypass_div, div); 300 + } 301 + 302 + static long bypass_div_round_rate(struct clk_hw *parent, 303 + unsigned long *parent_rate, 304 + unsigned long rate, int id, void *data) 305 + { 306 + struct cv1800_clk_bypass_div *div = data; 307 + 308 + if (id == -1) { 309 + if (cv1800_clk_checkbit(&div->div.common, &div->bypass)) 310 + return *parent_rate; 311 + else 312 + return div_round_rate(parent, parent_rate, rate, 313 + -1, &div->div); 314 + } 315 + 316 + if (id == 0) 317 + return *parent_rate; 318 + 319 + return div_round_rate(parent, parent_rate, rate, id - 1, &div->div); 320 + } 321 + 322 + static int bypass_div_determine_rate(struct clk_hw *hw, 323 + struct clk_rate_request *req) 324 + { 325 + struct cv1800_clk_bypass_div *div = hw_to_cv1800_clk_bypass_div(hw); 326 + 327 + return mux_helper_determine_rate(&div->div.common, req, 328 + bypass_div_round_rate, div); 329 + } 330 + 331 + static unsigned long bypass_div_recalc_rate(struct clk_hw *hw, 332 + unsigned long parent_rate) 333 + { 334 + struct cv1800_clk_bypass_div *div = hw_to_cv1800_clk_bypass_div(hw); 335 + 336 + if (cv1800_clk_checkbit(&div->div.common, &div->bypass)) 337 + return parent_rate; 338 + 339 + return div_recalc_rate(hw, parent_rate); 340 + } 341 + 342 + static int bypass_div_set_rate(struct clk_hw *hw, unsigned long rate, 343 + unsigned long parent_rate) 344 + { 345 + struct cv1800_clk_bypass_div *div = hw_to_cv1800_clk_bypass_div(hw); 346 + 347 + if (cv1800_clk_checkbit(&div->div.common, &div->bypass)) 348 + return 0; 349 + 350 + return div_set_rate(hw, rate, parent_rate); 351 + } 352 + 353 + static u8 bypass_div_get_parent(struct clk_hw *hw) 354 + { 355 + struct cv1800_clk_bypass_div *div = hw_to_cv1800_clk_bypass_div(hw); 356 + 357 + if (cv1800_clk_checkbit(&div->div.common, &div->bypass)) 358 + return 0; 359 + 360 + return 1; 361 + } 362 + 363 + static int bypass_div_set_parent(struct clk_hw *hw, u8 index) 364 + { 365 + struct cv1800_clk_bypass_div *div = hw_to_cv1800_clk_bypass_div(hw); 366 + 367 + if (index) 368 + return cv1800_clk_clearbit(&div->div.common, &div->bypass); 369 + 370 + return cv1800_clk_setbit(&div->div.common, &div->bypass); 371 + } 372 + 373 + const struct clk_ops cv1800_clk_bypass_div_ops = { 374 + .disable = div_disable, 375 + .enable = div_enable, 376 + .is_enabled = div_is_enabled, 377 + 378 + .determine_rate = bypass_div_determine_rate, 379 + .recalc_rate = bypass_div_recalc_rate, 380 + .set_rate = bypass_div_set_rate, 381 + 382 + .set_parent = bypass_div_set_parent, 383 + .get_parent = bypass_div_get_parent, 384 + }; 385 + 386 + /* MUX */ 387 + static inline struct cv1800_clk_mux *hw_to_cv1800_clk_mux(struct clk_hw *hw) 388 + { 389 + struct cv1800_clk_common *common = hw_to_cv1800_clk_common(hw); 390 + 391 + return container_of(common, struct cv1800_clk_mux, common); 392 + } 393 + 394 + static int mux_enable(struct clk_hw *hw) 395 + { 396 + struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw); 397 + 398 + return cv1800_clk_setbit(&mux->common, &mux->gate); 399 + } 400 + 401 + static void mux_disable(struct clk_hw *hw) 402 + { 403 + struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw); 404 + 405 + cv1800_clk_clearbit(&mux->common, &mux->gate); 406 + } 407 + 408 + static int mux_is_enabled(struct clk_hw *hw) 409 + { 410 + struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw); 411 + 412 + return cv1800_clk_checkbit(&mux->common, &mux->gate); 413 + } 414 + 415 + static long mux_round_rate(struct clk_hw *parent, unsigned long *parent_rate, 416 + unsigned long rate, int id, void *data) 417 + { 418 + struct cv1800_clk_mux *mux = data; 419 + 420 + return div_helper_round_rate(&mux->div, &mux->common.hw, parent, 421 + rate, parent_rate); 422 + } 423 + 424 + static int mux_determine_rate(struct clk_hw *hw, 425 + struct clk_rate_request *req) 426 + { 427 + struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw); 428 + 429 + return mux_helper_determine_rate(&mux->common, req, 430 + mux_round_rate, mux); 431 + } 432 + 433 + static unsigned long mux_recalc_rate(struct clk_hw *hw, 434 + unsigned long parent_rate) 435 + { 436 + struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw); 437 + unsigned long val; 438 + 439 + val = div_helper_get_clockdiv(&mux->common, &mux->div); 440 + if (val == 0) 441 + return 0; 442 + 443 + return divider_recalc_rate(hw, parent_rate, val, NULL, 444 + mux->div.flags, mux->div.width); 445 + } 446 + 447 + static int mux_set_rate(struct clk_hw *hw, unsigned long rate, 448 + unsigned long parent_rate) 449 + { 450 + struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw); 451 + unsigned long val; 452 + 453 + val = divider_get_val(rate, parent_rate, NULL, 454 + mux->div.width, mux->div.flags); 455 + 456 + return div_helper_set_rate(&mux->common, &mux->div, val); 457 + } 458 + 459 + static u8 mux_get_parent(struct clk_hw *hw) 460 + { 461 + struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw); 462 + u32 reg = readl(mux->common.base + mux->mux.reg); 463 + 464 + return cv1800_clk_regfield_get(reg, &mux->mux); 465 + } 466 + 467 + static int _mux_set_parent(struct cv1800_clk_mux *mux, u8 index) 468 + { 469 + u32 reg; 470 + 471 + reg = readl(mux->common.base + mux->mux.reg); 472 + reg = cv1800_clk_regfield_set(reg, index, &mux->mux); 473 + writel(reg, mux->common.base + mux->mux.reg); 474 + 475 + return 0; 476 + } 477 + 478 + static int mux_set_parent(struct clk_hw *hw, u8 index) 479 + { 480 + struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw); 481 + unsigned long flags; 482 + 483 + spin_lock_irqsave(mux->common.lock, flags); 484 + 485 + _mux_set_parent(mux, index); 486 + 487 + spin_unlock_irqrestore(mux->common.lock, flags); 488 + 489 + return 0; 490 + } 491 + 492 + const struct clk_ops cv1800_clk_mux_ops = { 493 + .disable = mux_disable, 494 + .enable = mux_enable, 495 + .is_enabled = mux_is_enabled, 496 + 497 + .determine_rate = mux_determine_rate, 498 + .recalc_rate = mux_recalc_rate, 499 + .set_rate = mux_set_rate, 500 + 501 + .set_parent = mux_set_parent, 502 + .get_parent = mux_get_parent, 503 + }; 504 + 505 + static inline struct cv1800_clk_bypass_mux * 506 + hw_to_cv1800_clk_bypass_mux(struct clk_hw *hw) 507 + { 508 + struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw); 509 + 510 + return container_of(mux, struct cv1800_clk_bypass_mux, mux); 511 + } 512 + 513 + static long bypass_mux_round_rate(struct clk_hw *parent, 514 + unsigned long *parent_rate, 515 + unsigned long rate, int id, void *data) 516 + { 517 + struct cv1800_clk_bypass_mux *mux = data; 518 + 519 + if (id == -1) { 520 + if (cv1800_clk_checkbit(&mux->mux.common, &mux->bypass)) 521 + return *parent_rate; 522 + else 523 + return mux_round_rate(parent, parent_rate, rate, 524 + -1, &mux->mux); 525 + } 526 + 527 + if (id == 0) 528 + return *parent_rate; 529 + 530 + return mux_round_rate(parent, parent_rate, rate, id - 1, &mux->mux); 531 + } 532 + 533 + static int bypass_mux_determine_rate(struct clk_hw *hw, 534 + struct clk_rate_request *req) 535 + { 536 + struct cv1800_clk_bypass_mux *mux = hw_to_cv1800_clk_bypass_mux(hw); 537 + 538 + return mux_helper_determine_rate(&mux->mux.common, req, 539 + bypass_mux_round_rate, mux); 540 + } 541 + 542 + static unsigned long bypass_mux_recalc_rate(struct clk_hw *hw, 543 + unsigned long parent_rate) 544 + { 545 + struct cv1800_clk_bypass_mux *mux = hw_to_cv1800_clk_bypass_mux(hw); 546 + 547 + if (cv1800_clk_checkbit(&mux->mux.common, &mux->bypass)) 548 + return parent_rate; 549 + 550 + return mux_recalc_rate(hw, parent_rate); 551 + } 552 + 553 + static int bypass_mux_set_rate(struct clk_hw *hw, unsigned long rate, 554 + unsigned long parent_rate) 555 + { 556 + struct cv1800_clk_bypass_mux *mux = hw_to_cv1800_clk_bypass_mux(hw); 557 + 558 + if (cv1800_clk_checkbit(&mux->mux.common, &mux->bypass)) 559 + return 0; 560 + 561 + return mux_set_rate(hw, rate, parent_rate); 562 + } 563 + 564 + static u8 bypass_mux_get_parent(struct clk_hw *hw) 565 + { 566 + struct cv1800_clk_bypass_mux *mux = hw_to_cv1800_clk_bypass_mux(hw); 567 + 568 + if (cv1800_clk_checkbit(&mux->mux.common, &mux->bypass)) 569 + return 0; 570 + 571 + return mux_get_parent(hw) + 1; 572 + } 573 + 574 + static int bypass_mux_set_parent(struct clk_hw *hw, u8 index) 575 + { 576 + struct cv1800_clk_bypass_mux *mux = hw_to_cv1800_clk_bypass_mux(hw); 577 + 578 + if (index == 0) 579 + return cv1800_clk_setbit(&mux->mux.common, &mux->bypass); 580 + 581 + return cv1800_clk_clearbit(&mux->mux.common, &mux->bypass); 582 + } 583 + 584 + const struct clk_ops cv1800_clk_bypass_mux_ops = { 585 + .disable = mux_disable, 586 + .enable = mux_enable, 587 + .is_enabled = mux_is_enabled, 588 + 589 + .determine_rate = bypass_mux_determine_rate, 590 + .recalc_rate = bypass_mux_recalc_rate, 591 + .set_rate = bypass_mux_set_rate, 592 + 593 + .set_parent = bypass_mux_set_parent, 594 + .get_parent = bypass_mux_get_parent, 595 + }; 596 + 597 + /* MMUX */ 598 + static inline struct cv1800_clk_mmux *hw_to_cv1800_clk_mmux(struct clk_hw *hw) 599 + { 600 + struct cv1800_clk_common *common = hw_to_cv1800_clk_common(hw); 601 + 602 + return container_of(common, struct cv1800_clk_mmux, common); 603 + } 604 + 605 + static u8 mmux_get_parent_id(struct cv1800_clk_mmux *mmux) 606 + { 607 + struct clk_hw *hw = &mmux->common.hw; 608 + struct clk_hw *parent = clk_hw_get_parent(hw); 609 + unsigned int i; 610 + 611 + for (i = 0; i < clk_hw_get_num_parents(hw); i++) { 612 + if (parent == clk_hw_get_parent_by_index(hw, i)) 613 + return i; 614 + } 615 + 616 + unreachable(); 617 + } 618 + 619 + static int mmux_enable(struct clk_hw *hw) 620 + { 621 + struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw); 622 + 623 + return cv1800_clk_setbit(&mmux->common, &mmux->gate); 624 + } 625 + 626 + static void mmux_disable(struct clk_hw *hw) 627 + { 628 + struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw); 629 + 630 + cv1800_clk_clearbit(&mmux->common, &mmux->gate); 631 + } 632 + 633 + static int mmux_is_enabled(struct clk_hw *hw) 634 + { 635 + struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw); 636 + 637 + return cv1800_clk_checkbit(&mmux->common, &mmux->gate); 638 + } 639 + 640 + static long mmux_round_rate(struct clk_hw *parent, unsigned long *parent_rate, 641 + unsigned long rate, int id, void *data) 642 + { 643 + struct cv1800_clk_mmux *mmux = data; 644 + s8 div_id; 645 + 646 + if (id == -1) { 647 + if (cv1800_clk_checkbit(&mmux->common, &mmux->bypass)) 648 + return *parent_rate; 649 + 650 + id = mmux_get_parent_id(mmux); 651 + } 652 + 653 + div_id = mmux->parent2sel[id]; 654 + 655 + if (div_id < 0) 656 + return *parent_rate; 657 + 658 + return div_helper_round_rate(&mmux->div[div_id], 659 + &mmux->common.hw, parent, 660 + rate, parent_rate); 661 + } 662 + 663 + static int mmux_determine_rate(struct clk_hw *hw, 664 + struct clk_rate_request *req) 665 + { 666 + struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw); 667 + 668 + return mux_helper_determine_rate(&mmux->common, req, 669 + mmux_round_rate, mmux); 670 + } 671 + 672 + static unsigned long mmux_recalc_rate(struct clk_hw *hw, 673 + unsigned long parent_rate) 674 + { 675 + struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw); 676 + unsigned long val; 677 + struct cv1800_clk_regfield *div; 678 + 679 + if (cv1800_clk_checkbit(&mmux->common, &mmux->bypass)) 680 + return parent_rate; 681 + 682 + if (cv1800_clk_checkbit(&mmux->common, &mmux->clk_sel)) 683 + div = &mmux->div[0]; 684 + else 685 + div = &mmux->div[1]; 686 + 687 + val = div_helper_get_clockdiv(&mmux->common, div); 688 + if (val == 0) 689 + return 0; 690 + 691 + return divider_recalc_rate(hw, parent_rate, val, NULL, 692 + div->flags, div->width); 693 + } 694 + 695 + static int mmux_set_rate(struct clk_hw *hw, unsigned long rate, 696 + unsigned long parent_rate) 697 + { 698 + struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw); 699 + struct cv1800_clk_regfield *div; 700 + unsigned long val; 701 + 702 + if (cv1800_clk_checkbit(&mmux->common, &mmux->bypass)) 703 + return parent_rate; 704 + 705 + if (cv1800_clk_checkbit(&mmux->common, &mmux->clk_sel)) 706 + div = &mmux->div[0]; 707 + else 708 + div = &mmux->div[1]; 709 + 710 + val = divider_get_val(rate, parent_rate, NULL, 711 + div->width, div->flags); 712 + 713 + return div_helper_set_rate(&mmux->common, div, val); 714 + } 715 + 716 + static u8 mmux_get_parent(struct clk_hw *hw) 717 + { 718 + struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw); 719 + struct cv1800_clk_regfield *mux; 720 + u32 reg; 721 + s8 clk_sel; 722 + 723 + if (cv1800_clk_checkbit(&mmux->common, &mmux->bypass)) 724 + return 0; 725 + 726 + if (cv1800_clk_checkbit(&mmux->common, &mmux->clk_sel)) 727 + clk_sel = 0; 728 + else 729 + clk_sel = 1; 730 + mux = &mmux->mux[clk_sel]; 731 + 732 + reg = readl(mmux->common.base + mux->reg); 733 + 734 + return mmux->sel2parent[clk_sel][cv1800_clk_regfield_get(reg, mux)]; 735 + } 736 + 737 + static int mmux_set_parent(struct clk_hw *hw, u8 index) 738 + { 739 + struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw); 740 + struct cv1800_clk_regfield *mux; 741 + unsigned long flags; 742 + u32 reg; 743 + s8 clk_sel = mmux->parent2sel[index]; 744 + 745 + if (index == 0 || clk_sel == -1) { 746 + cv1800_clk_setbit(&mmux->common, &mmux->bypass); 747 + goto release; 748 + } 749 + 750 + cv1800_clk_clearbit(&mmux->common, &mmux->bypass); 751 + 752 + if (clk_sel) 753 + cv1800_clk_clearbit(&mmux->common, &mmux->clk_sel); 754 + else 755 + cv1800_clk_setbit(&mmux->common, &mmux->clk_sel); 756 + 757 + spin_lock_irqsave(mmux->common.lock, flags); 758 + 759 + mux = &mmux->mux[clk_sel]; 760 + reg = readl(mmux->common.base + mux->reg); 761 + reg = cv1800_clk_regfield_set(reg, index, mux); 762 + 763 + writel(reg, mmux->common.base + mux->reg); 764 + 765 + spin_unlock_irqrestore(mmux->common.lock, flags); 766 + 767 + release: 768 + return 0; 769 + } 770 + 771 + const struct clk_ops cv1800_clk_mmux_ops = { 772 + .disable = mmux_disable, 773 + .enable = mmux_enable, 774 + .is_enabled = mmux_is_enabled, 775 + 776 + .determine_rate = mmux_determine_rate, 777 + .recalc_rate = mmux_recalc_rate, 778 + .set_rate = mmux_set_rate, 779 + 780 + .set_parent = mmux_set_parent, 781 + .get_parent = mmux_get_parent, 782 + }; 783 + 784 + /* AUDIO CLK */ 785 + static inline struct cv1800_clk_audio * 786 + hw_to_cv1800_clk_audio(struct clk_hw *hw) 787 + { 788 + struct cv1800_clk_common *common = hw_to_cv1800_clk_common(hw); 789 + 790 + return container_of(common, struct cv1800_clk_audio, common); 791 + } 792 + 793 + static int aclk_enable(struct clk_hw *hw) 794 + { 795 + struct cv1800_clk_audio *aclk = hw_to_cv1800_clk_audio(hw); 796 + 797 + cv1800_clk_setbit(&aclk->common, &aclk->src_en); 798 + return cv1800_clk_setbit(&aclk->common, &aclk->output_en); 799 + } 800 + 801 + static void aclk_disable(struct clk_hw *hw) 802 + { 803 + struct cv1800_clk_audio *aclk = hw_to_cv1800_clk_audio(hw); 804 + 805 + cv1800_clk_clearbit(&aclk->common, &aclk->output_en); 806 + cv1800_clk_clearbit(&aclk->common, &aclk->src_en); 807 + } 808 + 809 + static int aclk_is_enabled(struct clk_hw *hw) 810 + { 811 + struct cv1800_clk_audio *aclk = hw_to_cv1800_clk_audio(hw); 812 + 813 + return cv1800_clk_checkbit(&aclk->common, &aclk->output_en); 814 + } 815 + 816 + static int aclk_determine_rate(struct clk_hw *hw, 817 + struct clk_rate_request *req) 818 + { 819 + struct cv1800_clk_audio *aclk = hw_to_cv1800_clk_audio(hw); 820 + 821 + req->rate = aclk->target_rate; 822 + 823 + return 0; 824 + } 825 + 826 + static unsigned long aclk_recalc_rate(struct clk_hw *hw, 827 + unsigned long parent_rate) 828 + { 829 + struct cv1800_clk_audio *aclk = hw_to_cv1800_clk_audio(hw); 830 + u64 rate = parent_rate; 831 + u64 factor = 2; 832 + u32 regval; 833 + 834 + if (!cv1800_clk_checkbit(&aclk->common, &aclk->div_en)) 835 + return 0; 836 + 837 + regval = readl(aclk->common.base + aclk->m.reg); 838 + factor *= cv1800_clk_regfield_get(regval, &aclk->m); 839 + 840 + regval = readl(aclk->common.base + aclk->n.reg); 841 + rate *= cv1800_clk_regfield_get(regval, &aclk->n); 842 + 843 + return DIV64_U64_ROUND_UP(rate, factor); 844 + } 845 + 846 + static void aclk_determine_mn(unsigned long parent_rate, unsigned long rate, 847 + u32 *m, u32 *n) 848 + { 849 + u32 tm = parent_rate / 2; 850 + u32 tn = rate; 851 + u32 tcommon = gcd(tm, tn); 852 + *m = tm / tcommon; 853 + *n = tn / tcommon; 854 + } 855 + 856 + static int aclk_set_rate(struct clk_hw *hw, unsigned long rate, 857 + unsigned long parent_rate) 858 + { 859 + struct cv1800_clk_audio *aclk = hw_to_cv1800_clk_audio(hw); 860 + unsigned long flags; 861 + u32 m, n; 862 + 863 + aclk_determine_mn(parent_rate, rate, 864 + &m, &n); 865 + 866 + spin_lock_irqsave(aclk->common.lock, flags); 867 + 868 + writel(m, aclk->common.base + aclk->m.reg); 869 + writel(n, aclk->common.base + aclk->n.reg); 870 + 871 + cv1800_clk_setbit(&aclk->common, &aclk->div_en); 872 + cv1800_clk_setbit(&aclk->common, &aclk->div_up); 873 + 874 + spin_unlock_irqrestore(aclk->common.lock, flags); 875 + 876 + return 0; 877 + } 878 + 879 + const struct clk_ops cv1800_clk_audio_ops = { 880 + .disable = aclk_disable, 881 + .enable = aclk_enable, 882 + .is_enabled = aclk_is_enabled, 883 + 884 + .determine_rate = aclk_determine_rate, 885 + .recalc_rate = aclk_recalc_rate, 886 + .set_rate = aclk_set_rate, 887 + };
+261
drivers/clk/sophgo/clk-cv18xx-ip.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (C) 2023 Inochi Amaoto <inochiama@outlook.com> 4 + */ 5 + 6 + #ifndef _CLK_SOPHGO_CV1800_IP_H_ 7 + #define _CLK_SOPHGO_CV1800_IP_H_ 8 + 9 + #include "clk-cv18xx-common.h" 10 + 11 + struct cv1800_clk_gate { 12 + struct cv1800_clk_common common; 13 + struct cv1800_clk_regbit gate; 14 + }; 15 + 16 + struct cv1800_clk_div_data { 17 + u32 reg; 18 + u32 mask; 19 + u32 width; 20 + u32 init; 21 + u32 flags; 22 + }; 23 + 24 + struct cv1800_clk_div { 25 + struct cv1800_clk_common common; 26 + struct cv1800_clk_regbit gate; 27 + struct cv1800_clk_regfield div; 28 + }; 29 + 30 + struct cv1800_clk_bypass_div { 31 + struct cv1800_clk_div div; 32 + struct cv1800_clk_regbit bypass; 33 + }; 34 + 35 + struct cv1800_clk_mux { 36 + struct cv1800_clk_common common; 37 + struct cv1800_clk_regbit gate; 38 + struct cv1800_clk_regfield div; 39 + struct cv1800_clk_regfield mux; 40 + }; 41 + 42 + struct cv1800_clk_bypass_mux { 43 + struct cv1800_clk_mux mux; 44 + struct cv1800_clk_regbit bypass; 45 + }; 46 + 47 + struct cv1800_clk_mmux { 48 + struct cv1800_clk_common common; 49 + struct cv1800_clk_regbit gate; 50 + struct cv1800_clk_regfield div[2]; 51 + struct cv1800_clk_regfield mux[2]; 52 + struct cv1800_clk_regbit bypass; 53 + struct cv1800_clk_regbit clk_sel; 54 + const s8 *parent2sel; 55 + const u8 *sel2parent[2]; 56 + }; 57 + 58 + struct cv1800_clk_audio { 59 + struct cv1800_clk_common common; 60 + struct cv1800_clk_regbit src_en; 61 + struct cv1800_clk_regbit output_en; 62 + struct cv1800_clk_regbit div_en; 63 + struct cv1800_clk_regbit div_up; 64 + struct cv1800_clk_regfield m; 65 + struct cv1800_clk_regfield n; 66 + u32 target_rate; 67 + }; 68 + 69 + #define CV1800_GATE(_name, _parent, _gate_reg, _gate_shift, _flags) \ 70 + struct cv1800_clk_gate _name = { \ 71 + .common = CV1800_CLK_COMMON(#_name, _parent, \ 72 + &cv1800_clk_gate_ops, \ 73 + _flags), \ 74 + .gate = CV1800_CLK_BIT(_gate_reg, _gate_shift), \ 75 + } 76 + 77 + #define _CV1800_DIV(_name, _parent, _gate_reg, _gate_shift, \ 78 + _div_reg, _div_shift, _div_width, _div_init, \ 79 + _div_flag, _ops, _flags) \ 80 + { \ 81 + .common = CV1800_CLK_COMMON(#_name, _parent, \ 82 + _ops, _flags), \ 83 + .gate = CV1800_CLK_BIT(_gate_reg, \ 84 + _gate_shift), \ 85 + .div = CV1800_CLK_REG(_div_reg, _div_shift, \ 86 + _div_width, _div_init, \ 87 + _div_flag), \ 88 + } 89 + 90 + #define _CV1800_FIXED_DIV_FLAG \ 91 + (CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ROUND_CLOSEST) 92 + 93 + #define _CV1800_FIXED_DIV(_name, _parent, _gate_reg, _gate_shift, \ 94 + _fix_div, _ops, _flags) \ 95 + { \ 96 + .common = CV1800_CLK_COMMON(#_name, _parent, \ 97 + _ops, _flags), \ 98 + .gate = CV1800_CLK_BIT(_gate_reg, \ 99 + _gate_shift), \ 100 + .div = CV1800_CLK_REG(0, 0, 0, \ 101 + _fix_div, \ 102 + _CV1800_FIXED_DIV_FLAG),\ 103 + } 104 + 105 + #define CV1800_DIV(_name, _parent, _gate_reg, _gate_shift, \ 106 + _div_reg, _div_shift, _div_width, _div_init, \ 107 + _div_flag, _flags) \ 108 + struct cv1800_clk_div _name = \ 109 + _CV1800_DIV(_name, _parent, _gate_reg, _gate_shift, \ 110 + _div_reg, _div_shift, _div_width, _div_init,\ 111 + _div_flag, &cv1800_clk_div_ops, _flags) 112 + 113 + #define CV1800_BYPASS_DIV(_name, _parent, _gate_reg, _gate_shift, \ 114 + _div_reg, _div_shift, _div_width, _div_init, \ 115 + _div_flag, _bypass_reg, _bypass_shift, _flags)\ 116 + struct cv1800_clk_bypass_div _name = { \ 117 + .div = _CV1800_DIV(_name, _parent, \ 118 + _gate_reg, _gate_shift, \ 119 + _div_reg, _div_shift, \ 120 + _div_width, _div_init, _div_flag, \ 121 + &cv1800_clk_bypass_div_ops, \ 122 + _flags), \ 123 + .bypass = CV1800_CLK_BIT(_bypass_reg, _bypass_shift), \ 124 + } 125 + 126 + #define CV1800_FIXED_DIV(_name, _parent, _gate_reg, _gate_shift, \ 127 + _fix_div, _flags) \ 128 + struct cv1800_clk_div _name = \ 129 + _CV1800_FIXED_DIV(_name, _parent, \ 130 + _gate_reg, _gate_shift, \ 131 + _fix_div, \ 132 + &cv1800_clk_div_ops, _flags) \ 133 + 134 + #define CV1800_BYPASS_FIXED_DIV(_name, _parent, _gate_reg, _gate_shift, \ 135 + _fix_div, _bypass_reg, _bypass_shift, \ 136 + _flags) \ 137 + struct cv1800_clk_bypass_div _name = { \ 138 + .div = _CV1800_FIXED_DIV(_name, _parent, \ 139 + _gate_reg, _gate_shift, \ 140 + _fix_div, \ 141 + &cv1800_clk_bypass_div_ops, \ 142 + _flags), \ 143 + .bypass = CV1800_CLK_BIT(_bypass_reg, _bypass_shift), \ 144 + } 145 + 146 + #define _CV1800_MUX(_name, _parent, _gate_reg, _gate_shift, \ 147 + _div_reg, _div_shift, _div_width, _div_init, \ 148 + _div_flag, \ 149 + _mux_reg, _mux_shift, _mux_width, \ 150 + _ops, _flags) \ 151 + { \ 152 + .common = CV1800_CLK_COMMON(#_name, _parent, \ 153 + _ops, _flags), \ 154 + .gate = CV1800_CLK_BIT(_gate_reg, \ 155 + _gate_shift), \ 156 + .div = CV1800_CLK_REG(_div_reg, _div_shift, \ 157 + _div_width, _div_init, \ 158 + _div_flag), \ 159 + .mux = CV1800_CLK_REG(_mux_reg, _mux_shift, \ 160 + _mux_width, 0, 0), \ 161 + } 162 + 163 + #define CV1800_MUX(_name, _parent, _gate_reg, _gate_shift, \ 164 + _div_reg, _div_shift, _div_width, _div_init, \ 165 + _div_flag, \ 166 + _mux_reg, _mux_shift, _mux_width, _flags) \ 167 + struct cv1800_clk_mux _name = \ 168 + _CV1800_MUX(_name, _parent, _gate_reg, _gate_shift, \ 169 + _div_reg, _div_shift, _div_width, _div_init,\ 170 + _div_flag, _mux_reg, _mux_shift, _mux_width,\ 171 + &cv1800_clk_mux_ops, _flags) 172 + 173 + #define CV1800_BYPASS_MUX(_name, _parent, _gate_reg, _gate_shift, \ 174 + _div_reg, _div_shift, _div_width, _div_init, \ 175 + _div_flag, \ 176 + _mux_reg, _mux_shift, _mux_width, \ 177 + _bypass_reg, _bypass_shift, _flags) \ 178 + struct cv1800_clk_bypass_mux _name = { \ 179 + .mux = _CV1800_MUX(_name, _parent, \ 180 + _gate_reg, _gate_shift, \ 181 + _div_reg, _div_shift, _div_width, \ 182 + _div_init, _div_flag, \ 183 + _mux_reg, _mux_shift, _mux_width, \ 184 + &cv1800_clk_bypass_mux_ops, \ 185 + _flags), \ 186 + .bypass = CV1800_CLK_BIT(_bypass_reg, _bypass_shift), \ 187 + } 188 + 189 + #define CV1800_MMUX(_name, _parent, _gate_reg, _gate_shift, \ 190 + _div0_reg, _div0_shift, _div0_width, _div0_init, \ 191 + _div0_flag, \ 192 + _div1_reg, _div1_shift, _div1_width, _div1_init, \ 193 + _div1_flag, \ 194 + _mux0_reg, _mux0_shift, _mux0_width, \ 195 + _mux1_reg, _mux1_shift, _mux1_width, \ 196 + _bypass_reg, _bypass_shift, \ 197 + _clk_sel_reg, _clk_sel_shift, \ 198 + _parent2sel, _sel2parent0, _sel2parent1, _flags) \ 199 + struct cv1800_clk_mmux _name = { \ 200 + .common = CV1800_CLK_COMMON(#_name, _parent, \ 201 + &cv1800_clk_mmux_ops,\ 202 + _flags), \ 203 + .gate = CV1800_CLK_BIT(_gate_reg, _gate_shift),\ 204 + .div = { \ 205 + CV1800_CLK_REG(_div0_reg, _div0_shift, \ 206 + _div0_width, _div0_init, \ 207 + _div0_flag), \ 208 + CV1800_CLK_REG(_div1_reg, _div1_shift, \ 209 + _div1_width, _div1_init, \ 210 + _div1_flag), \ 211 + }, \ 212 + .mux = { \ 213 + CV1800_CLK_REG(_mux0_reg, _mux0_shift, \ 214 + _mux0_width, 0, 0), \ 215 + CV1800_CLK_REG(_mux1_reg, _mux1_shift, \ 216 + _mux1_width, 0, 0), \ 217 + }, \ 218 + .bypass = CV1800_CLK_BIT(_bypass_reg, \ 219 + _bypass_shift), \ 220 + .clk_sel = CV1800_CLK_BIT(_clk_sel_reg, \ 221 + _clk_sel_shift), \ 222 + .parent2sel = _parent2sel, \ 223 + .sel2parent = { _sel2parent0, _sel2parent1 }, \ 224 + } 225 + 226 + #define CV1800_ACLK(_name, _parent, \ 227 + _src_en_reg, _src_en_reg_shift, \ 228 + _output_en_reg, _output_en_shift, \ 229 + _div_en_reg, _div_en_reg_shift, \ 230 + _div_up_reg, _div_up_reg_shift, \ 231 + _m_reg, _m_shift, _m_width, _m_flag, \ 232 + _n_reg, _n_shift, _n_width, _n_flag, \ 233 + _target_rate, _flags) \ 234 + struct cv1800_clk_audio _name = { \ 235 + .common = CV1800_CLK_COMMON(#_name, _parent, \ 236 + &cv1800_clk_audio_ops,\ 237 + _flags), \ 238 + .src_en = CV1800_CLK_BIT(_src_en_reg, \ 239 + _src_en_reg_shift), \ 240 + .output_en = CV1800_CLK_BIT(_output_en_reg, \ 241 + _output_en_shift), \ 242 + .div_en = CV1800_CLK_BIT(_div_en_reg, \ 243 + _div_en_reg_shift), \ 244 + .div_up = CV1800_CLK_BIT(_div_up_reg, \ 245 + _div_up_reg_shift), \ 246 + .m = CV1800_CLK_REG(_m_reg, _m_shift, \ 247 + _m_width, 0, _m_flag), \ 248 + .n = CV1800_CLK_REG(_n_reg, _n_shift, \ 249 + _n_width, 0, _n_flag), \ 250 + .target_rate = _target_rate, \ 251 + } 252 + 253 + extern const struct clk_ops cv1800_clk_gate_ops; 254 + extern const struct clk_ops cv1800_clk_div_ops; 255 + extern const struct clk_ops cv1800_clk_bypass_div_ops; 256 + extern const struct clk_ops cv1800_clk_mux_ops; 257 + extern const struct clk_ops cv1800_clk_bypass_mux_ops; 258 + extern const struct clk_ops cv1800_clk_mmux_ops; 259 + extern const struct clk_ops cv1800_clk_audio_ops; 260 + 261 + #endif // _CLK_SOPHGO_CV1800_IP_H_
+420
drivers/clk/sophgo/clk-cv18xx-pll.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (C) 2023 Inochi Amaoto <inochiama@outlook.com> 4 + */ 5 + 6 + #include <linux/clk-provider.h> 7 + #include <linux/io.h> 8 + #include <linux/limits.h> 9 + #include <linux/spinlock.h> 10 + 11 + #include "clk-cv18xx-pll.h" 12 + 13 + static inline struct cv1800_clk_pll *hw_to_cv1800_clk_pll(struct clk_hw *hw) 14 + { 15 + struct cv1800_clk_common *common = hw_to_cv1800_clk_common(hw); 16 + 17 + return container_of(common, struct cv1800_clk_pll, common); 18 + } 19 + 20 + static unsigned long ipll_calc_rate(unsigned long parent_rate, 21 + unsigned long pre_div_sel, 22 + unsigned long div_sel, 23 + unsigned long post_div_sel) 24 + { 25 + uint64_t rate = parent_rate; 26 + 27 + rate *= div_sel; 28 + do_div(rate, pre_div_sel * post_div_sel); 29 + 30 + return rate; 31 + } 32 + 33 + static unsigned long ipll_recalc_rate(struct clk_hw *hw, 34 + unsigned long parent_rate) 35 + { 36 + struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw); 37 + u32 value; 38 + 39 + value = readl(pll->common.base + pll->pll_reg); 40 + 41 + return ipll_calc_rate(parent_rate, 42 + PLL_GET_PRE_DIV_SEL(value), 43 + PLL_GET_DIV_SEL(value), 44 + PLL_GET_POST_DIV_SEL(value)); 45 + } 46 + 47 + static int ipll_find_rate(const struct cv1800_clk_pll_limit *limit, 48 + unsigned long prate, unsigned long *rate, 49 + u32 *value) 50 + { 51 + unsigned long best_rate = 0; 52 + unsigned long trate = *rate; 53 + unsigned long pre_div_sel = 0, div_sel = 0, post_div_sel = 0; 54 + unsigned long pre, div, post; 55 + u32 detected = *value; 56 + unsigned long tmp; 57 + 58 + for_each_pll_limit_range(pre, &limit->pre_div) { 59 + for_each_pll_limit_range(div, &limit->div) { 60 + for_each_pll_limit_range(post, &limit->post_div) { 61 + tmp = ipll_calc_rate(prate, pre, div, post); 62 + 63 + if (tmp > trate) 64 + continue; 65 + 66 + if ((trate - tmp) < (trate - best_rate)) { 67 + best_rate = tmp; 68 + pre_div_sel = pre; 69 + div_sel = div; 70 + post_div_sel = post; 71 + } 72 + } 73 + } 74 + } 75 + 76 + if (best_rate) { 77 + detected = PLL_SET_PRE_DIV_SEL(detected, pre_div_sel); 78 + detected = PLL_SET_POST_DIV_SEL(detected, post_div_sel); 79 + detected = PLL_SET_DIV_SEL(detected, div_sel); 80 + *value = detected; 81 + *rate = best_rate; 82 + return 0; 83 + } 84 + 85 + return -EINVAL; 86 + } 87 + 88 + static int ipll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) 89 + { 90 + u32 val; 91 + struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw); 92 + 93 + return ipll_find_rate(pll->pll_limit, req->best_parent_rate, 94 + &req->rate, &val); 95 + } 96 + 97 + static void pll_get_mode_ctrl(unsigned long div_sel, 98 + bool (*mode_ctrl_check)(unsigned long, 99 + unsigned long, 100 + unsigned long), 101 + const struct cv1800_clk_pll_limit *limit, 102 + u32 *value) 103 + { 104 + unsigned long ictrl = 0, mode = 0; 105 + u32 detected = *value; 106 + 107 + for_each_pll_limit_range(mode, &limit->mode) { 108 + for_each_pll_limit_range(ictrl, &limit->ictrl) { 109 + if (mode_ctrl_check(div_sel, ictrl, mode)) { 110 + detected = PLL_SET_SEL_MODE(detected, mode); 111 + detected = PLL_SET_ICTRL(detected, ictrl); 112 + *value = detected; 113 + return; 114 + } 115 + } 116 + } 117 + } 118 + 119 + static bool ipll_check_mode_ctrl_restrict(unsigned long div_sel, 120 + unsigned long ictrl, 121 + unsigned long mode) 122 + { 123 + unsigned long left_rest = 20 * div_sel; 124 + unsigned long right_rest = 35 * div_sel; 125 + unsigned long test = 184 * (1 + mode) * (1 + ictrl) / 2; 126 + 127 + return test > left_rest && test <= right_rest; 128 + } 129 + 130 + static int ipll_set_rate(struct clk_hw *hw, unsigned long rate, 131 + unsigned long parent_rate) 132 + { 133 + u32 regval, detected = 0; 134 + unsigned long flags; 135 + struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw); 136 + 137 + ipll_find_rate(pll->pll_limit, parent_rate, &rate, &detected); 138 + pll_get_mode_ctrl(PLL_GET_DIV_SEL(detected), 139 + ipll_check_mode_ctrl_restrict, 140 + pll->pll_limit, &detected); 141 + 142 + spin_lock_irqsave(pll->common.lock, flags); 143 + 144 + regval = readl(pll->common.base + pll->pll_reg); 145 + regval = PLL_COPY_REG(regval, detected); 146 + 147 + writel(regval, pll->common.base + pll->pll_reg); 148 + 149 + spin_unlock_irqrestore(pll->common.lock, flags); 150 + 151 + cv1800_clk_wait_for_lock(&pll->common, pll->pll_status.reg, 152 + BIT(pll->pll_status.shift)); 153 + 154 + return 0; 155 + } 156 + 157 + static int pll_enable(struct clk_hw *hw) 158 + { 159 + struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw); 160 + 161 + return cv1800_clk_clearbit(&pll->common, &pll->pll_pwd); 162 + } 163 + 164 + static void pll_disable(struct clk_hw *hw) 165 + { 166 + struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw); 167 + 168 + cv1800_clk_setbit(&pll->common, &pll->pll_pwd); 169 + } 170 + 171 + static int pll_is_enable(struct clk_hw *hw) 172 + { 173 + struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw); 174 + 175 + return cv1800_clk_checkbit(&pll->common, &pll->pll_pwd) == 0; 176 + } 177 + 178 + const struct clk_ops cv1800_clk_ipll_ops = { 179 + .disable = pll_disable, 180 + .enable = pll_enable, 181 + .is_enabled = pll_is_enable, 182 + 183 + .recalc_rate = ipll_recalc_rate, 184 + .determine_rate = ipll_determine_rate, 185 + .set_rate = ipll_set_rate, 186 + }; 187 + 188 + #define PLL_SYN_FACTOR_DOT_POS 26 189 + #define PLL_SYN_FACTOR_MINIMUM ((4 << PLL_SYN_FACTOR_DOT_POS) + 1) 190 + 191 + static bool fpll_is_factional_mode(struct cv1800_clk_pll *pll) 192 + { 193 + return cv1800_clk_checkbit(&pll->common, &pll->pll_syn->en); 194 + } 195 + 196 + static unsigned long fpll_calc_rate(unsigned long parent_rate, 197 + unsigned long pre_div_sel, 198 + unsigned long div_sel, 199 + unsigned long post_div_sel, 200 + unsigned long ssc_syn_set, 201 + bool is_full_parent) 202 + { 203 + u64 dividend = parent_rate * div_sel; 204 + u64 factor = ssc_syn_set * pre_div_sel * post_div_sel; 205 + unsigned long rate; 206 + 207 + dividend <<= PLL_SYN_FACTOR_DOT_POS - 1; 208 + rate = dividend / factor; 209 + dividend %= factor; 210 + 211 + if (is_full_parent) { 212 + dividend <<= 1; 213 + rate <<= 1; 214 + } 215 + 216 + rate += DIV64_U64_ROUND_CLOSEST(dividend, factor); 217 + 218 + return rate; 219 + } 220 + 221 + static unsigned long fpll_recalc_rate(struct clk_hw *hw, 222 + unsigned long parent_rate) 223 + { 224 + struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw); 225 + u32 value; 226 + bool clk_full; 227 + u32 syn_set; 228 + 229 + if (!fpll_is_factional_mode(pll)) 230 + return ipll_recalc_rate(hw, parent_rate); 231 + 232 + syn_set = readl(pll->common.base + pll->pll_syn->set); 233 + 234 + if (syn_set == 0) 235 + return 0; 236 + 237 + clk_full = cv1800_clk_checkbit(&pll->common, 238 + &pll->pll_syn->clk_half); 239 + 240 + value = readl(pll->common.base + pll->pll_reg); 241 + 242 + return fpll_calc_rate(parent_rate, 243 + PLL_GET_PRE_DIV_SEL(value), 244 + PLL_GET_DIV_SEL(value), 245 + PLL_GET_POST_DIV_SEL(value), 246 + syn_set, clk_full); 247 + } 248 + 249 + static unsigned long fpll_find_synthesizer(unsigned long parent, 250 + unsigned long rate, 251 + unsigned long pre_div, 252 + unsigned long div, 253 + unsigned long post_div, 254 + bool is_full_parent, 255 + u32 *ssc_syn_set) 256 + { 257 + u32 test_max = U32_MAX, test_min = PLL_SYN_FACTOR_MINIMUM; 258 + unsigned long trate; 259 + 260 + while (test_min < test_max) { 261 + u32 tssc = (test_max + test_min) / 2; 262 + 263 + trate = fpll_calc_rate(parent, pre_div, div, post_div, 264 + tssc, is_full_parent); 265 + 266 + if (trate == rate) { 267 + test_min = tssc; 268 + break; 269 + } 270 + 271 + if (trate > rate) 272 + test_min = tssc + 1; 273 + else 274 + test_max = tssc - 1; 275 + } 276 + 277 + if (trate != 0) 278 + *ssc_syn_set = test_min; 279 + 280 + return trate; 281 + } 282 + 283 + static int fpll_find_rate(struct cv1800_clk_pll *pll, 284 + const struct cv1800_clk_pll_limit *limit, 285 + unsigned long prate, 286 + unsigned long *rate, 287 + u32 *value, u32 *ssc_syn_set) 288 + { 289 + unsigned long best_rate = 0; 290 + unsigned long pre_div_sel = 0, div_sel = 0, post_div_sel = 0; 291 + unsigned long pre, div, post; 292 + unsigned long trate = *rate; 293 + u32 detected = *value; 294 + unsigned long tmp; 295 + bool clk_full = cv1800_clk_checkbit(&pll->common, 296 + &pll->pll_syn->clk_half); 297 + 298 + for_each_pll_limit_range(pre, &limit->pre_div) { 299 + for_each_pll_limit_range(post, &limit->post_div) { 300 + for_each_pll_limit_range(div, &limit->div) { 301 + tmp = fpll_find_synthesizer(prate, trate, 302 + pre, div, post, 303 + clk_full, 304 + ssc_syn_set); 305 + 306 + if ((trate - tmp) < (trate - best_rate)) { 307 + best_rate = tmp; 308 + pre_div_sel = pre; 309 + div_sel = div; 310 + post_div_sel = post; 311 + } 312 + } 313 + } 314 + } 315 + 316 + if (best_rate) { 317 + detected = PLL_SET_PRE_DIV_SEL(detected, pre_div_sel); 318 + detected = PLL_SET_POST_DIV_SEL(detected, post_div_sel); 319 + detected = PLL_SET_DIV_SEL(detected, div_sel); 320 + *value = detected; 321 + *rate = best_rate; 322 + return 0; 323 + } 324 + 325 + return -EINVAL; 326 + } 327 + 328 + static int fpll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) 329 + { 330 + struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw); 331 + u32 val, ssc_syn_set; 332 + 333 + if (!fpll_is_factional_mode(pll)) 334 + return ipll_determine_rate(hw, req); 335 + 336 + fpll_find_rate(pll, &pll->pll_limit[2], req->best_parent_rate, 337 + &req->rate, &val, &ssc_syn_set); 338 + 339 + return 0; 340 + } 341 + 342 + static bool fpll_check_mode_ctrl_restrict(unsigned long div_sel, 343 + unsigned long ictrl, 344 + unsigned long mode) 345 + { 346 + unsigned long left_rest = 10 * div_sel; 347 + unsigned long right_rest = 24 * div_sel; 348 + unsigned long test = 184 * (1 + mode) * (1 + ictrl) / 2; 349 + 350 + return test > left_rest && test <= right_rest; 351 + } 352 + 353 + static int fpll_set_rate(struct clk_hw *hw, unsigned long rate, 354 + unsigned long parent_rate) 355 + { 356 + u32 regval; 357 + u32 detected = 0, detected_ssc = 0; 358 + unsigned long flags; 359 + struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw); 360 + 361 + if (!fpll_is_factional_mode(pll)) 362 + return ipll_set_rate(hw, rate, parent_rate); 363 + 364 + fpll_find_rate(pll, &pll->pll_limit[2], parent_rate, 365 + &rate, &detected, &detected_ssc); 366 + pll_get_mode_ctrl(PLL_GET_DIV_SEL(detected), 367 + fpll_check_mode_ctrl_restrict, 368 + pll->pll_limit, &detected); 369 + 370 + spin_lock_irqsave(pll->common.lock, flags); 371 + 372 + writel(detected_ssc, pll->common.base + pll->pll_syn->set); 373 + 374 + regval = readl(pll->common.base + pll->pll_reg); 375 + regval = PLL_COPY_REG(regval, detected); 376 + 377 + writel(regval, pll->common.base + pll->pll_reg); 378 + 379 + spin_unlock_irqrestore(pll->common.lock, flags); 380 + 381 + cv1800_clk_wait_for_lock(&pll->common, pll->pll_status.reg, 382 + BIT(pll->pll_status.shift)); 383 + 384 + return 0; 385 + } 386 + 387 + static u8 fpll_get_parent(struct clk_hw *hw) 388 + { 389 + struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw); 390 + 391 + if (fpll_is_factional_mode(pll)) 392 + return 1; 393 + 394 + return 0; 395 + } 396 + 397 + static int fpll_set_parent(struct clk_hw *hw, u8 index) 398 + { 399 + struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw); 400 + 401 + if (index) 402 + cv1800_clk_setbit(&pll->common, &pll->pll_syn->en); 403 + else 404 + cv1800_clk_clearbit(&pll->common, &pll->pll_syn->en); 405 + 406 + return 0; 407 + } 408 + 409 + const struct clk_ops cv1800_clk_fpll_ops = { 410 + .disable = pll_disable, 411 + .enable = pll_enable, 412 + .is_enabled = pll_is_enable, 413 + 414 + .recalc_rate = fpll_recalc_rate, 415 + .determine_rate = fpll_determine_rate, 416 + .set_rate = fpll_set_rate, 417 + 418 + .set_parent = fpll_set_parent, 419 + .get_parent = fpll_get_parent, 420 + };
+118
drivers/clk/sophgo/clk-cv18xx-pll.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (C) 2023 Inochi Amaoto <inochiama@outlook.com> 4 + */ 5 + 6 + #ifndef _CLK_SOPHGO_CV1800_PLL_H_ 7 + #define _CLK_SOPHGO_CV1800_PLL_H_ 8 + 9 + #include "clk-cv18xx-common.h" 10 + 11 + struct cv1800_clk_pll_limit { 12 + struct { 13 + u8 min; 14 + u8 max; 15 + } pre_div, div, post_div, ictrl, mode; 16 + }; 17 + 18 + #define _CV1800_PLL_LIMIT(_min, _max) \ 19 + { \ 20 + .min = _min, \ 21 + .max = _max, \ 22 + } \ 23 + 24 + #define for_each_pll_limit_range(_var, _restrict) \ 25 + for (_var = (_restrict)->min; _var <= (_restrict)->max; _var++) 26 + 27 + struct cv1800_clk_pll_synthesizer { 28 + struct cv1800_clk_regbit en; 29 + struct cv1800_clk_regbit clk_half; 30 + u32 ctrl; 31 + u32 set; 32 + }; 33 + 34 + #define _PLL_PRE_DIV_SEL_FIELD GENMASK(6, 0) 35 + #define _PLL_POST_DIV_SEL_FIELD GENMASK(14, 8) 36 + #define _PLL_SEL_MODE_FIELD GENMASK(16, 15) 37 + #define _PLL_DIV_SEL_FIELD GENMASK(23, 17) 38 + #define _PLL_ICTRL_FIELD GENMASK(26, 24) 39 + 40 + #define _PLL_ALL_FIELD_MASK \ 41 + (_PLL_PRE_DIV_SEL_FIELD | \ 42 + _PLL_POST_DIV_SEL_FIELD | \ 43 + _PLL_SEL_MODE_FIELD | \ 44 + _PLL_DIV_SEL_FIELD | \ 45 + _PLL_ICTRL_FIELD) 46 + 47 + #define PLL_COPY_REG(_dest, _src) \ 48 + (((_dest) & (~_PLL_ALL_FIELD_MASK)) | ((_src) & _PLL_ALL_FIELD_MASK)) 49 + 50 + #define PLL_GET_PRE_DIV_SEL(_reg) \ 51 + FIELD_GET(_PLL_PRE_DIV_SEL_FIELD, (_reg)) 52 + #define PLL_GET_POST_DIV_SEL(_reg) \ 53 + FIELD_GET(_PLL_POST_DIV_SEL_FIELD, (_reg)) 54 + #define PLL_GET_SEL_MODE(_reg) \ 55 + FIELD_GET(_PLL_SEL_MODE_FIELD, (_reg)) 56 + #define PLL_GET_DIV_SEL(_reg) \ 57 + FIELD_GET(_PLL_DIV_SEL_FIELD, (_reg)) 58 + #define PLL_GET_ICTRL(_reg) \ 59 + FIELD_GET(_PLL_ICTRL_FIELD, (_reg)) 60 + 61 + #define PLL_SET_PRE_DIV_SEL(_reg, _val) \ 62 + _CV1800_SET_FIELD((_reg), (_val), _PLL_PRE_DIV_SEL_FIELD) 63 + #define PLL_SET_POST_DIV_SEL(_reg, _val) \ 64 + _CV1800_SET_FIELD((_reg), (_val), _PLL_POST_DIV_SEL_FIELD) 65 + #define PLL_SET_SEL_MODE(_reg, _val) \ 66 + _CV1800_SET_FIELD((_reg), (_val), _PLL_SEL_MODE_FIELD) 67 + #define PLL_SET_DIV_SEL(_reg, _val) \ 68 + _CV1800_SET_FIELD((_reg), (_val), _PLL_DIV_SEL_FIELD) 69 + #define PLL_SET_ICTRL(_reg, _val) \ 70 + _CV1800_SET_FIELD((_reg), (_val), _PLL_ICTRL_FIELD) 71 + 72 + struct cv1800_clk_pll { 73 + struct cv1800_clk_common common; 74 + u32 pll_reg; 75 + struct cv1800_clk_regbit pll_pwd; 76 + struct cv1800_clk_regbit pll_status; 77 + const struct cv1800_clk_pll_limit *pll_limit; 78 + struct cv1800_clk_pll_synthesizer *pll_syn; 79 + }; 80 + 81 + #define CV1800_INTEGRAL_PLL(_name, _parent, _pll_reg, \ 82 + _pll_pwd_reg, _pll_pwd_shift, \ 83 + _pll_status_reg, _pll_status_shift, \ 84 + _pll_limit, _flags) \ 85 + struct cv1800_clk_pll _name = { \ 86 + .common = CV1800_CLK_COMMON(#_name, _parent, \ 87 + &cv1800_clk_ipll_ops,\ 88 + _flags), \ 89 + .pll_reg = _pll_reg, \ 90 + .pll_pwd = CV1800_CLK_BIT(_pll_pwd_reg, \ 91 + _pll_pwd_shift), \ 92 + .pll_status = CV1800_CLK_BIT(_pll_status_reg, \ 93 + _pll_status_shift), \ 94 + .pll_limit = _pll_limit, \ 95 + .pll_syn = NULL, \ 96 + } 97 + 98 + #define CV1800_FACTIONAL_PLL(_name, _parent, _pll_reg, \ 99 + _pll_pwd_reg, _pll_pwd_shift, \ 100 + _pll_status_reg, _pll_status_shift, \ 101 + _pll_limit, _pll_syn, _flags) \ 102 + struct cv1800_clk_pll _name = { \ 103 + .common = CV1800_CLK_COMMON(#_name, _parent, \ 104 + &cv1800_clk_fpll_ops,\ 105 + _flags), \ 106 + .pll_reg = _pll_reg, \ 107 + .pll_pwd = CV1800_CLK_BIT(_pll_pwd_reg, \ 108 + _pll_pwd_shift), \ 109 + .pll_status = CV1800_CLK_BIT(_pll_status_reg, \ 110 + _pll_status_shift), \ 111 + .pll_limit = _pll_limit, \ 112 + .pll_syn = _pll_syn, \ 113 + } 114 + 115 + extern const struct clk_ops cv1800_clk_ipll_ops; 116 + extern const struct clk_ops cv1800_clk_fpll_ops; 117 + 118 + #endif // _CLK_SOPHGO_CV1800_PLL_H_