1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
4 * Copyright (c) 2023, Linaro Limited
5 */
6
7 #include <linux/clk-provider.h>
8 #include <linux/mod_devicetable.h>
9 #include <linux/module.h>
10 #include <linux/platform_device.h>
11 #include <linux/regmap.h>
12
13 #include <dt-bindings/clock/qcom,x1e80100-tcsr.h>
14
15 #include "clk-branch.h"
16 #include "clk-regmap.h"
17 #include "common.h"
18 #include "reset.h"
19
20 enum {
21 DT_BI_TCXO_PAD,
22 };
23
24 static struct clk_branch tcsr_edp_clkref_en = {
25 .halt_reg = 0x15130,
26 .halt_check = BRANCH_HALT_DELAY,
27 .clkr = {
28 .enable_reg = 0x15130,
29 .enable_mask = BIT(0),
30 .hw.init = &(const struct clk_init_data) {
31 .name = "tcsr_edp_clkref_en",
32 .parent_data = &(const struct clk_parent_data){
33 .index = DT_BI_TCXO_PAD,
34 },
35 .num_parents = 1,
36 .ops = &clk_branch2_ops,
37 },
38 },
39 };
40
41 static struct clk_branch tcsr_pcie_2l_4_clkref_en = {
42 .halt_reg = 0x15100,
43 .halt_check = BRANCH_HALT_DELAY,
44 .clkr = {
45 .enable_reg = 0x15100,
46 .enable_mask = BIT(0),
47 .hw.init = &(struct clk_init_data){
48 .name = "tcsr_pcie_2l_4_clkref_en",
49 .parent_data = &(const struct clk_parent_data){
50 .index = DT_BI_TCXO_PAD,
51 },
52 .num_parents = 1,
53 .ops = &clk_branch2_ops,
54 },
55 },
56 };
57
58 static struct clk_branch tcsr_pcie_2l_5_clkref_en = {
59 .halt_reg = 0x15104,
60 .halt_check = BRANCH_HALT_DELAY,
61 .clkr = {
62 .enable_reg = 0x15104,
63 .enable_mask = BIT(0),
64 .hw.init = &(struct clk_init_data){
65 .name = "tcsr_pcie_2l_5_clkref_en",
66 .parent_data = &(const struct clk_parent_data){
67 .index = DT_BI_TCXO_PAD,
68 },
69 .num_parents = 1,
70 .ops = &clk_branch2_ops,
71 },
72 },
73 };
74
75 static struct clk_branch tcsr_pcie_8l_clkref_en = {
76 .halt_reg = 0x15108,
77 .halt_check = BRANCH_HALT_DELAY,
78 .clkr = {
79 .enable_reg = 0x15108,
80 .enable_mask = BIT(0),
81 .hw.init = &(struct clk_init_data){
82 .name = "tcsr_pcie_8l_clkref_en",
83 .parent_data = &(const struct clk_parent_data){
84 .index = DT_BI_TCXO_PAD,
85 },
86 .num_parents = 1,
87 .ops = &clk_branch2_ops,
88 },
89 },
90 };
91
92 static struct clk_branch tcsr_usb3_mp0_clkref_en = {
93 .halt_reg = 0x1510c,
94 .halt_check = BRANCH_HALT_DELAY,
95 .clkr = {
96 .enable_reg = 0x1510c,
97 .enable_mask = BIT(0),
98 .hw.init = &(struct clk_init_data){
99 .name = "tcsr_usb3_mp0_clkref_en",
100 .parent_data = &(const struct clk_parent_data){
101 .index = DT_BI_TCXO_PAD,
102 },
103 .num_parents = 1,
104 .ops = &clk_branch2_ops,
105 },
106 },
107 };
108
109 static struct clk_branch tcsr_usb3_mp1_clkref_en = {
110 .halt_reg = 0x15110,
111 .halt_check = BRANCH_HALT_DELAY,
112 .clkr = {
113 .enable_reg = 0x15110,
114 .enable_mask = BIT(0),
115 .hw.init = &(struct clk_init_data){
116 .name = "tcsr_usb3_mp1_clkref_en",
117 .parent_data = &(const struct clk_parent_data){
118 .index = DT_BI_TCXO_PAD,
119 },
120 .num_parents = 1,
121 .ops = &clk_branch2_ops,
122 },
123 },
124 };
125
126 static struct clk_branch tcsr_usb2_1_clkref_en = {
127 .halt_reg = 0x15114,
128 .halt_check = BRANCH_HALT_DELAY,
129 .clkr = {
130 .enable_reg = 0x15114,
131 .enable_mask = BIT(0),
132 .hw.init = &(struct clk_init_data){
133 .name = "tcsr_usb2_1_clkref_en",
134 .parent_data = &(const struct clk_parent_data){
135 .index = DT_BI_TCXO_PAD,
136 },
137 .num_parents = 1,
138 .ops = &clk_branch2_ops,
139 },
140 },
141 };
142
143 static struct clk_branch tcsr_ufs_phy_clkref_en = {
144 .halt_reg = 0x15118,
145 .halt_check = BRANCH_HALT_DELAY,
146 .clkr = {
147 .enable_reg = 0x15118,
148 .enable_mask = BIT(0),
149 .hw.init = &(struct clk_init_data){
150 .name = "tcsr_ufs_phy_clkref_en",
151 .parent_data = &(const struct clk_parent_data){
152 .index = DT_BI_TCXO_PAD,
153 },
154 .num_parents = 1,
155 .ops = &clk_branch2_ops,
156 },
157 },
158 };
159
160 static struct clk_branch tcsr_usb4_1_clkref_en = {
161 .halt_reg = 0x15120,
162 .halt_check = BRANCH_HALT_DELAY,
163 .clkr = {
164 .enable_reg = 0x15120,
165 .enable_mask = BIT(0),
166 .hw.init = &(struct clk_init_data){
167 .name = "tcsr_usb4_1_clkref_en",
168 .parent_data = &(const struct clk_parent_data){
169 .index = DT_BI_TCXO_PAD,
170 },
171 .num_parents = 1,
172 .ops = &clk_branch2_ops,
173 },
174 },
175 };
176
177 static struct clk_branch tcsr_usb4_2_clkref_en = {
178 .halt_reg = 0x15124,
179 .halt_check = BRANCH_HALT_DELAY,
180 .clkr = {
181 .enable_reg = 0x15124,
182 .enable_mask = BIT(0),
183 .hw.init = &(struct clk_init_data){
184 .name = "tcsr_usb4_2_clkref_en",
185 .parent_data = &(const struct clk_parent_data){
186 .index = DT_BI_TCXO_PAD,
187 },
188 .num_parents = 1,
189 .ops = &clk_branch2_ops,
190 },
191 },
192 };
193
194 static struct clk_branch tcsr_usb2_2_clkref_en = {
195 .halt_reg = 0x15128,
196 .halt_check = BRANCH_HALT_DELAY,
197 .clkr = {
198 .enable_reg = 0x15128,
199 .enable_mask = BIT(0),
200 .hw.init = &(struct clk_init_data){
201 .name = "tcsr_usb2_2_clkref_en",
202 .parent_data = &(const struct clk_parent_data){
203 .index = DT_BI_TCXO_PAD,
204 },
205 .num_parents = 1,
206 .ops = &clk_branch2_ops,
207 },
208 },
209 };
210
211 static struct clk_branch tcsr_pcie_4l_clkref_en = {
212 .halt_reg = 0x1512c,
213 .halt_check = BRANCH_HALT_DELAY,
214 .clkr = {
215 .enable_reg = 0x1512c,
216 .enable_mask = BIT(0),
217 .hw.init = &(struct clk_init_data){
218 .name = "tcsr_pcie_4l_clkref_en",
219 .parent_data = &(const struct clk_parent_data){
220 .index = DT_BI_TCXO_PAD,
221 },
222 .num_parents = 1,
223 .ops = &clk_branch2_ops,
224 },
225 },
226 };
227
228 static struct clk_regmap *tcsr_cc_x1e80100_clocks[] = {
229 [TCSR_EDP_CLKREF_EN] = &tcsr_edp_clkref_en.clkr,
230 [TCSR_PCIE_2L_4_CLKREF_EN] = &tcsr_pcie_2l_4_clkref_en.clkr,
231 [TCSR_PCIE_2L_5_CLKREF_EN] = &tcsr_pcie_2l_5_clkref_en.clkr,
232 [TCSR_PCIE_8L_CLKREF_EN] = &tcsr_pcie_8l_clkref_en.clkr,
233 [TCSR_USB3_MP0_CLKREF_EN] = &tcsr_usb3_mp0_clkref_en.clkr,
234 [TCSR_USB3_MP1_CLKREF_EN] = &tcsr_usb3_mp1_clkref_en.clkr,
235 [TCSR_USB2_1_CLKREF_EN] = &tcsr_usb2_1_clkref_en.clkr,
236 [TCSR_UFS_PHY_CLKREF_EN] = &tcsr_ufs_phy_clkref_en.clkr,
237 [TCSR_USB4_1_CLKREF_EN] = &tcsr_usb4_1_clkref_en.clkr,
238 [TCSR_USB4_2_CLKREF_EN] = &tcsr_usb4_2_clkref_en.clkr,
239 [TCSR_USB2_2_CLKREF_EN] = &tcsr_usb2_2_clkref_en.clkr,
240 [TCSR_PCIE_4L_CLKREF_EN] = &tcsr_pcie_4l_clkref_en.clkr,
241 };
242
243 static const struct regmap_config tcsr_cc_x1e80100_regmap_config = {
244 .reg_bits = 32,
245 .reg_stride = 4,
246 .val_bits = 32,
247 .max_register = 0x2f000,
248 .fast_io = true,
249 };
250
251 static const struct qcom_cc_desc tcsr_cc_x1e80100_desc = {
252 .config = &tcsr_cc_x1e80100_regmap_config,
253 .clks = tcsr_cc_x1e80100_clocks,
254 .num_clks = ARRAY_SIZE(tcsr_cc_x1e80100_clocks),
255 };
256
257 static const struct of_device_id tcsr_cc_x1e80100_match_table[] = {
258 { .compatible = "qcom,x1e80100-tcsr" },
259 { }
260 };
261 MODULE_DEVICE_TABLE(of, tcsr_cc_x1e80100_match_table);
262
tcsr_cc_x1e80100_probe(struct platform_device * pdev)263 static int tcsr_cc_x1e80100_probe(struct platform_device *pdev)
264 {
265 return qcom_cc_probe(pdev, &tcsr_cc_x1e80100_desc);
266 }
267
268 static struct platform_driver tcsr_cc_x1e80100_driver = {
269 .probe = tcsr_cc_x1e80100_probe,
270 .driver = {
271 .name = "tcsrcc-x1e80100",
272 .of_match_table = tcsr_cc_x1e80100_match_table,
273 },
274 };
275
tcsr_cc_x1e80100_init(void)276 static int __init tcsr_cc_x1e80100_init(void)
277 {
278 return platform_driver_register(&tcsr_cc_x1e80100_driver);
279 }
280 subsys_initcall(tcsr_cc_x1e80100_init);
281
tcsr_cc_x1e80100_exit(void)282 static void __exit tcsr_cc_x1e80100_exit(void)
283 {
284 platform_driver_unregister(&tcsr_cc_x1e80100_driver);
285 }
286 module_exit(tcsr_cc_x1e80100_exit);
287
288 MODULE_DESCRIPTION("QTI TCSR Clock Controller X1E80100 Driver");
289 MODULE_LICENSE("GPL");
290