Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
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 /* 400MHz Configuration */
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");