1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2021, The Linux Foundation. All rights reserved. 4 * Copyright (c) 2021, Konrad Dybcio <konrad.dybcio@somainline.org> 5 */ 6 7 #include <linux/clk-provider.h> 8 #include <linux/module.h> 9 #include <linux/platform_device.h> 10 #include <linux/regmap.h> 11 12 #include <dt-bindings/clock/qcom,gpucc-sm6350.h> 13 14 #include "common.h" 15 #include "clk-alpha-pll.h" 16 #include "clk-branch.h" 17 #include "clk-rcg.h" 18 #include "clk-regmap.h" 19 #include "reset.h" 20 #include "gdsc.h" 21 22 #define CX_GMU_CBCR_SLEEP_MASK 0xF 23 #define CX_GMU_CBCR_SLEEP_SHIFT 4 24 #define CX_GMU_CBCR_WAKE_MASK 0xF 25 #define CX_GMU_CBCR_WAKE_SHIFT 8 26 27 enum { 28 DT_BI_TCXO, 29 DT_GPLL0_OUT_MAIN, 30 DT_GPLL0_OUT_MAIN_DIV, 31 }; 32 33 enum { 34 P_BI_TCXO, 35 P_GPLL0_OUT_MAIN, 36 P_GPLL0_OUT_MAIN_DIV, 37 P_GPU_CC_PLL0_OUT_MAIN, 38 P_GPU_CC_PLL0_OUT_ODD, 39 P_GPU_CC_PLL1_OUT_EVEN, 40 P_GPU_CC_PLL1_OUT_MAIN, 41 P_GPU_CC_PLL1_OUT_ODD, 42 P_CRC_DIV, 43 }; 44 45 static const struct pll_vco fabia_vco[] = { 46 { 249600000, 2000000000, 0 }, 47 }; 48 49 /* 506MHz Configuration*/ 50 static const struct alpha_pll_config gpu_cc_pll0_config = { 51 .l = 0x1A, 52 .alpha = 0x5AAA, 53 .config_ctl_val = 0x20485699, 54 .config_ctl_hi_val = 0x00002067, 55 .test_ctl_val = 0x40000000, 56 .test_ctl_hi_val = 0x00000002, 57 .user_ctl_val = 0x00000001, 58 .user_ctl_hi_val = 0x00004805, 59 }; 60 61 static struct clk_alpha_pll gpu_cc_pll0 = { 62 .offset = 0x0, 63 .vco_table = fabia_vco, 64 .num_vco = ARRAY_SIZE(fabia_vco), 65 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], 66 .clkr = { 67 .hw.init = &(struct clk_init_data){ 68 .name = "gpu_cc_pll0", 69 .parent_data = &(const struct clk_parent_data){ 70 .index = DT_BI_TCXO, 71 .fw_name = "bi_tcxo", 72 }, 73 .num_parents = 1, 74 .ops = &clk_alpha_pll_fabia_ops, 75 }, 76 }, 77 }; 78 79 static struct clk_fixed_factor crc_div = { 80 .mult = 1, 81 .div = 2, 82 .hw.init = &(struct clk_init_data){ 83 .name = "crc_div", 84 .parent_hws = (const struct clk_hw*[]){ 85 &gpu_cc_pll0.clkr.hw, 86 }, 87 .num_parents = 1, 88 .flags = CLK_SET_RATE_PARENT, 89 .ops = &clk_fixed_factor_ops, 90 }, 91 }; 92 93 /* 514MHz Configuration*/ 94 static const struct alpha_pll_config gpu_cc_pll1_config = { 95 .l = 0x1A, 96 .alpha = 0xC555, 97 .config_ctl_val = 0x20485699, 98 .config_ctl_hi_val = 0x00002067, 99 .test_ctl_val = 0x40000000, 100 .test_ctl_hi_val = 0x00000002, 101 .user_ctl_val = 0x00000001, 102 .user_ctl_hi_val = 0x00004805, 103 }; 104 105 static struct clk_alpha_pll gpu_cc_pll1 = { 106 .offset = 0x100, 107 .vco_table = fabia_vco, 108 .num_vco = ARRAY_SIZE(fabia_vco), 109 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], 110 .clkr = { 111 .hw.init = &(struct clk_init_data){ 112 .name = "gpu_cc_pll1", 113 .parent_data = &(const struct clk_parent_data){ 114 .index = DT_BI_TCXO, 115 .fw_name = "bi_tcxo", 116 }, 117 .num_parents = 1, 118 .ops = &clk_alpha_pll_fabia_ops, 119 }, 120 }, 121 }; 122 123 static const struct parent_map gpu_cc_parent_map_0[] = { 124 { P_BI_TCXO, 0 }, 125 { P_GPU_CC_PLL0_OUT_MAIN, 1 }, 126 { P_GPU_CC_PLL1_OUT_MAIN, 3 }, 127 { P_GPLL0_OUT_MAIN, 5 }, 128 { P_GPLL0_OUT_MAIN_DIV, 6 }, 129 }; 130 131 static const struct clk_parent_data gpu_cc_parent_data_0[] = { 132 { .index = DT_BI_TCXO, .fw_name = "bi_tcxo" }, 133 { .hw = &gpu_cc_pll0.clkr.hw }, 134 { .hw = &gpu_cc_pll1.clkr.hw }, 135 { .index = DT_GPLL0_OUT_MAIN, .fw_name = "gcc_gpu_gpll0_clk_src" }, 136 { .index = DT_GPLL0_OUT_MAIN_DIV, .fw_name = "gcc_gpu_gpll0_div_clk_src" }, 137 }; 138 139 static const struct parent_map gpu_cc_parent_map_1[] = { 140 { P_BI_TCXO, 0 }, 141 { P_CRC_DIV, 1 }, 142 { P_GPU_CC_PLL0_OUT_ODD, 2 }, 143 { P_GPU_CC_PLL1_OUT_EVEN, 3 }, 144 { P_GPU_CC_PLL1_OUT_ODD, 4 }, 145 { P_GPLL0_OUT_MAIN, 5 }, 146 }; 147 148 static const struct clk_parent_data gpu_cc_parent_data_1[] = { 149 { .index = DT_BI_TCXO, .fw_name = "bi_tcxo" }, 150 { .hw = &crc_div.hw }, 151 { .hw = &gpu_cc_pll0.clkr.hw }, 152 { .hw = &gpu_cc_pll1.clkr.hw }, 153 { .hw = &gpu_cc_pll1.clkr.hw }, 154 { .index = DT_GPLL0_OUT_MAIN, .fw_name = "gcc_gpu_gpll0_clk_src" }, 155 }; 156 157 static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = { 158 F(200000000, P_GPLL0_OUT_MAIN_DIV, 1.5, 0, 0), 159 { } 160 }; 161 162 static struct clk_rcg2 gpu_cc_gmu_clk_src = { 163 .cmd_rcgr = 0x1120, 164 .mnd_width = 0, 165 .hid_width = 5, 166 .parent_map = gpu_cc_parent_map_0, 167 .freq_tbl = ftbl_gpu_cc_gmu_clk_src, 168 .clkr.hw.init = &(struct clk_init_data){ 169 .name = "gpu_cc_gmu_clk_src", 170 .parent_data = gpu_cc_parent_data_0, 171 .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0), 172 .flags = CLK_SET_RATE_PARENT, 173 .ops = &clk_rcg2_ops, 174 }, 175 }; 176 177 static const struct freq_tbl ftbl_gpu_cc_gx_gfx3d_clk_src[] = { 178 F(253000000, P_CRC_DIV, 1, 0, 0), 179 F(355000000, P_CRC_DIV, 1, 0, 0), 180 F(430000000, P_CRC_DIV, 1, 0, 0), 181 F(565000000, P_CRC_DIV, 1, 0, 0), 182 F(650000000, P_CRC_DIV, 1, 0, 0), 183 F(800000000, P_CRC_DIV, 1, 0, 0), 184 F(825000000, P_CRC_DIV, 1, 0, 0), 185 F(850000000, P_CRC_DIV, 1, 0, 0), 186 { } 187 }; 188 189 static struct clk_rcg2 gpu_cc_gx_gfx3d_clk_src = { 190 .cmd_rcgr = 0x101c, 191 .mnd_width = 0, 192 .hid_width = 5, 193 .parent_map = gpu_cc_parent_map_1, 194 .freq_tbl = ftbl_gpu_cc_gx_gfx3d_clk_src, 195 .clkr.hw.init = &(struct clk_init_data){ 196 .name = "gpu_cc_gx_gfx3d_clk_src", 197 .parent_data = gpu_cc_parent_data_1, 198 .num_parents = ARRAY_SIZE(gpu_cc_parent_data_1), 199 .flags = CLK_SET_RATE_PARENT, 200 .ops = &clk_rcg2_ops, 201 }, 202 }; 203 204 static struct clk_branch gpu_cc_acd_ahb_clk = { 205 .halt_reg = 0x1168, 206 .halt_check = BRANCH_HALT, 207 .clkr = { 208 .enable_reg = 0x1168, 209 .enable_mask = BIT(0), 210 .hw.init = &(struct clk_init_data){ 211 .name = "gpu_cc_acd_ahb_clk", 212 .ops = &clk_branch2_ops, 213 }, 214 }, 215 }; 216 217 static struct clk_branch gpu_cc_acd_cxo_clk = { 218 .halt_reg = 0x1164, 219 .halt_check = BRANCH_HALT, 220 .clkr = { 221 .enable_reg = 0x1164, 222 .enable_mask = BIT(0), 223 .hw.init = &(struct clk_init_data){ 224 .name = "gpu_cc_acd_cxo_clk", 225 .ops = &clk_branch2_ops, 226 }, 227 }, 228 }; 229 230 static struct clk_branch gpu_cc_ahb_clk = { 231 .halt_reg = 0x1078, 232 .halt_check = BRANCH_HALT_DELAY, 233 .clkr = { 234 .enable_reg = 0x1078, 235 .enable_mask = BIT(0), 236 .hw.init = &(struct clk_init_data){ 237 .name = "gpu_cc_ahb_clk", 238 .flags = CLK_IS_CRITICAL, 239 .ops = &clk_branch2_ops, 240 }, 241 }, 242 }; 243 244 static struct clk_branch gpu_cc_crc_ahb_clk = { 245 .halt_reg = 0x107c, 246 .halt_check = BRANCH_HALT_DELAY, 247 .clkr = { 248 .enable_reg = 0x107c, 249 .enable_mask = BIT(0), 250 .hw.init = &(struct clk_init_data){ 251 .name = "gpu_cc_crc_ahb_clk", 252 .ops = &clk_branch2_ops, 253 }, 254 }, 255 }; 256 257 static struct clk_branch gpu_cc_cx_gfx3d_clk = { 258 .halt_reg = 0x10a4, 259 .halt_check = BRANCH_HALT_DELAY, 260 .clkr = { 261 .enable_reg = 0x10a4, 262 .enable_mask = BIT(0), 263 .hw.init = &(struct clk_init_data){ 264 .name = "gpu_cc_cx_gfx3d_clk", 265 .parent_hws = (const struct clk_hw*[]){ 266 &gpu_cc_gx_gfx3d_clk_src.clkr.hw, 267 }, 268 .num_parents = 1, 269 .flags = CLK_SET_RATE_PARENT, 270 .ops = &clk_branch2_ops, 271 }, 272 }, 273 }; 274 275 static struct clk_branch gpu_cc_cx_gfx3d_slv_clk = { 276 .halt_reg = 0x10a8, 277 .halt_check = BRANCH_HALT_DELAY, 278 .clkr = { 279 .enable_reg = 0x10a8, 280 .enable_mask = BIT(0), 281 .hw.init = &(struct clk_init_data){ 282 .name = "gpu_cc_cx_gfx3d_slv_clk", 283 .parent_hws = (const struct clk_hw*[]){ 284 &gpu_cc_gx_gfx3d_clk_src.clkr.hw, 285 }, 286 .num_parents = 1, 287 .flags = CLK_SET_RATE_PARENT, 288 .ops = &clk_branch2_ops, 289 }, 290 }, 291 }; 292 293 static struct clk_branch gpu_cc_cx_gmu_clk = { 294 .halt_reg = 0x1098, 295 .halt_check = BRANCH_HALT, 296 .clkr = { 297 .enable_reg = 0x1098, 298 .enable_mask = BIT(0), 299 .hw.init = &(struct clk_init_data){ 300 .name = "gpu_cc_cx_gmu_clk", 301 .parent_hws = (const struct clk_hw*[]){ 302 &gpu_cc_gmu_clk_src.clkr.hw, 303 }, 304 .num_parents = 1, 305 .flags = CLK_SET_RATE_PARENT, 306 .ops = &clk_branch2_ops, 307 }, 308 }, 309 }; 310 311 static struct clk_branch gpu_cc_cx_snoc_dvm_clk = { 312 .halt_reg = 0x108c, 313 .halt_check = BRANCH_HALT_DELAY, 314 .clkr = { 315 .enable_reg = 0x108c, 316 .enable_mask = BIT(0), 317 .hw.init = &(struct clk_init_data){ 318 .name = "gpu_cc_cx_snoc_dvm_clk", 319 .ops = &clk_branch2_ops, 320 }, 321 }, 322 }; 323 324 static struct clk_branch gpu_cc_cxo_aon_clk = { 325 .halt_reg = 0x1004, 326 .halt_check = BRANCH_HALT_DELAY, 327 .clkr = { 328 .enable_reg = 0x1004, 329 .enable_mask = BIT(0), 330 .hw.init = &(struct clk_init_data){ 331 .name = "gpu_cc_cxo_aon_clk", 332 .ops = &clk_branch2_ops, 333 }, 334 }, 335 }; 336 337 static struct clk_branch gpu_cc_cxo_clk = { 338 .halt_reg = 0x109c, 339 .halt_check = BRANCH_HALT, 340 .clkr = { 341 .enable_reg = 0x109c, 342 .enable_mask = BIT(0), 343 .hw.init = &(struct clk_init_data){ 344 .name = "gpu_cc_cxo_clk", 345 .ops = &clk_branch2_ops, 346 }, 347 }, 348 }; 349 350 static struct clk_branch gpu_cc_gx_cxo_clk = { 351 .halt_reg = 0x1060, 352 .halt_check = BRANCH_HALT, 353 .clkr = { 354 .enable_reg = 0x1060, 355 .enable_mask = BIT(0), 356 .hw.init = &(struct clk_init_data){ 357 .name = "gpu_cc_gx_cxo_clk", 358 .ops = &clk_branch2_ops, 359 }, 360 }, 361 }; 362 363 static struct clk_branch gpu_cc_gx_gfx3d_clk = { 364 .halt_reg = 0x1054, 365 .halt_check = BRANCH_HALT_SKIP, 366 .clkr = { 367 .enable_reg = 0x1054, 368 .enable_mask = BIT(0), 369 .hw.init = &(struct clk_init_data){ 370 .name = "gpu_cc_gx_gfx3d_clk", 371 .parent_hws = (const struct clk_hw*[]){ 372 &gpu_cc_gx_gfx3d_clk_src.clkr.hw, 373 }, 374 .num_parents = 1, 375 .flags = CLK_SET_RATE_PARENT, 376 .ops = &clk_branch2_ops, 377 }, 378 }, 379 }; 380 381 static struct clk_branch gpu_cc_gx_gmu_clk = { 382 .halt_reg = 0x1064, 383 .halt_check = BRANCH_HALT, 384 .clkr = { 385 .enable_reg = 0x1064, 386 .enable_mask = BIT(0), 387 .hw.init = &(struct clk_init_data){ 388 .name = "gpu_cc_gx_gmu_clk", 389 .parent_hws = (const struct clk_hw*[]){ 390 &gpu_cc_gmu_clk_src.clkr.hw, 391 }, 392 .num_parents = 1, 393 .flags = CLK_SET_RATE_PARENT, 394 .ops = &clk_branch2_ops, 395 }, 396 }, 397 }; 398 399 static struct clk_branch gpu_cc_gx_vsense_clk = { 400 .halt_reg = 0x1058, 401 .halt_check = BRANCH_HALT_DELAY, 402 .clkr = { 403 .enable_reg = 0x1058, 404 .enable_mask = BIT(0), 405 .hw.init = &(struct clk_init_data){ 406 .name = "gpu_cc_gx_vsense_clk", 407 .ops = &clk_branch2_ops, 408 }, 409 }, 410 }; 411 412 static struct gdsc gpu_cx_gdsc = { 413 .gdscr = 0x106c, 414 .gds_hw_ctrl = 0x1540, 415 .pd = { 416 .name = "gpu_cx_gdsc", 417 }, 418 .pwrsts = PWRSTS_OFF_ON, 419 .flags = VOTABLE, 420 }; 421 422 static struct gdsc gpu_gx_gdsc = { 423 .gdscr = 0x100c, 424 .clamp_io_ctrl = 0x1508, 425 .pd = { 426 .name = "gpu_gx_gdsc", 427 .power_on = gdsc_gx_do_nothing_enable, 428 }, 429 .pwrsts = PWRSTS_OFF_ON, 430 .flags = CLAMP_IO | POLL_CFG_GDSCR, 431 }; 432 433 static struct clk_hw *gpu_cc_sm6350_hws[] = { 434 [GPU_CC_CRC_DIV] = &crc_div.hw, 435 }; 436 437 static struct clk_regmap *gpu_cc_sm6350_clocks[] = { 438 [GPU_CC_ACD_AHB_CLK] = &gpu_cc_acd_ahb_clk.clkr, 439 [GPU_CC_ACD_CXO_CLK] = &gpu_cc_acd_cxo_clk.clkr, 440 [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr, 441 [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr, 442 [GPU_CC_CX_GFX3D_CLK] = &gpu_cc_cx_gfx3d_clk.clkr, 443 [GPU_CC_CX_GFX3D_SLV_CLK] = &gpu_cc_cx_gfx3d_slv_clk.clkr, 444 [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr, 445 [GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_clk.clkr, 446 [GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr, 447 [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr, 448 [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr, 449 [GPU_CC_GX_CXO_CLK] = &gpu_cc_gx_cxo_clk.clkr, 450 [GPU_CC_GX_GFX3D_CLK] = &gpu_cc_gx_gfx3d_clk.clkr, 451 [GPU_CC_GX_GFX3D_CLK_SRC] = &gpu_cc_gx_gfx3d_clk_src.clkr, 452 [GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr, 453 [GPU_CC_GX_VSENSE_CLK] = &gpu_cc_gx_vsense_clk.clkr, 454 [GPU_CC_PLL0] = &gpu_cc_pll0.clkr, 455 [GPU_CC_PLL1] = &gpu_cc_pll1.clkr, 456 }; 457 458 static struct gdsc *gpu_cc_sm6350_gdscs[] = { 459 [GPU_CX_GDSC] = &gpu_cx_gdsc, 460 [GPU_GX_GDSC] = &gpu_gx_gdsc, 461 }; 462 463 static const struct regmap_config gpu_cc_sm6350_regmap_config = { 464 .reg_bits = 32, 465 .reg_stride = 4, 466 .val_bits = 32, 467 .max_register = 0x8008, 468 .fast_io = true, 469 }; 470 471 static const struct qcom_cc_desc gpu_cc_sm6350_desc = { 472 .config = &gpu_cc_sm6350_regmap_config, 473 .clk_hws = gpu_cc_sm6350_hws, 474 .num_clk_hws = ARRAY_SIZE(gpu_cc_sm6350_hws), 475 .clks = gpu_cc_sm6350_clocks, 476 .num_clks = ARRAY_SIZE(gpu_cc_sm6350_clocks), 477 .gdscs = gpu_cc_sm6350_gdscs, 478 .num_gdscs = ARRAY_SIZE(gpu_cc_sm6350_gdscs), 479 }; 480 481 static const struct of_device_id gpu_cc_sm6350_match_table[] = { 482 { .compatible = "qcom,sm6350-gpucc" }, 483 { } 484 }; 485 MODULE_DEVICE_TABLE(of, gpu_cc_sm6350_match_table); 486 487 static int gpu_cc_sm6350_probe(struct platform_device *pdev) 488 { 489 struct regmap *regmap; 490 unsigned int value, mask; 491 492 regmap = qcom_cc_map(pdev, &gpu_cc_sm6350_desc); 493 if (IS_ERR(regmap)) 494 return PTR_ERR(regmap); 495 496 clk_fabia_pll_configure(&gpu_cc_pll0, regmap, &gpu_cc_pll0_config); 497 clk_fabia_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config); 498 499 /* Configure gpu_cc_cx_gmu_clk with recommended wakeup/sleep settings */ 500 mask = CX_GMU_CBCR_WAKE_MASK << CX_GMU_CBCR_WAKE_SHIFT; 501 mask |= CX_GMU_CBCR_SLEEP_MASK << CX_GMU_CBCR_SLEEP_SHIFT; 502 value = 0xF << CX_GMU_CBCR_WAKE_SHIFT | 0xF << CX_GMU_CBCR_SLEEP_SHIFT; 503 regmap_update_bits(regmap, 0x1098, mask, value); 504 505 return qcom_cc_really_probe(pdev, &gpu_cc_sm6350_desc, regmap); 506 } 507 508 static struct platform_driver gpu_cc_sm6350_driver = { 509 .probe = gpu_cc_sm6350_probe, 510 .driver = { 511 .name = "sm6350-gpucc", 512 .of_match_table = gpu_cc_sm6350_match_table, 513 }, 514 }; 515 516 static int __init gpu_cc_sm6350_init(void) 517 { 518 return platform_driver_register(&gpu_cc_sm6350_driver); 519 } 520 core_initcall(gpu_cc_sm6350_init); 521 522 static void __exit gpu_cc_sm6350_exit(void) 523 { 524 platform_driver_unregister(&gpu_cc_sm6350_driver); 525 } 526 module_exit(gpu_cc_sm6350_exit); 527 528 MODULE_DESCRIPTION("QTI GPU_CC LAGOON Driver"); 529 MODULE_LICENSE("GPL v2"); 530