xref: /linux/drivers/clk/qcom/videocc-glymur.c (revision 0fc8f6200d2313278fbf4539bbab74677c685531)
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/regmap.h>
11 
12 #include <dt-bindings/clock/qcom,glymur-videocc.h>
13 
14 #include "clk-alpha-pll.h"
15 #include "clk-branch.h"
16 #include "clk-pll.h"
17 #include "clk-rcg.h"
18 #include "clk-regmap.h"
19 #include "clk-regmap-divider.h"
20 #include "clk-regmap-mux.h"
21 #include "common.h"
22 #include "gdsc.h"
23 #include "reset.h"
24 
25 enum {
26 	DT_BI_TCXO,
27 	DT_BI_TCXO_AO,
28 	DT_SLEEP_CLK,
29 };
30 
31 enum {
32 	P_BI_TCXO,
33 	P_SLEEP_CLK,
34 	P_VIDEO_CC_PLL0_OUT_MAIN,
35 };
36 
37 static const struct pll_vco taycan_eko_t_vco[] = {
38 	{ 249600000, 2500000000, 0 },
39 };
40 
41 /* 720.0 MHz Configuration */
42 static const struct alpha_pll_config video_cc_pll0_config = {
43 	.l = 0x25,
44 	.alpha = 0x8000,
45 	.config_ctl_val = 0x25c400e7,
46 	.config_ctl_hi_val = 0x0a8060e0,
47 	.config_ctl_hi1_val = 0xf51dea20,
48 	.user_ctl_val = 0x00000008,
49 	.user_ctl_hi_val = 0x00000002,
50 };
51 
52 static struct clk_alpha_pll video_cc_pll0 = {
53 	.offset = 0x0,
54 	.config = &video_cc_pll0_config,
55 	.vco_table = taycan_eko_t_vco,
56 	.num_vco = ARRAY_SIZE(taycan_eko_t_vco),
57 	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_EKO_T],
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_eko_t_ops,
66 		},
67 	},
68 };
69 
70 static const struct parent_map video_cc_parent_map_0[] = {
71 	{ P_BI_TCXO, 0 },
72 };
73 
74 static const struct clk_parent_data video_cc_parent_data_0[] = {
75 	{ .index = DT_BI_TCXO },
76 };
77 
78 static const struct parent_map video_cc_parent_map_1[] = {
79 	{ P_BI_TCXO, 0 },
80 	{ P_VIDEO_CC_PLL0_OUT_MAIN, 1 },
81 };
82 
83 static const struct clk_parent_data video_cc_parent_data_1[] = {
84 	{ .index = DT_BI_TCXO },
85 	{ .hw = &video_cc_pll0.clkr.hw },
86 };
87 
88 static const struct parent_map video_cc_parent_map_2[] = {
89 	{ P_SLEEP_CLK, 0 },
90 };
91 
92 static const struct clk_parent_data video_cc_parent_data_2[] = {
93 	{ .index = DT_SLEEP_CLK },
94 };
95 
96 static const struct freq_tbl ftbl_video_cc_ahb_clk_src[] = {
97 	F(19200000, P_BI_TCXO, 1, 0, 0),
98 	{ }
99 };
100 
101 static 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,
110 		.num_parents = ARRAY_SIZE(video_cc_parent_data_0),
111 		.flags = CLK_SET_RATE_PARENT,
112 		.ops = &clk_rcg2_shared_ops,
113 	},
114 };
115 
116 static 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(1098000000, 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(1965000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
123 	{ }
124 };
125 
126 static struct clk_rcg2 video_cc_mvs0_clk_src = {
127 	.cmd_rcgr = 0x8000,
128 	.mnd_width = 0,
129 	.hid_width = 5,
130 	.parent_map = video_cc_parent_map_1,
131 	.freq_tbl = ftbl_video_cc_mvs0_clk_src,
132 	.clkr.hw.init = &(const struct clk_init_data) {
133 		.name = "video_cc_mvs0_clk_src",
134 		.parent_data = video_cc_parent_data_1,
135 		.num_parents = ARRAY_SIZE(video_cc_parent_data_1),
136 		.flags = CLK_SET_RATE_PARENT,
137 		.ops = &clk_rcg2_shared_ops,
138 	},
139 };
140 
141 static const struct freq_tbl ftbl_video_cc_sleep_clk_src[] = {
142 	F(32000, P_SLEEP_CLK, 1, 0, 0),
143 	{ }
144 };
145 
146 static struct clk_rcg2 video_cc_sleep_clk_src = {
147 	.cmd_rcgr = 0x8120,
148 	.mnd_width = 0,
149 	.hid_width = 5,
150 	.parent_map = video_cc_parent_map_2,
151 	.freq_tbl = ftbl_video_cc_sleep_clk_src,
152 	.clkr.hw.init = &(const struct clk_init_data) {
153 		.name = "video_cc_sleep_clk_src",
154 		.parent_data = video_cc_parent_data_2,
155 		.num_parents = ARRAY_SIZE(video_cc_parent_data_2),
156 		.flags = CLK_SET_RATE_PARENT,
157 		.ops = &clk_rcg2_shared_ops,
158 	},
159 };
160 
161 static struct clk_rcg2 video_cc_xo_clk_src = {
162 	.cmd_rcgr = 0x80f8,
163 	.mnd_width = 0,
164 	.hid_width = 5,
165 	.parent_map = video_cc_parent_map_0,
166 	.freq_tbl = ftbl_video_cc_ahb_clk_src,
167 	.clkr.hw.init = &(const struct clk_init_data) {
168 		.name = "video_cc_xo_clk_src",
169 		.parent_data = video_cc_parent_data_0,
170 		.num_parents = ARRAY_SIZE(video_cc_parent_data_0),
171 		.flags = CLK_SET_RATE_PARENT,
172 		.ops = &clk_rcg2_shared_ops,
173 	},
174 };
175 
176 static struct clk_regmap_div video_cc_mvs0_div_clk_src = {
177 	.reg = 0x809c,
178 	.shift = 0,
179 	.width = 4,
180 	.clkr.hw.init = &(const struct clk_init_data) {
181 		.name = "video_cc_mvs0_div_clk_src",
182 		.parent_hws = (const struct clk_hw*[]) {
183 			&video_cc_mvs0_clk_src.clkr.hw,
184 		},
185 		.num_parents = 1,
186 		.flags = CLK_SET_RATE_PARENT,
187 		.ops = &clk_regmap_div_ro_ops,
188 	},
189 };
190 
191 static struct clk_regmap_div video_cc_mvs0c_div2_div_clk_src = {
192 	.reg = 0x8060,
193 	.shift = 0,
194 	.width = 4,
195 	.clkr.hw.init = &(const struct clk_init_data) {
196 		.name = "video_cc_mvs0c_div2_div_clk_src",
197 		.parent_hws = (const struct clk_hw*[]) {
198 			&video_cc_mvs0_clk_src.clkr.hw,
199 		},
200 		.num_parents = 1,
201 		.flags = CLK_SET_RATE_PARENT,
202 		.ops = &clk_regmap_div_ro_ops,
203 	},
204 };
205 
206 static struct clk_regmap_div video_cc_mvs1_div_clk_src = {
207 	.reg = 0x80d8,
208 	.shift = 0,
209 	.width = 4,
210 	.clkr.hw.init = &(const struct clk_init_data) {
211 		.name = "video_cc_mvs1_div_clk_src",
212 		.parent_hws = (const struct clk_hw*[]) {
213 			&video_cc_mvs0_clk_src.clkr.hw,
214 		},
215 		.num_parents = 1,
216 		.flags = CLK_SET_RATE_PARENT,
217 		.ops = &clk_regmap_div_ro_ops,
218 	},
219 };
220 
221 static struct clk_branch video_cc_mvs0_clk = {
222 	.halt_reg = 0x807c,
223 	.halt_check = BRANCH_HALT_VOTED,
224 	.hwcg_reg = 0x807c,
225 	.hwcg_bit = 1,
226 	.clkr = {
227 		.enable_reg = 0x807c,
228 		.enable_mask = BIT(0),
229 		.hw.init = &(const struct clk_init_data) {
230 			.name = "video_cc_mvs0_clk",
231 			.parent_hws = (const struct clk_hw*[]) {
232 				&video_cc_mvs0_div_clk_src.clkr.hw,
233 			},
234 			.num_parents = 1,
235 			.flags = CLK_SET_RATE_PARENT,
236 			.ops = &clk_branch2_ops,
237 		},
238 	},
239 };
240 
241 static struct clk_branch video_cc_mvs0_freerun_clk = {
242 	.halt_reg = 0x808c,
243 	.halt_check = BRANCH_HALT,
244 	.clkr = {
245 		.enable_reg = 0x808c,
246 		.enable_mask = BIT(0),
247 		.hw.init = &(const struct clk_init_data) {
248 			.name = "video_cc_mvs0_freerun_clk",
249 			.parent_hws = (const struct clk_hw*[]) {
250 				&video_cc_mvs0_div_clk_src.clkr.hw,
251 			},
252 			.num_parents = 1,
253 			.flags = CLK_SET_RATE_PARENT,
254 			.ops = &clk_branch2_ops,
255 		},
256 	},
257 };
258 
259 static struct clk_branch video_cc_mvs0_shift_clk = {
260 	.halt_reg = 0x8114,
261 	.halt_check = BRANCH_HALT_VOTED,
262 	.hwcg_reg = 0x8114,
263 	.hwcg_bit = 1,
264 	.clkr = {
265 		.enable_reg = 0x8114,
266 		.enable_mask = BIT(0),
267 		.hw.init = &(const struct clk_init_data) {
268 			.name = "video_cc_mvs0_shift_clk",
269 			.parent_hws = (const struct clk_hw*[]) {
270 				&video_cc_xo_clk_src.clkr.hw,
271 			},
272 			.num_parents = 1,
273 			.flags = CLK_SET_RATE_PARENT,
274 			.ops = &clk_branch2_ops,
275 		},
276 	},
277 };
278 
279 static struct clk_branch video_cc_mvs0c_clk = {
280 	.halt_reg = 0x804c,
281 	.halt_check = BRANCH_HALT,
282 	.clkr = {
283 		.enable_reg = 0x804c,
284 		.enable_mask = BIT(0),
285 		.hw.init = &(const struct clk_init_data) {
286 			.name = "video_cc_mvs0c_clk",
287 			.parent_hws = (const struct clk_hw*[]) {
288 				&video_cc_mvs0c_div2_div_clk_src.clkr.hw,
289 			},
290 			.num_parents = 1,
291 			.flags = CLK_SET_RATE_PARENT,
292 			.ops = &clk_branch2_ops,
293 		},
294 	},
295 };
296 
297 static struct clk_branch video_cc_mvs0c_freerun_clk = {
298 	.halt_reg = 0x805c,
299 	.halt_check = BRANCH_HALT,
300 	.clkr = {
301 		.enable_reg = 0x805c,
302 		.enable_mask = BIT(0),
303 		.hw.init = &(const struct clk_init_data) {
304 			.name = "video_cc_mvs0c_freerun_clk",
305 			.parent_hws = (const struct clk_hw*[]) {
306 				&video_cc_mvs0c_div2_div_clk_src.clkr.hw,
307 			},
308 			.num_parents = 1,
309 			.flags = CLK_SET_RATE_PARENT,
310 			.ops = &clk_branch2_ops,
311 		},
312 	},
313 };
314 
315 static struct clk_branch video_cc_mvs0c_shift_clk = {
316 	.halt_reg = 0x811c,
317 	.halt_check = BRANCH_HALT_VOTED,
318 	.hwcg_reg = 0x811c,
319 	.hwcg_bit = 1,
320 	.clkr = {
321 		.enable_reg = 0x811c,
322 		.enable_mask = BIT(0),
323 		.hw.init = &(const struct clk_init_data) {
324 			.name = "video_cc_mvs0c_shift_clk",
325 			.parent_hws = (const struct clk_hw*[]) {
326 				&video_cc_xo_clk_src.clkr.hw,
327 			},
328 			.num_parents = 1,
329 			.flags = CLK_SET_RATE_PARENT,
330 			.ops = &clk_branch2_ops,
331 		},
332 	},
333 };
334 
335 static struct clk_branch video_cc_mvs1_clk = {
336 	.halt_reg = 0x80b8,
337 	.halt_check = BRANCH_HALT_VOTED,
338 	.hwcg_reg = 0x80b8,
339 	.hwcg_bit = 1,
340 	.clkr = {
341 		.enable_reg = 0x80b8,
342 		.enable_mask = BIT(0),
343 		.hw.init = &(const struct clk_init_data) {
344 			.name = "video_cc_mvs1_clk",
345 			.parent_hws = (const struct clk_hw*[]) {
346 				&video_cc_mvs1_div_clk_src.clkr.hw,
347 			},
348 			.num_parents = 1,
349 			.flags = CLK_SET_RATE_PARENT,
350 			.ops = &clk_branch2_ops,
351 		},
352 	},
353 };
354 
355 static struct clk_branch video_cc_mvs1_freerun_clk = {
356 	.halt_reg = 0x80c8,
357 	.halt_check = BRANCH_HALT,
358 	.clkr = {
359 		.enable_reg = 0x80c8,
360 		.enable_mask = BIT(0),
361 		.hw.init = &(const struct clk_init_data) {
362 			.name = "video_cc_mvs1_freerun_clk",
363 			.parent_hws = (const struct clk_hw*[]) {
364 				&video_cc_mvs1_div_clk_src.clkr.hw,
365 			},
366 			.num_parents = 1,
367 			.flags = CLK_SET_RATE_PARENT,
368 			.ops = &clk_branch2_ops,
369 		},
370 	},
371 };
372 
373 static struct clk_branch video_cc_mvs1_shift_clk = {
374 	.halt_reg = 0x8118,
375 	.halt_check = BRANCH_HALT_VOTED,
376 	.hwcg_reg = 0x8118,
377 	.hwcg_bit = 1,
378 	.clkr = {
379 		.enable_reg = 0x8118,
380 		.enable_mask = BIT(0),
381 		.hw.init = &(const struct clk_init_data) {
382 			.name = "video_cc_mvs1_shift_clk",
383 			.parent_hws = (const struct clk_hw*[]) {
384 				&video_cc_xo_clk_src.clkr.hw,
385 			},
386 			.num_parents = 1,
387 			.flags = CLK_SET_RATE_PARENT,
388 			.ops = &clk_branch2_ops,
389 		},
390 	},
391 };
392 
393 static struct gdsc video_cc_mvs0c_gdsc = {
394 	.gdscr = 0x8034,
395 	.en_rest_wait_val = 0x2,
396 	.en_few_wait_val = 0x2,
397 	.clk_dis_wait_val = 0x6,
398 	.pd = {
399 		.name = "video_cc_mvs0c_gdsc",
400 	},
401 	.pwrsts = PWRSTS_OFF_ON,
402 	.flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
403 };
404 
405 static struct gdsc video_cc_mvs0_gdsc = {
406 	.gdscr = 0x8068,
407 	.en_rest_wait_val = 0x2,
408 	.en_few_wait_val = 0x2,
409 	.clk_dis_wait_val = 0x6,
410 	.pd = {
411 		.name = "video_cc_mvs0_gdsc",
412 	},
413 	.pwrsts = PWRSTS_OFF_ON,
414 	.flags = HW_CTRL_TRIGGER | POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
415 	.parent = &video_cc_mvs0c_gdsc.pd,
416 };
417 
418 static struct gdsc video_cc_mvs1_gdsc = {
419 	.gdscr = 0x80a4,
420 	.en_rest_wait_val = 0x2,
421 	.en_few_wait_val = 0x2,
422 	.clk_dis_wait_val = 0x6,
423 	.pd = {
424 		.name = "video_cc_mvs1_gdsc",
425 	},
426 	.pwrsts = PWRSTS_OFF_ON,
427 	.flags = HW_CTRL_TRIGGER | POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
428 };
429 
430 static struct clk_regmap *video_cc_glymur_clocks[] = {
431 	[VIDEO_CC_AHB_CLK_SRC] = &video_cc_ahb_clk_src.clkr,
432 	[VIDEO_CC_MVS0_CLK] = &video_cc_mvs0_clk.clkr,
433 	[VIDEO_CC_MVS0_CLK_SRC] = &video_cc_mvs0_clk_src.clkr,
434 	[VIDEO_CC_MVS0_DIV_CLK_SRC] = &video_cc_mvs0_div_clk_src.clkr,
435 	[VIDEO_CC_MVS0_FREERUN_CLK] = &video_cc_mvs0_freerun_clk.clkr,
436 	[VIDEO_CC_MVS0_SHIFT_CLK] = &video_cc_mvs0_shift_clk.clkr,
437 	[VIDEO_CC_MVS0C_CLK] = &video_cc_mvs0c_clk.clkr,
438 	[VIDEO_CC_MVS0C_DIV2_DIV_CLK_SRC] = &video_cc_mvs0c_div2_div_clk_src.clkr,
439 	[VIDEO_CC_MVS0C_FREERUN_CLK] = &video_cc_mvs0c_freerun_clk.clkr,
440 	[VIDEO_CC_MVS0C_SHIFT_CLK] = &video_cc_mvs0c_shift_clk.clkr,
441 	[VIDEO_CC_MVS1_CLK] = &video_cc_mvs1_clk.clkr,
442 	[VIDEO_CC_MVS1_DIV_CLK_SRC] = &video_cc_mvs1_div_clk_src.clkr,
443 	[VIDEO_CC_MVS1_FREERUN_CLK] = &video_cc_mvs1_freerun_clk.clkr,
444 	[VIDEO_CC_MVS1_SHIFT_CLK] = &video_cc_mvs1_shift_clk.clkr,
445 	[VIDEO_CC_PLL0] = &video_cc_pll0.clkr,
446 	[VIDEO_CC_SLEEP_CLK_SRC] = &video_cc_sleep_clk_src.clkr,
447 	[VIDEO_CC_XO_CLK_SRC] = &video_cc_xo_clk_src.clkr,
448 };
449 
450 static struct gdsc *video_cc_glymur_gdscs[] = {
451 	[VIDEO_CC_MVS0_GDSC] = &video_cc_mvs0_gdsc,
452 	[VIDEO_CC_MVS0C_GDSC] = &video_cc_mvs0c_gdsc,
453 	[VIDEO_CC_MVS1_GDSC] = &video_cc_mvs1_gdsc,
454 };
455 
456 static const struct qcom_reset_map video_cc_glymur_resets[] = {
457 	[VIDEO_CC_INTERFACE_BCR] = { 0x80dc },
458 	[VIDEO_CC_MVS0_BCR] = { 0x8064 },
459 	[VIDEO_CC_MVS0C_FREERUN_CLK_ARES] = { 0x805c, 2 },
460 	[VIDEO_CC_MVS0C_BCR] = { 0x8030 },
461 	[VIDEO_CC_MVS0_FREERUN_CLK_ARES] = { 0x808c, 2 },
462 	[VIDEO_CC_MVS1_FREERUN_CLK_ARES] = { 0x80c8, 2 },
463 	[VIDEO_CC_MVS1_BCR] = { 0x80a0 },
464 };
465 
466 static struct clk_alpha_pll *video_cc_glymur_plls[] = {
467 	&video_cc_pll0,
468 };
469 
470 static const u32 video_cc_glymur_critical_cbcrs[] = {
471 	0x80e0, /* VIDEO_CC_AHB_CLK */
472 	0x8138, /* VIDEO_CC_SLEEP_CLK */
473 	0x8110, /* VIDEO_CC_XO_CLK */
474 };
475 
476 static const struct regmap_config video_cc_glymur_regmap_config = {
477 	.reg_bits = 32,
478 	.reg_stride = 4,
479 	.val_bits = 32,
480 	.max_register = 0x9f54,
481 	.fast_io = true,
482 };
483 
484 static void clk_glymur_regs_configure(struct device *dev, struct regmap *regmap)
485 {
486 	/* Update CTRL_IN register */
487 	regmap_update_bits(regmap, 0x9f24, BIT(0), BIT(0));
488 }
489 
490 static const struct qcom_cc_driver_data video_cc_glymur_driver_data = {
491 	.alpha_plls = video_cc_glymur_plls,
492 	.num_alpha_plls = ARRAY_SIZE(video_cc_glymur_plls),
493 	.clk_cbcrs = video_cc_glymur_critical_cbcrs,
494 	.num_clk_cbcrs = ARRAY_SIZE(video_cc_glymur_critical_cbcrs),
495 	.clk_regs_configure = clk_glymur_regs_configure,
496 };
497 
498 static const struct qcom_cc_desc video_cc_glymur_desc = {
499 	.config = &video_cc_glymur_regmap_config,
500 	.clks = video_cc_glymur_clocks,
501 	.num_clks = ARRAY_SIZE(video_cc_glymur_clocks),
502 	.resets = video_cc_glymur_resets,
503 	.num_resets = ARRAY_SIZE(video_cc_glymur_resets),
504 	.gdscs = video_cc_glymur_gdscs,
505 	.num_gdscs = ARRAY_SIZE(video_cc_glymur_gdscs),
506 	.use_rpm = true,
507 	.driver_data = &video_cc_glymur_driver_data,
508 };
509 
510 static const struct of_device_id video_cc_glymur_match_table[] = {
511 	{ .compatible = "qcom,glymur-videocc" },
512 	{ }
513 };
514 MODULE_DEVICE_TABLE(of, video_cc_glymur_match_table);
515 
516 static int video_cc_glymur_probe(struct platform_device *pdev)
517 {
518 	return qcom_cc_probe(pdev, &video_cc_glymur_desc);
519 }
520 
521 static struct platform_driver video_cc_glymur_driver = {
522 	.probe = video_cc_glymur_probe,
523 	.driver = {
524 		.name = "videocc-glymur",
525 		.of_match_table = video_cc_glymur_match_table,
526 	},
527 };
528 
529 module_platform_driver(video_cc_glymur_driver);
530 
531 MODULE_DESCRIPTION("QTI VIDEOCC Glymur Driver");
532 MODULE_LICENSE("GPL");
533