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