Linux Audio

Check our new training course

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