1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. 4 * Copyright (c) 2023, Linaro Limited 5 */ 6 7 #include <linux/clk-provider.h> 8 #include <linux/module.h> 9 #include <linux/of_device.h> 10 #include <linux/regmap.h> 11 12 #include <dt-bindings/clock/qcom,sm6115-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 "clk-regmap-phy-mux.h" 21 #include "gdsc.h" 22 #include "reset.h" 23 24 enum { 25 DT_BI_TCXO, 26 DT_GCC_GPU_GPLL0_CLK_SRC, 27 DT_GCC_GPU_GPLL0_DIV_CLK_SRC, 28 }; 29 30 enum { 31 P_BI_TCXO, 32 P_GPLL0_OUT_MAIN, 33 P_GPLL0_OUT_MAIN_DIV, 34 P_GPU_CC_PLL0_OUT_AUX2, 35 P_GPU_CC_PLL0_OUT_MAIN, 36 P_GPU_CC_PLL1_OUT_AUX, 37 P_GPU_CC_PLL1_OUT_MAIN, 38 }; 39 40 static struct pll_vco default_vco[] = { 41 { 1000000000, 2000000000, 0 }, 42 }; 43 44 static struct pll_vco pll1_vco[] = { 45 { 500000000, 1000000000, 2 }, 46 }; 47 48 static const struct alpha_pll_config gpu_cc_pll0_config = { 49 .l = 0x3e, 50 .alpha = 0, 51 .alpha_hi = 0x80, 52 .vco_val = 0x0 << 20, 53 .vco_mask = GENMASK(21, 20), 54 .alpha_en_mask = BIT(24), 55 .main_output_mask = BIT(0), 56 .aux_output_mask = BIT(1), 57 .aux2_output_mask = BIT(2), 58 .config_ctl_val = 0x4001055b, 59 .test_ctl_hi1_val = 0x1, 60 }; 61 62 /* 1200MHz configuration */ 63 static struct clk_alpha_pll gpu_cc_pll0 = { 64 .offset = 0x0, 65 .vco_table = default_vco, 66 .num_vco = ARRAY_SIZE(default_vco), 67 .flags = SUPPORTS_DYNAMIC_UPDATE, 68 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], 69 .clkr = { 70 .hw.init = &(struct clk_init_data){ 71 .name = "gpu_cc_pll0", 72 .parent_data = &(const struct clk_parent_data){ 73 .index = DT_BI_TCXO, 74 }, 75 .num_parents = 1, 76 .ops = &clk_alpha_pll_ops, 77 }, 78 }, 79 }; 80 81 static const struct clk_div_table post_div_table_gpu_cc_pll0_out_aux2[] = { 82 { 0x0, 1 }, 83 { } 84 }; 85 86 static struct clk_alpha_pll_postdiv gpu_cc_pll0_out_aux2 = { 87 .offset = 0x0, 88 .post_div_shift = 8, 89 .post_div_table = post_div_table_gpu_cc_pll0_out_aux2, 90 .num_post_div = ARRAY_SIZE(post_div_table_gpu_cc_pll0_out_aux2), 91 .width = 4, 92 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], 93 .clkr.hw.init = &(struct clk_init_data){ 94 .name = "gpu_cc_pll0_out_aux2", 95 .parent_hws = (const struct clk_hw*[]) { 96 &gpu_cc_pll0.clkr.hw, 97 }, 98 .num_parents = 1, 99 .flags = CLK_SET_RATE_PARENT, 100 .ops = &clk_alpha_pll_postdiv_ops, 101 }, 102 }; 103 104 /* 640MHz configuration */ 105 static const struct alpha_pll_config gpu_cc_pll1_config = { 106 .l = 0x21, 107 .alpha = 0x55555555, 108 .alpha_hi = 0x55, 109 .alpha_en_mask = BIT(24), 110 .vco_val = 0x2 << 20, 111 .vco_mask = GENMASK(21, 20), 112 .main_output_mask = BIT(0), 113 .aux_output_mask = BIT(1), 114 .config_ctl_val = 0x4001055b, 115 .test_ctl_hi1_val = 0x1, 116 }; 117 118 static struct clk_alpha_pll gpu_cc_pll1 = { 119 .offset = 0x100, 120 .vco_table = pll1_vco, 121 .num_vco = ARRAY_SIZE(pll1_vco), 122 .flags = SUPPORTS_DYNAMIC_UPDATE, 123 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], 124 .clkr = { 125 .hw.init = &(struct clk_init_data){ 126 .name = "gpu_cc_pll1", 127 .parent_data = &(const struct clk_parent_data){ 128 .index = DT_BI_TCXO, 129 }, 130 .num_parents = 1, 131 .ops = &clk_alpha_pll_ops, 132 }, 133 }, 134 }; 135 136 static const struct clk_div_table post_div_table_gpu_cc_pll1_out_aux[] = { 137 { 0x0, 1 }, 138 { } 139 }; 140 141 static struct clk_alpha_pll_postdiv gpu_cc_pll1_out_aux = { 142 .offset = 0x100, 143 .post_div_shift = 15, 144 .post_div_table = post_div_table_gpu_cc_pll1_out_aux, 145 .num_post_div = ARRAY_SIZE(post_div_table_gpu_cc_pll1_out_aux), 146 .width = 3, 147 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], 148 .clkr.hw.init = &(struct clk_init_data){ 149 .name = "gpu_cc_pll1_out_aux", 150 .parent_hws = (const struct clk_hw*[]) { 151 &gpu_cc_pll1.clkr.hw, 152 }, 153 .num_parents = 1, 154 .flags = CLK_SET_RATE_PARENT, 155 .ops = &clk_alpha_pll_postdiv_ops, 156 }, 157 }; 158 159 static const struct parent_map gpu_cc_parent_map_0[] = { 160 { P_BI_TCXO, 0 }, 161 { P_GPU_CC_PLL0_OUT_MAIN, 1 }, 162 { P_GPU_CC_PLL1_OUT_MAIN, 3 }, 163 { P_GPLL0_OUT_MAIN, 5 }, 164 { P_GPLL0_OUT_MAIN_DIV, 6 }, 165 }; 166 167 static const struct clk_parent_data gpu_cc_parent_data_0[] = { 168 { .index = P_BI_TCXO }, 169 { .hw = &gpu_cc_pll0.clkr.hw }, 170 { .hw = &gpu_cc_pll1.clkr.hw }, 171 { .index = DT_GCC_GPU_GPLL0_CLK_SRC }, 172 { .index = DT_GCC_GPU_GPLL0_DIV_CLK_SRC }, 173 }; 174 175 static const struct parent_map gpu_cc_parent_map_1[] = { 176 { P_BI_TCXO, 0 }, 177 { P_GPU_CC_PLL0_OUT_AUX2, 2 }, 178 { P_GPU_CC_PLL1_OUT_AUX, 3 }, 179 { P_GPLL0_OUT_MAIN, 5 }, 180 }; 181 182 static const struct clk_parent_data gpu_cc_parent_data_1[] = { 183 { .index = P_BI_TCXO }, 184 { .hw = &gpu_cc_pll0_out_aux2.clkr.hw }, 185 { .hw = &gpu_cc_pll1_out_aux.clkr.hw }, 186 { .index = DT_GCC_GPU_GPLL0_CLK_SRC }, 187 }; 188 189 static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = { 190 F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0), 191 { } 192 }; 193 194 static struct clk_rcg2 gpu_cc_gmu_clk_src = { 195 .cmd_rcgr = 0x1120, 196 .mnd_width = 0, 197 .hid_width = 5, 198 .parent_map = gpu_cc_parent_map_0, 199 .freq_tbl = ftbl_gpu_cc_gmu_clk_src, 200 .clkr.hw.init = &(struct clk_init_data){ 201 .name = "gpu_cc_gmu_clk_src", 202 .parent_data = gpu_cc_parent_data_0, 203 .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0), 204 .flags = CLK_SET_RATE_PARENT, 205 .ops = &clk_rcg2_shared_ops, 206 }, 207 }; 208 209 static const struct freq_tbl ftbl_gpu_cc_gx_gfx3d_clk_src[] = { 210 F(320000000, P_GPU_CC_PLL1_OUT_AUX, 2, 0, 0), 211 F(465000000, P_GPU_CC_PLL1_OUT_AUX, 2, 0, 0), 212 F(600000000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), 213 F(745000000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), 214 F(820000000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), 215 F(900000000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), 216 F(950000000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), 217 F(980000000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), 218 { } 219 }; 220 221 static struct clk_rcg2 gpu_cc_gx_gfx3d_clk_src = { 222 .cmd_rcgr = 0x101c, 223 .mnd_width = 0, 224 .hid_width = 5, 225 .parent_map = gpu_cc_parent_map_1, 226 .freq_tbl = ftbl_gpu_cc_gx_gfx3d_clk_src, 227 .clkr.hw.init = &(struct clk_init_data){ 228 .name = "gpu_cc_gx_gfx3d_clk_src", 229 .parent_data = gpu_cc_parent_data_1, 230 .num_parents = ARRAY_SIZE(gpu_cc_parent_data_1), 231 .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, 232 .ops = &clk_rcg2_ops, 233 }, 234 }; 235 236 static struct clk_branch gpu_cc_ahb_clk = { 237 .halt_reg = 0x1078, 238 .halt_check = BRANCH_HALT_DELAY, 239 .clkr = { 240 .enable_reg = 0x1078, 241 .enable_mask = BIT(0), 242 .hw.init = &(struct clk_init_data){ 243 .name = "gpu_cc_ahb_clk", 244 .flags = CLK_IS_CRITICAL, 245 .ops = &clk_branch2_ops, 246 }, 247 }, 248 }; 249 250 static struct clk_branch gpu_cc_crc_ahb_clk = { 251 .halt_reg = 0x107c, 252 .halt_check = BRANCH_HALT_DELAY, 253 .clkr = { 254 .enable_reg = 0x107c, 255 .enable_mask = BIT(0), 256 .hw.init = &(struct clk_init_data){ 257 .name = "gpu_cc_crc_ahb_clk", 258 .ops = &clk_branch2_ops, 259 }, 260 }, 261 }; 262 263 static struct clk_branch gpu_cc_cx_gfx3d_clk = { 264 .halt_reg = 0x10a4, 265 .halt_check = BRANCH_HALT_DELAY, 266 .clkr = { 267 .enable_reg = 0x10a4, 268 .enable_mask = BIT(0), 269 .hw.init = &(struct clk_init_data){ 270 .name = "gpu_cc_cx_gfx3d_clk", 271 .parent_data = &(const struct clk_parent_data){ 272 .hw = &gpu_cc_gx_gfx3d_clk_src.clkr.hw, 273 }, 274 .num_parents = 1, 275 .flags = CLK_SET_RATE_PARENT, 276 .ops = &clk_branch2_ops, 277 }, 278 }, 279 }; 280 281 static struct clk_branch gpu_cc_cx_gmu_clk = { 282 .halt_reg = 0x1098, 283 .halt_check = BRANCH_HALT, 284 .clkr = { 285 .enable_reg = 0x1098, 286 .enable_mask = BIT(0), 287 .hw.init = &(struct clk_init_data){ 288 .name = "gpu_cc_cx_gmu_clk", 289 .parent_data = &(const struct clk_parent_data){ 290 .hw = &gpu_cc_gmu_clk_src.clkr.hw, 291 }, 292 .num_parents = 1, 293 .flags = CLK_SET_RATE_PARENT, 294 .ops = &clk_branch2_ops, 295 }, 296 }, 297 }; 298 299 static struct clk_branch gpu_cc_cx_snoc_dvm_clk = { 300 .halt_reg = 0x108c, 301 .halt_check = BRANCH_HALT_DELAY, 302 .clkr = { 303 .enable_reg = 0x108c, 304 .enable_mask = BIT(0), 305 .hw.init = &(struct clk_init_data){ 306 .name = "gpu_cc_cx_snoc_dvm_clk", 307 .ops = &clk_branch2_ops, 308 }, 309 }, 310 }; 311 312 static struct clk_branch gpu_cc_cxo_aon_clk = { 313 .halt_reg = 0x1004, 314 .halt_check = BRANCH_HALT_DELAY, 315 .clkr = { 316 .enable_reg = 0x1004, 317 .enable_mask = BIT(0), 318 .hw.init = &(struct clk_init_data){ 319 .name = "gpu_cc_cxo_aon_clk", 320 .ops = &clk_branch2_ops, 321 }, 322 }, 323 }; 324 325 static struct clk_branch gpu_cc_cxo_clk = { 326 .halt_reg = 0x109c, 327 .halt_check = BRANCH_HALT, 328 .clkr = { 329 .enable_reg = 0x109c, 330 .enable_mask = BIT(0), 331 .hw.init = &(struct clk_init_data){ 332 .name = "gpu_cc_cxo_clk", 333 .ops = &clk_branch2_ops, 334 }, 335 }, 336 }; 337 338 static struct clk_branch gpu_cc_gx_cxo_clk = { 339 .halt_reg = 0x1060, 340 .halt_check = BRANCH_HALT_DELAY, 341 .clkr = { 342 .enable_reg = 0x1060, 343 .enable_mask = BIT(0), 344 .hw.init = &(struct clk_init_data){ 345 .name = "gpu_cc_gx_cxo_clk", 346 .flags = CLK_IS_CRITICAL, 347 .ops = &clk_branch2_ops, 348 }, 349 }, 350 }; 351 352 static struct clk_branch gpu_cc_gx_gfx3d_clk = { 353 .halt_reg = 0x1054, 354 .halt_check = BRANCH_HALT_SKIP, 355 .clkr = { 356 .enable_reg = 0x1054, 357 .enable_mask = BIT(0), 358 .hw.init = &(struct clk_init_data){ 359 .name = "gpu_cc_gx_gfx3d_clk", 360 .parent_data = &(const struct clk_parent_data){ 361 .hw = &gpu_cc_gx_gfx3d_clk_src.clkr.hw, 362 }, 363 .num_parents = 1, 364 .flags = CLK_SET_RATE_PARENT, 365 .ops = &clk_branch2_ops, 366 }, 367 }, 368 }; 369 370 static struct clk_branch gpu_cc_sleep_clk = { 371 .halt_reg = 0x1090, 372 .halt_check = BRANCH_HALT_DELAY, 373 .clkr = { 374 .enable_reg = 0x1090, 375 .enable_mask = BIT(0), 376 .hw.init = &(struct clk_init_data){ 377 .name = "gpu_cc_sleep_clk", 378 .ops = &clk_branch2_ops, 379 }, 380 }, 381 }; 382 383 static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk = { 384 .halt_reg = 0x5000, 385 .halt_check = BRANCH_VOTED, 386 .clkr = { 387 .enable_reg = 0x5000, 388 .enable_mask = BIT(0), 389 .hw.init = &(struct clk_init_data){ 390 .name = "gpu_cc_hlos1_vote_gpu_smmu_clk", 391 .ops = &clk_branch2_ops, 392 }, 393 }, 394 }; 395 396 static struct gdsc gpu_cx_gdsc = { 397 .gdscr = 0x106c, 398 .gds_hw_ctrl = 0x1540, 399 .pd = { 400 .name = "gpu_cx_gdsc", 401 }, 402 .pwrsts = PWRSTS_OFF_ON, 403 .flags = VOTABLE, 404 }; 405 406 static struct gdsc gpu_gx_gdsc = { 407 .gdscr = 0x100c, 408 .clamp_io_ctrl = 0x1508, 409 .resets = (unsigned int []){ GPU_GX_BCR }, 410 .reset_count = 1, 411 .pd = { 412 .name = "gpu_gx_gdsc", 413 }, 414 .parent = &gpu_cx_gdsc.pd, 415 .pwrsts = PWRSTS_OFF_ON, 416 .flags = CLAMP_IO | SW_RESET | VOTABLE, 417 }; 418 419 static struct clk_regmap *gpu_cc_sm6115_clocks[] = { 420 [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr, 421 [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr, 422 [GPU_CC_CX_GFX3D_CLK] = &gpu_cc_cx_gfx3d_clk.clkr, 423 [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr, 424 [GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_clk.clkr, 425 [GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr, 426 [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr, 427 [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr, 428 [GPU_CC_GX_CXO_CLK] = &gpu_cc_gx_cxo_clk.clkr, 429 [GPU_CC_GX_GFX3D_CLK] = &gpu_cc_gx_gfx3d_clk.clkr, 430 [GPU_CC_GX_GFX3D_CLK_SRC] = &gpu_cc_gx_gfx3d_clk_src.clkr, 431 [GPU_CC_PLL0] = &gpu_cc_pll0.clkr, 432 [GPU_CC_PLL0_OUT_AUX2] = &gpu_cc_pll0_out_aux2.clkr, 433 [GPU_CC_PLL1] = &gpu_cc_pll1.clkr, 434 [GPU_CC_PLL1_OUT_AUX] = &gpu_cc_pll1_out_aux.clkr, 435 [GPU_CC_SLEEP_CLK] = &gpu_cc_sleep_clk.clkr, 436 [GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK] = &gpu_cc_hlos1_vote_gpu_smmu_clk.clkr, 437 }; 438 439 static const struct qcom_reset_map gpu_cc_sm6115_resets[] = { 440 [GPU_GX_BCR] = { 0x1008 }, 441 }; 442 443 static struct gdsc *gpu_cc_sm6115_gdscs[] = { 444 [GPU_CX_GDSC] = &gpu_cx_gdsc, 445 [GPU_GX_GDSC] = &gpu_gx_gdsc, 446 }; 447 448 static const struct regmap_config gpu_cc_sm6115_regmap_config = { 449 .reg_bits = 32, 450 .reg_stride = 4, 451 .val_bits = 32, 452 .max_register = 0x9000, 453 .fast_io = true, 454 }; 455 456 static const struct qcom_cc_desc gpu_cc_sm6115_desc = { 457 .config = &gpu_cc_sm6115_regmap_config, 458 .clks = gpu_cc_sm6115_clocks, 459 .num_clks = ARRAY_SIZE(gpu_cc_sm6115_clocks), 460 .resets = gpu_cc_sm6115_resets, 461 .num_resets = ARRAY_SIZE(gpu_cc_sm6115_resets), 462 .gdscs = gpu_cc_sm6115_gdscs, 463 .num_gdscs = ARRAY_SIZE(gpu_cc_sm6115_gdscs), 464 }; 465 466 static const struct of_device_id gpu_cc_sm6115_match_table[] = { 467 { .compatible = "qcom,sm6115-gpucc" }, 468 { } 469 }; 470 MODULE_DEVICE_TABLE(of, gpu_cc_sm6115_match_table); 471 472 static int gpu_cc_sm6115_probe(struct platform_device *pdev) 473 { 474 struct regmap *regmap; 475 476 regmap = qcom_cc_map(pdev, &gpu_cc_sm6115_desc); 477 if (IS_ERR(regmap)) 478 return PTR_ERR(regmap); 479 480 clk_alpha_pll_configure(&gpu_cc_pll0, regmap, &gpu_cc_pll0_config); 481 clk_alpha_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config); 482 483 /* Set recommended WAKEUP/SLEEP settings for the gpu_cc_cx_gmu_clk */ 484 qcom_branch_set_wakeup(regmap, gpu_cc_cx_gmu_clk, 0xf); 485 qcom_branch_set_sleep(regmap, gpu_cc_cx_gmu_clk, 0xf); 486 487 qcom_branch_set_force_mem_core(regmap, gpu_cc_gx_gfx3d_clk, true); 488 qcom_branch_set_force_periph_on(regmap, gpu_cc_gx_gfx3d_clk, true); 489 490 return qcom_cc_really_probe(pdev, &gpu_cc_sm6115_desc, regmap); 491 } 492 493 static struct platform_driver gpu_cc_sm6115_driver = { 494 .probe = gpu_cc_sm6115_probe, 495 .driver = { 496 .name = "sm6115-gpucc", 497 .of_match_table = gpu_cc_sm6115_match_table, 498 }, 499 }; 500 module_platform_driver(gpu_cc_sm6115_driver); 501 502 MODULE_DESCRIPTION("QTI GPU_CC SM6115 Driver"); 503 MODULE_LICENSE("GPL"); 504