1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2021, 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/pm_runtime.h> 11 #include <linux/regmap.h> 12 13 #include <dt-bindings/clock/qcom,sm6375-gpucc.h> 14 15 #include "clk-alpha-pll.h" 16 #include "clk-branch.h" 17 #include "clk-rcg.h" 18 #include "clk-regmap.h" 19 #include "clk-regmap-divider.h" 20 #include "clk-regmap-mux.h" 21 #include "clk-regmap-phy-mux.h" 22 #include "gdsc.h" 23 #include "reset.h" 24 25 enum { 26 DT_BI_TCXO, 27 DT_GCC_GPU_GPLL0_CLK_SRC, 28 DT_GCC_GPU_GPLL0_DIV_CLK_SRC, 29 DT_GCC_GPU_SNOC_DVM_GFX_CLK, 30 }; 31 32 enum { 33 P_BI_TCXO, 34 P_GCC_GPU_GPLL0_CLK_SRC, 35 P_GCC_GPU_GPLL0_DIV_CLK_SRC, 36 P_GPU_CC_PLL0_OUT_EVEN, 37 P_GPU_CC_PLL0_OUT_MAIN, 38 P_GPU_CC_PLL0_OUT_ODD, 39 P_GPU_CC_PLL1_OUT_EVEN, 40 P_GPU_CC_PLL1_OUT_MAIN, 41 P_GPU_CC_PLL1_OUT_ODD, 42 }; 43 44 static struct pll_vco lucid_vco[] = { 45 { 249600000, 2000000000, 0 }, 46 }; 47 48 /* 532MHz Configuration */ 49 static const struct alpha_pll_config gpucc_pll0_config = { 50 .l = 0x1b, 51 .alpha = 0xb555, 52 .config_ctl_val = 0x20485699, 53 .config_ctl_hi_val = 0x00002261, 54 .config_ctl_hi1_val = 0x329a299c, 55 .user_ctl_val = 0x00000001, 56 .user_ctl_hi_val = 0x00000805, 57 .user_ctl_hi1_val = 0x00000000, 58 }; 59 60 static struct clk_alpha_pll gpucc_pll0 = { 61 .offset = 0x0, 62 .vco_table = lucid_vco, 63 .num_vco = ARRAY_SIZE(lucid_vco), 64 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], 65 .clkr = { 66 .hw.init = &(struct clk_init_data){ 67 .name = "gpucc_pll0", 68 .parent_data = &(const struct clk_parent_data){ 69 .index = P_BI_TCXO, 70 }, 71 .num_parents = 1, 72 .ops = &clk_alpha_pll_lucid_ops, 73 }, 74 }, 75 }; 76 77 /* 514MHz Configuration */ 78 static const struct alpha_pll_config gpucc_pll1_config = { 79 .l = 0x1a, 80 .alpha = 0xc555, 81 .config_ctl_val = 0x20485699, 82 .config_ctl_hi_val = 0x00002261, 83 .config_ctl_hi1_val = 0x329a299c, 84 .user_ctl_val = 0x00000001, 85 .user_ctl_hi_val = 0x00000805, 86 .user_ctl_hi1_val = 0x00000000, 87 }; 88 89 static struct clk_alpha_pll gpucc_pll1 = { 90 .offset = 0x100, 91 .vco_table = lucid_vco, 92 .num_vco = ARRAY_SIZE(lucid_vco), 93 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], 94 .clkr = { 95 .hw.init = &(struct clk_init_data){ 96 .name = "gpucc_pll1", 97 .parent_data = &(const struct clk_parent_data){ 98 .index = P_BI_TCXO, 99 }, 100 .num_parents = 1, 101 .ops = &clk_alpha_pll_lucid_ops, 102 }, 103 }, 104 }; 105 106 static const struct parent_map gpucc_parent_map_0[] = { 107 { P_BI_TCXO, 0 }, 108 { P_GPU_CC_PLL0_OUT_MAIN, 1 }, 109 { P_GPU_CC_PLL1_OUT_MAIN, 3 }, 110 { P_GCC_GPU_GPLL0_CLK_SRC, 5 }, 111 { P_GCC_GPU_GPLL0_DIV_CLK_SRC, 6 }, 112 }; 113 114 static const struct clk_parent_data gpucc_parent_data_0[] = { 115 { .index = P_BI_TCXO }, 116 { .hw = &gpucc_pll0.clkr.hw }, 117 { .hw = &gpucc_pll1.clkr.hw }, 118 { .index = DT_GCC_GPU_GPLL0_CLK_SRC }, 119 { .index = DT_GCC_GPU_GPLL0_DIV_CLK_SRC }, 120 }; 121 122 static const struct parent_map gpucc_parent_map_1[] = { 123 { P_BI_TCXO, 0 }, 124 { P_GPU_CC_PLL0_OUT_EVEN, 1 }, 125 { P_GPU_CC_PLL0_OUT_ODD, 2 }, 126 { P_GPU_CC_PLL1_OUT_EVEN, 3 }, 127 { P_GPU_CC_PLL1_OUT_ODD, 4 }, 128 { P_GCC_GPU_GPLL0_CLK_SRC, 5 }, 129 }; 130 131 static const struct clk_parent_data gpucc_parent_data_1[] = { 132 { .index = P_BI_TCXO }, 133 { .hw = &gpucc_pll0.clkr.hw }, 134 { .hw = &gpucc_pll0.clkr.hw }, 135 { .hw = &gpucc_pll1.clkr.hw }, 136 { .hw = &gpucc_pll1.clkr.hw }, 137 { .index = DT_GCC_GPU_GPLL0_CLK_SRC }, 138 }; 139 140 static const struct freq_tbl ftbl_gpucc_gmu_clk_src[] = { 141 F(200000000, P_GCC_GPU_GPLL0_DIV_CLK_SRC, 1.5, 0, 0), 142 { } 143 }; 144 145 static struct clk_rcg2 gpucc_gmu_clk_src = { 146 .cmd_rcgr = 0x1120, 147 .mnd_width = 0, 148 .hid_width = 5, 149 .parent_map = gpucc_parent_map_0, 150 .freq_tbl = ftbl_gpucc_gmu_clk_src, 151 .clkr.hw.init = &(struct clk_init_data){ 152 .name = "gpucc_gmu_clk_src", 153 .parent_data = gpucc_parent_data_0, 154 .num_parents = ARRAY_SIZE(gpucc_parent_data_0), 155 .ops = &clk_rcg2_shared_ops, 156 }, 157 }; 158 159 static const struct freq_tbl ftbl_gpucc_gx_gfx3d_clk_src[] = { 160 F(266000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0), 161 F(390000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0), 162 F(490000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0), 163 F(650000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0), 164 F(770000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0), 165 F(840000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0), 166 F(900000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0), 167 { } 168 }; 169 170 static struct clk_rcg2 gpucc_gx_gfx3d_clk_src = { 171 .cmd_rcgr = 0x101c, 172 .mnd_width = 0, 173 .hid_width = 5, 174 .parent_map = gpucc_parent_map_1, 175 .freq_tbl = ftbl_gpucc_gx_gfx3d_clk_src, 176 .clkr.hw.init = &(struct clk_init_data){ 177 .name = "gpucc_gx_gfx3d_clk_src", 178 .parent_data = gpucc_parent_data_1, 179 .num_parents = ARRAY_SIZE(gpucc_parent_data_1), 180 .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, 181 .ops = &clk_rcg2_ops, 182 }, 183 }; 184 185 static struct clk_branch gpucc_ahb_clk = { 186 .halt_reg = 0x1078, 187 .halt_check = BRANCH_HALT_DELAY, 188 .clkr = { 189 .enable_reg = 0x1078, 190 .enable_mask = BIT(0), 191 .hw.init = &(struct clk_init_data){ 192 .name = "gpucc_ahb_clk", 193 .flags = CLK_IS_CRITICAL, 194 .ops = &clk_branch2_ops, 195 }, 196 }, 197 }; 198 199 static struct clk_branch gpucc_cx_gfx3d_clk = { 200 .halt_reg = 0x10a4, 201 .halt_check = BRANCH_HALT_DELAY, 202 .clkr = { 203 .enable_reg = 0x10a4, 204 .enable_mask = BIT(0), 205 .hw.init = &(struct clk_init_data){ 206 .name = "gpucc_cx_gfx3d_clk", 207 .parent_hws = (const struct clk_hw*[]) { 208 &gpucc_gx_gfx3d_clk_src.clkr.hw, 209 }, 210 .num_parents = 1, 211 .flags = CLK_SET_RATE_PARENT, 212 .ops = &clk_branch2_ops, 213 }, 214 }, 215 }; 216 217 static struct clk_branch gpucc_cx_gfx3d_slv_clk = { 218 .halt_reg = 0x10a8, 219 .halt_check = BRANCH_HALT_DELAY, 220 .clkr = { 221 .enable_reg = 0x10a8, 222 .enable_mask = BIT(0), 223 .hw.init = &(struct clk_init_data){ 224 .name = "gpucc_cx_gfx3d_slv_clk", 225 .parent_hws = (const struct clk_hw*[]) { 226 &gpucc_gx_gfx3d_clk_src.clkr.hw, 227 }, 228 .num_parents = 1, 229 .flags = CLK_SET_RATE_PARENT, 230 .ops = &clk_branch2_ops, 231 }, 232 }, 233 }; 234 235 static struct clk_branch gpucc_cx_gmu_clk = { 236 .halt_reg = 0x1098, 237 .halt_check = BRANCH_HALT, 238 .clkr = { 239 .enable_reg = 0x1098, 240 .enable_mask = BIT(0), 241 .hw.init = &(struct clk_init_data){ 242 .name = "gpucc_cx_gmu_clk", 243 .parent_hws = (const struct clk_hw*[]) { 244 &gpucc_gmu_clk_src.clkr.hw, 245 }, 246 .num_parents = 1, 247 .flags = CLK_SET_RATE_PARENT, 248 .ops = &clk_branch2_ops, 249 }, 250 }, 251 }; 252 253 static struct clk_branch gpucc_cx_snoc_dvm_clk = { 254 .halt_reg = 0x108c, 255 .halt_check = BRANCH_HALT_DELAY, 256 .clkr = { 257 .enable_reg = 0x108c, 258 .enable_mask = BIT(0), 259 .hw.init = &(struct clk_init_data){ 260 .name = "gpucc_cx_snoc_dvm_clk", 261 .parent_data = &(const struct clk_parent_data){ 262 .index = DT_GCC_GPU_SNOC_DVM_GFX_CLK, 263 }, 264 .num_parents = 1, 265 .ops = &clk_branch2_ops, 266 }, 267 }, 268 }; 269 270 static struct clk_branch gpucc_cxo_aon_clk = { 271 .halt_reg = 0x1004, 272 .halt_check = BRANCH_HALT_DELAY, 273 .clkr = { 274 .enable_reg = 0x1004, 275 .enable_mask = BIT(0), 276 .hw.init = &(struct clk_init_data){ 277 .name = "gpucc_cxo_aon_clk", 278 .ops = &clk_branch2_ops, 279 }, 280 }, 281 }; 282 283 static struct clk_branch gpucc_cxo_clk = { 284 .halt_reg = 0x109c, 285 .halt_check = BRANCH_HALT, 286 .clkr = { 287 .enable_reg = 0x109c, 288 .enable_mask = BIT(0), 289 .hw.init = &(struct clk_init_data){ 290 .name = "gpucc_cxo_clk", 291 .ops = &clk_branch2_ops, 292 }, 293 }, 294 }; 295 296 static struct clk_branch gpucc_gx_cxo_clk = { 297 .halt_reg = 0x1060, 298 .halt_check = BRANCH_HALT_DELAY, 299 .clkr = { 300 .enable_reg = 0x1060, 301 .enable_mask = BIT(0), 302 .hw.init = &(struct clk_init_data){ 303 .name = "gpucc_gx_cxo_clk", 304 .flags = CLK_IS_CRITICAL, 305 .ops = &clk_branch2_ops, 306 }, 307 }, 308 }; 309 310 static struct clk_branch gpucc_gx_gfx3d_clk = { 311 .halt_reg = 0x1054, 312 .halt_check = BRANCH_HALT_DELAY, 313 .clkr = { 314 .enable_reg = 0x1054, 315 .enable_mask = BIT(0), 316 .hw.init = &(struct clk_init_data){ 317 .name = "gpucc_gx_gfx3d_clk", 318 .parent_hws = (const struct clk_hw*[]) { 319 &gpucc_gx_gfx3d_clk_src.clkr.hw, 320 }, 321 .num_parents = 1, 322 .flags = CLK_SET_RATE_PARENT, 323 .ops = &clk_branch2_ops, 324 }, 325 }, 326 }; 327 328 static struct clk_branch gpucc_gx_gmu_clk = { 329 .halt_reg = 0x1064, 330 .halt_check = BRANCH_HALT, 331 .clkr = { 332 .enable_reg = 0x1064, 333 .enable_mask = BIT(0), 334 .hw.init = &(struct clk_init_data){ 335 .name = "gpucc_gx_gmu_clk", 336 .parent_hws = (const struct clk_hw*[]) { 337 &gpucc_gmu_clk_src.clkr.hw, 338 }, 339 .num_parents = 1, 340 .flags = CLK_SET_RATE_PARENT, 341 .ops = &clk_branch2_ops, 342 }, 343 }, 344 }; 345 346 static struct clk_branch gpucc_sleep_clk = { 347 .halt_reg = 0x1090, 348 .halt_check = BRANCH_HALT_VOTED, 349 .clkr = { 350 .enable_reg = 0x1090, 351 .enable_mask = BIT(0), 352 .hw.init = &(struct clk_init_data){ 353 .name = "gpucc_sleep_clk", 354 .ops = &clk_branch2_ops, 355 }, 356 }, 357 }; 358 359 static struct gdsc gpu_cx_gdsc = { 360 .gdscr = 0x106c, 361 .gds_hw_ctrl = 0x1540, 362 .clk_dis_wait_val = 8, 363 .pd = { 364 .name = "gpu_cx_gdsc", 365 }, 366 .pwrsts = PWRSTS_OFF_ON, 367 .flags = VOTABLE, 368 }; 369 370 static struct gdsc gpu_gx_gdsc = { 371 .gdscr = 0x100c, 372 .clamp_io_ctrl = 0x1508, 373 .resets = (unsigned int []){ GPU_GX_BCR, GPU_ACD_BCR, GPU_GX_ACD_MISC_BCR }, 374 .reset_count = 3, 375 .pd = { 376 .name = "gpu_gx_gdsc", 377 }, 378 .pwrsts = PWRSTS_OFF_ON, 379 .flags = CLAMP_IO | SW_RESET | AON_RESET, 380 }; 381 382 static struct clk_regmap *gpucc_sm6375_clocks[] = { 383 [GPU_CC_AHB_CLK] = &gpucc_ahb_clk.clkr, 384 [GPU_CC_CX_GFX3D_CLK] = &gpucc_cx_gfx3d_clk.clkr, 385 [GPU_CC_CX_GFX3D_SLV_CLK] = &gpucc_cx_gfx3d_slv_clk.clkr, 386 [GPU_CC_CX_GMU_CLK] = &gpucc_cx_gmu_clk.clkr, 387 [GPU_CC_CX_SNOC_DVM_CLK] = &gpucc_cx_snoc_dvm_clk.clkr, 388 [GPU_CC_CXO_AON_CLK] = &gpucc_cxo_aon_clk.clkr, 389 [GPU_CC_CXO_CLK] = &gpucc_cxo_clk.clkr, 390 [GPU_CC_GMU_CLK_SRC] = &gpucc_gmu_clk_src.clkr, 391 [GPU_CC_GX_CXO_CLK] = &gpucc_gx_cxo_clk.clkr, 392 [GPU_CC_GX_GFX3D_CLK] = &gpucc_gx_gfx3d_clk.clkr, 393 [GPU_CC_GX_GFX3D_CLK_SRC] = &gpucc_gx_gfx3d_clk_src.clkr, 394 [GPU_CC_GX_GMU_CLK] = &gpucc_gx_gmu_clk.clkr, 395 [GPU_CC_PLL0] = &gpucc_pll0.clkr, 396 [GPU_CC_PLL1] = &gpucc_pll1.clkr, 397 [GPU_CC_SLEEP_CLK] = &gpucc_sleep_clk.clkr, 398 }; 399 400 static const struct qcom_reset_map gpucc_sm6375_resets[] = { 401 [GPU_GX_BCR] = { 0x1008 }, 402 [GPU_ACD_BCR] = { 0x1160 }, 403 [GPU_GX_ACD_MISC_BCR] = { 0x8004 }, 404 }; 405 406 static struct gdsc *gpucc_sm6375_gdscs[] = { 407 [GPU_CX_GDSC] = &gpu_cx_gdsc, 408 [GPU_GX_GDSC] = &gpu_gx_gdsc, 409 }; 410 411 static const struct regmap_config gpucc_sm6375_regmap_config = { 412 .reg_bits = 32, 413 .reg_stride = 4, 414 .val_bits = 32, 415 .max_register = 0x9000, 416 .fast_io = true, 417 }; 418 419 static const struct qcom_cc_desc gpucc_sm6375_desc = { 420 .config = &gpucc_sm6375_regmap_config, 421 .clks = gpucc_sm6375_clocks, 422 .num_clks = ARRAY_SIZE(gpucc_sm6375_clocks), 423 .resets = gpucc_sm6375_resets, 424 .num_resets = ARRAY_SIZE(gpucc_sm6375_resets), 425 .gdscs = gpucc_sm6375_gdscs, 426 .num_gdscs = ARRAY_SIZE(gpucc_sm6375_gdscs), 427 }; 428 429 static const struct of_device_id gpucc_sm6375_match_table[] = { 430 { .compatible = "qcom,sm6375-gpucc" }, 431 { } 432 }; 433 MODULE_DEVICE_TABLE(of, gpucc_sm6375_match_table); 434 435 static int gpucc_sm6375_probe(struct platform_device *pdev) 436 { 437 struct regmap *regmap; 438 int ret; 439 440 ret = devm_pm_runtime_enable(&pdev->dev); 441 if (ret) 442 return ret; 443 444 ret = pm_runtime_resume_and_get(&pdev->dev); 445 if (ret) 446 return ret; 447 448 regmap = qcom_cc_map(pdev, &gpucc_sm6375_desc); 449 if (IS_ERR(regmap)) { 450 pm_runtime_put(&pdev->dev); 451 return PTR_ERR(regmap); 452 } 453 454 clk_lucid_pll_configure(&gpucc_pll0, regmap, &gpucc_pll0_config); 455 clk_lucid_pll_configure(&gpucc_pll1, regmap, &gpucc_pll1_config); 456 457 ret = qcom_cc_really_probe(pdev, &gpucc_sm6375_desc, regmap); 458 pm_runtime_put(&pdev->dev); 459 460 return ret; 461 } 462 463 static struct platform_driver gpucc_sm6375_driver = { 464 .probe = gpucc_sm6375_probe, 465 .driver = { 466 .name = "gpucc-sm6375", 467 .of_match_table = gpucc_sm6375_match_table, 468 }, 469 }; 470 module_platform_driver(gpucc_sm6375_driver); 471 472 MODULE_DESCRIPTION("QTI GPUCC SM6375 Driver"); 473 MODULE_LICENSE("GPL"); 474