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