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