1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2020, The Linux Foundation. All rights reserved.
4 * Copyright (c) 2020, AngeloGioacchino Del Regno
5 * <angelogioacchino.delregno@somainline.org>
8 #include <linux/bitops.h>
10 #include <linux/clk-provider.h>
11 #include <linux/err.h>
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/platform_device.h>
16 #include <linux/regmap.h>
17 #include <linux/reset-controller.h>
18 #include <dt-bindings/clock/qcom,gpucc-sdm660.h>
20 #include "clk-alpha-pll.h"
22 #include "clk-regmap.h"
25 #include "clk-branch.h"
33 P_GPU_PLL0_PLL_OUT_MAIN
,
34 P_GPU_PLL1_PLL_OUT_MAIN
,
37 static struct clk_branch gpucc_cxo_clk
= {
41 .enable_mask
= BIT(0),
42 .hw
.init
= &(struct clk_init_data
){
43 .name
= "gpucc_cxo_clk",
44 .parent_data
= &(const struct clk_parent_data
){
48 .ops
= &clk_branch2_ops
,
49 .flags
= CLK_IS_CRITICAL
,
54 static const struct pll_vco gpu_vco
[] = {
55 { 1000000000, 2000000000, 0 },
56 { 500000000, 1000000000, 2 },
57 { 250000000, 500000000, 3 },
60 static struct clk_alpha_pll gpu_pll0_pll_out_main
= {
62 .regs
= clk_alpha_pll_regs
[CLK_ALPHA_PLL_TYPE_DEFAULT
],
64 .num_vco
= ARRAY_SIZE(gpu_vco
),
65 .clkr
.hw
.init
= &(struct clk_init_data
){
66 .name
= "gpu_pll0_pll_out_main",
67 .parent_hws
= (const struct clk_hw
*[]){
68 &gpucc_cxo_clk
.clkr
.hw
,
71 .ops
= &clk_alpha_pll_ops
,
75 static struct clk_alpha_pll gpu_pll1_pll_out_main
= {
77 .regs
= clk_alpha_pll_regs
[CLK_ALPHA_PLL_TYPE_DEFAULT
],
79 .num_vco
= ARRAY_SIZE(gpu_vco
),
80 .clkr
.hw
.init
= &(struct clk_init_data
){
81 .name
= "gpu_pll1_pll_out_main",
82 .parent_hws
= (const struct clk_hw
*[]){
83 &gpucc_cxo_clk
.clkr
.hw
,
86 .ops
= &clk_alpha_pll_ops
,
90 static const struct parent_map gpucc_parent_map_1
[] = {
92 { P_GPU_PLL0_PLL_OUT_MAIN
, 1 },
93 { P_GPU_PLL1_PLL_OUT_MAIN
, 3 },
94 { P_GPLL0_OUT_MAIN
, 5 },
97 static const struct clk_parent_data gpucc_parent_data_1
[] = {
98 { .hw
= &gpucc_cxo_clk
.clkr
.hw
},
99 { .hw
= &gpu_pll0_pll_out_main
.clkr
.hw
},
100 { .hw
= &gpu_pll1_pll_out_main
.clkr
.hw
},
101 { .fw_name
= "gcc_gpu_gpll0_clk" },
104 static struct clk_rcg2_gfx3d gfx3d_clk_src
= {
110 .parent_map
= gpucc_parent_map_1
,
111 .clkr
.hw
.init
= &(struct clk_init_data
){
112 .name
= "gfx3d_clk_src",
113 .parent_data
= gpucc_parent_data_1
,
114 .num_parents
= ARRAY_SIZE(gpucc_parent_data_1
),
115 .ops
= &clk_gfx3d_ops
,
116 .flags
= CLK_SET_RATE_PARENT
| CLK_OPS_PARENT_ENABLE
,
119 .hws
= (struct clk_hw
*[]){
120 &gpucc_cxo_clk
.clkr
.hw
,
121 &gpu_pll0_pll_out_main
.clkr
.hw
,
122 &gpu_pll1_pll_out_main
.clkr
.hw
,
126 static struct clk_branch gpucc_gfx3d_clk
= {
128 .halt_check
= BRANCH_HALT
,
132 .enable_reg
= 0x1098,
133 .enable_mask
= BIT(0),
134 .hw
.init
= &(struct clk_init_data
){
135 .name
= "gpucc_gfx3d_clk",
136 .parent_hws
= (const struct clk_hw
*[]){
137 &gfx3d_clk_src
.rcg
.clkr
.hw
,
140 .ops
= &clk_branch2_ops
,
141 .flags
= CLK_SET_RATE_PARENT
,
146 static const struct parent_map gpucc_parent_map_0
[] = {
148 { P_GPLL0_OUT_MAIN
, 5 },
149 { P_GPLL0_OUT_MAIN_DIV
, 6 },
152 static const struct clk_parent_data gpucc_parent_data_0
[] = {
153 { .hw
= &gpucc_cxo_clk
.clkr
.hw
},
154 { .fw_name
= "gcc_gpu_gpll0_clk" },
155 { .fw_name
= "gcc_gpu_gpll0_div_clk" },
158 static const struct freq_tbl ftbl_rbbmtimer_clk_src
[] = {
159 F(19200000, P_GPU_XO
, 1, 0, 0),
163 static struct clk_rcg2 rbbmtimer_clk_src
= {
167 .parent_map
= gpucc_parent_map_0
,
168 .freq_tbl
= ftbl_rbbmtimer_clk_src
,
169 .clkr
.hw
.init
= &(struct clk_init_data
){
170 .name
= "rbbmtimer_clk_src",
171 .parent_data
= gpucc_parent_data_0
,
172 .num_parents
= ARRAY_SIZE(gpucc_parent_data_0
),
173 .ops
= &clk_rcg2_ops
,
177 static const struct freq_tbl ftbl_rbcpr_clk_src
[] = {
178 F(19200000, P_GPU_XO
, 1, 0, 0),
179 F(50000000, P_GPLL0_OUT_MAIN_DIV
, 6, 0, 0),
183 static struct clk_rcg2 rbcpr_clk_src
= {
187 .parent_map
= gpucc_parent_map_0
,
188 .freq_tbl
= ftbl_rbcpr_clk_src
,
189 .clkr
.hw
.init
= &(struct clk_init_data
){
190 .name
= "rbcpr_clk_src",
191 .parent_data
= gpucc_parent_data_0
,
192 .num_parents
= ARRAY_SIZE(gpucc_parent_data_0
),
193 .ops
= &clk_rcg2_ops
,
197 static struct clk_branch gpucc_rbbmtimer_clk
= {
199 .halt_check
= BRANCH_HALT
,
201 .enable_reg
= 0x10d0,
202 .enable_mask
= BIT(0),
203 .hw
.init
= &(struct clk_init_data
){
204 .name
= "gpucc_rbbmtimer_clk",
205 .parent_hws
= (const struct clk_hw
*[]){
206 &rbbmtimer_clk_src
.clkr
.hw
,
209 .flags
= CLK_SET_RATE_PARENT
,
210 .ops
= &clk_branch2_ops
,
215 static struct clk_branch gpucc_rbcpr_clk
= {
217 .halt_check
= BRANCH_HALT
,
219 .enable_reg
= 0x1054,
220 .enable_mask
= BIT(0),
221 .hw
.init
= &(struct clk_init_data
){
222 .name
= "gpucc_rbcpr_clk",
223 .parent_hws
= (const struct clk_hw
*[]){
224 &rbcpr_clk_src
.clkr
.hw
,
227 .flags
= CLK_SET_RATE_PARENT
,
228 .ops
= &clk_branch2_ops
,
233 static struct gdsc gpu_cx_gdsc
= {
235 .gds_hw_ctrl
= 0x1008,
239 .pwrsts
= PWRSTS_OFF_ON
,
243 static struct gdsc gpu_gx_gdsc
= {
245 .clamp_io_ctrl
= 0x130,
246 .resets
= (unsigned int []){ GPU_GX_BCR
},
248 .cxcs
= (unsigned int []){ 0x1098 },
253 .parent
= &gpu_cx_gdsc
.pd
,
254 .pwrsts
= PWRSTS_OFF
| PWRSTS_ON
| PWRSTS_RET
,
255 .flags
= CLAMP_IO
| SW_RESET
| AON_RESET
| NO_RET_PERIPH
,
258 static struct gdsc
*gpucc_sdm660_gdscs
[] = {
259 [GPU_CX_GDSC
] = &gpu_cx_gdsc
,
260 [GPU_GX_GDSC
] = &gpu_gx_gdsc
,
263 static const struct qcom_reset_map gpucc_sdm660_resets
[] = {
264 [GPU_CX_BCR
] = { 0x1000 },
265 [RBCPR_BCR
] = { 0x1050 },
266 [GPU_GX_BCR
] = { 0x1090 },
267 [SPDM_BCR
] = { 0x10E0 },
270 static struct clk_regmap
*gpucc_sdm660_clocks
[] = {
271 [GPUCC_CXO_CLK
] = &gpucc_cxo_clk
.clkr
,
272 [GPU_PLL0_PLL
] = &gpu_pll0_pll_out_main
.clkr
,
273 [GPU_PLL1_PLL
] = &gpu_pll1_pll_out_main
.clkr
,
274 [GFX3D_CLK_SRC
] = &gfx3d_clk_src
.rcg
.clkr
,
275 [RBCPR_CLK_SRC
] = &rbcpr_clk_src
.clkr
,
276 [RBBMTIMER_CLK_SRC
] = &rbbmtimer_clk_src
.clkr
,
277 [GPUCC_RBCPR_CLK
] = &gpucc_rbcpr_clk
.clkr
,
278 [GPUCC_GFX3D_CLK
] = &gpucc_gfx3d_clk
.clkr
,
279 [GPUCC_RBBMTIMER_CLK
] = &gpucc_rbbmtimer_clk
.clkr
,
282 static const struct regmap_config gpucc_660_regmap_config
= {
286 .max_register
= 0x9034,
290 static const struct qcom_cc_desc gpucc_sdm660_desc
= {
291 .config
= &gpucc_660_regmap_config
,
292 .clks
= gpucc_sdm660_clocks
,
293 .num_clks
= ARRAY_SIZE(gpucc_sdm660_clocks
),
294 .resets
= gpucc_sdm660_resets
,
295 .num_resets
= ARRAY_SIZE(gpucc_sdm660_resets
),
296 .gdscs
= gpucc_sdm660_gdscs
,
297 .num_gdscs
= ARRAY_SIZE(gpucc_sdm660_gdscs
),
300 static const struct of_device_id gpucc_sdm660_match_table
[] = {
301 { .compatible
= "qcom,gpucc-sdm660" },
302 { .compatible
= "qcom,gpucc-sdm630" },
305 MODULE_DEVICE_TABLE(of
, gpucc_sdm660_match_table
);
307 static int gpucc_sdm660_probe(struct platform_device
*pdev
)
309 struct regmap
*regmap
;
310 struct alpha_pll_config gpu_pll_config
= {
311 .config_ctl_val
= 0x4001055b,
313 .alpha_en_mask
= BIT(24),
314 .vco_val
= 0x2 << 20,
315 .vco_mask
= 0x3 << 20,
316 .main_output_mask
= 0x1,
319 regmap
= qcom_cc_map(pdev
, &gpucc_sdm660_desc
);
321 return PTR_ERR(regmap
);
323 /* 800MHz configuration for GPU PLL0 */
324 gpu_pll_config
.l
= 0x29;
325 gpu_pll_config
.alpha_hi
= 0xaa;
326 clk_alpha_pll_configure(&gpu_pll0_pll_out_main
, regmap
, &gpu_pll_config
);
328 /* 740MHz configuration for GPU PLL1 */
329 gpu_pll_config
.l
= 0x26;
330 gpu_pll_config
.alpha_hi
= 0x8a;
331 clk_alpha_pll_configure(&gpu_pll1_pll_out_main
, regmap
, &gpu_pll_config
);
333 return qcom_cc_really_probe(&pdev
->dev
, &gpucc_sdm660_desc
, regmap
);
336 static struct platform_driver gpucc_sdm660_driver
= {
337 .probe
= gpucc_sdm660_probe
,
339 .name
= "gpucc-sdm660",
340 .of_match_table
= gpucc_sdm660_match_table
,
343 module_platform_driver(gpucc_sdm660_driver
);
345 MODULE_DESCRIPTION("Qualcomm SDM630/SDM660 GPUCC Driver");
346 MODULE_LICENSE("GPL v2");