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