1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2019, 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-sc7180.h>
13 #include "clk-alpha-pll.h"
14 #include "clk-branch.h"
16 #include "clk-regmap.h"
20 #define CX_GMU_CBCR_SLEEP_MASK 0xF
21 #define CX_GMU_CBCR_SLEEP_SHIFT 4
22 #define CX_GMU_CBCR_WAKE_MASK 0xF
23 #define CX_GMU_CBCR_WAKE_SHIFT 8
29 P_GPU_CC_PLL1_OUT_MAIN
,
32 static const struct pll_vco fabia_vco
[] = {
33 { 249600000, 2000000000, 0 },
36 static struct clk_alpha_pll gpu_cc_pll1
= {
38 .vco_table
= fabia_vco
,
39 .num_vco
= ARRAY_SIZE(fabia_vco
),
40 .regs
= clk_alpha_pll_regs
[CLK_ALPHA_PLL_TYPE_FABIA
],
42 .hw
.init
= &(struct clk_init_data
){
43 .name
= "gpu_cc_pll1",
44 .parent_data
= &(const struct clk_parent_data
){
48 .ops
= &clk_alpha_pll_fabia_ops
,
53 static const struct parent_map gpu_cc_parent_map_0
[] = {
55 { P_GPU_CC_PLL1_OUT_MAIN
, 3 },
56 { P_GPLL0_OUT_MAIN
, 5 },
57 { P_GPLL0_OUT_MAIN_DIV
, 6 },
60 static const struct clk_parent_data gpu_cc_parent_data_0
[] = {
61 { .fw_name
= "bi_tcxo" },
62 { .hw
= &gpu_cc_pll1
.clkr
.hw
},
63 { .fw_name
= "gcc_gpu_gpll0_clk_src" },
64 { .fw_name
= "gcc_gpu_gpll0_div_clk_src" },
67 static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src
[] = {
68 F(19200000, P_BI_TCXO
, 1, 0, 0),
69 F(200000000, P_GPLL0_OUT_MAIN_DIV
, 1.5, 0, 0),
73 static struct clk_rcg2 gpu_cc_gmu_clk_src
= {
77 .parent_map
= gpu_cc_parent_map_0
,
78 .freq_tbl
= ftbl_gpu_cc_gmu_clk_src
,
79 .clkr
.hw
.init
= &(struct clk_init_data
){
80 .name
= "gpu_cc_gmu_clk_src",
81 .parent_data
= gpu_cc_parent_data_0
,
82 .num_parents
= ARRAY_SIZE(gpu_cc_parent_data_0
),
83 .flags
= CLK_SET_RATE_PARENT
,
84 .ops
= &clk_rcg2_shared_ops
,
88 static struct clk_branch gpu_cc_crc_ahb_clk
= {
90 .halt_check
= BRANCH_HALT_DELAY
,
93 .enable_mask
= BIT(0),
94 .hw
.init
= &(struct clk_init_data
){
95 .name
= "gpu_cc_crc_ahb_clk",
96 .ops
= &clk_branch2_ops
,
101 static struct clk_branch gpu_cc_cx_gmu_clk
= {
103 .halt_check
= BRANCH_HALT
,
105 .enable_reg
= 0x1098,
106 .enable_mask
= BIT(0),
107 .hw
.init
= &(struct clk_init_data
){
108 .name
= "gpu_cc_cx_gmu_clk",
109 .parent_hws
= (const struct clk_hw
*[]) {
110 &gpu_cc_gmu_clk_src
.clkr
.hw
,
113 .flags
= CLK_SET_RATE_PARENT
,
114 .ops
= &clk_branch2_ops
,
119 static struct clk_branch gpu_cc_cx_snoc_dvm_clk
= {
121 .halt_check
= BRANCH_HALT_DELAY
,
123 .enable_reg
= 0x108c,
124 .enable_mask
= BIT(0),
125 .hw
.init
= &(struct clk_init_data
){
126 .name
= "gpu_cc_cx_snoc_dvm_clk",
127 .ops
= &clk_branch2_ops
,
132 static struct clk_branch gpu_cc_cxo_aon_clk
= {
134 .halt_check
= BRANCH_HALT_DELAY
,
136 .enable_reg
= 0x1004,
137 .enable_mask
= BIT(0),
138 .hw
.init
= &(struct clk_init_data
){
139 .name
= "gpu_cc_cxo_aon_clk",
140 .ops
= &clk_branch2_ops
,
145 static struct clk_branch gpu_cc_cxo_clk
= {
147 .halt_check
= BRANCH_HALT
,
149 .enable_reg
= 0x109c,
150 .enable_mask
= BIT(0),
151 .hw
.init
= &(struct clk_init_data
){
152 .name
= "gpu_cc_cxo_clk",
153 .ops
= &clk_branch2_ops
,
158 static struct gdsc cx_gdsc
= {
160 .gds_hw_ctrl
= 0x1540,
161 .clk_dis_wait_val
= 8,
165 .pwrsts
= PWRSTS_OFF_ON
,
169 static struct gdsc gx_gdsc
= {
171 .clamp_io_ctrl
= 0x1508,
174 .power_on
= gdsc_gx_do_nothing_enable
,
176 .pwrsts
= PWRSTS_OFF_ON
,
180 static struct gdsc
*gpu_cc_sc7180_gdscs
[] = {
181 [CX_GDSC
] = &cx_gdsc
,
182 [GX_GDSC
] = &gx_gdsc
,
185 static struct clk_regmap
*gpu_cc_sc7180_clocks
[] = {
186 [GPU_CC_CXO_CLK
] = &gpu_cc_cxo_clk
.clkr
,
187 [GPU_CC_CRC_AHB_CLK
] = &gpu_cc_crc_ahb_clk
.clkr
,
188 [GPU_CC_CX_GMU_CLK
] = &gpu_cc_cx_gmu_clk
.clkr
,
189 [GPU_CC_CX_SNOC_DVM_CLK
] = &gpu_cc_cx_snoc_dvm_clk
.clkr
,
190 [GPU_CC_CXO_AON_CLK
] = &gpu_cc_cxo_aon_clk
.clkr
,
191 [GPU_CC_GMU_CLK_SRC
] = &gpu_cc_gmu_clk_src
.clkr
,
192 [GPU_CC_PLL1
] = &gpu_cc_pll1
.clkr
,
195 static const struct regmap_config gpu_cc_sc7180_regmap_config
= {
199 .max_register
= 0x8008,
203 static const struct qcom_cc_desc gpu_cc_sc7180_desc
= {
204 .config
= &gpu_cc_sc7180_regmap_config
,
205 .clks
= gpu_cc_sc7180_clocks
,
206 .num_clks
= ARRAY_SIZE(gpu_cc_sc7180_clocks
),
207 .gdscs
= gpu_cc_sc7180_gdscs
,
208 .num_gdscs
= ARRAY_SIZE(gpu_cc_sc7180_gdscs
),
211 static const struct of_device_id gpu_cc_sc7180_match_table
[] = {
212 { .compatible
= "qcom,sc7180-gpucc" },
215 MODULE_DEVICE_TABLE(of
, gpu_cc_sc7180_match_table
);
217 static int gpu_cc_sc7180_probe(struct platform_device
*pdev
)
219 struct regmap
*regmap
;
220 struct alpha_pll_config gpu_cc_pll_config
= {};
221 unsigned int value
, mask
;
223 regmap
= qcom_cc_map(pdev
, &gpu_cc_sc7180_desc
);
225 return PTR_ERR(regmap
);
227 /* 360MHz Configuration */
228 gpu_cc_pll_config
.l
= 0x12;
229 gpu_cc_pll_config
.alpha
= 0xc000;
230 gpu_cc_pll_config
.config_ctl_val
= 0x20485699;
231 gpu_cc_pll_config
.config_ctl_hi_val
= 0x00002067;
232 gpu_cc_pll_config
.user_ctl_val
= 0x00000001;
233 gpu_cc_pll_config
.user_ctl_hi_val
= 0x00004805;
234 gpu_cc_pll_config
.test_ctl_hi_val
= 0x40000000;
236 clk_fabia_pll_configure(&gpu_cc_pll1
, regmap
, &gpu_cc_pll_config
);
238 /* Recommended WAKEUP/SLEEP settings for the gpu_cc_cx_gmu_clk */
239 mask
= CX_GMU_CBCR_WAKE_MASK
<< CX_GMU_CBCR_WAKE_SHIFT
;
240 mask
|= CX_GMU_CBCR_SLEEP_MASK
<< CX_GMU_CBCR_SLEEP_SHIFT
;
241 value
= 0xF << CX_GMU_CBCR_WAKE_SHIFT
| 0xF << CX_GMU_CBCR_SLEEP_SHIFT
;
242 regmap_update_bits(regmap
, 0x1098, mask
, value
);
244 return qcom_cc_really_probe(&pdev
->dev
, &gpu_cc_sc7180_desc
, regmap
);
247 static struct platform_driver gpu_cc_sc7180_driver
= {
248 .probe
= gpu_cc_sc7180_probe
,
250 .name
= "sc7180-gpucc",
251 .of_match_table
= gpu_cc_sc7180_match_table
,
255 module_platform_driver(gpu_cc_sc7180_driver
);
257 MODULE_DESCRIPTION("QTI GPU_CC SC7180 Driver");
258 MODULE_LICENSE("GPL v2");