xref: /linux/drivers/clk/qcom/evacc-glymur.c (revision 502d45774af09f1c681c754c4b7cdfb5d7f72fd9)
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