]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - drivers/clk/qcom/lcc-mdm9615.c
Merge tag 'soc-fsl-fix-v5.1' of git://git.kernel.org/pub/scm/linux/kernel/git/leo...
[mirror_ubuntu-jammy-kernel.git] / drivers / clk / qcom / lcc-mdm9615.c
1 /*
2 * Copyright (c) 2014, The Linux Foundation. All rights reserved.
3 * Copyright (c) BayLibre, SAS.
4 * Author : Neil Armstrong <narmstrong@baylibre.com>
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16 #include <linux/kernel.h>
17 #include <linux/bitops.h>
18 #include <linux/err.h>
19 #include <linux/platform_device.h>
20 #include <linux/module.h>
21 #include <linux/of.h>
22 #include <linux/of_device.h>
23 #include <linux/clk-provider.h>
24 #include <linux/regmap.h>
25
26 #include <dt-bindings/clock/qcom,lcc-mdm9615.h>
27
28 #include "common.h"
29 #include "clk-regmap.h"
30 #include "clk-pll.h"
31 #include "clk-rcg.h"
32 #include "clk-branch.h"
33 #include "clk-regmap-divider.h"
34 #include "clk-regmap-mux.h"
35
36 static struct clk_pll pll4 = {
37 .l_reg = 0x4,
38 .m_reg = 0x8,
39 .n_reg = 0xc,
40 .config_reg = 0x14,
41 .mode_reg = 0x0,
42 .status_reg = 0x18,
43 .status_bit = 16,
44 .clkr.hw.init = &(struct clk_init_data){
45 .name = "pll4",
46 .parent_names = (const char *[]){ "cxo" },
47 .num_parents = 1,
48 .ops = &clk_pll_ops,
49 },
50 };
51
52 enum {
53 P_CXO,
54 P_PLL4,
55 };
56
57 static const struct parent_map lcc_cxo_pll4_map[] = {
58 { P_CXO, 0 },
59 { P_PLL4, 2 }
60 };
61
62 static const char * const lcc_cxo_pll4[] = {
63 "cxo",
64 "pll4_vote",
65 };
66
67 static struct freq_tbl clk_tbl_aif_osr_492[] = {
68 { 512000, P_PLL4, 4, 1, 240 },
69 { 768000, P_PLL4, 4, 1, 160 },
70 { 1024000, P_PLL4, 4, 1, 120 },
71 { 1536000, P_PLL4, 4, 1, 80 },
72 { 2048000, P_PLL4, 4, 1, 60 },
73 { 3072000, P_PLL4, 4, 1, 40 },
74 { 4096000, P_PLL4, 4, 1, 30 },
75 { 6144000, P_PLL4, 4, 1, 20 },
76 { 8192000, P_PLL4, 4, 1, 15 },
77 { 12288000, P_PLL4, 4, 1, 10 },
78 { 24576000, P_PLL4, 4, 1, 5 },
79 { 27000000, P_CXO, 1, 0, 0 },
80 { }
81 };
82
83 static struct freq_tbl clk_tbl_aif_osr_393[] = {
84 { 512000, P_PLL4, 4, 1, 192 },
85 { 768000, P_PLL4, 4, 1, 128 },
86 { 1024000, P_PLL4, 4, 1, 96 },
87 { 1536000, P_PLL4, 4, 1, 64 },
88 { 2048000, P_PLL4, 4, 1, 48 },
89 { 3072000, P_PLL4, 4, 1, 32 },
90 { 4096000, P_PLL4, 4, 1, 24 },
91 { 6144000, P_PLL4, 4, 1, 16 },
92 { 8192000, P_PLL4, 4, 1, 12 },
93 { 12288000, P_PLL4, 4, 1, 8 },
94 { 24576000, P_PLL4, 4, 1, 4 },
95 { 27000000, P_CXO, 1, 0, 0 },
96 { }
97 };
98
99 static struct clk_rcg mi2s_osr_src = {
100 .ns_reg = 0x48,
101 .md_reg = 0x4c,
102 .mn = {
103 .mnctr_en_bit = 8,
104 .mnctr_reset_bit = 7,
105 .mnctr_mode_shift = 5,
106 .n_val_shift = 24,
107 .m_val_shift = 8,
108 .width = 8,
109 },
110 .p = {
111 .pre_div_shift = 3,
112 .pre_div_width = 2,
113 },
114 .s = {
115 .src_sel_shift = 0,
116 .parent_map = lcc_cxo_pll4_map,
117 },
118 .freq_tbl = clk_tbl_aif_osr_393,
119 .clkr = {
120 .enable_reg = 0x48,
121 .enable_mask = BIT(9),
122 .hw.init = &(struct clk_init_data){
123 .name = "mi2s_osr_src",
124 .parent_names = lcc_cxo_pll4,
125 .num_parents = 2,
126 .ops = &clk_rcg_ops,
127 .flags = CLK_SET_RATE_GATE,
128 },
129 },
130 };
131
132 static const char * const lcc_mi2s_parents[] = {
133 "mi2s_osr_src",
134 };
135
136 static struct clk_branch mi2s_osr_clk = {
137 .halt_reg = 0x50,
138 .halt_bit = 1,
139 .halt_check = BRANCH_HALT_ENABLE,
140 .clkr = {
141 .enable_reg = 0x48,
142 .enable_mask = BIT(17),
143 .hw.init = &(struct clk_init_data){
144 .name = "mi2s_osr_clk",
145 .parent_names = lcc_mi2s_parents,
146 .num_parents = 1,
147 .ops = &clk_branch_ops,
148 .flags = CLK_SET_RATE_PARENT,
149 },
150 },
151 };
152
153 static struct clk_regmap_div mi2s_div_clk = {
154 .reg = 0x48,
155 .shift = 10,
156 .width = 4,
157 .clkr = {
158 .enable_reg = 0x48,
159 .enable_mask = BIT(15),
160 .hw.init = &(struct clk_init_data){
161 .name = "mi2s_div_clk",
162 .parent_names = lcc_mi2s_parents,
163 .num_parents = 1,
164 .ops = &clk_regmap_div_ops,
165 },
166 },
167 };
168
169 static struct clk_branch mi2s_bit_div_clk = {
170 .halt_reg = 0x50,
171 .halt_bit = 0,
172 .halt_check = BRANCH_HALT_ENABLE,
173 .clkr = {
174 .enable_reg = 0x48,
175 .enable_mask = BIT(15),
176 .hw.init = &(struct clk_init_data){
177 .name = "mi2s_bit_div_clk",
178 .parent_names = (const char *[]){ "mi2s_div_clk" },
179 .num_parents = 1,
180 .ops = &clk_branch_ops,
181 .flags = CLK_SET_RATE_PARENT,
182 },
183 },
184 };
185
186 static struct clk_regmap_mux mi2s_bit_clk = {
187 .reg = 0x48,
188 .shift = 14,
189 .width = 1,
190 .clkr = {
191 .hw.init = &(struct clk_init_data){
192 .name = "mi2s_bit_clk",
193 .parent_names = (const char *[]){
194 "mi2s_bit_div_clk",
195 "mi2s_codec_clk",
196 },
197 .num_parents = 2,
198 .ops = &clk_regmap_mux_closest_ops,
199 .flags = CLK_SET_RATE_PARENT,
200 },
201 },
202 };
203
204 #define CLK_AIF_OSR_DIV(prefix, _ns, _md, hr) \
205 static struct clk_rcg prefix##_osr_src = { \
206 .ns_reg = _ns, \
207 .md_reg = _md, \
208 .mn = { \
209 .mnctr_en_bit = 8, \
210 .mnctr_reset_bit = 7, \
211 .mnctr_mode_shift = 5, \
212 .n_val_shift = 24, \
213 .m_val_shift = 8, \
214 .width = 8, \
215 }, \
216 .p = { \
217 .pre_div_shift = 3, \
218 .pre_div_width = 2, \
219 }, \
220 .s = { \
221 .src_sel_shift = 0, \
222 .parent_map = lcc_cxo_pll4_map, \
223 }, \
224 .freq_tbl = clk_tbl_aif_osr_393, \
225 .clkr = { \
226 .enable_reg = _ns, \
227 .enable_mask = BIT(9), \
228 .hw.init = &(struct clk_init_data){ \
229 .name = #prefix "_osr_src", \
230 .parent_names = lcc_cxo_pll4, \
231 .num_parents = 2, \
232 .ops = &clk_rcg_ops, \
233 .flags = CLK_SET_RATE_GATE, \
234 }, \
235 }, \
236 }; \
237 \
238 static const char * const lcc_##prefix##_parents[] = { \
239 #prefix "_osr_src", \
240 }; \
241 \
242 static struct clk_branch prefix##_osr_clk = { \
243 .halt_reg = hr, \
244 .halt_bit = 1, \
245 .halt_check = BRANCH_HALT_ENABLE, \
246 .clkr = { \
247 .enable_reg = _ns, \
248 .enable_mask = BIT(21), \
249 .hw.init = &(struct clk_init_data){ \
250 .name = #prefix "_osr_clk", \
251 .parent_names = lcc_##prefix##_parents, \
252 .num_parents = 1, \
253 .ops = &clk_branch_ops, \
254 .flags = CLK_SET_RATE_PARENT, \
255 }, \
256 }, \
257 }; \
258 \
259 static struct clk_regmap_div prefix##_div_clk = { \
260 .reg = _ns, \
261 .shift = 10, \
262 .width = 8, \
263 .clkr = { \
264 .hw.init = &(struct clk_init_data){ \
265 .name = #prefix "_div_clk", \
266 .parent_names = lcc_##prefix##_parents, \
267 .num_parents = 1, \
268 .ops = &clk_regmap_div_ops, \
269 }, \
270 }, \
271 }; \
272 \
273 static struct clk_branch prefix##_bit_div_clk = { \
274 .halt_reg = hr, \
275 .halt_bit = 0, \
276 .halt_check = BRANCH_HALT_ENABLE, \
277 .clkr = { \
278 .enable_reg = _ns, \
279 .enable_mask = BIT(19), \
280 .hw.init = &(struct clk_init_data){ \
281 .name = #prefix "_bit_div_clk", \
282 .parent_names = (const char *[]){ \
283 #prefix "_div_clk" \
284 }, \
285 .num_parents = 1, \
286 .ops = &clk_branch_ops, \
287 .flags = CLK_SET_RATE_PARENT, \
288 }, \
289 }, \
290 }; \
291 \
292 static struct clk_regmap_mux prefix##_bit_clk = { \
293 .reg = _ns, \
294 .shift = 18, \
295 .width = 1, \
296 .clkr = { \
297 .hw.init = &(struct clk_init_data){ \
298 .name = #prefix "_bit_clk", \
299 .parent_names = (const char *[]){ \
300 #prefix "_bit_div_clk", \
301 #prefix "_codec_clk", \
302 }, \
303 .num_parents = 2, \
304 .ops = &clk_regmap_mux_closest_ops, \
305 .flags = CLK_SET_RATE_PARENT, \
306 }, \
307 }, \
308 }
309
310 CLK_AIF_OSR_DIV(codec_i2s_mic, 0x60, 0x64, 0x68);
311 CLK_AIF_OSR_DIV(spare_i2s_mic, 0x78, 0x7c, 0x80);
312 CLK_AIF_OSR_DIV(codec_i2s_spkr, 0x6c, 0x70, 0x74);
313 CLK_AIF_OSR_DIV(spare_i2s_spkr, 0x84, 0x88, 0x8c);
314
315 static struct freq_tbl clk_tbl_pcm_492[] = {
316 { 256000, P_PLL4, 4, 1, 480 },
317 { 512000, P_PLL4, 4, 1, 240 },
318 { 768000, P_PLL4, 4, 1, 160 },
319 { 1024000, P_PLL4, 4, 1, 120 },
320 { 1536000, P_PLL4, 4, 1, 80 },
321 { 2048000, P_PLL4, 4, 1, 60 },
322 { 3072000, P_PLL4, 4, 1, 40 },
323 { 4096000, P_PLL4, 4, 1, 30 },
324 { 6144000, P_PLL4, 4, 1, 20 },
325 { 8192000, P_PLL4, 4, 1, 15 },
326 { 12288000, P_PLL4, 4, 1, 10 },
327 { 24576000, P_PLL4, 4, 1, 5 },
328 { 27000000, P_CXO, 1, 0, 0 },
329 { }
330 };
331
332 static struct freq_tbl clk_tbl_pcm_393[] = {
333 { 256000, P_PLL4, 4, 1, 384 },
334 { 512000, P_PLL4, 4, 1, 192 },
335 { 768000, P_PLL4, 4, 1, 128 },
336 { 1024000, P_PLL4, 4, 1, 96 },
337 { 1536000, P_PLL4, 4, 1, 64 },
338 { 2048000, P_PLL4, 4, 1, 48 },
339 { 3072000, P_PLL4, 4, 1, 32 },
340 { 4096000, P_PLL4, 4, 1, 24 },
341 { 6144000, P_PLL4, 4, 1, 16 },
342 { 8192000, P_PLL4, 4, 1, 12 },
343 { 12288000, P_PLL4, 4, 1, 8 },
344 { 24576000, P_PLL4, 4, 1, 4 },
345 { 27000000, P_CXO, 1, 0, 0 },
346 { }
347 };
348
349 static struct clk_rcg pcm_src = {
350 .ns_reg = 0x54,
351 .md_reg = 0x58,
352 .mn = {
353 .mnctr_en_bit = 8,
354 .mnctr_reset_bit = 7,
355 .mnctr_mode_shift = 5,
356 .n_val_shift = 16,
357 .m_val_shift = 16,
358 .width = 16,
359 },
360 .p = {
361 .pre_div_shift = 3,
362 .pre_div_width = 2,
363 },
364 .s = {
365 .src_sel_shift = 0,
366 .parent_map = lcc_cxo_pll4_map,
367 },
368 .freq_tbl = clk_tbl_pcm_393,
369 .clkr = {
370 .enable_reg = 0x54,
371 .enable_mask = BIT(9),
372 .hw.init = &(struct clk_init_data){
373 .name = "pcm_src",
374 .parent_names = lcc_cxo_pll4,
375 .num_parents = 2,
376 .ops = &clk_rcg_ops,
377 .flags = CLK_SET_RATE_GATE,
378 },
379 },
380 };
381
382 static struct clk_branch pcm_clk_out = {
383 .halt_reg = 0x5c,
384 .halt_bit = 0,
385 .halt_check = BRANCH_HALT_ENABLE,
386 .clkr = {
387 .enable_reg = 0x54,
388 .enable_mask = BIT(11),
389 .hw.init = &(struct clk_init_data){
390 .name = "pcm_clk_out",
391 .parent_names = (const char *[]){ "pcm_src" },
392 .num_parents = 1,
393 .ops = &clk_branch_ops,
394 .flags = CLK_SET_RATE_PARENT,
395 },
396 },
397 };
398
399 static struct clk_regmap_mux pcm_clk = {
400 .reg = 0x54,
401 .shift = 10,
402 .width = 1,
403 .clkr = {
404 .hw.init = &(struct clk_init_data){
405 .name = "pcm_clk",
406 .parent_names = (const char *[]){
407 "pcm_clk_out",
408 "pcm_codec_clk",
409 },
410 .num_parents = 2,
411 .ops = &clk_regmap_mux_closest_ops,
412 .flags = CLK_SET_RATE_PARENT,
413 },
414 },
415 };
416
417 static struct clk_rcg slimbus_src = {
418 .ns_reg = 0xcc,
419 .md_reg = 0xd0,
420 .mn = {
421 .mnctr_en_bit = 8,
422 .mnctr_reset_bit = 7,
423 .mnctr_mode_shift = 5,
424 .n_val_shift = 24,
425 .m_val_shift = 8,
426 .width = 8,
427 },
428 .p = {
429 .pre_div_shift = 3,
430 .pre_div_width = 2,
431 },
432 .s = {
433 .src_sel_shift = 0,
434 .parent_map = lcc_cxo_pll4_map,
435 },
436 .freq_tbl = clk_tbl_aif_osr_393,
437 .clkr = {
438 .enable_reg = 0xcc,
439 .enable_mask = BIT(9),
440 .hw.init = &(struct clk_init_data){
441 .name = "slimbus_src",
442 .parent_names = lcc_cxo_pll4,
443 .num_parents = 2,
444 .ops = &clk_rcg_ops,
445 .flags = CLK_SET_RATE_GATE,
446 },
447 },
448 };
449
450 static const char * const lcc_slimbus_parents[] = {
451 "slimbus_src",
452 };
453
454 static struct clk_branch audio_slimbus_clk = {
455 .halt_reg = 0xd4,
456 .halt_bit = 0,
457 .halt_check = BRANCH_HALT_ENABLE,
458 .clkr = {
459 .enable_reg = 0xcc,
460 .enable_mask = BIT(10),
461 .hw.init = &(struct clk_init_data){
462 .name = "audio_slimbus_clk",
463 .parent_names = lcc_slimbus_parents,
464 .num_parents = 1,
465 .ops = &clk_branch_ops,
466 .flags = CLK_SET_RATE_PARENT,
467 },
468 },
469 };
470
471 static struct clk_branch sps_slimbus_clk = {
472 .halt_reg = 0xd4,
473 .halt_bit = 1,
474 .halt_check = BRANCH_HALT_ENABLE,
475 .clkr = {
476 .enable_reg = 0xcc,
477 .enable_mask = BIT(12),
478 .hw.init = &(struct clk_init_data){
479 .name = "sps_slimbus_clk",
480 .parent_names = lcc_slimbus_parents,
481 .num_parents = 1,
482 .ops = &clk_branch_ops,
483 .flags = CLK_SET_RATE_PARENT,
484 },
485 },
486 };
487
488 static struct clk_regmap *lcc_mdm9615_clks[] = {
489 [PLL4] = &pll4.clkr,
490 [MI2S_OSR_SRC] = &mi2s_osr_src.clkr,
491 [MI2S_OSR_CLK] = &mi2s_osr_clk.clkr,
492 [MI2S_DIV_CLK] = &mi2s_div_clk.clkr,
493 [MI2S_BIT_DIV_CLK] = &mi2s_bit_div_clk.clkr,
494 [MI2S_BIT_CLK] = &mi2s_bit_clk.clkr,
495 [PCM_SRC] = &pcm_src.clkr,
496 [PCM_CLK_OUT] = &pcm_clk_out.clkr,
497 [PCM_CLK] = &pcm_clk.clkr,
498 [SLIMBUS_SRC] = &slimbus_src.clkr,
499 [AUDIO_SLIMBUS_CLK] = &audio_slimbus_clk.clkr,
500 [SPS_SLIMBUS_CLK] = &sps_slimbus_clk.clkr,
501 [CODEC_I2S_MIC_OSR_SRC] = &codec_i2s_mic_osr_src.clkr,
502 [CODEC_I2S_MIC_OSR_CLK] = &codec_i2s_mic_osr_clk.clkr,
503 [CODEC_I2S_MIC_DIV_CLK] = &codec_i2s_mic_div_clk.clkr,
504 [CODEC_I2S_MIC_BIT_DIV_CLK] = &codec_i2s_mic_bit_div_clk.clkr,
505 [CODEC_I2S_MIC_BIT_CLK] = &codec_i2s_mic_bit_clk.clkr,
506 [SPARE_I2S_MIC_OSR_SRC] = &spare_i2s_mic_osr_src.clkr,
507 [SPARE_I2S_MIC_OSR_CLK] = &spare_i2s_mic_osr_clk.clkr,
508 [SPARE_I2S_MIC_DIV_CLK] = &spare_i2s_mic_div_clk.clkr,
509 [SPARE_I2S_MIC_BIT_DIV_CLK] = &spare_i2s_mic_bit_div_clk.clkr,
510 [SPARE_I2S_MIC_BIT_CLK] = &spare_i2s_mic_bit_clk.clkr,
511 [CODEC_I2S_SPKR_OSR_SRC] = &codec_i2s_spkr_osr_src.clkr,
512 [CODEC_I2S_SPKR_OSR_CLK] = &codec_i2s_spkr_osr_clk.clkr,
513 [CODEC_I2S_SPKR_DIV_CLK] = &codec_i2s_spkr_div_clk.clkr,
514 [CODEC_I2S_SPKR_BIT_DIV_CLK] = &codec_i2s_spkr_bit_div_clk.clkr,
515 [CODEC_I2S_SPKR_BIT_CLK] = &codec_i2s_spkr_bit_clk.clkr,
516 [SPARE_I2S_SPKR_OSR_SRC] = &spare_i2s_spkr_osr_src.clkr,
517 [SPARE_I2S_SPKR_OSR_CLK] = &spare_i2s_spkr_osr_clk.clkr,
518 [SPARE_I2S_SPKR_DIV_CLK] = &spare_i2s_spkr_div_clk.clkr,
519 [SPARE_I2S_SPKR_BIT_DIV_CLK] = &spare_i2s_spkr_bit_div_clk.clkr,
520 [SPARE_I2S_SPKR_BIT_CLK] = &spare_i2s_spkr_bit_clk.clkr,
521 };
522
523 static const struct regmap_config lcc_mdm9615_regmap_config = {
524 .reg_bits = 32,
525 .reg_stride = 4,
526 .val_bits = 32,
527 .max_register = 0xfc,
528 .fast_io = true,
529 };
530
531 static const struct qcom_cc_desc lcc_mdm9615_desc = {
532 .config = &lcc_mdm9615_regmap_config,
533 .clks = lcc_mdm9615_clks,
534 .num_clks = ARRAY_SIZE(lcc_mdm9615_clks),
535 };
536
537 static const struct of_device_id lcc_mdm9615_match_table[] = {
538 { .compatible = "qcom,lcc-mdm9615" },
539 { }
540 };
541 MODULE_DEVICE_TABLE(of, lcc_mdm9615_match_table);
542
543 static int lcc_mdm9615_probe(struct platform_device *pdev)
544 {
545 u32 val;
546 struct regmap *regmap;
547
548 regmap = qcom_cc_map(pdev, &lcc_mdm9615_desc);
549 if (IS_ERR(regmap))
550 return PTR_ERR(regmap);
551
552 /* Use the correct frequency plan depending on speed of PLL4 */
553 regmap_read(regmap, 0x4, &val);
554 if (val == 0x12) {
555 slimbus_src.freq_tbl = clk_tbl_aif_osr_492;
556 mi2s_osr_src.freq_tbl = clk_tbl_aif_osr_492;
557 codec_i2s_mic_osr_src.freq_tbl = clk_tbl_aif_osr_492;
558 spare_i2s_mic_osr_src.freq_tbl = clk_tbl_aif_osr_492;
559 codec_i2s_spkr_osr_src.freq_tbl = clk_tbl_aif_osr_492;
560 spare_i2s_spkr_osr_src.freq_tbl = clk_tbl_aif_osr_492;
561 pcm_src.freq_tbl = clk_tbl_pcm_492;
562 }
563 /* Enable PLL4 source on the LPASS Primary PLL Mux */
564 regmap_write(regmap, 0xc4, 0x1);
565
566 return qcom_cc_really_probe(pdev, &lcc_mdm9615_desc, regmap);
567 }
568
569 static struct platform_driver lcc_mdm9615_driver = {
570 .probe = lcc_mdm9615_probe,
571 .driver = {
572 .name = "lcc-mdm9615",
573 .of_match_table = lcc_mdm9615_match_table,
574 },
575 };
576 module_platform_driver(lcc_mdm9615_driver);
577
578 MODULE_DESCRIPTION("QCOM LCC MDM9615 Driver");
579 MODULE_LICENSE("GPL v2");
580 MODULE_ALIAS("platform:lcc-mdm9615");