xref: /linux/drivers/clk/qcom/gpucc-sm8750.c (revision d2c9a99135da931377240942d44f3dea104cedb8)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
4  */
5 #include <linux/clk-provider.h>
6 #include <linux/module.h>
7 #include <linux/platform_device.h>
8 #include <linux/pm_runtime.h>
9 #include <linux/regmap.h>
10 
11 #include <dt-bindings/clock/qcom,sm8750-gpucc.h>
12 
13 #include "clk-alpha-pll.h"
14 #include "clk-branch.h"
15 #include "clk-rcg.h"
16 #include "clk-regmap.h"
17 #include "clk-regmap-divider.h"
18 #include "clk-regmap-mux.h"
19 #include "gdsc.h"
20 #include "reset.h"
21 
22 enum {
23 	DT_BI_TCXO,
24 	DT_GPLL0_OUT_MAIN,
25 	DT_GPLL0_OUT_MAIN_DIV,
26 };
27 
28 enum {
29 	P_BI_TCXO,
30 	P_GPLL0_OUT_MAIN,
31 	P_GPLL0_OUT_MAIN_DIV,
32 	P_GPU_CC_PLL0_OUT_EVEN,
33 	P_GPU_CC_PLL0_OUT_MAIN,
34 	P_GPU_CC_PLL0_OUT_ODD,
35 };
36 
37 static const struct pll_vco taycan_elu_vco[] = {
38 	{ 249600000, 2500000000, 0 },
39 };
40 
41 static const struct alpha_pll_config gpu_cc_pll0_config = {
42 	.l = 0x34,
43 	.alpha = 0x1555,
44 	.config_ctl_val = 0x19660387,
45 	.config_ctl_hi_val = 0x098060a0,
46 	.config_ctl_hi1_val = 0xb416cb20,
47 	.user_ctl_val = 0x00000400,
48 	.user_ctl_hi_val = 0x00000002,
49 };
50 
51 static struct clk_alpha_pll gpu_cc_pll0 = {
52 	.offset = 0x0,
53 	.config = &gpu_cc_pll0_config,
54 	.vco_table = taycan_elu_vco,
55 	.num_vco = ARRAY_SIZE(taycan_elu_vco),
56 	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_ELU],
57 	.clkr = {
58 		.hw.init = &(const struct clk_init_data) {
59 			.name = "gpu_cc_pll0",
60 			.parent_data = &(const struct clk_parent_data) {
61 				.index = DT_BI_TCXO,
62 			},
63 			.num_parents = 1,
64 			.ops = &clk_alpha_pll_taycan_elu_ops,
65 		},
66 	},
67 };
68 
69 static const struct clk_div_table post_div_table_gpu_cc_pll0_out_even[] = {
70 	{ 0x1, 2 },
71 	{ }
72 };
73 
74 static struct clk_alpha_pll_postdiv gpu_cc_pll0_out_even = {
75 	.offset = 0x0,
76 	.post_div_shift = 10,
77 	.post_div_table = post_div_table_gpu_cc_pll0_out_even,
78 	.num_post_div = ARRAY_SIZE(post_div_table_gpu_cc_pll0_out_even),
79 	.width = 4,
80 	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_ELU],
81 	.clkr.hw.init = &(const struct clk_init_data) {
82 		.name = "gpu_cc_pll0_out_even",
83 		.parent_hws = (const struct clk_hw*[]) {
84 			&gpu_cc_pll0.clkr.hw,
85 		},
86 		.num_parents = 1,
87 		.flags = CLK_SET_RATE_PARENT,
88 		.ops = &clk_alpha_pll_postdiv_taycan_elu_ops,
89 	},
90 };
91 
92 static const struct parent_map gpu_cc_parent_map_1[] = {
93 	{ P_BI_TCXO, 0 },
94 	{ P_GPU_CC_PLL0_OUT_MAIN, 1 },
95 	{ P_GPU_CC_PLL0_OUT_EVEN, 2 },
96 	{ P_GPU_CC_PLL0_OUT_ODD, 3 },
97 	{ P_GPLL0_OUT_MAIN, 5 },
98 	{ P_GPLL0_OUT_MAIN_DIV, 6 },
99 };
100 
101 static const struct clk_parent_data gpu_cc_parent_data_1[] = {
102 	{ .index = DT_BI_TCXO },
103 	{ .hw = &gpu_cc_pll0.clkr.hw },
104 	{ .hw = &gpu_cc_pll0_out_even.clkr.hw },
105 	{ .hw = &gpu_cc_pll0.clkr.hw },
106 	{ .index = DT_GPLL0_OUT_MAIN },
107 	{ .index = DT_GPLL0_OUT_MAIN_DIV },
108 };
109 
110 static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = {
111 	F(19200000, P_BI_TCXO, 1, 0, 0),
112 	F(500000000, P_GPU_CC_PLL0_OUT_EVEN, 1, 0, 0),
113 	F(650000000, P_GPU_CC_PLL0_OUT_EVEN, 1, 0, 0),
114 	F(687500000, P_GPU_CC_PLL0_OUT_EVEN, 1, 0, 0),
115 	{ }
116 };
117 
118 static struct clk_rcg2 gpu_cc_gmu_clk_src = {
119 	.cmd_rcgr = 0x9318,
120 	.mnd_width = 0,
121 	.hid_width = 5,
122 	.parent_map = gpu_cc_parent_map_1,
123 	.freq_tbl = ftbl_gpu_cc_gmu_clk_src,
124 	.clkr.hw.init = &(const struct clk_init_data) {
125 		.name = "gpu_cc_gmu_clk_src",
126 		.parent_data = gpu_cc_parent_data_1,
127 		.num_parents = ARRAY_SIZE(gpu_cc_parent_data_1),
128 		.flags = CLK_SET_RATE_PARENT,
129 		.ops = &clk_rcg2_shared_ops,
130 	},
131 };
132 
133 static const struct freq_tbl ftbl_gpu_cc_hub_clk_src[] = {
134 	F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0),
135 	F(300000000, P_GPLL0_OUT_MAIN, 2, 0, 0),
136 	F(400000000, P_GPLL0_OUT_MAIN, 1.5, 0, 0),
137 	{ }
138 };
139 
140 static struct clk_rcg2 gpu_cc_hub_clk_src = {
141 	.cmd_rcgr = 0x93ec,
142 	.mnd_width = 0,
143 	.hid_width = 5,
144 	.parent_map = gpu_cc_parent_map_1,
145 	.freq_tbl = ftbl_gpu_cc_hub_clk_src,
146 	.clkr.hw.init = &(const struct clk_init_data) {
147 		.name = "gpu_cc_hub_clk_src",
148 		.parent_data = gpu_cc_parent_data_1,
149 		.num_parents = ARRAY_SIZE(gpu_cc_parent_data_1),
150 		.flags = CLK_SET_RATE_PARENT,
151 		.ops = &clk_rcg2_shared_ops,
152 	},
153 };
154 
155 static struct clk_regmap_div gpu_cc_hub_div_clk_src = {
156 	.reg = 0x942c,
157 	.shift = 0,
158 	.width = 4,
159 	.clkr.hw.init = &(const struct clk_init_data) {
160 		.name = "gpu_cc_hub_div_clk_src",
161 		.parent_hws = (const struct clk_hw*[]) {
162 			&gpu_cc_hub_clk_src.clkr.hw,
163 		},
164 		.num_parents = 1,
165 		.flags = CLK_SET_RATE_PARENT,
166 		.ops = &clk_regmap_div_ro_ops,
167 	},
168 };
169 
170 static struct clk_branch gpu_cc_ahb_clk = {
171 	.halt_reg = 0x90bc,
172 	.halt_check = BRANCH_HALT_DELAY,
173 	.clkr = {
174 		.enable_reg = 0x90bc,
175 		.enable_mask = BIT(0),
176 		.hw.init = &(const struct clk_init_data) {
177 			.name = "gpu_cc_ahb_clk",
178 			.parent_hws = (const struct clk_hw*[]) {
179 				&gpu_cc_hub_div_clk_src.clkr.hw,
180 			},
181 			.num_parents = 1,
182 			.flags = CLK_SET_RATE_PARENT,
183 			.ops = &clk_branch2_ops,
184 		},
185 	},
186 };
187 
188 static struct clk_branch gpu_cc_cx_accu_shift_clk = {
189 	.halt_reg = 0x910c,
190 	.halt_check = BRANCH_HALT_VOTED,
191 	.clkr = {
192 		.enable_reg = 0x910c,
193 		.enable_mask = BIT(0),
194 		.hw.init = &(const struct clk_init_data) {
195 			.name = "gpu_cc_cx_accu_shift_clk",
196 			.ops = &clk_branch2_ops,
197 		},
198 	},
199 };
200 
201 static struct clk_branch gpu_cc_cx_gmu_clk = {
202 	.halt_reg = 0x90d4,
203 	.halt_check = BRANCH_HALT_VOTED,
204 	.clkr = {
205 		.enable_reg = 0x90d4,
206 		.enable_mask = BIT(0),
207 		.hw.init = &(const struct clk_init_data) {
208 			.name = "gpu_cc_cx_gmu_clk",
209 			.parent_hws = (const struct clk_hw*[]) {
210 				&gpu_cc_gmu_clk_src.clkr.hw,
211 			},
212 			.num_parents = 1,
213 			.flags = CLK_SET_RATE_PARENT,
214 			.ops = &clk_branch2_aon_ops,
215 		},
216 	},
217 };
218 
219 static struct clk_branch gpu_cc_cxo_clk = {
220 	.halt_reg = 0x90e4,
221 	.halt_check = BRANCH_HALT,
222 	.clkr = {
223 		.enable_reg = 0x90e4,
224 		.enable_mask = BIT(0),
225 		.hw.init = &(const struct clk_init_data) {
226 			.name = "gpu_cc_cxo_clk",
227 			.ops = &clk_branch2_ops,
228 		},
229 	},
230 };
231 
232 static struct clk_branch gpu_cc_demet_clk = {
233 	.halt_reg = 0x9010,
234 	.halt_check = BRANCH_HALT_VOTED,
235 	.clkr = {
236 		.enable_reg = 0x9010,
237 		.enable_mask = BIT(0),
238 		.hw.init = &(const struct clk_init_data) {
239 			.name = "gpu_cc_demet_clk",
240 			.ops = &clk_branch2_ops,
241 		},
242 	},
243 };
244 
245 static struct clk_branch gpu_cc_dpm_clk = {
246 	.halt_reg = 0x9110,
247 	.halt_check = BRANCH_HALT,
248 	.clkr = {
249 		.enable_reg = 0x9110,
250 		.enable_mask = BIT(0),
251 		.hw.init = &(const struct clk_init_data) {
252 			.name = "gpu_cc_dpm_clk",
253 			.ops = &clk_branch2_ops,
254 		},
255 	},
256 };
257 
258 static struct clk_branch gpu_cc_freq_measure_clk = {
259 	.halt_reg = 0x900c,
260 	.halt_check = BRANCH_HALT,
261 	.clkr = {
262 		.enable_reg = 0x900c,
263 		.enable_mask = BIT(0),
264 		.hw.init = &(const struct clk_init_data) {
265 			.name = "gpu_cc_freq_measure_clk",
266 			.ops = &clk_branch2_ops,
267 		},
268 	},
269 };
270 
271 static struct clk_branch gpu_cc_gx_accu_shift_clk = {
272 	.halt_reg = 0x9070,
273 	.halt_check = BRANCH_HALT_VOTED,
274 	.clkr = {
275 		.enable_reg = 0x9070,
276 		.enable_mask = BIT(0),
277 		.hw.init = &(const struct clk_init_data) {
278 			.name = "gpu_cc_gx_accu_shift_clk",
279 			.ops = &clk_branch2_ops,
280 		},
281 	},
282 };
283 
284 static struct clk_branch gpu_cc_gx_gmu_clk = {
285 	.halt_reg = 0x9060,
286 	.halt_check = BRANCH_HALT,
287 	.clkr = {
288 		.enable_reg = 0x9060,
289 		.enable_mask = BIT(0),
290 		.hw.init = &(const struct clk_init_data) {
291 			.name = "gpu_cc_gx_gmu_clk",
292 			.parent_hws = (const struct clk_hw*[]) {
293 				&gpu_cc_gmu_clk_src.clkr.hw,
294 			},
295 			.num_parents = 1,
296 			.flags = CLK_SET_RATE_PARENT,
297 			.ops = &clk_branch2_ops,
298 		},
299 	},
300 };
301 
302 static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk = {
303 	.halt_reg = 0x7000,
304 	.halt_check = BRANCH_HALT_VOTED,
305 	.clkr = {
306 		.enable_reg = 0x7000,
307 		.enable_mask = BIT(0),
308 		.hw.init = &(const struct clk_init_data) {
309 			.name = "gpu_cc_hlos1_vote_gpu_smmu_clk",
310 			.ops = &clk_branch2_ops,
311 		},
312 	},
313 };
314 
315 static struct clk_branch gpu_cc_hub_aon_clk = {
316 	.halt_reg = 0x93e8,
317 	.halt_check = BRANCH_HALT_VOTED,
318 	.clkr = {
319 		.enable_reg = 0x93e8,
320 		.enable_mask = BIT(0),
321 		.hw.init = &(const struct clk_init_data) {
322 			.name = "gpu_cc_hub_aon_clk",
323 			.parent_hws = (const struct clk_hw*[]) {
324 				&gpu_cc_hub_clk_src.clkr.hw,
325 			},
326 			.num_parents = 1,
327 			.flags = CLK_SET_RATE_PARENT,
328 			.ops = &clk_branch2_aon_ops,
329 		},
330 	},
331 };
332 
333 static struct clk_branch gpu_cc_hub_cx_int_clk = {
334 	.halt_reg = 0x90e8,
335 	.halt_check = BRANCH_HALT_VOTED,
336 	.clkr = {
337 		.enable_reg = 0x90e8,
338 		.enable_mask = BIT(0),
339 		.hw.init = &(const struct clk_init_data) {
340 			.name = "gpu_cc_hub_cx_int_clk",
341 			.parent_hws = (const struct clk_hw*[]) {
342 				&gpu_cc_hub_clk_src.clkr.hw,
343 			},
344 			.num_parents = 1,
345 			.flags = CLK_SET_RATE_PARENT,
346 			.ops = &clk_branch2_aon_ops,
347 		},
348 	},
349 };
350 
351 static struct clk_branch gpu_cc_memnoc_gfx_clk = {
352 	.halt_reg = 0x90f4,
353 	.halt_check = BRANCH_HALT_VOTED,
354 	.clkr = {
355 		.enable_reg = 0x90f4,
356 		.enable_mask = BIT(0),
357 		.hw.init = &(const struct clk_init_data) {
358 			.name = "gpu_cc_memnoc_gfx_clk",
359 			.ops = &clk_branch2_ops,
360 		},
361 	},
362 };
363 
364 static struct gdsc gpu_cc_cx_gdsc = {
365 	.gdscr = 0x9080,
366 	.gds_hw_ctrl = 0x9094,
367 	.en_rest_wait_val = 0x2,
368 	.en_few_wait_val = 0x2,
369 	.clk_dis_wait_val = 0x8,
370 	.pd = {
371 		.name = "gpu_cc_cx_gdsc",
372 	},
373 	.pwrsts = PWRSTS_OFF_ON,
374 	.flags = RETAIN_FF_ENABLE | VOTABLE,
375 };
376 
377 static struct clk_regmap *gpu_cc_sm8750_clocks[] = {
378 	[GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr,
379 	[GPU_CC_CX_ACCU_SHIFT_CLK] = &gpu_cc_cx_accu_shift_clk.clkr,
380 	[GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr,
381 	[GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr,
382 	[GPU_CC_DEMET_CLK] = &gpu_cc_demet_clk.clkr,
383 	[GPU_CC_DPM_CLK] = &gpu_cc_dpm_clk.clkr,
384 	[GPU_CC_FREQ_MEASURE_CLK] = &gpu_cc_freq_measure_clk.clkr,
385 	[GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr,
386 	[GPU_CC_GX_ACCU_SHIFT_CLK] = &gpu_cc_gx_accu_shift_clk.clkr,
387 	[GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr,
388 	[GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK] = &gpu_cc_hlos1_vote_gpu_smmu_clk.clkr,
389 	[GPU_CC_HUB_AON_CLK] = &gpu_cc_hub_aon_clk.clkr,
390 	[GPU_CC_HUB_CLK_SRC] = &gpu_cc_hub_clk_src.clkr,
391 	[GPU_CC_HUB_CX_INT_CLK] = &gpu_cc_hub_cx_int_clk.clkr,
392 	[GPU_CC_HUB_DIV_CLK_SRC] = &gpu_cc_hub_div_clk_src.clkr,
393 	[GPU_CC_MEMNOC_GFX_CLK] = &gpu_cc_memnoc_gfx_clk.clkr,
394 	[GPU_CC_PLL0] = &gpu_cc_pll0.clkr,
395 	[GPU_CC_PLL0_OUT_EVEN] = &gpu_cc_pll0_out_even.clkr,
396 };
397 
398 static struct gdsc *gpu_cc_sm8750_gdscs[] = {
399 	[GPU_CC_CX_GDSC] = &gpu_cc_cx_gdsc,
400 };
401 
402 static const struct qcom_reset_map gpu_cc_sm8750_resets[] = {
403 	[GPU_CC_GPU_CC_XO_BCR] = { 0x9000 },
404 	[GPU_CC_GPU_CC_GX_BCR] = { 0x905c },
405 	[GPU_CC_GPU_CC_CX_BCR] = { 0x907c },
406 	[GPU_CC_GPU_CC_GMU_BCR] = { 0x9314 },
407 	[GPU_CC_GPU_CC_CB_BCR] = { 0x93a0 },
408 	[GPU_CC_GPU_CC_FAST_HUB_BCR] = { 0x93e4 },
409 };
410 
411 static const struct regmap_config gpu_cc_sm8750_regmap_config = {
412 	.reg_bits = 32,
413 	.reg_stride = 4,
414 	.val_bits = 32,
415 	.max_register = 0x9800,
416 	.fast_io = true,
417 };
418 
419 static struct clk_alpha_pll *gpu_cc_alpha_plls[] = {
420 	&gpu_cc_pll0,
421 };
422 
423 static const u32 gpu_cc_sm8750_critical_cbcrs[] = {
424 	0x9004, /* GPU_CC_RSCC_XO_AON_CLK */
425 	0x9008, /* GPU_CC_CXO_AON_CLK */
426 	0x9064, /* GPU_CC_GX_AHB_FF_CLK */
427 	0x90cc, /* GPU_CC_SLEEP_CLK */
428 	0x93a4, /* GPU_CC_CB_CLK */
429 	0x93a8, /* GPU_CC_RSCC_HUB_AON_CLK */
430 };
431 
432 static const struct qcom_cc_driver_data gpu_cc_sm8750_driver_data = {
433 	.alpha_plls = gpu_cc_alpha_plls,
434 	.num_alpha_plls = ARRAY_SIZE(gpu_cc_alpha_plls),
435 	.clk_cbcrs = gpu_cc_sm8750_critical_cbcrs,
436 	.num_clk_cbcrs = ARRAY_SIZE(gpu_cc_sm8750_critical_cbcrs),
437 };
438 
439 static const struct qcom_cc_desc gpu_cc_sm8750_desc = {
440 	.config = &gpu_cc_sm8750_regmap_config,
441 	.clks = gpu_cc_sm8750_clocks,
442 	.num_clks = ARRAY_SIZE(gpu_cc_sm8750_clocks),
443 	.resets = gpu_cc_sm8750_resets,
444 	.num_resets = ARRAY_SIZE(gpu_cc_sm8750_resets),
445 	.gdscs = gpu_cc_sm8750_gdscs,
446 	.num_gdscs = ARRAY_SIZE(gpu_cc_sm8750_gdscs),
447 	.use_rpm = true,
448 	.driver_data = &gpu_cc_sm8750_driver_data,
449 };
450 
451 static const struct of_device_id gpu_cc_sm8750_match_table[] = {
452 	{ .compatible = "qcom,sm8750-gpucc" },
453 	{ }
454 };
455 MODULE_DEVICE_TABLE(of, gpu_cc_sm8750_match_table);
456 
gpu_cc_sm8750_probe(struct platform_device * pdev)457 static int gpu_cc_sm8750_probe(struct platform_device *pdev)
458 {
459 	return qcom_cc_probe(pdev, &gpu_cc_sm8750_desc);
460 }
461 
462 static struct platform_driver gpu_cc_sm8750_driver = {
463 	.probe = gpu_cc_sm8750_probe,
464 	.driver = {
465 		.name = "sm8750-gpucc",
466 		.of_match_table = gpu_cc_sm8750_match_table,
467 	},
468 };
469 module_platform_driver(gpu_cc_sm8750_driver);
470 
471 MODULE_DESCRIPTION("QTI GPU_CC SM8750 Driver");
472 MODULE_LICENSE("GPL");
473