1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
4 */
5
6 #include <linux/clk-provider.h>
7 #include <linux/module.h>
8 #include <linux/of.h>
9 #include <linux/platform_device.h>
10 #include <linux/regmap.h>
11
12 #include <dt-bindings/clock/qcom,glymur-evacc.h>
13
14 #include "clk-alpha-pll.h"
15 #include "clk-branch.h"
16 #include "clk-pll.h"
17 #include "clk-rcg.h"
18 #include "clk-regmap.h"
19 #include "clk-regmap-divider.h"
20 #include "clk-regmap-mux.h"
21 #include "common.h"
22 #include "gdsc.h"
23 #include "reset.h"
24
25 enum {
26 DT_AHB_CLK,
27 DT_BI_TCXO,
28 DT_SLEEP_CLK,
29 };
30
31 enum {
32 P_BI_TCXO,
33 P_EVA_CC_PLL0_OUT_MAIN,
34 P_SLEEP_CLK,
35 };
36
37 static const struct pll_vco taycan_eko_t_vco[] = {
38 { 249600000, 2500000000, 0 },
39 };
40
41 /* 840.0 MHz Configuration */
42 static const struct alpha_pll_config eva_cc_pll0_config = {
43 .l = 0x2b,
44 .alpha = 0xc000,
45 .config_ctl_val = 0x25c400e7,
46 .config_ctl_hi_val = 0x0a8060e0,
47 .config_ctl_hi1_val = 0xf51dea20,
48 .user_ctl_val = 0x00000008,
49 .user_ctl_hi_val = 0x00000002,
50 };
51
52 static struct clk_alpha_pll eva_cc_pll0 = {
53 .offset = 0x0,
54 .config = &eva_cc_pll0_config,
55 .vco_table = taycan_eko_t_vco,
56 .num_vco = ARRAY_SIZE(taycan_eko_t_vco),
57 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_EKO_T],
58 .clkr = {
59 .hw.init = &(const struct clk_init_data) {
60 .name = "eva_cc_pll0",
61 .parent_data = &(const struct clk_parent_data) {
62 .index = DT_BI_TCXO,
63 },
64 .num_parents = 1,
65 .ops = &clk_alpha_pll_taycan_eko_t_ops,
66 },
67 },
68 };
69
70 static const struct parent_map eva_cc_parent_map_0[] = {
71 { P_BI_TCXO, 0 },
72 };
73
74 static const struct clk_parent_data eva_cc_parent_data_0[] = {
75 { .index = DT_BI_TCXO },
76 };
77
78 static const struct parent_map eva_cc_parent_map_1[] = {
79 { P_BI_TCXO, 0 },
80 { P_EVA_CC_PLL0_OUT_MAIN, 1 },
81 };
82
83 static const struct clk_parent_data eva_cc_parent_data_1[] = {
84 { .index = DT_BI_TCXO },
85 { .hw = &eva_cc_pll0.clkr.hw },
86 };
87
88 static const struct parent_map eva_cc_parent_map_2[] = {
89 { P_SLEEP_CLK, 0 },
90 };
91
92 static const struct clk_parent_data eva_cc_parent_data_2[] = {
93 { .index = DT_SLEEP_CLK },
94 };
95
96 static const struct freq_tbl ftbl_eva_cc_ahb_clk_src[] = {
97 F(19200000, P_BI_TCXO, 1, 0, 0),
98 { }
99 };
100
101 static struct clk_rcg2 eva_cc_ahb_clk_src = {
102 .cmd_rcgr = 0x8018,
103 .mnd_width = 0,
104 .hid_width = 5,
105 .parent_map = eva_cc_parent_map_0,
106 .freq_tbl = ftbl_eva_cc_ahb_clk_src,
107 .hw_clk_ctrl = true,
108 .clkr = {
109 .hw.init = &(const struct clk_init_data) {
110 .name = "eva_cc_ahb_clk_src",
111 .parent_data = eva_cc_parent_data_0,
112 .num_parents = ARRAY_SIZE(eva_cc_parent_data_0),
113 .flags = CLK_SET_RATE_PARENT,
114 .ops = &clk_rcg2_shared_ops,
115 },
116 },
117 };
118
119 static const struct freq_tbl ftbl_eva_cc_mvs0_clk_src[] = {
120 F(840000000, P_EVA_CC_PLL0_OUT_MAIN, 1, 0, 0),
121 F(1050000000, P_EVA_CC_PLL0_OUT_MAIN, 1, 0, 0),
122 F(1350000000, P_EVA_CC_PLL0_OUT_MAIN, 1, 0, 0),
123 F(1500000000, P_EVA_CC_PLL0_OUT_MAIN, 1, 0, 0),
124 F(1650000000, P_EVA_CC_PLL0_OUT_MAIN, 1, 0, 0),
125 { }
126 };
127
128 static struct clk_rcg2 eva_cc_mvs0_clk_src = {
129 .cmd_rcgr = 0x8000,
130 .mnd_width = 0,
131 .hid_width = 5,
132 .parent_map = eva_cc_parent_map_1,
133 .freq_tbl = ftbl_eva_cc_mvs0_clk_src,
134 .hw_clk_ctrl = true,
135 .clkr = {
136 .hw.init = &(const struct clk_init_data) {
137 .name = "eva_cc_mvs0_clk_src",
138 .parent_data = eva_cc_parent_data_1,
139 .num_parents = ARRAY_SIZE(eva_cc_parent_data_1),
140 .flags = CLK_SET_RATE_PARENT,
141 .ops = &clk_rcg2_shared_ops,
142 },
143 },
144 };
145
146 static const struct freq_tbl ftbl_eva_cc_sleep_clk_src[] = {
147 F(32000, P_SLEEP_CLK, 1, 0, 0),
148 { }
149 };
150
151 static struct clk_rcg2 eva_cc_sleep_clk_src = {
152 .cmd_rcgr = 0x80e0,
153 .mnd_width = 0,
154 .hid_width = 5,
155 .parent_map = eva_cc_parent_map_2,
156 .freq_tbl = ftbl_eva_cc_sleep_clk_src,
157 .hw_clk_ctrl = true,
158 .clkr = {
159 .hw.init = &(const struct clk_init_data) {
160 .name = "eva_cc_sleep_clk_src",
161 .parent_data = eva_cc_parent_data_2,
162 .num_parents = ARRAY_SIZE(eva_cc_parent_data_2),
163 .flags = CLK_SET_RATE_PARENT,
164 .ops = &clk_rcg2_shared_ops,
165 },
166 },
167 };
168
169 static struct clk_rcg2 eva_cc_xo_clk_src = {
170 .cmd_rcgr = 0x80bc,
171 .mnd_width = 0,
172 .hid_width = 5,
173 .parent_map = eva_cc_parent_map_0,
174 .freq_tbl = ftbl_eva_cc_ahb_clk_src,
175 .hw_clk_ctrl = true,
176 .clkr = {
177 .hw.init = &(const struct clk_init_data) {
178 .name = "eva_cc_xo_clk_src",
179 .parent_data = eva_cc_parent_data_0,
180 .num_parents = ARRAY_SIZE(eva_cc_parent_data_0),
181 .flags = CLK_SET_RATE_PARENT,
182 .ops = &clk_rcg2_shared_ops,
183 },
184 },
185 };
186
187 static struct clk_regmap_div eva_cc_mvs0_div_clk_src = {
188 .reg = 0x809c,
189 .shift = 0,
190 .width = 4,
191 .clkr.hw.init = &(const struct clk_init_data) {
192 .name = "eva_cc_mvs0_div_clk_src",
193 .parent_hws = (const struct clk_hw*[]) {
194 &eva_cc_mvs0_clk_src.clkr.hw,
195 },
196 .num_parents = 1,
197 .flags = CLK_SET_RATE_PARENT,
198 .ops = &clk_regmap_div_ro_ops,
199 },
200 };
201
202 static struct clk_regmap_div eva_cc_mvs0c_div2_div_clk_src = {
203 .reg = 0x8060,
204 .shift = 0,
205 .width = 4,
206 .clkr.hw.init = &(const struct clk_init_data) {
207 .name = "eva_cc_mvs0c_div2_div_clk_src",
208 .parent_hws = (const struct clk_hw*[]) {
209 &eva_cc_mvs0_clk_src.clkr.hw,
210 },
211 .num_parents = 1,
212 .flags = CLK_SET_RATE_PARENT,
213 .ops = &clk_regmap_div_ro_ops,
214 },
215 };
216
217 static struct clk_branch eva_cc_mvs0_clk = {
218 .halt_reg = 0x807c,
219 .halt_check = BRANCH_HALT_VOTED,
220 .hwcg_reg = 0x807c,
221 .hwcg_bit = 1,
222 .clkr = {
223 .enable_reg = 0x807c,
224 .enable_mask = BIT(0),
225 .hw.init = &(const struct clk_init_data) {
226 .name = "eva_cc_mvs0_clk",
227 .parent_hws = (const struct clk_hw*[]) {
228 &eva_cc_mvs0_div_clk_src.clkr.hw,
229 },
230 .num_parents = 1,
231 .flags = CLK_SET_RATE_PARENT,
232 .ops = &clk_branch2_ops,
233 },
234 },
235 };
236
237 static struct clk_branch eva_cc_mvs0_freerun_clk = {
238 .halt_reg = 0x808c,
239 .halt_check = BRANCH_HALT,
240 .clkr = {
241 .enable_reg = 0x808c,
242 .enable_mask = BIT(0),
243 .hw.init = &(const struct clk_init_data) {
244 .name = "eva_cc_mvs0_freerun_clk",
245 .parent_hws = (const struct clk_hw*[]) {
246 &eva_cc_mvs0_div_clk_src.clkr.hw,
247 },
248 .num_parents = 1,
249 .flags = CLK_SET_RATE_PARENT,
250 .ops = &clk_branch2_ops,
251 },
252 },
253 };
254
255 static struct clk_branch eva_cc_mvs0_shift_clk = {
256 .halt_reg = 0x80d8,
257 .halt_check = BRANCH_HALT_VOTED,
258 .hwcg_reg = 0x80d8,
259 .hwcg_bit = 1,
260 .clkr = {
261 .enable_reg = 0x80d8,
262 .enable_mask = BIT(0),
263 .hw.init = &(const struct clk_init_data) {
264 .name = "eva_cc_mvs0_shift_clk",
265 .parent_hws = (const struct clk_hw*[]) {
266 &eva_cc_xo_clk_src.clkr.hw,
267 },
268 .num_parents = 1,
269 .flags = CLK_SET_RATE_PARENT,
270 .ops = &clk_branch2_ops,
271 },
272 },
273 };
274
275 static struct clk_branch eva_cc_mvs0c_clk = {
276 .halt_reg = 0x804c,
277 .halt_check = BRANCH_HALT,
278 .clkr = {
279 .enable_reg = 0x804c,
280 .enable_mask = BIT(0),
281 .hw.init = &(const struct clk_init_data) {
282 .name = "eva_cc_mvs0c_clk",
283 .parent_hws = (const struct clk_hw*[]) {
284 &eva_cc_mvs0c_div2_div_clk_src.clkr.hw,
285 },
286 .num_parents = 1,
287 .flags = CLK_SET_RATE_PARENT,
288 .ops = &clk_branch2_ops,
289 },
290 },
291 };
292
293 static struct clk_branch eva_cc_mvs0c_freerun_clk = {
294 .halt_reg = 0x805c,
295 .halt_check = BRANCH_HALT,
296 .clkr = {
297 .enable_reg = 0x805c,
298 .enable_mask = BIT(0),
299 .hw.init = &(const struct clk_init_data) {
300 .name = "eva_cc_mvs0c_freerun_clk",
301 .parent_hws = (const struct clk_hw*[]) {
302 &eva_cc_mvs0c_div2_div_clk_src.clkr.hw,
303 },
304 .num_parents = 1,
305 .flags = CLK_SET_RATE_PARENT,
306 .ops = &clk_branch2_ops,
307 },
308 },
309 };
310
311 static struct clk_branch eva_cc_mvs0c_shift_clk = {
312 .halt_reg = 0x80dc,
313 .halt_check = BRANCH_HALT_VOTED,
314 .hwcg_reg = 0x80dc,
315 .hwcg_bit = 1,
316 .clkr = {
317 .enable_reg = 0x80dc,
318 .enable_mask = BIT(0),
319 .hw.init = &(const struct clk_init_data) {
320 .name = "eva_cc_mvs0c_shift_clk",
321 .parent_hws = (const struct clk_hw*[]) {
322 &eva_cc_xo_clk_src.clkr.hw,
323 },
324 .num_parents = 1,
325 .flags = CLK_SET_RATE_PARENT,
326 .ops = &clk_branch2_ops,
327 },
328 },
329 };
330
331 static struct gdsc eva_cc_mvs0c_gdsc = {
332 .gdscr = 0x8034,
333 .en_rest_wait_val = 0x2,
334 .en_few_wait_val = 0x2,
335 .clk_dis_wait_val = 0x6,
336 .pd = {
337 .name = "eva_cc_mvs0c_gdsc",
338 },
339 .pwrsts = PWRSTS_OFF_ON,
340 .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
341 };
342
343 static struct gdsc eva_cc_mvs0_gdsc = {
344 .gdscr = 0x8068,
345 .en_rest_wait_val = 0x2,
346 .en_few_wait_val = 0x2,
347 .clk_dis_wait_val = 0x6,
348 .pd = {
349 .name = "eva_cc_mvs0_gdsc",
350 },
351 .pwrsts = PWRSTS_OFF_ON,
352 .flags = HW_CTRL_TRIGGER | POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
353 .parent = &eva_cc_mvs0c_gdsc.pd,
354 };
355
356 static struct clk_regmap *eva_cc_glymur_clocks[] = {
357 [EVA_CC_AHB_CLK_SRC] = &eva_cc_ahb_clk_src.clkr,
358 [EVA_CC_MVS0_CLK] = &eva_cc_mvs0_clk.clkr,
359 [EVA_CC_MVS0_CLK_SRC] = &eva_cc_mvs0_clk_src.clkr,
360 [EVA_CC_MVS0_DIV_CLK_SRC] = &eva_cc_mvs0_div_clk_src.clkr,
361 [EVA_CC_MVS0_FREERUN_CLK] = &eva_cc_mvs0_freerun_clk.clkr,
362 [EVA_CC_MVS0_SHIFT_CLK] = &eva_cc_mvs0_shift_clk.clkr,
363 [EVA_CC_MVS0C_CLK] = &eva_cc_mvs0c_clk.clkr,
364 [EVA_CC_MVS0C_DIV2_DIV_CLK_SRC] = &eva_cc_mvs0c_div2_div_clk_src.clkr,
365 [EVA_CC_MVS0C_FREERUN_CLK] = &eva_cc_mvs0c_freerun_clk.clkr,
366 [EVA_CC_MVS0C_SHIFT_CLK] = &eva_cc_mvs0c_shift_clk.clkr,
367 [EVA_CC_PLL0] = &eva_cc_pll0.clkr,
368 [EVA_CC_SLEEP_CLK_SRC] = &eva_cc_sleep_clk_src.clkr,
369 [EVA_CC_XO_CLK_SRC] = &eva_cc_xo_clk_src.clkr,
370 };
371
372 static struct gdsc *eva_cc_glymur_gdscs[] = {
373 [EVA_CC_MVS0_GDSC] = &eva_cc_mvs0_gdsc,
374 [EVA_CC_MVS0C_GDSC] = &eva_cc_mvs0c_gdsc,
375 };
376
377 static const struct qcom_reset_map eva_cc_glymur_resets[] = {
378 [EVA_CC_INTERFACE_BCR] = { 0x80a0 },
379 [EVA_CC_MVS0_BCR] = { 0x8064 },
380 [EVA_CC_MVS0C_CLK_ARES] = { 0x804c, 2 },
381 [EVA_CC_MVS0C_BCR] = { 0x8030 },
382 [EVA_CC_MVS0C_FREERUN_CLK_ARES] = { 0x805c, 2 },
383 };
384
385 static struct clk_alpha_pll *eva_cc_glymur_plls[] = {
386 &eva_cc_pll0,
387 };
388
389 static const u32 eva_cc_glymur_critical_cbcrs[] = {
390 0x80a4, /* EVA_CC_AHB_CLK */
391 0x80f8, /* EVA_CC_SLEEP_CLK */
392 0x80d4, /* EVA_CC_XO_CLK */
393 };
394
395 static const struct regmap_config eva_cc_glymur_regmap_config = {
396 .reg_bits = 32,
397 .reg_stride = 4,
398 .val_bits = 32,
399 .max_register = 0x9f50,
400 .fast_io = true,
401 };
402
clk_glymur_regs_configure(struct device * dev,struct regmap * regmap)403 static void clk_glymur_regs_configure(struct device *dev, struct regmap *regmap)
404 {
405 /*
406 * Update CTRL_IN register as per HW recommendation to ensure clocks
407 * stay cycle‑aligned when the EVA core is ON.
408 */
409 regmap_set_bits(regmap, 0x9f24, BIT(0));
410 }
411
412 static const struct qcom_cc_driver_data eva_cc_glymur_driver_data = {
413 .alpha_plls = eva_cc_glymur_plls,
414 .num_alpha_plls = ARRAY_SIZE(eva_cc_glymur_plls),
415 .clk_cbcrs = eva_cc_glymur_critical_cbcrs,
416 .num_clk_cbcrs = ARRAY_SIZE(eva_cc_glymur_critical_cbcrs),
417 .clk_regs_configure = clk_glymur_regs_configure,
418 };
419
420 static const struct qcom_cc_desc eva_cc_glymur_desc = {
421 .config = &eva_cc_glymur_regmap_config,
422 .clks = eva_cc_glymur_clocks,
423 .num_clks = ARRAY_SIZE(eva_cc_glymur_clocks),
424 .resets = eva_cc_glymur_resets,
425 .num_resets = ARRAY_SIZE(eva_cc_glymur_resets),
426 .gdscs = eva_cc_glymur_gdscs,
427 .num_gdscs = ARRAY_SIZE(eva_cc_glymur_gdscs),
428 .use_rpm = true,
429 .driver_data = &eva_cc_glymur_driver_data,
430 };
431
432 static const struct of_device_id eva_cc_glymur_match_table[] = {
433 { .compatible = "qcom,glymur-evacc" },
434 { }
435 };
436 MODULE_DEVICE_TABLE(of, eva_cc_glymur_match_table);
437
eva_cc_glymur_probe(struct platform_device * pdev)438 static int eva_cc_glymur_probe(struct platform_device *pdev)
439 {
440 return qcom_cc_probe(pdev, &eva_cc_glymur_desc);
441 }
442
443 static struct platform_driver eva_cc_glymur_driver = {
444 .probe = eva_cc_glymur_probe,
445 .driver = {
446 .name = "evacc-glymur",
447 .of_match_table = eva_cc_glymur_match_table,
448 },
449 };
450
451 module_platform_driver(eva_cc_glymur_driver);
452
453 MODULE_DESCRIPTION("QTI EVACC Glymur Driver");
454 MODULE_LICENSE("GPL");
455