Merge tag 'trace-printf-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/trace...
[drm/drm-misc.git] / drivers / clk / qcom / videocc-sm8450.c
blobf26c7eccb62e7eb8dbd022e2f01fa496eb570b3f
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
4 */
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>
13 #include <dt-bindings/clock/qcom,sm8450-videocc.h>
15 #include "clk-alpha-pll.h"
16 #include "clk-branch.h"
17 #include "clk-rcg.h"
18 #include "clk-regmap.h"
19 #include "clk-regmap-divider.h"
20 #include "common.h"
21 #include "gdsc.h"
22 #include "reset.h"
24 enum {
25 DT_BI_TCXO,
28 enum {
29 P_BI_TCXO,
30 P_VIDEO_CC_PLL0_OUT_MAIN,
31 P_VIDEO_CC_PLL1_OUT_MAIN,
34 static const struct pll_vco lucid_evo_vco[] = {
35 { 249600000, 2020000000, 0 },
38 static const struct alpha_pll_config video_cc_pll0_config = {
39 /* .l includes CAL_L_VAL, L_VAL fields */
40 .l = 0x0044001e,
41 .alpha = 0x0,
42 .config_ctl_val = 0x20485699,
43 .config_ctl_hi_val = 0x00182261,
44 .config_ctl_hi1_val = 0x32aa299c,
45 .user_ctl_val = 0x00000000,
46 .user_ctl_hi_val = 0x00000805,
49 static const struct alpha_pll_config sm8475_video_cc_pll0_config = {
50 /* .l includes CAL_L_VAL, L_VAL fields */
51 .l = 0x1e,
52 .alpha = 0x0,
53 .config_ctl_val = 0x20485699,
54 .config_ctl_hi_val = 0x00182261,
55 .config_ctl_hi1_val = 0x82aa299c,
56 .test_ctl_val = 0x00000000,
57 .test_ctl_hi_val = 0x00000003,
58 .test_ctl_hi1_val = 0x00009000,
59 .test_ctl_hi2_val = 0x00000034,
60 .user_ctl_val = 0x00000000,
61 .user_ctl_hi_val = 0x00000005,
64 static struct clk_alpha_pll video_cc_pll0 = {
65 .offset = 0x0,
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,
75 .num_parents = 1,
76 .ops = &clk_alpha_pll_lucid_evo_ops,
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,
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,
107 static struct clk_alpha_pll video_cc_pll1 = {
108 .offset = 0x1000,
109 .vco_table = lucid_evo_vco,
110 .num_vco = ARRAY_SIZE(lucid_evo_vco),
111 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
112 .clkr = {
113 .hw.init = &(const struct clk_init_data) {
114 .name = "video_cc_pll1",
115 .parent_data = &(const struct clk_parent_data) {
116 .index = DT_BI_TCXO,
118 .num_parents = 1,
119 .ops = &clk_alpha_pll_lucid_evo_ops,
124 static const struct parent_map video_cc_parent_map_0[] = {
125 { P_BI_TCXO, 0 },
126 { P_VIDEO_CC_PLL0_OUT_MAIN, 1 },
129 static const struct clk_parent_data video_cc_parent_data_0[] = {
130 { .index = DT_BI_TCXO },
131 { .hw = &video_cc_pll0.clkr.hw },
134 static const struct parent_map video_cc_parent_map_1[] = {
135 { P_BI_TCXO, 0 },
136 { P_VIDEO_CC_PLL1_OUT_MAIN, 1 },
139 static const struct clk_parent_data video_cc_parent_data_1[] = {
140 { .index = DT_BI_TCXO },
141 { .hw = &video_cc_pll1.clkr.hw },
144 static const struct freq_tbl ftbl_video_cc_mvs0_clk_src[] = {
145 F(576000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
146 F(720000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
147 F(1014000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
148 F(1098000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
149 F(1332000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
153 static struct clk_rcg2 video_cc_mvs0_clk_src = {
154 .cmd_rcgr = 0x8000,
155 .mnd_width = 0,
156 .hid_width = 5,
157 .parent_map = video_cc_parent_map_0,
158 .freq_tbl = ftbl_video_cc_mvs0_clk_src,
159 .clkr.hw.init = &(const struct clk_init_data) {
160 .name = "video_cc_mvs0_clk_src",
161 .parent_data = video_cc_parent_data_0,
162 .num_parents = ARRAY_SIZE(video_cc_parent_data_0),
163 .flags = CLK_SET_RATE_PARENT,
164 .ops = &clk_rcg2_shared_ops,
168 static const struct freq_tbl ftbl_video_cc_mvs1_clk_src[] = {
169 F(840000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0),
170 F(1050000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0),
171 F(1350000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0),
172 F(1500000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0),
173 F(1650000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0),
177 static struct clk_rcg2 video_cc_mvs1_clk_src = {
178 .cmd_rcgr = 0x8018,
179 .mnd_width = 0,
180 .hid_width = 5,
181 .parent_map = video_cc_parent_map_1,
182 .freq_tbl = ftbl_video_cc_mvs1_clk_src,
183 .clkr.hw.init = &(const struct clk_init_data) {
184 .name = "video_cc_mvs1_clk_src",
185 .parent_data = video_cc_parent_data_1,
186 .num_parents = ARRAY_SIZE(video_cc_parent_data_1),
187 .flags = CLK_SET_RATE_PARENT,
188 .ops = &clk_rcg2_shared_ops,
192 static struct clk_regmap_div video_cc_mvs0_div_clk_src = {
193 .reg = 0x80b8,
194 .shift = 0,
195 .width = 4,
196 .clkr.hw.init = &(const struct clk_init_data) {
197 .name = "video_cc_mvs0_div_clk_src",
198 .parent_hws = (const struct clk_hw*[]) {
199 &video_cc_mvs0_clk_src.clkr.hw,
201 .num_parents = 1,
202 .flags = CLK_SET_RATE_PARENT,
203 .ops = &clk_regmap_div_ro_ops,
207 static struct clk_regmap_div video_cc_mvs0c_div2_div_clk_src = {
208 .reg = 0x806c,
209 .shift = 0,
210 .width = 4,
211 .clkr.hw.init = &(const struct clk_init_data) {
212 .name = "video_cc_mvs0c_div2_div_clk_src",
213 .parent_hws = (const struct clk_hw*[]) {
214 &video_cc_mvs0_clk_src.clkr.hw,
216 .num_parents = 1,
217 .flags = CLK_SET_RATE_PARENT,
218 .ops = &clk_regmap_div_ro_ops,
222 static struct clk_regmap_div video_cc_mvs1_div_clk_src = {
223 .reg = 0x80dc,
224 .shift = 0,
225 .width = 4,
226 .clkr.hw.init = &(const struct clk_init_data) {
227 .name = "video_cc_mvs1_div_clk_src",
228 .parent_hws = (const struct clk_hw*[]) {
229 &video_cc_mvs1_clk_src.clkr.hw,
231 .num_parents = 1,
232 .flags = CLK_SET_RATE_PARENT,
233 .ops = &clk_regmap_div_ro_ops,
237 static struct clk_regmap_div video_cc_mvs1c_div2_div_clk_src = {
238 .reg = 0x8094,
239 .shift = 0,
240 .width = 4,
241 .clkr.hw.init = &(const struct clk_init_data) {
242 .name = "video_cc_mvs1c_div2_div_clk_src",
243 .parent_hws = (const struct clk_hw*[]) {
244 &video_cc_mvs1_clk_src.clkr.hw,
246 .num_parents = 1,
247 .flags = CLK_SET_RATE_PARENT,
248 .ops = &clk_regmap_div_ro_ops,
252 static struct clk_branch video_cc_mvs0_clk = {
253 .halt_reg = 0x80b0,
254 .halt_check = BRANCH_HALT_SKIP,
255 .hwcg_reg = 0x80b0,
256 .hwcg_bit = 1,
257 .clkr = {
258 .enable_reg = 0x80b0,
259 .enable_mask = BIT(0),
260 .hw.init = &(const struct clk_init_data) {
261 .name = "video_cc_mvs0_clk",
262 .parent_hws = (const struct clk_hw*[]) {
263 &video_cc_mvs0_div_clk_src.clkr.hw,
265 .num_parents = 1,
266 .flags = CLK_SET_RATE_PARENT,
267 .ops = &clk_branch2_ops,
272 static struct clk_branch video_cc_mvs0c_clk = {
273 .halt_reg = 0x8064,
274 .halt_check = BRANCH_HALT,
275 .clkr = {
276 .enable_reg = 0x8064,
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,
283 .num_parents = 1,
284 .flags = CLK_SET_RATE_PARENT,
285 .ops = &clk_branch2_ops,
290 static struct clk_branch video_cc_mvs1_clk = {
291 .halt_reg = 0x80d4,
292 .halt_check = BRANCH_HALT_SKIP,
293 .hwcg_reg = 0x80d4,
294 .hwcg_bit = 1,
295 .clkr = {
296 .enable_reg = 0x80d4,
297 .enable_mask = BIT(0),
298 .hw.init = &(const struct clk_init_data) {
299 .name = "video_cc_mvs1_clk",
300 .parent_hws = (const struct clk_hw*[]) {
301 &video_cc_mvs1_div_clk_src.clkr.hw,
303 .num_parents = 1,
304 .flags = CLK_SET_RATE_PARENT,
305 .ops = &clk_branch2_ops,
310 static struct clk_branch video_cc_mvs1c_clk = {
311 .halt_reg = 0x808c,
312 .halt_check = BRANCH_HALT,
313 .clkr = {
314 .enable_reg = 0x808c,
315 .enable_mask = BIT(0),
316 .hw.init = &(const struct clk_init_data) {
317 .name = "video_cc_mvs1c_clk",
318 .parent_hws = (const struct clk_hw*[]) {
319 &video_cc_mvs1c_div2_div_clk_src.clkr.hw,
321 .num_parents = 1,
322 .flags = CLK_SET_RATE_PARENT,
323 .ops = &clk_branch2_ops,
328 static struct gdsc video_cc_mvs0c_gdsc = {
329 .gdscr = 0x804c,
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",
336 .pwrsts = PWRSTS_OFF_ON,
337 .flags = RETAIN_FF_ENABLE,
340 static struct gdsc video_cc_mvs0_gdsc = {
341 .gdscr = 0x809c,
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",
348 .pwrsts = PWRSTS_OFF_ON,
349 .parent = &video_cc_mvs0c_gdsc.pd,
350 .flags = RETAIN_FF_ENABLE | HW_CTRL,
353 static struct gdsc video_cc_mvs1c_gdsc = {
354 .gdscr = 0x8074,
355 .en_rest_wait_val = 0x2,
356 .en_few_wait_val = 0x2,
357 .clk_dis_wait_val = 0x6,
358 .pd = {
359 .name = "video_cc_mvs1c_gdsc",
361 .pwrsts = PWRSTS_OFF_ON,
362 .flags = RETAIN_FF_ENABLE,
365 static struct gdsc video_cc_mvs1_gdsc = {
366 .gdscr = 0x80c0,
367 .en_rest_wait_val = 0x2,
368 .en_few_wait_val = 0x2,
369 .clk_dis_wait_val = 0x6,
370 .pd = {
371 .name = "video_cc_mvs1_gdsc",
373 .pwrsts = PWRSTS_OFF_ON,
374 .parent = &video_cc_mvs1c_gdsc.pd,
375 .flags = RETAIN_FF_ENABLE | HW_CTRL,
378 static struct clk_regmap *video_cc_sm8450_clocks[] = {
379 [VIDEO_CC_MVS0_CLK] = &video_cc_mvs0_clk.clkr,
380 [VIDEO_CC_MVS0_CLK_SRC] = &video_cc_mvs0_clk_src.clkr,
381 [VIDEO_CC_MVS0_DIV_CLK_SRC] = &video_cc_mvs0_div_clk_src.clkr,
382 [VIDEO_CC_MVS0C_CLK] = &video_cc_mvs0c_clk.clkr,
383 [VIDEO_CC_MVS0C_DIV2_DIV_CLK_SRC] = &video_cc_mvs0c_div2_div_clk_src.clkr,
384 [VIDEO_CC_MVS1_CLK] = &video_cc_mvs1_clk.clkr,
385 [VIDEO_CC_MVS1_CLK_SRC] = &video_cc_mvs1_clk_src.clkr,
386 [VIDEO_CC_MVS1_DIV_CLK_SRC] = &video_cc_mvs1_div_clk_src.clkr,
387 [VIDEO_CC_MVS1C_CLK] = &video_cc_mvs1c_clk.clkr,
388 [VIDEO_CC_MVS1C_DIV2_DIV_CLK_SRC] = &video_cc_mvs1c_div2_div_clk_src.clkr,
389 [VIDEO_CC_PLL0] = &video_cc_pll0.clkr,
390 [VIDEO_CC_PLL1] = &video_cc_pll1.clkr,
393 static struct gdsc *video_cc_sm8450_gdscs[] = {
394 [VIDEO_CC_MVS0C_GDSC] = &video_cc_mvs0c_gdsc,
395 [VIDEO_CC_MVS0_GDSC] = &video_cc_mvs0_gdsc,
396 [VIDEO_CC_MVS1C_GDSC] = &video_cc_mvs1c_gdsc,
397 [VIDEO_CC_MVS1_GDSC] = &video_cc_mvs1_gdsc,
400 static const struct qcom_reset_map video_cc_sm8450_resets[] = {
401 [CVP_VIDEO_CC_INTERFACE_BCR] = { 0x80e0 },
402 [CVP_VIDEO_CC_MVS0_BCR] = { 0x8098 },
403 [CVP_VIDEO_CC_MVS0C_BCR] = { 0x8048 },
404 [CVP_VIDEO_CC_MVS1_BCR] = { 0x80bc },
405 [CVP_VIDEO_CC_MVS1C_BCR] = { 0x8070 },
406 [VIDEO_CC_MVS0C_CLK_ARES] = { .reg = 0x8064, .bit = 2, .udelay = 1000 },
407 [VIDEO_CC_MVS1C_CLK_ARES] = { .reg = 0x808c, .bit = 2, .udelay = 1000 },
410 static const struct regmap_config video_cc_sm8450_regmap_config = {
411 .reg_bits = 32,
412 .reg_stride = 4,
413 .val_bits = 32,
414 .max_register = 0x9f4c,
415 .fast_io = true,
418 static struct qcom_cc_desc video_cc_sm8450_desc = {
419 .config = &video_cc_sm8450_regmap_config,
420 .clks = video_cc_sm8450_clocks,
421 .num_clks = ARRAY_SIZE(video_cc_sm8450_clocks),
422 .resets = video_cc_sm8450_resets,
423 .num_resets = ARRAY_SIZE(video_cc_sm8450_resets),
424 .gdscs = video_cc_sm8450_gdscs,
425 .num_gdscs = ARRAY_SIZE(video_cc_sm8450_gdscs),
428 static const struct of_device_id video_cc_sm8450_match_table[] = {
429 { .compatible = "qcom,sm8450-videocc" },
430 { .compatible = "qcom,sm8475-videocc" },
433 MODULE_DEVICE_TABLE(of, video_cc_sm8450_match_table);
435 static int video_cc_sm8450_probe(struct platform_device *pdev)
437 struct regmap *regmap;
438 int ret;
440 ret = devm_pm_runtime_enable(&pdev->dev);
441 if (ret)
442 return ret;
444 ret = pm_runtime_resume_and_get(&pdev->dev);
445 if (ret)
446 return ret;
448 regmap = qcom_cc_map(pdev, &video_cc_sm8450_desc);
449 if (IS_ERR(regmap)) {
450 pm_runtime_put(&pdev->dev);
451 return PTR_ERR(regmap);
454 if (of_device_is_compatible(pdev->dev.of_node, "qcom,sm8475-videocc")) {
455 /* Update VideoCC PLL0 */
456 video_cc_pll0.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
458 /* Update VideoCC PLL1 */
459 video_cc_pll1.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
461 clk_lucid_ole_pll_configure(&video_cc_pll0, regmap, &sm8475_video_cc_pll0_config);
462 clk_lucid_ole_pll_configure(&video_cc_pll1, regmap, &sm8475_video_cc_pll1_config);
463 } else {
464 clk_lucid_evo_pll_configure(&video_cc_pll0, regmap, &video_cc_pll0_config);
465 clk_lucid_evo_pll_configure(&video_cc_pll1, regmap, &video_cc_pll1_config);
468 /* Keep some clocks always-on */
469 qcom_branch_set_clk_en(regmap, 0x80e4); /* VIDEO_CC_AHB_CLK */
470 qcom_branch_set_clk_en(regmap, 0x8130); /* VIDEO_CC_SLEEP_CLK */
471 qcom_branch_set_clk_en(regmap, 0x8114); /* VIDEO_CC_XO_CLK */
473 ret = qcom_cc_really_probe(&pdev->dev, &video_cc_sm8450_desc, regmap);
475 pm_runtime_put(&pdev->dev);
477 return ret;
480 static struct platform_driver video_cc_sm8450_driver = {
481 .probe = video_cc_sm8450_probe,
482 .driver = {
483 .name = "video_cc-sm8450",
484 .of_match_table = video_cc_sm8450_match_table,
488 module_platform_driver(video_cc_sm8450_driver);
490 MODULE_DESCRIPTION("QTI VIDEOCC SM8450 / SM8475 Driver");
491 MODULE_LICENSE("GPL");