xref: /linux/drivers/clk/qcom/videocc-sm8450.c (revision 59cb902371227c2cd7932a565eda97ac7e4707bf)
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 
23 enum {
24 	DT_BI_TCXO,
25 };
26 
27 enum {
28 	P_BI_TCXO,
29 	P_VIDEO_CC_PLL0_OUT_MAIN,
30 	P_VIDEO_CC_PLL1_OUT_MAIN,
31 };
32 
33 static const struct pll_vco lucid_evo_vco[] = {
34 	{ 249600000, 2020000000, 0 },
35 };
36 
37 static 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 
48 static 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 
63 static 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 
81 static 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 
92 static 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 
107 static 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 
125 static const struct parent_map video_cc_parent_map_0[] = {
126 	{ P_BI_TCXO, 0 },
127 	{ P_VIDEO_CC_PLL0_OUT_MAIN, 1 },
128 };
129 
130 static const struct clk_parent_data video_cc_parent_data_0[] = {
131 	{ .index = DT_BI_TCXO },
132 	{ .hw = &video_cc_pll0.clkr.hw },
133 };
134 
135 static const struct parent_map video_cc_parent_map_1[] = {
136 	{ P_BI_TCXO, 0 },
137 	{ P_VIDEO_CC_PLL1_OUT_MAIN, 1 },
138 };
139 
140 static const struct clk_parent_data video_cc_parent_data_1[] = {
141 	{ .index = DT_BI_TCXO },
142 	{ .hw = &video_cc_pll1.clkr.hw },
143 };
144 
145 static 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 
154 static 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 
169 static 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 
178 static 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 
193 static 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 
208 static 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 
223 static 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 
238 static 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 
253 static 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 
273 static 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 
291 static 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 
311 static 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 
329 static 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 
341 static 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 
354 static 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 
366 static 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 
379 static 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 
394 static 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 
401 static 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 
411 static struct clk_alpha_pll *video_cc_sm8450_plls[] = {
412 	&video_cc_pll0,
413 	&video_cc_pll1,
414 };
415 
416 static 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 
422 static 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 
430 static 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 
437 static 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 
449 static const struct of_device_id video_cc_sm8450_match_table[] = {
450 	{ .compatible = "qcom,sm8450-videocc" },
451 	{ .compatible = "qcom,sm8475-videocc" },
452 	{ }
453 };
454 MODULE_DEVICE_TABLE(of, video_cc_sm8450_match_table);
455 
456 static 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 
472 static 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 
480 module_platform_driver(video_cc_sm8450_driver);
481 
482 MODULE_DESCRIPTION("QTI VIDEOCC SM8450 / SM8475 Driver");
483 MODULE_LICENSE("GPL");
484