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
20enum {
21 DT_BI_TCXO_PAD,
22};
23
24static 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
37static 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
54static 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
71static 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
88static 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
105static 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
122static 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
139static 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
156static 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
173static 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
190static 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
207static 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
224static 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
239static 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
247static 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
253static const struct of_device_id tcsr_cc_x1e80100_match_table[] = {
254 { .compatible = "qcom,x1e80100-tcsr" },
255 { }
256};
257MODULE_DEVICE_TABLE(of, tcsr_cc_x1e80100_match_table);
258
259static int tcsr_cc_x1e80100_probe(struct platform_device *pdev)
260{
261 return qcom_cc_probe(pdev, desc: &tcsr_cc_x1e80100_desc);
262}
263
264static 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
272static int __init tcsr_cc_x1e80100_init(void)
273{
274 return platform_driver_register(&tcsr_cc_x1e80100_driver);
275}
276subsys_initcall(tcsr_cc_x1e80100_init);
277
278static void __exit tcsr_cc_x1e80100_exit(void)
279{
280 platform_driver_unregister(&tcsr_cc_x1e80100_driver);
281}
282module_exit(tcsr_cc_x1e80100_exit);
283
284MODULE_DESCRIPTION("QTI TCSR Clock Controller X1E80100 Driver");
285MODULE_LICENSE("GPL");
286

source code of linux/drivers/clk/qcom/tcsrcc-x1e80100.c