Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
0004  */
0005 
0006 #include <linux/clk-provider.h>
0007 #include <linux/platform_device.h>
0008 #include <linux/pm_clock.h>
0009 #include <linux/pm_runtime.h>
0010 #include <linux/module.h>
0011 #include <linux/of_address.h>
0012 #include <linux/regmap.h>
0013 
0014 #include <dt-bindings/clock/qcom,lpass-sc7280.h>
0015 
0016 #include "clk-regmap.h"
0017 #include "clk-branch.h"
0018 #include "common.h"
0019 
0020 static struct clk_branch lpass_q6ss_ahbm_clk = {
0021     .halt_reg = 0x1c,
0022     .halt_check = BRANCH_HALT,
0023     .clkr = {
0024         .enable_reg = 0x1c,
0025         .enable_mask = BIT(0),
0026         .hw.init = &(struct clk_init_data){
0027             .name = "lpass_q6ss_ahbm_clk",
0028             .ops = &clk_branch2_ops,
0029         },
0030     },
0031 };
0032 
0033 static struct clk_branch lpass_q6ss_ahbs_clk = {
0034     .halt_reg = 0x20,
0035     .halt_check = BRANCH_HALT_VOTED,
0036     .clkr = {
0037         .enable_reg = 0x20,
0038         .enable_mask = BIT(0),
0039         .hw.init = &(struct clk_init_data){
0040             .name = "lpass_q6ss_ahbs_clk",
0041             .ops = &clk_branch2_ops,
0042         },
0043     },
0044 };
0045 
0046 static struct clk_branch lpass_top_cc_lpi_q6_axim_hs_clk = {
0047     .halt_reg = 0x0,
0048     .halt_check = BRANCH_HALT,
0049     .clkr = {
0050         .enable_reg = 0x0,
0051         .enable_mask = BIT(0),
0052         .hw.init = &(struct clk_init_data){
0053             .name = "lpass_top_cc_lpi_q6_axim_hs_clk",
0054             .ops = &clk_branch2_ops,
0055         },
0056     },
0057 };
0058 
0059 static struct clk_branch lpass_qdsp6ss_core_clk = {
0060     .halt_reg = 0x20,
0061     /* CLK_OFF would not toggle until LPASS is out of reset */
0062     .halt_check = BRANCH_HALT_SKIP,
0063     .clkr = {
0064         .enable_reg = 0x20,
0065         .enable_mask = BIT(0),
0066         .hw.init = &(struct clk_init_data){
0067             .name = "lpass_qdsp6ss_core_clk",
0068             .ops = &clk_branch2_ops,
0069         },
0070     },
0071 };
0072 
0073 static struct clk_branch lpass_qdsp6ss_xo_clk = {
0074     .halt_reg = 0x38,
0075     /* CLK_OFF would not toggle until LPASS is out of reset */
0076     .halt_check = BRANCH_HALT_SKIP,
0077     .clkr = {
0078         .enable_reg = 0x38,
0079         .enable_mask = BIT(0),
0080         .hw.init = &(struct clk_init_data){
0081             .name = "lpass_qdsp6ss_xo_clk",
0082             .ops = &clk_branch2_ops,
0083         },
0084     },
0085 };
0086 
0087 static struct clk_branch lpass_qdsp6ss_sleep_clk = {
0088     .halt_reg = 0x3c,
0089     /* CLK_OFF would not toggle until LPASS is out of reset */
0090     .halt_check = BRANCH_HALT_SKIP,
0091     .clkr = {
0092         .enable_reg = 0x3c,
0093         .enable_mask = BIT(0),
0094         .hw.init = &(struct clk_init_data){
0095             .name = "lpass_qdsp6ss_sleep_clk",
0096             .ops = &clk_branch2_ops,
0097         },
0098     },
0099 };
0100 
0101 static struct regmap_config lpass_regmap_config = {
0102     .reg_bits   = 32,
0103     .reg_stride = 4,
0104     .val_bits   = 32,
0105     .fast_io    = true,
0106 };
0107 
0108 static struct clk_regmap *lpass_cc_sc7280_clocks[] = {
0109     [LPASS_Q6SS_AHBM_CLK] = &lpass_q6ss_ahbm_clk.clkr,
0110     [LPASS_Q6SS_AHBS_CLK] = &lpass_q6ss_ahbs_clk.clkr,
0111 };
0112 
0113 static const struct qcom_cc_desc lpass_cc_sc7280_desc = {
0114     .config = &lpass_regmap_config,
0115     .clks = lpass_cc_sc7280_clocks,
0116     .num_clks = ARRAY_SIZE(lpass_cc_sc7280_clocks),
0117 };
0118 
0119 static struct clk_regmap *lpass_cc_top_sc7280_clocks[] = {
0120     [LPASS_TOP_CC_LPI_Q6_AXIM_HS_CLK] =
0121                 &lpass_top_cc_lpi_q6_axim_hs_clk.clkr,
0122 };
0123 
0124 static const struct qcom_cc_desc lpass_cc_top_sc7280_desc = {
0125     .config = &lpass_regmap_config,
0126     .clks = lpass_cc_top_sc7280_clocks,
0127     .num_clks = ARRAY_SIZE(lpass_cc_top_sc7280_clocks),
0128 };
0129 
0130 static struct clk_regmap *lpass_qdsp6ss_sc7280_clocks[] = {
0131     [LPASS_QDSP6SS_XO_CLK] = &lpass_qdsp6ss_xo_clk.clkr,
0132     [LPASS_QDSP6SS_SLEEP_CLK] = &lpass_qdsp6ss_sleep_clk.clkr,
0133     [LPASS_QDSP6SS_CORE_CLK] = &lpass_qdsp6ss_core_clk.clkr,
0134 };
0135 
0136 static const struct qcom_cc_desc lpass_qdsp6ss_sc7280_desc = {
0137     .config = &lpass_regmap_config,
0138     .clks = lpass_qdsp6ss_sc7280_clocks,
0139     .num_clks = ARRAY_SIZE(lpass_qdsp6ss_sc7280_clocks),
0140 };
0141 
0142 static int lpass_cc_sc7280_probe(struct platform_device *pdev)
0143 {
0144     const struct qcom_cc_desc *desc;
0145     int ret;
0146 
0147     pm_runtime_enable(&pdev->dev);
0148     ret = pm_clk_create(&pdev->dev);
0149     if (ret)
0150         goto disable_pm_runtime;
0151 
0152     ret = pm_clk_add(&pdev->dev, "iface");
0153     if (ret < 0) {
0154         dev_err(&pdev->dev, "failed to acquire iface clock\n");
0155         goto destroy_pm_clk;
0156     }
0157 
0158     lpass_regmap_config.name = "qdsp6ss";
0159     desc = &lpass_qdsp6ss_sc7280_desc;
0160 
0161     ret = qcom_cc_probe_by_index(pdev, 0, desc);
0162     if (ret)
0163         goto destroy_pm_clk;
0164 
0165     lpass_regmap_config.name = "top_cc";
0166     desc = &lpass_cc_top_sc7280_desc;
0167 
0168     ret = qcom_cc_probe_by_index(pdev, 1, desc);
0169     if (ret)
0170         goto destroy_pm_clk;
0171 
0172     lpass_regmap_config.name = "cc";
0173     desc = &lpass_cc_sc7280_desc;
0174 
0175     ret = qcom_cc_probe_by_index(pdev, 2, desc);
0176     if (ret)
0177         goto destroy_pm_clk;
0178 
0179     return 0;
0180 
0181 destroy_pm_clk:
0182     pm_clk_destroy(&pdev->dev);
0183 
0184 disable_pm_runtime:
0185     pm_runtime_disable(&pdev->dev);
0186 
0187     return ret;
0188 }
0189 
0190 static const struct of_device_id lpass_cc_sc7280_match_table[] = {
0191     { .compatible = "qcom,sc7280-lpasscc" },
0192     { }
0193 };
0194 MODULE_DEVICE_TABLE(of, lpass_cc_sc7280_match_table);
0195 
0196 static struct platform_driver lpass_cc_sc7280_driver = {
0197     .probe      = lpass_cc_sc7280_probe,
0198     .driver     = {
0199         .name   = "sc7280-lpasscc",
0200         .of_match_table = lpass_cc_sc7280_match_table,
0201     },
0202 };
0203 
0204 static int __init lpass_cc_sc7280_init(void)
0205 {
0206     return platform_driver_register(&lpass_cc_sc7280_driver);
0207 }
0208 subsys_initcall(lpass_cc_sc7280_init);
0209 
0210 static void __exit lpass_cc_sc7280_exit(void)
0211 {
0212     platform_driver_unregister(&lpass_cc_sc7280_driver);
0213 }
0214 module_exit(lpass_cc_sc7280_exit);
0215 
0216 MODULE_DESCRIPTION("QTI LPASS_CC SC7280 Driver");
0217 MODULE_LICENSE("GPL v2");