1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (c) 2021, Qualcomm Innovation Center, Inc. All rights reserved.
4 * Copyright (c) 2024, Linaro Limited
5 */
6
7 #include <linux/clk-provider.h>
8 #include <linux/kernel.h>
9 #include <linux/mod_devicetable.h>
10 #include <linux/module.h>
11 #include <linux/platform_device.h>
12 #include <linux/regmap.h>
13
14 #include <dt-bindings/clock/qcom,sar2130p-gpucc.h>
15 #include <dt-bindings/reset/qcom,sar2130p-gpucc.h>
16
17 #include "clk-alpha-pll.h"
18 #include "clk-branch.h"
19 #include "clk-rcg.h"
20 #include "common.h"
21 #include "gdsc.h"
22 #include "reset.h"
23
24 enum {
25 DT_BI_TCXO,
26 DT_GPLL0_OUT_MAIN,
27 DT_GPLL0_OUT_MAIN_DIV,
28 };
29
30 enum {
31 P_BI_TCXO,
32 P_GPLL0_OUT_MAIN,
33 P_GPLL0_OUT_MAIN_DIV,
34 P_GPU_CC_PLL0_OUT_MAIN,
35 P_GPU_CC_PLL1_OUT_MAIN,
36 };
37
38 static const struct pll_vco lucid_ole_vco[] = {
39 { 249600000, 2000000000, 0 },
40 };
41
42 /* 470MHz Configuration */
43 static const struct alpha_pll_config gpu_cc_pll0_config = {
44 .l = 0x18,
45 .alpha = 0x7aaa,
46 .config_ctl_val = 0x20485699,
47 .config_ctl_hi_val = 0x00182261,
48 .config_ctl_hi1_val = 0x82aa299c,
49 .test_ctl_val = 0x00000000,
50 .test_ctl_hi_val = 0x00000003,
51 .test_ctl_hi1_val = 0x00009000,
52 .test_ctl_hi2_val = 0x00000034,
53 .user_ctl_val = 0x00000000,
54 .user_ctl_hi_val = 0x00000005,
55 };
56
57 static struct clk_alpha_pll gpu_cc_pll0 = {
58 .offset = 0x0,
59 .vco_table = lucid_ole_vco,
60 .num_vco = ARRAY_SIZE(lucid_ole_vco),
61 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
62 .clkr = {
63 .hw.init = &(const struct clk_init_data) {
64 .name = "gpu_cc_pll0",
65 .parent_data = &(const struct clk_parent_data) {
66 .index = DT_BI_TCXO,
67 },
68 .num_parents = 1,
69 .ops = &clk_alpha_pll_lucid_evo_ops,
70 },
71 },
72 };
73
74 /* 440MHz Configuration */
75 static const struct alpha_pll_config gpu_cc_pll1_config = {
76 .l = 0x16,
77 .alpha = 0xeaaa,
78 .config_ctl_val = 0x20485699,
79 .config_ctl_hi_val = 0x00182261,
80 .config_ctl_hi1_val = 0x82aa299c,
81 .test_ctl_val = 0x00000000,
82 .test_ctl_hi_val = 0x00000003,
83 .test_ctl_hi1_val = 0x00009000,
84 .test_ctl_hi2_val = 0x00000034,
85 .user_ctl_val = 0x00000000,
86 .user_ctl_hi_val = 0x00000005,
87 };
88
89 static struct clk_alpha_pll gpu_cc_pll1 = {
90 .offset = 0x1000,
91 .vco_table = lucid_ole_vco,
92 .num_vco = ARRAY_SIZE(lucid_ole_vco),
93 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
94 .clkr = {
95 .hw.init = &(const struct clk_init_data) {
96 .name = "gpu_cc_pll1",
97 .parent_data = &(const struct clk_parent_data) {
98 .index = DT_BI_TCXO,
99 },
100 .num_parents = 1,
101 .ops = &clk_alpha_pll_lucid_evo_ops,
102 },
103 },
104 };
105
106 static const struct parent_map gpu_cc_parent_map_0[] = {
107 { P_BI_TCXO, 0 },
108 { P_GPLL0_OUT_MAIN, 5 },
109 { P_GPLL0_OUT_MAIN_DIV, 6 },
110 };
111
112 static const struct clk_parent_data gpu_cc_parent_data_0[] = {
113 { .index = DT_BI_TCXO },
114 { .index = DT_GPLL0_OUT_MAIN },
115 { .index = DT_GPLL0_OUT_MAIN_DIV },
116 };
117
118 static const struct parent_map gpu_cc_parent_map_1[] = {
119 { P_BI_TCXO, 0 },
120 { P_GPU_CC_PLL0_OUT_MAIN, 1 },
121 { P_GPU_CC_PLL1_OUT_MAIN, 3 },
122 { P_GPLL0_OUT_MAIN, 5 },
123 { P_GPLL0_OUT_MAIN_DIV, 6 },
124 };
125
126 static const struct clk_parent_data gpu_cc_parent_data_1[] = {
127 { .index = DT_BI_TCXO },
128 { .hw = &gpu_cc_pll0.clkr.hw },
129 { .hw = &gpu_cc_pll1.clkr.hw },
130 { .index = DT_GPLL0_OUT_MAIN },
131 { .index = DT_GPLL0_OUT_MAIN_DIV },
132 };
133
134 static const struct parent_map gpu_cc_parent_map_2[] = {
135 { P_BI_TCXO, 0 },
136 { P_GPU_CC_PLL1_OUT_MAIN, 3 },
137 { P_GPLL0_OUT_MAIN, 5 },
138 { P_GPLL0_OUT_MAIN_DIV, 6 },
139 };
140
141 static const struct clk_parent_data gpu_cc_parent_data_2[] = {
142 { .index = DT_BI_TCXO },
143 { .hw = &gpu_cc_pll1.clkr.hw },
144 { .index = DT_GPLL0_OUT_MAIN },
145 { .index = DT_GPLL0_OUT_MAIN_DIV },
146 };
147
148 static const struct freq_tbl ftbl_gpu_cc_ff_clk_src[] = {
149 F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0),
150 { }
151 };
152
153 static struct clk_rcg2 gpu_cc_ff_clk_src = {
154 .cmd_rcgr = 0x9474,
155 .mnd_width = 0,
156 .hid_width = 5,
157 .parent_map = gpu_cc_parent_map_0,
158 .freq_tbl = ftbl_gpu_cc_ff_clk_src,
159 .clkr.hw.init = &(const struct clk_init_data) {
160 .name = "gpu_cc_ff_clk_src",
161 .parent_data = gpu_cc_parent_data_0,
162 .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0),
163 .ops = &clk_rcg2_shared_ops,
164 },
165 };
166
167 static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = {
168 F(19200000, P_BI_TCXO, 1, 0, 0),
169 F(220000000, P_GPU_CC_PLL1_OUT_MAIN, 2, 0, 0),
170 F(550000000, P_GPU_CC_PLL1_OUT_MAIN, 2, 0, 0),
171 { }
172 };
173
174 static struct clk_rcg2 gpu_cc_gmu_clk_src = {
175 .cmd_rcgr = 0x9318,
176 .mnd_width = 0,
177 .hid_width = 5,
178 .parent_map = gpu_cc_parent_map_1,
179 .freq_tbl = ftbl_gpu_cc_gmu_clk_src,
180 .clkr.hw.init = &(const struct clk_init_data) {
181 .name = "gpu_cc_gmu_clk_src",
182 .parent_data = gpu_cc_parent_data_1,
183 .num_parents = ARRAY_SIZE(gpu_cc_parent_data_1),
184 .flags = CLK_SET_RATE_PARENT,
185 .ops = &clk_rcg2_shared_ops,
186 },
187 };
188
189 static struct clk_rcg2 gpu_cc_hub_clk_src = {
190 .cmd_rcgr = 0x93ec,
191 .mnd_width = 0,
192 .hid_width = 5,
193 .parent_map = gpu_cc_parent_map_2,
194 .freq_tbl = ftbl_gpu_cc_ff_clk_src,
195 .clkr.hw.init = &(const struct clk_init_data) {
196 .name = "gpu_cc_hub_clk_src",
197 .parent_data = gpu_cc_parent_data_2,
198 .num_parents = ARRAY_SIZE(gpu_cc_parent_data_2),
199 .ops = &clk_rcg2_shared_ops,
200 },
201 };
202
203 static struct clk_branch gpu_cc_ahb_clk = {
204 .halt_reg = 0x911c,
205 .halt_check = BRANCH_HALT_DELAY,
206 .clkr = {
207 .enable_reg = 0x911c,
208 .enable_mask = BIT(0),
209 .hw.init = &(const struct clk_init_data) {
210 .name = "gpu_cc_ahb_clk",
211 .parent_hws = (const struct clk_hw*[]) {
212 &gpu_cc_hub_clk_src.clkr.hw,
213 },
214 .num_parents = 1,
215 .flags = CLK_SET_RATE_PARENT,
216 .ops = &clk_branch2_ops,
217 },
218 },
219 };
220
221 static struct clk_branch gpu_cc_crc_ahb_clk = {
222 .halt_reg = 0x9120,
223 .halt_check = BRANCH_HALT_VOTED,
224 .clkr = {
225 .enable_reg = 0x9120,
226 .enable_mask = BIT(0),
227 .hw.init = &(const struct clk_init_data) {
228 .name = "gpu_cc_crc_ahb_clk",
229 .parent_hws = (const struct clk_hw*[]) {
230 &gpu_cc_hub_clk_src.clkr.hw,
231 },
232 .num_parents = 1,
233 .flags = CLK_SET_RATE_PARENT,
234 .ops = &clk_branch2_ops,
235 },
236 },
237 };
238
239 static struct clk_branch gpu_cc_cx_ff_clk = {
240 .halt_reg = 0x914c,
241 .halt_check = BRANCH_HALT,
242 .clkr = {
243 .enable_reg = 0x914c,
244 .enable_mask = BIT(0),
245 .hw.init = &(const struct clk_init_data) {
246 .name = "gpu_cc_cx_ff_clk",
247 .parent_hws = (const struct clk_hw*[]) {
248 &gpu_cc_ff_clk_src.clkr.hw,
249 },
250 .num_parents = 1,
251 .flags = CLK_SET_RATE_PARENT,
252 .ops = &clk_branch2_ops,
253 },
254 },
255 };
256
257 static struct clk_branch gpu_cc_cx_gmu_clk = {
258 .halt_reg = 0x913c,
259 .halt_check = BRANCH_HALT_VOTED,
260 .clkr = {
261 .enable_reg = 0x913c,
262 .enable_mask = BIT(0),
263 .hw.init = &(const struct clk_init_data) {
264 .name = "gpu_cc_cx_gmu_clk",
265 .parent_hws = (const struct clk_hw*[]) {
266 &gpu_cc_gmu_clk_src.clkr.hw,
267 },
268 .num_parents = 1,
269 .flags = CLK_SET_RATE_PARENT,
270 .ops = &clk_branch2_aon_ops,
271 },
272 },
273 };
274
275 static struct clk_branch gpu_cc_cxo_aon_clk = {
276 .halt_reg = 0x9004,
277 .halt_check = BRANCH_HALT_VOTED,
278 .clkr = {
279 .enable_reg = 0x9004,
280 .enable_mask = BIT(0),
281 .hw.init = &(const struct clk_init_data) {
282 .name = "gpu_cc_cxo_aon_clk",
283 .ops = &clk_branch2_ops,
284 },
285 },
286 };
287
288 static struct clk_branch gpu_cc_cxo_clk = {
289 .halt_reg = 0x9144,
290 .halt_check = BRANCH_HALT,
291 .clkr = {
292 .enable_reg = 0x9144,
293 .enable_mask = BIT(0),
294 .hw.init = &(const struct clk_init_data) {
295 .name = "gpu_cc_cxo_clk",
296 .ops = &clk_branch2_ops,
297 },
298 },
299 };
300
301 static struct clk_branch gpu_cc_gx_gmu_clk = {
302 .halt_reg = 0x90bc,
303 .halt_check = BRANCH_HALT,
304 .clkr = {
305 .enable_reg = 0x90bc,
306 .enable_mask = BIT(0),
307 .hw.init = &(const struct clk_init_data) {
308 .name = "gpu_cc_gx_gmu_clk",
309 .parent_hws = (const struct clk_hw*[]) {
310 &gpu_cc_gmu_clk_src.clkr.hw,
311 },
312 .num_parents = 1,
313 .flags = CLK_SET_RATE_PARENT,
314 .ops = &clk_branch2_ops,
315 },
316 },
317 };
318
319 static struct clk_branch gpu_cc_hub_aon_clk = {
320 .halt_reg = 0x93e8,
321 .halt_check = BRANCH_HALT,
322 .clkr = {
323 .enable_reg = 0x93e8,
324 .enable_mask = BIT(0),
325 .hw.init = &(const struct clk_init_data) {
326 .name = "gpu_cc_hub_aon_clk",
327 .parent_hws = (const struct clk_hw*[]) {
328 &gpu_cc_hub_clk_src.clkr.hw,
329 },
330 .num_parents = 1,
331 .flags = CLK_SET_RATE_PARENT,
332 .ops = &clk_branch2_aon_ops,
333 },
334 },
335 };
336
337 static struct clk_branch gpu_cc_hub_cx_int_clk = {
338 .halt_reg = 0x9148,
339 .halt_check = BRANCH_HALT_VOTED,
340 .clkr = {
341 .enable_reg = 0x9148,
342 .enable_mask = BIT(0),
343 .hw.init = &(const struct clk_init_data) {
344 .name = "gpu_cc_hub_cx_int_clk",
345 .parent_hws = (const struct clk_hw*[]) {
346 &gpu_cc_hub_clk_src.clkr.hw,
347 },
348 .num_parents = 1,
349 .flags = CLK_SET_RATE_PARENT,
350 .ops = &clk_branch2_aon_ops,
351 },
352 },
353 };
354
355 static struct clk_branch gpu_cc_memnoc_gfx_clk = {
356 .halt_reg = 0x9150,
357 .halt_check = BRANCH_HALT_VOTED,
358 .clkr = {
359 .enable_reg = 0x9150,
360 .enable_mask = BIT(0),
361 .hw.init = &(const struct clk_init_data) {
362 .name = "gpu_cc_memnoc_gfx_clk",
363 .ops = &clk_branch2_ops,
364 },
365 },
366 };
367
368 static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk = {
369 .halt_reg = 0x7000,
370 .halt_check = BRANCH_HALT_VOTED,
371 .clkr = {
372 .enable_reg = 0x7000,
373 .enable_mask = BIT(0),
374 .hw.init = &(const struct clk_init_data) {
375 .name = "gpu_cc_hlos1_vote_gpu_smmu_clk",
376 .ops = &clk_branch2_ops,
377 },
378 },
379 };
380
381 static struct clk_branch gpu_cc_sleep_clk = {
382 .halt_reg = 0x9134,
383 .halt_check = BRANCH_HALT_VOTED,
384 .clkr = {
385 .enable_reg = 0x9134,
386 .enable_mask = BIT(0),
387 .hw.init = &(const struct clk_init_data) {
388 .name = "gpu_cc_sleep_clk",
389 .ops = &clk_branch2_ops,
390 },
391 },
392 };
393
394 static struct gdsc gpu_cx_gdsc = {
395 .gdscr = 0x9108,
396 .gds_hw_ctrl = 0x953c,
397 .clk_dis_wait_val = 8,
398 .pd = {
399 .name = "gpu_cx_gdsc",
400 },
401 .pwrsts = PWRSTS_OFF_ON,
402 .flags = VOTABLE | RETAIN_FF_ENABLE,
403 };
404
405 static struct gdsc gpu_gx_gdsc = {
406 .gdscr = 0x905c,
407 .clamp_io_ctrl = 0x9504,
408 .resets = (unsigned int []){ GPUCC_GPU_CC_GX_BCR,
409 GPUCC_GPU_CC_ACD_BCR,
410 GPUCC_GPU_CC_GX_ACD_IROOT_BCR },
411 .reset_count = 3,
412 .pd = {
413 .name = "gpu_gx_gdsc",
414 .power_on = gdsc_gx_do_nothing_enable,
415 },
416 .pwrsts = PWRSTS_OFF_ON,
417 .flags = CLAMP_IO | AON_RESET | SW_RESET,
418 };
419
420 static struct clk_regmap *gpu_cc_sar2130p_clocks[] = {
421 [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr,
422 [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr,
423 [GPU_CC_CX_FF_CLK] = &gpu_cc_cx_ff_clk.clkr,
424 [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr,
425 [GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr,
426 [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr,
427 [GPU_CC_FF_CLK_SRC] = &gpu_cc_ff_clk_src.clkr,
428 [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr,
429 [GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr,
430 [GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK] = &gpu_cc_hlos1_vote_gpu_smmu_clk.clkr,
431 [GPU_CC_HUB_AON_CLK] = &gpu_cc_hub_aon_clk.clkr,
432 [GPU_CC_HUB_CLK_SRC] = &gpu_cc_hub_clk_src.clkr,
433 [GPU_CC_HUB_CX_INT_CLK] = &gpu_cc_hub_cx_int_clk.clkr,
434 [GPU_CC_MEMNOC_GFX_CLK] = &gpu_cc_memnoc_gfx_clk.clkr,
435 [GPU_CC_PLL0] = &gpu_cc_pll0.clkr,
436 [GPU_CC_PLL1] = &gpu_cc_pll1.clkr,
437 [GPU_CC_SLEEP_CLK] = &gpu_cc_sleep_clk.clkr,
438 };
439
440 static const struct qcom_reset_map gpu_cc_sar2130p_resets[] = {
441 [GPUCC_GPU_CC_ACD_BCR] = { 0x9358 },
442 [GPUCC_GPU_CC_GX_ACD_IROOT_BCR] = { 0x958c },
443 [GPUCC_GPU_CC_GX_BCR] = { 0x9058 },
444 };
445
446 static struct gdsc *gpu_cc_sar2130p_gdscs[] = {
447 [GPU_CX_GDSC] = &gpu_cx_gdsc,
448 [GPU_GX_GDSC] = &gpu_gx_gdsc,
449 };
450
451 static const struct regmap_config gpu_cc_sar2130p_regmap_config = {
452 .reg_bits = 32,
453 .reg_stride = 4,
454 .val_bits = 32,
455 .max_register = 0xa000,
456 .fast_io = true,
457 };
458
459 static const struct qcom_cc_desc gpu_cc_sar2130p_desc = {
460 .config = &gpu_cc_sar2130p_regmap_config,
461 .clks = gpu_cc_sar2130p_clocks,
462 .num_clks = ARRAY_SIZE(gpu_cc_sar2130p_clocks),
463 .resets = gpu_cc_sar2130p_resets,
464 .num_resets = ARRAY_SIZE(gpu_cc_sar2130p_resets),
465 .gdscs = gpu_cc_sar2130p_gdscs,
466 .num_gdscs = ARRAY_SIZE(gpu_cc_sar2130p_gdscs),
467 };
468
469 static const struct of_device_id gpu_cc_sar2130p_match_table[] = {
470 { .compatible = "qcom,sar2130p-gpucc" },
471 { }
472 };
473 MODULE_DEVICE_TABLE(of, gpu_cc_sar2130p_match_table);
474
gpu_cc_sar2130p_probe(struct platform_device * pdev)475 static int gpu_cc_sar2130p_probe(struct platform_device *pdev)
476 {
477 struct device *dev = &pdev->dev;
478 struct regmap *regmap;
479
480 regmap = qcom_cc_map(pdev, &gpu_cc_sar2130p_desc);
481 if (IS_ERR(regmap))
482 return dev_err_probe(dev, PTR_ERR(regmap), "Couldn't map GPU_CC\n");
483
484 clk_lucid_ole_pll_configure(&gpu_cc_pll0, regmap, &gpu_cc_pll0_config);
485 clk_lucid_ole_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config);
486
487 /* Keep some clocks always-on */
488 qcom_branch_set_clk_en(regmap, 0x900c); /* GPU_CC_DEMET_CLK */
489
490 return qcom_cc_really_probe(dev, &gpu_cc_sar2130p_desc, regmap);
491 }
492
493 static struct platform_driver gpu_cc_sar2130p_driver = {
494 .probe = gpu_cc_sar2130p_probe,
495 .driver = {
496 .name = "gpu_cc-sar2130p",
497 .of_match_table = gpu_cc_sar2130p_match_table,
498 },
499 };
500 module_platform_driver(gpu_cc_sar2130p_driver);
501
502 MODULE_DESCRIPTION("QTI GPU_CC SAR2130P Driver");
503 MODULE_LICENSE("GPL");
504