1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
6 #include <linux/clk-provider.h>
7 #include <linux/module.h>
8 #include <linux/platform_device.h>
9 #include <linux/regmap.h>
11 #include <dt-bindings/clock/qcom,gpucc-sm8250.h>
14 #include "clk-alpha-pll.h"
15 #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
29 P_CORE_BI_PLL_TEST_SE
,
32 P_GPU_CC_PLL0_OUT_MAIN
,
33 P_GPU_CC_PLL1_OUT_MAIN
,
36 static struct pll_vco lucid_vco
[] = {
37 { 249600000, 2000000000, 0 },
40 static const struct alpha_pll_config gpu_cc_pll1_config
= {
43 .config_ctl_val
= 0x20485699,
44 .config_ctl_hi_val
= 0x00002261,
45 .config_ctl_hi1_val
= 0x029a699c,
46 .user_ctl_val
= 0x00000000,
47 .user_ctl_hi_val
= 0x00000805,
48 .user_ctl_hi1_val
= 0x00000000,
51 static struct clk_alpha_pll gpu_cc_pll1
= {
53 .vco_table
= lucid_vco
,
54 .num_vco
= ARRAY_SIZE(lucid_vco
),
55 .regs
= clk_alpha_pll_regs
[CLK_ALPHA_PLL_TYPE_LUCID
],
57 .hw
.init
= &(struct clk_init_data
){
58 .name
= "gpu_cc_pll1",
59 .parent_data
= &(const struct clk_parent_data
){
63 .ops
= &clk_alpha_pll_lucid_ops
,
68 static const struct parent_map gpu_cc_parent_map_0
[] = {
70 { P_GPU_CC_PLL1_OUT_MAIN
, 3 },
71 { P_GPLL0_OUT_MAIN
, 5 },
72 { P_GPLL0_OUT_MAIN_DIV
, 6 },
75 static const struct clk_parent_data gpu_cc_parent_data_0
[] = {
76 { .fw_name
= "bi_tcxo" },
77 { .hw
= &gpu_cc_pll1
.clkr
.hw
},
78 { .fw_name
= "gcc_gpu_gpll0_clk_src" },
79 { .fw_name
= "gcc_gpu_gpll0_div_clk_src" },
82 static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src
[] = {
83 F(19200000, P_BI_TCXO
, 1, 0, 0),
84 F(200000000, P_GPLL0_OUT_MAIN_DIV
, 1.5, 0, 0),
85 F(500000000, P_GPU_CC_PLL1_OUT_MAIN
, 1, 0, 0),
89 static struct clk_rcg2 gpu_cc_gmu_clk_src
= {
93 .parent_map
= gpu_cc_parent_map_0
,
94 .freq_tbl
= ftbl_gpu_cc_gmu_clk_src
,
95 .clkr
.hw
.init
= &(struct clk_init_data
){
96 .name
= "gpu_cc_gmu_clk_src",
97 .parent_data
= gpu_cc_parent_data_0
,
98 .num_parents
= ARRAY_SIZE(gpu_cc_parent_data_0
),
99 .flags
= CLK_SET_RATE_PARENT
,
100 .ops
= &clk_rcg2_ops
,
104 static struct clk_branch gpu_cc_ahb_clk
= {
106 .halt_check
= BRANCH_HALT_DELAY
,
108 .enable_reg
= 0x1078,
109 .enable_mask
= BIT(0),
110 .hw
.init
= &(struct clk_init_data
){
111 .name
= "gpu_cc_ahb_clk",
112 .ops
= &clk_branch2_ops
,
117 static struct clk_branch gpu_cc_crc_ahb_clk
= {
119 .halt_check
= BRANCH_HALT_VOTED
,
121 .enable_reg
= 0x107c,
122 .enable_mask
= BIT(0),
123 .hw
.init
= &(struct clk_init_data
){
124 .name
= "gpu_cc_crc_ahb_clk",
125 .ops
= &clk_branch2_ops
,
130 static struct clk_branch gpu_cc_cx_apb_clk
= {
132 .halt_check
= BRANCH_HALT_VOTED
,
134 .enable_reg
= 0x1088,
135 .enable_mask
= BIT(0),
136 .hw
.init
= &(struct clk_init_data
){
137 .name
= "gpu_cc_cx_apb_clk",
138 .ops
= &clk_branch2_ops
,
143 static struct clk_branch gpu_cc_cx_gmu_clk
= {
145 .halt_check
= BRANCH_HALT
,
147 .enable_reg
= 0x1098,
148 .enable_mask
= BIT(0),
149 .hw
.init
= &(struct clk_init_data
){
150 .name
= "gpu_cc_cx_gmu_clk",
151 .parent_data
= &(const struct clk_parent_data
){
152 .hw
= &gpu_cc_gmu_clk_src
.clkr
.hw
,
155 .flags
= CLK_SET_RATE_PARENT
,
156 .ops
= &clk_branch2_ops
,
161 static struct clk_branch gpu_cc_cx_snoc_dvm_clk
= {
163 .halt_check
= BRANCH_HALT_VOTED
,
165 .enable_reg
= 0x108c,
166 .enable_mask
= BIT(0),
167 .hw
.init
= &(struct clk_init_data
){
168 .name
= "gpu_cc_cx_snoc_dvm_clk",
169 .ops
= &clk_branch2_ops
,
174 static struct clk_branch gpu_cc_cxo_aon_clk
= {
176 .halt_check
= BRANCH_HALT_VOTED
,
178 .enable_reg
= 0x1004,
179 .enable_mask
= BIT(0),
180 .hw
.init
= &(struct clk_init_data
){
181 .name
= "gpu_cc_cxo_aon_clk",
182 .ops
= &clk_branch2_ops
,
187 static struct clk_branch gpu_cc_cxo_clk
= {
189 .halt_check
= BRANCH_HALT
,
191 .enable_reg
= 0x109c,
192 .enable_mask
= BIT(0),
193 .hw
.init
= &(struct clk_init_data
){
194 .name
= "gpu_cc_cxo_clk",
195 .ops
= &clk_branch2_ops
,
200 static struct clk_branch gpu_cc_gx_gmu_clk
= {
202 .halt_check
= BRANCH_HALT
,
204 .enable_reg
= 0x1064,
205 .enable_mask
= BIT(0),
206 .hw
.init
= &(struct clk_init_data
){
207 .name
= "gpu_cc_gx_gmu_clk",
208 .parent_data
= &(const struct clk_parent_data
){
209 .hw
= &gpu_cc_gmu_clk_src
.clkr
.hw
,
212 .flags
= CLK_SET_RATE_PARENT
,
213 .ops
= &clk_branch2_ops
,
218 static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk
= {
220 .halt_check
= BRANCH_VOTED
,
222 .enable_reg
= 0x5000,
223 .enable_mask
= BIT(0),
224 .hw
.init
= &(struct clk_init_data
){
225 .name
= "gpu_cc_hlos1_vote_gpu_smmu_clk",
226 .ops
= &clk_branch2_ops
,
231 static struct gdsc gpu_cx_gdsc
= {
233 .gds_hw_ctrl
= 0x1540,
235 .name
= "gpu_cx_gdsc",
237 .pwrsts
= PWRSTS_OFF_ON
,
241 static struct gdsc gpu_gx_gdsc
= {
243 .clamp_io_ctrl
= 0x1508,
245 .name
= "gpu_gx_gdsc",
246 .power_on
= gdsc_gx_do_nothing_enable
,
248 .pwrsts
= PWRSTS_OFF_ON
,
249 .flags
= CLAMP_IO
| AON_RESET
| POLL_CFG_GDSCR
,
252 static struct clk_regmap
*gpu_cc_sm8250_clocks
[] = {
253 [GPU_CC_AHB_CLK
] = &gpu_cc_ahb_clk
.clkr
,
254 [GPU_CC_CRC_AHB_CLK
] = &gpu_cc_crc_ahb_clk
.clkr
,
255 [GPU_CC_CX_APB_CLK
] = &gpu_cc_cx_apb_clk
.clkr
,
256 [GPU_CC_CX_GMU_CLK
] = &gpu_cc_cx_gmu_clk
.clkr
,
257 [GPU_CC_CX_SNOC_DVM_CLK
] = &gpu_cc_cx_snoc_dvm_clk
.clkr
,
258 [GPU_CC_CXO_AON_CLK
] = &gpu_cc_cxo_aon_clk
.clkr
,
259 [GPU_CC_CXO_CLK
] = &gpu_cc_cxo_clk
.clkr
,
260 [GPU_CC_GMU_CLK_SRC
] = &gpu_cc_gmu_clk_src
.clkr
,
261 [GPU_CC_GX_GMU_CLK
] = &gpu_cc_gx_gmu_clk
.clkr
,
262 [GPU_CC_PLL1
] = &gpu_cc_pll1
.clkr
,
263 [GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK
] = &gpu_cc_hlos1_vote_gpu_smmu_clk
.clkr
,
266 static const struct qcom_reset_map gpu_cc_sm8250_resets
[] = {
267 [GPUCC_GPU_CC_ACD_BCR
] = { 0x1160 },
268 [GPUCC_GPU_CC_CX_BCR
] = { 0x1068 },
269 [GPUCC_GPU_CC_GFX3D_AON_BCR
] = { 0x10a0 },
270 [GPUCC_GPU_CC_GMU_BCR
] = { 0x111c },
271 [GPUCC_GPU_CC_GX_BCR
] = { 0x1008 },
272 [GPUCC_GPU_CC_XO_BCR
] = { 0x1000 },
275 static struct gdsc
*gpu_cc_sm8250_gdscs
[] = {
276 [GPU_CX_GDSC
] = &gpu_cx_gdsc
,
277 [GPU_GX_GDSC
] = &gpu_gx_gdsc
,
280 static const struct regmap_config gpu_cc_sm8250_regmap_config
= {
284 .max_register
= 0x8008,
288 static const struct qcom_cc_desc gpu_cc_sm8250_desc
= {
289 .config
= &gpu_cc_sm8250_regmap_config
,
290 .clks
= gpu_cc_sm8250_clocks
,
291 .num_clks
= ARRAY_SIZE(gpu_cc_sm8250_clocks
),
292 .resets
= gpu_cc_sm8250_resets
,
293 .num_resets
= ARRAY_SIZE(gpu_cc_sm8250_resets
),
294 .gdscs
= gpu_cc_sm8250_gdscs
,
295 .num_gdscs
= ARRAY_SIZE(gpu_cc_sm8250_gdscs
),
298 static const struct of_device_id gpu_cc_sm8250_match_table
[] = {
299 { .compatible
= "qcom,sm8250-gpucc" },
302 MODULE_DEVICE_TABLE(of
, gpu_cc_sm8250_match_table
);
304 static int gpu_cc_sm8250_probe(struct platform_device
*pdev
)
306 struct regmap
*regmap
;
307 unsigned int value
, mask
;
309 regmap
= qcom_cc_map(pdev
, &gpu_cc_sm8250_desc
);
311 return PTR_ERR(regmap
);
313 clk_lucid_pll_configure(&gpu_cc_pll1
, regmap
, &gpu_cc_pll1_config
);
316 * Configure gpu_cc_cx_gmu_clk with recommended
317 * wakeup/sleep settings
319 mask
= CX_GMU_CBCR_WAKE_MASK
<< CX_GMU_CBCR_WAKE_SHIFT
;
320 mask
|= CX_GMU_CBCR_SLEEP_MASK
<< CX_GMU_CBCR_SLEEP_SHIFT
;
321 value
= 0xf << CX_GMU_CBCR_WAKE_SHIFT
| 0xf << CX_GMU_CBCR_SLEEP_SHIFT
;
322 regmap_update_bits(regmap
, 0x1098, mask
, value
);
324 return qcom_cc_really_probe(pdev
, &gpu_cc_sm8250_desc
, regmap
);
327 static struct platform_driver gpu_cc_sm8250_driver
= {
328 .probe
= gpu_cc_sm8250_probe
,
330 .name
= "sm8250-gpucc",
331 .of_match_table
= gpu_cc_sm8250_match_table
,
335 static int __init
gpu_cc_sm8250_init(void)
337 return platform_driver_register(&gpu_cc_sm8250_driver
);
339 subsys_initcall(gpu_cc_sm8250_init
);
341 static void __exit
gpu_cc_sm8250_exit(void)
343 platform_driver_unregister(&gpu_cc_sm8250_driver
);
345 module_exit(gpu_cc_sm8250_exit
);
347 MODULE_DESCRIPTION("QTI GPU_CC SM8250 Driver");
348 MODULE_LICENSE("GPL v2");