GNU Linux-libre 6.7.9-gnu
[releases.git] / drivers / clk / qcom / gpucc-sm6350.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
4  * Copyright (c) 2021, Konrad Dybcio <konrad.dybcio@somainline.org>
5  */
6
7 #include <linux/clk-provider.h>
8 #include <linux/module.h>
9 #include <linux/platform_device.h>
10 #include <linux/regmap.h>
11
12 #include <dt-bindings/clock/qcom,gpucc-sm6350.h>
13
14 #include "common.h"
15 #include "clk-alpha-pll.h"
16 #include "clk-branch.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         DT_BI_TCXO,
29         DT_GPLL0_OUT_MAIN,
30         DT_GPLL0_OUT_MAIN_DIV,
31 };
32
33 enum {
34         P_BI_TCXO,
35         P_GPLL0_OUT_MAIN,
36         P_GPLL0_OUT_MAIN_DIV,
37         P_GPU_CC_PLL0_OUT_MAIN,
38         P_GPU_CC_PLL0_OUT_ODD,
39         P_GPU_CC_PLL1_OUT_EVEN,
40         P_GPU_CC_PLL1_OUT_MAIN,
41         P_GPU_CC_PLL1_OUT_ODD,
42         P_CRC_DIV,
43 };
44
45 static const struct pll_vco fabia_vco[] = {
46         { 249600000, 2000000000, 0 },
47 };
48
49 /* 506MHz Configuration*/
50 static const struct alpha_pll_config gpu_cc_pll0_config = {
51         .l = 0x1A,
52         .alpha = 0x5AAA,
53         .config_ctl_val = 0x20485699,
54         .config_ctl_hi_val = 0x00002067,
55         .test_ctl_val = 0x40000000,
56         .test_ctl_hi_val = 0x00000002,
57         .user_ctl_val = 0x00000001,
58         .user_ctl_hi_val = 0x00004805,
59 };
60
61 static struct clk_alpha_pll gpu_cc_pll0 = {
62         .offset = 0x0,
63         .vco_table = fabia_vco,
64         .num_vco = ARRAY_SIZE(fabia_vco),
65         .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
66         .clkr = {
67                 .hw.init = &(struct clk_init_data){
68                         .name = "gpu_cc_pll0",
69                         .parent_data =  &(const struct clk_parent_data){
70                                 .index = DT_BI_TCXO,
71                                 .fw_name = "bi_tcxo",
72                         },
73                         .num_parents = 1,
74                         .ops = &clk_alpha_pll_fabia_ops,
75                 },
76         },
77 };
78
79 static struct clk_fixed_factor crc_div = {
80         .mult = 1,
81         .div = 2,
82         .hw.init = &(struct clk_init_data){
83                 .name = "crc_div",
84                 .parent_hws = (const struct clk_hw*[]){
85                         &gpu_cc_pll0.clkr.hw,
86                 },
87                 .num_parents = 1,
88                 .flags = CLK_SET_RATE_PARENT,
89                 .ops = &clk_fixed_factor_ops,
90         },
91 };
92
93 /* 514MHz Configuration*/
94 static const struct alpha_pll_config gpu_cc_pll1_config = {
95         .l = 0x1A,
96         .alpha = 0xC555,
97         .config_ctl_val = 0x20485699,
98         .config_ctl_hi_val = 0x00002067,
99         .test_ctl_val = 0x40000000,
100         .test_ctl_hi_val = 0x00000002,
101         .user_ctl_val = 0x00000001,
102         .user_ctl_hi_val = 0x00004805,
103 };
104
105 static struct clk_alpha_pll gpu_cc_pll1 = {
106         .offset = 0x100,
107         .vco_table = fabia_vco,
108         .num_vco = ARRAY_SIZE(fabia_vco),
109         .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
110         .clkr = {
111                 .hw.init = &(struct clk_init_data){
112                         .name = "gpu_cc_pll1",
113                         .parent_data =  &(const struct clk_parent_data){
114                                 .index = DT_BI_TCXO,
115                                 .fw_name = "bi_tcxo",
116                         },
117                         .num_parents = 1,
118                         .ops = &clk_alpha_pll_fabia_ops,
119                 },
120         },
121 };
122
123 static const struct parent_map gpu_cc_parent_map_0[] = {
124         { P_BI_TCXO, 0 },
125         { P_GPU_CC_PLL0_OUT_MAIN, 1 },
126         { P_GPU_CC_PLL1_OUT_MAIN, 3 },
127         { P_GPLL0_OUT_MAIN, 5 },
128         { P_GPLL0_OUT_MAIN_DIV, 6 },
129 };
130
131 static const struct clk_parent_data gpu_cc_parent_data_0[] = {
132         { .index = DT_BI_TCXO, .fw_name = "bi_tcxo" },
133         { .hw = &gpu_cc_pll0.clkr.hw },
134         { .hw = &gpu_cc_pll1.clkr.hw },
135         { .index = DT_GPLL0_OUT_MAIN, .fw_name = "gcc_gpu_gpll0_clk_src" },
136         { .index = DT_GPLL0_OUT_MAIN_DIV, .fw_name = "gcc_gpu_gpll0_div_clk_src" },
137 };
138
139 static const struct parent_map gpu_cc_parent_map_1[] = {
140         { P_BI_TCXO, 0 },
141         { P_CRC_DIV, 1 },
142         { P_GPU_CC_PLL0_OUT_ODD, 2 },
143         { P_GPU_CC_PLL1_OUT_EVEN, 3 },
144         { P_GPU_CC_PLL1_OUT_ODD, 4 },
145         { P_GPLL0_OUT_MAIN, 5 },
146 };
147
148 static const struct clk_parent_data gpu_cc_parent_data_1[] = {
149         { .index = DT_BI_TCXO, .fw_name = "bi_tcxo" },
150         { .hw = &crc_div.hw },
151         { .hw = &gpu_cc_pll0.clkr.hw },
152         { .hw = &gpu_cc_pll1.clkr.hw },
153         { .hw = &gpu_cc_pll1.clkr.hw },
154         { .index = DT_GPLL0_OUT_MAIN, .fw_name = "gcc_gpu_gpll0_clk_src" },
155 };
156
157 static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = {
158         F(200000000, P_GPLL0_OUT_MAIN_DIV, 1.5, 0, 0),
159         { }
160 };
161
162 static struct clk_rcg2 gpu_cc_gmu_clk_src = {
163         .cmd_rcgr = 0x1120,
164         .mnd_width = 0,
165         .hid_width = 5,
166         .parent_map = gpu_cc_parent_map_0,
167         .freq_tbl = ftbl_gpu_cc_gmu_clk_src,
168         .clkr.hw.init = &(struct clk_init_data){
169                 .name = "gpu_cc_gmu_clk_src",
170                 .parent_data = gpu_cc_parent_data_0,
171                 .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0),
172                 .flags = CLK_SET_RATE_PARENT,
173                 .ops = &clk_rcg2_ops,
174         },
175 };
176
177 static const struct freq_tbl ftbl_gpu_cc_gx_gfx3d_clk_src[] = {
178         F(253000000, P_CRC_DIV, 1, 0, 0),
179         F(355000000, P_CRC_DIV, 1, 0, 0),
180         F(430000000, P_CRC_DIV, 1, 0, 0),
181         F(565000000, P_CRC_DIV, 1, 0, 0),
182         F(650000000, P_CRC_DIV, 1, 0, 0),
183         F(800000000, P_CRC_DIV, 1, 0, 0),
184         F(825000000, P_CRC_DIV, 1, 0, 0),
185         F(850000000, P_CRC_DIV, 1, 0, 0),
186         { }
187 };
188
189 static struct clk_rcg2 gpu_cc_gx_gfx3d_clk_src = {
190         .cmd_rcgr = 0x101c,
191         .mnd_width = 0,
192         .hid_width = 5,
193         .parent_map = gpu_cc_parent_map_1,
194         .freq_tbl = ftbl_gpu_cc_gx_gfx3d_clk_src,
195         .clkr.hw.init = &(struct clk_init_data){
196                 .name = "gpu_cc_gx_gfx3d_clk_src",
197                 .parent_data = gpu_cc_parent_data_1,
198                 .num_parents = ARRAY_SIZE(gpu_cc_parent_data_1),
199                 .flags = CLK_SET_RATE_PARENT,
200                 .ops = &clk_rcg2_ops,
201         },
202 };
203
204 static struct clk_branch gpu_cc_acd_ahb_clk = {
205         .halt_reg = 0x1168,
206         .halt_check = BRANCH_HALT,
207         .clkr = {
208                 .enable_reg = 0x1168,
209                 .enable_mask = BIT(0),
210                 .hw.init = &(struct clk_init_data){
211                         .name = "gpu_cc_acd_ahb_clk",
212                         .ops = &clk_branch2_ops,
213                 },
214         },
215 };
216
217 static struct clk_branch gpu_cc_acd_cxo_clk = {
218         .halt_reg = 0x1164,
219         .halt_check = BRANCH_HALT,
220         .clkr = {
221                 .enable_reg = 0x1164,
222                 .enable_mask = BIT(0),
223                 .hw.init = &(struct clk_init_data){
224                         .name = "gpu_cc_acd_cxo_clk",
225                         .ops = &clk_branch2_ops,
226                 },
227         },
228 };
229
230 static struct clk_branch gpu_cc_ahb_clk = {
231         .halt_reg = 0x1078,
232         .halt_check = BRANCH_HALT_DELAY,
233         .clkr = {
234                 .enable_reg = 0x1078,
235                 .enable_mask = BIT(0),
236                 .hw.init = &(struct clk_init_data){
237                         .name = "gpu_cc_ahb_clk",
238                         .flags = CLK_IS_CRITICAL,
239                         .ops = &clk_branch2_ops,
240                 },
241         },
242 };
243
244 static struct clk_branch gpu_cc_crc_ahb_clk = {
245         .halt_reg = 0x107c,
246         .halt_check = BRANCH_HALT_DELAY,
247         .clkr = {
248                 .enable_reg = 0x107c,
249                 .enable_mask = BIT(0),
250                 .hw.init = &(struct clk_init_data){
251                         .name = "gpu_cc_crc_ahb_clk",
252                         .ops = &clk_branch2_ops,
253                 },
254         },
255 };
256
257 static struct clk_branch gpu_cc_cx_gfx3d_clk = {
258         .halt_reg = 0x10a4,
259         .halt_check = BRANCH_HALT_DELAY,
260         .clkr = {
261                 .enable_reg = 0x10a4,
262                 .enable_mask = BIT(0),
263                 .hw.init = &(struct clk_init_data){
264                         .name = "gpu_cc_cx_gfx3d_clk",
265                         .parent_hws = (const struct clk_hw*[]){
266                                 &gpu_cc_gx_gfx3d_clk_src.clkr.hw,
267                         },
268                         .num_parents = 1,
269                         .flags = CLK_SET_RATE_PARENT,
270                         .ops = &clk_branch2_ops,
271                 },
272         },
273 };
274
275 static struct clk_branch gpu_cc_cx_gfx3d_slv_clk = {
276         .halt_reg = 0x10a8,
277         .halt_check = BRANCH_HALT_DELAY,
278         .clkr = {
279                 .enable_reg = 0x10a8,
280                 .enable_mask = BIT(0),
281                 .hw.init = &(struct clk_init_data){
282                         .name = "gpu_cc_cx_gfx3d_slv_clk",
283                         .parent_hws = (const struct clk_hw*[]){
284                                 &gpu_cc_gx_gfx3d_clk_src.clkr.hw,
285                         },
286                         .num_parents = 1,
287                         .flags = CLK_SET_RATE_PARENT,
288                         .ops = &clk_branch2_ops,
289                 },
290         },
291 };
292
293 static struct clk_branch gpu_cc_cx_gmu_clk = {
294         .halt_reg = 0x1098,
295         .halt_check = BRANCH_HALT,
296         .clkr = {
297                 .enable_reg = 0x1098,
298                 .enable_mask = BIT(0),
299                 .hw.init = &(struct clk_init_data){
300                         .name = "gpu_cc_cx_gmu_clk",
301                         .parent_hws = (const struct clk_hw*[]){
302                                 &gpu_cc_gmu_clk_src.clkr.hw,
303                         },
304                         .num_parents = 1,
305                         .flags = CLK_SET_RATE_PARENT,
306                         .ops = &clk_branch2_ops,
307                 },
308         },
309 };
310
311 static struct clk_branch gpu_cc_cx_snoc_dvm_clk = {
312         .halt_reg = 0x108c,
313         .halt_check = BRANCH_HALT_DELAY,
314         .clkr = {
315                 .enable_reg = 0x108c,
316                 .enable_mask = BIT(0),
317                 .hw.init = &(struct clk_init_data){
318                         .name = "gpu_cc_cx_snoc_dvm_clk",
319                         .ops = &clk_branch2_ops,
320                 },
321         },
322 };
323
324 static struct clk_branch gpu_cc_cxo_aon_clk = {
325         .halt_reg = 0x1004,
326         .halt_check = BRANCH_HALT_DELAY,
327         .clkr = {
328                 .enable_reg = 0x1004,
329                 .enable_mask = BIT(0),
330                 .hw.init = &(struct clk_init_data){
331                         .name = "gpu_cc_cxo_aon_clk",
332                         .ops = &clk_branch2_ops,
333                 },
334         },
335 };
336
337 static struct clk_branch gpu_cc_cxo_clk = {
338         .halt_reg = 0x109c,
339         .halt_check = BRANCH_HALT,
340         .clkr = {
341                 .enable_reg = 0x109c,
342                 .enable_mask = BIT(0),
343                 .hw.init = &(struct clk_init_data){
344                         .name = "gpu_cc_cxo_clk",
345                         .ops = &clk_branch2_ops,
346                 },
347         },
348 };
349
350 static struct clk_branch gpu_cc_gx_cxo_clk = {
351         .halt_reg = 0x1060,
352         .halt_check = BRANCH_HALT,
353         .clkr = {
354                 .enable_reg = 0x1060,
355                 .enable_mask = BIT(0),
356                 .hw.init = &(struct clk_init_data){
357                         .name = "gpu_cc_gx_cxo_clk",
358                         .ops = &clk_branch2_ops,
359                 },
360         },
361 };
362
363 static struct clk_branch gpu_cc_gx_gfx3d_clk = {
364         .halt_reg = 0x1054,
365         .halt_check = BRANCH_HALT_SKIP,
366         .clkr = {
367                 .enable_reg = 0x1054,
368                 .enable_mask = BIT(0),
369                 .hw.init = &(struct clk_init_data){
370                         .name = "gpu_cc_gx_gfx3d_clk",
371                         .parent_hws = (const struct clk_hw*[]){
372                                 &gpu_cc_gx_gfx3d_clk_src.clkr.hw,
373                         },
374                         .num_parents = 1,
375                         .flags = CLK_SET_RATE_PARENT,
376                         .ops = &clk_branch2_ops,
377                 },
378         },
379 };
380
381 static struct clk_branch gpu_cc_gx_gmu_clk = {
382         .halt_reg = 0x1064,
383         .halt_check = BRANCH_HALT,
384         .clkr = {
385                 .enable_reg = 0x1064,
386                 .enable_mask = BIT(0),
387                 .hw.init = &(struct clk_init_data){
388                         .name = "gpu_cc_gx_gmu_clk",
389                         .parent_hws = (const struct clk_hw*[]){
390                                 &gpu_cc_gmu_clk_src.clkr.hw,
391                         },
392                         .num_parents = 1,
393                         .flags = CLK_SET_RATE_PARENT,
394                         .ops = &clk_branch2_ops,
395                 },
396         },
397 };
398
399 static struct clk_branch gpu_cc_gx_vsense_clk = {
400         .halt_reg = 0x1058,
401         .halt_check = BRANCH_HALT_DELAY,
402         .clkr = {
403                 .enable_reg = 0x1058,
404                 .enable_mask = BIT(0),
405                 .hw.init = &(struct clk_init_data){
406                         .name = "gpu_cc_gx_vsense_clk",
407                         .ops = &clk_branch2_ops,
408                 },
409         },
410 };
411
412 static struct gdsc gpu_cx_gdsc = {
413         .gdscr = 0x106c,
414         .gds_hw_ctrl = 0x1540,
415         .pd = {
416                 .name = "gpu_cx_gdsc",
417         },
418         .pwrsts = PWRSTS_OFF_ON,
419         .flags = VOTABLE,
420 };
421
422 static struct gdsc gpu_gx_gdsc = {
423         .gdscr = 0x100c,
424         .clamp_io_ctrl = 0x1508,
425         .pd = {
426                 .name = "gpu_gx_gdsc",
427                 .power_on = gdsc_gx_do_nothing_enable,
428         },
429         .pwrsts = PWRSTS_OFF_ON,
430         .flags = CLAMP_IO | POLL_CFG_GDSCR,
431 };
432
433 static struct clk_hw *gpu_cc_sm6350_hws[] = {
434         [GPU_CC_CRC_DIV] = &crc_div.hw,
435 };
436
437 static struct clk_regmap *gpu_cc_sm6350_clocks[] = {
438         [GPU_CC_ACD_AHB_CLK] = &gpu_cc_acd_ahb_clk.clkr,
439         [GPU_CC_ACD_CXO_CLK] = &gpu_cc_acd_cxo_clk.clkr,
440         [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr,
441         [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr,
442         [GPU_CC_CX_GFX3D_CLK] = &gpu_cc_cx_gfx3d_clk.clkr,
443         [GPU_CC_CX_GFX3D_SLV_CLK] = &gpu_cc_cx_gfx3d_slv_clk.clkr,
444         [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr,
445         [GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_clk.clkr,
446         [GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr,
447         [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr,
448         [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr,
449         [GPU_CC_GX_CXO_CLK] = &gpu_cc_gx_cxo_clk.clkr,
450         [GPU_CC_GX_GFX3D_CLK] = &gpu_cc_gx_gfx3d_clk.clkr,
451         [GPU_CC_GX_GFX3D_CLK_SRC] = &gpu_cc_gx_gfx3d_clk_src.clkr,
452         [GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr,
453         [GPU_CC_GX_VSENSE_CLK] = &gpu_cc_gx_vsense_clk.clkr,
454         [GPU_CC_PLL0] = &gpu_cc_pll0.clkr,
455         [GPU_CC_PLL1] = &gpu_cc_pll1.clkr,
456 };
457
458 static struct gdsc *gpu_cc_sm6350_gdscs[] = {
459         [GPU_CX_GDSC] = &gpu_cx_gdsc,
460         [GPU_GX_GDSC] = &gpu_gx_gdsc,
461 };
462
463 static const struct regmap_config gpu_cc_sm6350_regmap_config = {
464         .reg_bits = 32,
465         .reg_stride = 4,
466         .val_bits = 32,
467         .max_register = 0x8008,
468         .fast_io = true,
469 };
470
471 static const struct qcom_cc_desc gpu_cc_sm6350_desc = {
472         .config = &gpu_cc_sm6350_regmap_config,
473         .clk_hws = gpu_cc_sm6350_hws,
474         .num_clk_hws = ARRAY_SIZE(gpu_cc_sm6350_hws),
475         .clks = gpu_cc_sm6350_clocks,
476         .num_clks = ARRAY_SIZE(gpu_cc_sm6350_clocks),
477         .gdscs = gpu_cc_sm6350_gdscs,
478         .num_gdscs = ARRAY_SIZE(gpu_cc_sm6350_gdscs),
479 };
480
481 static const struct of_device_id gpu_cc_sm6350_match_table[] = {
482         { .compatible = "qcom,sm6350-gpucc" },
483         { }
484 };
485 MODULE_DEVICE_TABLE(of, gpu_cc_sm6350_match_table);
486
487 static int gpu_cc_sm6350_probe(struct platform_device *pdev)
488 {
489         struct regmap *regmap;
490         unsigned int value, mask;
491
492         regmap = qcom_cc_map(pdev, &gpu_cc_sm6350_desc);
493         if (IS_ERR(regmap))
494                 return PTR_ERR(regmap);
495
496         clk_fabia_pll_configure(&gpu_cc_pll0, regmap, &gpu_cc_pll0_config);
497         clk_fabia_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config);
498
499         /* Configure gpu_cc_cx_gmu_clk with recommended wakeup/sleep settings */
500         mask = CX_GMU_CBCR_WAKE_MASK << CX_GMU_CBCR_WAKE_SHIFT;
501         mask |= CX_GMU_CBCR_SLEEP_MASK << CX_GMU_CBCR_SLEEP_SHIFT;
502         value = 0xF << CX_GMU_CBCR_WAKE_SHIFT | 0xF << CX_GMU_CBCR_SLEEP_SHIFT;
503         regmap_update_bits(regmap, 0x1098, mask, value);
504
505         return qcom_cc_really_probe(pdev, &gpu_cc_sm6350_desc, regmap);
506 }
507
508 static struct platform_driver gpu_cc_sm6350_driver = {
509         .probe = gpu_cc_sm6350_probe,
510         .driver = {
511                 .name = "sm6350-gpucc",
512                 .of_match_table = gpu_cc_sm6350_match_table,
513         },
514 };
515
516 static int __init gpu_cc_sm6350_init(void)
517 {
518         return platform_driver_register(&gpu_cc_sm6350_driver);
519 }
520 core_initcall(gpu_cc_sm6350_init);
521
522 static void __exit gpu_cc_sm6350_exit(void)
523 {
524         platform_driver_unregister(&gpu_cc_sm6350_driver);
525 }
526 module_exit(gpu_cc_sm6350_exit);
527
528 MODULE_DESCRIPTION("QTI GPU_CC LAGOON Driver");
529 MODULE_LICENSE("GPL v2");