File Index
Files and directories
Sign in
FILE

videocc-sm8450.c

File preview with syntax highlighting.

linux-6.19.14/drivers/clk/qcom/videocc-sm8450.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
  4 */
  5
  6#include <linux/clk-provider.h>
  7#include <linux/mod_devicetable.h>
  8#include <linux/module.h>
  9#include <linux/platform_device.h>
 10#include <linux/regmap.h>
 11
 12#include <dt-bindings/clock/qcom,sm8450-videocc.h>
 13
 14#include "clk-alpha-pll.h"
 15#include "clk-branch.h"
 16#include "clk-rcg.h"
 17#include "clk-regmap.h"
 18#include "clk-regmap-divider.h"
 19#include "common.h"
 20#include "gdsc.h"
 21#include "reset.h"
 22
 23enum {
 24	DT_BI_TCXO,
 25};
 26
 27enum {
 28	P_BI_TCXO,
 29	P_VIDEO_CC_PLL0_OUT_MAIN,
 30	P_VIDEO_CC_PLL1_OUT_MAIN,
 31};
 32
 33static const struct pll_vco lucid_evo_vco[] = {
 34	{ 249600000, 2020000000, 0 },
 35};
 36
 37static const struct alpha_pll_config video_cc_pll0_config = {
 38	/* .l includes CAL_L_VAL, L_VAL fields */
 39	.l = 0x0044001e,
 40	.alpha = 0x0,
 41	.config_ctl_val = 0x20485699,
 42	.config_ctl_hi_val = 0x00182261,
 43	.config_ctl_hi1_val = 0x32aa299c,
 44	.user_ctl_val = 0x00000000,
 45	.user_ctl_hi_val = 0x00000805,
 46};
 47
 48static const struct alpha_pll_config sm8475_video_cc_pll0_config = {
 49	/* .l includes CAL_L_VAL, L_VAL fields */
 50	.l = 0x1e,
 51	.alpha = 0x0,
 52	.config_ctl_val = 0x20485699,
 53	.config_ctl_hi_val = 0x00182261,
 54	.config_ctl_hi1_val = 0x82aa299c,
 55	.test_ctl_val = 0x00000000,
 56	.test_ctl_hi_val = 0x00000003,
 57	.test_ctl_hi1_val = 0x00009000,
 58	.test_ctl_hi2_val = 0x00000034,
 59	.user_ctl_val = 0x00000000,
 60	.user_ctl_hi_val = 0x00000005,
 61};
 62
 63static struct clk_alpha_pll video_cc_pll0 = {
 64	.offset = 0x0,
 65	.config = &video_cc_pll0_config,
 66	.vco_table = lucid_evo_vco,
 67	.num_vco = ARRAY_SIZE(lucid_evo_vco),
 68	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
 69	.clkr = {
 70		.hw.init = &(const struct clk_init_data) {
 71			.name = "video_cc_pll0",
 72			.parent_data = &(const struct clk_parent_data) {
 73				.index = DT_BI_TCXO,
 74			},
 75			.num_parents = 1,
 76			.ops = &clk_alpha_pll_lucid_evo_ops,
 77		},
 78	},
 79};
 80
 81static const struct alpha_pll_config video_cc_pll1_config = {
 82	/* .l includes CAL_L_VAL, L_VAL fields */
 83	.l = 0x0044002b,
 84	.alpha = 0xc000,
 85	.config_ctl_val = 0x20485699,
 86	.config_ctl_hi_val = 0x00182261,
 87	.config_ctl_hi1_val = 0x32aa299c,
 88	.user_ctl_val = 0x00000000,
 89	.user_ctl_hi_val = 0x00000805,
 90};
 91
 92static const struct alpha_pll_config sm8475_video_cc_pll1_config = {
 93	/* .l includes CAL_L_VAL, L_VAL fields */
 94	.l = 0x2b,
 95	.alpha = 0xc000,
 96	.config_ctl_val = 0x20485699,
 97	.config_ctl_hi_val = 0x00182261,
 98	.config_ctl_hi1_val = 0x82aa299c,
 99	.test_ctl_val = 0x00000000,
100	.test_ctl_hi_val = 0x00000003,
101	.test_ctl_hi1_val = 0x00009000,
102	.test_ctl_hi2_val = 0x00000034,
103	.user_ctl_val = 0x00000000,
104	.user_ctl_hi_val = 0x00000005,
105};
106
107static struct clk_alpha_pll video_cc_pll1 = {
108	.offset = 0x1000,
109	.config = &video_cc_pll1_config,
110	.vco_table = lucid_evo_vco,
111	.num_vco = ARRAY_SIZE(lucid_evo_vco),
112	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
113	.clkr = {
114		.hw.init = &(const struct clk_init_data) {
115			.name = "video_cc_pll1",
116			.parent_data = &(const struct clk_parent_data) {
117				.index = DT_BI_TCXO,
118			},
119			.num_parents = 1,
120			.ops = &clk_alpha_pll_lucid_evo_ops,
121		},
122	},
123};
124
125static const struct parent_map video_cc_parent_map_0[] = {
126	{ P_BI_TCXO, 0 },
127	{ P_VIDEO_CC_PLL0_OUT_MAIN, 1 },
128};
129
130static const struct clk_parent_data video_cc_parent_data_0[] = {
131	{ .index = DT_BI_TCXO },
132	{ .hw = &video_cc_pll0.clkr.hw },
133};
134
135static const struct parent_map video_cc_parent_map_1[] = {
136	{ P_BI_TCXO, 0 },
137	{ P_VIDEO_CC_PLL1_OUT_MAIN, 1 },
138};
139
140static const struct clk_parent_data video_cc_parent_data_1[] = {
141	{ .index = DT_BI_TCXO },
142	{ .hw = &video_cc_pll1.clkr.hw },
143};
144
145static const struct freq_tbl ftbl_video_cc_mvs0_clk_src[] = {
146	F(576000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
147	F(720000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
148	F(1014000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
149	F(1098000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
150	F(1332000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
151	{ }
152};
153
154static struct clk_rcg2 video_cc_mvs0_clk_src = {
155	.cmd_rcgr = 0x8000,
156	.mnd_width = 0,
157	.hid_width = 5,
158	.parent_map = video_cc_parent_map_0,
159	.freq_tbl = ftbl_video_cc_mvs0_clk_src,
160	.clkr.hw.init = &(const struct clk_init_data) {
161		.name = "video_cc_mvs0_clk_src",
162		.parent_data = video_cc_parent_data_0,
163		.num_parents = ARRAY_SIZE(video_cc_parent_data_0),
164		.flags = CLK_SET_RATE_PARENT,
165		.ops = &clk_rcg2_shared_ops,
166	},
167};
168
169static const struct freq_tbl ftbl_video_cc_mvs1_clk_src[] = {
170	F(840000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0),
171	F(1050000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0),
172	F(1350000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0),
173	F(1500000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0),
174	F(1650000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0),
175	{ }
176};
177
178static struct clk_rcg2 video_cc_mvs1_clk_src = {
179	.cmd_rcgr = 0x8018,
180	.mnd_width = 0,
181	.hid_width = 5,
182	.parent_map = video_cc_parent_map_1,
183	.freq_tbl = ftbl_video_cc_mvs1_clk_src,
184	.clkr.hw.init = &(const struct clk_init_data) {
185		.name = "video_cc_mvs1_clk_src",
186		.parent_data = video_cc_parent_data_1,
187		.num_parents = ARRAY_SIZE(video_cc_parent_data_1),
188		.flags = CLK_SET_RATE_PARENT,
189		.ops = &clk_rcg2_shared_ops,
190	},
191};
192
193static struct clk_regmap_div video_cc_mvs0_div_clk_src = {
194	.reg = 0x80b8,
195	.shift = 0,
196	.width = 4,
197	.clkr.hw.init = &(const struct clk_init_data) {
198		.name = "video_cc_mvs0_div_clk_src",
199		.parent_hws = (const struct clk_hw*[]) {
200			&video_cc_mvs0_clk_src.clkr.hw,
201		},
202		.num_parents = 1,
203		.flags = CLK_SET_RATE_PARENT,
204		.ops = &clk_regmap_div_ro_ops,
205	},
206};
207
208static struct clk_regmap_div video_cc_mvs0c_div2_div_clk_src = {
209	.reg = 0x806c,
210	.shift = 0,
211	.width = 4,
212	.clkr.hw.init = &(const struct clk_init_data) {
213		.name = "video_cc_mvs0c_div2_div_clk_src",
214		.parent_hws = (const struct clk_hw*[]) {
215			&video_cc_mvs0_clk_src.clkr.hw,
216		},
217		.num_parents = 1,
218		.flags = CLK_SET_RATE_PARENT,
219		.ops = &clk_regmap_div_ro_ops,
220	},
221};
222
223static struct clk_regmap_div video_cc_mvs1_div_clk_src = {
224	.reg = 0x80dc,
225	.shift = 0,
226	.width = 4,
227	.clkr.hw.init = &(const struct clk_init_data) {
228		.name = "video_cc_mvs1_div_clk_src",
229		.parent_hws = (const struct clk_hw*[]) {
230			&video_cc_mvs1_clk_src.clkr.hw,
231		},
232		.num_parents = 1,
233		.flags = CLK_SET_RATE_PARENT,
234		.ops = &clk_regmap_div_ro_ops,
235	},
236};
237
238static struct clk_regmap_div video_cc_mvs1c_div2_div_clk_src = {
239	.reg = 0x8094,
240	.shift = 0,
241	.width = 4,
242	.clkr.hw.init = &(const struct clk_init_data) {
243		.name = "video_cc_mvs1c_div2_div_clk_src",
244		.parent_hws = (const struct clk_hw*[]) {
245			&video_cc_mvs1_clk_src.clkr.hw,
246		},
247		.num_parents = 1,
248		.flags = CLK_SET_RATE_PARENT,
249		.ops = &clk_regmap_div_ro_ops,
250	},
251};
252
253static struct clk_branch video_cc_mvs0_clk = {
254	.halt_reg = 0x80b0,
255	.halt_check = BRANCH_HALT_SKIP,
256	.hwcg_reg = 0x80b0,
257	.hwcg_bit = 1,
258	.clkr = {
259		.enable_reg = 0x80b0,
260		.enable_mask = BIT(0),
261		.hw.init = &(const struct clk_init_data) {
262			.name = "video_cc_mvs0_clk",
263			.parent_hws = (const struct clk_hw*[]) {
264				&video_cc_mvs0_div_clk_src.clkr.hw,
265			},
266			.num_parents = 1,
267			.flags = CLK_SET_RATE_PARENT,
268			.ops = &clk_branch2_ops,
269		},
270	},
271};
272
273static struct clk_branch video_cc_mvs0c_clk = {
274	.halt_reg = 0x8064,
275	.halt_check = BRANCH_HALT,
276	.clkr = {
277		.enable_reg = 0x8064,
278		.enable_mask = BIT(0),
279		.hw.init = &(const struct clk_init_data) {
280			.name = "video_cc_mvs0c_clk",
281			.parent_hws = (const struct clk_hw*[]) {
282				&video_cc_mvs0c_div2_div_clk_src.clkr.hw,
283			},
284			.num_parents = 1,
285			.flags = CLK_SET_RATE_PARENT,
286			.ops = &clk_branch2_ops,
287		},
288	},
289};
290
291static struct clk_branch video_cc_mvs1_clk = {
292	.halt_reg = 0x80d4,
293	.halt_check = BRANCH_HALT_SKIP,
294	.hwcg_reg = 0x80d4,
295	.hwcg_bit = 1,
296	.clkr = {
297		.enable_reg = 0x80d4,
298		.enable_mask = BIT(0),
299		.hw.init = &(const struct clk_init_data) {
300			.name = "video_cc_mvs1_clk",
301			.parent_hws = (const struct clk_hw*[]) {
302				&video_cc_mvs1_div_clk_src.clkr.hw,
303			},
304			.num_parents = 1,
305			.flags = CLK_SET_RATE_PARENT,
306			.ops = &clk_branch2_ops,
307		},
308	},
309};
310
311static struct clk_branch video_cc_mvs1c_clk = {
312	.halt_reg = 0x808c,
313	.halt_check = BRANCH_HALT,
314	.clkr = {
315		.enable_reg = 0x808c,
316		.enable_mask = BIT(0),
317		.hw.init = &(const struct clk_init_data) {
318			.name = "video_cc_mvs1c_clk",
319			.parent_hws = (const struct clk_hw*[]) {
320				&video_cc_mvs1c_div2_div_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 gdsc video_cc_mvs0c_gdsc = {
330	.gdscr = 0x804c,
331	.en_rest_wait_val = 0x2,
332	.en_few_wait_val = 0x2,
333	.clk_dis_wait_val = 0x6,
334	.pd = {
335		.name = "video_cc_mvs0c_gdsc",
336	},
337	.pwrsts = PWRSTS_OFF_ON,
338	.flags = RETAIN_FF_ENABLE,
339};
340
341static struct gdsc video_cc_mvs0_gdsc = {
342	.gdscr = 0x809c,
343	.en_rest_wait_val = 0x2,
344	.en_few_wait_val = 0x2,
345	.clk_dis_wait_val = 0x6,
346	.pd = {
347		.name = "video_cc_mvs0_gdsc",
348	},
349	.pwrsts = PWRSTS_OFF_ON,
350	.parent = &video_cc_mvs0c_gdsc.pd,
351	.flags = HW_CTRL_TRIGGER | RETAIN_FF_ENABLE,
352};
353
354static struct gdsc video_cc_mvs1c_gdsc = {
355	.gdscr = 0x8074,
356	.en_rest_wait_val = 0x2,
357	.en_few_wait_val = 0x2,
358	.clk_dis_wait_val = 0x6,
359	.pd = {
360		.name = "video_cc_mvs1c_gdsc",
361	},
362	.pwrsts = PWRSTS_OFF_ON,
363	.flags = RETAIN_FF_ENABLE,
364};
365
366static struct gdsc video_cc_mvs1_gdsc = {
367	.gdscr = 0x80c0,
368	.en_rest_wait_val = 0x2,
369	.en_few_wait_val = 0x2,
370	.clk_dis_wait_val = 0x6,
371	.pd = {
372		.name = "video_cc_mvs1_gdsc",
373	},
374	.pwrsts = PWRSTS_OFF_ON,
375	.parent = &video_cc_mvs1c_gdsc.pd,
376	.flags = HW_CTRL_TRIGGER | RETAIN_FF_ENABLE,
377};
378
379static struct clk_regmap *video_cc_sm8450_clocks[] = {
380	[VIDEO_CC_MVS0_CLK] = &video_cc_mvs0_clk.clkr,
381	[VIDEO_CC_MVS0_CLK_SRC] = &video_cc_mvs0_clk_src.clkr,
382	[VIDEO_CC_MVS0_DIV_CLK_SRC] = &video_cc_mvs0_div_clk_src.clkr,
383	[VIDEO_CC_MVS0C_CLK] = &video_cc_mvs0c_clk.clkr,
384	[VIDEO_CC_MVS0C_DIV2_DIV_CLK_SRC] = &video_cc_mvs0c_div2_div_clk_src.clkr,
385	[VIDEO_CC_MVS1_CLK] = &video_cc_mvs1_clk.clkr,
386	[VIDEO_CC_MVS1_CLK_SRC] = &video_cc_mvs1_clk_src.clkr,
387	[VIDEO_CC_MVS1_DIV_CLK_SRC] = &video_cc_mvs1_div_clk_src.clkr,
388	[VIDEO_CC_MVS1C_CLK] = &video_cc_mvs1c_clk.clkr,
389	[VIDEO_CC_MVS1C_DIV2_DIV_CLK_SRC] = &video_cc_mvs1c_div2_div_clk_src.clkr,
390	[VIDEO_CC_PLL0] = &video_cc_pll0.clkr,
391	[VIDEO_CC_PLL1] = &video_cc_pll1.clkr,
392};
393
394static struct gdsc *video_cc_sm8450_gdscs[] = {
395	[VIDEO_CC_MVS0C_GDSC] = &video_cc_mvs0c_gdsc,
396	[VIDEO_CC_MVS0_GDSC] = &video_cc_mvs0_gdsc,
397	[VIDEO_CC_MVS1C_GDSC] = &video_cc_mvs1c_gdsc,
398	[VIDEO_CC_MVS1_GDSC] = &video_cc_mvs1_gdsc,
399};
400
401static const struct qcom_reset_map video_cc_sm8450_resets[] = {
402	[CVP_VIDEO_CC_INTERFACE_BCR] = { 0x80e0 },
403	[CVP_VIDEO_CC_MVS0_BCR] = { 0x8098 },
404	[CVP_VIDEO_CC_MVS0C_BCR] = { 0x8048 },
405	[CVP_VIDEO_CC_MVS1_BCR] = { 0x80bc },
406	[CVP_VIDEO_CC_MVS1C_BCR] = { 0x8070 },
407	[VIDEO_CC_MVS0C_CLK_ARES] = { .reg = 0x8064, .bit = 2, .udelay = 1000 },
408	[VIDEO_CC_MVS1C_CLK_ARES] = { .reg = 0x808c, .bit = 2, .udelay = 1000 },
409};
410
411static struct clk_alpha_pll *video_cc_sm8450_plls[] = {
412	&video_cc_pll0,
413	&video_cc_pll1,
414};
415
416static u32 video_cc_sm8450_critical_cbcrs[] = {
417	0x80e4, /* VIDEO_CC_AHB_CLK */
418	0x8114, /* VIDEO_CC_XO_CLK */
419	0x8130, /* VIDEO_CC_SLEEP_CLK */
420};
421
422static const struct regmap_config video_cc_sm8450_regmap_config = {
423	.reg_bits = 32,
424	.reg_stride = 4,
425	.val_bits = 32,
426	.max_register = 0x9f4c,
427	.fast_io = true,
428};
429
430static struct qcom_cc_driver_data video_cc_sm8450_driver_data = {
431	.alpha_plls = video_cc_sm8450_plls,
432	.num_alpha_plls = ARRAY_SIZE(video_cc_sm8450_plls),
433	.clk_cbcrs = video_cc_sm8450_critical_cbcrs,
434	.num_clk_cbcrs = ARRAY_SIZE(video_cc_sm8450_critical_cbcrs),
435};
436
437static const struct qcom_cc_desc video_cc_sm8450_desc = {
438	.config = &video_cc_sm8450_regmap_config,
439	.clks = video_cc_sm8450_clocks,
440	.num_clks = ARRAY_SIZE(video_cc_sm8450_clocks),
441	.resets = video_cc_sm8450_resets,
442	.num_resets = ARRAY_SIZE(video_cc_sm8450_resets),
443	.gdscs = video_cc_sm8450_gdscs,
444	.num_gdscs = ARRAY_SIZE(video_cc_sm8450_gdscs),
445	.use_rpm = true,
446	.driver_data = &video_cc_sm8450_driver_data,
447};
448
449static const struct of_device_id video_cc_sm8450_match_table[] = {
450	{ .compatible = "qcom,sm8450-videocc" },
451	{ .compatible = "qcom,sm8475-videocc" },
452	{ }
453};
454MODULE_DEVICE_TABLE(of, video_cc_sm8450_match_table);
455
456static int video_cc_sm8450_probe(struct platform_device *pdev)
457{
458	if (of_device_is_compatible(pdev->dev.of_node, "qcom,sm8475-videocc")) {
459		/* Update VideoCC PLL0 */
460		video_cc_pll0.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
461
462		/* Update VideoCC PLL1 */
463		video_cc_pll1.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
464
465		video_cc_pll0.config = &sm8475_video_cc_pll0_config;
466		video_cc_pll1.config = &sm8475_video_cc_pll1_config;
467	}
468
469	return qcom_cc_probe(pdev, &video_cc_sm8450_desc);
470}
471
472static struct platform_driver video_cc_sm8450_driver = {
473	.probe = video_cc_sm8450_probe,
474	.driver = {
475		.name = "video_cc-sm8450",
476		.of_match_table = video_cc_sm8450_match_table,
477	},
478};
479
480module_platform_driver(video_cc_sm8450_driver);
481
482MODULE_DESCRIPTION("QTI VIDEOCC SM8450 / SM8475 Driver");
483MODULE_LICENSE("GPL");
~/ Read-only file preview.