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