1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. 4 */ 5 #include <linux/clk-provider.h> 6 #include <linux/module.h> 7 #include <linux/platform_device.h> 8 #include <linux/pm_runtime.h> 9 #include <linux/regmap.h> 10 11 #include <dt-bindings/clock/qcom,sm8750-gpucc.h> 12 13 #include "clk-alpha-pll.h" 14 #include "clk-branch.h" 15 #include "clk-rcg.h" 16 #include "clk-regmap.h" 17 #include "clk-regmap-divider.h" 18 #include "clk-regmap-mux.h" 19 #include "gdsc.h" 20 #include "reset.h" 21 22 enum { 23 DT_BI_TCXO, 24 DT_GPLL0_OUT_MAIN, 25 DT_GPLL0_OUT_MAIN_DIV, 26 }; 27 28 enum { 29 P_BI_TCXO, 30 P_GPLL0_OUT_MAIN, 31 P_GPLL0_OUT_MAIN_DIV, 32 P_GPU_CC_PLL0_OUT_EVEN, 33 P_GPU_CC_PLL0_OUT_MAIN, 34 P_GPU_CC_PLL0_OUT_ODD, 35 }; 36 37 static const struct pll_vco taycan_elu_vco[] = { 38 { 249600000, 2500000000, 0 }, 39 }; 40 41 static const struct alpha_pll_config gpu_cc_pll0_config = { 42 .l = 0x34, 43 .alpha = 0x1555, 44 .config_ctl_val = 0x19660387, 45 .config_ctl_hi_val = 0x098060a0, 46 .config_ctl_hi1_val = 0xb416cb20, 47 .user_ctl_val = 0x00000400, 48 .user_ctl_hi_val = 0x00000002, 49 }; 50 51 static struct clk_alpha_pll gpu_cc_pll0 = { 52 .offset = 0x0, 53 .config = &gpu_cc_pll0_config, 54 .vco_table = taycan_elu_vco, 55 .num_vco = ARRAY_SIZE(taycan_elu_vco), 56 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_ELU], 57 .clkr = { 58 .hw.init = &(const struct clk_init_data) { 59 .name = "gpu_cc_pll0", 60 .parent_data = &(const struct clk_parent_data) { 61 .index = DT_BI_TCXO, 62 }, 63 .num_parents = 1, 64 .ops = &clk_alpha_pll_taycan_elu_ops, 65 }, 66 }, 67 }; 68 69 static const struct clk_div_table post_div_table_gpu_cc_pll0_out_even[] = { 70 { 0x1, 2 }, 71 { } 72 }; 73 74 static struct clk_alpha_pll_postdiv gpu_cc_pll0_out_even = { 75 .offset = 0x0, 76 .post_div_shift = 10, 77 .post_div_table = post_div_table_gpu_cc_pll0_out_even, 78 .num_post_div = ARRAY_SIZE(post_div_table_gpu_cc_pll0_out_even), 79 .width = 4, 80 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_ELU], 81 .clkr.hw.init = &(const struct clk_init_data) { 82 .name = "gpu_cc_pll0_out_even", 83 .parent_hws = (const struct clk_hw*[]) { 84 &gpu_cc_pll0.clkr.hw, 85 }, 86 .num_parents = 1, 87 .flags = CLK_SET_RATE_PARENT, 88 .ops = &clk_alpha_pll_postdiv_taycan_elu_ops, 89 }, 90 }; 91 92 static const struct parent_map gpu_cc_parent_map_1[] = { 93 { P_BI_TCXO, 0 }, 94 { P_GPU_CC_PLL0_OUT_MAIN, 1 }, 95 { P_GPU_CC_PLL0_OUT_EVEN, 2 }, 96 { P_GPU_CC_PLL0_OUT_ODD, 3 }, 97 { P_GPLL0_OUT_MAIN, 5 }, 98 { P_GPLL0_OUT_MAIN_DIV, 6 }, 99 }; 100 101 static const struct clk_parent_data gpu_cc_parent_data_1[] = { 102 { .index = DT_BI_TCXO }, 103 { .hw = &gpu_cc_pll0.clkr.hw }, 104 { .hw = &gpu_cc_pll0_out_even.clkr.hw }, 105 { .hw = &gpu_cc_pll0.clkr.hw }, 106 { .index = DT_GPLL0_OUT_MAIN }, 107 { .index = DT_GPLL0_OUT_MAIN_DIV }, 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(500000000, P_GPU_CC_PLL0_OUT_EVEN, 1, 0, 0), 113 F(650000000, P_GPU_CC_PLL0_OUT_EVEN, 1, 0, 0), 114 F(687500000, P_GPU_CC_PLL0_OUT_EVEN, 1, 0, 0), 115 { } 116 }; 117 118 static struct clk_rcg2 gpu_cc_gmu_clk_src = { 119 .cmd_rcgr = 0x9318, 120 .mnd_width = 0, 121 .hid_width = 5, 122 .parent_map = gpu_cc_parent_map_1, 123 .freq_tbl = ftbl_gpu_cc_gmu_clk_src, 124 .clkr.hw.init = &(const struct clk_init_data) { 125 .name = "gpu_cc_gmu_clk_src", 126 .parent_data = gpu_cc_parent_data_1, 127 .num_parents = ARRAY_SIZE(gpu_cc_parent_data_1), 128 .flags = CLK_SET_RATE_PARENT, 129 .ops = &clk_rcg2_shared_ops, 130 }, 131 }; 132 133 static const struct freq_tbl ftbl_gpu_cc_hub_clk_src[] = { 134 F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0), 135 F(300000000, P_GPLL0_OUT_MAIN, 2, 0, 0), 136 F(400000000, P_GPLL0_OUT_MAIN, 1.5, 0, 0), 137 { } 138 }; 139 140 static struct clk_rcg2 gpu_cc_hub_clk_src = { 141 .cmd_rcgr = 0x93ec, 142 .mnd_width = 0, 143 .hid_width = 5, 144 .parent_map = gpu_cc_parent_map_1, 145 .freq_tbl = ftbl_gpu_cc_hub_clk_src, 146 .clkr.hw.init = &(const struct clk_init_data) { 147 .name = "gpu_cc_hub_clk_src", 148 .parent_data = gpu_cc_parent_data_1, 149 .num_parents = ARRAY_SIZE(gpu_cc_parent_data_1), 150 .flags = CLK_SET_RATE_PARENT, 151 .ops = &clk_rcg2_shared_ops, 152 }, 153 }; 154 155 static struct clk_regmap_div gpu_cc_hub_div_clk_src = { 156 .reg = 0x942c, 157 .shift = 0, 158 .width = 4, 159 .clkr.hw.init = &(const struct clk_init_data) { 160 .name = "gpu_cc_hub_div_clk_src", 161 .parent_hws = (const struct clk_hw*[]) { 162 &gpu_cc_hub_clk_src.clkr.hw, 163 }, 164 .num_parents = 1, 165 .flags = CLK_SET_RATE_PARENT, 166 .ops = &clk_regmap_div_ro_ops, 167 }, 168 }; 169 170 static struct clk_branch gpu_cc_ahb_clk = { 171 .halt_reg = 0x90bc, 172 .halt_check = BRANCH_HALT_DELAY, 173 .clkr = { 174 .enable_reg = 0x90bc, 175 .enable_mask = BIT(0), 176 .hw.init = &(const struct clk_init_data) { 177 .name = "gpu_cc_ahb_clk", 178 .parent_hws = (const struct clk_hw*[]) { 179 &gpu_cc_hub_div_clk_src.clkr.hw, 180 }, 181 .num_parents = 1, 182 .flags = CLK_SET_RATE_PARENT, 183 .ops = &clk_branch2_ops, 184 }, 185 }, 186 }; 187 188 static struct clk_branch gpu_cc_cx_accu_shift_clk = { 189 .halt_reg = 0x910c, 190 .halt_check = BRANCH_HALT_VOTED, 191 .clkr = { 192 .enable_reg = 0x910c, 193 .enable_mask = BIT(0), 194 .hw.init = &(const struct clk_init_data) { 195 .name = "gpu_cc_cx_accu_shift_clk", 196 .ops = &clk_branch2_ops, 197 }, 198 }, 199 }; 200 201 static struct clk_branch gpu_cc_cx_gmu_clk = { 202 .halt_reg = 0x90d4, 203 .halt_check = BRANCH_HALT_VOTED, 204 .clkr = { 205 .enable_reg = 0x90d4, 206 .enable_mask = BIT(0), 207 .hw.init = &(const struct clk_init_data) { 208 .name = "gpu_cc_cx_gmu_clk", 209 .parent_hws = (const struct clk_hw*[]) { 210 &gpu_cc_gmu_clk_src.clkr.hw, 211 }, 212 .num_parents = 1, 213 .flags = CLK_SET_RATE_PARENT, 214 .ops = &clk_branch2_aon_ops, 215 }, 216 }, 217 }; 218 219 static struct clk_branch gpu_cc_cxo_clk = { 220 .halt_reg = 0x90e4, 221 .halt_check = BRANCH_HALT, 222 .clkr = { 223 .enable_reg = 0x90e4, 224 .enable_mask = BIT(0), 225 .hw.init = &(const struct clk_init_data) { 226 .name = "gpu_cc_cxo_clk", 227 .ops = &clk_branch2_ops, 228 }, 229 }, 230 }; 231 232 static struct clk_branch gpu_cc_demet_clk = { 233 .halt_reg = 0x9010, 234 .halt_check = BRANCH_HALT_VOTED, 235 .clkr = { 236 .enable_reg = 0x9010, 237 .enable_mask = BIT(0), 238 .hw.init = &(const struct clk_init_data) { 239 .name = "gpu_cc_demet_clk", 240 .ops = &clk_branch2_ops, 241 }, 242 }, 243 }; 244 245 static struct clk_branch gpu_cc_dpm_clk = { 246 .halt_reg = 0x9110, 247 .halt_check = BRANCH_HALT, 248 .clkr = { 249 .enable_reg = 0x9110, 250 .enable_mask = BIT(0), 251 .hw.init = &(const struct clk_init_data) { 252 .name = "gpu_cc_dpm_clk", 253 .ops = &clk_branch2_ops, 254 }, 255 }, 256 }; 257 258 static struct clk_branch gpu_cc_freq_measure_clk = { 259 .halt_reg = 0x900c, 260 .halt_check = BRANCH_HALT, 261 .clkr = { 262 .enable_reg = 0x900c, 263 .enable_mask = BIT(0), 264 .hw.init = &(const struct clk_init_data) { 265 .name = "gpu_cc_freq_measure_clk", 266 .ops = &clk_branch2_ops, 267 }, 268 }, 269 }; 270 271 static struct clk_branch gpu_cc_gx_accu_shift_clk = { 272 .halt_reg = 0x9070, 273 .halt_check = BRANCH_HALT_VOTED, 274 .clkr = { 275 .enable_reg = 0x9070, 276 .enable_mask = BIT(0), 277 .hw.init = &(const struct clk_init_data) { 278 .name = "gpu_cc_gx_accu_shift_clk", 279 .ops = &clk_branch2_ops, 280 }, 281 }, 282 }; 283 284 static struct clk_branch gpu_cc_gx_gmu_clk = { 285 .halt_reg = 0x9060, 286 .halt_check = BRANCH_HALT, 287 .clkr = { 288 .enable_reg = 0x9060, 289 .enable_mask = BIT(0), 290 .hw.init = &(const struct clk_init_data) { 291 .name = "gpu_cc_gx_gmu_clk", 292 .parent_hws = (const struct clk_hw*[]) { 293 &gpu_cc_gmu_clk_src.clkr.hw, 294 }, 295 .num_parents = 1, 296 .flags = CLK_SET_RATE_PARENT, 297 .ops = &clk_branch2_ops, 298 }, 299 }, 300 }; 301 302 static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk = { 303 .halt_reg = 0x7000, 304 .halt_check = BRANCH_HALT_VOTED, 305 .clkr = { 306 .enable_reg = 0x7000, 307 .enable_mask = BIT(0), 308 .hw.init = &(const struct clk_init_data) { 309 .name = "gpu_cc_hlos1_vote_gpu_smmu_clk", 310 .ops = &clk_branch2_ops, 311 }, 312 }, 313 }; 314 315 static struct clk_branch gpu_cc_hub_aon_clk = { 316 .halt_reg = 0x93e8, 317 .halt_check = BRANCH_HALT_VOTED, 318 .clkr = { 319 .enable_reg = 0x93e8, 320 .enable_mask = BIT(0), 321 .hw.init = &(const struct clk_init_data) { 322 .name = "gpu_cc_hub_aon_clk", 323 .parent_hws = (const struct clk_hw*[]) { 324 &gpu_cc_hub_clk_src.clkr.hw, 325 }, 326 .num_parents = 1, 327 .flags = CLK_SET_RATE_PARENT, 328 .ops = &clk_branch2_aon_ops, 329 }, 330 }, 331 }; 332 333 static struct clk_branch gpu_cc_hub_cx_int_clk = { 334 .halt_reg = 0x90e8, 335 .halt_check = BRANCH_HALT_VOTED, 336 .clkr = { 337 .enable_reg = 0x90e8, 338 .enable_mask = BIT(0), 339 .hw.init = &(const struct clk_init_data) { 340 .name = "gpu_cc_hub_cx_int_clk", 341 .parent_hws = (const struct clk_hw*[]) { 342 &gpu_cc_hub_clk_src.clkr.hw, 343 }, 344 .num_parents = 1, 345 .flags = CLK_SET_RATE_PARENT, 346 .ops = &clk_branch2_aon_ops, 347 }, 348 }, 349 }; 350 351 static struct clk_branch gpu_cc_memnoc_gfx_clk = { 352 .halt_reg = 0x90f4, 353 .halt_check = BRANCH_HALT_VOTED, 354 .clkr = { 355 .enable_reg = 0x90f4, 356 .enable_mask = BIT(0), 357 .hw.init = &(const struct clk_init_data) { 358 .name = "gpu_cc_memnoc_gfx_clk", 359 .ops = &clk_branch2_ops, 360 }, 361 }, 362 }; 363 364 static struct gdsc gpu_cc_cx_gdsc = { 365 .gdscr = 0x9080, 366 .gds_hw_ctrl = 0x9094, 367 .en_rest_wait_val = 0x2, 368 .en_few_wait_val = 0x2, 369 .clk_dis_wait_val = 0x8, 370 .pd = { 371 .name = "gpu_cc_cx_gdsc", 372 }, 373 .pwrsts = PWRSTS_OFF_ON, 374 .flags = RETAIN_FF_ENABLE | VOTABLE, 375 }; 376 377 static struct clk_regmap *gpu_cc_sm8750_clocks[] = { 378 [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr, 379 [GPU_CC_CX_ACCU_SHIFT_CLK] = &gpu_cc_cx_accu_shift_clk.clkr, 380 [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr, 381 [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr, 382 [GPU_CC_DEMET_CLK] = &gpu_cc_demet_clk.clkr, 383 [GPU_CC_DPM_CLK] = &gpu_cc_dpm_clk.clkr, 384 [GPU_CC_FREQ_MEASURE_CLK] = &gpu_cc_freq_measure_clk.clkr, 385 [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr, 386 [GPU_CC_GX_ACCU_SHIFT_CLK] = &gpu_cc_gx_accu_shift_clk.clkr, 387 [GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr, 388 [GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK] = &gpu_cc_hlos1_vote_gpu_smmu_clk.clkr, 389 [GPU_CC_HUB_AON_CLK] = &gpu_cc_hub_aon_clk.clkr, 390 [GPU_CC_HUB_CLK_SRC] = &gpu_cc_hub_clk_src.clkr, 391 [GPU_CC_HUB_CX_INT_CLK] = &gpu_cc_hub_cx_int_clk.clkr, 392 [GPU_CC_HUB_DIV_CLK_SRC] = &gpu_cc_hub_div_clk_src.clkr, 393 [GPU_CC_MEMNOC_GFX_CLK] = &gpu_cc_memnoc_gfx_clk.clkr, 394 [GPU_CC_PLL0] = &gpu_cc_pll0.clkr, 395 [GPU_CC_PLL0_OUT_EVEN] = &gpu_cc_pll0_out_even.clkr, 396 }; 397 398 static struct gdsc *gpu_cc_sm8750_gdscs[] = { 399 [GPU_CC_CX_GDSC] = &gpu_cc_cx_gdsc, 400 }; 401 402 static const struct qcom_reset_map gpu_cc_sm8750_resets[] = { 403 [GPU_CC_GPU_CC_XO_BCR] = { 0x9000 }, 404 [GPU_CC_GPU_CC_GX_BCR] = { 0x905c }, 405 [GPU_CC_GPU_CC_CX_BCR] = { 0x907c }, 406 [GPU_CC_GPU_CC_GMU_BCR] = { 0x9314 }, 407 [GPU_CC_GPU_CC_CB_BCR] = { 0x93a0 }, 408 [GPU_CC_GPU_CC_FAST_HUB_BCR] = { 0x93e4 }, 409 }; 410 411 static const struct regmap_config gpu_cc_sm8750_regmap_config = { 412 .reg_bits = 32, 413 .reg_stride = 4, 414 .val_bits = 32, 415 .max_register = 0x9800, 416 .fast_io = true, 417 }; 418 419 static struct clk_alpha_pll *gpu_cc_alpha_plls[] = { 420 &gpu_cc_pll0, 421 }; 422 423 static const u32 gpu_cc_sm8750_critical_cbcrs[] = { 424 0x9004, /* GPU_CC_RSCC_XO_AON_CLK */ 425 0x9008, /* GPU_CC_CXO_AON_CLK */ 426 0x9064, /* GPU_CC_GX_AHB_FF_CLK */ 427 0x90cc, /* GPU_CC_SLEEP_CLK */ 428 0x93a4, /* GPU_CC_CB_CLK */ 429 0x93a8, /* GPU_CC_RSCC_HUB_AON_CLK */ 430 }; 431 432 static const struct qcom_cc_driver_data gpu_cc_sm8750_driver_data = { 433 .alpha_plls = gpu_cc_alpha_plls, 434 .num_alpha_plls = ARRAY_SIZE(gpu_cc_alpha_plls), 435 .clk_cbcrs = gpu_cc_sm8750_critical_cbcrs, 436 .num_clk_cbcrs = ARRAY_SIZE(gpu_cc_sm8750_critical_cbcrs), 437 }; 438 439 static const struct qcom_cc_desc gpu_cc_sm8750_desc = { 440 .config = &gpu_cc_sm8750_regmap_config, 441 .clks = gpu_cc_sm8750_clocks, 442 .num_clks = ARRAY_SIZE(gpu_cc_sm8750_clocks), 443 .resets = gpu_cc_sm8750_resets, 444 .num_resets = ARRAY_SIZE(gpu_cc_sm8750_resets), 445 .gdscs = gpu_cc_sm8750_gdscs, 446 .num_gdscs = ARRAY_SIZE(gpu_cc_sm8750_gdscs), 447 .use_rpm = true, 448 .driver_data = &gpu_cc_sm8750_driver_data, 449 }; 450 451 static const struct of_device_id gpu_cc_sm8750_match_table[] = { 452 { .compatible = "qcom,sm8750-gpucc" }, 453 { } 454 }; 455 MODULE_DEVICE_TABLE(of, gpu_cc_sm8750_match_table); 456 457 static int gpu_cc_sm8750_probe(struct platform_device *pdev) 458 { 459 return qcom_cc_probe(pdev, &gpu_cc_sm8750_desc); 460 } 461 462 static struct platform_driver gpu_cc_sm8750_driver = { 463 .probe = gpu_cc_sm8750_probe, 464 .driver = { 465 .name = "sm8750-gpucc", 466 .of_match_table = gpu_cc_sm8750_match_table, 467 }, 468 }; 469 module_platform_driver(gpu_cc_sm8750_driver); 470 471 MODULE_DESCRIPTION("QTI GPU_CC SM8750 Driver"); 472 MODULE_LICENSE("GPL"); 473