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"
22 P_VIDEO_PLL0_OUT_MAIN
,
25 static const struct pll_vco fabia_vco
[] = {
26 { 249600000, 2000000000, 0 },
29 static struct clk_alpha_pll video_pll0
= {
31 .vco_table
= fabia_vco
,
32 .num_vco
= ARRAY_SIZE(fabia_vco
),
33 .regs
= clk_alpha_pll_regs
[CLK_ALPHA_PLL_TYPE_FABIA
],
35 .hw
.init
= &(struct clk_init_data
){
37 .parent_data
= &(const struct clk_parent_data
){
41 .ops
= &clk_alpha_pll_fabia_ops
,
46 static const struct parent_map video_cc_parent_map_1
[] = {
48 { P_VIDEO_PLL0_OUT_MAIN
, 1 },
51 static const struct clk_parent_data video_cc_parent_data_1
[] = {
52 { .fw_name
= "bi_tcxo" },
53 { .hw
= &video_pll0
.clkr
.hw
},
56 static const struct freq_tbl ftbl_video_cc_venus_clk_src
[] = {
57 F(19200000, P_BI_TCXO
, 1, 0, 0),
58 F(150000000, P_VIDEO_PLL0_OUT_MAIN
, 4, 0, 0),
59 F(270000000, P_VIDEO_PLL0_OUT_MAIN
, 2.5, 0, 0),
60 F(340000000, P_VIDEO_PLL0_OUT_MAIN
, 2, 0, 0),
61 F(434000000, P_VIDEO_PLL0_OUT_MAIN
, 2, 0, 0),
62 F(500000000, P_VIDEO_PLL0_OUT_MAIN
, 2, 0, 0),
66 static struct clk_rcg2 video_cc_venus_clk_src
= {
70 .parent_map
= video_cc_parent_map_1
,
71 .freq_tbl
= ftbl_video_cc_venus_clk_src
,
72 .clkr
.hw
.init
= &(struct clk_init_data
){
73 .name
= "video_cc_venus_clk_src",
74 .parent_data
= video_cc_parent_data_1
,
75 .num_parents
= ARRAY_SIZE(video_cc_parent_data_1
),
76 .flags
= CLK_SET_RATE_PARENT
,
77 .ops
= &clk_rcg2_shared_ops
,
81 static struct clk_branch video_cc_vcodec0_axi_clk
= {
83 .halt_check
= BRANCH_HALT
,
86 .enable_mask
= BIT(0),
87 .hw
.init
= &(struct clk_init_data
){
88 .name
= "video_cc_vcodec0_axi_clk",
89 .ops
= &clk_branch2_ops
,
94 static struct clk_branch video_cc_vcodec0_core_clk
= {
96 .halt_check
= BRANCH_HALT_VOTED
,
99 .enable_mask
= BIT(0),
100 .hw
.init
= &(struct clk_init_data
){
101 .name
= "video_cc_vcodec0_core_clk",
102 .parent_hws
= (const struct clk_hw
*[]){
103 &video_cc_venus_clk_src
.clkr
.hw
,
106 .flags
= CLK_SET_RATE_PARENT
,
107 .ops
= &clk_branch2_ops
,
112 static struct clk_branch video_cc_venus_ahb_clk
= {
114 .halt_check
= BRANCH_HALT
,
117 .enable_mask
= BIT(0),
118 .hw
.init
= &(struct clk_init_data
){
119 .name
= "video_cc_venus_ahb_clk",
120 .ops
= &clk_branch2_ops
,
125 static struct clk_branch video_cc_venus_ctl_axi_clk
= {
127 .halt_check
= BRANCH_HALT
,
130 .enable_mask
= BIT(0),
131 .hw
.init
= &(struct clk_init_data
){
132 .name
= "video_cc_venus_ctl_axi_clk",
133 .ops
= &clk_branch2_ops
,
138 static struct clk_branch video_cc_venus_ctl_core_clk
= {
140 .halt_check
= BRANCH_HALT
,
143 .enable_mask
= BIT(0),
144 .hw
.init
= &(struct clk_init_data
){
145 .name
= "video_cc_venus_ctl_core_clk",
146 .parent_hws
= (const struct clk_hw
*[]){
147 &video_cc_venus_clk_src
.clkr
.hw
,
150 .flags
= CLK_SET_RATE_PARENT
,
151 .ops
= &clk_branch2_ops
,
156 static struct gdsc venus_gdsc
= {
159 .name
= "venus_gdsc",
161 .pwrsts
= PWRSTS_OFF_ON
,
164 static struct gdsc vcodec0_gdsc
= {
167 .name
= "vcodec0_gdsc",
170 .pwrsts
= PWRSTS_OFF_ON
,
173 static struct clk_regmap
*video_cc_sc7180_clocks
[] = {
174 [VIDEO_CC_VCODEC0_AXI_CLK
] = &video_cc_vcodec0_axi_clk
.clkr
,
175 [VIDEO_CC_VCODEC0_CORE_CLK
] = &video_cc_vcodec0_core_clk
.clkr
,
176 [VIDEO_CC_VENUS_AHB_CLK
] = &video_cc_venus_ahb_clk
.clkr
,
177 [VIDEO_CC_VENUS_CLK_SRC
] = &video_cc_venus_clk_src
.clkr
,
178 [VIDEO_CC_VENUS_CTL_AXI_CLK
] = &video_cc_venus_ctl_axi_clk
.clkr
,
179 [VIDEO_CC_VENUS_CTL_CORE_CLK
] = &video_cc_venus_ctl_core_clk
.clkr
,
180 [VIDEO_PLL0
] = &video_pll0
.clkr
,
183 static struct gdsc
*video_cc_sc7180_gdscs
[] = {
184 [VENUS_GDSC
] = &venus_gdsc
,
185 [VCODEC0_GDSC
] = &vcodec0_gdsc
,
188 static const struct regmap_config video_cc_sc7180_regmap_config
= {
192 .max_register
= 0xb94,
196 static const struct qcom_cc_desc video_cc_sc7180_desc
= {
197 .config
= &video_cc_sc7180_regmap_config
,
198 .clks
= video_cc_sc7180_clocks
,
199 .num_clks
= ARRAY_SIZE(video_cc_sc7180_clocks
),
200 .gdscs
= video_cc_sc7180_gdscs
,
201 .num_gdscs
= ARRAY_SIZE(video_cc_sc7180_gdscs
),
204 static const struct of_device_id video_cc_sc7180_match_table
[] = {
205 { .compatible
= "qcom,sc7180-videocc" },
208 MODULE_DEVICE_TABLE(of
, video_cc_sc7180_match_table
);
210 static int video_cc_sc7180_probe(struct platform_device
*pdev
)
212 struct regmap
*regmap
;
213 struct alpha_pll_config video_pll0_config
= {};
215 regmap
= qcom_cc_map(pdev
, &video_cc_sc7180_desc
);
217 return PTR_ERR(regmap
);
219 video_pll0_config
.l
= 0x1f;
220 video_pll0_config
.alpha
= 0x4000;
221 video_pll0_config
.user_ctl_val
= 0x00000001;
222 video_pll0_config
.user_ctl_hi_val
= 0x00004805;
224 clk_fabia_pll_configure(&video_pll0
, regmap
, &video_pll0_config
);
226 /* Keep VIDEO_CC_XO_CLK ALWAYS-ON */
227 regmap_update_bits(regmap
, 0x984, 0x1, 0x1);
229 return qcom_cc_really_probe(&pdev
->dev
, &video_cc_sc7180_desc
, regmap
);
232 static struct platform_driver video_cc_sc7180_driver
= {
233 .probe
= video_cc_sc7180_probe
,
235 .name
= "sc7180-videocc",
236 .of_match_table
= video_cc_sc7180_match_table
,
240 module_platform_driver(video_cc_sc7180_driver
);
242 MODULE_LICENSE("GPL v2");
243 MODULE_DESCRIPTION("QTI VIDEOCC SC7180 Driver");