Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2018, The Linux Foundation. All rights reserved.
0004  */
0005 
0006 #include <linux/clk-provider.h>
0007 #include <linux/platform_device.h>
0008 #include <linux/module.h>
0009 #include <linux/of_address.h>
0010 #include <linux/regmap.h>
0011 
0012 #include <dt-bindings/clock/qcom,lpass-sdm845.h>
0013 
0014 #include "clk-regmap.h"
0015 #include "clk-branch.h"
0016 #include "common.h"
0017 
0018 static struct clk_branch lpass_q6ss_ahbm_aon_clk = {
0019     .halt_reg = 0x12000,
0020     .halt_check = BRANCH_VOTED,
0021     .clkr = {
0022         .enable_reg = 0x12000,
0023         .enable_mask = BIT(0),
0024         .hw.init = &(struct clk_init_data){
0025             .name = "lpass_q6ss_ahbm_aon_clk",
0026             .ops = &clk_branch2_ops,
0027         },
0028     },
0029 };
0030 
0031 static struct clk_branch lpass_q6ss_ahbs_aon_clk = {
0032     .halt_reg = 0x1f000,
0033     .halt_check = BRANCH_VOTED,
0034     .clkr = {
0035         .enable_reg = 0x1f000,
0036         .enable_mask = BIT(0),
0037         .hw.init = &(struct clk_init_data){
0038             .name = "lpass_q6ss_ahbs_aon_clk",
0039             .ops = &clk_branch2_ops,
0040         },
0041     },
0042 };
0043 
0044 static struct clk_branch lpass_qdsp6ss_core_clk = {
0045     .halt_reg = 0x20,
0046     /* CLK_OFF would not toggle until LPASS is out of reset */
0047     .halt_check = BRANCH_HALT_SKIP,
0048     .clkr = {
0049         .enable_reg = 0x20,
0050         .enable_mask = BIT(0),
0051         .hw.init = &(struct clk_init_data){
0052             .name = "lpass_qdsp6ss_core_clk",
0053             .ops = &clk_branch2_ops,
0054         },
0055     },
0056 };
0057 
0058 static struct clk_branch lpass_qdsp6ss_xo_clk = {
0059     .halt_reg = 0x38,
0060     /* CLK_OFF would not toggle until LPASS is out of reset */
0061     .halt_check = BRANCH_HALT_SKIP,
0062     .clkr = {
0063         .enable_reg = 0x38,
0064         .enable_mask = BIT(0),
0065         .hw.init = &(struct clk_init_data){
0066             .name = "lpass_qdsp6ss_xo_clk",
0067             .ops = &clk_branch2_ops,
0068         },
0069     },
0070 };
0071 
0072 static struct clk_branch lpass_qdsp6ss_sleep_clk = {
0073     .halt_reg = 0x3c,
0074     /* CLK_OFF would not toggle until LPASS is out of reset */
0075     .halt_check = BRANCH_HALT_SKIP,
0076     .clkr = {
0077         .enable_reg = 0x3c,
0078         .enable_mask = BIT(0),
0079         .hw.init = &(struct clk_init_data){
0080             .name = "lpass_qdsp6ss_sleep_clk",
0081             .ops = &clk_branch2_ops,
0082         },
0083     },
0084 };
0085 
0086 static struct regmap_config lpass_regmap_config = {
0087     .reg_bits   = 32,
0088     .reg_stride = 4,
0089     .val_bits   = 32,
0090     .fast_io    = true,
0091 };
0092 
0093 static struct clk_regmap *lpass_cc_sdm845_clocks[] = {
0094     [LPASS_Q6SS_AHBM_AON_CLK] = &lpass_q6ss_ahbm_aon_clk.clkr,
0095     [LPASS_Q6SS_AHBS_AON_CLK] = &lpass_q6ss_ahbs_aon_clk.clkr,
0096 };
0097 
0098 static const struct qcom_cc_desc lpass_cc_sdm845_desc = {
0099     .config = &lpass_regmap_config,
0100     .clks = lpass_cc_sdm845_clocks,
0101     .num_clks = ARRAY_SIZE(lpass_cc_sdm845_clocks),
0102 };
0103 
0104 static struct clk_regmap *lpass_qdsp6ss_sdm845_clocks[] = {
0105     [LPASS_QDSP6SS_XO_CLK] = &lpass_qdsp6ss_xo_clk.clkr,
0106     [LPASS_QDSP6SS_SLEEP_CLK] = &lpass_qdsp6ss_sleep_clk.clkr,
0107     [LPASS_QDSP6SS_CORE_CLK] = &lpass_qdsp6ss_core_clk.clkr,
0108 };
0109 
0110 static const struct qcom_cc_desc lpass_qdsp6ss_sdm845_desc = {
0111     .config = &lpass_regmap_config,
0112     .clks = lpass_qdsp6ss_sdm845_clocks,
0113     .num_clks = ARRAY_SIZE(lpass_qdsp6ss_sdm845_clocks),
0114 };
0115 
0116 static int lpass_cc_sdm845_probe(struct platform_device *pdev)
0117 {
0118     const struct qcom_cc_desc *desc;
0119     int ret;
0120 
0121     lpass_regmap_config.name = "cc";
0122     desc = &lpass_cc_sdm845_desc;
0123 
0124     ret = qcom_cc_probe_by_index(pdev, 0, desc);
0125     if (ret)
0126         return ret;
0127 
0128     lpass_regmap_config.name = "qdsp6ss";
0129     desc = &lpass_qdsp6ss_sdm845_desc;
0130 
0131     return qcom_cc_probe_by_index(pdev, 1, desc);
0132 }
0133 
0134 static const struct of_device_id lpass_cc_sdm845_match_table[] = {
0135     { .compatible = "qcom,sdm845-lpasscc" },
0136     { }
0137 };
0138 MODULE_DEVICE_TABLE(of, lpass_cc_sdm845_match_table);
0139 
0140 static struct platform_driver lpass_cc_sdm845_driver = {
0141     .probe      = lpass_cc_sdm845_probe,
0142     .driver     = {
0143         .name   = "sdm845-lpasscc",
0144         .of_match_table = lpass_cc_sdm845_match_table,
0145     },
0146 };
0147 
0148 static int __init lpass_cc_sdm845_init(void)
0149 {
0150     return platform_driver_register(&lpass_cc_sdm845_driver);
0151 }
0152 subsys_initcall(lpass_cc_sdm845_init);
0153 
0154 static void __exit lpass_cc_sdm845_exit(void)
0155 {
0156     platform_driver_unregister(&lpass_cc_sdm845_driver);
0157 }
0158 module_exit(lpass_cc_sdm845_exit);
0159 
0160 MODULE_DESCRIPTION("QTI LPASS_CC SDM845 Driver");
0161 MODULE_LICENSE("GPL v2");