1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2019, 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-sc7180.h>
13 #include "clk-alpha-pll.h"
14 #include "clk-branch.h"
16 #include "clk-regmap.h"
23 P_CORE_BI_PLL_TEST_SE
,
24 P_VIDEO_PLL0_OUT_EVEN
,
25 P_VIDEO_PLL0_OUT_MAIN
,
29 static const struct pll_vco fabia_vco
[] = {
30 { 249600000, 2000000000, 0 },
33 static struct clk_alpha_pll video_pll0
= {
35 .vco_table
= fabia_vco
,
36 .num_vco
= ARRAY_SIZE(fabia_vco
),
37 .regs
= clk_alpha_pll_regs
[CLK_ALPHA_PLL_TYPE_FABIA
],
39 .hw
.init
= &(struct clk_init_data
){
41 .parent_data
= &(const struct clk_parent_data
){
45 .ops
= &clk_alpha_pll_fabia_ops
,
50 static const struct parent_map video_cc_parent_map_1
[] = {
52 { P_VIDEO_PLL0_OUT_MAIN
, 1 },
55 static const struct clk_parent_data video_cc_parent_data_1
[] = {
56 { .fw_name
= "bi_tcxo" },
57 { .hw
= &video_pll0
.clkr
.hw
},
60 static const struct freq_tbl ftbl_video_cc_venus_clk_src
[] = {
61 F(19200000, P_BI_TCXO
, 1, 0, 0),
62 F(150000000, P_VIDEO_PLL0_OUT_MAIN
, 4, 0, 0),
63 F(270000000, P_VIDEO_PLL0_OUT_MAIN
, 2.5, 0, 0),
64 F(340000000, P_VIDEO_PLL0_OUT_MAIN
, 2, 0, 0),
65 F(434000000, P_VIDEO_PLL0_OUT_MAIN
, 2, 0, 0),
66 F(500000000, P_VIDEO_PLL0_OUT_MAIN
, 2, 0, 0),
70 static struct clk_rcg2 video_cc_venus_clk_src
= {
74 .parent_map
= video_cc_parent_map_1
,
75 .freq_tbl
= ftbl_video_cc_venus_clk_src
,
76 .clkr
.hw
.init
= &(struct clk_init_data
){
77 .name
= "video_cc_venus_clk_src",
78 .parent_data
= video_cc_parent_data_1
,
79 .num_parents
= ARRAY_SIZE(video_cc_parent_data_1
),
80 .flags
= CLK_SET_RATE_PARENT
,
81 .ops
= &clk_rcg2_shared_ops
,
85 static struct clk_branch video_cc_vcodec0_axi_clk
= {
87 .halt_check
= BRANCH_HALT
,
90 .enable_mask
= BIT(0),
91 .hw
.init
= &(struct clk_init_data
){
92 .name
= "video_cc_vcodec0_axi_clk",
93 .ops
= &clk_branch2_ops
,
98 static struct clk_branch video_cc_vcodec0_core_clk
= {
100 .halt_check
= BRANCH_HALT_VOTED
,
103 .enable_mask
= BIT(0),
104 .hw
.init
= &(struct clk_init_data
){
105 .name
= "video_cc_vcodec0_core_clk",
106 .parent_data
= &(const struct clk_parent_data
){
107 .hw
= &video_cc_venus_clk_src
.clkr
.hw
,
110 .flags
= CLK_SET_RATE_PARENT
,
111 .ops
= &clk_branch2_ops
,
116 static struct clk_branch video_cc_venus_ahb_clk
= {
118 .halt_check
= BRANCH_HALT
,
121 .enable_mask
= BIT(0),
122 .hw
.init
= &(struct clk_init_data
){
123 .name
= "video_cc_venus_ahb_clk",
124 .ops
= &clk_branch2_ops
,
129 static struct clk_branch video_cc_venus_ctl_axi_clk
= {
131 .halt_check
= BRANCH_HALT
,
134 .enable_mask
= BIT(0),
135 .hw
.init
= &(struct clk_init_data
){
136 .name
= "video_cc_venus_ctl_axi_clk",
137 .ops
= &clk_branch2_ops
,
142 static struct clk_branch video_cc_venus_ctl_core_clk
= {
144 .halt_check
= BRANCH_HALT
,
147 .enable_mask
= BIT(0),
148 .hw
.init
= &(struct clk_init_data
){
149 .name
= "video_cc_venus_ctl_core_clk",
150 .parent_data
= &(const struct clk_parent_data
){
151 .hw
= &video_cc_venus_clk_src
.clkr
.hw
,
154 .flags
= CLK_SET_RATE_PARENT
,
155 .ops
= &clk_branch2_ops
,
160 static struct gdsc venus_gdsc
= {
163 .name
= "venus_gdsc",
165 .pwrsts
= PWRSTS_OFF_ON
,
168 static struct gdsc vcodec0_gdsc
= {
171 .name
= "vcodec0_gdsc",
174 .pwrsts
= PWRSTS_OFF_ON
,
177 static struct clk_regmap
*video_cc_sc7180_clocks
[] = {
178 [VIDEO_CC_VCODEC0_AXI_CLK
] = &video_cc_vcodec0_axi_clk
.clkr
,
179 [VIDEO_CC_VCODEC0_CORE_CLK
] = &video_cc_vcodec0_core_clk
.clkr
,
180 [VIDEO_CC_VENUS_AHB_CLK
] = &video_cc_venus_ahb_clk
.clkr
,
181 [VIDEO_CC_VENUS_CLK_SRC
] = &video_cc_venus_clk_src
.clkr
,
182 [VIDEO_CC_VENUS_CTL_AXI_CLK
] = &video_cc_venus_ctl_axi_clk
.clkr
,
183 [VIDEO_CC_VENUS_CTL_CORE_CLK
] = &video_cc_venus_ctl_core_clk
.clkr
,
184 [VIDEO_PLL0
] = &video_pll0
.clkr
,
187 static struct gdsc
*video_cc_sc7180_gdscs
[] = {
188 [VENUS_GDSC
] = &venus_gdsc
,
189 [VCODEC0_GDSC
] = &vcodec0_gdsc
,
192 static const struct regmap_config video_cc_sc7180_regmap_config
= {
196 .max_register
= 0xb94,
200 static const struct qcom_cc_desc video_cc_sc7180_desc
= {
201 .config
= &video_cc_sc7180_regmap_config
,
202 .clks
= video_cc_sc7180_clocks
,
203 .num_clks
= ARRAY_SIZE(video_cc_sc7180_clocks
),
204 .gdscs
= video_cc_sc7180_gdscs
,
205 .num_gdscs
= ARRAY_SIZE(video_cc_sc7180_gdscs
),
208 static const struct of_device_id video_cc_sc7180_match_table
[] = {
209 { .compatible
= "qcom,sc7180-videocc" },
212 MODULE_DEVICE_TABLE(of
, video_cc_sc7180_match_table
);
214 static int video_cc_sc7180_probe(struct platform_device
*pdev
)
216 struct regmap
*regmap
;
217 struct alpha_pll_config video_pll0_config
= {};
219 regmap
= qcom_cc_map(pdev
, &video_cc_sc7180_desc
);
221 return PTR_ERR(regmap
);
223 video_pll0_config
.l
= 0x1f;
224 video_pll0_config
.alpha
= 0x4000;
225 video_pll0_config
.user_ctl_val
= 0x00000001;
226 video_pll0_config
.user_ctl_hi_val
= 0x00004805;
228 clk_fabia_pll_configure(&video_pll0
, regmap
, &video_pll0_config
);
230 /* Keep VIDEO_CC_XO_CLK ALWAYS-ON */
231 regmap_update_bits(regmap
, 0x984, 0x1, 0x1);
233 return qcom_cc_really_probe(pdev
, &video_cc_sc7180_desc
, regmap
);
236 static struct platform_driver video_cc_sc7180_driver
= {
237 .probe
= video_cc_sc7180_probe
,
239 .name
= "sc7180-videocc",
240 .of_match_table
= video_cc_sc7180_match_table
,
244 static int __init
video_cc_sc7180_init(void)
246 return platform_driver_register(&video_cc_sc7180_driver
);
248 subsys_initcall(video_cc_sc7180_init
);
250 static void __exit
video_cc_sc7180_exit(void)
252 platform_driver_unregister(&video_cc_sc7180_driver
);
254 module_exit(video_cc_sc7180_exit
);
256 MODULE_LICENSE("GPL v2");
257 MODULE_DESCRIPTION("QTI VIDEOCC SC7180 Driver");