File Index
Files and directories
Sign in
FILE

gpucc-milos.c

File preview with syntax highlighting.

linux-6.19.14/drivers/clk/qcom/gpucc-milos.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (c) 2023-2024, Qualcomm Innovation Center, Inc. All rights reserved.
  4 * Copyright (c) 2025, Luca Weiss <luca.weiss@fairphone.com>
  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,milos-gpucc.h>
 14
 15#include "clk-alpha-pll.h"
 16#include "clk-branch.h"
 17#include "clk-pll.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 "common.h"
 23#include "gdsc.h"
 24#include "reset.h"
 25
 26/* Need to match the order of clocks in DT binding */
 27enum {
 28	DT_BI_TCXO,
 29	DT_GPLL0_OUT_MAIN,
 30	DT_GPLL0_OUT_MAIN_DIV,
 31};
 32
 33enum {
 34	P_BI_TCXO,
 35	P_GPLL0_OUT_MAIN,
 36	P_GPLL0_OUT_MAIN_DIV,
 37	P_GPU_CC_PLL0_OUT_EVEN,
 38	P_GPU_CC_PLL0_OUT_MAIN,
 39	P_GPU_CC_PLL0_OUT_ODD,
 40};
 41
 42static const struct pll_vco lucid_ole_vco[] = {
 43	{ 249600000, 2300000000, 0 },
 44};
 45
 46/* 700.0 MHz Configuration */
 47static const struct alpha_pll_config gpu_cc_pll0_config = {
 48	.l = 0x24,
 49	.alpha = 0x7555,
 50	.config_ctl_val = 0x20485699,
 51	.config_ctl_hi_val = 0x00182261,
 52	.config_ctl_hi1_val = 0x82aa299c,
 53	.test_ctl_val = 0x00000000,
 54	.test_ctl_hi_val = 0x00000003,
 55	.test_ctl_hi1_val = 0x00009000,
 56	.test_ctl_hi2_val = 0x00000034,
 57	.user_ctl_val = 0x00000400,
 58	.user_ctl_hi_val = 0x00000005,
 59};
 60
 61static struct clk_alpha_pll gpu_cc_pll0 = {
 62	.offset = 0x0,
 63	.config = &gpu_cc_pll0_config,
 64	.vco_table = lucid_ole_vco,
 65	.num_vco = ARRAY_SIZE(lucid_ole_vco),
 66	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
 67	.clkr = {
 68		.hw.init = &(const struct clk_init_data) {
 69			.name = "gpu_cc_pll0",
 70			.parent_data = &(const struct clk_parent_data) {
 71				.index = DT_BI_TCXO,
 72			},
 73			.num_parents = 1,
 74			.ops = &clk_alpha_pll_lucid_evo_ops,
 75		},
 76	},
 77};
 78
 79static const struct clk_div_table post_div_table_gpu_cc_pll0_out_even[] = {
 80	{ 0x1, 2 },
 81	{ }
 82};
 83
 84static struct clk_alpha_pll_postdiv gpu_cc_pll0_out_even = {
 85	.offset = 0x0,
 86	.post_div_shift = 10,
 87	.post_div_table = post_div_table_gpu_cc_pll0_out_even,
 88	.num_post_div = ARRAY_SIZE(post_div_table_gpu_cc_pll0_out_even),
 89	.width = 4,
 90	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
 91	.clkr.hw.init = &(const struct clk_init_data) {
 92		.name = "gpu_cc_pll0_out_even",
 93		.parent_hws = (const struct clk_hw*[]) {
 94			&gpu_cc_pll0.clkr.hw,
 95		},
 96		.num_parents = 1,
 97		.flags = CLK_SET_RATE_PARENT,
 98		.ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
 99	},
100};
101
102static const struct parent_map gpu_cc_parent_map_0[] = {
103	{ P_BI_TCXO, 0 },
104	{ P_GPLL0_OUT_MAIN, 5 },
105	{ P_GPLL0_OUT_MAIN_DIV, 6 },
106};
107
108static const struct clk_parent_data gpu_cc_parent_data_0[] = {
109	{ .index = DT_BI_TCXO },
110	{ .index = DT_GPLL0_OUT_MAIN },
111	{ .index = DT_GPLL0_OUT_MAIN_DIV },
112};
113
114static const struct parent_map gpu_cc_parent_map_1[] = {
115	{ P_BI_TCXO, 0 },
116	{ P_GPU_CC_PLL0_OUT_MAIN, 1 },
117	{ P_GPU_CC_PLL0_OUT_EVEN, 2 },
118	{ P_GPU_CC_PLL0_OUT_ODD, 3 },
119	{ P_GPLL0_OUT_MAIN, 5 },
120	{ P_GPLL0_OUT_MAIN_DIV, 6 },
121};
122
123static const struct clk_parent_data gpu_cc_parent_data_1[] = {
124	{ .index = DT_BI_TCXO },
125	{ .hw = &gpu_cc_pll0.clkr.hw },
126	{ .hw = &gpu_cc_pll0_out_even.clkr.hw },
127	{ .hw = &gpu_cc_pll0.clkr.hw },
128	{ .index = DT_GPLL0_OUT_MAIN },
129	{ .index = DT_GPLL0_OUT_MAIN_DIV },
130};
131
132static const struct freq_tbl ftbl_gpu_cc_ff_clk_src[] = {
133	F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0),
134	{ }
135};
136
137static struct clk_rcg2 gpu_cc_ff_clk_src = {
138	.cmd_rcgr = 0x9474,
139	.mnd_width = 0,
140	.hid_width = 5,
141	.parent_map = gpu_cc_parent_map_0,
142	.freq_tbl = ftbl_gpu_cc_ff_clk_src,
143	.clkr.hw.init = &(const struct clk_init_data) {
144		.name = "gpu_cc_ff_clk_src",
145		.parent_data = gpu_cc_parent_data_0,
146		.num_parents = ARRAY_SIZE(gpu_cc_parent_data_0),
147		.flags = CLK_SET_RATE_PARENT,
148		.ops = &clk_rcg2_shared_ops,
149	},
150};
151
152static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = {
153	F(19200000, P_BI_TCXO, 1, 0, 0),
154	F(350000000, P_GPU_CC_PLL0_OUT_EVEN, 1, 0, 0),
155	F(650000000, P_GPU_CC_PLL0_OUT_EVEN, 1, 0, 0),
156	F(687500000, P_GPU_CC_PLL0_OUT_EVEN, 1, 0, 0),
157	{ }
158};
159
160static struct clk_rcg2 gpu_cc_gmu_clk_src = {
161	.cmd_rcgr = 0x9318,
162	.mnd_width = 0,
163	.hid_width = 5,
164	.parent_map = gpu_cc_parent_map_1,
165	.freq_tbl = ftbl_gpu_cc_gmu_clk_src,
166	.clkr.hw.init = &(const struct clk_init_data) {
167		.name = "gpu_cc_gmu_clk_src",
168		.parent_data = gpu_cc_parent_data_1,
169		.num_parents = ARRAY_SIZE(gpu_cc_parent_data_1),
170		.flags = CLK_SET_RATE_PARENT,
171		.ops = &clk_rcg2_shared_ops,
172	},
173};
174
175static const struct freq_tbl ftbl_gpu_cc_hub_clk_src[] = {
176	F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0),
177	F(300000000, P_GPLL0_OUT_MAIN, 2, 0, 0),
178	F(400000000, P_GPLL0_OUT_MAIN, 1.5, 0, 0),
179	{ }
180};
181
182static struct clk_rcg2 gpu_cc_hub_clk_src = {
183	.cmd_rcgr = 0x93ec,
184	.mnd_width = 0,
185	.hid_width = 5,
186	.parent_map = gpu_cc_parent_map_1,
187	.freq_tbl = ftbl_gpu_cc_hub_clk_src,
188	.clkr.hw.init = &(const struct clk_init_data) {
189		.name = "gpu_cc_hub_clk_src",
190		.parent_data = gpu_cc_parent_data_1,
191		.num_parents = ARRAY_SIZE(gpu_cc_parent_data_1),
192		.flags = CLK_SET_RATE_PARENT,
193		.ops = &clk_rcg2_shared_ops,
194	},
195};
196
197static struct clk_regmap_div gpu_cc_hub_div_clk_src = {
198	.reg = 0x942c,
199	.shift = 0,
200	.width = 4,
201	.clkr.hw.init = &(const struct clk_init_data) {
202		.name = "gpu_cc_hub_div_clk_src",
203		.parent_hws = (const struct clk_hw*[]) {
204			&gpu_cc_hub_clk_src.clkr.hw,
205		},
206		.num_parents = 1,
207		.flags = CLK_SET_RATE_PARENT,
208		.ops = &clk_regmap_div_ro_ops,
209	},
210};
211
212static struct clk_branch gpu_cc_ahb_clk = {
213	.halt_reg = 0x90bc,
214	.halt_check = BRANCH_HALT_DELAY,
215	.clkr = {
216		.enable_reg = 0x90bc,
217		.enable_mask = BIT(0),
218		.hw.init = &(const struct clk_init_data) {
219			.name = "gpu_cc_ahb_clk",
220			.parent_hws = (const struct clk_hw*[]) {
221				&gpu_cc_hub_div_clk_src.clkr.hw,
222			},
223			.num_parents = 1,
224			.flags = CLK_SET_RATE_PARENT,
225			.ops = &clk_branch2_ops,
226		},
227	},
228};
229
230static struct clk_branch gpu_cc_cx_accu_shift_clk = {
231	.halt_reg = 0x910c,
232	.halt_check = BRANCH_HALT_VOTED,
233	.clkr = {
234		.enable_reg = 0x910c,
235		.enable_mask = BIT(0),
236		.hw.init = &(const struct clk_init_data) {
237			.name = "gpu_cc_cx_accu_shift_clk",
238			.ops = &clk_branch2_ops,
239		},
240	},
241};
242
243static struct clk_branch gpu_cc_cx_ff_clk = {
244	.halt_reg = 0x90ec,
245	.halt_check = BRANCH_HALT,
246	.clkr = {
247		.enable_reg = 0x90ec,
248		.enable_mask = BIT(0),
249		.hw.init = &(const struct clk_init_data) {
250			.name = "gpu_cc_cx_ff_clk",
251			.parent_hws = (const struct clk_hw*[]) {
252				&gpu_cc_ff_clk_src.clkr.hw,
253			},
254			.num_parents = 1,
255			.flags = CLK_SET_RATE_PARENT,
256			.ops = &clk_branch2_ops,
257		},
258	},
259};
260
261static struct clk_branch gpu_cc_cx_gmu_clk = {
262	.halt_reg = 0x90d4,
263	.halt_check = BRANCH_HALT_VOTED,
264	.clkr = {
265		.enable_reg = 0x90d4,
266		.enable_mask = BIT(0),
267		.hw.init = &(const struct clk_init_data) {
268			.name = "gpu_cc_cx_gmu_clk",
269			.parent_hws = (const struct clk_hw*[]) {
270				&gpu_cc_gmu_clk_src.clkr.hw,
271			},
272			.num_parents = 1,
273			.flags = CLK_SET_RATE_PARENT,
274			.ops = &clk_branch2_aon_ops,
275		},
276	},
277};
278
279static struct clk_branch gpu_cc_cxo_clk = {
280	.halt_reg = 0x90e4,
281	.halt_check = BRANCH_HALT,
282	.clkr = {
283		.enable_reg = 0x90e4,
284		.enable_mask = BIT(0),
285		.hw.init = &(const struct clk_init_data) {
286			.name = "gpu_cc_cxo_clk",
287			.ops = &clk_branch2_ops,
288		},
289	},
290};
291
292static struct clk_branch gpu_cc_dpm_clk = {
293	.halt_reg = 0x9110,
294	.halt_check = BRANCH_HALT,
295	.clkr = {
296		.enable_reg = 0x9110,
297		.enable_mask = BIT(0),
298		.hw.init = &(const struct clk_init_data) {
299			.name = "gpu_cc_dpm_clk",
300			.ops = &clk_branch2_ops,
301		},
302	},
303};
304
305static struct clk_branch gpu_cc_freq_measure_clk = {
306	.halt_reg = 0x900c,
307	.halt_check = BRANCH_HALT,
308	.clkr = {
309		.enable_reg = 0x900c,
310		.enable_mask = BIT(0),
311		.hw.init = &(const struct clk_init_data) {
312			.name = "gpu_cc_freq_measure_clk",
313			.ops = &clk_branch2_ops,
314		},
315	},
316};
317
318static struct clk_branch gpu_cc_gx_accu_shift_clk = {
319	.halt_reg = 0x9070,
320	.halt_check = BRANCH_HALT_VOTED,
321	.clkr = {
322		.enable_reg = 0x9070,
323		.enable_mask = BIT(0),
324		.hw.init = &(const struct clk_init_data) {
325			.name = "gpu_cc_gx_accu_shift_clk",
326			.ops = &clk_branch2_ops,
327		},
328	},
329};
330
331static struct clk_branch gpu_cc_gx_acd_ahb_ff_clk = {
332	.halt_reg = 0x9068,
333	.halt_check = BRANCH_HALT,
334	.clkr = {
335		.enable_reg = 0x9068,
336		.enable_mask = BIT(0),
337		.hw.init = &(const struct clk_init_data) {
338			.name = "gpu_cc_gx_acd_ahb_ff_clk",
339			.parent_hws = (const struct clk_hw*[]) {
340				&gpu_cc_ff_clk_src.clkr.hw,
341			},
342			.num_parents = 1,
343			.flags = CLK_SET_RATE_PARENT,
344			.ops = &clk_branch2_ops,
345		},
346	},
347};
348
349static struct clk_branch gpu_cc_gx_gmu_clk = {
350	.halt_reg = 0x9060,
351	.halt_check = BRANCH_HALT,
352	.clkr = {
353		.enable_reg = 0x9060,
354		.enable_mask = BIT(0),
355		.hw.init = &(const struct clk_init_data) {
356			.name = "gpu_cc_gx_gmu_clk",
357			.parent_hws = (const struct clk_hw*[]) {
358				&gpu_cc_gmu_clk_src.clkr.hw,
359			},
360			.num_parents = 1,
361			.flags = CLK_SET_RATE_PARENT,
362			.ops = &clk_branch2_ops,
363		},
364	},
365};
366
367static struct clk_branch gpu_cc_gx_rcg_ahb_ff_clk = {
368	.halt_reg = 0x906c,
369	.halt_check = BRANCH_HALT_VOTED,
370	.clkr = {
371		.enable_reg = 0x906c,
372		.enable_mask = BIT(0),
373		.hw.init = &(const struct clk_init_data) {
374			.name = "gpu_cc_gx_rcg_ahb_ff_clk",
375			.parent_hws = (const struct clk_hw*[]) {
376				&gpu_cc_ff_clk_src.clkr.hw,
377			},
378			.num_parents = 1,
379			.flags = CLK_SET_RATE_PARENT,
380			.ops = &clk_branch2_ops,
381		},
382	},
383};
384
385static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk = {
386	.halt_reg = 0x7000,
387	.halt_check = BRANCH_HALT_VOTED,
388	.clkr = {
389		.enable_reg = 0x7000,
390		.enable_mask = BIT(0),
391		.hw.init = &(const struct clk_init_data) {
392			.name = "gpu_cc_hlos1_vote_gpu_smmu_clk",
393			.ops = &clk_branch2_ops,
394		},
395	},
396};
397
398static struct clk_branch gpu_cc_hub_aon_clk = {
399	.halt_reg = 0x93e8,
400	.halt_check = BRANCH_HALT_VOTED,
401	.clkr = {
402		.enable_reg = 0x93e8,
403		.enable_mask = BIT(0),
404		.hw.init = &(const struct clk_init_data) {
405			.name = "gpu_cc_hub_aon_clk",
406			.parent_hws = (const struct clk_hw*[]) {
407				&gpu_cc_hub_clk_src.clkr.hw,
408			},
409			.num_parents = 1,
410			.flags = CLK_SET_RATE_PARENT,
411			.ops = &clk_branch2_aon_ops,
412		},
413	},
414};
415
416static struct clk_branch gpu_cc_hub_cx_int_clk = {
417	.halt_reg = 0x90e8,
418	.halt_check = BRANCH_HALT_VOTED,
419	.clkr = {
420		.enable_reg = 0x90e8,
421		.enable_mask = BIT(0),
422		.hw.init = &(const struct clk_init_data) {
423			.name = "gpu_cc_hub_cx_int_clk",
424			.parent_hws = (const struct clk_hw*[]) {
425				&gpu_cc_hub_clk_src.clkr.hw,
426			},
427			.num_parents = 1,
428			.flags = CLK_SET_RATE_PARENT,
429			.ops = &clk_branch2_aon_ops,
430		},
431	},
432};
433
434static struct clk_branch gpu_cc_memnoc_gfx_clk = {
435	.halt_reg = 0x90f4,
436	.halt_check = BRANCH_HALT_VOTED,
437	.clkr = {
438		.enable_reg = 0x90f4,
439		.enable_mask = BIT(0),
440		.hw.init = &(const struct clk_init_data) {
441			.name = "gpu_cc_memnoc_gfx_clk",
442			.ops = &clk_branch2_ops,
443		},
444	},
445};
446
447static struct gdsc gpu_cc_cx_gdsc = {
448	.gdscr = 0x9080,
449	.gds_hw_ctrl = 0x9094,
450	.en_rest_wait_val = 0x2,
451	.en_few_wait_val = 0x2,
452	.clk_dis_wait_val = 0x8,
453	.pd = {
454		.name = "gpu_cc_cx_gdsc",
455	},
456	.pwrsts = PWRSTS_OFF_ON,
457	.flags = RETAIN_FF_ENABLE | VOTABLE,
458};
459
460static struct clk_regmap *gpu_cc_milos_clocks[] = {
461	[GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr,
462	[GPU_CC_CX_ACCU_SHIFT_CLK] = &gpu_cc_cx_accu_shift_clk.clkr,
463	[GPU_CC_CX_FF_CLK] = &gpu_cc_cx_ff_clk.clkr,
464	[GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr,
465	[GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr,
466	[GPU_CC_DPM_CLK] = &gpu_cc_dpm_clk.clkr,
467	[GPU_CC_FF_CLK_SRC] = &gpu_cc_ff_clk_src.clkr,
468	[GPU_CC_FREQ_MEASURE_CLK] = &gpu_cc_freq_measure_clk.clkr,
469	[GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr,
470	[GPU_CC_GX_ACCU_SHIFT_CLK] = &gpu_cc_gx_accu_shift_clk.clkr,
471	[GPU_CC_GX_ACD_AHB_FF_CLK] = &gpu_cc_gx_acd_ahb_ff_clk.clkr,
472	[GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr,
473	[GPU_CC_GX_RCG_AHB_FF_CLK] = &gpu_cc_gx_rcg_ahb_ff_clk.clkr,
474	[GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK] = &gpu_cc_hlos1_vote_gpu_smmu_clk.clkr,
475	[GPU_CC_HUB_AON_CLK] = &gpu_cc_hub_aon_clk.clkr,
476	[GPU_CC_HUB_CLK_SRC] = &gpu_cc_hub_clk_src.clkr,
477	[GPU_CC_HUB_CX_INT_CLK] = &gpu_cc_hub_cx_int_clk.clkr,
478	[GPU_CC_HUB_DIV_CLK_SRC] = &gpu_cc_hub_div_clk_src.clkr,
479	[GPU_CC_MEMNOC_GFX_CLK] = &gpu_cc_memnoc_gfx_clk.clkr,
480	[GPU_CC_PLL0] = &gpu_cc_pll0.clkr,
481	[GPU_CC_PLL0_OUT_EVEN] = &gpu_cc_pll0_out_even.clkr,
482};
483
484static struct gdsc *gpu_cc_milos_gdscs[] = {
485	[GPU_CC_CX_GDSC] = &gpu_cc_cx_gdsc,
486};
487
488static const struct qcom_reset_map gpu_cc_milos_resets[] = {
489	[GPU_CC_CB_BCR] = { 0x93a0 },
490	[GPU_CC_CX_BCR] = { 0x907c },
491	[GPU_CC_FAST_HUB_BCR] = { 0x93e4 },
492	[GPU_CC_FF_BCR] = { 0x9470 },
493	[GPU_CC_GMU_BCR] = { 0x9314 },
494	[GPU_CC_GX_BCR] = { 0x905c },
495	[GPU_CC_RBCPR_BCR] = { 0x91e0 },
496	[GPU_CC_XO_BCR] = { 0x9000 },
497};
498
499static struct clk_alpha_pll *gpu_cc_milos_plls[] = {
500	&gpu_cc_pll0,
501};
502
503static u32 gpu_cc_milos_critical_cbcrs[] = {
504	0x93a4, /* GPU_CC_CB_CLK */
505	0x9008, /* GPU_CC_CXO_AON_CLK */
506	0x9010, /* GPU_CC_DEMET_CLK */
507	0x9064, /* GPU_CC_GX_AHB_FF_CLK */
508	0x93a8, /* GPU_CC_RSCC_HUB_AON_CLK */
509	0x9004, /* GPU_CC_RSCC_XO_AON_CLK */
510	0x90cc, /* GPU_CC_SLEEP_CLK */
511};
512
513static const struct regmap_config gpu_cc_milos_regmap_config = {
514	.reg_bits = 32,
515	.reg_stride = 4,
516	.val_bits = 32,
517	.max_register = 0x95e8,
518	.fast_io = true,
519};
520
521static struct qcom_cc_driver_data gpu_cc_milos_driver_data = {
522	.alpha_plls = gpu_cc_milos_plls,
523	.num_alpha_plls = ARRAY_SIZE(gpu_cc_milos_plls),
524	.clk_cbcrs = gpu_cc_milos_critical_cbcrs,
525	.num_clk_cbcrs = ARRAY_SIZE(gpu_cc_milos_critical_cbcrs),
526};
527
528static const struct qcom_cc_desc gpu_cc_milos_desc = {
529	.config = &gpu_cc_milos_regmap_config,
530	.clks = gpu_cc_milos_clocks,
531	.num_clks = ARRAY_SIZE(gpu_cc_milos_clocks),
532	.resets = gpu_cc_milos_resets,
533	.num_resets = ARRAY_SIZE(gpu_cc_milos_resets),
534	.gdscs = gpu_cc_milos_gdscs,
535	.num_gdscs = ARRAY_SIZE(gpu_cc_milos_gdscs),
536	.use_rpm = true,
537	.driver_data = &gpu_cc_milos_driver_data,
538};
539
540static const struct of_device_id gpu_cc_milos_match_table[] = {
541	{ .compatible = "qcom,milos-gpucc" },
542	{ }
543};
544MODULE_DEVICE_TABLE(of, gpu_cc_milos_match_table);
545
546static int gpu_cc_milos_probe(struct platform_device *pdev)
547{
548	return qcom_cc_probe(pdev, &gpu_cc_milos_desc);
549}
550
551static struct platform_driver gpu_cc_milos_driver = {
552	.probe = gpu_cc_milos_probe,
553	.driver = {
554		.name = "gpu_cc-milos",
555		.of_match_table = gpu_cc_milos_match_table,
556	},
557};
558
559module_platform_driver(gpu_cc_milos_driver);
560
561MODULE_DESCRIPTION("QTI GPU_CC Milos Driver");
562MODULE_LICENSE("GPL");
~/ Read-only file preview.