1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2021, The Linux Foundation. All rights reserved.
4 * Copyright (c) 2021, Konrad Dybcio <konrad.dybcio@somainline.org>
7 #include <linux/clk-provider.h>
8 #include <linux/module.h>
9 #include <linux/platform_device.h>
10 #include <linux/regmap.h>
12 #include <dt-bindings/clock/qcom,gpucc-sm6350.h>
15 #include "clk-alpha-pll.h"
16 #include "clk-branch.h"
18 #include "clk-regmap.h"
22 #define CX_GMU_CBCR_SLEEP_MASK 0xF
23 #define CX_GMU_CBCR_SLEEP_SHIFT 4
24 #define CX_GMU_CBCR_WAKE_MASK 0xF
25 #define CX_GMU_CBCR_WAKE_SHIFT 8
30 DT_GPLL0_OUT_MAIN_DIV
,
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
,
45 static const struct pll_vco fabia_vco
[] = {
46 { 249600000, 2000000000, 0 },
49 /* 506MHz Configuration*/
50 static const struct alpha_pll_config gpu_cc_pll0_config
= {
53 .config_ctl_val
= 0x20485699,
54 .config_ctl_hi_val
= 0x00002067,
55 .test_ctl_val
= 0x40000000,
56 .test_ctl_hi_val
= 0x00000002,
57 .user_ctl_val
= 0x00000001,
58 .user_ctl_hi_val
= 0x00004805,
61 static struct clk_alpha_pll gpu_cc_pll0
= {
63 .vco_table
= fabia_vco
,
64 .num_vco
= ARRAY_SIZE(fabia_vco
),
65 .regs
= clk_alpha_pll_regs
[CLK_ALPHA_PLL_TYPE_FABIA
],
67 .hw
.init
= &(struct clk_init_data
){
68 .name
= "gpu_cc_pll0",
69 .parent_data
= &(const struct clk_parent_data
){
74 .ops
= &clk_alpha_pll_fabia_ops
,
79 static struct clk_fixed_factor crc_div
= {
82 .hw
.init
= &(struct clk_init_data
){
84 .parent_hws
= (const struct clk_hw
*[]){
88 .flags
= CLK_SET_RATE_PARENT
,
89 .ops
= &clk_fixed_factor_ops
,
93 /* 514MHz Configuration*/
94 static const struct alpha_pll_config gpu_cc_pll1_config
= {
97 .config_ctl_val
= 0x20485699,
98 .config_ctl_hi_val
= 0x00002067,
99 .test_ctl_val
= 0x40000000,
100 .test_ctl_hi_val
= 0x00000002,
101 .user_ctl_val
= 0x00000001,
102 .user_ctl_hi_val
= 0x00004805,
105 static struct clk_alpha_pll gpu_cc_pll1
= {
107 .vco_table
= fabia_vco
,
108 .num_vco
= ARRAY_SIZE(fabia_vco
),
109 .regs
= clk_alpha_pll_regs
[CLK_ALPHA_PLL_TYPE_FABIA
],
111 .hw
.init
= &(struct clk_init_data
){
112 .name
= "gpu_cc_pll1",
113 .parent_data
= &(const struct clk_parent_data
){
115 .fw_name
= "bi_tcxo",
118 .ops
= &clk_alpha_pll_fabia_ops
,
123 static const struct parent_map gpu_cc_parent_map_0
[] = {
125 { P_GPU_CC_PLL0_OUT_MAIN
, 1 },
126 { P_GPU_CC_PLL1_OUT_MAIN
, 3 },
127 { P_GPLL0_OUT_MAIN
, 5 },
128 { P_GPLL0_OUT_MAIN_DIV
, 6 },
131 static const struct clk_parent_data gpu_cc_parent_data_0
[] = {
132 { .index
= DT_BI_TCXO
, .fw_name
= "bi_tcxo" },
133 { .hw
= &gpu_cc_pll0
.clkr
.hw
},
134 { .hw
= &gpu_cc_pll1
.clkr
.hw
},
135 { .index
= DT_GPLL0_OUT_MAIN
, .fw_name
= "gcc_gpu_gpll0_clk_src" },
136 { .index
= DT_GPLL0_OUT_MAIN_DIV
, .fw_name
= "gcc_gpu_gpll0_div_clk_src" },
139 static const struct parent_map gpu_cc_parent_map_1
[] = {
142 { P_GPU_CC_PLL0_OUT_ODD
, 2 },
143 { P_GPU_CC_PLL1_OUT_EVEN
, 3 },
144 { P_GPU_CC_PLL1_OUT_ODD
, 4 },
145 { P_GPLL0_OUT_MAIN
, 5 },
148 static const struct clk_parent_data gpu_cc_parent_data_1
[] = {
149 { .index
= DT_BI_TCXO
, .fw_name
= "bi_tcxo" },
150 { .hw
= &crc_div
.hw
},
151 { .hw
= &gpu_cc_pll0
.clkr
.hw
},
152 { .hw
= &gpu_cc_pll1
.clkr
.hw
},
153 { .hw
= &gpu_cc_pll1
.clkr
.hw
},
154 { .index
= DT_GPLL0_OUT_MAIN
, .fw_name
= "gcc_gpu_gpll0_clk_src" },
157 static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src
[] = {
158 F(200000000, P_GPLL0_OUT_MAIN_DIV
, 1.5, 0, 0),
162 static struct clk_rcg2 gpu_cc_gmu_clk_src
= {
166 .parent_map
= gpu_cc_parent_map_0
,
167 .freq_tbl
= ftbl_gpu_cc_gmu_clk_src
,
168 .clkr
.hw
.init
= &(struct clk_init_data
){
169 .name
= "gpu_cc_gmu_clk_src",
170 .parent_data
= gpu_cc_parent_data_0
,
171 .num_parents
= ARRAY_SIZE(gpu_cc_parent_data_0
),
172 .flags
= CLK_SET_RATE_PARENT
,
173 .ops
= &clk_rcg2_ops
,
177 static const struct freq_tbl ftbl_gpu_cc_gx_gfx3d_clk_src
[] = {
178 F(253000000, P_CRC_DIV
, 1, 0, 0),
179 F(355000000, P_CRC_DIV
, 1, 0, 0),
180 F(430000000, P_CRC_DIV
, 1, 0, 0),
181 F(565000000, P_CRC_DIV
, 1, 0, 0),
182 F(650000000, P_CRC_DIV
, 1, 0, 0),
183 F(800000000, P_CRC_DIV
, 1, 0, 0),
184 F(825000000, P_CRC_DIV
, 1, 0, 0),
185 F(850000000, P_CRC_DIV
, 1, 0, 0),
189 static struct clk_rcg2 gpu_cc_gx_gfx3d_clk_src
= {
193 .parent_map
= gpu_cc_parent_map_1
,
194 .freq_tbl
= ftbl_gpu_cc_gx_gfx3d_clk_src
,
195 .clkr
.hw
.init
= &(struct clk_init_data
){
196 .name
= "gpu_cc_gx_gfx3d_clk_src",
197 .parent_data
= gpu_cc_parent_data_1
,
198 .num_parents
= ARRAY_SIZE(gpu_cc_parent_data_1
),
199 .flags
= CLK_SET_RATE_PARENT
,
200 .ops
= &clk_rcg2_ops
,
204 static struct clk_branch gpu_cc_acd_ahb_clk
= {
206 .halt_check
= BRANCH_HALT
,
208 .enable_reg
= 0x1168,
209 .enable_mask
= BIT(0),
210 .hw
.init
= &(struct clk_init_data
){
211 .name
= "gpu_cc_acd_ahb_clk",
212 .ops
= &clk_branch2_ops
,
217 static struct clk_branch gpu_cc_acd_cxo_clk
= {
219 .halt_check
= BRANCH_HALT
,
221 .enable_reg
= 0x1164,
222 .enable_mask
= BIT(0),
223 .hw
.init
= &(struct clk_init_data
){
224 .name
= "gpu_cc_acd_cxo_clk",
225 .ops
= &clk_branch2_ops
,
230 static struct clk_branch gpu_cc_ahb_clk
= {
232 .halt_check
= BRANCH_HALT_DELAY
,
234 .enable_reg
= 0x1078,
235 .enable_mask
= BIT(0),
236 .hw
.init
= &(struct clk_init_data
){
237 .name
= "gpu_cc_ahb_clk",
238 .flags
= CLK_IS_CRITICAL
,
239 .ops
= &clk_branch2_ops
,
244 static struct clk_branch gpu_cc_crc_ahb_clk
= {
246 .halt_check
= BRANCH_HALT_DELAY
,
248 .enable_reg
= 0x107c,
249 .enable_mask
= BIT(0),
250 .hw
.init
= &(struct clk_init_data
){
251 .name
= "gpu_cc_crc_ahb_clk",
252 .ops
= &clk_branch2_ops
,
257 static struct clk_branch gpu_cc_cx_gfx3d_clk
= {
259 .halt_check
= BRANCH_HALT_DELAY
,
261 .enable_reg
= 0x10a4,
262 .enable_mask
= BIT(0),
263 .hw
.init
= &(struct clk_init_data
){
264 .name
= "gpu_cc_cx_gfx3d_clk",
265 .parent_hws
= (const struct clk_hw
*[]){
266 &gpu_cc_gx_gfx3d_clk_src
.clkr
.hw
,
269 .flags
= CLK_SET_RATE_PARENT
,
270 .ops
= &clk_branch2_ops
,
275 static struct clk_branch gpu_cc_cx_gfx3d_slv_clk
= {
277 .halt_check
= BRANCH_HALT_DELAY
,
279 .enable_reg
= 0x10a8,
280 .enable_mask
= BIT(0),
281 .hw
.init
= &(struct clk_init_data
){
282 .name
= "gpu_cc_cx_gfx3d_slv_clk",
283 .parent_hws
= (const struct clk_hw
*[]){
284 &gpu_cc_gx_gfx3d_clk_src
.clkr
.hw
,
287 .flags
= CLK_SET_RATE_PARENT
,
288 .ops
= &clk_branch2_ops
,
293 static struct clk_branch gpu_cc_cx_gmu_clk
= {
295 .halt_check
= BRANCH_HALT
,
297 .enable_reg
= 0x1098,
298 .enable_mask
= BIT(0),
299 .hw
.init
= &(struct clk_init_data
){
300 .name
= "gpu_cc_cx_gmu_clk",
301 .parent_hws
= (const struct clk_hw
*[]){
302 &gpu_cc_gmu_clk_src
.clkr
.hw
,
305 .flags
= CLK_SET_RATE_PARENT
,
306 .ops
= &clk_branch2_ops
,
311 static struct clk_branch gpu_cc_cx_snoc_dvm_clk
= {
313 .halt_check
= BRANCH_HALT_DELAY
,
315 .enable_reg
= 0x108c,
316 .enable_mask
= BIT(0),
317 .hw
.init
= &(struct clk_init_data
){
318 .name
= "gpu_cc_cx_snoc_dvm_clk",
319 .ops
= &clk_branch2_ops
,
324 static struct clk_branch gpu_cc_cxo_aon_clk
= {
326 .halt_check
= BRANCH_HALT_DELAY
,
328 .enable_reg
= 0x1004,
329 .enable_mask
= BIT(0),
330 .hw
.init
= &(struct clk_init_data
){
331 .name
= "gpu_cc_cxo_aon_clk",
332 .ops
= &clk_branch2_ops
,
337 static struct clk_branch gpu_cc_cxo_clk
= {
339 .halt_check
= BRANCH_HALT
,
341 .enable_reg
= 0x109c,
342 .enable_mask
= BIT(0),
343 .hw
.init
= &(struct clk_init_data
){
344 .name
= "gpu_cc_cxo_clk",
345 .ops
= &clk_branch2_ops
,
350 static struct clk_branch gpu_cc_gx_cxo_clk
= {
352 .halt_check
= BRANCH_HALT
,
354 .enable_reg
= 0x1060,
355 .enable_mask
= BIT(0),
356 .hw
.init
= &(struct clk_init_data
){
357 .name
= "gpu_cc_gx_cxo_clk",
358 .ops
= &clk_branch2_ops
,
363 static struct clk_branch gpu_cc_gx_gfx3d_clk
= {
365 .halt_check
= BRANCH_HALT_SKIP
,
367 .enable_reg
= 0x1054,
368 .enable_mask
= BIT(0),
369 .hw
.init
= &(struct clk_init_data
){
370 .name
= "gpu_cc_gx_gfx3d_clk",
371 .parent_hws
= (const struct clk_hw
*[]){
372 &gpu_cc_gx_gfx3d_clk_src
.clkr
.hw
,
375 .flags
= CLK_SET_RATE_PARENT
,
376 .ops
= &clk_branch2_ops
,
381 static struct clk_branch gpu_cc_gx_gmu_clk
= {
383 .halt_check
= BRANCH_HALT
,
385 .enable_reg
= 0x1064,
386 .enable_mask
= BIT(0),
387 .hw
.init
= &(struct clk_init_data
){
388 .name
= "gpu_cc_gx_gmu_clk",
389 .parent_hws
= (const struct clk_hw
*[]){
390 &gpu_cc_gmu_clk_src
.clkr
.hw
,
393 .flags
= CLK_SET_RATE_PARENT
,
394 .ops
= &clk_branch2_ops
,
399 static struct clk_branch gpu_cc_gx_vsense_clk
= {
401 .halt_check
= BRANCH_HALT_DELAY
,
403 .enable_reg
= 0x1058,
404 .enable_mask
= BIT(0),
405 .hw
.init
= &(struct clk_init_data
){
406 .name
= "gpu_cc_gx_vsense_clk",
407 .ops
= &clk_branch2_ops
,
412 static struct gdsc gpu_cx_gdsc
= {
414 .gds_hw_ctrl
= 0x1540,
416 .name
= "gpu_cx_gdsc",
418 .pwrsts
= PWRSTS_OFF_ON
,
422 static struct gdsc gpu_gx_gdsc
= {
424 .clamp_io_ctrl
= 0x1508,
426 .name
= "gpu_gx_gdsc",
427 .power_on
= gdsc_gx_do_nothing_enable
,
429 .pwrsts
= PWRSTS_OFF_ON
,
430 .flags
= CLAMP_IO
| POLL_CFG_GDSCR
,
433 static struct clk_hw
*gpu_cc_sm6350_hws
[] = {
434 [GPU_CC_CRC_DIV
] = &crc_div
.hw
,
437 static struct clk_regmap
*gpu_cc_sm6350_clocks
[] = {
438 [GPU_CC_ACD_AHB_CLK
] = &gpu_cc_acd_ahb_clk
.clkr
,
439 [GPU_CC_ACD_CXO_CLK
] = &gpu_cc_acd_cxo_clk
.clkr
,
440 [GPU_CC_AHB_CLK
] = &gpu_cc_ahb_clk
.clkr
,
441 [GPU_CC_CRC_AHB_CLK
] = &gpu_cc_crc_ahb_clk
.clkr
,
442 [GPU_CC_CX_GFX3D_CLK
] = &gpu_cc_cx_gfx3d_clk
.clkr
,
443 [GPU_CC_CX_GFX3D_SLV_CLK
] = &gpu_cc_cx_gfx3d_slv_clk
.clkr
,
444 [GPU_CC_CX_GMU_CLK
] = &gpu_cc_cx_gmu_clk
.clkr
,
445 [GPU_CC_CX_SNOC_DVM_CLK
] = &gpu_cc_cx_snoc_dvm_clk
.clkr
,
446 [GPU_CC_CXO_AON_CLK
] = &gpu_cc_cxo_aon_clk
.clkr
,
447 [GPU_CC_CXO_CLK
] = &gpu_cc_cxo_clk
.clkr
,
448 [GPU_CC_GMU_CLK_SRC
] = &gpu_cc_gmu_clk_src
.clkr
,
449 [GPU_CC_GX_CXO_CLK
] = &gpu_cc_gx_cxo_clk
.clkr
,
450 [GPU_CC_GX_GFX3D_CLK
] = &gpu_cc_gx_gfx3d_clk
.clkr
,
451 [GPU_CC_GX_GFX3D_CLK_SRC
] = &gpu_cc_gx_gfx3d_clk_src
.clkr
,
452 [GPU_CC_GX_GMU_CLK
] = &gpu_cc_gx_gmu_clk
.clkr
,
453 [GPU_CC_GX_VSENSE_CLK
] = &gpu_cc_gx_vsense_clk
.clkr
,
454 [GPU_CC_PLL0
] = &gpu_cc_pll0
.clkr
,
455 [GPU_CC_PLL1
] = &gpu_cc_pll1
.clkr
,
458 static struct gdsc
*gpu_cc_sm6350_gdscs
[] = {
459 [GPU_CX_GDSC
] = &gpu_cx_gdsc
,
460 [GPU_GX_GDSC
] = &gpu_gx_gdsc
,
463 static const struct regmap_config gpu_cc_sm6350_regmap_config
= {
467 .max_register
= 0x8008,
471 static const struct qcom_cc_desc gpu_cc_sm6350_desc
= {
472 .config
= &gpu_cc_sm6350_regmap_config
,
473 .clk_hws
= gpu_cc_sm6350_hws
,
474 .num_clk_hws
= ARRAY_SIZE(gpu_cc_sm6350_hws
),
475 .clks
= gpu_cc_sm6350_clocks
,
476 .num_clks
= ARRAY_SIZE(gpu_cc_sm6350_clocks
),
477 .gdscs
= gpu_cc_sm6350_gdscs
,
478 .num_gdscs
= ARRAY_SIZE(gpu_cc_sm6350_gdscs
),
481 static const struct of_device_id gpu_cc_sm6350_match_table
[] = {
482 { .compatible
= "qcom,sm6350-gpucc" },
485 MODULE_DEVICE_TABLE(of
, gpu_cc_sm6350_match_table
);
487 static int gpu_cc_sm6350_probe(struct platform_device
*pdev
)
489 struct regmap
*regmap
;
490 unsigned int value
, mask
;
492 regmap
= qcom_cc_map(pdev
, &gpu_cc_sm6350_desc
);
494 return PTR_ERR(regmap
);
496 clk_fabia_pll_configure(&gpu_cc_pll0
, regmap
, &gpu_cc_pll0_config
);
497 clk_fabia_pll_configure(&gpu_cc_pll1
, regmap
, &gpu_cc_pll1_config
);
499 /* Configure gpu_cc_cx_gmu_clk with recommended wakeup/sleep settings */
500 mask
= CX_GMU_CBCR_WAKE_MASK
<< CX_GMU_CBCR_WAKE_SHIFT
;
501 mask
|= CX_GMU_CBCR_SLEEP_MASK
<< CX_GMU_CBCR_SLEEP_SHIFT
;
502 value
= 0xF << CX_GMU_CBCR_WAKE_SHIFT
| 0xF << CX_GMU_CBCR_SLEEP_SHIFT
;
503 regmap_update_bits(regmap
, 0x1098, mask
, value
);
505 return qcom_cc_really_probe(&pdev
->dev
, &gpu_cc_sm6350_desc
, regmap
);
508 static struct platform_driver gpu_cc_sm6350_driver
= {
509 .probe
= gpu_cc_sm6350_probe
,
511 .name
= "sm6350-gpucc",
512 .of_match_table
= gpu_cc_sm6350_match_table
,
516 static int __init
gpu_cc_sm6350_init(void)
518 return platform_driver_register(&gpu_cc_sm6350_driver
);
520 core_initcall(gpu_cc_sm6350_init
);
522 static void __exit
gpu_cc_sm6350_exit(void)
524 platform_driver_unregister(&gpu_cc_sm6350_driver
);
526 module_exit(gpu_cc_sm6350_exit
);
528 MODULE_DESCRIPTION("QTI GPU_CC LAGOON Driver");
529 MODULE_LICENSE("GPL v2");