File Index
Files and directories
Sign in
FILE

gpucc-sm6350.c

File preview with syntax highlighting.

linux-6.19.14/drivers/clk/qcom/gpucc-sm6350.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (c) 2021, The Linux Foundation. All rights reserved.
  4 * Copyright (c) 2021, Konrad Dybcio <konrad.dybcio@somainline.org>
  5 */
  6
  7#include <linux/clk-provider.h>
  8#include <linux/mod_devicetable.h>
  9#include <linux/module.h>
 10#include <linux/platform_device.h>
 11#include <linux/regmap.h>
 12
 13#include <dt-bindings/clock/qcom,gpucc-sm6350.h>
 14
 15#include "common.h"
 16#include "clk-alpha-pll.h"
 17#include "clk-branch.h"
 18#include "clk-rcg.h"
 19#include "clk-regmap.h"
 20#include "reset.h"
 21#include "gdsc.h"
 22
 23#define CX_GMU_CBCR_SLEEP_MASK		0xF
 24#define CX_GMU_CBCR_SLEEP_SHIFT		4
 25#define CX_GMU_CBCR_WAKE_MASK		0xF
 26#define CX_GMU_CBCR_WAKE_SHIFT		8
 27
 28enum {
 29	DT_BI_TCXO,
 30	DT_GPLL0_OUT_MAIN,
 31	DT_GPLL0_OUT_MAIN_DIV,
 32};
 33
 34enum {
 35	P_BI_TCXO,
 36	P_GPLL0_OUT_MAIN,
 37	P_GPLL0_OUT_MAIN_DIV,
 38	P_GPU_CC_PLL0_OUT_MAIN,
 39	P_GPU_CC_PLL0_OUT_ODD,
 40	P_GPU_CC_PLL1_OUT_EVEN,
 41	P_GPU_CC_PLL1_OUT_MAIN,
 42	P_GPU_CC_PLL1_OUT_ODD,
 43	P_CRC_DIV,
 44};
 45
 46static const struct pll_vco fabia_vco[] = {
 47	{ 249600000, 2000000000, 0 },
 48};
 49
 50/* 506MHz Configuration*/
 51static const struct alpha_pll_config gpu_cc_pll0_config = {
 52	.l = 0x1A,
 53	.alpha = 0x5AAA,
 54	.config_ctl_val = 0x20485699,
 55	.config_ctl_hi_val = 0x00002067,
 56	.test_ctl_val = 0x40000000,
 57	.test_ctl_hi_val = 0x00000002,
 58	.user_ctl_val = 0x00000001,
 59	.user_ctl_hi_val = 0x00004805,
 60};
 61
 62static struct clk_alpha_pll gpu_cc_pll0 = {
 63	.offset = 0x0,
 64	.vco_table = fabia_vco,
 65	.num_vco = ARRAY_SIZE(fabia_vco),
 66	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
 67	.clkr = {
 68		.hw.init = &(struct clk_init_data){
 69			.name = "gpu_cc_pll0",
 70			.parent_data = &(const struct clk_parent_data){
 71				.index = DT_BI_TCXO,
 72				.fw_name = "bi_tcxo",
 73			},
 74			.num_parents = 1,
 75			.ops = &clk_alpha_pll_fabia_ops,
 76		},
 77	},
 78};
 79
 80static struct clk_fixed_factor crc_div = {
 81	.mult = 1,
 82	.div = 2,
 83	.hw.init = &(struct clk_init_data){
 84		.name = "crc_div",
 85		.parent_hws = (const struct clk_hw*[]){
 86			&gpu_cc_pll0.clkr.hw,
 87		},
 88		.num_parents = 1,
 89		.flags = CLK_SET_RATE_PARENT,
 90		.ops = &clk_fixed_factor_ops,
 91	},
 92};
 93
 94/* 514MHz Configuration*/
 95static const struct alpha_pll_config gpu_cc_pll1_config = {
 96	.l = 0x1A,
 97	.alpha = 0xC555,
 98	.config_ctl_val = 0x20485699,
 99	.config_ctl_hi_val = 0x00002067,
100	.test_ctl_val = 0x40000000,
101	.test_ctl_hi_val = 0x00000002,
102	.user_ctl_val = 0x00000001,
103	.user_ctl_hi_val = 0x00004805,
104};
105
106static struct clk_alpha_pll gpu_cc_pll1 = {
107	.offset = 0x100,
108	.vco_table = fabia_vco,
109	.num_vco = ARRAY_SIZE(fabia_vco),
110	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
111	.clkr = {
112		.hw.init = &(struct clk_init_data){
113			.name = "gpu_cc_pll1",
114			.parent_data = &(const struct clk_parent_data){
115				.index = DT_BI_TCXO,
116				.fw_name = "bi_tcxo",
117			},
118			.num_parents = 1,
119			.ops = &clk_alpha_pll_fabia_ops,
120		},
121	},
122};
123
124static const struct parent_map gpu_cc_parent_map_0[] = {
125	{ P_BI_TCXO, 0 },
126	{ P_GPU_CC_PLL0_OUT_MAIN, 1 },
127	{ P_GPU_CC_PLL1_OUT_MAIN, 3 },
128	{ P_GPLL0_OUT_MAIN, 5 },
129	{ P_GPLL0_OUT_MAIN_DIV, 6 },
130};
131
132static const struct clk_parent_data gpu_cc_parent_data_0[] = {
133	{ .index = DT_BI_TCXO, .fw_name = "bi_tcxo" },
134	{ .hw = &gpu_cc_pll0.clkr.hw },
135	{ .hw = &gpu_cc_pll1.clkr.hw },
136	{ .index = DT_GPLL0_OUT_MAIN, .fw_name = "gcc_gpu_gpll0_clk_src" },
137	{ .index = DT_GPLL0_OUT_MAIN_DIV, .fw_name = "gcc_gpu_gpll0_div_clk_src" },
138};
139
140static const struct parent_map gpu_cc_parent_map_1[] = {
141	{ P_BI_TCXO, 0 },
142	{ P_CRC_DIV, 1 },
143	{ P_GPU_CC_PLL0_OUT_ODD, 2 },
144	{ P_GPU_CC_PLL1_OUT_EVEN, 3 },
145	{ P_GPU_CC_PLL1_OUT_ODD, 4 },
146	{ P_GPLL0_OUT_MAIN, 5 },
147};
148
149static const struct clk_parent_data gpu_cc_parent_data_1[] = {
150	{ .index = DT_BI_TCXO, .fw_name = "bi_tcxo" },
151	{ .hw = &crc_div.hw },
152	{ .hw = &gpu_cc_pll0.clkr.hw },
153	{ .hw = &gpu_cc_pll1.clkr.hw },
154	{ .hw = &gpu_cc_pll1.clkr.hw },
155	{ .index = DT_GPLL0_OUT_MAIN, .fw_name = "gcc_gpu_gpll0_clk_src" },
156};
157
158static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = {
159	F(200000000, P_GPLL0_OUT_MAIN_DIV, 1.5, 0, 0),
160	{ }
161};
162
163static struct clk_rcg2 gpu_cc_gmu_clk_src = {
164	.cmd_rcgr = 0x1120,
165	.mnd_width = 0,
166	.hid_width = 5,
167	.parent_map = gpu_cc_parent_map_0,
168	.freq_tbl = ftbl_gpu_cc_gmu_clk_src,
169	.clkr.hw.init = &(struct clk_init_data){
170		.name = "gpu_cc_gmu_clk_src",
171		.parent_data = gpu_cc_parent_data_0,
172		.num_parents = ARRAY_SIZE(gpu_cc_parent_data_0),
173		.flags = CLK_SET_RATE_PARENT,
174		.ops = &clk_rcg2_ops,
175	},
176};
177
178static const struct freq_tbl ftbl_gpu_cc_gx_gfx3d_clk_src[] = {
179	F(253000000, P_CRC_DIV, 1, 0, 0),
180	F(355000000, P_CRC_DIV, 1, 0, 0),
181	F(430000000, P_CRC_DIV, 1, 0, 0),
182	F(565000000, P_CRC_DIV, 1, 0, 0),
183	F(650000000, P_CRC_DIV, 1, 0, 0),
184	F(800000000, P_CRC_DIV, 1, 0, 0),
185	F(825000000, P_CRC_DIV, 1, 0, 0),
186	F(850000000, P_CRC_DIV, 1, 0, 0),
187	{ }
188};
189
190static struct clk_rcg2 gpu_cc_gx_gfx3d_clk_src = {
191	.cmd_rcgr = 0x101c,
192	.mnd_width = 0,
193	.hid_width = 5,
194	.parent_map = gpu_cc_parent_map_1,
195	.freq_tbl = ftbl_gpu_cc_gx_gfx3d_clk_src,
196	.clkr.hw.init = &(struct clk_init_data){
197		.name = "gpu_cc_gx_gfx3d_clk_src",
198		.parent_data = gpu_cc_parent_data_1,
199		.num_parents = ARRAY_SIZE(gpu_cc_parent_data_1),
200		.flags = CLK_SET_RATE_PARENT,
201		.ops = &clk_rcg2_ops,
202	},
203};
204
205static struct clk_branch gpu_cc_acd_ahb_clk = {
206	.halt_reg = 0x1168,
207	.halt_check = BRANCH_HALT,
208	.clkr = {
209		.enable_reg = 0x1168,
210		.enable_mask = BIT(0),
211		.hw.init = &(struct clk_init_data){
212			.name = "gpu_cc_acd_ahb_clk",
213			.ops = &clk_branch2_ops,
214		},
215	},
216};
217
218static struct clk_branch gpu_cc_acd_cxo_clk = {
219	.halt_reg = 0x1164,
220	.halt_check = BRANCH_HALT,
221	.clkr = {
222		.enable_reg = 0x1164,
223		.enable_mask = BIT(0),
224		.hw.init = &(struct clk_init_data){
225			.name = "gpu_cc_acd_cxo_clk",
226			.ops = &clk_branch2_ops,
227		},
228	},
229};
230
231static struct clk_branch gpu_cc_ahb_clk = {
232	.halt_reg = 0x1078,
233	.halt_check = BRANCH_HALT_DELAY,
234	.clkr = {
235		.enable_reg = 0x1078,
236		.enable_mask = BIT(0),
237		.hw.init = &(struct clk_init_data){
238			.name = "gpu_cc_ahb_clk",
239			.flags = CLK_IS_CRITICAL,
240			.ops = &clk_branch2_ops,
241		},
242	},
243};
244
245static struct clk_branch gpu_cc_crc_ahb_clk = {
246	.halt_reg = 0x107c,
247	.halt_check = BRANCH_HALT_DELAY,
248	.clkr = {
249		.enable_reg = 0x107c,
250		.enable_mask = BIT(0),
251		.hw.init = &(struct clk_init_data){
252			.name = "gpu_cc_crc_ahb_clk",
253			.ops = &clk_branch2_ops,
254		},
255	},
256};
257
258static struct clk_branch gpu_cc_cx_gfx3d_clk = {
259	.halt_reg = 0x10a4,
260	.halt_check = BRANCH_HALT_DELAY,
261	.clkr = {
262		.enable_reg = 0x10a4,
263		.enable_mask = BIT(0),
264		.hw.init = &(struct clk_init_data){
265			.name = "gpu_cc_cx_gfx3d_clk",
266			.parent_hws = (const struct clk_hw*[]){
267				&gpu_cc_gx_gfx3d_clk_src.clkr.hw,
268			},
269			.num_parents = 1,
270			.flags = CLK_SET_RATE_PARENT,
271			.ops = &clk_branch2_ops,
272		},
273	},
274};
275
276static struct clk_branch gpu_cc_cx_gfx3d_slv_clk = {
277	.halt_reg = 0x10a8,
278	.halt_check = BRANCH_HALT_DELAY,
279	.clkr = {
280		.enable_reg = 0x10a8,
281		.enable_mask = BIT(0),
282		.hw.init = &(struct clk_init_data){
283			.name = "gpu_cc_cx_gfx3d_slv_clk",
284			.parent_hws = (const struct clk_hw*[]){
285				&gpu_cc_gx_gfx3d_clk_src.clkr.hw,
286			},
287			.num_parents = 1,
288			.flags = CLK_SET_RATE_PARENT,
289			.ops = &clk_branch2_ops,
290		},
291	},
292};
293
294static struct clk_branch gpu_cc_cx_gmu_clk = {
295	.halt_reg = 0x1098,
296	.halt_check = BRANCH_HALT,
297	.clkr = {
298		.enable_reg = 0x1098,
299		.enable_mask = BIT(0),
300		.hw.init = &(struct clk_init_data){
301			.name = "gpu_cc_cx_gmu_clk",
302			.parent_hws = (const struct clk_hw*[]){
303				&gpu_cc_gmu_clk_src.clkr.hw,
304			},
305			.num_parents = 1,
306			.flags = CLK_SET_RATE_PARENT,
307			.ops = &clk_branch2_ops,
308		},
309	},
310};
311
312static struct clk_branch gpu_cc_cx_snoc_dvm_clk = {
313	.halt_reg = 0x108c,
314	.halt_check = BRANCH_HALT_DELAY,
315	.clkr = {
316		.enable_reg = 0x108c,
317		.enable_mask = BIT(0),
318		.hw.init = &(struct clk_init_data){
319			.name = "gpu_cc_cx_snoc_dvm_clk",
320			.ops = &clk_branch2_ops,
321		},
322	},
323};
324
325static struct clk_branch gpu_cc_cxo_aon_clk = {
326	.halt_reg = 0x1004,
327	.halt_check = BRANCH_HALT_DELAY,
328	.clkr = {
329		.enable_reg = 0x1004,
330		.enable_mask = BIT(0),
331		.hw.init = &(struct clk_init_data){
332			.name = "gpu_cc_cxo_aon_clk",
333			.ops = &clk_branch2_ops,
334		},
335	},
336};
337
338static struct clk_branch gpu_cc_cxo_clk = {
339	.halt_reg = 0x109c,
340	.halt_check = BRANCH_HALT,
341	.clkr = {
342		.enable_reg = 0x109c,
343		.enable_mask = BIT(0),
344		.hw.init = &(struct clk_init_data){
345			.name = "gpu_cc_cxo_clk",
346			.ops = &clk_branch2_ops,
347		},
348	},
349};
350
351static struct clk_branch gpu_cc_gx_cxo_clk = {
352	.halt_reg = 0x1060,
353	.halt_check = BRANCH_HALT,
354	.clkr = {
355		.enable_reg = 0x1060,
356		.enable_mask = BIT(0),
357		.hw.init = &(struct clk_init_data){
358			.name = "gpu_cc_gx_cxo_clk",
359			.ops = &clk_branch2_ops,
360		},
361	},
362};
363
364static struct clk_branch gpu_cc_gx_gfx3d_clk = {
365	.halt_reg = 0x1054,
366	.halt_check = BRANCH_HALT_SKIP,
367	.clkr = {
368		.enable_reg = 0x1054,
369		.enable_mask = BIT(0),
370		.hw.init = &(struct clk_init_data){
371			.name = "gpu_cc_gx_gfx3d_clk",
372			.parent_hws = (const struct clk_hw*[]){
373				&gpu_cc_gx_gfx3d_clk_src.clkr.hw,
374			},
375			.num_parents = 1,
376			.flags = CLK_SET_RATE_PARENT,
377			.ops = &clk_branch2_ops,
378		},
379	},
380};
381
382static struct clk_branch gpu_cc_gx_gmu_clk = {
383	.halt_reg = 0x1064,
384	.halt_check = BRANCH_HALT,
385	.clkr = {
386		.enable_reg = 0x1064,
387		.enable_mask = BIT(0),
388		.hw.init = &(struct clk_init_data){
389			.name = "gpu_cc_gx_gmu_clk",
390			.parent_hws = (const struct clk_hw*[]){
391				&gpu_cc_gmu_clk_src.clkr.hw,
392			},
393			.num_parents = 1,
394			.flags = CLK_SET_RATE_PARENT,
395			.ops = &clk_branch2_ops,
396		},
397	},
398};
399
400static struct clk_branch gpu_cc_gx_vsense_clk = {
401	.halt_reg = 0x1058,
402	.halt_check = BRANCH_HALT_DELAY,
403	.clkr = {
404		.enable_reg = 0x1058,
405		.enable_mask = BIT(0),
406		.hw.init = &(struct clk_init_data){
407			.name = "gpu_cc_gx_vsense_clk",
408			.ops = &clk_branch2_ops,
409		},
410	},
411};
412
413static struct gdsc gpu_cx_gdsc = {
414	.gdscr = 0x106c,
415	.gds_hw_ctrl = 0x1540,
416	.en_rest_wait_val = 0x2,
417	.en_few_wait_val = 0x2,
418	.clk_dis_wait_val = 0x8,
419	.pd = {
420		.name = "gpu_cx_gdsc",
421	},
422	.pwrsts = PWRSTS_OFF_ON,
423	.flags = VOTABLE,
424};
425
426static struct gdsc gpu_gx_gdsc = {
427	.gdscr = 0x100c,
428	.clamp_io_ctrl = 0x1508,
429	.en_rest_wait_val = 0x2,
430	.en_few_wait_val = 0x2,
431	.clk_dis_wait_val = 0x2,
432	.pd = {
433		.name = "gpu_gx_gdsc",
434		.power_on = gdsc_gx_do_nothing_enable,
435	},
436	.pwrsts = PWRSTS_OFF_ON,
437	.flags = CLAMP_IO | POLL_CFG_GDSCR,
438};
439
440static struct clk_hw *gpu_cc_sm6350_hws[] = {
441	[GPU_CC_CRC_DIV] = &crc_div.hw,
442};
443
444static struct clk_regmap *gpu_cc_sm6350_clocks[] = {
445	[GPU_CC_ACD_AHB_CLK] = &gpu_cc_acd_ahb_clk.clkr,
446	[GPU_CC_ACD_CXO_CLK] = &gpu_cc_acd_cxo_clk.clkr,
447	[GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr,
448	[GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr,
449	[GPU_CC_CX_GFX3D_CLK] = &gpu_cc_cx_gfx3d_clk.clkr,
450	[GPU_CC_CX_GFX3D_SLV_CLK] = &gpu_cc_cx_gfx3d_slv_clk.clkr,
451	[GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr,
452	[GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_clk.clkr,
453	[GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr,
454	[GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr,
455	[GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr,
456	[GPU_CC_GX_CXO_CLK] = &gpu_cc_gx_cxo_clk.clkr,
457	[GPU_CC_GX_GFX3D_CLK] = &gpu_cc_gx_gfx3d_clk.clkr,
458	[GPU_CC_GX_GFX3D_CLK_SRC] = &gpu_cc_gx_gfx3d_clk_src.clkr,
459	[GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr,
460	[GPU_CC_GX_VSENSE_CLK] = &gpu_cc_gx_vsense_clk.clkr,
461	[GPU_CC_PLL0] = &gpu_cc_pll0.clkr,
462	[GPU_CC_PLL1] = &gpu_cc_pll1.clkr,
463};
464
465static struct gdsc *gpu_cc_sm6350_gdscs[] = {
466	[GPU_CX_GDSC] = &gpu_cx_gdsc,
467	[GPU_GX_GDSC] = &gpu_gx_gdsc,
468};
469
470static const struct regmap_config gpu_cc_sm6350_regmap_config = {
471	.reg_bits = 32,
472	.reg_stride = 4,
473	.val_bits = 32,
474	.max_register = 0x8008,
475	.fast_io = true,
476};
477
478static const struct qcom_cc_desc gpu_cc_sm6350_desc = {
479	.config = &gpu_cc_sm6350_regmap_config,
480	.clk_hws = gpu_cc_sm6350_hws,
481	.num_clk_hws = ARRAY_SIZE(gpu_cc_sm6350_hws),
482	.clks = gpu_cc_sm6350_clocks,
483	.num_clks = ARRAY_SIZE(gpu_cc_sm6350_clocks),
484	.gdscs = gpu_cc_sm6350_gdscs,
485	.num_gdscs = ARRAY_SIZE(gpu_cc_sm6350_gdscs),
486};
487
488static const struct of_device_id gpu_cc_sm6350_match_table[] = {
489	{ .compatible = "qcom,sm6350-gpucc" },
490	{ }
491};
492MODULE_DEVICE_TABLE(of, gpu_cc_sm6350_match_table);
493
494static int gpu_cc_sm6350_probe(struct platform_device *pdev)
495{
496	struct regmap *regmap;
497	unsigned int value, mask;
498
499	regmap = qcom_cc_map(pdev, &gpu_cc_sm6350_desc);
500	if (IS_ERR(regmap))
501		return PTR_ERR(regmap);
502
503	clk_fabia_pll_configure(&gpu_cc_pll0, regmap, &gpu_cc_pll0_config);
504	clk_fabia_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config);
505
506	/* Configure gpu_cc_cx_gmu_clk with recommended wakeup/sleep settings */
507	mask = CX_GMU_CBCR_WAKE_MASK << CX_GMU_CBCR_WAKE_SHIFT;
508	mask |= CX_GMU_CBCR_SLEEP_MASK << CX_GMU_CBCR_SLEEP_SHIFT;
509	value = 0xF << CX_GMU_CBCR_WAKE_SHIFT | 0xF << CX_GMU_CBCR_SLEEP_SHIFT;
510	regmap_update_bits(regmap, 0x1098, mask, value);
511
512	return qcom_cc_really_probe(&pdev->dev, &gpu_cc_sm6350_desc, regmap);
513}
514
515static struct platform_driver gpu_cc_sm6350_driver = {
516	.probe = gpu_cc_sm6350_probe,
517	.driver = {
518		.name = "sm6350-gpucc",
519		.of_match_table = gpu_cc_sm6350_match_table,
520	},
521};
522
523static int __init gpu_cc_sm6350_init(void)
524{
525	return platform_driver_register(&gpu_cc_sm6350_driver);
526}
527core_initcall(gpu_cc_sm6350_init);
528
529static void __exit gpu_cc_sm6350_exit(void)
530{
531	platform_driver_unregister(&gpu_cc_sm6350_driver);
532}
533module_exit(gpu_cc_sm6350_exit);
534
535MODULE_DESCRIPTION("QTI GPU_CC LAGOON Driver");
536MODULE_LICENSE("GPL v2");
~/ Read-only file preview.