GNU Linux-libre 6.7.9-gnu
[releases.git] / drivers / clk / qcom / gpucc-sm8250.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
4  */
5
6 #include <linux/clk-provider.h>
7 #include <linux/module.h>
8 #include <linux/platform_device.h>
9 #include <linux/regmap.h>
10
11 #include <dt-bindings/clock/qcom,gpucc-sm8250.h>
12
13 #include "common.h"
14 #include "clk-alpha-pll.h"
15 #include "clk-branch.h"
16 #include "clk-pll.h"
17 #include "clk-rcg.h"
18 #include "clk-regmap.h"
19 #include "reset.h"
20 #include "gdsc.h"
21
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
26
27 enum {
28         P_BI_TCXO,
29         P_GPLL0_OUT_MAIN,
30         P_GPLL0_OUT_MAIN_DIV,
31         P_GPU_CC_PLL0_OUT_MAIN,
32         P_GPU_CC_PLL1_OUT_MAIN,
33 };
34
35 static struct pll_vco lucid_vco[] = {
36         { 249600000, 2000000000, 0 },
37 };
38
39 static const struct alpha_pll_config gpu_cc_pll1_config = {
40         .l = 0x1a,
41         .alpha = 0xaaa,
42         .config_ctl_val = 0x20485699,
43         .config_ctl_hi_val = 0x00002261,
44         .config_ctl_hi1_val = 0x029a699c,
45         .user_ctl_val = 0x00000000,
46         .user_ctl_hi_val = 0x00000805,
47         .user_ctl_hi1_val = 0x00000000,
48 };
49
50 static struct clk_alpha_pll gpu_cc_pll1 = {
51         .offset = 0x100,
52         .vco_table = lucid_vco,
53         .num_vco = ARRAY_SIZE(lucid_vco),
54         .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
55         .clkr = {
56                 .hw.init = &(struct clk_init_data){
57                         .name = "gpu_cc_pll1",
58                         .parent_data =  &(const struct clk_parent_data){
59                                 .fw_name = "bi_tcxo",
60                         },
61                         .num_parents = 1,
62                         .ops = &clk_alpha_pll_lucid_ops,
63                 },
64         },
65 };
66
67 static const struct parent_map gpu_cc_parent_map_0[] = {
68         { P_BI_TCXO, 0 },
69         { P_GPU_CC_PLL1_OUT_MAIN, 3 },
70         { P_GPLL0_OUT_MAIN, 5 },
71         { P_GPLL0_OUT_MAIN_DIV, 6 },
72 };
73
74 static const struct clk_parent_data gpu_cc_parent_data_0[] = {
75         { .fw_name = "bi_tcxo" },
76         { .hw = &gpu_cc_pll1.clkr.hw },
77         { .fw_name = "gcc_gpu_gpll0_clk_src" },
78         { .fw_name = "gcc_gpu_gpll0_div_clk_src" },
79 };
80
81 static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = {
82         F(19200000, P_BI_TCXO, 1, 0, 0),
83         F(200000000, P_GPLL0_OUT_MAIN_DIV, 1.5, 0, 0),
84         F(500000000, P_GPU_CC_PLL1_OUT_MAIN, 1, 0, 0),
85         { }
86 };
87
88 static struct clk_rcg2 gpu_cc_gmu_clk_src = {
89         .cmd_rcgr = 0x1120,
90         .mnd_width = 0,
91         .hid_width = 5,
92         .parent_map = gpu_cc_parent_map_0,
93         .freq_tbl = ftbl_gpu_cc_gmu_clk_src,
94         .clkr.hw.init = &(struct clk_init_data){
95                 .name = "gpu_cc_gmu_clk_src",
96                 .parent_data = gpu_cc_parent_data_0,
97                 .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0),
98                 .flags = CLK_SET_RATE_PARENT,
99                 .ops = &clk_rcg2_ops,
100         },
101 };
102
103 static struct clk_branch gpu_cc_ahb_clk = {
104         .halt_reg = 0x1078,
105         .halt_check = BRANCH_HALT_DELAY,
106         .clkr = {
107                 .enable_reg = 0x1078,
108                 .enable_mask = BIT(0),
109                 .hw.init = &(struct clk_init_data){
110                         .name = "gpu_cc_ahb_clk",
111                         .ops = &clk_branch2_ops,
112                 },
113         },
114 };
115
116 static struct clk_branch gpu_cc_crc_ahb_clk = {
117         .halt_reg = 0x107c,
118         .halt_check = BRANCH_HALT_VOTED,
119         .clkr = {
120                 .enable_reg = 0x107c,
121                 .enable_mask = BIT(0),
122                 .hw.init = &(struct clk_init_data){
123                         .name = "gpu_cc_crc_ahb_clk",
124                         .ops = &clk_branch2_ops,
125                 },
126         },
127 };
128
129 static struct clk_branch gpu_cc_cx_apb_clk = {
130         .halt_reg = 0x1088,
131         .halt_check = BRANCH_HALT_VOTED,
132         .clkr = {
133                 .enable_reg = 0x1088,
134                 .enable_mask = BIT(0),
135                 .hw.init = &(struct clk_init_data){
136                         .name = "gpu_cc_cx_apb_clk",
137                         .ops = &clk_branch2_ops,
138                 },
139         },
140 };
141
142 static struct clk_branch gpu_cc_cx_gmu_clk = {
143         .halt_reg = 0x1098,
144         .halt_check = BRANCH_HALT,
145         .clkr = {
146                 .enable_reg = 0x1098,
147                 .enable_mask = BIT(0),
148                 .hw.init = &(struct clk_init_data){
149                         .name = "gpu_cc_cx_gmu_clk",
150                         .parent_hws = (const struct clk_hw*[]){
151                                 &gpu_cc_gmu_clk_src.clkr.hw,
152                         },
153                         .num_parents = 1,
154                         .flags = CLK_SET_RATE_PARENT,
155                         .ops = &clk_branch2_ops,
156                 },
157         },
158 };
159
160 static struct clk_branch gpu_cc_cx_snoc_dvm_clk = {
161         .halt_reg = 0x108c,
162         .halt_check = BRANCH_HALT_VOTED,
163         .clkr = {
164                 .enable_reg = 0x108c,
165                 .enable_mask = BIT(0),
166                 .hw.init = &(struct clk_init_data){
167                         .name = "gpu_cc_cx_snoc_dvm_clk",
168                         .ops = &clk_branch2_ops,
169                 },
170         },
171 };
172
173 static struct clk_branch gpu_cc_cxo_aon_clk = {
174         .halt_reg = 0x1004,
175         .halt_check = BRANCH_HALT_VOTED,
176         .clkr = {
177                 .enable_reg = 0x1004,
178                 .enable_mask = BIT(0),
179                 .hw.init = &(struct clk_init_data){
180                         .name = "gpu_cc_cxo_aon_clk",
181                         .ops = &clk_branch2_ops,
182                 },
183         },
184 };
185
186 static struct clk_branch gpu_cc_cxo_clk = {
187         .halt_reg = 0x109c,
188         .halt_check = BRANCH_HALT,
189         .clkr = {
190                 .enable_reg = 0x109c,
191                 .enable_mask = BIT(0),
192                 .hw.init = &(struct clk_init_data){
193                         .name = "gpu_cc_cxo_clk",
194                         .ops = &clk_branch2_ops,
195                 },
196         },
197 };
198
199 static struct clk_branch gpu_cc_gx_gmu_clk = {
200         .halt_reg = 0x1064,
201         .halt_check = BRANCH_HALT,
202         .clkr = {
203                 .enable_reg = 0x1064,
204                 .enable_mask = BIT(0),
205                 .hw.init = &(struct clk_init_data){
206                         .name = "gpu_cc_gx_gmu_clk",
207                         .parent_hws = (const struct clk_hw*[]){
208                                 &gpu_cc_gmu_clk_src.clkr.hw,
209                         },
210                         .num_parents = 1,
211                         .flags = CLK_SET_RATE_PARENT,
212                         .ops = &clk_branch2_ops,
213                 },
214         },
215 };
216
217 static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk = {
218         .halt_reg = 0x5000,
219         .halt_check = BRANCH_VOTED,
220         .clkr = {
221                 .enable_reg = 0x5000,
222                 .enable_mask = BIT(0),
223                 .hw.init = &(struct clk_init_data){
224                          .name = "gpu_cc_hlos1_vote_gpu_smmu_clk",
225                          .ops = &clk_branch2_ops,
226                 },
227         },
228 };
229
230 static struct gdsc gpu_cx_gdsc = {
231         .gdscr = 0x106c,
232         .gds_hw_ctrl = 0x1540,
233         .pd = {
234                 .name = "gpu_cx_gdsc",
235         },
236         .pwrsts = PWRSTS_OFF_ON,
237         .flags = VOTABLE,
238 };
239
240 static struct gdsc gpu_gx_gdsc = {
241         .gdscr = 0x100c,
242         .clamp_io_ctrl = 0x1508,
243         .pd = {
244                 .name = "gpu_gx_gdsc",
245                 .power_on = gdsc_gx_do_nothing_enable,
246         },
247         .pwrsts = PWRSTS_OFF_ON,
248         .flags = CLAMP_IO | AON_RESET | POLL_CFG_GDSCR,
249 };
250
251 static struct clk_regmap *gpu_cc_sm8250_clocks[] = {
252         [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr,
253         [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr,
254         [GPU_CC_CX_APB_CLK] = &gpu_cc_cx_apb_clk.clkr,
255         [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr,
256         [GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_clk.clkr,
257         [GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr,
258         [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr,
259         [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr,
260         [GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr,
261         [GPU_CC_PLL1] = &gpu_cc_pll1.clkr,
262         [GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK] = &gpu_cc_hlos1_vote_gpu_smmu_clk.clkr,
263 };
264
265 static const struct qcom_reset_map gpu_cc_sm8250_resets[] = {
266         [GPUCC_GPU_CC_ACD_BCR] = { 0x1160 },
267         [GPUCC_GPU_CC_CX_BCR] = { 0x1068 },
268         [GPUCC_GPU_CC_GFX3D_AON_BCR] = { 0x10a0 },
269         [GPUCC_GPU_CC_GMU_BCR] = { 0x111c },
270         [GPUCC_GPU_CC_GX_BCR] = { 0x1008 },
271         [GPUCC_GPU_CC_XO_BCR] = { 0x1000 },
272 };
273
274 static struct gdsc *gpu_cc_sm8250_gdscs[] = {
275         [GPU_CX_GDSC] = &gpu_cx_gdsc,
276         [GPU_GX_GDSC] = &gpu_gx_gdsc,
277 };
278
279 static const struct regmap_config gpu_cc_sm8250_regmap_config = {
280         .reg_bits = 32,
281         .reg_stride = 4,
282         .val_bits = 32,
283         .max_register = 0x8008,
284         .fast_io = true,
285 };
286
287 static const struct qcom_cc_desc gpu_cc_sm8250_desc = {
288         .config = &gpu_cc_sm8250_regmap_config,
289         .clks = gpu_cc_sm8250_clocks,
290         .num_clks = ARRAY_SIZE(gpu_cc_sm8250_clocks),
291         .resets = gpu_cc_sm8250_resets,
292         .num_resets = ARRAY_SIZE(gpu_cc_sm8250_resets),
293         .gdscs = gpu_cc_sm8250_gdscs,
294         .num_gdscs = ARRAY_SIZE(gpu_cc_sm8250_gdscs),
295 };
296
297 static const struct of_device_id gpu_cc_sm8250_match_table[] = {
298         { .compatible = "qcom,sm8250-gpucc" },
299         { }
300 };
301 MODULE_DEVICE_TABLE(of, gpu_cc_sm8250_match_table);
302
303 static int gpu_cc_sm8250_probe(struct platform_device *pdev)
304 {
305         struct regmap *regmap;
306         unsigned int value, mask;
307
308         regmap = qcom_cc_map(pdev, &gpu_cc_sm8250_desc);
309         if (IS_ERR(regmap))
310                 return PTR_ERR(regmap);
311
312         clk_lucid_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config);
313
314         /*
315          * Configure gpu_cc_cx_gmu_clk with recommended
316          * wakeup/sleep settings
317          */
318         mask = CX_GMU_CBCR_WAKE_MASK << CX_GMU_CBCR_WAKE_SHIFT;
319         mask |= CX_GMU_CBCR_SLEEP_MASK << CX_GMU_CBCR_SLEEP_SHIFT;
320         value = 0xf << CX_GMU_CBCR_WAKE_SHIFT | 0xf << CX_GMU_CBCR_SLEEP_SHIFT;
321         regmap_update_bits(regmap, 0x1098, mask, value);
322
323         return qcom_cc_really_probe(pdev, &gpu_cc_sm8250_desc, regmap);
324 }
325
326 static struct platform_driver gpu_cc_sm8250_driver = {
327         .probe = gpu_cc_sm8250_probe,
328         .driver = {
329                 .name = "sm8250-gpucc",
330                 .of_match_table = gpu_cc_sm8250_match_table,
331         },
332 };
333
334 static int __init gpu_cc_sm8250_init(void)
335 {
336         return platform_driver_register(&gpu_cc_sm8250_driver);
337 }
338 subsys_initcall(gpu_cc_sm8250_init);
339
340 static void __exit gpu_cc_sm8250_exit(void)
341 {
342         platform_driver_unregister(&gpu_cc_sm8250_driver);
343 }
344 module_exit(gpu_cc_sm8250_exit);
345
346 MODULE_DESCRIPTION("QTI GPU_CC SM8250 Driver");
347 MODULE_LICENSE("GPL v2");