xref: /openbmc/linux/drivers/clk/qcom/gpucc-sm6115.c (revision 35e6bcd1)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
4  * Copyright (c) 2023, Linaro Limited
5  */
6 
7 #include <linux/clk-provider.h>
8 #include <linux/module.h>
9 #include <linux/of_device.h>
10 #include <linux/regmap.h>
11 
12 #include <dt-bindings/clock/qcom,sm6115-gpucc.h>
13 
14 #include "clk-alpha-pll.h"
15 #include "clk-branch.h"
16 #include "clk-rcg.h"
17 #include "clk-regmap.h"
18 #include "clk-regmap-divider.h"
19 #include "clk-regmap-mux.h"
20 #include "clk-regmap-phy-mux.h"
21 #include "gdsc.h"
22 #include "reset.h"
23 
24 enum {
25 	DT_BI_TCXO,
26 	DT_GCC_GPU_GPLL0_CLK_SRC,
27 	DT_GCC_GPU_GPLL0_DIV_CLK_SRC,
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_AUX2,
35 	P_GPU_CC_PLL0_OUT_MAIN,
36 	P_GPU_CC_PLL1_OUT_AUX,
37 	P_GPU_CC_PLL1_OUT_MAIN,
38 };
39 
40 static struct pll_vco default_vco[] = {
41 	{ 1000000000, 2000000000, 0 },
42 };
43 
44 static struct pll_vco pll1_vco[] = {
45 	{ 500000000, 1000000000, 2 },
46 };
47 
48 static const struct alpha_pll_config gpu_cc_pll0_config = {
49 	.l = 0x3e,
50 	.alpha = 0,
51 	.alpha_hi = 0x80,
52 	.vco_val = 0x0 << 20,
53 	.vco_mask = GENMASK(21, 20),
54 	.alpha_en_mask = BIT(24),
55 	.main_output_mask = BIT(0),
56 	.aux_output_mask = BIT(1),
57 	.aux2_output_mask = BIT(2),
58 	.config_ctl_val = 0x4001055b,
59 	.test_ctl_hi1_val = 0x1,
60 };
61 
62 /* 1200MHz configuration */
63 static struct clk_alpha_pll gpu_cc_pll0 = {
64 	.offset = 0x0,
65 	.vco_table = default_vco,
66 	.num_vco = ARRAY_SIZE(default_vco),
67 	.flags = SUPPORTS_DYNAMIC_UPDATE,
68 	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
69 	.clkr = {
70 		.hw.init = &(struct clk_init_data){
71 			.name = "gpu_cc_pll0",
72 			.parent_data = &(const struct clk_parent_data){
73 				.index = DT_BI_TCXO,
74 			},
75 			.num_parents = 1,
76 			.ops = &clk_alpha_pll_ops,
77 		},
78 	},
79 };
80 
81 static const struct clk_div_table post_div_table_gpu_cc_pll0_out_aux2[] = {
82 	{ 0x0, 1 },
83 	{ }
84 };
85 
86 static struct clk_alpha_pll_postdiv gpu_cc_pll0_out_aux2 = {
87 	.offset = 0x0,
88 	.post_div_shift = 8,
89 	.post_div_table = post_div_table_gpu_cc_pll0_out_aux2,
90 	.num_post_div = ARRAY_SIZE(post_div_table_gpu_cc_pll0_out_aux2),
91 	.width = 4,
92 	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
93 	.clkr.hw.init = &(struct clk_init_data){
94 		.name = "gpu_cc_pll0_out_aux2",
95 		.parent_hws = (const struct clk_hw*[]) {
96 			&gpu_cc_pll0.clkr.hw,
97 		},
98 		.num_parents = 1,
99 		.flags = CLK_SET_RATE_PARENT,
100 		.ops = &clk_alpha_pll_postdiv_ops,
101 	},
102 };
103 
104 /* 640MHz configuration */
105 static const struct alpha_pll_config gpu_cc_pll1_config = {
106 	.l = 0x21,
107 	.alpha = 0x55555555,
108 	.alpha_hi = 0x55,
109 	.alpha_en_mask = BIT(24),
110 	.vco_val = 0x2 << 20,
111 	.vco_mask = GENMASK(21, 20),
112 	.main_output_mask = BIT(0),
113 	.aux_output_mask = BIT(1),
114 	.config_ctl_val = 0x4001055b,
115 	.test_ctl_hi1_val = 0x1,
116 };
117 
118 static struct clk_alpha_pll gpu_cc_pll1 = {
119 	.offset = 0x100,
120 	.vco_table = pll1_vco,
121 	.num_vco = ARRAY_SIZE(pll1_vco),
122 	.flags = SUPPORTS_DYNAMIC_UPDATE,
123 	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
124 	.clkr = {
125 		.hw.init = &(struct clk_init_data){
126 			.name = "gpu_cc_pll1",
127 			.parent_data = &(const struct clk_parent_data){
128 				.index = DT_BI_TCXO,
129 			},
130 			.num_parents = 1,
131 			.ops = &clk_alpha_pll_ops,
132 		},
133 	},
134 };
135 
136 static const struct clk_div_table post_div_table_gpu_cc_pll1_out_aux[] = {
137 	{ 0x0, 1 },
138 	{ }
139 };
140 
141 static struct clk_alpha_pll_postdiv gpu_cc_pll1_out_aux = {
142 	.offset = 0x100,
143 	.post_div_shift = 15,
144 	.post_div_table = post_div_table_gpu_cc_pll1_out_aux,
145 	.num_post_div = ARRAY_SIZE(post_div_table_gpu_cc_pll1_out_aux),
146 	.width = 3,
147 	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
148 	.clkr.hw.init = &(struct clk_init_data){
149 		.name = "gpu_cc_pll1_out_aux",
150 		.parent_hws = (const struct clk_hw*[]) {
151 			&gpu_cc_pll1.clkr.hw,
152 		},
153 		.num_parents = 1,
154 		.flags = CLK_SET_RATE_PARENT,
155 		.ops = &clk_alpha_pll_postdiv_ops,
156 	},
157 };
158 
159 static const struct parent_map gpu_cc_parent_map_0[] = {
160 	{ P_BI_TCXO, 0 },
161 	{ P_GPU_CC_PLL0_OUT_MAIN, 1 },
162 	{ P_GPU_CC_PLL1_OUT_MAIN, 3 },
163 	{ P_GPLL0_OUT_MAIN, 5 },
164 	{ P_GPLL0_OUT_MAIN_DIV, 6 },
165 };
166 
167 static const struct clk_parent_data gpu_cc_parent_data_0[] = {
168 	{ .index = P_BI_TCXO },
169 	{ .hw = &gpu_cc_pll0.clkr.hw },
170 	{ .hw = &gpu_cc_pll1.clkr.hw },
171 	{ .index = DT_GCC_GPU_GPLL0_CLK_SRC },
172 	{ .index = DT_GCC_GPU_GPLL0_DIV_CLK_SRC },
173 };
174 
175 static const struct parent_map gpu_cc_parent_map_1[] = {
176 	{ P_BI_TCXO, 0 },
177 	{ P_GPU_CC_PLL0_OUT_AUX2, 2 },
178 	{ P_GPU_CC_PLL1_OUT_AUX, 3 },
179 	{ P_GPLL0_OUT_MAIN, 5 },
180 };
181 
182 static const struct clk_parent_data gpu_cc_parent_data_1[] = {
183 	{ .index = P_BI_TCXO },
184 	{ .hw = &gpu_cc_pll0_out_aux2.clkr.hw },
185 	{ .hw = &gpu_cc_pll1_out_aux.clkr.hw },
186 	{ .index = DT_GCC_GPU_GPLL0_CLK_SRC },
187 };
188 
189 static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = {
190 	F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0),
191 	{ }
192 };
193 
194 static struct clk_rcg2 gpu_cc_gmu_clk_src = {
195 	.cmd_rcgr = 0x1120,
196 	.mnd_width = 0,
197 	.hid_width = 5,
198 	.parent_map = gpu_cc_parent_map_0,
199 	.freq_tbl = ftbl_gpu_cc_gmu_clk_src,
200 	.clkr.hw.init = &(struct clk_init_data){
201 		.name = "gpu_cc_gmu_clk_src",
202 		.parent_data = gpu_cc_parent_data_0,
203 		.num_parents = ARRAY_SIZE(gpu_cc_parent_data_0),
204 		.flags = CLK_SET_RATE_PARENT,
205 		.ops = &clk_rcg2_shared_ops,
206 	},
207 };
208 
209 static const struct freq_tbl ftbl_gpu_cc_gx_gfx3d_clk_src[] = {
210 	F(320000000, P_GPU_CC_PLL1_OUT_AUX, 2, 0, 0),
211 	F(465000000, P_GPU_CC_PLL1_OUT_AUX, 2, 0, 0),
212 	F(600000000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0),
213 	F(745000000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0),
214 	F(820000000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0),
215 	F(900000000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0),
216 	F(950000000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0),
217 	F(980000000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0),
218 	{ }
219 };
220 
221 static struct clk_rcg2 gpu_cc_gx_gfx3d_clk_src = {
222 	.cmd_rcgr = 0x101c,
223 	.mnd_width = 0,
224 	.hid_width = 5,
225 	.parent_map = gpu_cc_parent_map_1,
226 	.freq_tbl = ftbl_gpu_cc_gx_gfx3d_clk_src,
227 	.clkr.hw.init = &(struct clk_init_data){
228 		.name = "gpu_cc_gx_gfx3d_clk_src",
229 		.parent_data = gpu_cc_parent_data_1,
230 		.num_parents = ARRAY_SIZE(gpu_cc_parent_data_1),
231 		.flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
232 		.ops = &clk_rcg2_ops,
233 	},
234 };
235 
236 static struct clk_branch gpu_cc_ahb_clk = {
237 	.halt_reg = 0x1078,
238 	.halt_check = BRANCH_HALT_DELAY,
239 	.clkr = {
240 		.enable_reg = 0x1078,
241 		.enable_mask = BIT(0),
242 		.hw.init = &(struct clk_init_data){
243 			.name = "gpu_cc_ahb_clk",
244 			.flags = CLK_IS_CRITICAL,
245 			.ops = &clk_branch2_ops,
246 		},
247 	},
248 };
249 
250 static struct clk_branch gpu_cc_crc_ahb_clk = {
251 	.halt_reg = 0x107c,
252 	.halt_check = BRANCH_HALT_DELAY,
253 	.clkr = {
254 		.enable_reg = 0x107c,
255 		.enable_mask = BIT(0),
256 		.hw.init = &(struct clk_init_data){
257 			.name = "gpu_cc_crc_ahb_clk",
258 			.ops = &clk_branch2_ops,
259 		},
260 	},
261 };
262 
263 static struct clk_branch gpu_cc_cx_gfx3d_clk = {
264 	.halt_reg = 0x10a4,
265 	.halt_check = BRANCH_HALT_DELAY,
266 	.clkr = {
267 		.enable_reg = 0x10a4,
268 		.enable_mask = BIT(0),
269 		.hw.init = &(struct clk_init_data){
270 			.name = "gpu_cc_cx_gfx3d_clk",
271 			.parent_data = &(const struct clk_parent_data){
272 				.hw = &gpu_cc_gx_gfx3d_clk_src.clkr.hw,
273 			},
274 			.num_parents = 1,
275 			.flags = CLK_SET_RATE_PARENT,
276 			.ops = &clk_branch2_ops,
277 		},
278 	},
279 };
280 
281 static struct clk_branch gpu_cc_cx_gmu_clk = {
282 	.halt_reg = 0x1098,
283 	.halt_check = BRANCH_HALT,
284 	.clkr = {
285 		.enable_reg = 0x1098,
286 		.enable_mask = BIT(0),
287 		.hw.init = &(struct clk_init_data){
288 			.name = "gpu_cc_cx_gmu_clk",
289 			.parent_data = &(const struct clk_parent_data){
290 				.hw = &gpu_cc_gmu_clk_src.clkr.hw,
291 			},
292 			.num_parents = 1,
293 			.flags = CLK_SET_RATE_PARENT,
294 			.ops = &clk_branch2_ops,
295 		},
296 	},
297 };
298 
299 static struct clk_branch gpu_cc_cx_snoc_dvm_clk = {
300 	.halt_reg = 0x108c,
301 	.halt_check = BRANCH_HALT_DELAY,
302 	.clkr = {
303 		.enable_reg = 0x108c,
304 		.enable_mask = BIT(0),
305 		.hw.init = &(struct clk_init_data){
306 			.name = "gpu_cc_cx_snoc_dvm_clk",
307 			.ops = &clk_branch2_ops,
308 		},
309 	},
310 };
311 
312 static struct clk_branch gpu_cc_cxo_aon_clk = {
313 	.halt_reg = 0x1004,
314 	.halt_check = BRANCH_HALT_DELAY,
315 	.clkr = {
316 		.enable_reg = 0x1004,
317 		.enable_mask = BIT(0),
318 		.hw.init = &(struct clk_init_data){
319 			.name = "gpu_cc_cxo_aon_clk",
320 			.ops = &clk_branch2_ops,
321 		},
322 	},
323 };
324 
325 static struct clk_branch gpu_cc_cxo_clk = {
326 	.halt_reg = 0x109c,
327 	.halt_check = BRANCH_HALT,
328 	.clkr = {
329 		.enable_reg = 0x109c,
330 		.enable_mask = BIT(0),
331 		.hw.init = &(struct clk_init_data){
332 			.name = "gpu_cc_cxo_clk",
333 			.ops = &clk_branch2_ops,
334 		},
335 	},
336 };
337 
338 static struct clk_branch gpu_cc_gx_cxo_clk = {
339 	.halt_reg = 0x1060,
340 	.halt_check = BRANCH_HALT_DELAY,
341 	.clkr = {
342 		.enable_reg = 0x1060,
343 		.enable_mask = BIT(0),
344 		.hw.init = &(struct clk_init_data){
345 			.name = "gpu_cc_gx_cxo_clk",
346 			.flags = CLK_IS_CRITICAL,
347 			.ops = &clk_branch2_ops,
348 		},
349 	},
350 };
351 
352 static struct clk_branch gpu_cc_gx_gfx3d_clk = {
353 	.halt_reg = 0x1054,
354 	.halt_check = BRANCH_HALT_SKIP,
355 	.clkr = {
356 		.enable_reg = 0x1054,
357 		.enable_mask = BIT(0),
358 		.hw.init = &(struct clk_init_data){
359 			.name = "gpu_cc_gx_gfx3d_clk",
360 			.parent_data = &(const struct clk_parent_data){
361 				.hw = &gpu_cc_gx_gfx3d_clk_src.clkr.hw,
362 			},
363 			.num_parents = 1,
364 			.flags = CLK_SET_RATE_PARENT,
365 			.ops = &clk_branch2_ops,
366 		},
367 	},
368 };
369 
370 static struct clk_branch gpu_cc_sleep_clk = {
371 	.halt_reg = 0x1090,
372 	.halt_check = BRANCH_HALT_DELAY,
373 	.clkr = {
374 		.enable_reg = 0x1090,
375 		.enable_mask = BIT(0),
376 		.hw.init = &(struct clk_init_data){
377 			.name = "gpu_cc_sleep_clk",
378 			.ops = &clk_branch2_ops,
379 		},
380 	},
381 };
382 
383 static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk = {
384 	.halt_reg = 0x5000,
385 	.halt_check = BRANCH_VOTED,
386 	.clkr = {
387 		.enable_reg = 0x5000,
388 		.enable_mask = BIT(0),
389 		.hw.init = &(struct clk_init_data){
390 			 .name = "gpu_cc_hlos1_vote_gpu_smmu_clk",
391 			 .ops = &clk_branch2_ops,
392 		},
393 	},
394 };
395 
396 static struct gdsc gpu_cx_gdsc = {
397 	.gdscr = 0x106c,
398 	.gds_hw_ctrl = 0x1540,
399 	.pd = {
400 		.name = "gpu_cx_gdsc",
401 	},
402 	.pwrsts = PWRSTS_OFF_ON,
403 	.flags = VOTABLE,
404 };
405 
406 static struct gdsc gpu_gx_gdsc = {
407 	.gdscr = 0x100c,
408 	.clamp_io_ctrl = 0x1508,
409 	.resets = (unsigned int []){ GPU_GX_BCR },
410 	.reset_count = 1,
411 	.pd = {
412 		.name = "gpu_gx_gdsc",
413 	},
414 	.parent = &gpu_cx_gdsc.pd,
415 	.pwrsts = PWRSTS_OFF_ON,
416 	.flags = CLAMP_IO | SW_RESET | VOTABLE,
417 };
418 
419 static struct clk_regmap *gpu_cc_sm6115_clocks[] = {
420 	[GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr,
421 	[GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr,
422 	[GPU_CC_CX_GFX3D_CLK] = &gpu_cc_cx_gfx3d_clk.clkr,
423 	[GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr,
424 	[GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_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_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr,
428 	[GPU_CC_GX_CXO_CLK] = &gpu_cc_gx_cxo_clk.clkr,
429 	[GPU_CC_GX_GFX3D_CLK] = &gpu_cc_gx_gfx3d_clk.clkr,
430 	[GPU_CC_GX_GFX3D_CLK_SRC] = &gpu_cc_gx_gfx3d_clk_src.clkr,
431 	[GPU_CC_PLL0] = &gpu_cc_pll0.clkr,
432 	[GPU_CC_PLL0_OUT_AUX2] = &gpu_cc_pll0_out_aux2.clkr,
433 	[GPU_CC_PLL1] = &gpu_cc_pll1.clkr,
434 	[GPU_CC_PLL1_OUT_AUX] = &gpu_cc_pll1_out_aux.clkr,
435 	[GPU_CC_SLEEP_CLK] = &gpu_cc_sleep_clk.clkr,
436 	[GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK] = &gpu_cc_hlos1_vote_gpu_smmu_clk.clkr,
437 };
438 
439 static const struct qcom_reset_map gpu_cc_sm6115_resets[] = {
440 	[GPU_GX_BCR] = { 0x1008 },
441 };
442 
443 static struct gdsc *gpu_cc_sm6115_gdscs[] = {
444 	[GPU_CX_GDSC] = &gpu_cx_gdsc,
445 	[GPU_GX_GDSC] = &gpu_gx_gdsc,
446 };
447 
448 static const struct regmap_config gpu_cc_sm6115_regmap_config = {
449 	.reg_bits = 32,
450 	.reg_stride = 4,
451 	.val_bits = 32,
452 	.max_register = 0x9000,
453 	.fast_io = true,
454 };
455 
456 static const struct qcom_cc_desc gpu_cc_sm6115_desc = {
457 	.config = &gpu_cc_sm6115_regmap_config,
458 	.clks = gpu_cc_sm6115_clocks,
459 	.num_clks = ARRAY_SIZE(gpu_cc_sm6115_clocks),
460 	.resets = gpu_cc_sm6115_resets,
461 	.num_resets = ARRAY_SIZE(gpu_cc_sm6115_resets),
462 	.gdscs = gpu_cc_sm6115_gdscs,
463 	.num_gdscs = ARRAY_SIZE(gpu_cc_sm6115_gdscs),
464 };
465 
466 static const struct of_device_id gpu_cc_sm6115_match_table[] = {
467 	{ .compatible = "qcom,sm6115-gpucc" },
468 	{ }
469 };
470 MODULE_DEVICE_TABLE(of, gpu_cc_sm6115_match_table);
471 
472 static int gpu_cc_sm6115_probe(struct platform_device *pdev)
473 {
474 	struct regmap *regmap;
475 
476 	regmap = qcom_cc_map(pdev, &gpu_cc_sm6115_desc);
477 	if (IS_ERR(regmap))
478 		return PTR_ERR(regmap);
479 
480 	clk_alpha_pll_configure(&gpu_cc_pll0, regmap, &gpu_cc_pll0_config);
481 	clk_alpha_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config);
482 
483 	/* Set recommended WAKEUP/SLEEP settings for the gpu_cc_cx_gmu_clk */
484 	qcom_branch_set_wakeup(regmap, gpu_cc_cx_gmu_clk, 0xf);
485 	qcom_branch_set_sleep(regmap, gpu_cc_cx_gmu_clk, 0xf);
486 
487 	qcom_branch_set_force_mem_core(regmap, gpu_cc_gx_gfx3d_clk, true);
488 	qcom_branch_set_force_periph_on(regmap, gpu_cc_gx_gfx3d_clk, true);
489 
490 	return qcom_cc_really_probe(pdev, &gpu_cc_sm6115_desc, regmap);
491 }
492 
493 static struct platform_driver gpu_cc_sm6115_driver = {
494 	.probe = gpu_cc_sm6115_probe,
495 	.driver = {
496 		.name = "sm6115-gpucc",
497 		.of_match_table = gpu_cc_sm6115_match_table,
498 	},
499 };
500 module_platform_driver(gpu_cc_sm6115_driver);
501 
502 MODULE_DESCRIPTION("QTI GPU_CC SM6115 Driver");
503 MODULE_LICENSE("GPL");
504