1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2021, The Linux Foundation. All rights reserved. 4 */ 5 6 #include <linux/clk-provider.h> 7 #include <linux/module.h> 8 #include <linux/platform_device.h> 9 #include <linux/regmap.h> 10 11 #include <dt-bindings/clock/qcom,gpucc-sc7280.h> 12 13 #include "clk-alpha-pll.h" 14 #include "clk-branch.h" 15 #include "clk-rcg.h" 16 #include "clk-regmap-divider.h" 17 #include "common.h" 18 #include "reset.h" 19 #include "gdsc.h" 20 21 enum { 22 P_BI_TCXO, 23 P_GCC_GPU_GPLL0_CLK_SRC, 24 P_GCC_GPU_GPLL0_DIV_CLK_SRC, 25 P_GPU_CC_PLL0_OUT_MAIN, 26 P_GPU_CC_PLL1_OUT_MAIN, 27 }; 28 29 static const struct pll_vco lucid_vco[] = { 30 { 249600000, 2000000000, 0 }, 31 }; 32 33 static struct clk_alpha_pll gpu_cc_pll0 = { 34 .offset = 0x0, 35 .vco_table = lucid_vco, 36 .num_vco = ARRAY_SIZE(lucid_vco), 37 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], 38 .clkr = { 39 .hw.init = &(struct clk_init_data){ 40 .name = "gpu_cc_pll0", 41 .parent_data = &(const struct clk_parent_data){ 42 .fw_name = "bi_tcxo", 43 }, 44 .num_parents = 1, 45 .ops = &clk_alpha_pll_lucid_ops, 46 }, 47 }, 48 }; 49 50 /* 500MHz Configuration */ 51 static const struct alpha_pll_config gpu_cc_pll1_config = { 52 .l = 0x1A, 53 .alpha = 0xAAA, 54 .config_ctl_val = 0x20485699, 55 .config_ctl_hi_val = 0x00002261, 56 .config_ctl_hi1_val = 0x329A299C, 57 .user_ctl_val = 0x00000001, 58 .user_ctl_hi_val = 0x00000805, 59 .user_ctl_hi1_val = 0x00000000, 60 }; 61 62 static struct clk_alpha_pll gpu_cc_pll1 = { 63 .offset = 0x100, 64 .vco_table = lucid_vco, 65 .num_vco = ARRAY_SIZE(lucid_vco), 66 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], 67 .clkr = { 68 .hw.init = &(struct clk_init_data){ 69 .name = "gpu_cc_pll1", 70 .parent_data = &(const struct clk_parent_data){ 71 .fw_name = "bi_tcxo", 72 }, 73 .num_parents = 1, 74 .ops = &clk_alpha_pll_lucid_ops, 75 }, 76 }, 77 }; 78 79 static const struct parent_map gpu_cc_parent_map_0[] = { 80 { P_BI_TCXO, 0 }, 81 { P_GPU_CC_PLL0_OUT_MAIN, 1 }, 82 { P_GPU_CC_PLL1_OUT_MAIN, 3 }, 83 { P_GCC_GPU_GPLL0_CLK_SRC, 5 }, 84 { P_GCC_GPU_GPLL0_DIV_CLK_SRC, 6 }, 85 }; 86 87 static const struct clk_parent_data gpu_cc_parent_data_0[] = { 88 { .fw_name = "bi_tcxo" }, 89 { .hw = &gpu_cc_pll0.clkr.hw }, 90 { .hw = &gpu_cc_pll1.clkr.hw }, 91 { .fw_name = "gcc_gpu_gpll0_clk_src" }, 92 { .fw_name = "gcc_gpu_gpll0_div_clk_src" }, 93 }; 94 95 static const struct parent_map gpu_cc_parent_map_1[] = { 96 { P_BI_TCXO, 0 }, 97 { P_GPU_CC_PLL1_OUT_MAIN, 3 }, 98 { P_GCC_GPU_GPLL0_CLK_SRC, 5 }, 99 { P_GCC_GPU_GPLL0_DIV_CLK_SRC, 6 }, 100 }; 101 102 static const struct clk_parent_data gpu_cc_parent_data_1[] = { 103 { .fw_name = "bi_tcxo", }, 104 { .hw = &gpu_cc_pll1.clkr.hw }, 105 { .fw_name = "gcc_gpu_gpll0_clk_src", }, 106 { .fw_name = "gcc_gpu_gpll0_div_clk_src", }, 107 }; 108 109 static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = { 110 F(19200000, P_BI_TCXO, 1, 0, 0), 111 F(200000000, P_GCC_GPU_GPLL0_DIV_CLK_SRC, 1.5, 0, 0), 112 F(500000000, P_GPU_CC_PLL1_OUT_MAIN, 1, 0, 0), 113 { } 114 }; 115 116 static struct clk_rcg2 gpu_cc_gmu_clk_src = { 117 .cmd_rcgr = 0x1120, 118 .mnd_width = 0, 119 .hid_width = 5, 120 .parent_map = gpu_cc_parent_map_0, 121 .freq_tbl = ftbl_gpu_cc_gmu_clk_src, 122 .clkr.hw.init = &(struct clk_init_data){ 123 .name = "gpu_cc_gmu_clk_src", 124 .parent_data = gpu_cc_parent_data_0, 125 .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0), 126 .ops = &clk_rcg2_shared_ops, 127 }, 128 }; 129 130 static const struct freq_tbl ftbl_gpu_cc_hub_clk_src[] = { 131 F(150000000, P_GCC_GPU_GPLL0_DIV_CLK_SRC, 2, 0, 0), 132 F(240000000, P_GCC_GPU_GPLL0_CLK_SRC, 2.5, 0, 0), 133 F(300000000, P_GCC_GPU_GPLL0_CLK_SRC, 2, 0, 0), 134 { } 135 }; 136 137 static struct clk_rcg2 gpu_cc_hub_clk_src = { 138 .cmd_rcgr = 0x117c, 139 .mnd_width = 0, 140 .hid_width = 5, 141 .parent_map = gpu_cc_parent_map_1, 142 .freq_tbl = ftbl_gpu_cc_hub_clk_src, 143 .clkr.hw.init = &(struct clk_init_data){ 144 .name = "gpu_cc_hub_clk_src", 145 .parent_data = gpu_cc_parent_data_1, 146 .num_parents = ARRAY_SIZE(gpu_cc_parent_data_1), 147 .ops = &clk_rcg2_shared_ops, 148 }, 149 }; 150 151 static struct clk_regmap_div gpu_cc_hub_ahb_div_clk_src = { 152 .reg = 0x11c0, 153 .shift = 0, 154 .width = 4, 155 .clkr.hw.init = &(struct clk_init_data) { 156 .name = "gpu_cc_hub_ahb_div_clk_src", 157 .parent_hws = (const struct clk_hw*[]){ 158 &gpu_cc_hub_clk_src.clkr.hw, 159 }, 160 .num_parents = 1, 161 .flags = CLK_SET_RATE_PARENT, 162 .ops = &clk_regmap_div_ro_ops, 163 }, 164 }; 165 166 static struct clk_regmap_div gpu_cc_hub_cx_int_div_clk_src = { 167 .reg = 0x11bc, 168 .shift = 0, 169 .width = 4, 170 .clkr.hw.init = &(struct clk_init_data) { 171 .name = "gpu_cc_hub_cx_int_div_clk_src", 172 .parent_hws = (const struct clk_hw*[]){ 173 &gpu_cc_hub_clk_src.clkr.hw, 174 }, 175 .num_parents = 1, 176 .flags = CLK_SET_RATE_PARENT, 177 .ops = &clk_regmap_div_ro_ops, 178 }, 179 }; 180 181 static struct clk_branch gpu_cc_ahb_clk = { 182 .halt_reg = 0x1078, 183 .halt_check = BRANCH_HALT_DELAY, 184 .clkr = { 185 .enable_reg = 0x1078, 186 .enable_mask = BIT(0), 187 .hw.init = &(struct clk_init_data){ 188 .name = "gpu_cc_ahb_clk", 189 .parent_hws = (const struct clk_hw*[]){ 190 &gpu_cc_hub_ahb_div_clk_src.clkr.hw, 191 }, 192 .num_parents = 1, 193 .flags = CLK_SET_RATE_PARENT, 194 .ops = &clk_branch2_ops, 195 }, 196 }, 197 }; 198 199 static struct clk_branch gpu_cc_crc_ahb_clk = { 200 .halt_reg = 0x107c, 201 .halt_check = BRANCH_HALT_VOTED, 202 .clkr = { 203 .enable_reg = 0x107c, 204 .enable_mask = BIT(0), 205 .hw.init = &(struct clk_init_data){ 206 .name = "gpu_cc_crc_ahb_clk", 207 .parent_hws = (const struct clk_hw*[]){ 208 &gpu_cc_hub_ahb_div_clk_src.clkr.hw, 209 }, 210 .num_parents = 1, 211 .flags = CLK_SET_RATE_PARENT, 212 .ops = &clk_branch2_ops, 213 }, 214 }, 215 }; 216 217 static struct clk_branch gpu_cc_cx_gmu_clk = { 218 .halt_reg = 0x1098, 219 .halt_check = BRANCH_HALT, 220 .clkr = { 221 .enable_reg = 0x1098, 222 .enable_mask = BIT(0), 223 .hw.init = &(struct clk_init_data){ 224 .name = "gpu_cc_cx_gmu_clk", 225 .parent_hws = (const struct clk_hw*[]){ 226 &gpu_cc_gmu_clk_src.clkr.hw, 227 }, 228 .num_parents = 1, 229 .flags = CLK_SET_RATE_PARENT, 230 .ops = &clk_branch2_aon_ops, 231 }, 232 }, 233 }; 234 235 static struct clk_branch gpu_cc_cx_snoc_dvm_clk = { 236 .halt_reg = 0x108c, 237 .halt_check = BRANCH_HALT_VOTED, 238 .clkr = { 239 .enable_reg = 0x108c, 240 .enable_mask = BIT(0), 241 .hw.init = &(struct clk_init_data){ 242 .name = "gpu_cc_cx_snoc_dvm_clk", 243 .ops = &clk_branch2_ops, 244 }, 245 }, 246 }; 247 248 static struct clk_branch gpu_cc_cxo_aon_clk = { 249 .halt_reg = 0x1004, 250 .halt_check = BRANCH_HALT_VOTED, 251 .clkr = { 252 .enable_reg = 0x1004, 253 .enable_mask = BIT(0), 254 .hw.init = &(struct clk_init_data){ 255 .name = "gpu_cc_cxo_aon_clk", 256 .ops = &clk_branch2_ops, 257 }, 258 }, 259 }; 260 261 static struct clk_branch gpu_cc_cxo_clk = { 262 .halt_reg = 0x109c, 263 .halt_check = BRANCH_HALT, 264 .clkr = { 265 .enable_reg = 0x109c, 266 .enable_mask = BIT(0), 267 .hw.init = &(struct clk_init_data){ 268 .name = "gpu_cc_cxo_clk", 269 .ops = &clk_branch2_aon_ops, 270 }, 271 }, 272 }; 273 274 static struct clk_branch gpu_cc_gx_gmu_clk = { 275 .halt_reg = 0x1064, 276 .halt_check = BRANCH_HALT, 277 .clkr = { 278 .enable_reg = 0x1064, 279 .enable_mask = BIT(0), 280 .hw.init = &(struct clk_init_data){ 281 .name = "gpu_cc_gx_gmu_clk", 282 .parent_hws = (const struct clk_hw*[]){ 283 &gpu_cc_gmu_clk_src.clkr.hw, 284 }, 285 .num_parents = 1, 286 .flags = CLK_SET_RATE_PARENT, 287 .ops = &clk_branch2_ops, 288 }, 289 }, 290 }; 291 292 static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk = { 293 .halt_reg = 0x5000, 294 .halt_check = BRANCH_VOTED, 295 .clkr = { 296 .enable_reg = 0x5000, 297 .enable_mask = BIT(0), 298 .hw.init = &(struct clk_init_data){ 299 .name = "gpu_cc_hlos1_vote_gpu_smmu_clk", 300 .ops = &clk_branch2_ops, 301 }, 302 }, 303 }; 304 305 static struct clk_branch gpu_cc_hub_aon_clk = { 306 .halt_reg = 0x1178, 307 .halt_check = BRANCH_HALT, 308 .clkr = { 309 .enable_reg = 0x1178, 310 .enable_mask = BIT(0), 311 .hw.init = &(struct clk_init_data){ 312 .name = "gpu_cc_hub_aon_clk", 313 .parent_hws = (const struct clk_hw*[]){ 314 &gpu_cc_hub_clk_src.clkr.hw, 315 }, 316 .num_parents = 1, 317 .flags = CLK_SET_RATE_PARENT, 318 .ops = &clk_branch2_aon_ops, 319 }, 320 }, 321 }; 322 323 static struct clk_branch gpu_cc_hub_cx_int_clk = { 324 .halt_reg = 0x1204, 325 .halt_check = BRANCH_HALT, 326 .clkr = { 327 .enable_reg = 0x1204, 328 .enable_mask = BIT(0), 329 .hw.init = &(struct clk_init_data){ 330 .name = "gpu_cc_hub_cx_int_clk", 331 .parent_hws = (const struct clk_hw*[]){ 332 &gpu_cc_hub_cx_int_div_clk_src.clkr.hw, 333 }, 334 .num_parents = 1, 335 .flags = CLK_SET_RATE_PARENT, 336 .ops = &clk_branch2_aon_ops, 337 }, 338 }, 339 }; 340 341 static struct clk_branch gpu_cc_mnd1x_0_gfx3d_clk = { 342 .halt_reg = 0x802c, 343 .halt_check = BRANCH_HALT_SKIP, 344 .clkr = { 345 .enable_reg = 0x802c, 346 .enable_mask = BIT(0), 347 .hw.init = &(struct clk_init_data){ 348 .name = "gpu_cc_mnd1x_0_gfx3d_clk", 349 .ops = &clk_branch2_ops, 350 }, 351 }, 352 }; 353 354 static struct clk_branch gpu_cc_mnd1x_1_gfx3d_clk = { 355 .halt_reg = 0x8030, 356 .halt_check = BRANCH_HALT_SKIP, 357 .clkr = { 358 .enable_reg = 0x8030, 359 .enable_mask = BIT(0), 360 .hw.init = &(struct clk_init_data){ 361 .name = "gpu_cc_mnd1x_1_gfx3d_clk", 362 .ops = &clk_branch2_ops, 363 }, 364 }, 365 }; 366 367 static struct clk_branch gpu_cc_sleep_clk = { 368 .halt_reg = 0x1090, 369 .halt_check = BRANCH_HALT_VOTED, 370 .clkr = { 371 .enable_reg = 0x1090, 372 .enable_mask = BIT(0), 373 .hw.init = &(struct clk_init_data){ 374 .name = "gpu_cc_sleep_clk", 375 .ops = &clk_branch2_ops, 376 }, 377 }, 378 }; 379 380 static struct gdsc cx_gdsc = { 381 .gdscr = 0x106c, 382 .gds_hw_ctrl = 0x1540, 383 .pd = { 384 .name = "cx_gdsc", 385 }, 386 .pwrsts = PWRSTS_OFF_ON, 387 .flags = VOTABLE | RETAIN_FF_ENABLE, 388 }; 389 390 static struct gdsc gx_gdsc = { 391 .gdscr = 0x100c, 392 .clamp_io_ctrl = 0x1508, 393 .pd = { 394 .name = "gx_gdsc", 395 .power_on = gdsc_gx_do_nothing_enable, 396 }, 397 .pwrsts = PWRSTS_OFF_ON, 398 .flags = CLAMP_IO | RETAIN_FF_ENABLE, 399 }; 400 401 static struct gdsc *gpu_cc_sc7180_gdscs[] = { 402 [GPU_CC_CX_GDSC] = &cx_gdsc, 403 [GPU_CC_GX_GDSC] = &gx_gdsc, 404 }; 405 406 static struct clk_regmap *gpu_cc_sc7280_clocks[] = { 407 [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr, 408 [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr, 409 [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr, 410 [GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_clk.clkr, 411 [GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr, 412 [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr, 413 [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr, 414 [GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr, 415 [GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK] = &gpu_cc_hlos1_vote_gpu_smmu_clk.clkr, 416 [GPU_CC_HUB_AHB_DIV_CLK_SRC] = &gpu_cc_hub_ahb_div_clk_src.clkr, 417 [GPU_CC_HUB_AON_CLK] = &gpu_cc_hub_aon_clk.clkr, 418 [GPU_CC_HUB_CLK_SRC] = &gpu_cc_hub_clk_src.clkr, 419 [GPU_CC_HUB_CX_INT_CLK] = &gpu_cc_hub_cx_int_clk.clkr, 420 [GPU_CC_HUB_CX_INT_DIV_CLK_SRC] = &gpu_cc_hub_cx_int_div_clk_src.clkr, 421 [GPU_CC_MND1X_0_GFX3D_CLK] = &gpu_cc_mnd1x_0_gfx3d_clk.clkr, 422 [GPU_CC_MND1X_1_GFX3D_CLK] = &gpu_cc_mnd1x_1_gfx3d_clk.clkr, 423 [GPU_CC_PLL0] = &gpu_cc_pll0.clkr, 424 [GPU_CC_PLL1] = &gpu_cc_pll1.clkr, 425 [GPU_CC_SLEEP_CLK] = &gpu_cc_sleep_clk.clkr, 426 }; 427 428 static const struct regmap_config gpu_cc_sc7280_regmap_config = { 429 .reg_bits = 32, 430 .reg_stride = 4, 431 .val_bits = 32, 432 .max_register = 0x8030, 433 .fast_io = true, 434 }; 435 436 static const struct qcom_cc_desc gpu_cc_sc7280_desc = { 437 .config = &gpu_cc_sc7280_regmap_config, 438 .clks = gpu_cc_sc7280_clocks, 439 .num_clks = ARRAY_SIZE(gpu_cc_sc7280_clocks), 440 .gdscs = gpu_cc_sc7180_gdscs, 441 .num_gdscs = ARRAY_SIZE(gpu_cc_sc7180_gdscs), 442 }; 443 444 static const struct of_device_id gpu_cc_sc7280_match_table[] = { 445 { .compatible = "qcom,sc7280-gpucc" }, 446 { } 447 }; 448 MODULE_DEVICE_TABLE(of, gpu_cc_sc7280_match_table); 449 450 static int gpu_cc_sc7280_probe(struct platform_device *pdev) 451 { 452 struct regmap *regmap; 453 454 regmap = qcom_cc_map(pdev, &gpu_cc_sc7280_desc); 455 if (IS_ERR(regmap)) 456 return PTR_ERR(regmap); 457 458 clk_lucid_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config); 459 460 /* 461 * Keep the clocks always-ON 462 * GPU_CC_CB_CLK, GPUCC_CX_GMU_CLK 463 */ 464 regmap_update_bits(regmap, 0x1170, BIT(0), BIT(0)); 465 regmap_update_bits(regmap, 0x1098, BIT(0), BIT(0)); 466 467 return qcom_cc_really_probe(pdev, &gpu_cc_sc7280_desc, regmap); 468 } 469 470 static struct platform_driver gpu_cc_sc7280_driver = { 471 .probe = gpu_cc_sc7280_probe, 472 .driver = { 473 .name = "gpu_cc-sc7280", 474 .of_match_table = gpu_cc_sc7280_match_table, 475 }, 476 }; 477 478 static int __init gpu_cc_sc7280_init(void) 479 { 480 return platform_driver_register(&gpu_cc_sc7280_driver); 481 } 482 subsys_initcall(gpu_cc_sc7280_init); 483 484 static void __exit gpu_cc_sc7280_exit(void) 485 { 486 platform_driver_unregister(&gpu_cc_sc7280_driver); 487 } 488 module_exit(gpu_cc_sc7280_exit); 489 490 MODULE_DESCRIPTION("QTI GPU_CC SC7280 Driver"); 491 MODULE_LICENSE("GPL v2"); 492