1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2021, Qualcomm Innovation Center, Inc. All rights reserved. 4 * Copyright (c) 2024, Linaro Limited 5 */ 6 7 #include <linux/clk-provider.h> 8 #include <linux/kernel.h> 9 #include <linux/module.h> 10 #include <linux/platform_device.h> 11 #include <linux/regmap.h> 12 13 #include <dt-bindings/clock/qcom,sar2130p-gpucc.h> 14 #include <dt-bindings/reset/qcom,sar2130p-gpucc.h> 15 16 #include "clk-alpha-pll.h" 17 #include "clk-branch.h" 18 #include "clk-rcg.h" 19 #include "common.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_MAIN, 34 P_GPU_CC_PLL1_OUT_MAIN, 35 }; 36 37 static const struct pll_vco lucid_ole_vco[] = { 38 { 249600000, 2000000000, 0 }, 39 }; 40 41 /* 470MHz Configuration */ 42 static const struct alpha_pll_config gpu_cc_pll0_config = { 43 .l = 0x18, 44 .alpha = 0x7aaa, 45 .config_ctl_val = 0x20485699, 46 .config_ctl_hi_val = 0x00182261, 47 .config_ctl_hi1_val = 0x82aa299c, 48 .test_ctl_val = 0x00000000, 49 .test_ctl_hi_val = 0x00000003, 50 .test_ctl_hi1_val = 0x00009000, 51 .test_ctl_hi2_val = 0x00000034, 52 .user_ctl_val = 0x00000000, 53 .user_ctl_hi_val = 0x00000005, 54 }; 55 56 static struct clk_alpha_pll gpu_cc_pll0 = { 57 .offset = 0x0, 58 .vco_table = lucid_ole_vco, 59 .num_vco = ARRAY_SIZE(lucid_ole_vco), 60 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], 61 .clkr = { 62 .hw.init = &(const struct clk_init_data) { 63 .name = "gpu_cc_pll0", 64 .parent_data = &(const struct clk_parent_data) { 65 .index = DT_BI_TCXO, 66 }, 67 .num_parents = 1, 68 .ops = &clk_alpha_pll_lucid_evo_ops, 69 }, 70 }, 71 }; 72 73 /* 440MHz Configuration */ 74 static const struct alpha_pll_config gpu_cc_pll1_config = { 75 .l = 0x16, 76 .alpha = 0xeaaa, 77 .config_ctl_val = 0x20485699, 78 .config_ctl_hi_val = 0x00182261, 79 .config_ctl_hi1_val = 0x82aa299c, 80 .test_ctl_val = 0x00000000, 81 .test_ctl_hi_val = 0x00000003, 82 .test_ctl_hi1_val = 0x00009000, 83 .test_ctl_hi2_val = 0x00000034, 84 .user_ctl_val = 0x00000000, 85 .user_ctl_hi_val = 0x00000005, 86 }; 87 88 static struct clk_alpha_pll gpu_cc_pll1 = { 89 .offset = 0x1000, 90 .vco_table = lucid_ole_vco, 91 .num_vco = ARRAY_SIZE(lucid_ole_vco), 92 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], 93 .clkr = { 94 .hw.init = &(const struct clk_init_data) { 95 .name = "gpu_cc_pll1", 96 .parent_data = &(const struct clk_parent_data) { 97 .index = DT_BI_TCXO, 98 }, 99 .num_parents = 1, 100 .ops = &clk_alpha_pll_lucid_evo_ops, 101 }, 102 }, 103 }; 104 105 static const struct parent_map gpu_cc_parent_map_0[] = { 106 { P_BI_TCXO, 0 }, 107 { P_GPLL0_OUT_MAIN, 5 }, 108 { P_GPLL0_OUT_MAIN_DIV, 6 }, 109 }; 110 111 static const struct clk_parent_data gpu_cc_parent_data_0[] = { 112 { .index = DT_BI_TCXO }, 113 { .index = DT_GPLL0_OUT_MAIN }, 114 { .index = DT_GPLL0_OUT_MAIN_DIV }, 115 }; 116 117 static const struct parent_map gpu_cc_parent_map_1[] = { 118 { P_BI_TCXO, 0 }, 119 { P_GPU_CC_PLL0_OUT_MAIN, 1 }, 120 { P_GPU_CC_PLL1_OUT_MAIN, 3 }, 121 { P_GPLL0_OUT_MAIN, 5 }, 122 { P_GPLL0_OUT_MAIN_DIV, 6 }, 123 }; 124 125 static const struct clk_parent_data gpu_cc_parent_data_1[] = { 126 { .index = DT_BI_TCXO }, 127 { .hw = &gpu_cc_pll0.clkr.hw }, 128 { .hw = &gpu_cc_pll1.clkr.hw }, 129 { .index = DT_GPLL0_OUT_MAIN }, 130 { .index = DT_GPLL0_OUT_MAIN_DIV }, 131 }; 132 133 static const struct parent_map gpu_cc_parent_map_2[] = { 134 { P_BI_TCXO, 0 }, 135 { P_GPU_CC_PLL1_OUT_MAIN, 3 }, 136 { P_GPLL0_OUT_MAIN, 5 }, 137 { P_GPLL0_OUT_MAIN_DIV, 6 }, 138 }; 139 140 static const struct clk_parent_data gpu_cc_parent_data_2[] = { 141 { .index = DT_BI_TCXO }, 142 { .hw = &gpu_cc_pll1.clkr.hw }, 143 { .index = DT_GPLL0_OUT_MAIN }, 144 { .index = DT_GPLL0_OUT_MAIN_DIV }, 145 }; 146 147 static const struct freq_tbl ftbl_gpu_cc_ff_clk_src[] = { 148 F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0), 149 { } 150 }; 151 152 static struct clk_rcg2 gpu_cc_ff_clk_src = { 153 .cmd_rcgr = 0x9474, 154 .mnd_width = 0, 155 .hid_width = 5, 156 .parent_map = gpu_cc_parent_map_0, 157 .freq_tbl = ftbl_gpu_cc_ff_clk_src, 158 .clkr.hw.init = &(const struct clk_init_data) { 159 .name = "gpu_cc_ff_clk_src", 160 .parent_data = gpu_cc_parent_data_0, 161 .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0), 162 .ops = &clk_rcg2_shared_ops, 163 }, 164 }; 165 166 static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = { 167 F(19200000, P_BI_TCXO, 1, 0, 0), 168 F(220000000, P_GPU_CC_PLL1_OUT_MAIN, 2, 0, 0), 169 F(550000000, P_GPU_CC_PLL1_OUT_MAIN, 2, 0, 0), 170 { } 171 }; 172 173 static struct clk_rcg2 gpu_cc_gmu_clk_src = { 174 .cmd_rcgr = 0x9318, 175 .mnd_width = 0, 176 .hid_width = 5, 177 .parent_map = gpu_cc_parent_map_1, 178 .freq_tbl = ftbl_gpu_cc_gmu_clk_src, 179 .clkr.hw.init = &(const struct clk_init_data) { 180 .name = "gpu_cc_gmu_clk_src", 181 .parent_data = gpu_cc_parent_data_1, 182 .num_parents = ARRAY_SIZE(gpu_cc_parent_data_1), 183 .flags = CLK_SET_RATE_PARENT, 184 .ops = &clk_rcg2_shared_ops, 185 }, 186 }; 187 188 static struct clk_rcg2 gpu_cc_hub_clk_src = { 189 .cmd_rcgr = 0x93ec, 190 .mnd_width = 0, 191 .hid_width = 5, 192 .parent_map = gpu_cc_parent_map_2, 193 .freq_tbl = ftbl_gpu_cc_ff_clk_src, 194 .clkr.hw.init = &(const struct clk_init_data) { 195 .name = "gpu_cc_hub_clk_src", 196 .parent_data = gpu_cc_parent_data_2, 197 .num_parents = ARRAY_SIZE(gpu_cc_parent_data_2), 198 .ops = &clk_rcg2_shared_ops, 199 }, 200 }; 201 202 static struct clk_branch gpu_cc_ahb_clk = { 203 .halt_reg = 0x911c, 204 .halt_check = BRANCH_HALT_DELAY, 205 .clkr = { 206 .enable_reg = 0x911c, 207 .enable_mask = BIT(0), 208 .hw.init = &(const struct clk_init_data) { 209 .name = "gpu_cc_ahb_clk", 210 .parent_hws = (const struct clk_hw*[]) { 211 &gpu_cc_hub_clk_src.clkr.hw, 212 }, 213 .num_parents = 1, 214 .flags = CLK_SET_RATE_PARENT, 215 .ops = &clk_branch2_ops, 216 }, 217 }, 218 }; 219 220 static struct clk_branch gpu_cc_crc_ahb_clk = { 221 .halt_reg = 0x9120, 222 .halt_check = BRANCH_HALT_VOTED, 223 .clkr = { 224 .enable_reg = 0x9120, 225 .enable_mask = BIT(0), 226 .hw.init = &(const struct clk_init_data) { 227 .name = "gpu_cc_crc_ahb_clk", 228 .parent_hws = (const struct clk_hw*[]) { 229 &gpu_cc_hub_clk_src.clkr.hw, 230 }, 231 .num_parents = 1, 232 .flags = CLK_SET_RATE_PARENT, 233 .ops = &clk_branch2_ops, 234 }, 235 }, 236 }; 237 238 static struct clk_branch gpu_cc_cx_ff_clk = { 239 .halt_reg = 0x914c, 240 .halt_check = BRANCH_HALT, 241 .clkr = { 242 .enable_reg = 0x914c, 243 .enable_mask = BIT(0), 244 .hw.init = &(const struct clk_init_data) { 245 .name = "gpu_cc_cx_ff_clk", 246 .parent_hws = (const struct clk_hw*[]) { 247 &gpu_cc_ff_clk_src.clkr.hw, 248 }, 249 .num_parents = 1, 250 .flags = CLK_SET_RATE_PARENT, 251 .ops = &clk_branch2_ops, 252 }, 253 }, 254 }; 255 256 static struct clk_branch gpu_cc_cx_gmu_clk = { 257 .halt_reg = 0x913c, 258 .halt_check = BRANCH_HALT_VOTED, 259 .clkr = { 260 .enable_reg = 0x913c, 261 .enable_mask = BIT(0), 262 .hw.init = &(const struct clk_init_data) { 263 .name = "gpu_cc_cx_gmu_clk", 264 .parent_hws = (const struct clk_hw*[]) { 265 &gpu_cc_gmu_clk_src.clkr.hw, 266 }, 267 .num_parents = 1, 268 .flags = CLK_SET_RATE_PARENT, 269 .ops = &clk_branch2_aon_ops, 270 }, 271 }, 272 }; 273 274 static struct clk_branch gpu_cc_cxo_aon_clk = { 275 .halt_reg = 0x9004, 276 .halt_check = BRANCH_HALT_VOTED, 277 .clkr = { 278 .enable_reg = 0x9004, 279 .enable_mask = BIT(0), 280 .hw.init = &(const struct clk_init_data) { 281 .name = "gpu_cc_cxo_aon_clk", 282 .ops = &clk_branch2_ops, 283 }, 284 }, 285 }; 286 287 static struct clk_branch gpu_cc_cxo_clk = { 288 .halt_reg = 0x9144, 289 .halt_check = BRANCH_HALT, 290 .clkr = { 291 .enable_reg = 0x9144, 292 .enable_mask = BIT(0), 293 .hw.init = &(const struct clk_init_data) { 294 .name = "gpu_cc_cxo_clk", 295 .ops = &clk_branch2_ops, 296 }, 297 }, 298 }; 299 300 static struct clk_branch gpu_cc_gx_gmu_clk = { 301 .halt_reg = 0x90bc, 302 .halt_check = BRANCH_HALT, 303 .clkr = { 304 .enable_reg = 0x90bc, 305 .enable_mask = BIT(0), 306 .hw.init = &(const struct clk_init_data) { 307 .name = "gpu_cc_gx_gmu_clk", 308 .parent_hws = (const struct clk_hw*[]) { 309 &gpu_cc_gmu_clk_src.clkr.hw, 310 }, 311 .num_parents = 1, 312 .flags = CLK_SET_RATE_PARENT, 313 .ops = &clk_branch2_ops, 314 }, 315 }, 316 }; 317 318 static struct clk_branch gpu_cc_hub_aon_clk = { 319 .halt_reg = 0x93e8, 320 .halt_check = BRANCH_HALT, 321 .clkr = { 322 .enable_reg = 0x93e8, 323 .enable_mask = BIT(0), 324 .hw.init = &(const struct clk_init_data) { 325 .name = "gpu_cc_hub_aon_clk", 326 .parent_hws = (const struct clk_hw*[]) { 327 &gpu_cc_hub_clk_src.clkr.hw, 328 }, 329 .num_parents = 1, 330 .flags = CLK_SET_RATE_PARENT, 331 .ops = &clk_branch2_aon_ops, 332 }, 333 }, 334 }; 335 336 static struct clk_branch gpu_cc_hub_cx_int_clk = { 337 .halt_reg = 0x9148, 338 .halt_check = BRANCH_HALT_VOTED, 339 .clkr = { 340 .enable_reg = 0x9148, 341 .enable_mask = BIT(0), 342 .hw.init = &(const struct clk_init_data) { 343 .name = "gpu_cc_hub_cx_int_clk", 344 .parent_hws = (const struct clk_hw*[]) { 345 &gpu_cc_hub_clk_src.clkr.hw, 346 }, 347 .num_parents = 1, 348 .flags = CLK_SET_RATE_PARENT, 349 .ops = &clk_branch2_aon_ops, 350 }, 351 }, 352 }; 353 354 static struct clk_branch gpu_cc_memnoc_gfx_clk = { 355 .halt_reg = 0x9150, 356 .halt_check = BRANCH_HALT_VOTED, 357 .clkr = { 358 .enable_reg = 0x9150, 359 .enable_mask = BIT(0), 360 .hw.init = &(const struct clk_init_data) { 361 .name = "gpu_cc_memnoc_gfx_clk", 362 .ops = &clk_branch2_ops, 363 }, 364 }, 365 }; 366 367 static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk = { 368 .halt_reg = 0x7000, 369 .halt_check = BRANCH_HALT_VOTED, 370 .clkr = { 371 .enable_reg = 0x7000, 372 .enable_mask = BIT(0), 373 .hw.init = &(const struct clk_init_data) { 374 .name = "gpu_cc_hlos1_vote_gpu_smmu_clk", 375 .ops = &clk_branch2_ops, 376 }, 377 }, 378 }; 379 380 static struct clk_branch gpu_cc_sleep_clk = { 381 .halt_reg = 0x9134, 382 .halt_check = BRANCH_HALT_VOTED, 383 .clkr = { 384 .enable_reg = 0x9134, 385 .enable_mask = BIT(0), 386 .hw.init = &(const struct clk_init_data) { 387 .name = "gpu_cc_sleep_clk", 388 .ops = &clk_branch2_ops, 389 }, 390 }, 391 }; 392 393 static struct gdsc gpu_cx_gdsc = { 394 .gdscr = 0x9108, 395 .gds_hw_ctrl = 0x953c, 396 .clk_dis_wait_val = 8, 397 .pd = { 398 .name = "gpu_cx_gdsc", 399 }, 400 .pwrsts = PWRSTS_OFF_ON, 401 .flags = VOTABLE | RETAIN_FF_ENABLE, 402 }; 403 404 static struct gdsc gpu_gx_gdsc = { 405 .gdscr = 0x905c, 406 .clamp_io_ctrl = 0x9504, 407 .resets = (unsigned int []){ GPUCC_GPU_CC_GX_BCR, 408 GPUCC_GPU_CC_ACD_BCR, 409 GPUCC_GPU_CC_GX_ACD_IROOT_BCR }, 410 .reset_count = 3, 411 .pd = { 412 .name = "gpu_gx_gdsc", 413 .power_on = gdsc_gx_do_nothing_enable, 414 }, 415 .pwrsts = PWRSTS_OFF_ON, 416 .flags = CLAMP_IO | AON_RESET | SW_RESET, 417 }; 418 419 static struct clk_regmap *gpu_cc_sar2130p_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_FF_CLK] = &gpu_cc_cx_ff_clk.clkr, 423 [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr, 424 [GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr, 425 [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr, 426 [GPU_CC_FF_CLK_SRC] = &gpu_cc_ff_clk_src.clkr, 427 [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr, 428 [GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr, 429 [GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK] = &gpu_cc_hlos1_vote_gpu_smmu_clk.clkr, 430 [GPU_CC_HUB_AON_CLK] = &gpu_cc_hub_aon_clk.clkr, 431 [GPU_CC_HUB_CLK_SRC] = &gpu_cc_hub_clk_src.clkr, 432 [GPU_CC_HUB_CX_INT_CLK] = &gpu_cc_hub_cx_int_clk.clkr, 433 [GPU_CC_MEMNOC_GFX_CLK] = &gpu_cc_memnoc_gfx_clk.clkr, 434 [GPU_CC_PLL0] = &gpu_cc_pll0.clkr, 435 [GPU_CC_PLL1] = &gpu_cc_pll1.clkr, 436 [GPU_CC_SLEEP_CLK] = &gpu_cc_sleep_clk.clkr, 437 }; 438 439 static const struct qcom_reset_map gpu_cc_sar2130p_resets[] = { 440 [GPUCC_GPU_CC_ACD_BCR] = { 0x9358 }, 441 [GPUCC_GPU_CC_GX_ACD_IROOT_BCR] = { 0x958c }, 442 [GPUCC_GPU_CC_GX_BCR] = { 0x9058 }, 443 }; 444 445 static struct gdsc *gpu_cc_sar2130p_gdscs[] = { 446 [GPU_CX_GDSC] = &gpu_cx_gdsc, 447 [GPU_GX_GDSC] = &gpu_gx_gdsc, 448 }; 449 450 static const struct regmap_config gpu_cc_sar2130p_regmap_config = { 451 .reg_bits = 32, 452 .reg_stride = 4, 453 .val_bits = 32, 454 .max_register = 0xa000, 455 .fast_io = true, 456 }; 457 458 static const struct qcom_cc_desc gpu_cc_sar2130p_desc = { 459 .config = &gpu_cc_sar2130p_regmap_config, 460 .clks = gpu_cc_sar2130p_clocks, 461 .num_clks = ARRAY_SIZE(gpu_cc_sar2130p_clocks), 462 .resets = gpu_cc_sar2130p_resets, 463 .num_resets = ARRAY_SIZE(gpu_cc_sar2130p_resets), 464 .gdscs = gpu_cc_sar2130p_gdscs, 465 .num_gdscs = ARRAY_SIZE(gpu_cc_sar2130p_gdscs), 466 }; 467 468 static const struct of_device_id gpu_cc_sar2130p_match_table[] = { 469 { .compatible = "qcom,sar2130p-gpucc" }, 470 { } 471 }; 472 MODULE_DEVICE_TABLE(of, gpu_cc_sar2130p_match_table); 473 474 static int gpu_cc_sar2130p_probe(struct platform_device *pdev) 475 { 476 struct device *dev = &pdev->dev; 477 struct regmap *regmap; 478 479 regmap = qcom_cc_map(pdev, &gpu_cc_sar2130p_desc); 480 if (IS_ERR(regmap)) 481 return dev_err_probe(dev, PTR_ERR(regmap), "Couldn't map GPU_CC\n"); 482 483 clk_lucid_ole_pll_configure(&gpu_cc_pll0, regmap, &gpu_cc_pll0_config); 484 clk_lucid_ole_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config); 485 486 /* Keep some clocks always-on */ 487 qcom_branch_set_clk_en(regmap, 0x900c); /* GPU_CC_DEMET_CLK */ 488 489 return qcom_cc_really_probe(dev, &gpu_cc_sar2130p_desc, regmap); 490 } 491 492 static struct platform_driver gpu_cc_sar2130p_driver = { 493 .probe = gpu_cc_sar2130p_probe, 494 .driver = { 495 .name = "gpu_cc-sar2130p", 496 .of_match_table = gpu_cc_sar2130p_match_table, 497 }, 498 }; 499 module_platform_driver(gpu_cc_sar2130p_driver); 500 501 MODULE_DESCRIPTION("QTI GPU_CC SAR2130P Driver"); 502 MODULE_LICENSE("GPL"); 503