1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2018, 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-sdm845.h>
14 #include "clk-alpha-pll.h"
15 #include "clk-branch.h"
18 #include "clk-regmap.h"
21 #define CX_GMU_CBCR_SLEEP_MASK 0xf
22 #define CX_GMU_CBCR_SLEEP_SHIFT 4
23 #define CX_GMU_CBCR_WAKE_MASK 0xf
24 #define CX_GMU_CBCR_WAKE_SHIFT 8
25 #define CLK_DIS_WAIT_SHIFT 12
26 #define CLK_DIS_WAIT_MASK (0xf << CLK_DIS_WAIT_SHIFT)
30 P_CORE_BI_PLL_TEST_SE
,
33 P_GPU_CC_PLL1_OUT_EVEN
,
34 P_GPU_CC_PLL1_OUT_MAIN
,
35 P_GPU_CC_PLL1_OUT_ODD
,
38 static const struct parent_map gpu_cc_parent_map_0
[] = {
40 { P_GPU_CC_PLL1_OUT_MAIN
, 3 },
41 { P_GPLL0_OUT_MAIN
, 5 },
42 { P_GPLL0_OUT_MAIN_DIV
, 6 },
43 { P_CORE_BI_PLL_TEST_SE
, 7 },
46 static const char * const gpu_cc_parent_names_0
[] = {
49 "gcc_gpu_gpll0_clk_src",
50 "gcc_gpu_gpll0_div_clk_src",
51 "core_bi_pll_test_se",
54 static const struct alpha_pll_config gpu_cc_pll1_config
= {
59 static struct clk_alpha_pll gpu_cc_pll1
= {
61 .regs
= clk_alpha_pll_regs
[CLK_ALPHA_PLL_TYPE_FABIA
],
63 .hw
.init
= &(struct clk_init_data
){
64 .name
= "gpu_cc_pll1",
65 .parent_names
= (const char *[]){ "bi_tcxo" },
67 .ops
= &clk_alpha_pll_fabia_ops
,
72 static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src
[] = {
73 F(19200000, P_BI_TCXO
, 1, 0, 0),
74 F(200000000, P_GPLL0_OUT_MAIN_DIV
, 1.5, 0, 0),
75 F(500000000, P_GPU_CC_PLL1_OUT_MAIN
, 1, 0, 0),
79 static struct clk_rcg2 gpu_cc_gmu_clk_src
= {
83 .parent_map
= gpu_cc_parent_map_0
,
84 .freq_tbl
= ftbl_gpu_cc_gmu_clk_src
,
85 .clkr
.hw
.init
= &(struct clk_init_data
){
86 .name
= "gpu_cc_gmu_clk_src",
87 .parent_names
= gpu_cc_parent_names_0
,
89 .ops
= &clk_rcg2_shared_ops
,
93 static struct clk_branch gpu_cc_cx_gmu_clk
= {
95 .halt_check
= BRANCH_HALT
,
98 .enable_mask
= BIT(0),
99 .hw
.init
= &(struct clk_init_data
){
100 .name
= "gpu_cc_cx_gmu_clk",
101 .parent_names
= (const char *[]){
102 "gpu_cc_gmu_clk_src",
105 .flags
= CLK_SET_RATE_PARENT
,
106 .ops
= &clk_branch2_ops
,
111 static struct clk_branch gpu_cc_cxo_clk
= {
113 .halt_check
= BRANCH_HALT
,
115 .enable_reg
= 0x109c,
116 .enable_mask
= BIT(0),
117 .hw
.init
= &(struct clk_init_data
){
118 .name
= "gpu_cc_cxo_clk",
119 .ops
= &clk_branch2_ops
,
124 static struct gdsc gpu_cx_gdsc
= {
126 .gds_hw_ctrl
= 0x1540,
128 .name
= "gpu_cx_gdsc",
130 .pwrsts
= PWRSTS_OFF_ON
,
134 static struct gdsc gpu_gx_gdsc
= {
136 .clamp_io_ctrl
= 0x1508,
138 .name
= "gpu_gx_gdsc",
139 .power_on
= gdsc_gx_do_nothing_enable
,
141 .pwrsts
= PWRSTS_OFF_ON
,
142 .flags
= CLAMP_IO
| AON_RESET
| POLL_CFG_GDSCR
,
145 static struct clk_regmap
*gpu_cc_sdm845_clocks
[] = {
146 [GPU_CC_CXO_CLK
] = &gpu_cc_cxo_clk
.clkr
,
147 [GPU_CC_CX_GMU_CLK
] = &gpu_cc_cx_gmu_clk
.clkr
,
148 [GPU_CC_GMU_CLK_SRC
] = &gpu_cc_gmu_clk_src
.clkr
,
149 [GPU_CC_PLL1
] = &gpu_cc_pll1
.clkr
,
152 static struct gdsc
*gpu_cc_sdm845_gdscs
[] = {
153 [GPU_CX_GDSC
] = &gpu_cx_gdsc
,
154 [GPU_GX_GDSC
] = &gpu_gx_gdsc
,
157 static const struct regmap_config gpu_cc_sdm845_regmap_config
= {
161 .max_register
= 0x8008,
165 static const struct qcom_cc_desc gpu_cc_sdm845_desc
= {
166 .config
= &gpu_cc_sdm845_regmap_config
,
167 .clks
= gpu_cc_sdm845_clocks
,
168 .num_clks
= ARRAY_SIZE(gpu_cc_sdm845_clocks
),
169 .gdscs
= gpu_cc_sdm845_gdscs
,
170 .num_gdscs
= ARRAY_SIZE(gpu_cc_sdm845_gdscs
),
173 static const struct of_device_id gpu_cc_sdm845_match_table
[] = {
174 { .compatible
= "qcom,sdm845-gpucc" },
177 MODULE_DEVICE_TABLE(of
, gpu_cc_sdm845_match_table
);
179 static int gpu_cc_sdm845_probe(struct platform_device
*pdev
)
181 struct regmap
*regmap
;
182 unsigned int value
, mask
;
184 regmap
= qcom_cc_map(pdev
, &gpu_cc_sdm845_desc
);
186 return PTR_ERR(regmap
);
188 clk_fabia_pll_configure(&gpu_cc_pll1
, regmap
, &gpu_cc_pll1_config
);
191 * Configure gpu_cc_cx_gmu_clk with recommended
192 * wakeup/sleep settings
194 mask
= CX_GMU_CBCR_WAKE_MASK
<< CX_GMU_CBCR_WAKE_SHIFT
;
195 mask
|= CX_GMU_CBCR_SLEEP_MASK
<< CX_GMU_CBCR_SLEEP_SHIFT
;
196 value
= 0xf << CX_GMU_CBCR_WAKE_SHIFT
| 0xf << CX_GMU_CBCR_SLEEP_SHIFT
;
197 regmap_update_bits(regmap
, 0x1098, mask
, value
);
199 /* Configure clk_dis_wait for gpu_cx_gdsc */
200 regmap_update_bits(regmap
, 0x106c, CLK_DIS_WAIT_MASK
,
201 8 << CLK_DIS_WAIT_SHIFT
);
203 return qcom_cc_really_probe(pdev
, &gpu_cc_sdm845_desc
, regmap
);
206 static struct platform_driver gpu_cc_sdm845_driver
= {
207 .probe
= gpu_cc_sdm845_probe
,
209 .name
= "sdm845-gpucc",
210 .of_match_table
= gpu_cc_sdm845_match_table
,
214 static int __init
gpu_cc_sdm845_init(void)
216 return platform_driver_register(&gpu_cc_sdm845_driver
);
218 subsys_initcall(gpu_cc_sdm845_init
);
220 static void __exit
gpu_cc_sdm845_exit(void)
222 platform_driver_unregister(&gpu_cc_sdm845_driver
);
224 module_exit(gpu_cc_sdm845_exit
);
226 MODULE_DESCRIPTION("QTI GPUCC SDM845 Driver");
227 MODULE_LICENSE("GPL v2");