1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
4 * Copyright (c) 2022, Linaro Limited
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include <linux/of_device.h>
13 #include <linux/regmap.h>
15 #include <dt-bindings/clock/qcom,gpucc-sm8350.h>
17 #include "clk-alpha-pll.h"
18 #include "clk-branch.h"
21 #include "clk-regmap.h"
23 #include "clk-regmap-mux.h"
24 #include "clk-regmap-divider.h"
32 P_GPU_CC_PLL0_OUT_MAIN,
33 P_GPU_CC_PLL1_OUT_MAIN,
36 static struct pll_vco lucid_5lpe_vco[] = {
37 { 249600000, 1750000000, 0 },
40 static const struct alpha_pll_config gpu_cc_pll0_config = {
43 .config_ctl_val = 0x20485699,
44 .config_ctl_hi_val = 0x00002261,
45 .config_ctl_hi1_val = 0x2a9a699c,
46 .test_ctl_val = 0x00000000,
47 .test_ctl_hi_val = 0x00000000,
48 .test_ctl_hi1_val = 0x01800000,
49 .user_ctl_val = 0x00000000,
50 .user_ctl_hi_val = 0x00000805,
51 .user_ctl_hi1_val = 0x00000000,
54 static const struct clk_parent_data gpu_cc_parent = {
58 static struct clk_alpha_pll gpu_cc_pll0 = {
60 .vco_table = lucid_5lpe_vco,
61 .num_vco = ARRAY_SIZE(lucid_5lpe_vco),
62 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
64 .hw.init = &(const struct clk_init_data){
65 .name = "gpu_cc_pll0",
66 .parent_data = &gpu_cc_parent,
68 .ops = &clk_alpha_pll_lucid_5lpe_ops,
73 static const struct alpha_pll_config gpu_cc_pll1_config = {
76 .config_ctl_val = 0x20485699,
77 .config_ctl_hi_val = 0x00002261,
78 .config_ctl_hi1_val = 0x2a9a699c,
79 .test_ctl_val = 0x00000000,
80 .test_ctl_hi_val = 0x00000000,
81 .test_ctl_hi1_val = 0x01800000,
82 .user_ctl_val = 0x00000000,
83 .user_ctl_hi_val = 0x00000805,
84 .user_ctl_hi1_val = 0x00000000,
87 static struct clk_alpha_pll gpu_cc_pll1 = {
89 .vco_table = lucid_5lpe_vco,
90 .num_vco = ARRAY_SIZE(lucid_5lpe_vco),
91 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
93 .hw.init = &(struct clk_init_data){
94 .name = "gpu_cc_pll1",
95 .parent_data = &gpu_cc_parent,
97 .ops = &clk_alpha_pll_lucid_5lpe_ops,
102 static const struct parent_map gpu_cc_parent_map_0[] = {
104 { P_GPU_CC_PLL0_OUT_MAIN, 1 },
105 { P_GPU_CC_PLL1_OUT_MAIN, 3 },
106 { P_GPLL0_OUT_MAIN, 5 },
107 { P_GPLL0_OUT_MAIN_DIV, 6 },
110 static const struct clk_parent_data gpu_cc_parent_data_0[] = {
111 { .fw_name = "bi_tcxo" },
112 { .hw = &gpu_cc_pll0.clkr.hw },
113 { .hw = &gpu_cc_pll1.clkr.hw },
114 { .fw_name = "gcc_gpu_gpll0_clk_src" },
115 { .fw_name = "gcc_gpu_gpll0_div_clk_src" },
118 static const struct parent_map gpu_cc_parent_map_1[] = {
120 { P_GPU_CC_PLL1_OUT_MAIN, 3 },
121 { P_GPLL0_OUT_MAIN, 5 },
122 { P_GPLL0_OUT_MAIN_DIV, 6 },
125 static const struct clk_parent_data gpu_cc_parent_data_1[] = {
126 { .fw_name = "bi_tcxo" },
127 { .hw = &gpu_cc_pll1.clkr.hw },
128 { .fw_name = "gcc_gpu_gpll0_clk_src" },
129 { .fw_name = "gcc_gpu_gpll0_div_clk_src" },
132 static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = {
133 F(19200000, P_BI_TCXO, 1, 0, 0),
134 F(200000000, P_GPLL0_OUT_MAIN_DIV, 1.5, 0, 0),
135 F(500000000, P_GPU_CC_PLL1_OUT_MAIN, 1, 0, 0),
139 static struct clk_rcg2 gpu_cc_gmu_clk_src = {
143 .parent_map = gpu_cc_parent_map_0,
144 .freq_tbl = ftbl_gpu_cc_gmu_clk_src,
145 .clkr.hw.init = &(struct clk_init_data){
146 .name = "gpu_cc_gmu_clk_src",
147 .parent_data = gpu_cc_parent_data_0,
148 .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0),
149 .flags = CLK_SET_RATE_PARENT,
150 .ops = &clk_rcg2_ops,
154 static const struct freq_tbl ftbl_gpu_cc_hub_clk_src[] = {
155 F(150000000, P_GPLL0_OUT_MAIN_DIV, 2, 0, 0),
156 F(240000000, P_GPLL0_OUT_MAIN, 2.5, 0, 0),
157 F(300000000, P_GPLL0_OUT_MAIN, 2, 0, 0),
161 static struct clk_rcg2 gpu_cc_hub_clk_src = {
165 .parent_map = gpu_cc_parent_map_1,
166 .freq_tbl = ftbl_gpu_cc_hub_clk_src,
167 .clkr.hw.init = &(struct clk_init_data){
168 .name = "gpu_cc_hub_clk_src",
169 .parent_data = gpu_cc_parent_data_1,
170 .num_parents = ARRAY_SIZE(gpu_cc_parent_data_1),
171 .flags = CLK_SET_RATE_PARENT,
172 .ops = &clk_rcg2_ops,
176 static struct clk_regmap_div gpu_cc_hub_ahb_div_clk_src = {
180 .clkr.hw.init = &(struct clk_init_data) {
181 .name = "gpu_cc_hub_ahb_div_clk_src",
182 .parent_hws = (const struct clk_hw*[]){
183 &gpu_cc_hub_clk_src.clkr.hw,
186 .flags = CLK_SET_RATE_PARENT,
187 .ops = &clk_regmap_div_ro_ops,
191 static struct clk_regmap_div gpu_cc_hub_cx_int_div_clk_src = {
195 .clkr.hw.init = &(struct clk_init_data) {
196 .name = "gpu_cc_hub_cx_int_div_clk_src",
197 .parent_hws = (const struct clk_hw*[]){
198 &gpu_cc_hub_clk_src.clkr.hw,
201 .flags = CLK_SET_RATE_PARENT,
202 .ops = &clk_regmap_div_ro_ops,
206 static struct clk_branch gpu_cc_ahb_clk = {
208 .halt_check = BRANCH_HALT_DELAY,
210 .enable_reg = 0x1078,
211 .enable_mask = BIT(0),
212 .hw.init = &(struct clk_init_data){
213 .name = "gpu_cc_ahb_clk",
214 .parent_hws = (const struct clk_hw*[]){
215 &gpu_cc_hub_ahb_div_clk_src.clkr.hw,
218 .flags = CLK_SET_RATE_PARENT,
219 .ops = &clk_branch2_ops,
224 static struct clk_branch gpu_cc_cb_clk = {
226 .halt_check = BRANCH_HALT,
228 .enable_reg = 0x1170,
229 .enable_mask = BIT(0),
230 .hw.init = &(struct clk_init_data){
231 .name = "gpu_cc_cb_clk",
232 .ops = &clk_branch2_ops,
237 static struct clk_branch gpu_cc_crc_ahb_clk = {
239 .halt_check = BRANCH_HALT_VOTED,
241 .enable_reg = 0x107c,
242 .enable_mask = BIT(0),
243 .hw.init = &(struct clk_init_data){
244 .name = "gpu_cc_crc_ahb_clk",
245 .parent_hws = (const struct clk_hw*[]){
246 &gpu_cc_hub_ahb_div_clk_src.clkr.hw,
249 .flags = CLK_SET_RATE_PARENT,
250 .ops = &clk_branch2_ops,
255 static struct clk_branch gpu_cc_cx_apb_clk = {
257 .halt_check = BRANCH_HALT_VOTED,
259 .enable_reg = 0x1088,
260 .enable_mask = BIT(0),
261 .hw.init = &(struct clk_init_data){
262 .name = "gpu_cc_cx_apb_clk",
263 .ops = &clk_branch2_ops,
268 static struct clk_branch gpu_cc_cx_gmu_clk = {
270 .halt_check = BRANCH_HALT,
272 .enable_reg = 0x1098,
273 .enable_mask = BIT(0),
274 .hw.init = &(struct clk_init_data){
275 .name = "gpu_cc_cx_gmu_clk",
276 .parent_hws = (const struct clk_hw*[]){
277 &gpu_cc_gmu_clk_src.clkr.hw,
280 .flags = CLK_SET_RATE_PARENT,
281 .ops = &clk_branch2_aon_ops,
286 static struct clk_branch gpu_cc_cx_qdss_at_clk = {
288 .halt_check = BRANCH_HALT_VOTED,
290 .enable_reg = 0x1080,
291 .enable_mask = BIT(0),
292 .hw.init = &(struct clk_init_data){
293 .name = "gpu_cc_cx_qdss_at_clk",
294 .ops = &clk_branch2_ops,
299 static struct clk_branch gpu_cc_cx_qdss_trig_clk = {
301 .halt_check = BRANCH_HALT_VOTED,
303 .enable_reg = 0x1094,
304 .enable_mask = BIT(0),
305 .hw.init = &(struct clk_init_data){
306 .name = "gpu_cc_cx_qdss_trig_clk",
307 .ops = &clk_branch2_ops,
312 static struct clk_branch gpu_cc_cx_qdss_tsctr_clk = {
314 .halt_check = BRANCH_HALT_VOTED,
316 .enable_reg = 0x1084,
317 .enable_mask = BIT(0),
318 .hw.init = &(struct clk_init_data){
319 .name = "gpu_cc_cx_qdss_tsctr_clk",
320 .ops = &clk_branch2_ops,
325 static struct clk_branch gpu_cc_cx_snoc_dvm_clk = {
327 .halt_check = BRANCH_HALT_VOTED,
329 .enable_reg = 0x108c,
330 .enable_mask = BIT(0),
331 .hw.init = &(struct clk_init_data){
332 .name = "gpu_cc_cx_snoc_dvm_clk",
333 .ops = &clk_branch2_ops,
338 static struct clk_branch gpu_cc_cxo_aon_clk = {
340 .halt_check = BRANCH_HALT_VOTED,
342 .enable_reg = 0x1004,
343 .enable_mask = BIT(0),
344 .hw.init = &(struct clk_init_data){
345 .name = "gpu_cc_cxo_aon_clk",
346 .ops = &clk_branch2_ops,
351 static struct clk_branch gpu_cc_cxo_clk = {
353 .halt_check = BRANCH_HALT,
355 .enable_reg = 0x109c,
356 .enable_mask = BIT(0),
357 .hw.init = &(struct clk_init_data){
358 .name = "gpu_cc_cxo_clk",
359 .ops = &clk_branch2_ops,
364 static struct clk_branch gpu_cc_freq_measure_clk = {
366 .halt_check = BRANCH_HALT,
368 .enable_reg = 0x120c,
369 .enable_mask = BIT(0),
370 .hw.init = &(struct clk_init_data){
371 .name = "gpu_cc_freq_measure_clk",
372 .ops = &clk_branch2_ops,
377 static struct clk_branch gpu_cc_gx_gmu_clk = {
379 .halt_check = BRANCH_HALT,
381 .enable_reg = 0x1064,
382 .enable_mask = BIT(0),
383 .hw.init = &(struct clk_init_data){
384 .name = "gpu_cc_gx_gmu_clk",
385 .parent_hws = (const struct clk_hw*[]){
386 &gpu_cc_gmu_clk_src.clkr.hw,
389 .flags = CLK_SET_RATE_PARENT,
390 .ops = &clk_branch2_ops,
395 static struct clk_branch gpu_cc_gx_qdss_tsctr_clk = {
397 .halt_check = BRANCH_HALT_VOTED,
399 .enable_reg = 0x105c,
400 .enable_mask = BIT(0),
401 .hw.init = &(struct clk_init_data){
402 .name = "gpu_cc_gx_qdss_tsctr_clk",
403 .ops = &clk_branch2_ops,
408 static struct clk_branch gpu_cc_gx_vsense_clk = {
410 .halt_check = BRANCH_HALT_VOTED,
412 .enable_reg = 0x1058,
413 .enable_mask = BIT(0),
414 .hw.init = &(struct clk_init_data){
415 .name = "gpu_cc_gx_vsense_clk",
416 .ops = &clk_branch2_ops,
421 static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk = {
423 .halt_check = BRANCH_HALT_VOTED,
425 .enable_reg = 0x5000,
426 .enable_mask = BIT(0),
427 .hw.init = &(struct clk_init_data){
428 .name = "gpu_cc_hlos1_vote_gpu_smmu_clk",
429 .ops = &clk_branch2_ops,
434 static struct clk_branch gpu_cc_hub_aon_clk = {
436 .halt_check = BRANCH_HALT,
438 .enable_reg = 0x1178,
439 .enable_mask = BIT(0),
440 .hw.init = &(struct clk_init_data){
441 .name = "gpu_cc_hub_aon_clk",
442 .parent_hws = (const struct clk_hw*[]){
443 &gpu_cc_hub_clk_src.clkr.hw,
446 .flags = CLK_SET_RATE_PARENT,
447 .ops = &clk_branch2_aon_ops,
452 static struct clk_branch gpu_cc_hub_cx_int_clk = {
454 .halt_check = BRANCH_HALT,
456 .enable_reg = 0x1204,
457 .enable_mask = BIT(0),
458 .hw.init = &(struct clk_init_data){
459 .name = "gpu_cc_hub_cx_int_clk",
460 .parent_hws = (const struct clk_hw*[]){
461 &gpu_cc_hub_cx_int_div_clk_src.clkr.hw,
464 .flags = CLK_SET_RATE_PARENT,
465 .ops = &clk_branch2_aon_ops,
470 static struct clk_branch gpu_cc_mnd1x_0_gfx3d_clk = {
472 .halt_check = BRANCH_HALT,
474 .enable_reg = 0x802c,
475 .enable_mask = BIT(0),
476 .hw.init = &(struct clk_init_data){
477 .name = "gpu_cc_mnd1x_0_gfx3d_clk",
478 .ops = &clk_branch2_ops,
483 static struct clk_branch gpu_cc_mnd1x_1_gfx3d_clk = {
485 .halt_check = BRANCH_HALT,
487 .enable_reg = 0x8030,
488 .enable_mask = BIT(0),
489 .hw.init = &(struct clk_init_data){
490 .name = "gpu_cc_mnd1x_1_gfx3d_clk",
491 .ops = &clk_branch2_ops,
496 static struct clk_branch gpu_cc_sleep_clk = {
498 .halt_check = BRANCH_HALT_VOTED,
500 .enable_reg = 0x1090,
501 .enable_mask = BIT(0),
502 .hw.init = &(struct clk_init_data){
503 .name = "gpu_cc_sleep_clk",
504 .ops = &clk_branch2_ops,
509 static struct gdsc gpu_cx_gdsc = {
511 .gds_hw_ctrl = 0x1540,
513 .name = "gpu_cx_gdsc",
515 .pwrsts = PWRSTS_OFF_ON,
519 static struct gdsc gpu_gx_gdsc = {
521 .clamp_io_ctrl = 0x1508,
523 .name = "gpu_gx_gdsc",
524 .power_on = gdsc_gx_do_nothing_enable,
526 .pwrsts = PWRSTS_OFF_ON,
527 .flags = CLAMP_IO | AON_RESET | POLL_CFG_GDSCR,
530 static struct clk_regmap *gpu_cc_sm8350_clocks[] = {
531 [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr,
532 [GPU_CC_CB_CLK] = &gpu_cc_cb_clk.clkr,
533 [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr,
534 [GPU_CC_CX_APB_CLK] = &gpu_cc_cx_apb_clk.clkr,
535 [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr,
536 [GPU_CC_CX_QDSS_AT_CLK] = &gpu_cc_cx_qdss_at_clk.clkr,
537 [GPU_CC_CX_QDSS_TRIG_CLK] = &gpu_cc_cx_qdss_trig_clk.clkr,
538 [GPU_CC_CX_QDSS_TSCTR_CLK] = &gpu_cc_cx_qdss_tsctr_clk.clkr,
539 [GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_clk.clkr,
540 [GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr,
541 [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr,
542 [GPU_CC_FREQ_MEASURE_CLK] = &gpu_cc_freq_measure_clk.clkr,
543 [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr,
544 [GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr,
545 [GPU_CC_GX_QDSS_TSCTR_CLK] = &gpu_cc_gx_qdss_tsctr_clk.clkr,
546 [GPU_CC_GX_VSENSE_CLK] = &gpu_cc_gx_vsense_clk.clkr,
547 [GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK] = &gpu_cc_hlos1_vote_gpu_smmu_clk.clkr,
548 [GPU_CC_HUB_AHB_DIV_CLK_SRC] = &gpu_cc_hub_ahb_div_clk_src.clkr,
549 [GPU_CC_HUB_AON_CLK] = &gpu_cc_hub_aon_clk.clkr,
550 [GPU_CC_HUB_CLK_SRC] = &gpu_cc_hub_clk_src.clkr,
551 [GPU_CC_HUB_CX_INT_CLK] = &gpu_cc_hub_cx_int_clk.clkr,
552 [GPU_CC_HUB_CX_INT_DIV_CLK_SRC] = &gpu_cc_hub_cx_int_div_clk_src.clkr,
553 [GPU_CC_MND1X_0_GFX3D_CLK] = &gpu_cc_mnd1x_0_gfx3d_clk.clkr,
554 [GPU_CC_MND1X_1_GFX3D_CLK] = &gpu_cc_mnd1x_1_gfx3d_clk.clkr,
555 [GPU_CC_PLL0] = &gpu_cc_pll0.clkr,
556 [GPU_CC_PLL1] = &gpu_cc_pll1.clkr,
557 [GPU_CC_SLEEP_CLK] = &gpu_cc_sleep_clk.clkr,
560 static const struct qcom_reset_map gpu_cc_sm8350_resets[] = {
561 [GPUCC_GPU_CC_ACD_BCR] = { 0x1160 },
562 [GPUCC_GPU_CC_CB_BCR] = { 0x116c },
563 [GPUCC_GPU_CC_CX_BCR] = { 0x1068 },
564 [GPUCC_GPU_CC_FAST_HUB_BCR] = { 0x1174 },
565 [GPUCC_GPU_CC_GFX3D_AON_BCR] = { 0x10a0 },
566 [GPUCC_GPU_CC_GMU_BCR] = { 0x111c },
567 [GPUCC_GPU_CC_GX_BCR] = { 0x1008 },
568 [GPUCC_GPU_CC_XO_BCR] = { 0x1000 },
571 static struct gdsc *gpu_cc_sm8350_gdscs[] = {
572 [GPU_CX_GDSC] = &gpu_cx_gdsc,
573 [GPU_GX_GDSC] = &gpu_gx_gdsc,
576 static const struct regmap_config gpu_cc_sm8350_regmap_config = {
580 .max_register = 0x8030,
584 static const struct qcom_cc_desc gpu_cc_sm8350_desc = {
585 .config = &gpu_cc_sm8350_regmap_config,
586 .clks = gpu_cc_sm8350_clocks,
587 .num_clks = ARRAY_SIZE(gpu_cc_sm8350_clocks),
588 .resets = gpu_cc_sm8350_resets,
589 .num_resets = ARRAY_SIZE(gpu_cc_sm8350_resets),
590 .gdscs = gpu_cc_sm8350_gdscs,
591 .num_gdscs = ARRAY_SIZE(gpu_cc_sm8350_gdscs),
594 static int gpu_cc_sm8350_probe(struct platform_device *pdev)
596 struct regmap *regmap;
598 regmap = qcom_cc_map(pdev, &gpu_cc_sm8350_desc);
599 if (IS_ERR(regmap)) {
600 dev_err(&pdev->dev, "Failed to map gpu cc registers\n");
601 return PTR_ERR(regmap);
604 clk_lucid_pll_configure(&gpu_cc_pll0, regmap, &gpu_cc_pll0_config);
605 clk_lucid_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config);
607 return qcom_cc_really_probe(pdev, &gpu_cc_sm8350_desc, regmap);
610 static const struct of_device_id gpu_cc_sm8350_match_table[] = {
611 { .compatible = "qcom,sm8350-gpucc" },
614 MODULE_DEVICE_TABLE(of, gpu_cc_sm8350_match_table);
616 static struct platform_driver gpu_cc_sm8350_driver = {
617 .probe = gpu_cc_sm8350_probe,
619 .name = "sm8350-gpucc",
620 .of_match_table = gpu_cc_sm8350_match_table,
624 static int __init gpu_cc_sm8350_init(void)
626 return platform_driver_register(&gpu_cc_sm8350_driver);
628 subsys_initcall(gpu_cc_sm8350_init);
630 static void __exit gpu_cc_sm8350_exit(void)
632 platform_driver_unregister(&gpu_cc_sm8350_driver);
634 module_exit(gpu_cc_sm8350_exit);
636 MODULE_DESCRIPTION("QTI GPU_CC SM8350 Driver");
637 MODULE_LICENSE("GPL v2");