1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
6 #include <linux/bitops.h>
8 #include <linux/module.h>
9 #include <linux/platform_device.h>
10 #include <linux/pm_clock.h>
11 #include <linux/pm_runtime.h>
12 #include <linux/regmap.h>
14 #include <dt-bindings/clock/qcom,q6sstopcc-qcs404.h>
16 #include "clk-regmap.h"
17 #include "clk-branch.h"
21 static struct clk_branch lcc_ahbfabric_cbc_clk
= {
23 .halt_check
= BRANCH_HALT
,
25 .enable_reg
= 0x1b004,
26 .enable_mask
= BIT(0),
27 .hw
.init
= &(struct clk_init_data
){
28 .name
= "lcc_ahbfabric_cbc_clk",
29 .ops
= &clk_branch2_ops
,
34 static struct clk_branch lcc_q6ss_ahbs_cbc_clk
= {
36 .halt_check
= BRANCH_VOTED
,
38 .enable_reg
= 0x22000,
39 .enable_mask
= BIT(0),
40 .hw
.init
= &(struct clk_init_data
){
41 .name
= "lcc_q6ss_ahbs_cbc_clk",
42 .ops
= &clk_branch2_ops
,
47 static struct clk_branch lcc_q6ss_tcm_slave_cbc_clk
= {
49 .halt_check
= BRANCH_VOTED
,
51 .enable_reg
= 0x1c000,
52 .enable_mask
= BIT(0),
53 .hw
.init
= &(struct clk_init_data
){
54 .name
= "lcc_q6ss_tcm_slave_cbc_clk",
55 .ops
= &clk_branch2_ops
,
60 static struct clk_branch lcc_q6ss_ahbm_cbc_clk
= {
62 .halt_check
= BRANCH_VOTED
,
64 .enable_reg
= 0x22004,
65 .enable_mask
= BIT(0),
66 .hw
.init
= &(struct clk_init_data
){
67 .name
= "lcc_q6ss_ahbm_cbc_clk",
68 .ops
= &clk_branch2_ops
,
73 static struct clk_branch lcc_q6ss_axim_cbc_clk
= {
75 .halt_check
= BRANCH_VOTED
,
77 .enable_reg
= 0x1c004,
78 .enable_mask
= BIT(0),
79 .hw
.init
= &(struct clk_init_data
){
80 .name
= "lcc_q6ss_axim_cbc_clk",
81 .ops
= &clk_branch2_ops
,
86 static struct clk_branch lcc_q6ss_bcr_sleep_clk
= {
88 .halt_check
= BRANCH_VOTED
,
91 .enable_mask
= BIT(0),
92 .hw
.init
= &(struct clk_init_data
){
93 .name
= "lcc_q6ss_bcr_sleep_clk",
94 .ops
= &clk_branch2_ops
,
100 static struct clk_branch tcsr_lcc_csr_cbcr_clk
= {
102 .halt_check
= BRANCH_VOTED
,
104 .enable_reg
= 0x8008,
105 .enable_mask
= BIT(0),
106 .hw
.init
= &(struct clk_init_data
){
107 .name
= "tcsr_lcc_csr_cbcr_clk",
108 .ops
= &clk_branch2_ops
,
113 static struct regmap_config q6sstop_regmap_config
= {
120 static struct clk_regmap
*q6sstop_qcs404_clocks
[] = {
121 [LCC_AHBFABRIC_CBC_CLK
] = &lcc_ahbfabric_cbc_clk
.clkr
,
122 [LCC_Q6SS_AHBS_CBC_CLK
] = &lcc_q6ss_ahbs_cbc_clk
.clkr
,
123 [LCC_Q6SS_TCM_SLAVE_CBC_CLK
] = &lcc_q6ss_tcm_slave_cbc_clk
.clkr
,
124 [LCC_Q6SS_AHBM_CBC_CLK
] = &lcc_q6ss_ahbm_cbc_clk
.clkr
,
125 [LCC_Q6SS_AXIM_CBC_CLK
] = &lcc_q6ss_axim_cbc_clk
.clkr
,
126 [LCC_Q6SS_BCR_SLEEP_CLK
] = &lcc_q6ss_bcr_sleep_clk
.clkr
,
129 static const struct qcom_reset_map q6sstop_qcs404_resets
[] = {
130 [Q6SSTOP_BCR_RESET
] = { 0x6000 },
133 static const struct qcom_cc_desc q6sstop_qcs404_desc
= {
134 .config
= &q6sstop_regmap_config
,
135 .clks
= q6sstop_qcs404_clocks
,
136 .num_clks
= ARRAY_SIZE(q6sstop_qcs404_clocks
),
137 .resets
= q6sstop_qcs404_resets
,
138 .num_resets
= ARRAY_SIZE(q6sstop_qcs404_resets
),
141 static struct clk_regmap
*tcsr_qcs404_clocks
[] = {
142 [TCSR_Q6SS_LCC_CBCR_CLK
] = &tcsr_lcc_csr_cbcr_clk
.clkr
,
145 static const struct qcom_cc_desc tcsr_qcs404_desc
= {
146 .config
= &q6sstop_regmap_config
,
147 .clks
= tcsr_qcs404_clocks
,
148 .num_clks
= ARRAY_SIZE(tcsr_qcs404_clocks
),
151 static const struct of_device_id q6sstopcc_qcs404_match_table
[] = {
152 { .compatible
= "qcom,qcs404-q6sstopcc" },
155 MODULE_DEVICE_TABLE(of
, q6sstopcc_qcs404_match_table
);
157 static int q6sstopcc_qcs404_probe(struct platform_device
*pdev
)
159 const struct qcom_cc_desc
*desc
;
162 pm_runtime_enable(&pdev
->dev
);
163 ret
= pm_clk_create(&pdev
->dev
);
165 goto disable_pm_runtime
;
167 ret
= pm_clk_add(&pdev
->dev
, NULL
);
169 dev_err(&pdev
->dev
, "failed to acquire iface clock\n");
173 q6sstop_regmap_config
.name
= "q6sstop_tcsr";
174 desc
= &tcsr_qcs404_desc
;
176 ret
= qcom_cc_probe_by_index(pdev
, 1, desc
);
180 q6sstop_regmap_config
.name
= "q6sstop_cc";
181 desc
= &q6sstop_qcs404_desc
;
183 ret
= qcom_cc_probe_by_index(pdev
, 0, desc
);
190 pm_clk_destroy(&pdev
->dev
);
193 pm_runtime_disable(&pdev
->dev
);
198 static int q6sstopcc_qcs404_remove(struct platform_device
*pdev
)
200 pm_clk_destroy(&pdev
->dev
);
201 pm_runtime_disable(&pdev
->dev
);
206 static const struct dev_pm_ops q6sstopcc_pm_ops
= {
207 SET_RUNTIME_PM_OPS(pm_clk_suspend
, pm_clk_resume
, NULL
)
210 static struct platform_driver q6sstopcc_qcs404_driver
= {
211 .probe
= q6sstopcc_qcs404_probe
,
212 .remove
= q6sstopcc_qcs404_remove
,
214 .name
= "qcs404-q6sstopcc",
215 .of_match_table
= q6sstopcc_qcs404_match_table
,
216 .pm
= &q6sstopcc_pm_ops
,
220 module_platform_driver(q6sstopcc_qcs404_driver
);
222 MODULE_DESCRIPTION("QTI QCS404 Q6SSTOP Clock Controller Driver");
223 MODULE_LICENSE("GPL v2");