1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2021, The Linux Foundation. All rights reserved.
6 #include <linux/clk-provider.h>
8 #include <linux/module.h>
10 #include <linux/platform_device.h>
11 #include <linux/pm_clock.h>
12 #include <linux/pm_runtime.h>
13 #include <linux/regmap.h>
15 #include <dt-bindings/clock/qcom,lpasscorecc-sc7280.h>
17 #include "clk-alpha-pll.h"
18 #include "clk-branch.h"
20 #include "clk-regmap.h"
21 #include "clk-regmap-divider.h"
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
,
32 static const struct pll_vco lucid_vco
[] = {
33 { 249600000, 2000000000, 0 },
36 /* 614.4MHz configuration */
37 static const struct alpha_pll_config lpass_core_cc_dig_pll_config
= {
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,
48 static struct clk_alpha_pll lpass_core_cc_dig_pll
= {
50 .vco_table
= lucid_vco
,
51 .num_vco
= ARRAY_SIZE(lucid_vco
),
52 .regs
= clk_alpha_pll_regs
[CLK_ALPHA_PLL_TYPE_LUCID
],
54 .hw
.init
= &(struct clk_init_data
){
55 .name
= "lpass_core_cc_dig_pll",
56 .parent_data
= &(const struct clk_parent_data
){
60 .ops
= &clk_alpha_pll_lucid_ops
,
65 static const struct clk_div_table post_div_table_lpass_core_cc_dig_pll_out_odd
[] = {
70 static struct clk_alpha_pll_postdiv lpass_core_cc_dig_pll_out_odd
= {
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
),
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
,
83 .flags
= CLK_SET_RATE_PARENT
,
84 .ops
= &clk_alpha_pll_postdiv_lucid_ops
,
88 static struct clk_regmap_div lpass_core_cc_dig_pll_out_main_div_clk_src
= {
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
,
98 .flags
= CLK_SET_RATE_PARENT
,
99 .ops
= &clk_regmap_div_ro_ops
,
104 static const struct parent_map lpass_core_cc_parent_map_0
[] = {
106 { P_LPASS_CORE_CC_DIG_PLL_OUT_ODD
, 5 },
109 static const struct clk_parent_data lpass_core_cc_parent_data_0
[] = {
111 { .hw
= &lpass_core_cc_dig_pll_out_odd
.clkr
.hw
},
114 static const struct parent_map lpass_core_cc_parent_map_2
[] = {
116 { P_LPASS_CORE_CC_DIG_PLL_OUT_MAIN
, 1 },
117 { P_LPASS_CORE_CC_DIG_PLL_OUT_MAIN_DIV_CLK_SRC
, 2 },
120 static const struct clk_parent_data lpass_core_cc_parent_data_ao_2
[] = {
122 { .hw
= &lpass_core_cc_dig_pll
.clkr
.hw
},
123 { .hw
= &lpass_core_cc_dig_pll_out_main_div_clk_src
.clkr
.hw
},
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),
134 static struct clk_rcg2 lpass_core_cc_core_clk_src
= {
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
,
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),
166 static struct clk_rcg2 lpass_core_cc_ext_if0_clk_src
= {
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
,
180 static struct clk_rcg2 lpass_core_cc_ext_if1_clk_src
= {
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
,
194 static struct clk_rcg2 lpass_core_cc_ext_mclk0_clk_src
= {
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
,
208 static struct clk_branch lpass_core_cc_core_clk
= {
210 .halt_check
= BRANCH_HALT_VOTED
,
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
,
222 .flags
= CLK_SET_RATE_PARENT
,
223 .ops
= &clk_branch2_aon_ops
,
228 static struct clk_branch lpass_core_cc_ext_if0_ibit_clk
= {
230 .halt_check
= BRANCH_HALT
,
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
,
240 .flags
= CLK_SET_RATE_PARENT
,
241 .ops
= &clk_branch2_ops
,
246 static struct clk_branch lpass_core_cc_ext_if1_ibit_clk
= {
248 .halt_check
= BRANCH_HALT
,
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
,
258 .flags
= CLK_SET_RATE_PARENT
,
259 .ops
= &clk_branch2_ops
,
264 static struct clk_branch lpass_core_cc_lpm_core_clk
= {
266 .halt_check
= BRANCH_HALT
,
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
,
276 .flags
= CLK_SET_RATE_PARENT
,
277 .ops
= &clk_branch2_ops
,
282 static struct clk_branch lpass_core_cc_lpm_mem0_core_clk
= {
284 .halt_check
= BRANCH_HALT
,
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
,
294 .flags
= CLK_SET_RATE_PARENT
,
295 .ops
= &clk_branch2_ops
,
300 static struct clk_branch lpass_core_cc_ext_mclk0_clk
= {
302 .halt_check
= BRANCH_HALT
,
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
,
312 .flags
= CLK_SET_RATE_PARENT
,
313 .ops
= &clk_branch2_ops
,
318 static struct clk_branch lpass_core_cc_sysnoc_mport_core_clk
= {
320 .halt_check
= BRANCH_HALT_VOTED
,
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
,
332 .flags
= CLK_SET_RATE_PARENT
,
333 .ops
= &clk_branch2_ops
,
338 static struct gdsc lpass_core_cc_lpass_core_hm_gdsc
= {
341 .name
= "lpass_core_cc_lpass_core_hm_gdsc",
343 .pwrsts
= PWRSTS_OFF_ON
,
344 .flags
= RETAIN_FF_ENABLE
,
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
,
365 static struct regmap_config lpass_core_cc_sc7280_regmap_config
= {
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
),
378 static const struct of_device_id lpass_core_cc_sc7280_match_table
[] = {
379 { .compatible
= "qcom,sc7280-lpasscorecc" },
382 MODULE_DEVICE_TABLE(of
, lpass_core_cc_sc7280_match_table
);
384 static struct gdsc
*lpass_core_hm_sc7280_gdscs
[] = {
385 [LPASS_CORE_CC_LPASS_CORE_HM_GDSC
] = &lpass_core_cc_lpass_core_hm_gdsc
,
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
),
394 static int lpass_core_cc_sc7280_probe(struct platform_device
*pdev
)
396 const struct qcom_cc_desc
*desc
;
397 struct regmap
*regmap
;
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
;
403 regmap
= qcom_cc_map(pdev
, desc
);
405 return PTR_ERR(regmap
);
407 clk_lucid_pll_configure(&lpass_core_cc_dig_pll
, regmap
, &lpass_core_cc_dig_pll_config
);
409 return qcom_cc_really_probe(&pdev
->dev
, &lpass_core_cc_sc7280_desc
, regmap
);
412 static struct platform_driver lpass_core_cc_sc7280_driver
= {
413 .probe
= lpass_core_cc_sc7280_probe
,
415 .name
= "lpass_core_cc-sc7280",
416 .of_match_table
= lpass_core_cc_sc7280_match_table
,
420 static int lpass_hm_core_probe(struct platform_device
*pdev
)
422 const struct qcom_cc_desc
*desc
;
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
;
428 return qcom_cc_probe_by_index(pdev
, 0, desc
);
431 static const struct of_device_id lpass_hm_sc7280_match_table
[] = {
432 { .compatible
= "qcom,sc7280-lpasshm" },
435 MODULE_DEVICE_TABLE(of
, lpass_hm_sc7280_match_table
);
437 static struct platform_driver lpass_hm_sc7280_driver
= {
438 .probe
= lpass_hm_core_probe
,
440 .name
= "lpass_hm-sc7280",
441 .of_match_table
= lpass_hm_sc7280_match_table
,
445 static int __init
lpass_core_cc_sc7280_init(void)
449 ret
= platform_driver_register(&lpass_hm_sc7280_driver
);
453 return platform_driver_register(&lpass_core_cc_sc7280_driver
);
455 subsys_initcall(lpass_core_cc_sc7280_init
);
457 static void __exit
lpass_core_cc_sc7280_exit(void)
459 platform_driver_unregister(&lpass_core_cc_sc7280_driver
);
460 platform_driver_unregister(&lpass_hm_sc7280_driver
);
462 module_exit(lpass_core_cc_sc7280_exit
);
464 MODULE_DESCRIPTION("QTI LPASS_CORE_CC SC7280 Driver");
465 MODULE_LICENSE("GPL v2");