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