1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2021, The Linux Foundation. All rights reserved.
4 * Copyright (c) 2023, Linaro Limited
7 #include <linux/clk-provider.h>
8 #include <linux/mod_devicetable.h>
9 #include <linux/module.h>
10 #include <linux/platform_device.h>
11 #include <linux/pm_runtime.h>
12 #include <linux/regmap.h>
14 #include <dt-bindings/clock/qcom,sm6375-gpucc.h>
16 #include "clk-alpha-pll.h"
17 #include "clk-branch.h"
19 #include "clk-regmap.h"
20 #include "clk-regmap-divider.h"
21 #include "clk-regmap-mux.h"
22 #include "clk-regmap-phy-mux.h"
28 DT_GCC_GPU_GPLL0_CLK_SRC
,
29 DT_GCC_GPU_GPLL0_DIV_CLK_SRC
,
30 DT_GCC_GPU_SNOC_DVM_GFX_CLK
,
35 P_GCC_GPU_GPLL0_CLK_SRC
,
36 P_GCC_GPU_GPLL0_DIV_CLK_SRC
,
37 P_GPU_CC_PLL0_OUT_EVEN
,
38 P_GPU_CC_PLL0_OUT_MAIN
,
39 P_GPU_CC_PLL0_OUT_ODD
,
40 P_GPU_CC_PLL1_OUT_EVEN
,
41 P_GPU_CC_PLL1_OUT_MAIN
,
42 P_GPU_CC_PLL1_OUT_ODD
,
45 static const struct pll_vco lucid_vco
[] = {
46 { 249600000, 2000000000, 0 },
49 /* 532MHz Configuration */
50 static const struct alpha_pll_config gpucc_pll0_config
= {
53 .config_ctl_val
= 0x20485699,
54 .config_ctl_hi_val
= 0x00002261,
55 .config_ctl_hi1_val
= 0x329a299c,
56 .user_ctl_val
= 0x00000001,
57 .user_ctl_hi_val
= 0x00000805,
58 .user_ctl_hi1_val
= 0x00000000,
61 static struct clk_alpha_pll gpucc_pll0
= {
63 .vco_table
= lucid_vco
,
64 .num_vco
= ARRAY_SIZE(lucid_vco
),
65 .regs
= clk_alpha_pll_regs
[CLK_ALPHA_PLL_TYPE_LUCID
],
67 .hw
.init
= &(struct clk_init_data
){
69 .parent_data
= &(const struct clk_parent_data
){
73 .ops
= &clk_alpha_pll_lucid_ops
,
78 /* 514MHz Configuration */
79 static const struct alpha_pll_config gpucc_pll1_config
= {
82 .config_ctl_val
= 0x20485699,
83 .config_ctl_hi_val
= 0x00002261,
84 .config_ctl_hi1_val
= 0x329a299c,
85 .user_ctl_val
= 0x00000001,
86 .user_ctl_hi_val
= 0x00000805,
87 .user_ctl_hi1_val
= 0x00000000,
90 static struct clk_alpha_pll gpucc_pll1
= {
92 .vco_table
= lucid_vco
,
93 .num_vco
= ARRAY_SIZE(lucid_vco
),
94 .regs
= clk_alpha_pll_regs
[CLK_ALPHA_PLL_TYPE_LUCID
],
96 .hw
.init
= &(struct clk_init_data
){
98 .parent_data
= &(const struct clk_parent_data
){
102 .ops
= &clk_alpha_pll_lucid_ops
,
107 static const struct parent_map gpucc_parent_map_0
[] = {
109 { P_GPU_CC_PLL0_OUT_MAIN
, 1 },
110 { P_GPU_CC_PLL1_OUT_MAIN
, 3 },
111 { P_GCC_GPU_GPLL0_CLK_SRC
, 5 },
112 { P_GCC_GPU_GPLL0_DIV_CLK_SRC
, 6 },
115 static const struct clk_parent_data gpucc_parent_data_0
[] = {
116 { .index
= P_BI_TCXO
},
117 { .hw
= &gpucc_pll0
.clkr
.hw
},
118 { .hw
= &gpucc_pll1
.clkr
.hw
},
119 { .index
= DT_GCC_GPU_GPLL0_CLK_SRC
},
120 { .index
= DT_GCC_GPU_GPLL0_DIV_CLK_SRC
},
123 static const struct parent_map gpucc_parent_map_1
[] = {
125 { P_GPU_CC_PLL0_OUT_EVEN
, 1 },
126 { P_GPU_CC_PLL0_OUT_ODD
, 2 },
127 { P_GPU_CC_PLL1_OUT_EVEN
, 3 },
128 { P_GPU_CC_PLL1_OUT_ODD
, 4 },
129 { P_GCC_GPU_GPLL0_CLK_SRC
, 5 },
132 static const struct clk_parent_data gpucc_parent_data_1
[] = {
133 { .index
= P_BI_TCXO
},
134 { .hw
= &gpucc_pll0
.clkr
.hw
},
135 { .hw
= &gpucc_pll0
.clkr
.hw
},
136 { .hw
= &gpucc_pll1
.clkr
.hw
},
137 { .hw
= &gpucc_pll1
.clkr
.hw
},
138 { .index
= DT_GCC_GPU_GPLL0_CLK_SRC
},
141 static const struct freq_tbl ftbl_gpucc_gmu_clk_src
[] = {
142 F(200000000, P_GCC_GPU_GPLL0_DIV_CLK_SRC
, 1.5, 0, 0),
146 static struct clk_rcg2 gpucc_gmu_clk_src
= {
150 .parent_map
= gpucc_parent_map_0
,
151 .freq_tbl
= ftbl_gpucc_gmu_clk_src
,
152 .clkr
.hw
.init
= &(struct clk_init_data
){
153 .name
= "gpucc_gmu_clk_src",
154 .parent_data
= gpucc_parent_data_0
,
155 .num_parents
= ARRAY_SIZE(gpucc_parent_data_0
),
156 .ops
= &clk_rcg2_shared_ops
,
160 static const struct freq_tbl ftbl_gpucc_gx_gfx3d_clk_src
[] = {
161 F(266000000, P_GPU_CC_PLL0_OUT_EVEN
, 2, 0, 0),
162 F(390000000, P_GPU_CC_PLL0_OUT_EVEN
, 2, 0, 0),
163 F(490000000, P_GPU_CC_PLL0_OUT_EVEN
, 2, 0, 0),
164 F(650000000, P_GPU_CC_PLL0_OUT_EVEN
, 2, 0, 0),
165 F(770000000, P_GPU_CC_PLL0_OUT_EVEN
, 2, 0, 0),
166 F(840000000, P_GPU_CC_PLL0_OUT_EVEN
, 2, 0, 0),
167 F(900000000, P_GPU_CC_PLL0_OUT_EVEN
, 2, 0, 0),
171 static struct clk_rcg2 gpucc_gx_gfx3d_clk_src
= {
175 .parent_map
= gpucc_parent_map_1
,
176 .freq_tbl
= ftbl_gpucc_gx_gfx3d_clk_src
,
177 .clkr
.hw
.init
= &(struct clk_init_data
){
178 .name
= "gpucc_gx_gfx3d_clk_src",
179 .parent_data
= gpucc_parent_data_1
,
180 .num_parents
= ARRAY_SIZE(gpucc_parent_data_1
),
181 .flags
= CLK_SET_RATE_PARENT
| CLK_OPS_PARENT_ENABLE
,
182 .ops
= &clk_rcg2_ops
,
186 static struct clk_branch gpucc_ahb_clk
= {
188 .halt_check
= BRANCH_HALT_DELAY
,
190 .enable_reg
= 0x1078,
191 .enable_mask
= BIT(0),
192 .hw
.init
= &(struct clk_init_data
){
193 .name
= "gpucc_ahb_clk",
194 .flags
= CLK_IS_CRITICAL
,
195 .ops
= &clk_branch2_ops
,
200 static struct clk_branch gpucc_cx_gfx3d_clk
= {
202 .halt_check
= BRANCH_HALT_DELAY
,
204 .enable_reg
= 0x10a4,
205 .enable_mask
= BIT(0),
206 .hw
.init
= &(struct clk_init_data
){
207 .name
= "gpucc_cx_gfx3d_clk",
208 .parent_hws
= (const struct clk_hw
*[]) {
209 &gpucc_gx_gfx3d_clk_src
.clkr
.hw
,
212 .flags
= CLK_SET_RATE_PARENT
,
213 .ops
= &clk_branch2_ops
,
218 static struct clk_branch gpucc_cx_gfx3d_slv_clk
= {
220 .halt_check
= BRANCH_HALT_DELAY
,
222 .enable_reg
= 0x10a8,
223 .enable_mask
= BIT(0),
224 .hw
.init
= &(struct clk_init_data
){
225 .name
= "gpucc_cx_gfx3d_slv_clk",
226 .parent_hws
= (const struct clk_hw
*[]) {
227 &gpucc_gx_gfx3d_clk_src
.clkr
.hw
,
230 .flags
= CLK_SET_RATE_PARENT
,
231 .ops
= &clk_branch2_ops
,
236 static struct clk_branch gpucc_cx_gmu_clk
= {
238 .halt_check
= BRANCH_HALT
,
240 .enable_reg
= 0x1098,
241 .enable_mask
= BIT(0),
242 .hw
.init
= &(struct clk_init_data
){
243 .name
= "gpucc_cx_gmu_clk",
244 .parent_hws
= (const struct clk_hw
*[]) {
245 &gpucc_gmu_clk_src
.clkr
.hw
,
248 .flags
= CLK_SET_RATE_PARENT
,
249 .ops
= &clk_branch2_ops
,
254 static struct clk_branch gpucc_cx_snoc_dvm_clk
= {
256 .halt_check
= BRANCH_HALT_DELAY
,
258 .enable_reg
= 0x108c,
259 .enable_mask
= BIT(0),
260 .hw
.init
= &(struct clk_init_data
){
261 .name
= "gpucc_cx_snoc_dvm_clk",
262 .parent_data
= &(const struct clk_parent_data
){
263 .index
= DT_GCC_GPU_SNOC_DVM_GFX_CLK
,
266 .ops
= &clk_branch2_ops
,
271 static struct clk_branch gpucc_cxo_aon_clk
= {
273 .halt_check
= BRANCH_HALT_DELAY
,
275 .enable_reg
= 0x1004,
276 .enable_mask
= BIT(0),
277 .hw
.init
= &(struct clk_init_data
){
278 .name
= "gpucc_cxo_aon_clk",
279 .ops
= &clk_branch2_ops
,
284 static struct clk_branch gpucc_cxo_clk
= {
286 .halt_check
= BRANCH_HALT
,
288 .enable_reg
= 0x109c,
289 .enable_mask
= BIT(0),
290 .hw
.init
= &(struct clk_init_data
){
291 .name
= "gpucc_cxo_clk",
292 .ops
= &clk_branch2_ops
,
297 static struct clk_branch gpucc_gx_cxo_clk
= {
299 .halt_check
= BRANCH_HALT_DELAY
,
301 .enable_reg
= 0x1060,
302 .enable_mask
= BIT(0),
303 .hw
.init
= &(struct clk_init_data
){
304 .name
= "gpucc_gx_cxo_clk",
305 .flags
= CLK_IS_CRITICAL
,
306 .ops
= &clk_branch2_ops
,
311 static struct clk_branch gpucc_gx_gfx3d_clk
= {
313 .halt_check
= BRANCH_HALT_DELAY
,
315 .enable_reg
= 0x1054,
316 .enable_mask
= BIT(0),
317 .hw
.init
= &(struct clk_init_data
){
318 .name
= "gpucc_gx_gfx3d_clk",
319 .parent_hws
= (const struct clk_hw
*[]) {
320 &gpucc_gx_gfx3d_clk_src
.clkr
.hw
,
323 .flags
= CLK_SET_RATE_PARENT
,
324 .ops
= &clk_branch2_ops
,
329 static struct clk_branch gpucc_gx_gmu_clk
= {
331 .halt_check
= BRANCH_HALT
,
333 .enable_reg
= 0x1064,
334 .enable_mask
= BIT(0),
335 .hw
.init
= &(struct clk_init_data
){
336 .name
= "gpucc_gx_gmu_clk",
337 .parent_hws
= (const struct clk_hw
*[]) {
338 &gpucc_gmu_clk_src
.clkr
.hw
,
341 .flags
= CLK_SET_RATE_PARENT
,
342 .ops
= &clk_branch2_ops
,
347 static struct clk_branch gpucc_sleep_clk
= {
349 .halt_check
= BRANCH_HALT_VOTED
,
351 .enable_reg
= 0x1090,
352 .enable_mask
= BIT(0),
353 .hw
.init
= &(struct clk_init_data
){
354 .name
= "gpucc_sleep_clk",
355 .ops
= &clk_branch2_ops
,
360 static struct gdsc gpu_cx_gdsc
= {
362 .gds_hw_ctrl
= 0x1540,
363 .clk_dis_wait_val
= 8,
365 .name
= "gpu_cx_gdsc",
367 .pwrsts
= PWRSTS_OFF_ON
,
371 static struct gdsc gpu_gx_gdsc
= {
373 .clamp_io_ctrl
= 0x1508,
374 .resets
= (unsigned int []){ GPU_GX_BCR
, GPU_ACD_BCR
, GPU_GX_ACD_MISC_BCR
},
377 .name
= "gpu_gx_gdsc",
379 .pwrsts
= PWRSTS_OFF_ON
,
380 .flags
= CLAMP_IO
| SW_RESET
| AON_RESET
,
383 static struct clk_regmap
*gpucc_sm6375_clocks
[] = {
384 [GPU_CC_AHB_CLK
] = &gpucc_ahb_clk
.clkr
,
385 [GPU_CC_CX_GFX3D_CLK
] = &gpucc_cx_gfx3d_clk
.clkr
,
386 [GPU_CC_CX_GFX3D_SLV_CLK
] = &gpucc_cx_gfx3d_slv_clk
.clkr
,
387 [GPU_CC_CX_GMU_CLK
] = &gpucc_cx_gmu_clk
.clkr
,
388 [GPU_CC_CX_SNOC_DVM_CLK
] = &gpucc_cx_snoc_dvm_clk
.clkr
,
389 [GPU_CC_CXO_AON_CLK
] = &gpucc_cxo_aon_clk
.clkr
,
390 [GPU_CC_CXO_CLK
] = &gpucc_cxo_clk
.clkr
,
391 [GPU_CC_GMU_CLK_SRC
] = &gpucc_gmu_clk_src
.clkr
,
392 [GPU_CC_GX_CXO_CLK
] = &gpucc_gx_cxo_clk
.clkr
,
393 [GPU_CC_GX_GFX3D_CLK
] = &gpucc_gx_gfx3d_clk
.clkr
,
394 [GPU_CC_GX_GFX3D_CLK_SRC
] = &gpucc_gx_gfx3d_clk_src
.clkr
,
395 [GPU_CC_GX_GMU_CLK
] = &gpucc_gx_gmu_clk
.clkr
,
396 [GPU_CC_PLL0
] = &gpucc_pll0
.clkr
,
397 [GPU_CC_PLL1
] = &gpucc_pll1
.clkr
,
398 [GPU_CC_SLEEP_CLK
] = &gpucc_sleep_clk
.clkr
,
401 static const struct qcom_reset_map gpucc_sm6375_resets
[] = {
402 [GPU_GX_BCR
] = { 0x1008 },
403 [GPU_ACD_BCR
] = { 0x1160 },
404 [GPU_GX_ACD_MISC_BCR
] = { 0x8004 },
407 static struct gdsc
*gpucc_sm6375_gdscs
[] = {
408 [GPU_CX_GDSC
] = &gpu_cx_gdsc
,
409 [GPU_GX_GDSC
] = &gpu_gx_gdsc
,
412 static const struct regmap_config gpucc_sm6375_regmap_config
= {
416 .max_register
= 0x9000,
420 static const struct qcom_cc_desc gpucc_sm6375_desc
= {
421 .config
= &gpucc_sm6375_regmap_config
,
422 .clks
= gpucc_sm6375_clocks
,
423 .num_clks
= ARRAY_SIZE(gpucc_sm6375_clocks
),
424 .resets
= gpucc_sm6375_resets
,
425 .num_resets
= ARRAY_SIZE(gpucc_sm6375_resets
),
426 .gdscs
= gpucc_sm6375_gdscs
,
427 .num_gdscs
= ARRAY_SIZE(gpucc_sm6375_gdscs
),
430 static const struct of_device_id gpucc_sm6375_match_table
[] = {
431 { .compatible
= "qcom,sm6375-gpucc" },
434 MODULE_DEVICE_TABLE(of
, gpucc_sm6375_match_table
);
436 static int gpucc_sm6375_probe(struct platform_device
*pdev
)
438 struct regmap
*regmap
;
441 ret
= devm_pm_runtime_enable(&pdev
->dev
);
445 ret
= pm_runtime_resume_and_get(&pdev
->dev
);
449 regmap
= qcom_cc_map(pdev
, &gpucc_sm6375_desc
);
450 if (IS_ERR(regmap
)) {
451 pm_runtime_put(&pdev
->dev
);
452 return PTR_ERR(regmap
);
455 clk_lucid_pll_configure(&gpucc_pll0
, regmap
, &gpucc_pll0_config
);
456 clk_lucid_pll_configure(&gpucc_pll1
, regmap
, &gpucc_pll1_config
);
458 ret
= qcom_cc_really_probe(&pdev
->dev
, &gpucc_sm6375_desc
, regmap
);
459 pm_runtime_put(&pdev
->dev
);
464 static struct platform_driver gpucc_sm6375_driver
= {
465 .probe
= gpucc_sm6375_probe
,
467 .name
= "gpucc-sm6375",
468 .of_match_table
= gpucc_sm6375_match_table
,
471 module_platform_driver(gpucc_sm6375_driver
);
473 MODULE_DESCRIPTION("QTI GPUCC SM6375 Driver");
474 MODULE_LICENSE("GPL");