1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (c) 2021, The Linux Foundation. All rights reserved. |
4 | * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. |
5 | * Copyright (c) 2022, Linaro Limited |
6 | */ |
7 | |
8 | #include <linux/clk-provider.h> |
9 | #include <linux/module.h> |
10 | #include <linux/of.h> |
11 | #include <linux/platform_device.h> |
12 | #include <linux/regmap.h> |
13 | |
14 | #include <dt-bindings/clock/qcom,sm8550-tcsr.h> |
15 | |
16 | #include "clk-alpha-pll.h" |
17 | #include "clk-branch.h" |
18 | #include "clk-pll.h" |
19 | #include "clk-rcg.h" |
20 | #include "clk-regmap.h" |
21 | #include "clk-regmap-divider.h" |
22 | #include "clk-regmap-mux.h" |
23 | #include "common.h" |
24 | #include "reset.h" |
25 | |
26 | enum { |
27 | DT_BI_TCXO_PAD, |
28 | }; |
29 | |
30 | static struct clk_branch tcsr_pcie_0_clkref_en = { |
31 | .halt_reg = 0x15100, |
32 | .halt_check = BRANCH_HALT_SKIP, |
33 | .clkr = { |
34 | .enable_reg = 0x15100, |
35 | .enable_mask = BIT(0), |
36 | .hw.init = &(struct clk_init_data){ |
37 | .name = "tcsr_pcie_0_clkref_en" , |
38 | .parent_data = &(const struct clk_parent_data){ |
39 | .index = DT_BI_TCXO_PAD, |
40 | }, |
41 | .num_parents = 1, |
42 | .ops = &clk_branch2_ops, |
43 | }, |
44 | }, |
45 | }; |
46 | |
47 | static struct clk_branch tcsr_pcie_1_clkref_en = { |
48 | .halt_reg = 0x15114, |
49 | .halt_check = BRANCH_HALT_SKIP, |
50 | .clkr = { |
51 | .enable_reg = 0x15114, |
52 | .enable_mask = BIT(0), |
53 | .hw.init = &(struct clk_init_data){ |
54 | .name = "tcsr_pcie_1_clkref_en" , |
55 | .parent_data = &(const struct clk_parent_data){ |
56 | .index = DT_BI_TCXO_PAD, |
57 | }, |
58 | .num_parents = 1, |
59 | .ops = &clk_branch2_ops, |
60 | }, |
61 | }, |
62 | }; |
63 | |
64 | static struct clk_branch tcsr_ufs_clkref_en = { |
65 | .halt_reg = 0x15110, |
66 | .halt_check = BRANCH_HALT_SKIP, |
67 | .clkr = { |
68 | .enable_reg = 0x15110, |
69 | .enable_mask = BIT(0), |
70 | .hw.init = &(struct clk_init_data){ |
71 | .name = "tcsr_ufs_clkref_en" , |
72 | .parent_data = &(const struct clk_parent_data){ |
73 | .index = DT_BI_TCXO_PAD, |
74 | }, |
75 | .num_parents = 1, |
76 | .ops = &clk_branch2_ops, |
77 | }, |
78 | }, |
79 | }; |
80 | |
81 | static struct clk_branch tcsr_ufs_pad_clkref_en = { |
82 | .halt_reg = 0x15104, |
83 | .halt_check = BRANCH_HALT_SKIP, |
84 | .clkr = { |
85 | .enable_reg = 0x15104, |
86 | .enable_mask = BIT(0), |
87 | .hw.init = &(struct clk_init_data){ |
88 | .name = "tcsr_ufs_pad_clkref_en" , |
89 | .parent_data = &(const struct clk_parent_data){ |
90 | .index = DT_BI_TCXO_PAD, |
91 | }, |
92 | .num_parents = 1, |
93 | .ops = &clk_branch2_ops, |
94 | }, |
95 | }, |
96 | }; |
97 | |
98 | static struct clk_branch tcsr_usb2_clkref_en = { |
99 | .halt_reg = 0x15118, |
100 | .halt_check = BRANCH_HALT_SKIP, |
101 | .clkr = { |
102 | .enable_reg = 0x15118, |
103 | .enable_mask = BIT(0), |
104 | .hw.init = &(struct clk_init_data){ |
105 | .name = "tcsr_usb2_clkref_en" , |
106 | .parent_data = &(const struct clk_parent_data){ |
107 | .index = DT_BI_TCXO_PAD, |
108 | }, |
109 | .num_parents = 1, |
110 | .ops = &clk_branch2_ops, |
111 | }, |
112 | }, |
113 | }; |
114 | |
115 | static struct clk_branch tcsr_usb3_clkref_en = { |
116 | .halt_reg = 0x15108, |
117 | .halt_check = BRANCH_HALT_SKIP, |
118 | .clkr = { |
119 | .enable_reg = 0x15108, |
120 | .enable_mask = BIT(0), |
121 | .hw.init = &(struct clk_init_data){ |
122 | .name = "tcsr_usb3_clkref_en" , |
123 | .parent_data = &(const struct clk_parent_data){ |
124 | .index = DT_BI_TCXO_PAD, |
125 | }, |
126 | .num_parents = 1, |
127 | .ops = &clk_branch2_ops, |
128 | }, |
129 | }, |
130 | }; |
131 | |
132 | static struct clk_regmap *tcsr_cc_sm8550_clocks[] = { |
133 | [TCSR_PCIE_0_CLKREF_EN] = &tcsr_pcie_0_clkref_en.clkr, |
134 | [TCSR_PCIE_1_CLKREF_EN] = &tcsr_pcie_1_clkref_en.clkr, |
135 | [TCSR_UFS_CLKREF_EN] = &tcsr_ufs_clkref_en.clkr, |
136 | [TCSR_UFS_PAD_CLKREF_EN] = &tcsr_ufs_pad_clkref_en.clkr, |
137 | [TCSR_USB2_CLKREF_EN] = &tcsr_usb2_clkref_en.clkr, |
138 | [TCSR_USB3_CLKREF_EN] = &tcsr_usb3_clkref_en.clkr, |
139 | }; |
140 | |
141 | static const struct regmap_config tcsr_cc_sm8550_regmap_config = { |
142 | .reg_bits = 32, |
143 | .reg_stride = 4, |
144 | .val_bits = 32, |
145 | .max_register = 0x2f000, |
146 | .fast_io = true, |
147 | }; |
148 | |
149 | static const struct qcom_cc_desc tcsr_cc_sm8550_desc = { |
150 | .config = &tcsr_cc_sm8550_regmap_config, |
151 | .clks = tcsr_cc_sm8550_clocks, |
152 | .num_clks = ARRAY_SIZE(tcsr_cc_sm8550_clocks), |
153 | }; |
154 | |
155 | static const struct of_device_id tcsr_cc_sm8550_match_table[] = { |
156 | { .compatible = "qcom,sm8550-tcsr" }, |
157 | { } |
158 | }; |
159 | MODULE_DEVICE_TABLE(of, tcsr_cc_sm8550_match_table); |
160 | |
161 | static int tcsr_cc_sm8550_probe(struct platform_device *pdev) |
162 | { |
163 | struct regmap *regmap; |
164 | |
165 | regmap = qcom_cc_map(pdev, desc: &tcsr_cc_sm8550_desc); |
166 | if (IS_ERR(ptr: regmap)) |
167 | return PTR_ERR(ptr: regmap); |
168 | |
169 | return qcom_cc_really_probe(pdev, desc: &tcsr_cc_sm8550_desc, regmap); |
170 | } |
171 | |
172 | static struct platform_driver tcsr_cc_sm8550_driver = { |
173 | .probe = tcsr_cc_sm8550_probe, |
174 | .driver = { |
175 | .name = "tcsr_cc-sm8550" , |
176 | .of_match_table = tcsr_cc_sm8550_match_table, |
177 | }, |
178 | }; |
179 | |
180 | static int __init tcsr_cc_sm8550_init(void) |
181 | { |
182 | return platform_driver_register(&tcsr_cc_sm8550_driver); |
183 | } |
184 | subsys_initcall(tcsr_cc_sm8550_init); |
185 | |
186 | static void __exit tcsr_cc_sm8550_exit(void) |
187 | { |
188 | platform_driver_unregister(&tcsr_cc_sm8550_driver); |
189 | } |
190 | module_exit(tcsr_cc_sm8550_exit); |
191 | |
192 | MODULE_DESCRIPTION("QTI TCSRCC SM8550 Driver" ); |
193 | MODULE_LICENSE("GPL" ); |
194 | |