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) 2021, 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/pm_runtime.h>
 12#include <linux/regmap.h>
 13
 14#include <dt-bindings/clock/qcom,sm6375-gpucc.h>
 15
 16#include "clk-alpha-pll.h"
 17#include "clk-branch.h"
 18#include "clk-rcg.h"
 19#include "clk-regmap.h"
 20#include "clk-regmap-divider.h"
 21#include "clk-regmap-mux.h"
 22#include "clk-regmap-phy-mux.h"
 23#include "gdsc.h"
 24#include "reset.h"
 25
 26enum {
 27	DT_BI_TCXO,
 28	DT_GCC_GPU_GPLL0_CLK_SRC,
 29	DT_GCC_GPU_GPLL0_DIV_CLK_SRC,
 30	DT_GCC_GPU_SNOC_DVM_GFX_CLK,
 31};
 32
 33enum {
 34	P_BI_TCXO,
 35	P_GCC_GPU_GPLL0_CLK_SRC,
 36	P_GCC_GPU_GPLL0_DIV_CLK_SRC,
 37	P_GPU_CC_PLL0_OUT_EVEN,
 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};
 44
 45static const struct pll_vco lucid_vco[] = {
 46	{ 249600000, 2000000000, 0 },
 47};
 48
 49/* 532MHz Configuration */
 50static const struct alpha_pll_config gpucc_pll0_config = {
 51	.l = 0x1b,
 52	.alpha = 0xb555,
 53	.config_ctl_val = 0x20485699,
 54	.config_ctl_hi_val = 0x00002261,
 55	.config_ctl_hi1_val = 0x329a299c,
 56	.user_ctl_val = 0x00000001,
 57	.user_ctl_hi_val = 0x00000805,
 58	.user_ctl_hi1_val = 0x00000000,
 59};
 60
 61static struct clk_alpha_pll gpucc_pll0 = {
 62	.offset = 0x0,
 63	.vco_table = lucid_vco,
 64	.num_vco = ARRAY_SIZE(lucid_vco),
 65	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
 66	.clkr = {
 67		.hw.init = &(struct clk_init_data){
 68			.name = "gpucc_pll0",
 69			.parent_data = &(const struct clk_parent_data){
 70				.index = P_BI_TCXO,
 71			},
 72			.num_parents = 1,
 73			.ops = &clk_alpha_pll_lucid_ops,
 74		},
 75	},
 76};
 77
 78/* 514MHz Configuration */
 79static const struct alpha_pll_config gpucc_pll1_config = {
 80	.l = 0x1a,
 81	.alpha = 0xc555,
 82	.config_ctl_val = 0x20485699,
 83	.config_ctl_hi_val = 0x00002261,
 84	.config_ctl_hi1_val = 0x329a299c,
 85	.user_ctl_val = 0x00000001,
 86	.user_ctl_hi_val = 0x00000805,
 87	.user_ctl_hi1_val = 0x00000000,
 88};
 89
 90static struct clk_alpha_pll gpucc_pll1 = {
 91	.offset = 0x100,
 92	.vco_table = lucid_vco,
 93	.num_vco = ARRAY_SIZE(lucid_vco),
 94	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
 95	.clkr = {
 96		.hw.init = &(struct clk_init_data){
 97			.name = "gpucc_pll1",
 98			.parent_data = &(const struct clk_parent_data){
 99				.index = P_BI_TCXO,
100			},
101			.num_parents = 1,
102			.ops = &clk_alpha_pll_lucid_ops,
103		},
104	},
105};
106
107static const struct parent_map gpucc_parent_map_0[] = {
108	{ P_BI_TCXO, 0 },
109	{ P_GPU_CC_PLL0_OUT_MAIN, 1 },
110	{ P_GPU_CC_PLL1_OUT_MAIN, 3 },
111	{ P_GCC_GPU_GPLL0_CLK_SRC, 5 },
112	{ P_GCC_GPU_GPLL0_DIV_CLK_SRC, 6 },
113};
114
115static const struct clk_parent_data gpucc_parent_data_0[] = {
116	{ .index = P_BI_TCXO },
117	{ .hw = &gpucc_pll0.clkr.hw },
118	{ .hw = &gpucc_pll1.clkr.hw },
119	{ .index = DT_GCC_GPU_GPLL0_CLK_SRC },
120	{ .index = DT_GCC_GPU_GPLL0_DIV_CLK_SRC },
121};
122
123static const struct parent_map gpucc_parent_map_1[] = {
124	{ P_BI_TCXO, 0 },
125	{ P_GPU_CC_PLL0_OUT_EVEN, 1 },
126	{ P_GPU_CC_PLL0_OUT_ODD, 2 },
127	{ P_GPU_CC_PLL1_OUT_EVEN, 3 },
128	{ P_GPU_CC_PLL1_OUT_ODD, 4 },
129	{ P_GCC_GPU_GPLL0_CLK_SRC, 5 },
130};
131
132static const struct clk_parent_data gpucc_parent_data_1[] = {
133	{ .index = P_BI_TCXO },
134	{ .hw = &gpucc_pll0.clkr.hw },
135	{ .hw = &gpucc_pll0.clkr.hw },
136	{ .hw = &gpucc_pll1.clkr.hw },
137	{ .hw = &gpucc_pll1.clkr.hw },
138	{ .index = DT_GCC_GPU_GPLL0_CLK_SRC },
139};
140
141static const struct freq_tbl ftbl_gpucc_gmu_clk_src[] = {
142	F(200000000, P_GCC_GPU_GPLL0_DIV_CLK_SRC, 1.5, 0, 0),
143	{ }
144};
145
146static struct clk_rcg2 gpucc_gmu_clk_src = {
147	.cmd_rcgr = 0x1120,
148	.mnd_width = 0,
149	.hid_width = 5,
150	.parent_map = gpucc_parent_map_0,
151	.freq_tbl = ftbl_gpucc_gmu_clk_src,
152	.clkr.hw.init = &(struct clk_init_data){
153		.name = "gpucc_gmu_clk_src",
154		.parent_data = gpucc_parent_data_0,
155		.num_parents = ARRAY_SIZE(gpucc_parent_data_0),
156		.ops = &clk_rcg2_shared_ops,
157	},
158};
159
160static const struct freq_tbl ftbl_gpucc_gx_gfx3d_clk_src[] = {
161	F(266000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0),
162	F(390000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0),
163	F(490000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0),
164	F(650000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0),
165	F(770000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0),
166	F(840000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0),
167	F(900000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0),
168	{ }
169};
170
171static struct clk_rcg2 gpucc_gx_gfx3d_clk_src = {
172	.cmd_rcgr = 0x101c,
173	.mnd_width = 0,
174	.hid_width = 5,
175	.parent_map = gpucc_parent_map_1,
176	.freq_tbl = ftbl_gpucc_gx_gfx3d_clk_src,
177	.clkr.hw.init = &(struct clk_init_data){
178		.name = "gpucc_gx_gfx3d_clk_src",
179		.parent_data = gpucc_parent_data_1,
180		.num_parents = ARRAY_SIZE(gpucc_parent_data_1),
181		.flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
182		.ops = &clk_rcg2_ops,
183	},
184};
185
186static struct clk_branch gpucc_ahb_clk = {
187	.halt_reg = 0x1078,
188	.halt_check = BRANCH_HALT_DELAY,
189	.clkr = {
190		.enable_reg = 0x1078,
191		.enable_mask = BIT(0),
192		.hw.init = &(struct clk_init_data){
193			.name = "gpucc_ahb_clk",
194			.flags = CLK_IS_CRITICAL,
195			.ops = &clk_branch2_ops,
196		},
197	},
198};
199
200static struct clk_branch gpucc_cx_gfx3d_clk = {
201	.halt_reg = 0x10a4,
202	.halt_check = BRANCH_HALT_DELAY,
203	.clkr = {
204		.enable_reg = 0x10a4,
205		.enable_mask = BIT(0),
206		.hw.init = &(struct clk_init_data){
207			.name = "gpucc_cx_gfx3d_clk",
208			.parent_hws = (const struct clk_hw*[]) {
209				&gpucc_gx_gfx3d_clk_src.clkr.hw,
210			},
211			.num_parents = 1,
212			.flags = CLK_SET_RATE_PARENT,
213			.ops = &clk_branch2_ops,
214		},
215	},
216};
217
218static struct clk_branch gpucc_cx_gfx3d_slv_clk = {
219	.halt_reg = 0x10a8,
220	.halt_check = BRANCH_HALT_DELAY,
221	.clkr = {
222		.enable_reg = 0x10a8,
223		.enable_mask = BIT(0),
224		.hw.init = &(struct clk_init_data){
225			.name = "gpucc_cx_gfx3d_slv_clk",
226			.parent_hws = (const struct clk_hw*[]) {
227				&gpucc_gx_gfx3d_clk_src.clkr.hw,
228			},
229			.num_parents = 1,
230			.flags = CLK_SET_RATE_PARENT,
231			.ops = &clk_branch2_ops,
232		},
233	},
234};
235
236static struct clk_branch gpucc_cx_gmu_clk = {
237	.halt_reg = 0x1098,
238	.halt_check = BRANCH_HALT,
239	.clkr = {
240		.enable_reg = 0x1098,
241		.enable_mask = BIT(0),
242		.hw.init = &(struct clk_init_data){
243			.name = "gpucc_cx_gmu_clk",
244			.parent_hws = (const struct clk_hw*[]) {
245				&gpucc_gmu_clk_src.clkr.hw,
246			},
247			.num_parents = 1,
248			.flags = CLK_SET_RATE_PARENT,
249			.ops = &clk_branch2_ops,
250		},
251	},
252};
253
254static struct clk_branch gpucc_cx_snoc_dvm_clk = {
255	.halt_reg = 0x108c,
256	.halt_check = BRANCH_HALT_DELAY,
257	.clkr = {
258		.enable_reg = 0x108c,
259		.enable_mask = BIT(0),
260		.hw.init = &(struct clk_init_data){
261			.name = "gpucc_cx_snoc_dvm_clk",
262			.parent_data = &(const struct clk_parent_data){
263				.index = DT_GCC_GPU_SNOC_DVM_GFX_CLK,
264			},
265			.num_parents = 1,
266			.ops = &clk_branch2_ops,
267		},
268	},
269};
270
271static struct clk_branch gpucc_cxo_aon_clk = {
272	.halt_reg = 0x1004,
273	.halt_check = BRANCH_HALT_DELAY,
274	.clkr = {
275		.enable_reg = 0x1004,
276		.enable_mask = BIT(0),
277		.hw.init = &(struct clk_init_data){
278			.name = "gpucc_cxo_aon_clk",
279			.ops = &clk_branch2_ops,
280		},
281	},
282};
283
284static struct clk_branch gpucc_cxo_clk = {
285	.halt_reg = 0x109c,
286	.halt_check = BRANCH_HALT,
287	.clkr = {
288		.enable_reg = 0x109c,
289		.enable_mask = BIT(0),
290		.hw.init = &(struct clk_init_data){
291			.name = "gpucc_cxo_clk",
292			.ops = &clk_branch2_ops,
293		},
294	},
295};
296
297static struct clk_branch gpucc_gx_cxo_clk = {
298	.halt_reg = 0x1060,
299	.halt_check = BRANCH_HALT_DELAY,
300	.clkr = {
301		.enable_reg = 0x1060,
302		.enable_mask = BIT(0),
303		.hw.init = &(struct clk_init_data){
304			.name = "gpucc_gx_cxo_clk",
305			.flags = CLK_IS_CRITICAL,
306			.ops = &clk_branch2_ops,
307		},
308	},
309};
310
311static struct clk_branch gpucc_gx_gfx3d_clk = {
312	.halt_reg = 0x1054,
313	.halt_check = BRANCH_HALT_DELAY,
314	.clkr = {
315		.enable_reg = 0x1054,
316		.enable_mask = BIT(0),
317		.hw.init = &(struct clk_init_data){
318			.name = "gpucc_gx_gfx3d_clk",
319			.parent_hws = (const struct clk_hw*[]) {
320				&gpucc_gx_gfx3d_clk_src.clkr.hw,
321			},
322			.num_parents = 1,
323			.flags = CLK_SET_RATE_PARENT,
324			.ops = &clk_branch2_ops,
325		},
326	},
327};
328
329static struct clk_branch gpucc_gx_gmu_clk = {
330	.halt_reg = 0x1064,
331	.halt_check = BRANCH_HALT,
332	.clkr = {
333		.enable_reg = 0x1064,
334		.enable_mask = BIT(0),
335		.hw.init = &(struct clk_init_data){
336			.name = "gpucc_gx_gmu_clk",
337			.parent_hws = (const struct clk_hw*[]) {
338				&gpucc_gmu_clk_src.clkr.hw,
339			},
340			.num_parents = 1,
341			.flags = CLK_SET_RATE_PARENT,
342			.ops = &clk_branch2_ops,
343		},
344	},
345};
346
347static struct clk_branch gpucc_sleep_clk = {
348	.halt_reg = 0x1090,
349	.halt_check = BRANCH_HALT_VOTED,
350	.clkr = {
351		.enable_reg = 0x1090,
352		.enable_mask = BIT(0),
353		.hw.init = &(struct clk_init_data){
354			.name = "gpucc_sleep_clk",
355			.ops = &clk_branch2_ops,
356		},
357	},
358};
359
360static struct gdsc gpu_cx_gdsc = {
361	.gdscr = 0x106c,
362	.gds_hw_ctrl = 0x1540,
363	.clk_dis_wait_val = 8,
364	.pd = {
365		.name = "gpu_cx_gdsc",
366	},
367	.pwrsts = PWRSTS_OFF_ON,
368	.flags = VOTABLE,
369};
370
371static struct gdsc gpu_gx_gdsc = {
372	.gdscr = 0x100c,
373	.clamp_io_ctrl = 0x1508,
374	.resets = (unsigned int []){ GPU_GX_BCR, GPU_ACD_BCR, GPU_GX_ACD_MISC_BCR },
375	.reset_count = 3,
376	.pd = {
377		.name = "gpu_gx_gdsc",
378	},
379	.pwrsts = PWRSTS_OFF_ON,
380	.flags = CLAMP_IO | SW_RESET | AON_RESET,
381};
382
383static struct clk_regmap *gpucc_sm6375_clocks[] = {
384	[GPU_CC_AHB_CLK] = &gpucc_ahb_clk.clkr,
385	[GPU_CC_CX_GFX3D_CLK] = &gpucc_cx_gfx3d_clk.clkr,
386	[GPU_CC_CX_GFX3D_SLV_CLK] = &gpucc_cx_gfx3d_slv_clk.clkr,
387	[GPU_CC_CX_GMU_CLK] = &gpucc_cx_gmu_clk.clkr,
388	[GPU_CC_CX_SNOC_DVM_CLK] = &gpucc_cx_snoc_dvm_clk.clkr,
389	[GPU_CC_CXO_AON_CLK] = &gpucc_cxo_aon_clk.clkr,
390	[GPU_CC_CXO_CLK] = &gpucc_cxo_clk.clkr,
391	[GPU_CC_GMU_CLK_SRC] = &gpucc_gmu_clk_src.clkr,
392	[GPU_CC_GX_CXO_CLK] = &gpucc_gx_cxo_clk.clkr,
393	[GPU_CC_GX_GFX3D_CLK] = &gpucc_gx_gfx3d_clk.clkr,
394	[GPU_CC_GX_GFX3D_CLK_SRC] = &gpucc_gx_gfx3d_clk_src.clkr,
395	[GPU_CC_GX_GMU_CLK] = &gpucc_gx_gmu_clk.clkr,
396	[GPU_CC_PLL0] = &gpucc_pll0.clkr,
397	[GPU_CC_PLL1] = &gpucc_pll1.clkr,
398	[GPU_CC_SLEEP_CLK] = &gpucc_sleep_clk.clkr,
399};
400
401static const struct qcom_reset_map gpucc_sm6375_resets[] = {
402	[GPU_GX_BCR] = { 0x1008 },
403	[GPU_ACD_BCR] = { 0x1160 },
404	[GPU_GX_ACD_MISC_BCR] = { 0x8004 },
405};
406
407static struct gdsc *gpucc_sm6375_gdscs[] = {
408	[GPU_CX_GDSC] = &gpu_cx_gdsc,
409	[GPU_GX_GDSC] = &gpu_gx_gdsc,
410};
411
412static const struct regmap_config gpucc_sm6375_regmap_config = {
413	.reg_bits = 32,
414	.reg_stride = 4,
415	.val_bits = 32,
416	.max_register = 0x9000,
417	.fast_io = true,
418};
419
420static const struct qcom_cc_desc gpucc_sm6375_desc = {
421	.config = &gpucc_sm6375_regmap_config,
422	.clks = gpucc_sm6375_clocks,
423	.num_clks = ARRAY_SIZE(gpucc_sm6375_clocks),
424	.resets = gpucc_sm6375_resets,
425	.num_resets = ARRAY_SIZE(gpucc_sm6375_resets),
426	.gdscs = gpucc_sm6375_gdscs,
427	.num_gdscs = ARRAY_SIZE(gpucc_sm6375_gdscs),
428};
429
430static const struct of_device_id gpucc_sm6375_match_table[] = {
431	{ .compatible = "qcom,sm6375-gpucc" },
432	{ }
433};
434MODULE_DEVICE_TABLE(of, gpucc_sm6375_match_table);
435
436static int gpucc_sm6375_probe(struct platform_device *pdev)
437{
438	struct regmap *regmap;
439	int ret;
440
441	ret = devm_pm_runtime_enable(&pdev->dev);
442	if (ret)
443		return ret;
444
445	ret = pm_runtime_resume_and_get(&pdev->dev);
446	if (ret)
447		return ret;
448
449	regmap = qcom_cc_map(pdev, &gpucc_sm6375_desc);
450	if (IS_ERR(regmap)) {
451		pm_runtime_put(&pdev->dev);
452		return PTR_ERR(regmap);
453	}
454
455	clk_lucid_pll_configure(&gpucc_pll0, regmap, &gpucc_pll0_config);
456	clk_lucid_pll_configure(&gpucc_pll1, regmap, &gpucc_pll1_config);
457
458	ret = qcom_cc_really_probe(&pdev->dev, &gpucc_sm6375_desc, regmap);
459	pm_runtime_put(&pdev->dev);
460
461	return ret;
462}
463
464static struct platform_driver gpucc_sm6375_driver = {
465	.probe = gpucc_sm6375_probe,
466	.driver = {
467		.name = "gpucc-sm6375",
468		.of_match_table = gpucc_sm6375_match_table,
469	},
470};
471module_platform_driver(gpucc_sm6375_driver);
472
473MODULE_DESCRIPTION("QTI GPUCC SM6375 Driver");
474MODULE_LICENSE("GPL");