File Index
Files and directories
Sign in
FILE

gpucc-sc7280.c

File preview with syntax highlighting.

linux-6.19.14/drivers/clk/qcom/gpucc-sc7280.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (c) 2021, The Linux Foundation. All rights reserved.
  4 * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
  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-sc7280.h>
 14
 15#include "clk-alpha-pll.h"
 16#include "clk-branch.h"
 17#include "clk-rcg.h"
 18#include "clk-regmap-divider.h"
 19#include "common.h"
 20#include "reset.h"
 21#include "gdsc.h"
 22
 23enum {
 24	P_BI_TCXO,
 25	P_GCC_GPU_GPLL0_CLK_SRC,
 26	P_GCC_GPU_GPLL0_DIV_CLK_SRC,
 27	P_GPU_CC_PLL0_OUT_MAIN,
 28	P_GPU_CC_PLL1_OUT_MAIN,
 29};
 30
 31static const struct pll_vco lucid_vco[] = {
 32	{ 249600000, 2000000000, 0 },
 33};
 34
 35static struct clk_alpha_pll gpu_cc_pll0 = {
 36	.offset = 0x0,
 37	.vco_table = lucid_vco,
 38	.num_vco = ARRAY_SIZE(lucid_vco),
 39	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
 40	.clkr = {
 41		.hw.init = &(struct clk_init_data){
 42			.name = "gpu_cc_pll0",
 43			.parent_data = &(const struct clk_parent_data){
 44				.fw_name = "bi_tcxo",
 45			},
 46			.num_parents = 1,
 47			.ops = &clk_alpha_pll_lucid_ops,
 48		},
 49	},
 50};
 51
 52/* 500MHz Configuration */
 53static const struct alpha_pll_config gpu_cc_pll1_config = {
 54	.l = 0x1A,
 55	.alpha = 0xAAA,
 56	.config_ctl_val = 0x20485699,
 57	.config_ctl_hi_val = 0x00002261,
 58	.config_ctl_hi1_val = 0x329A299C,
 59	.user_ctl_val = 0x00000001,
 60	.user_ctl_hi_val = 0x00000805,
 61	.user_ctl_hi1_val = 0x00000000,
 62};
 63
 64static struct clk_alpha_pll gpu_cc_pll1 = {
 65	.offset = 0x100,
 66	.vco_table = lucid_vco,
 67	.num_vco = ARRAY_SIZE(lucid_vco),
 68	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
 69	.clkr = {
 70		.hw.init = &(struct clk_init_data){
 71			.name = "gpu_cc_pll1",
 72			.parent_data = &(const struct clk_parent_data){
 73				.fw_name = "bi_tcxo",
 74			},
 75			.num_parents = 1,
 76			.ops = &clk_alpha_pll_lucid_ops,
 77		},
 78	},
 79};
 80
 81static const struct parent_map gpu_cc_parent_map_0[] = {
 82	{ P_BI_TCXO, 0 },
 83	{ P_GPU_CC_PLL0_OUT_MAIN, 1 },
 84	{ P_GPU_CC_PLL1_OUT_MAIN, 3 },
 85	{ P_GCC_GPU_GPLL0_CLK_SRC, 5 },
 86	{ P_GCC_GPU_GPLL0_DIV_CLK_SRC, 6 },
 87};
 88
 89static const struct clk_parent_data gpu_cc_parent_data_0[] = {
 90	{ .fw_name = "bi_tcxo" },
 91	{ .hw = &gpu_cc_pll0.clkr.hw },
 92	{ .hw = &gpu_cc_pll1.clkr.hw },
 93	{ .fw_name = "gcc_gpu_gpll0_clk_src" },
 94	{ .fw_name = "gcc_gpu_gpll0_div_clk_src" },
 95};
 96
 97static const struct parent_map gpu_cc_parent_map_1[] = {
 98	{ P_BI_TCXO, 0 },
 99	{ P_GPU_CC_PLL1_OUT_MAIN, 3 },
100	{ P_GCC_GPU_GPLL0_CLK_SRC, 5 },
101	{ P_GCC_GPU_GPLL0_DIV_CLK_SRC, 6 },
102};
103
104static const struct clk_parent_data gpu_cc_parent_data_1[] = {
105	{ .fw_name = "bi_tcxo", },
106	{ .hw = &gpu_cc_pll1.clkr.hw },
107	{ .fw_name = "gcc_gpu_gpll0_clk_src", },
108	{ .fw_name = "gcc_gpu_gpll0_div_clk_src", },
109};
110
111static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = {
112	F(19200000, P_BI_TCXO, 1, 0, 0),
113	F(200000000, P_GCC_GPU_GPLL0_DIV_CLK_SRC, 1.5, 0, 0),
114	F(500000000, P_GPU_CC_PLL1_OUT_MAIN, 1, 0, 0),
115	{ }
116};
117
118static struct clk_rcg2 gpu_cc_gmu_clk_src = {
119	.cmd_rcgr = 0x1120,
120	.mnd_width = 0,
121	.hid_width = 5,
122	.parent_map = gpu_cc_parent_map_0,
123	.freq_tbl = ftbl_gpu_cc_gmu_clk_src,
124	.clkr.hw.init = &(struct clk_init_data){
125		.name = "gpu_cc_gmu_clk_src",
126		.parent_data = gpu_cc_parent_data_0,
127		.num_parents = ARRAY_SIZE(gpu_cc_parent_data_0),
128		.ops = &clk_rcg2_shared_ops,
129	},
130};
131
132static const struct freq_tbl ftbl_gpu_cc_hub_clk_src[] = {
133	F(150000000, P_GCC_GPU_GPLL0_DIV_CLK_SRC, 2, 0, 0),
134	F(240000000, P_GCC_GPU_GPLL0_CLK_SRC, 2.5, 0, 0),
135	F(300000000, P_GCC_GPU_GPLL0_CLK_SRC, 2, 0, 0),
136	{ }
137};
138
139static struct clk_rcg2 gpu_cc_hub_clk_src = {
140	.cmd_rcgr = 0x117c,
141	.mnd_width = 0,
142	.hid_width = 5,
143	.parent_map = gpu_cc_parent_map_1,
144	.freq_tbl = ftbl_gpu_cc_hub_clk_src,
145	.clkr.hw.init = &(struct clk_init_data){
146		.name = "gpu_cc_hub_clk_src",
147		.parent_data = gpu_cc_parent_data_1,
148		.num_parents = ARRAY_SIZE(gpu_cc_parent_data_1),
149		.ops = &clk_rcg2_shared_ops,
150	},
151};
152
153static struct clk_regmap_div gpu_cc_hub_ahb_div_clk_src = {
154	.reg = 0x11c0,
155	.shift = 0,
156	.width = 4,
157	.clkr.hw.init = &(struct clk_init_data) {
158		.name = "gpu_cc_hub_ahb_div_clk_src",
159		.parent_hws = (const struct clk_hw*[]){
160			&gpu_cc_hub_clk_src.clkr.hw,
161		},
162		.num_parents = 1,
163		.flags = CLK_SET_RATE_PARENT,
164		.ops = &clk_regmap_div_ro_ops,
165	},
166};
167
168static struct clk_regmap_div gpu_cc_hub_cx_int_div_clk_src = {
169	.reg = 0x11bc,
170	.shift = 0,
171	.width = 4,
172	.clkr.hw.init = &(struct clk_init_data) {
173		.name = "gpu_cc_hub_cx_int_div_clk_src",
174		.parent_hws = (const struct clk_hw*[]){
175			&gpu_cc_hub_clk_src.clkr.hw,
176		},
177		.num_parents = 1,
178		.flags = CLK_SET_RATE_PARENT,
179		.ops = &clk_regmap_div_ro_ops,
180	},
181};
182
183static struct clk_branch gpu_cc_ahb_clk = {
184	.halt_reg = 0x1078,
185	.halt_check = BRANCH_HALT_DELAY,
186	.clkr = {
187		.enable_reg = 0x1078,
188		.enable_mask = BIT(0),
189		.hw.init = &(struct clk_init_data){
190			.name = "gpu_cc_ahb_clk",
191			.parent_hws = (const struct clk_hw*[]){
192				&gpu_cc_hub_ahb_div_clk_src.clkr.hw,
193			},
194			.num_parents = 1,
195			.flags = CLK_SET_RATE_PARENT,
196			.ops = &clk_branch2_ops,
197		},
198	},
199};
200
201static struct clk_branch gpu_cc_crc_ahb_clk = {
202	.halt_reg = 0x107c,
203	.halt_check = BRANCH_HALT_VOTED,
204	.clkr = {
205		.enable_reg = 0x107c,
206		.enable_mask = BIT(0),
207		.hw.init = &(struct clk_init_data){
208			.name = "gpu_cc_crc_ahb_clk",
209			.parent_hws = (const struct clk_hw*[]){
210				&gpu_cc_hub_ahb_div_clk_src.clkr.hw,
211			},
212			.num_parents = 1,
213			.flags = CLK_SET_RATE_PARENT,
214			.ops = &clk_branch2_ops,
215		},
216	},
217};
218
219static struct clk_branch gpu_cc_cx_gmu_clk = {
220	.halt_reg = 0x1098,
221	.halt_check = BRANCH_HALT,
222	.clkr = {
223		.enable_reg = 0x1098,
224		.enable_mask = BIT(0),
225		.hw.init = &(struct clk_init_data){
226			.name = "gpu_cc_cx_gmu_clk",
227			.parent_hws = (const struct clk_hw*[]){
228				&gpu_cc_gmu_clk_src.clkr.hw,
229			},
230			.num_parents = 1,
231			.flags = CLK_SET_RATE_PARENT,
232			.ops = &clk_branch2_aon_ops,
233		},
234	},
235};
236
237static struct clk_branch gpu_cc_cx_snoc_dvm_clk = {
238	.halt_reg = 0x108c,
239	.halt_check = BRANCH_HALT_VOTED,
240	.clkr = {
241		.enable_reg = 0x108c,
242		.enable_mask = BIT(0),
243		.hw.init = &(struct clk_init_data){
244			.name = "gpu_cc_cx_snoc_dvm_clk",
245			.ops = &clk_branch2_ops,
246		},
247	},
248};
249
250static struct clk_branch gpu_cc_cxo_aon_clk = {
251	.halt_reg = 0x1004,
252	.halt_check = BRANCH_HALT_VOTED,
253	.clkr = {
254		.enable_reg = 0x1004,
255		.enable_mask = BIT(0),
256		.hw.init = &(struct clk_init_data){
257			.name = "gpu_cc_cxo_aon_clk",
258			.ops = &clk_branch2_ops,
259		},
260	},
261};
262
263static struct clk_branch gpu_cc_cxo_clk = {
264	.halt_reg = 0x109c,
265	.halt_check = BRANCH_HALT,
266	.clkr = {
267		.enable_reg = 0x109c,
268		.enable_mask = BIT(0),
269		.hw.init = &(struct clk_init_data){
270			.name = "gpu_cc_cxo_clk",
271			.ops = &clk_branch2_aon_ops,
272		},
273	},
274};
275
276static struct clk_branch gpu_cc_gx_gmu_clk = {
277	.halt_reg = 0x1064,
278	.halt_check = BRANCH_HALT,
279	.clkr = {
280		.enable_reg = 0x1064,
281		.enable_mask = BIT(0),
282		.hw.init = &(struct clk_init_data){
283			.name = "gpu_cc_gx_gmu_clk",
284			.parent_hws = (const struct clk_hw*[]){
285				&gpu_cc_gmu_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_hlos1_vote_gpu_smmu_clk = {
295	.halt_reg = 0x5000,
296	.halt_check = BRANCH_VOTED,
297	.clkr = {
298		.enable_reg = 0x5000,
299		.enable_mask = BIT(0),
300		.hw.init = &(struct clk_init_data){
301			.name = "gpu_cc_hlos1_vote_gpu_smmu_clk",
302			.ops = &clk_branch2_ops,
303		},
304	},
305};
306
307static struct clk_branch gpu_cc_hub_aon_clk = {
308	.halt_reg = 0x1178,
309	.halt_check = BRANCH_HALT,
310	.clkr = {
311		.enable_reg = 0x1178,
312		.enable_mask = BIT(0),
313		.hw.init = &(struct clk_init_data){
314			.name = "gpu_cc_hub_aon_clk",
315			.parent_hws = (const struct clk_hw*[]){
316				&gpu_cc_hub_clk_src.clkr.hw,
317			},
318			.num_parents = 1,
319			.flags = CLK_SET_RATE_PARENT,
320			.ops = &clk_branch2_aon_ops,
321		},
322	},
323};
324
325static struct clk_branch gpu_cc_hub_cx_int_clk = {
326	.halt_reg = 0x1204,
327	.halt_check = BRANCH_HALT,
328	.clkr = {
329		.enable_reg = 0x1204,
330		.enable_mask = BIT(0),
331		.hw.init = &(struct clk_init_data){
332			.name = "gpu_cc_hub_cx_int_clk",
333			.parent_hws = (const struct clk_hw*[]){
334				&gpu_cc_hub_cx_int_div_clk_src.clkr.hw,
335			},
336			.num_parents = 1,
337			.flags = CLK_SET_RATE_PARENT,
338			.ops = &clk_branch2_aon_ops,
339		},
340	},
341};
342
343static struct clk_branch gpu_cc_mnd1x_0_gfx3d_clk = {
344	.halt_reg = 0x802c,
345	.halt_check = BRANCH_HALT_SKIP,
346	.clkr = {
347		.enable_reg = 0x802c,
348		.enable_mask = BIT(0),
349		.hw.init = &(struct clk_init_data){
350			.name = "gpu_cc_mnd1x_0_gfx3d_clk",
351			.ops = &clk_branch2_ops,
352		},
353	},
354};
355
356static struct clk_branch gpu_cc_mnd1x_1_gfx3d_clk = {
357	.halt_reg = 0x8030,
358	.halt_check = BRANCH_HALT_SKIP,
359	.clkr = {
360		.enable_reg = 0x8030,
361		.enable_mask = BIT(0),
362		.hw.init = &(struct clk_init_data){
363			.name = "gpu_cc_mnd1x_1_gfx3d_clk",
364			.ops = &clk_branch2_ops,
365		},
366	},
367};
368
369static struct clk_branch gpu_cc_sleep_clk = {
370	.halt_reg = 0x1090,
371	.halt_check = BRANCH_HALT_VOTED,
372	.clkr = {
373		.enable_reg = 0x1090,
374		.enable_mask = BIT(0),
375		.hw.init = &(struct clk_init_data){
376			.name = "gpu_cc_sleep_clk",
377			.ops = &clk_branch2_ops,
378		},
379	},
380};
381
382static struct gdsc cx_gdsc = {
383	.gdscr = 0x106c,
384	.en_rest_wait_val = 0x2,
385	.en_few_wait_val = 0x2,
386	.clk_dis_wait_val = 0x2,
387	.gds_hw_ctrl = 0x1540,
388	.pd = {
389		.name = "cx_gdsc",
390	},
391	.pwrsts = PWRSTS_OFF_ON,
392	.flags = VOTABLE | RETAIN_FF_ENABLE,
393};
394
395static struct gdsc gx_gdsc = {
396	.gdscr = 0x100c,
397	.en_rest_wait_val = 0x2,
398	.en_few_wait_val = 0x2,
399	.clk_dis_wait_val = 0x2,
400	.clamp_io_ctrl = 0x1508,
401	.pd = {
402		.name = "gx_gdsc",
403		.power_on = gdsc_gx_do_nothing_enable,
404	},
405	.pwrsts = PWRSTS_OFF_ON,
406	.flags = CLAMP_IO | RETAIN_FF_ENABLE,
407};
408
409static struct gdsc *gpu_cc_sc7180_gdscs[] = {
410	[GPU_CC_CX_GDSC] = &cx_gdsc,
411	[GPU_CC_GX_GDSC] = &gx_gdsc,
412};
413
414static struct clk_regmap *gpu_cc_sc7280_clocks[] = {
415	[GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr,
416	[GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr,
417	[GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr,
418	[GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_clk.clkr,
419	[GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr,
420	[GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr,
421	[GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr,
422	[GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr,
423	[GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK] = &gpu_cc_hlos1_vote_gpu_smmu_clk.clkr,
424	[GPU_CC_HUB_AHB_DIV_CLK_SRC] = &gpu_cc_hub_ahb_div_clk_src.clkr,
425	[GPU_CC_HUB_AON_CLK] = &gpu_cc_hub_aon_clk.clkr,
426	[GPU_CC_HUB_CLK_SRC] = &gpu_cc_hub_clk_src.clkr,
427	[GPU_CC_HUB_CX_INT_CLK] = &gpu_cc_hub_cx_int_clk.clkr,
428	[GPU_CC_HUB_CX_INT_DIV_CLK_SRC] = &gpu_cc_hub_cx_int_div_clk_src.clkr,
429	[GPU_CC_MND1X_0_GFX3D_CLK] = &gpu_cc_mnd1x_0_gfx3d_clk.clkr,
430	[GPU_CC_MND1X_1_GFX3D_CLK] = &gpu_cc_mnd1x_1_gfx3d_clk.clkr,
431	[GPU_CC_PLL0] = &gpu_cc_pll0.clkr,
432	[GPU_CC_PLL1] = &gpu_cc_pll1.clkr,
433	[GPU_CC_SLEEP_CLK] = &gpu_cc_sleep_clk.clkr,
434};
435
436static const struct regmap_config gpu_cc_sc7280_regmap_config = {
437	.reg_bits = 32,
438	.reg_stride = 4,
439	.val_bits = 32,
440	.max_register = 0x8030,
441	.fast_io = true,
442};
443
444static const struct qcom_cc_desc gpu_cc_sc7280_desc = {
445	.config = &gpu_cc_sc7280_regmap_config,
446	.clks = gpu_cc_sc7280_clocks,
447	.num_clks = ARRAY_SIZE(gpu_cc_sc7280_clocks),
448	.gdscs = gpu_cc_sc7180_gdscs,
449	.num_gdscs = ARRAY_SIZE(gpu_cc_sc7180_gdscs),
450};
451
452static const struct of_device_id gpu_cc_sc7280_match_table[] = {
453	{ .compatible = "qcom,sc7280-gpucc" },
454	{ }
455};
456MODULE_DEVICE_TABLE(of, gpu_cc_sc7280_match_table);
457
458static int gpu_cc_sc7280_probe(struct platform_device *pdev)
459{
460	struct regmap *regmap;
461
462	regmap = qcom_cc_map(pdev, &gpu_cc_sc7280_desc);
463	if (IS_ERR(regmap))
464		return PTR_ERR(regmap);
465
466	clk_lucid_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config);
467
468	/* Keep some clocks always-on */
469	qcom_branch_set_clk_en(regmap, 0x1170); /* GPU_CC_CB_CLK */
470	qcom_branch_set_clk_en(regmap, 0x1098); /* GPUCC_CX_GMU_CLK */
471	regmap_update_bits(regmap, 0x1098, BIT(13), BIT(13));
472
473	return qcom_cc_really_probe(&pdev->dev, &gpu_cc_sc7280_desc, regmap);
474}
475
476static struct platform_driver gpu_cc_sc7280_driver = {
477	.probe = gpu_cc_sc7280_probe,
478	.driver = {
479		.name = "gpu_cc-sc7280",
480		.of_match_table = gpu_cc_sc7280_match_table,
481	},
482};
483
484module_platform_driver(gpu_cc_sc7280_driver);
485
486MODULE_DESCRIPTION("QTI GPU_CC SC7280 Driver");
487MODULE_LICENSE("GPL v2");
~/ Read-only file preview.