Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2018-2020, 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,gpucc-sm8250.h>
0012 
0013 #include "common.h"
0014 #include "clk-alpha-pll.h"
0015 #include "clk-branch.h"
0016 #include "clk-pll.h"
0017 #include "clk-rcg.h"
0018 #include "clk-regmap.h"
0019 #include "reset.h"
0020 #include "gdsc.h"
0021 
0022 #define CX_GMU_CBCR_SLEEP_MASK      0xf
0023 #define CX_GMU_CBCR_SLEEP_SHIFT     4
0024 #define CX_GMU_CBCR_WAKE_MASK       0xf
0025 #define CX_GMU_CBCR_WAKE_SHIFT      8
0026 
0027 enum {
0028     P_BI_TCXO,
0029     P_GPLL0_OUT_MAIN,
0030     P_GPLL0_OUT_MAIN_DIV,
0031     P_GPU_CC_PLL0_OUT_MAIN,
0032     P_GPU_CC_PLL1_OUT_MAIN,
0033 };
0034 
0035 static struct pll_vco lucid_vco[] = {
0036     { 249600000, 2000000000, 0 },
0037 };
0038 
0039 static const struct alpha_pll_config gpu_cc_pll1_config = {
0040     .l = 0x1a,
0041     .alpha = 0xaaa,
0042     .config_ctl_val = 0x20485699,
0043     .config_ctl_hi_val = 0x00002261,
0044     .config_ctl_hi1_val = 0x029a699c,
0045     .user_ctl_val = 0x00000000,
0046     .user_ctl_hi_val = 0x00000805,
0047     .user_ctl_hi1_val = 0x00000000,
0048 };
0049 
0050 static struct clk_alpha_pll gpu_cc_pll1 = {
0051     .offset = 0x100,
0052     .vco_table = lucid_vco,
0053     .num_vco = ARRAY_SIZE(lucid_vco),
0054     .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
0055     .clkr = {
0056         .hw.init = &(struct clk_init_data){
0057             .name = "gpu_cc_pll1",
0058             .parent_data =  &(const struct clk_parent_data){
0059                 .fw_name = "bi_tcxo",
0060             },
0061             .num_parents = 1,
0062             .ops = &clk_alpha_pll_lucid_ops,
0063         },
0064     },
0065 };
0066 
0067 static const struct parent_map gpu_cc_parent_map_0[] = {
0068     { P_BI_TCXO, 0 },
0069     { P_GPU_CC_PLL1_OUT_MAIN, 3 },
0070     { P_GPLL0_OUT_MAIN, 5 },
0071     { P_GPLL0_OUT_MAIN_DIV, 6 },
0072 };
0073 
0074 static const struct clk_parent_data gpu_cc_parent_data_0[] = {
0075     { .fw_name = "bi_tcxo" },
0076     { .hw = &gpu_cc_pll1.clkr.hw },
0077     { .fw_name = "gcc_gpu_gpll0_clk_src" },
0078     { .fw_name = "gcc_gpu_gpll0_div_clk_src" },
0079 };
0080 
0081 static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = {
0082     F(19200000, P_BI_TCXO, 1, 0, 0),
0083     F(200000000, P_GPLL0_OUT_MAIN_DIV, 1.5, 0, 0),
0084     F(500000000, P_GPU_CC_PLL1_OUT_MAIN, 1, 0, 0),
0085     { }
0086 };
0087 
0088 static struct clk_rcg2 gpu_cc_gmu_clk_src = {
0089     .cmd_rcgr = 0x1120,
0090     .mnd_width = 0,
0091     .hid_width = 5,
0092     .parent_map = gpu_cc_parent_map_0,
0093     .freq_tbl = ftbl_gpu_cc_gmu_clk_src,
0094     .clkr.hw.init = &(struct clk_init_data){
0095         .name = "gpu_cc_gmu_clk_src",
0096         .parent_data = gpu_cc_parent_data_0,
0097         .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0),
0098         .flags = CLK_SET_RATE_PARENT,
0099         .ops = &clk_rcg2_ops,
0100     },
0101 };
0102 
0103 static struct clk_branch gpu_cc_ahb_clk = {
0104     .halt_reg = 0x1078,
0105     .halt_check = BRANCH_HALT_DELAY,
0106     .clkr = {
0107         .enable_reg = 0x1078,
0108         .enable_mask = BIT(0),
0109         .hw.init = &(struct clk_init_data){
0110             .name = "gpu_cc_ahb_clk",
0111             .ops = &clk_branch2_ops,
0112         },
0113     },
0114 };
0115 
0116 static struct clk_branch gpu_cc_crc_ahb_clk = {
0117     .halt_reg = 0x107c,
0118     .halt_check = BRANCH_HALT_VOTED,
0119     .clkr = {
0120         .enable_reg = 0x107c,
0121         .enable_mask = BIT(0),
0122         .hw.init = &(struct clk_init_data){
0123             .name = "gpu_cc_crc_ahb_clk",
0124             .ops = &clk_branch2_ops,
0125         },
0126     },
0127 };
0128 
0129 static struct clk_branch gpu_cc_cx_apb_clk = {
0130     .halt_reg = 0x1088,
0131     .halt_check = BRANCH_HALT_VOTED,
0132     .clkr = {
0133         .enable_reg = 0x1088,
0134         .enable_mask = BIT(0),
0135         .hw.init = &(struct clk_init_data){
0136             .name = "gpu_cc_cx_apb_clk",
0137             .ops = &clk_branch2_ops,
0138         },
0139     },
0140 };
0141 
0142 static struct clk_branch gpu_cc_cx_gmu_clk = {
0143     .halt_reg = 0x1098,
0144     .halt_check = BRANCH_HALT,
0145     .clkr = {
0146         .enable_reg = 0x1098,
0147         .enable_mask = BIT(0),
0148         .hw.init = &(struct clk_init_data){
0149             .name = "gpu_cc_cx_gmu_clk",
0150             .parent_hws = (const struct clk_hw*[]){
0151                 &gpu_cc_gmu_clk_src.clkr.hw,
0152             },
0153             .num_parents = 1,
0154             .flags = CLK_SET_RATE_PARENT,
0155             .ops = &clk_branch2_ops,
0156         },
0157     },
0158 };
0159 
0160 static struct clk_branch gpu_cc_cx_snoc_dvm_clk = {
0161     .halt_reg = 0x108c,
0162     .halt_check = BRANCH_HALT_VOTED,
0163     .clkr = {
0164         .enable_reg = 0x108c,
0165         .enable_mask = BIT(0),
0166         .hw.init = &(struct clk_init_data){
0167             .name = "gpu_cc_cx_snoc_dvm_clk",
0168             .ops = &clk_branch2_ops,
0169         },
0170     },
0171 };
0172 
0173 static struct clk_branch gpu_cc_cxo_aon_clk = {
0174     .halt_reg = 0x1004,
0175     .halt_check = BRANCH_HALT_VOTED,
0176     .clkr = {
0177         .enable_reg = 0x1004,
0178         .enable_mask = BIT(0),
0179         .hw.init = &(struct clk_init_data){
0180             .name = "gpu_cc_cxo_aon_clk",
0181             .ops = &clk_branch2_ops,
0182         },
0183     },
0184 };
0185 
0186 static struct clk_branch gpu_cc_cxo_clk = {
0187     .halt_reg = 0x109c,
0188     .halt_check = BRANCH_HALT,
0189     .clkr = {
0190         .enable_reg = 0x109c,
0191         .enable_mask = BIT(0),
0192         .hw.init = &(struct clk_init_data){
0193             .name = "gpu_cc_cxo_clk",
0194             .ops = &clk_branch2_ops,
0195         },
0196     },
0197 };
0198 
0199 static struct clk_branch gpu_cc_gx_gmu_clk = {
0200     .halt_reg = 0x1064,
0201     .halt_check = BRANCH_HALT,
0202     .clkr = {
0203         .enable_reg = 0x1064,
0204         .enable_mask = BIT(0),
0205         .hw.init = &(struct clk_init_data){
0206             .name = "gpu_cc_gx_gmu_clk",
0207             .parent_hws = (const struct clk_hw*[]){
0208                 &gpu_cc_gmu_clk_src.clkr.hw,
0209             },
0210             .num_parents = 1,
0211             .flags = CLK_SET_RATE_PARENT,
0212             .ops = &clk_branch2_ops,
0213         },
0214     },
0215 };
0216 
0217 static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk = {
0218     .halt_reg = 0x5000,
0219     .halt_check = BRANCH_VOTED,
0220     .clkr = {
0221         .enable_reg = 0x5000,
0222         .enable_mask = BIT(0),
0223         .hw.init = &(struct clk_init_data){
0224              .name = "gpu_cc_hlos1_vote_gpu_smmu_clk",
0225              .ops = &clk_branch2_ops,
0226         },
0227     },
0228 };
0229 
0230 static struct gdsc gpu_cx_gdsc = {
0231     .gdscr = 0x106c,
0232     .gds_hw_ctrl = 0x1540,
0233     .pd = {
0234         .name = "gpu_cx_gdsc",
0235     },
0236     .pwrsts = PWRSTS_OFF_ON,
0237     .flags = VOTABLE,
0238 };
0239 
0240 static struct gdsc gpu_gx_gdsc = {
0241     .gdscr = 0x100c,
0242     .clamp_io_ctrl = 0x1508,
0243     .pd = {
0244         .name = "gpu_gx_gdsc",
0245         .power_on = gdsc_gx_do_nothing_enable,
0246     },
0247     .pwrsts = PWRSTS_OFF_ON,
0248     .flags = CLAMP_IO | AON_RESET | POLL_CFG_GDSCR,
0249 };
0250 
0251 static struct clk_regmap *gpu_cc_sm8250_clocks[] = {
0252     [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr,
0253     [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr,
0254     [GPU_CC_CX_APB_CLK] = &gpu_cc_cx_apb_clk.clkr,
0255     [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr,
0256     [GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_clk.clkr,
0257     [GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr,
0258     [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr,
0259     [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr,
0260     [GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr,
0261     [GPU_CC_PLL1] = &gpu_cc_pll1.clkr,
0262     [GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK] = &gpu_cc_hlos1_vote_gpu_smmu_clk.clkr,
0263 };
0264 
0265 static const struct qcom_reset_map gpu_cc_sm8250_resets[] = {
0266     [GPUCC_GPU_CC_ACD_BCR] = { 0x1160 },
0267     [GPUCC_GPU_CC_CX_BCR] = { 0x1068 },
0268     [GPUCC_GPU_CC_GFX3D_AON_BCR] = { 0x10a0 },
0269     [GPUCC_GPU_CC_GMU_BCR] = { 0x111c },
0270     [GPUCC_GPU_CC_GX_BCR] = { 0x1008 },
0271     [GPUCC_GPU_CC_XO_BCR] = { 0x1000 },
0272 };
0273 
0274 static struct gdsc *gpu_cc_sm8250_gdscs[] = {
0275     [GPU_CX_GDSC] = &gpu_cx_gdsc,
0276     [GPU_GX_GDSC] = &gpu_gx_gdsc,
0277 };
0278 
0279 static const struct regmap_config gpu_cc_sm8250_regmap_config = {
0280     .reg_bits = 32,
0281     .reg_stride = 4,
0282     .val_bits = 32,
0283     .max_register = 0x8008,
0284     .fast_io = true,
0285 };
0286 
0287 static const struct qcom_cc_desc gpu_cc_sm8250_desc = {
0288     .config = &gpu_cc_sm8250_regmap_config,
0289     .clks = gpu_cc_sm8250_clocks,
0290     .num_clks = ARRAY_SIZE(gpu_cc_sm8250_clocks),
0291     .resets = gpu_cc_sm8250_resets,
0292     .num_resets = ARRAY_SIZE(gpu_cc_sm8250_resets),
0293     .gdscs = gpu_cc_sm8250_gdscs,
0294     .num_gdscs = ARRAY_SIZE(gpu_cc_sm8250_gdscs),
0295 };
0296 
0297 static const struct of_device_id gpu_cc_sm8250_match_table[] = {
0298     { .compatible = "qcom,sm8250-gpucc" },
0299     { }
0300 };
0301 MODULE_DEVICE_TABLE(of, gpu_cc_sm8250_match_table);
0302 
0303 static int gpu_cc_sm8250_probe(struct platform_device *pdev)
0304 {
0305     struct regmap *regmap;
0306     unsigned int value, mask;
0307 
0308     regmap = qcom_cc_map(pdev, &gpu_cc_sm8250_desc);
0309     if (IS_ERR(regmap))
0310         return PTR_ERR(regmap);
0311 
0312     clk_lucid_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config);
0313 
0314     /*
0315      * Configure gpu_cc_cx_gmu_clk with recommended
0316      * wakeup/sleep settings
0317      */
0318     mask = CX_GMU_CBCR_WAKE_MASK << CX_GMU_CBCR_WAKE_SHIFT;
0319     mask |= CX_GMU_CBCR_SLEEP_MASK << CX_GMU_CBCR_SLEEP_SHIFT;
0320     value = 0xf << CX_GMU_CBCR_WAKE_SHIFT | 0xf << CX_GMU_CBCR_SLEEP_SHIFT;
0321     regmap_update_bits(regmap, 0x1098, mask, value);
0322 
0323     return qcom_cc_really_probe(pdev, &gpu_cc_sm8250_desc, regmap);
0324 }
0325 
0326 static struct platform_driver gpu_cc_sm8250_driver = {
0327     .probe = gpu_cc_sm8250_probe,
0328     .driver = {
0329         .name = "sm8250-gpucc",
0330         .of_match_table = gpu_cc_sm8250_match_table,
0331     },
0332 };
0333 
0334 static int __init gpu_cc_sm8250_init(void)
0335 {
0336     return platform_driver_register(&gpu_cc_sm8250_driver);
0337 }
0338 subsys_initcall(gpu_cc_sm8250_init);
0339 
0340 static void __exit gpu_cc_sm8250_exit(void)
0341 {
0342     platform_driver_unregister(&gpu_cc_sm8250_driver);
0343 }
0344 module_exit(gpu_cc_sm8250_exit);
0345 
0346 MODULE_DESCRIPTION("QTI GPU_CC SM8250 Driver");
0347 MODULE_LICENSE("GPL v2");