0001
0002
0003
0004
0005
0006 #include <linux/clk-provider.h>
0007 #include <linux/module.h>
0008 #include <linux/platform_device.h>
0009 #include <linux/regmap.h>
0010
0011 #include <dt-bindings/clock/qcom,videocc-sc7280.h>
0012
0013 #include "clk-alpha-pll.h"
0014 #include "clk-branch.h"
0015 #include "clk-rcg.h"
0016 #include "common.h"
0017 #include "reset.h"
0018 #include "gdsc.h"
0019
0020 enum {
0021 P_BI_TCXO,
0022 P_SLEEP_CLK,
0023 P_VIDEO_PLL0_OUT_EVEN,
0024 };
0025
0026 static const struct pll_vco lucid_vco[] = {
0027 { 249600000, 2000000000, 0 },
0028 };
0029
0030
0031 static const struct alpha_pll_config video_pll0_config = {
0032 .l = 0x14,
0033 .alpha = 0xD555,
0034 .config_ctl_val = 0x20485699,
0035 .config_ctl_hi_val = 0x00002261,
0036 .config_ctl_hi1_val = 0x329A299C,
0037 .user_ctl_val = 0x00000001,
0038 .user_ctl_hi_val = 0x00000805,
0039 .user_ctl_hi1_val = 0x00000000,
0040 };
0041
0042 static struct clk_alpha_pll video_pll0 = {
0043 .offset = 0x0,
0044 .vco_table = lucid_vco,
0045 .num_vco = ARRAY_SIZE(lucid_vco),
0046 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
0047 .clkr = {
0048 .hw.init = &(struct clk_init_data){
0049 .name = "video_pll0",
0050 .parent_data = &(const struct clk_parent_data){
0051 .fw_name = "bi_tcxo",
0052 },
0053 .num_parents = 1,
0054 .ops = &clk_alpha_pll_lucid_ops,
0055 },
0056 },
0057 };
0058
0059 static const struct parent_map video_cc_parent_map_0[] = {
0060 { P_BI_TCXO, 0 },
0061 { P_VIDEO_PLL0_OUT_EVEN, 3 },
0062 };
0063
0064 static const struct clk_parent_data video_cc_parent_data_0[] = {
0065 { .fw_name = "bi_tcxo" },
0066 { .hw = &video_pll0.clkr.hw },
0067 };
0068
0069 static const struct parent_map video_cc_parent_map_1[] = {
0070 { P_SLEEP_CLK, 0 },
0071 };
0072
0073 static const struct clk_parent_data video_cc_parent_data_1[] = {
0074 { .fw_name = "sleep_clk" },
0075 };
0076
0077 static const struct freq_tbl ftbl_video_cc_iris_clk_src[] = {
0078 F(133333333, P_VIDEO_PLL0_OUT_EVEN, 3, 0, 0),
0079 F(240000000, P_VIDEO_PLL0_OUT_EVEN, 2, 0, 0),
0080 F(335000000, P_VIDEO_PLL0_OUT_EVEN, 2, 0, 0),
0081 F(424000000, P_VIDEO_PLL0_OUT_EVEN, 2, 0, 0),
0082 F(460000000, P_VIDEO_PLL0_OUT_EVEN, 2, 0, 0),
0083 { }
0084 };
0085
0086 static struct clk_rcg2 video_cc_iris_clk_src = {
0087 .cmd_rcgr = 0x1000,
0088 .mnd_width = 0,
0089 .hid_width = 5,
0090 .parent_map = video_cc_parent_map_0,
0091 .freq_tbl = ftbl_video_cc_iris_clk_src,
0092 .clkr.hw.init = &(struct clk_init_data){
0093 .name = "video_cc_iris_clk_src",
0094 .parent_data = video_cc_parent_data_0,
0095 .num_parents = ARRAY_SIZE(video_cc_parent_data_0),
0096 .flags = CLK_SET_RATE_PARENT,
0097 .ops = &clk_rcg2_shared_ops,
0098 },
0099 };
0100
0101 static const struct freq_tbl ftbl_video_cc_sleep_clk_src[] = {
0102 F(32000, P_SLEEP_CLK, 1, 0, 0),
0103 { }
0104 };
0105
0106 static struct clk_rcg2 video_cc_sleep_clk_src = {
0107 .cmd_rcgr = 0x701c,
0108 .mnd_width = 0,
0109 .hid_width = 5,
0110 .parent_map = video_cc_parent_map_1,
0111 .freq_tbl = ftbl_video_cc_sleep_clk_src,
0112 .clkr.hw.init = &(struct clk_init_data){
0113 .name = "video_cc_sleep_clk_src",
0114 .parent_data = video_cc_parent_data_1,
0115 .num_parents = ARRAY_SIZE(video_cc_parent_data_1),
0116 .ops = &clk_rcg2_ops,
0117 },
0118 };
0119
0120 static struct clk_branch video_cc_iris_ahb_clk = {
0121 .halt_reg = 0x5004,
0122 .halt_check = BRANCH_HALT_VOTED,
0123 .clkr = {
0124 .enable_reg = 0x5004,
0125 .enable_mask = BIT(0),
0126 .hw.init = &(struct clk_init_data){
0127 .name = "video_cc_iris_ahb_clk",
0128 .parent_hws = (const struct clk_hw*[]){
0129 &video_cc_iris_clk_src.clkr.hw,
0130 },
0131 .num_parents = 1,
0132 .flags = CLK_SET_RATE_PARENT,
0133 .ops = &clk_branch2_ops,
0134 },
0135 },
0136 };
0137
0138 static struct clk_branch video_cc_mvs0_axi_clk = {
0139 .halt_reg = 0x800c,
0140 .halt_check = BRANCH_HALT,
0141 .clkr = {
0142 .enable_reg = 0x800c,
0143 .enable_mask = BIT(0),
0144 .hw.init = &(struct clk_init_data){
0145 .name = "video_cc_mvs0_axi_clk",
0146 .ops = &clk_branch2_ops,
0147 },
0148 },
0149 };
0150
0151 static struct clk_branch video_cc_mvs0_core_clk = {
0152 .halt_reg = 0x3010,
0153 .halt_check = BRANCH_HALT_VOTED,
0154 .hwcg_reg = 0x3010,
0155 .hwcg_bit = 1,
0156 .clkr = {
0157 .enable_reg = 0x3010,
0158 .enable_mask = BIT(0),
0159 .hw.init = &(struct clk_init_data){
0160 .name = "video_cc_mvs0_core_clk",
0161 .parent_hws = (const struct clk_hw*[]){
0162 &video_cc_iris_clk_src.clkr.hw,
0163 },
0164 .num_parents = 1,
0165 .flags = CLK_SET_RATE_PARENT,
0166 .ops = &clk_branch2_ops,
0167 },
0168 },
0169 };
0170
0171 static struct clk_branch video_cc_mvsc_core_clk = {
0172 .halt_reg = 0x2014,
0173 .halt_check = BRANCH_HALT,
0174 .clkr = {
0175 .enable_reg = 0x2014,
0176 .enable_mask = BIT(0),
0177 .hw.init = &(struct clk_init_data){
0178 .name = "video_cc_mvsc_core_clk",
0179 .parent_hws = (const struct clk_hw*[]){
0180 &video_cc_iris_clk_src.clkr.hw,
0181 },
0182 .num_parents = 1,
0183 .flags = CLK_SET_RATE_PARENT,
0184 .ops = &clk_branch2_ops,
0185 },
0186 },
0187 };
0188
0189 static struct clk_branch video_cc_mvsc_ctl_axi_clk = {
0190 .halt_reg = 0x8004,
0191 .halt_check = BRANCH_HALT,
0192 .clkr = {
0193 .enable_reg = 0x8004,
0194 .enable_mask = BIT(0),
0195 .hw.init = &(struct clk_init_data){
0196 .name = "video_cc_mvsc_ctl_axi_clk",
0197 .ops = &clk_branch2_ops,
0198 },
0199 },
0200 };
0201
0202 static struct clk_branch video_cc_sleep_clk = {
0203 .halt_reg = 0x7034,
0204 .halt_check = BRANCH_HALT,
0205 .clkr = {
0206 .enable_reg = 0x7034,
0207 .enable_mask = BIT(0),
0208 .hw.init = &(struct clk_init_data){
0209 .name = "video_cc_sleep_clk",
0210 .parent_hws = (const struct clk_hw*[]){
0211 &video_cc_sleep_clk_src.clkr.hw,
0212 },
0213 .num_parents = 1,
0214 .flags = CLK_SET_RATE_PARENT,
0215 .ops = &clk_branch2_ops,
0216 },
0217 },
0218 };
0219
0220 static struct clk_branch video_cc_venus_ahb_clk = {
0221 .halt_reg = 0x801c,
0222 .halt_check = BRANCH_HALT,
0223 .clkr = {
0224 .enable_reg = 0x801c,
0225 .enable_mask = BIT(0),
0226 .hw.init = &(struct clk_init_data){
0227 .name = "video_cc_venus_ahb_clk",
0228 .ops = &clk_branch2_ops,
0229 },
0230 },
0231 };
0232
0233 static struct gdsc mvs0_gdsc = {
0234 .gdscr = 0x3004,
0235 .pd = {
0236 .name = "mvs0_gdsc",
0237 },
0238 .pwrsts = PWRSTS_OFF_ON,
0239 .flags = HW_CTRL | RETAIN_FF_ENABLE,
0240 };
0241
0242 static struct gdsc mvsc_gdsc = {
0243 .gdscr = 0x2004,
0244 .pd = {
0245 .name = "mvsc_gdsc",
0246 },
0247 .flags = RETAIN_FF_ENABLE,
0248 .pwrsts = PWRSTS_OFF_ON,
0249 };
0250
0251 static struct clk_regmap *video_cc_sc7280_clocks[] = {
0252 [VIDEO_CC_IRIS_AHB_CLK] = &video_cc_iris_ahb_clk.clkr,
0253 [VIDEO_CC_IRIS_CLK_SRC] = &video_cc_iris_clk_src.clkr,
0254 [VIDEO_CC_MVS0_AXI_CLK] = &video_cc_mvs0_axi_clk.clkr,
0255 [VIDEO_CC_MVS0_CORE_CLK] = &video_cc_mvs0_core_clk.clkr,
0256 [VIDEO_CC_MVSC_CORE_CLK] = &video_cc_mvsc_core_clk.clkr,
0257 [VIDEO_CC_MVSC_CTL_AXI_CLK] = &video_cc_mvsc_ctl_axi_clk.clkr,
0258 [VIDEO_CC_SLEEP_CLK] = &video_cc_sleep_clk.clkr,
0259 [VIDEO_CC_SLEEP_CLK_SRC] = &video_cc_sleep_clk_src.clkr,
0260 [VIDEO_CC_VENUS_AHB_CLK] = &video_cc_venus_ahb_clk.clkr,
0261 [VIDEO_PLL0] = &video_pll0.clkr,
0262 };
0263
0264 static struct gdsc *video_cc_sc7280_gdscs[] = {
0265 [MVS0_GDSC] = &mvs0_gdsc,
0266 [MVSC_GDSC] = &mvsc_gdsc,
0267 };
0268
0269 static const struct regmap_config video_cc_sc7280_regmap_config = {
0270 .reg_bits = 32,
0271 .reg_stride = 4,
0272 .val_bits = 32,
0273 .max_register = 0xb000,
0274 .fast_io = true,
0275 };
0276
0277 static const struct qcom_cc_desc video_cc_sc7280_desc = {
0278 .config = &video_cc_sc7280_regmap_config,
0279 .clks = video_cc_sc7280_clocks,
0280 .num_clks = ARRAY_SIZE(video_cc_sc7280_clocks),
0281 .gdscs = video_cc_sc7280_gdscs,
0282 .num_gdscs = ARRAY_SIZE(video_cc_sc7280_gdscs),
0283 };
0284
0285 static const struct of_device_id video_cc_sc7280_match_table[] = {
0286 { .compatible = "qcom,sc7280-videocc" },
0287 { }
0288 };
0289 MODULE_DEVICE_TABLE(of, video_cc_sc7280_match_table);
0290
0291 static int video_cc_sc7280_probe(struct platform_device *pdev)
0292 {
0293 struct regmap *regmap;
0294
0295 regmap = qcom_cc_map(pdev, &video_cc_sc7280_desc);
0296 if (IS_ERR(regmap))
0297 return PTR_ERR(regmap);
0298
0299 clk_lucid_pll_configure(&video_pll0, regmap, &video_pll0_config);
0300
0301 return qcom_cc_really_probe(pdev, &video_cc_sc7280_desc, regmap);
0302 }
0303
0304 static struct platform_driver video_cc_sc7280_driver = {
0305 .probe = video_cc_sc7280_probe,
0306 .driver = {
0307 .name = "video_cc-sc7280",
0308 .of_match_table = video_cc_sc7280_match_table,
0309 },
0310 };
0311
0312 static int __init video_cc_sc7280_init(void)
0313 {
0314 return platform_driver_register(&video_cc_sc7280_driver);
0315 }
0316 subsys_initcall(video_cc_sc7280_init);
0317
0318 static void __exit video_cc_sc7280_exit(void)
0319 {
0320 platform_driver_unregister(&video_cc_sc7280_driver);
0321 }
0322 module_exit(video_cc_sc7280_exit);
0323
0324 MODULE_DESCRIPTION("QTI VIDEO_CC sc7280 Driver");
0325 MODULE_LICENSE("GPL v2");