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