a2f1e6ad6da40432d704925f0904dc5af002a26b
[releases.git] / lpasscorecc-sc7280.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
4  */
5
6 #include <linux/clk-provider.h>
7 #include <linux/err.h>
8 #include <linux/module.h>
9 #include <linux/of.h>
10 #include <linux/platform_device.h>
11 #include <linux/pm_clock.h>
12 #include <linux/pm_runtime.h>
13 #include <linux/regmap.h>
14
15 #include <dt-bindings/clock/qcom,lpasscorecc-sc7280.h>
16
17 #include "clk-alpha-pll.h"
18 #include "clk-branch.h"
19 #include "clk-rcg.h"
20 #include "clk-regmap.h"
21 #include "clk-regmap-divider.h"
22 #include "common.h"
23 #include "gdsc.h"
24
25 enum {
26         P_BI_TCXO,
27         P_LPASS_CORE_CC_DIG_PLL_OUT_MAIN,
28         P_LPASS_CORE_CC_DIG_PLL_OUT_MAIN_DIV_CLK_SRC,
29         P_LPASS_CORE_CC_DIG_PLL_OUT_ODD,
30 };
31
32 static const struct pll_vco lucid_vco[] = {
33         { 249600000, 2000000000, 0 },
34 };
35
36 /* 614.4MHz configuration */
37 static const struct alpha_pll_config lpass_core_cc_dig_pll_config = {
38         .l = 0x20,
39         .alpha = 0x0,
40         .config_ctl_val = 0x20485699,
41         .config_ctl_hi_val = 0x00002261,
42         .config_ctl_hi1_val = 0xB2923BBC,
43         .user_ctl_val = 0x00005100,
44         .user_ctl_hi_val = 0x00050805,
45         .user_ctl_hi1_val = 0x00000000,
46 };
47
48 static struct clk_alpha_pll lpass_core_cc_dig_pll = {
49         .offset = 0x1000,
50         .vco_table = lucid_vco,
51         .num_vco = ARRAY_SIZE(lucid_vco),
52         .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
53         .clkr = {
54                 .hw.init = &(struct clk_init_data){
55                         .name = "lpass_core_cc_dig_pll",
56                         .parent_data = &(const struct clk_parent_data){
57                                 .index = 0,
58                         },
59                         .num_parents = 1,
60                         .ops = &clk_alpha_pll_lucid_ops,
61                 },
62         },
63 };
64
65 static const struct clk_div_table post_div_table_lpass_core_cc_dig_pll_out_odd[] = {
66         { 0x5, 5 },
67         { }
68 };
69
70 static struct clk_alpha_pll_postdiv lpass_core_cc_dig_pll_out_odd = {
71         .offset = 0x1000,
72         .post_div_shift = 12,
73         .post_div_table = post_div_table_lpass_core_cc_dig_pll_out_odd,
74         .num_post_div = ARRAY_SIZE(post_div_table_lpass_core_cc_dig_pll_out_odd),
75         .width = 4,
76         .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
77         .clkr.hw.init = &(struct clk_init_data){
78                 .name = "lpass_core_cc_dig_pll_out_odd",
79                 .parent_hws = (const struct clk_hw*[]){
80                         &lpass_core_cc_dig_pll.clkr.hw,
81                 },
82                 .num_parents = 1,
83                 .flags = CLK_SET_RATE_PARENT,
84                 .ops = &clk_alpha_pll_postdiv_lucid_ops,
85         },
86 };
87
88 static struct clk_regmap_div lpass_core_cc_dig_pll_out_main_div_clk_src = {
89         .reg = 0x1054,
90         .shift = 0,
91         .width = 4,
92         .clkr.hw.init = &(struct clk_init_data) {
93                 .name = "lpass_core_cc_dig_pll_out_main_div_clk_src",
94                 .parent_hws = (const struct clk_hw*[]){
95                         &lpass_core_cc_dig_pll.clkr.hw,
96                 },
97                 .num_parents = 1,
98                 .flags = CLK_SET_RATE_PARENT,
99                 .ops = &clk_regmap_div_ro_ops,
100         },
101 };
102
103
104 static const struct parent_map lpass_core_cc_parent_map_0[] = {
105         { P_BI_TCXO, 0 },
106         { P_LPASS_CORE_CC_DIG_PLL_OUT_ODD, 5 },
107 };
108
109 static const struct clk_parent_data lpass_core_cc_parent_data_0[] = {
110         { .index = 0 },
111         { .hw = &lpass_core_cc_dig_pll_out_odd.clkr.hw },
112 };
113
114 static const struct parent_map lpass_core_cc_parent_map_2[] = {
115         { P_BI_TCXO, 0 },
116         { P_LPASS_CORE_CC_DIG_PLL_OUT_MAIN, 1 },
117         { P_LPASS_CORE_CC_DIG_PLL_OUT_MAIN_DIV_CLK_SRC, 2 },
118 };
119
120 static const struct clk_parent_data lpass_core_cc_parent_data_ao_2[] = {
121         { .index = 1 },
122         { .hw = &lpass_core_cc_dig_pll.clkr.hw },
123         { .hw = &lpass_core_cc_dig_pll_out_main_div_clk_src.clkr.hw },
124 };
125
126 static const struct freq_tbl ftbl_lpass_core_cc_core_clk_src[] = {
127         F(19200000, P_BI_TCXO, 1, 0, 0),
128         F(51200000, P_LPASS_CORE_CC_DIG_PLL_OUT_MAIN_DIV_CLK_SRC, 6, 0, 0),
129         F(102400000, P_LPASS_CORE_CC_DIG_PLL_OUT_MAIN_DIV_CLK_SRC, 3, 0, 0),
130         F(204800000, P_LPASS_CORE_CC_DIG_PLL_OUT_MAIN, 3, 0, 0),
131         { }
132 };
133
134 static struct clk_rcg2 lpass_core_cc_core_clk_src = {
135         .cmd_rcgr = 0x1d000,
136         .mnd_width = 8,
137         .hid_width = 5,
138         .parent_map = lpass_core_cc_parent_map_2,
139         .freq_tbl = ftbl_lpass_core_cc_core_clk_src,
140         .clkr.hw.init = &(const struct clk_init_data){
141                 .name = "lpass_core_cc_core_clk_src",
142                 .parent_data = lpass_core_cc_parent_data_ao_2,
143                 .num_parents = ARRAY_SIZE(lpass_core_cc_parent_data_ao_2),
144                 .ops = &clk_rcg2_shared_ops,
145         },
146 };
147
148 static const struct freq_tbl ftbl_lpass_core_cc_ext_if0_clk_src[] = {
149         F(256000, P_LPASS_CORE_CC_DIG_PLL_OUT_ODD, 15, 1, 32),
150         F(512000, P_LPASS_CORE_CC_DIG_PLL_OUT_ODD, 15, 1, 16),
151         F(768000, P_LPASS_CORE_CC_DIG_PLL_OUT_ODD, 10, 1, 16),
152         F(1024000, P_LPASS_CORE_CC_DIG_PLL_OUT_ODD, 15, 1, 8),
153         F(1536000, P_LPASS_CORE_CC_DIG_PLL_OUT_ODD, 10, 1, 8),
154         F(2048000, P_LPASS_CORE_CC_DIG_PLL_OUT_ODD, 15, 1, 4),
155         F(3072000, P_LPASS_CORE_CC_DIG_PLL_OUT_ODD, 10, 1, 4),
156         F(4096000, P_LPASS_CORE_CC_DIG_PLL_OUT_ODD, 15, 1, 2),
157         F(6144000, P_LPASS_CORE_CC_DIG_PLL_OUT_ODD, 10, 1, 2),
158         F(8192000, P_LPASS_CORE_CC_DIG_PLL_OUT_ODD, 15, 0, 0),
159         F(9600000, P_BI_TCXO, 2, 0, 0),
160         F(12288000, P_LPASS_CORE_CC_DIG_PLL_OUT_ODD, 10, 0, 0),
161         F(19200000, P_BI_TCXO, 1, 0, 0),
162         F(24576000, P_LPASS_CORE_CC_DIG_PLL_OUT_ODD, 5, 0, 0),
163         { }
164 };
165
166 static struct clk_rcg2 lpass_core_cc_ext_if0_clk_src = {
167         .cmd_rcgr = 0x10000,
168         .mnd_width = 16,
169         .hid_width = 5,
170         .parent_map = lpass_core_cc_parent_map_0,
171         .freq_tbl = ftbl_lpass_core_cc_ext_if0_clk_src,
172         .clkr.hw.init = &(const struct clk_init_data){
173                 .name = "lpass_core_cc_ext_if0_clk_src",
174                 .parent_data = lpass_core_cc_parent_data_0,
175                 .num_parents = ARRAY_SIZE(lpass_core_cc_parent_data_0),
176                 .ops = &clk_rcg2_ops,
177         },
178 };
179
180 static struct clk_rcg2 lpass_core_cc_ext_if1_clk_src = {
181         .cmd_rcgr = 0x11000,
182         .mnd_width = 16,
183         .hid_width = 5,
184         .parent_map = lpass_core_cc_parent_map_0,
185         .freq_tbl = ftbl_lpass_core_cc_ext_if0_clk_src,
186         .clkr.hw.init = &(const struct clk_init_data){
187                 .name = "lpass_core_cc_ext_if1_clk_src",
188                 .parent_data = lpass_core_cc_parent_data_0,
189                 .num_parents = ARRAY_SIZE(lpass_core_cc_parent_data_0),
190                 .ops = &clk_rcg2_ops,
191         },
192 };
193
194 static struct clk_rcg2 lpass_core_cc_ext_mclk0_clk_src = {
195         .cmd_rcgr = 0x20000,
196         .mnd_width = 8,
197         .hid_width = 5,
198         .parent_map = lpass_core_cc_parent_map_0,
199         .freq_tbl = ftbl_lpass_core_cc_ext_if0_clk_src,
200         .clkr.hw.init = &(const struct clk_init_data){
201                 .name = "lpass_core_cc_ext_mclk0_clk_src",
202                 .parent_data = lpass_core_cc_parent_data_0,
203                 .num_parents = ARRAY_SIZE(lpass_core_cc_parent_data_0),
204                 .ops = &clk_rcg2_ops,
205         },
206 };
207
208 static struct clk_branch lpass_core_cc_core_clk = {
209         .halt_reg = 0x1f000,
210         .halt_check = BRANCH_HALT_VOTED,
211         .hwcg_reg = 0x1f000,
212         .hwcg_bit = 1,
213         .clkr = {
214                 .enable_reg = 0x1f000,
215                 .enable_mask = BIT(0),
216                 .hw.init = &(const struct clk_init_data){
217                         .name = "lpass_core_cc_core_clk",
218                         .parent_hws = (const struct clk_hw*[]){
219                                 &lpass_core_cc_core_clk_src.clkr.hw,
220                         },
221                         .num_parents = 1,
222                         .flags = CLK_SET_RATE_PARENT,
223                         .ops = &clk_branch2_aon_ops,
224                 },
225         },
226 };
227
228 static struct clk_branch lpass_core_cc_ext_if0_ibit_clk = {
229         .halt_reg = 0x10018,
230         .halt_check = BRANCH_HALT,
231         .clkr = {
232                 .enable_reg = 0x10018,
233                 .enable_mask = BIT(0),
234                 .hw.init = &(const struct clk_init_data){
235                         .name = "lpass_core_cc_ext_if0_ibit_clk",
236                         .parent_hws = (const struct clk_hw*[]){
237                                 &lpass_core_cc_ext_if0_clk_src.clkr.hw,
238                         },
239                         .num_parents = 1,
240                         .flags = CLK_SET_RATE_PARENT,
241                         .ops = &clk_branch2_ops,
242                 },
243         },
244 };
245
246 static struct clk_branch lpass_core_cc_ext_if1_ibit_clk = {
247         .halt_reg = 0x11018,
248         .halt_check = BRANCH_HALT,
249         .clkr = {
250                 .enable_reg = 0x11018,
251                 .enable_mask = BIT(0),
252                 .hw.init = &(const struct clk_init_data){
253                         .name = "lpass_core_cc_ext_if1_ibit_clk",
254                         .parent_hws = (const struct clk_hw*[]){
255                                 &lpass_core_cc_ext_if1_clk_src.clkr.hw,
256                         },
257                         .num_parents = 1,
258                         .flags = CLK_SET_RATE_PARENT,
259                         .ops = &clk_branch2_ops,
260                 },
261         },
262 };
263
264 static struct clk_branch lpass_core_cc_lpm_core_clk = {
265         .halt_reg = 0x1e000,
266         .halt_check = BRANCH_HALT,
267         .clkr = {
268                 .enable_reg = 0x1e000,
269                 .enable_mask = BIT(0),
270                 .hw.init = &(const struct clk_init_data){
271                         .name = "lpass_core_cc_lpm_core_clk",
272                         .parent_hws = (const struct clk_hw*[]){
273                                 &lpass_core_cc_core_clk_src.clkr.hw,
274                         },
275                         .num_parents = 1,
276                         .flags = CLK_SET_RATE_PARENT,
277                         .ops = &clk_branch2_ops,
278                 },
279         },
280 };
281
282 static struct clk_branch lpass_core_cc_lpm_mem0_core_clk = {
283         .halt_reg = 0x1e004,
284         .halt_check = BRANCH_HALT,
285         .clkr = {
286                 .enable_reg = 0x1e004,
287                 .enable_mask = BIT(0),
288                 .hw.init = &(const struct clk_init_data){
289                         .name = "lpass_core_cc_lpm_mem0_core_clk",
290                         .parent_hws = (const struct clk_hw*[]){
291                                 &lpass_core_cc_core_clk_src.clkr.hw,
292                         },
293                         .num_parents = 1,
294                         .flags = CLK_SET_RATE_PARENT,
295                         .ops = &clk_branch2_ops,
296                 },
297         },
298 };
299
300 static struct clk_branch lpass_core_cc_ext_mclk0_clk = {
301         .halt_reg = 0x20014,
302         .halt_check = BRANCH_HALT,
303         .clkr = {
304                 .enable_reg = 0x20014,
305                 .enable_mask = BIT(0),
306                 .hw.init = &(const struct clk_init_data){
307                         .name = "lpass_core_cc_ext_mclk0_clk",
308                         .parent_hws = (const struct clk_hw*[]){
309                                 &lpass_core_cc_ext_mclk0_clk_src.clkr.hw,
310                         },
311                         .num_parents = 1,
312                         .flags = CLK_SET_RATE_PARENT,
313                         .ops = &clk_branch2_ops,
314                 },
315         },
316 };
317
318 static struct clk_branch lpass_core_cc_sysnoc_mport_core_clk = {
319         .halt_reg = 0x23000,
320         .halt_check = BRANCH_HALT_VOTED,
321         .hwcg_reg = 0x23000,
322         .hwcg_bit = 1,
323         .clkr = {
324                 .enable_reg = 0x23000,
325                 .enable_mask = BIT(0),
326                 .hw.init = &(const struct clk_init_data){
327                         .name = "lpass_core_cc_sysnoc_mport_core_clk",
328                         .parent_hws = (const struct clk_hw*[]){
329                                 &lpass_core_cc_core_clk_src.clkr.hw,
330                         },
331                         .num_parents = 1,
332                         .flags = CLK_SET_RATE_PARENT,
333                         .ops = &clk_branch2_ops,
334                 },
335         },
336 };
337
338 static struct gdsc lpass_core_cc_lpass_core_hm_gdsc = {
339         .gdscr = 0x0,
340         .pd = {
341                 .name = "lpass_core_cc_lpass_core_hm_gdsc",
342         },
343         .pwrsts = PWRSTS_OFF_ON,
344         .flags = RETAIN_FF_ENABLE,
345 };
346
347 static struct clk_regmap *lpass_core_cc_sc7280_clocks[] = {
348         [LPASS_CORE_CC_CORE_CLK] = &lpass_core_cc_core_clk.clkr,
349         [LPASS_CORE_CC_CORE_CLK_SRC] = &lpass_core_cc_core_clk_src.clkr,
350         [LPASS_CORE_CC_DIG_PLL] = &lpass_core_cc_dig_pll.clkr,
351         [LPASS_CORE_CC_DIG_PLL_OUT_MAIN_DIV_CLK_SRC] =
352                 &lpass_core_cc_dig_pll_out_main_div_clk_src.clkr,
353         [LPASS_CORE_CC_DIG_PLL_OUT_ODD] = &lpass_core_cc_dig_pll_out_odd.clkr,
354         [LPASS_CORE_CC_EXT_IF0_CLK_SRC] = &lpass_core_cc_ext_if0_clk_src.clkr,
355         [LPASS_CORE_CC_EXT_IF0_IBIT_CLK] = &lpass_core_cc_ext_if0_ibit_clk.clkr,
356         [LPASS_CORE_CC_EXT_IF1_CLK_SRC] = &lpass_core_cc_ext_if1_clk_src.clkr,
357         [LPASS_CORE_CC_EXT_IF1_IBIT_CLK] = &lpass_core_cc_ext_if1_ibit_clk.clkr,
358         [LPASS_CORE_CC_LPM_CORE_CLK] = &lpass_core_cc_lpm_core_clk.clkr,
359         [LPASS_CORE_CC_LPM_MEM0_CORE_CLK] = &lpass_core_cc_lpm_mem0_core_clk.clkr,
360         [LPASS_CORE_CC_SYSNOC_MPORT_CORE_CLK] = &lpass_core_cc_sysnoc_mport_core_clk.clkr,
361         [LPASS_CORE_CC_EXT_MCLK0_CLK] = &lpass_core_cc_ext_mclk0_clk.clkr,
362         [LPASS_CORE_CC_EXT_MCLK0_CLK_SRC] = &lpass_core_cc_ext_mclk0_clk_src.clkr,
363 };
364
365 static struct regmap_config lpass_core_cc_sc7280_regmap_config = {
366         .reg_bits = 32,
367         .reg_stride = 4,
368         .val_bits = 32,
369         .fast_io = true,
370 };
371
372 static const struct qcom_cc_desc lpass_core_cc_sc7280_desc = {
373         .config = &lpass_core_cc_sc7280_regmap_config,
374         .clks = lpass_core_cc_sc7280_clocks,
375         .num_clks = ARRAY_SIZE(lpass_core_cc_sc7280_clocks),
376 };
377
378 static const struct of_device_id lpass_core_cc_sc7280_match_table[] = {
379         { .compatible = "qcom,sc7280-lpasscorecc" },
380         { }
381 };
382 MODULE_DEVICE_TABLE(of, lpass_core_cc_sc7280_match_table);
383
384 static struct gdsc *lpass_core_hm_sc7280_gdscs[] = {
385         [LPASS_CORE_CC_LPASS_CORE_HM_GDSC] = &lpass_core_cc_lpass_core_hm_gdsc,
386 };
387
388 static const struct qcom_cc_desc lpass_core_hm_sc7280_desc = {
389         .config = &lpass_core_cc_sc7280_regmap_config,
390         .gdscs = lpass_core_hm_sc7280_gdscs,
391         .num_gdscs = ARRAY_SIZE(lpass_core_hm_sc7280_gdscs),
392 };
393
394 static int lpass_core_cc_sc7280_probe(struct platform_device *pdev)
395 {
396         const struct qcom_cc_desc *desc;
397         struct regmap *regmap;
398
399         lpass_core_cc_sc7280_regmap_config.name = "lpass_core_cc";
400         lpass_core_cc_sc7280_regmap_config.max_register = 0x4f004;
401         desc = &lpass_core_cc_sc7280_desc;
402
403         regmap = qcom_cc_map(pdev, desc);
404         if (IS_ERR(regmap))
405                 return PTR_ERR(regmap);
406
407         clk_lucid_pll_configure(&lpass_core_cc_dig_pll, regmap, &lpass_core_cc_dig_pll_config);
408
409         return qcom_cc_really_probe(pdev, &lpass_core_cc_sc7280_desc, regmap);
410 }
411
412 static struct platform_driver lpass_core_cc_sc7280_driver = {
413         .probe = lpass_core_cc_sc7280_probe,
414         .driver = {
415                 .name = "lpass_core_cc-sc7280",
416                 .of_match_table = lpass_core_cc_sc7280_match_table,
417         },
418 };
419
420 static int lpass_hm_core_probe(struct platform_device *pdev)
421 {
422         const struct qcom_cc_desc *desc;
423
424         lpass_core_cc_sc7280_regmap_config.name = "lpass_hm_core";
425         lpass_core_cc_sc7280_regmap_config.max_register = 0x24;
426         desc = &lpass_core_hm_sc7280_desc;
427
428         return qcom_cc_probe_by_index(pdev, 0, desc);
429 }
430
431 static const struct of_device_id lpass_hm_sc7280_match_table[] = {
432         { .compatible = "qcom,sc7280-lpasshm" },
433         { }
434 };
435 MODULE_DEVICE_TABLE(of, lpass_hm_sc7280_match_table);
436
437 static struct platform_driver lpass_hm_sc7280_driver = {
438         .probe = lpass_hm_core_probe,
439         .driver = {
440                 .name = "lpass_hm-sc7280",
441                 .of_match_table = lpass_hm_sc7280_match_table,
442         },
443 };
444
445 static int __init lpass_core_cc_sc7280_init(void)
446 {
447         int ret;
448
449         ret = platform_driver_register(&lpass_hm_sc7280_driver);
450         if (ret)
451                 return ret;
452
453         return platform_driver_register(&lpass_core_cc_sc7280_driver);
454 }
455 subsys_initcall(lpass_core_cc_sc7280_init);
456
457 static void __exit lpass_core_cc_sc7280_exit(void)
458 {
459         platform_driver_unregister(&lpass_core_cc_sc7280_driver);
460         platform_driver_unregister(&lpass_hm_sc7280_driver);
461 }
462 module_exit(lpass_core_cc_sc7280_exit);
463
464 MODULE_DESCRIPTION("QTI LPASS_CORE_CC SC7280 Driver");
465 MODULE_LICENSE("GPL v2");