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