File Index
Files and directories
Sign in
FILE

videocc-sm8750.c

File preview with syntax highlighting.

linux-6.19.14/drivers/clk/qcom/videocc-sm8750.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
  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/pm_runtime.h>
 11#include <linux/regmap.h>
 12
 13#include <dt-bindings/clock/qcom,sm8750-videocc.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
 26enum {
 27	DT_BI_TCXO,
 28	DT_BI_TCXO_AO,
 29	DT_SLEEP_CLK,
 30};
 31
 32enum {
 33	P_BI_TCXO,
 34	P_SLEEP_CLK,
 35	P_VIDEO_CC_PLL0_OUT_MAIN,
 36};
 37
 38static const struct pll_vco taycan_elu_vco[] = {
 39	{ 249600000, 2500000000, 0 },
 40};
 41
 42static const struct alpha_pll_config video_cc_pll0_config = {
 43	.l = 0x25,
 44	.alpha = 0x8000,
 45	.config_ctl_val = 0x19660387,
 46	.config_ctl_hi_val = 0x098060a0,
 47	.config_ctl_hi1_val = 0xb416cb20,
 48	.user_ctl_val = 0x00000000,
 49	.user_ctl_hi_val = 0x00000002,
 50};
 51
 52static struct clk_alpha_pll video_cc_pll0 = {
 53	.offset = 0x0,
 54	.config = &video_cc_pll0_config,
 55	.vco_table = taycan_elu_vco,
 56	.num_vco = ARRAY_SIZE(taycan_elu_vco),
 57	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_ELU],
 58	.clkr = {
 59		.hw.init = &(const struct clk_init_data) {
 60			.name = "video_cc_pll0",
 61			.parent_data = &(const struct clk_parent_data) {
 62				.index = DT_BI_TCXO,
 63			},
 64			.num_parents = 1,
 65			.ops = &clk_alpha_pll_taycan_elu_ops,
 66		},
 67	},
 68};
 69
 70static const struct parent_map video_cc_parent_map_0[] = {
 71	{ P_BI_TCXO, 0 },
 72};
 73
 74static const struct clk_parent_data video_cc_parent_data_0_ao[] = {
 75	{ .index = DT_BI_TCXO_AO },
 76};
 77
 78static const struct parent_map video_cc_parent_map_1[] = {
 79	{ P_BI_TCXO, 0 },
 80	{ P_VIDEO_CC_PLL0_OUT_MAIN, 1 },
 81};
 82
 83static const struct clk_parent_data video_cc_parent_data_1[] = {
 84	{ .index = DT_BI_TCXO },
 85	{ .hw = &video_cc_pll0.clkr.hw },
 86};
 87
 88static const struct parent_map video_cc_parent_map_2[] = {
 89	{ P_SLEEP_CLK, 0 },
 90};
 91
 92static const struct clk_parent_data video_cc_parent_data_2_ao[] = {
 93	{ .index = DT_SLEEP_CLK },
 94};
 95
 96static const struct freq_tbl ftbl_video_cc_ahb_clk_src[] = {
 97	F(19200000, P_BI_TCXO, 1, 0, 0),
 98	{ }
 99};
100
101static struct clk_rcg2 video_cc_ahb_clk_src = {
102	.cmd_rcgr = 0x8018,
103	.mnd_width = 0,
104	.hid_width = 5,
105	.parent_map = video_cc_parent_map_0,
106	.freq_tbl = ftbl_video_cc_ahb_clk_src,
107	.clkr.hw.init = &(const struct clk_init_data) {
108		.name = "video_cc_ahb_clk_src",
109		.parent_data = video_cc_parent_data_0_ao,
110		.num_parents = ARRAY_SIZE(video_cc_parent_data_0_ao),
111		.flags = CLK_SET_RATE_PARENT,
112		.ops = &clk_rcg2_ops,
113	},
114};
115
116static const struct freq_tbl ftbl_video_cc_mvs0_clk_src[] = {
117	F(720000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
118	F(1014000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
119	F(1260000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
120	F(1332000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
121	F(1600000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
122	F(1710000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
123	F(1890000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
124	{ }
125};
126
127static struct clk_rcg2 video_cc_mvs0_clk_src = {
128	.cmd_rcgr = 0x8000,
129	.mnd_width = 0,
130	.hid_width = 5,
131	.parent_map = video_cc_parent_map_1,
132	.freq_tbl = ftbl_video_cc_mvs0_clk_src,
133	.clkr.hw.init = &(const struct clk_init_data) {
134		.name = "video_cc_mvs0_clk_src",
135		.parent_data = video_cc_parent_data_1,
136		.num_parents = ARRAY_SIZE(video_cc_parent_data_1),
137		.flags = CLK_SET_RATE_PARENT,
138		.ops = &clk_rcg2_shared_ops,
139	},
140};
141
142static const struct freq_tbl ftbl_video_cc_sleep_clk_src[] = {
143	F(32000, P_SLEEP_CLK, 1, 0, 0),
144	{ }
145};
146
147static struct clk_rcg2 video_cc_sleep_clk_src = {
148	.cmd_rcgr = 0x80e0,
149	.mnd_width = 0,
150	.hid_width = 5,
151	.parent_map = video_cc_parent_map_2,
152	.freq_tbl = ftbl_video_cc_sleep_clk_src,
153	.clkr.hw.init = &(const struct clk_init_data) {
154		.name = "video_cc_sleep_clk_src",
155		.parent_data = video_cc_parent_data_2_ao,
156		.num_parents = ARRAY_SIZE(video_cc_parent_data_2_ao),
157		.flags = CLK_SET_RATE_PARENT,
158		.ops = &clk_rcg2_ops,
159	},
160};
161
162static struct clk_rcg2 video_cc_xo_clk_src = {
163	.cmd_rcgr = 0x80bc,
164	.mnd_width = 0,
165	.hid_width = 5,
166	.parent_map = video_cc_parent_map_0,
167	.freq_tbl = ftbl_video_cc_ahb_clk_src,
168	.clkr.hw.init = &(const struct clk_init_data) {
169		.name = "video_cc_xo_clk_src",
170		.parent_data = video_cc_parent_data_0_ao,
171		.num_parents = ARRAY_SIZE(video_cc_parent_data_0_ao),
172		.flags = CLK_SET_RATE_PARENT,
173		.ops = &clk_rcg2_ops,
174	},
175};
176
177static struct clk_regmap_div video_cc_mvs0_div_clk_src = {
178	.reg = 0x809c,
179	.shift = 0,
180	.width = 4,
181	.clkr.hw.init = &(const struct clk_init_data) {
182		.name = "video_cc_mvs0_div_clk_src",
183		.parent_hws = (const struct clk_hw*[]) {
184			&video_cc_mvs0_clk_src.clkr.hw,
185		},
186		.num_parents = 1,
187		.flags = CLK_SET_RATE_PARENT,
188		.ops = &clk_regmap_div_ro_ops,
189	},
190};
191
192static struct clk_regmap_div video_cc_mvs0c_div2_div_clk_src = {
193	.reg = 0x8060,
194	.shift = 0,
195	.width = 4,
196	.clkr.hw.init = &(const struct clk_init_data) {
197		.name = "video_cc_mvs0c_div2_div_clk_src",
198		.parent_hws = (const struct clk_hw*[]) {
199			&video_cc_mvs0_clk_src.clkr.hw,
200		},
201		.num_parents = 1,
202		.flags = CLK_SET_RATE_PARENT,
203		.ops = &clk_regmap_div_ro_ops,
204	},
205};
206
207static struct clk_branch video_cc_mvs0_clk = {
208	.halt_reg = 0x807c,
209	.halt_check = BRANCH_HALT_VOTED,
210	.hwcg_reg = 0x807c,
211	.hwcg_bit = 1,
212	.clkr = {
213		.enable_reg = 0x807c,
214		.enable_mask = BIT(0),
215		.hw.init = &(const struct clk_init_data) {
216			.name = "video_cc_mvs0_clk",
217			.parent_hws = (const struct clk_hw*[]) {
218				&video_cc_mvs0_div_clk_src.clkr.hw,
219			},
220			.num_parents = 1,
221			.flags = CLK_SET_RATE_PARENT,
222			.ops = &clk_branch2_ops,
223		},
224	},
225};
226
227static struct clk_mem_branch video_cc_mvs0_freerun_clk = {
228	.mem_enable_reg = 0x8090,
229	.mem_ack_reg =  0x8090,
230	.mem_enable_mask = BIT(3),
231	.mem_enable_ack_mask = GENMASK(11, 10),
232	.mem_enable_invert = true,
233	.branch = {
234		.halt_reg = 0x808c,
235		.halt_check = BRANCH_HALT,
236		.clkr = {
237			.enable_reg = 0x808c,
238			.enable_mask = BIT(0),
239			.hw.init = &(const struct clk_init_data) {
240				.name = "video_cc_mvs0_freerun_clk",
241				.parent_hws = (const struct clk_hw*[]) {
242					&video_cc_mvs0_div_clk_src.clkr.hw,
243				},
244				.num_parents = 1,
245				.flags = CLK_SET_RATE_PARENT,
246				.ops = &clk_branch2_mem_ops,
247			},
248		},
249	},
250};
251
252static struct clk_branch video_cc_mvs0_shift_clk = {
253	.halt_reg = 0x80d8,
254	.halt_check = BRANCH_HALT_VOTED,
255	.hwcg_reg = 0x80d8,
256	.hwcg_bit = 1,
257	.clkr = {
258		.enable_reg = 0x80d8,
259		.enable_mask = BIT(0),
260		.hw.init = &(const struct clk_init_data) {
261			.name = "video_cc_mvs0_shift_clk",
262			.parent_hws = (const struct clk_hw*[]) {
263				&video_cc_xo_clk_src.clkr.hw,
264			},
265			.num_parents = 1,
266			.flags = CLK_SET_RATE_PARENT,
267			.ops = &clk_branch2_ops,
268		},
269	},
270};
271
272static struct clk_branch video_cc_mvs0c_clk = {
273	.halt_reg = 0x804c,
274	.halt_check = BRANCH_HALT,
275	.clkr = {
276		.enable_reg = 0x804c,
277		.enable_mask = BIT(0),
278		.hw.init = &(const struct clk_init_data) {
279			.name = "video_cc_mvs0c_clk",
280			.parent_hws = (const struct clk_hw*[]) {
281				&video_cc_mvs0c_div2_div_clk_src.clkr.hw,
282			},
283			.num_parents = 1,
284			.flags = CLK_SET_RATE_PARENT,
285			.ops = &clk_branch2_ops,
286		},
287	},
288};
289
290static struct clk_branch video_cc_mvs0c_freerun_clk = {
291	.halt_reg = 0x805c,
292	.halt_check = BRANCH_HALT,
293	.clkr = {
294		.enable_reg = 0x805c,
295		.enable_mask = BIT(0),
296		.hw.init = &(const struct clk_init_data) {
297			.name = "video_cc_mvs0c_freerun_clk",
298			.parent_hws = (const struct clk_hw*[]) {
299				&video_cc_mvs0c_div2_div_clk_src.clkr.hw,
300			},
301			.num_parents = 1,
302			.flags = CLK_SET_RATE_PARENT,
303			.ops = &clk_branch2_ops,
304		},
305	},
306};
307
308static struct clk_branch video_cc_mvs0c_shift_clk = {
309	.halt_reg = 0x80dc,
310	.halt_check = BRANCH_HALT_VOTED,
311	.hwcg_reg = 0x80dc,
312	.hwcg_bit = 1,
313	.clkr = {
314		.enable_reg = 0x80dc,
315		.enable_mask = BIT(0),
316		.hw.init = &(const struct clk_init_data) {
317			.name = "video_cc_mvs0c_shift_clk",
318			.parent_hws = (const struct clk_hw*[]) {
319				&video_cc_xo_clk_src.clkr.hw,
320			},
321			.num_parents = 1,
322			.flags = CLK_SET_RATE_PARENT,
323			.ops = &clk_branch2_ops,
324		},
325	},
326};
327
328static struct gdsc video_cc_mvs0c_gdsc = {
329	.gdscr = 0x8034,
330	.en_rest_wait_val = 0x2,
331	.en_few_wait_val = 0x2,
332	.clk_dis_wait_val = 0x6,
333	.pd = {
334		.name = "video_cc_mvs0c_gdsc",
335	},
336	.pwrsts = PWRSTS_OFF_ON,
337	.flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
338};
339
340static struct gdsc video_cc_mvs0_gdsc = {
341	.gdscr = 0x8068,
342	.en_rest_wait_val = 0x2,
343	.en_few_wait_val = 0x2,
344	.clk_dis_wait_val = 0x6,
345	.pd = {
346		.name = "video_cc_mvs0_gdsc",
347	},
348	.pwrsts = PWRSTS_OFF_ON,
349	.parent = &video_cc_mvs0c_gdsc.pd,
350	.flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE | HW_CTRL_TRIGGER,
351};
352
353static struct clk_regmap *video_cc_sm8750_clocks[] = {
354	[VIDEO_CC_AHB_CLK_SRC] = &video_cc_ahb_clk_src.clkr,
355	[VIDEO_CC_MVS0_CLK] = &video_cc_mvs0_clk.clkr,
356	[VIDEO_CC_MVS0_CLK_SRC] = &video_cc_mvs0_clk_src.clkr,
357	[VIDEO_CC_MVS0_DIV_CLK_SRC] = &video_cc_mvs0_div_clk_src.clkr,
358	[VIDEO_CC_MVS0_FREERUN_CLK] = &video_cc_mvs0_freerun_clk.branch.clkr,
359	[VIDEO_CC_MVS0_SHIFT_CLK] = &video_cc_mvs0_shift_clk.clkr,
360	[VIDEO_CC_MVS0C_CLK] = &video_cc_mvs0c_clk.clkr,
361	[VIDEO_CC_MVS0C_DIV2_DIV_CLK_SRC] = &video_cc_mvs0c_div2_div_clk_src.clkr,
362	[VIDEO_CC_MVS0C_FREERUN_CLK] = &video_cc_mvs0c_freerun_clk.clkr,
363	[VIDEO_CC_MVS0C_SHIFT_CLK] = &video_cc_mvs0c_shift_clk.clkr,
364	[VIDEO_CC_PLL0] = &video_cc_pll0.clkr,
365	[VIDEO_CC_SLEEP_CLK_SRC] = &video_cc_sleep_clk_src.clkr,
366	[VIDEO_CC_XO_CLK_SRC] = &video_cc_xo_clk_src.clkr,
367};
368
369static struct gdsc *video_cc_sm8750_gdscs[] = {
370	[VIDEO_CC_MVS0_GDSC] = &video_cc_mvs0_gdsc,
371	[VIDEO_CC_MVS0C_GDSC] = &video_cc_mvs0c_gdsc,
372};
373
374static const struct qcom_reset_map video_cc_sm8750_resets[] = {
375	[VIDEO_CC_INTERFACE_BCR] = { 0x80a0 },
376	[VIDEO_CC_MVS0_BCR] = { 0x8064 },
377	[VIDEO_CC_MVS0C_CLK_ARES] = { 0x804c, 2 },
378	[VIDEO_CC_MVS0C_BCR] = { 0x8030 },
379	[VIDEO_CC_MVS0_FREERUN_CLK_ARES] = { 0x808c, 2 },
380	[VIDEO_CC_MVS0C_FREERUN_CLK_ARES] = { 0x805c, 2 },
381	[VIDEO_CC_XO_CLK_ARES] = { 0x80d4, 2 },
382};
383
384static const struct regmap_config video_cc_sm8750_regmap_config = {
385	.reg_bits = 32,
386	.reg_stride = 4,
387	.val_bits = 32,
388	.max_register = 0x9f4c,
389	.fast_io = true,
390};
391
392static struct clk_alpha_pll *video_cc_sm8750_plls[] = {
393	&video_cc_pll0,
394};
395
396static u32 video_cc_sm8750_critical_cbcrs[] = {
397	0x80a4, /* VIDEO_CC_AHB_CLK */
398	0x80f8, /* VIDEO_CC_SLEEP_CLK */
399	0x80d4, /* VIDEO_CC_XO_CLK */
400};
401
402static void clk_sm8750_regs_configure(struct device *dev, struct regmap *regmap)
403{
404	/* Update DLY_ACCU_RED_SHIFTER_DONE to 0xF for mvs0, mvs0c */
405	regmap_update_bits(regmap, 0x8074, GENMASK(25, 21), GENMASK(25, 21));
406	regmap_update_bits(regmap, 0x8040, GENMASK(25, 21), GENMASK(25, 21));
407
408	regmap_update_bits(regmap, 0x9f24, BIT(0), BIT(0));
409}
410
411static struct qcom_cc_driver_data video_cc_sm8750_driver_data = {
412	.alpha_plls = video_cc_sm8750_plls,
413	.num_alpha_plls = ARRAY_SIZE(video_cc_sm8750_plls),
414	.clk_cbcrs = video_cc_sm8750_critical_cbcrs,
415	.num_clk_cbcrs = ARRAY_SIZE(video_cc_sm8750_critical_cbcrs),
416	.clk_regs_configure = clk_sm8750_regs_configure,
417};
418
419static struct qcom_cc_desc video_cc_sm8750_desc = {
420	.config = &video_cc_sm8750_regmap_config,
421	.clks = video_cc_sm8750_clocks,
422	.num_clks = ARRAY_SIZE(video_cc_sm8750_clocks),
423	.resets = video_cc_sm8750_resets,
424	.num_resets = ARRAY_SIZE(video_cc_sm8750_resets),
425	.gdscs = video_cc_sm8750_gdscs,
426	.num_gdscs = ARRAY_SIZE(video_cc_sm8750_gdscs),
427	.use_rpm = true,
428	.driver_data = &video_cc_sm8750_driver_data,
429};
430
431static const struct of_device_id video_cc_sm8750_match_table[] = {
432	{ .compatible = "qcom,sm8750-videocc" },
433	{ }
434};
435MODULE_DEVICE_TABLE(of, video_cc_sm8750_match_table);
436
437static int video_cc_sm8750_probe(struct platform_device *pdev)
438{
439	return qcom_cc_probe(pdev, &video_cc_sm8750_desc);
440}
441
442static struct platform_driver video_cc_sm8750_driver = {
443	.probe = video_cc_sm8750_probe,
444	.driver = {
445		.name = "video_cc-sm8750",
446		.of_match_table = video_cc_sm8750_match_table,
447	},
448};
449
450static int __init video_cc_sm8750_init(void)
451{
452	return platform_driver_register(&video_cc_sm8750_driver);
453}
454subsys_initcall(video_cc_sm8750_init);
455
456static void __exit video_cc_sm8750_exit(void)
457{
458	platform_driver_unregister(&video_cc_sm8750_driver);
459}
460module_exit(video_cc_sm8750_exit);
461
462MODULE_DESCRIPTION("QTI VIDEO_CC SM8750 Driver");
463MODULE_LICENSE("GPL");
~/ Read-only file preview.