1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
6 #include <linux/clk-provider.h>
7 #include <linux/module.h>
8 #include <linux/platform_device.h>
9 #include <linux/regmap.h>
11 #include <dt-bindings/clock/qcom,videocc-sm8250.h>
13 #include "clk-alpha-pll.h"
14 #include "clk-branch.h"
16 #include "clk-regmap.h"
17 #include "clk-regmap-divider.h"
25 P_CORE_BI_PLL_TEST_SE
,
26 P_VIDEO_PLL0_OUT_MAIN
,
27 P_VIDEO_PLL1_OUT_MAIN
,
30 static struct pll_vco lucid_vco
[] = {
31 { 249600000, 2000000000, 0 },
34 static const struct alpha_pll_config video_pll0_config
= {
37 .config_ctl_val
= 0x20485699,
38 .config_ctl_hi_val
= 0x00002261,
39 .config_ctl_hi1_val
= 0x329A699C,
40 .user_ctl_val
= 0x00000000,
41 .user_ctl_hi_val
= 0x00000805,
42 .user_ctl_hi1_val
= 0x00000000,
45 static struct clk_alpha_pll video_pll0
= {
47 .vco_table
= lucid_vco
,
48 .num_vco
= ARRAY_SIZE(lucid_vco
),
49 .regs
= clk_alpha_pll_regs
[CLK_ALPHA_PLL_TYPE_LUCID
],
51 .hw
.init
= &(struct clk_init_data
){
53 .parent_data
= &(const struct clk_parent_data
){
57 .ops
= &clk_alpha_pll_lucid_ops
,
62 static const struct alpha_pll_config video_pll1_config
= {
65 .config_ctl_val
= 0x20485699,
66 .config_ctl_hi_val
= 0x00002261,
67 .config_ctl_hi1_val
= 0x329A699C,
68 .user_ctl_val
= 0x00000000,
69 .user_ctl_hi_val
= 0x00000805,
70 .user_ctl_hi1_val
= 0x00000000,
73 static struct clk_alpha_pll video_pll1
= {
75 .vco_table
= lucid_vco
,
76 .num_vco
= ARRAY_SIZE(lucid_vco
),
77 .regs
= clk_alpha_pll_regs
[CLK_ALPHA_PLL_TYPE_LUCID
],
79 .hw
.init
= &(struct clk_init_data
){
81 .parent_data
= &(const struct clk_parent_data
){
85 .ops
= &clk_alpha_pll_lucid_ops
,
90 static const struct parent_map video_cc_parent_map_1
[] = {
92 { P_VIDEO_PLL0_OUT_MAIN
, 1 },
95 static const struct clk_parent_data video_cc_parent_data_1
[] = {
96 { .fw_name
= "bi_tcxo" },
97 { .hw
= &video_pll0
.clkr
.hw
},
100 static const struct parent_map video_cc_parent_map_2
[] = {
102 { P_VIDEO_PLL1_OUT_MAIN
, 1 },
105 static const struct clk_parent_data video_cc_parent_data_2
[] = {
106 { .fw_name
= "bi_tcxo" },
107 { .hw
= &video_pll1
.clkr
.hw
},
110 static const struct freq_tbl ftbl_video_cc_mvs0_clk_src
[] = {
111 F(19200000, P_BI_TCXO
, 1, 0, 0),
112 F(720000000, P_VIDEO_PLL0_OUT_MAIN
, 1, 0, 0),
113 F(1014000000, P_VIDEO_PLL0_OUT_MAIN
, 1, 0, 0),
114 F(1098000000, P_VIDEO_PLL0_OUT_MAIN
, 1, 0, 0),
115 F(1332000000, P_VIDEO_PLL0_OUT_MAIN
, 1, 0, 0),
119 static struct clk_rcg2 video_cc_mvs0_clk_src
= {
123 .parent_map
= video_cc_parent_map_1
,
124 .freq_tbl
= ftbl_video_cc_mvs0_clk_src
,
125 .clkr
.hw
.init
= &(struct clk_init_data
){
126 .name
= "video_cc_mvs0_clk_src",
127 .parent_data
= video_cc_parent_data_1
,
128 .num_parents
= ARRAY_SIZE(video_cc_parent_data_1
),
129 .flags
= CLK_SET_RATE_PARENT
,
130 .ops
= &clk_rcg2_shared_ops
,
134 static const struct freq_tbl ftbl_video_cc_mvs1_clk_src
[] = {
135 F(19200000, P_BI_TCXO
, 1, 0, 0),
136 F(840000000, P_VIDEO_PLL1_OUT_MAIN
, 1, 0, 0),
137 F(1098000000, P_VIDEO_PLL1_OUT_MAIN
, 1, 0, 0),
138 F(1332000000, P_VIDEO_PLL1_OUT_MAIN
, 1, 0, 0),
142 static struct clk_rcg2 video_cc_mvs1_clk_src
= {
146 .parent_map
= video_cc_parent_map_2
,
147 .freq_tbl
= ftbl_video_cc_mvs1_clk_src
,
148 .clkr
.hw
.init
= &(struct clk_init_data
){
149 .name
= "video_cc_mvs1_clk_src",
150 .parent_data
= video_cc_parent_data_2
,
151 .num_parents
= ARRAY_SIZE(video_cc_parent_data_2
),
152 .flags
= CLK_SET_RATE_PARENT
,
153 .ops
= &clk_rcg2_shared_ops
,
157 static struct clk_regmap_div video_cc_mvs0c_div2_div_clk_src
= {
161 .clkr
.hw
.init
= &(struct clk_init_data
) {
162 .name
= "video_cc_mvs0c_div2_div_clk_src",
163 .parent_data
= &(const struct clk_parent_data
){
164 .hw
= &video_cc_mvs0_clk_src
.clkr
.hw
,
167 .flags
= CLK_SET_RATE_PARENT
,
168 .ops
= &clk_regmap_div_ro_ops
,
172 static struct clk_regmap_div video_cc_mvs1c_div2_div_clk_src
= {
176 .clkr
.hw
.init
= &(struct clk_init_data
) {
177 .name
= "video_cc_mvs1c_div2_div_clk_src",
178 .parent_data
= &(const struct clk_parent_data
){
179 .hw
= &video_cc_mvs1_clk_src
.clkr
.hw
,
182 .flags
= CLK_SET_RATE_PARENT
,
183 .ops
= &clk_regmap_div_ro_ops
,
187 static struct clk_branch video_cc_mvs0c_clk
= {
189 .halt_check
= BRANCH_HALT
,
192 .enable_mask
= BIT(0),
193 .hw
.init
= &(struct clk_init_data
){
194 .name
= "video_cc_mvs0c_clk",
195 .parent_data
= &(const struct clk_parent_data
){
196 .hw
= &video_cc_mvs0c_div2_div_clk_src
.clkr
.hw
,
199 .flags
= CLK_SET_RATE_PARENT
,
200 .ops
= &clk_branch2_ops
,
205 static struct clk_branch video_cc_mvs1_div2_clk
= {
207 .halt_check
= BRANCH_HALT_VOTED
,
210 .enable_mask
= BIT(0),
211 .hw
.init
= &(struct clk_init_data
){
212 .name
= "video_cc_mvs1_div2_clk",
213 .parent_data
= &(const struct clk_parent_data
){
214 .hw
= &video_cc_mvs1c_div2_div_clk_src
.clkr
.hw
,
217 .flags
= CLK_SET_RATE_PARENT
,
218 .ops
= &clk_branch2_ops
,
223 static struct clk_branch video_cc_mvs1c_clk
= {
225 .halt_check
= BRANCH_HALT_VOTED
,
228 .enable_mask
= BIT(0),
229 .hw
.init
= &(struct clk_init_data
){
230 .name
= "video_cc_mvs1c_clk",
231 .parent_data
= &(const struct clk_parent_data
){
232 .hw
= &video_cc_mvs1c_div2_div_clk_src
.clkr
.hw
,
235 .flags
= CLK_SET_RATE_PARENT
,
236 .ops
= &clk_branch2_ops
,
241 static struct gdsc mvs0c_gdsc
= {
244 .name
= "mvs0c_gdsc",
247 .pwrsts
= PWRSTS_OFF_ON
,
250 static struct gdsc mvs1c_gdsc
= {
253 .name
= "mvs1c_gdsc",
256 .pwrsts
= PWRSTS_OFF_ON
,
259 static struct gdsc mvs0_gdsc
= {
265 .pwrsts
= PWRSTS_OFF_ON
,
268 static struct gdsc mvs1_gdsc
= {
274 .pwrsts
= PWRSTS_OFF_ON
,
277 static struct clk_regmap
*video_cc_sm8250_clocks
[] = {
278 [VIDEO_CC_MVS0_CLK_SRC
] = &video_cc_mvs0_clk_src
.clkr
,
279 [VIDEO_CC_MVS0C_CLK
] = &video_cc_mvs0c_clk
.clkr
,
280 [VIDEO_CC_MVS0C_DIV2_DIV_CLK_SRC
] = &video_cc_mvs0c_div2_div_clk_src
.clkr
,
281 [VIDEO_CC_MVS1_CLK_SRC
] = &video_cc_mvs1_clk_src
.clkr
,
282 [VIDEO_CC_MVS1_DIV2_CLK
] = &video_cc_mvs1_div2_clk
.clkr
,
283 [VIDEO_CC_MVS1C_CLK
] = &video_cc_mvs1c_clk
.clkr
,
284 [VIDEO_CC_MVS1C_DIV2_DIV_CLK_SRC
] = &video_cc_mvs1c_div2_div_clk_src
.clkr
,
285 [VIDEO_CC_PLL0
] = &video_pll0
.clkr
,
286 [VIDEO_CC_PLL1
] = &video_pll1
.clkr
,
289 static const struct qcom_reset_map video_cc_sm8250_resets
[] = {
290 [VIDEO_CC_CVP_INTERFACE_BCR
] = { 0xe54 },
291 [VIDEO_CC_CVP_MVS0_BCR
] = { 0xd14 },
292 [VIDEO_CC_MVS0C_CLK_ARES
] = { 0xc34, 2 },
293 [VIDEO_CC_CVP_MVS0C_BCR
] = { 0xbf4 },
294 [VIDEO_CC_CVP_MVS1_BCR
] = { 0xd94 },
295 [VIDEO_CC_MVS1C_CLK_ARES
] = { 0xcd4, 2 },
296 [VIDEO_CC_CVP_MVS1C_BCR
] = { 0xc94 },
299 static struct gdsc
*video_cc_sm8250_gdscs
[] = {
300 [MVS0C_GDSC
] = &mvs0c_gdsc
,
301 [MVS1C_GDSC
] = &mvs1c_gdsc
,
302 [MVS0_GDSC
] = &mvs0_gdsc
,
303 [MVS1_GDSC
] = &mvs1_gdsc
,
306 static const struct regmap_config video_cc_sm8250_regmap_config
= {
310 .max_register
= 0xf4c,
314 static const struct qcom_cc_desc video_cc_sm8250_desc
= {
315 .config
= &video_cc_sm8250_regmap_config
,
316 .clks
= video_cc_sm8250_clocks
,
317 .num_clks
= ARRAY_SIZE(video_cc_sm8250_clocks
),
318 .resets
= video_cc_sm8250_resets
,
319 .num_resets
= ARRAY_SIZE(video_cc_sm8250_resets
),
320 .gdscs
= video_cc_sm8250_gdscs
,
321 .num_gdscs
= ARRAY_SIZE(video_cc_sm8250_gdscs
),
324 static const struct of_device_id video_cc_sm8250_match_table
[] = {
325 { .compatible
= "qcom,sm8250-videocc" },
328 MODULE_DEVICE_TABLE(of
, video_cc_sm8250_match_table
);
330 static int video_cc_sm8250_probe(struct platform_device
*pdev
)
332 struct regmap
*regmap
;
334 regmap
= qcom_cc_map(pdev
, &video_cc_sm8250_desc
);
336 return PTR_ERR(regmap
);
338 clk_lucid_pll_configure(&video_pll0
, regmap
, &video_pll0_config
);
339 clk_lucid_pll_configure(&video_pll1
, regmap
, &video_pll1_config
);
341 /* Keep VIDEO_CC_AHB_CLK and VIDEO_CC_XO_CLK ALWAYS-ON */
342 regmap_update_bits(regmap
, 0xe58, BIT(0), BIT(0));
343 regmap_update_bits(regmap
, 0xeec, BIT(0), BIT(0));
345 return qcom_cc_really_probe(pdev
, &video_cc_sm8250_desc
, regmap
);
348 static struct platform_driver video_cc_sm8250_driver
= {
349 .probe
= video_cc_sm8250_probe
,
351 .name
= "sm8250-videocc",
352 .of_match_table
= video_cc_sm8250_match_table
,
356 static int __init
video_cc_sm8250_init(void)
358 return platform_driver_register(&video_cc_sm8250_driver
);
360 subsys_initcall(video_cc_sm8250_init
);
362 static void __exit
video_cc_sm8250_exit(void)
364 platform_driver_unregister(&video_cc_sm8250_driver
);
366 module_exit(video_cc_sm8250_exit
);
368 MODULE_LICENSE("GPL v2");
369 MODULE_DESCRIPTION("QTI VIDEOCC SM8250 Driver");