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