459f123a6720b15efd629deabac2a751665362dd
[releases.git] / gpucc-sdm660.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2020, The Linux Foundation. All rights reserved.
4  * Copyright (c) 2020, AngeloGioacchino Del Regno
5  *                     <angelogioacchino.delregno@somainline.org>
6  */
7
8 #include <linux/bitops.h>
9 #include <linux/clk.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>
15 #include <linux/of.h>
16 #include <linux/regmap.h>
17 #include <linux/reset-controller.h>
18 #include <dt-bindings/clock/qcom,gpucc-sdm660.h>
19
20 #include "clk-alpha-pll.h"
21 #include "common.h"
22 #include "clk-regmap.h"
23 #include "clk-pll.h"
24 #include "clk-rcg.h"
25 #include "clk-branch.h"
26 #include "gdsc.h"
27 #include "reset.h"
28
29 enum {
30         P_GPU_XO,
31         P_GPLL0_OUT_MAIN,
32         P_GPLL0_OUT_MAIN_DIV,
33         P_GPU_PLL0_PLL_OUT_MAIN,
34         P_GPU_PLL1_PLL_OUT_MAIN,
35 };
36
37 static struct clk_branch gpucc_cxo_clk = {
38         .halt_reg = 0x1020,
39         .clkr = {
40                 .enable_reg = 0x1020,
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){
45                                 .fw_name = "xo"
46                         },
47                         .num_parents = 1,
48                         .ops = &clk_branch2_ops,
49                         .flags = CLK_IS_CRITICAL,
50                 },
51         },
52 };
53
54 static struct pll_vco gpu_vco[] = {
55         { 1000000000, 2000000000, 0 },
56         { 500000000,  1000000000, 2 },
57         { 250000000,   500000000, 3 },
58 };
59
60 static struct clk_alpha_pll gpu_pll0_pll_out_main = {
61         .offset = 0x0,
62         .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
63         .vco_table = gpu_vco,
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,
69                 },
70                 .num_parents = 1,
71                 .ops = &clk_alpha_pll_ops,
72         },
73 };
74
75 static struct clk_alpha_pll gpu_pll1_pll_out_main = {
76         .offset = 0x40,
77         .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
78         .vco_table = gpu_vco,
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,
84                 },
85                 .num_parents = 1,
86                 .ops = &clk_alpha_pll_ops,
87         },
88 };
89
90 static const struct parent_map gpucc_parent_map_1[] = {
91         { P_GPU_XO, 0 },
92         { P_GPU_PLL0_PLL_OUT_MAIN, 1 },
93         { P_GPU_PLL1_PLL_OUT_MAIN, 3 },
94         { P_GPLL0_OUT_MAIN, 5 },
95 };
96
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" },
102 };
103
104 static struct clk_rcg2_gfx3d gfx3d_clk_src = {
105         .div = 2,
106         .rcg = {
107                 .cmd_rcgr = 0x1070,
108                 .mnd_width = 0,
109                 .hid_width = 5,
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,
117                 },
118         },
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,
123         }
124 };
125
126 static struct clk_branch gpucc_gfx3d_clk = {
127         .halt_reg = 0x1098,
128         .halt_check = BRANCH_HALT,
129         .hwcg_reg = 0x1098,
130         .hwcg_bit = 1,
131         .clkr = {
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,
138                         },
139                         .num_parents = 1,
140                         .ops = &clk_branch2_ops,
141                         .flags = CLK_SET_RATE_PARENT,
142                 },
143         },
144 };
145
146 static const struct parent_map gpucc_parent_map_0[] = {
147         { P_GPU_XO, 0 },
148         { P_GPLL0_OUT_MAIN, 5 },
149         { P_GPLL0_OUT_MAIN_DIV, 6 },
150 };
151
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" },
156 };
157
158 static const struct freq_tbl ftbl_rbbmtimer_clk_src[] = {
159         F(19200000, P_GPU_XO, 1, 0, 0),
160         { }
161 };
162
163 static struct clk_rcg2 rbbmtimer_clk_src = {
164         .cmd_rcgr = 0x10b0,
165         .mnd_width = 0,
166         .hid_width = 5,
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,
174         },
175 };
176
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),
180         { }
181 };
182
183 static struct clk_rcg2 rbcpr_clk_src = {
184         .cmd_rcgr = 0x1030,
185         .mnd_width = 0,
186         .hid_width = 5,
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,
194         },
195 };
196
197 static struct clk_branch gpucc_rbbmtimer_clk = {
198         .halt_reg = 0x10d0,
199         .halt_check = BRANCH_HALT,
200         .clkr = {
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,
207                         },
208                         .num_parents = 1,
209                         .flags = CLK_SET_RATE_PARENT,
210                         .ops = &clk_branch2_ops,
211                 },
212         },
213 };
214
215 static struct clk_branch gpucc_rbcpr_clk = {
216         .halt_reg = 0x1054,
217         .halt_check = BRANCH_HALT,
218         .clkr = {
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,
225                         },
226                         .num_parents = 1,
227                         .flags = CLK_SET_RATE_PARENT,
228                         .ops = &clk_branch2_ops,
229                 },
230         },
231 };
232
233 static struct gdsc gpu_cx_gdsc = {
234         .gdscr = 0x1004,
235         .gds_hw_ctrl = 0x1008,
236         .pd = {
237                 .name = "gpu_cx",
238         },
239         .pwrsts = PWRSTS_OFF_ON,
240         .flags = VOTABLE,
241 };
242
243 static struct gdsc gpu_gx_gdsc = {
244         .gdscr = 0x1094,
245         .clamp_io_ctrl = 0x130,
246         .resets = (unsigned int []){ GPU_GX_BCR },
247         .reset_count = 1,
248         .cxcs = (unsigned int []){ 0x1098 },
249         .cxc_count = 1,
250         .pd = {
251                 .name = "gpu_gx",
252         },
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,
256 };
257
258 static struct gdsc *gpucc_sdm660_gdscs[] = {
259         [GPU_CX_GDSC] = &gpu_cx_gdsc,
260         [GPU_GX_GDSC] = &gpu_gx_gdsc,
261 };
262
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 },
268 };
269
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,
280 };
281
282 static const struct regmap_config gpucc_660_regmap_config = {
283         .reg_bits       = 32,
284         .reg_stride     = 4,
285         .val_bits       = 32,
286         .max_register   = 0x9034,
287         .fast_io        = true,
288 };
289
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),
298 };
299
300 static const struct of_device_id gpucc_sdm660_match_table[] = {
301         { .compatible = "qcom,gpucc-sdm660" },
302         { .compatible = "qcom,gpucc-sdm630" },
303         { }
304 };
305 MODULE_DEVICE_TABLE(of, gpucc_sdm660_match_table);
306
307 static int gpucc_sdm660_probe(struct platform_device *pdev)
308 {
309         struct regmap *regmap;
310         struct alpha_pll_config gpu_pll_config = {
311                 .config_ctl_val = 0x4001055b,
312                 .alpha = 0xaaaaab00,
313                 .alpha_en_mask = BIT(24),
314                 .vco_val = 0x2 << 20,
315                 .vco_mask = 0x3 << 20,
316                 .main_output_mask = 0x1,
317         };
318
319         regmap = qcom_cc_map(pdev, &gpucc_sdm660_desc);
320         if (IS_ERR(regmap))
321                 return PTR_ERR(regmap);
322
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);
327
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);
332
333         return qcom_cc_really_probe(pdev, &gpucc_sdm660_desc, regmap);
334 }
335
336 static struct platform_driver gpucc_sdm660_driver = {
337         .probe          = gpucc_sdm660_probe,
338         .driver         = {
339                 .name   = "gpucc-sdm660",
340                 .of_match_table = gpucc_sdm660_match_table,
341         },
342 };
343 module_platform_driver(gpucc_sdm660_driver);
344
345 MODULE_DESCRIPTION("Qualcomm SDM630/SDM660 GPUCC Driver");
346 MODULE_LICENSE("GPL v2");