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