fa8cda63cf204e2e55929f403e23426da161a4f4
[releases.git] / lcc-ipq806x.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2014, The Linux Foundation. All rights reserved.
4  */
5
6 #include <linux/kernel.h>
7 #include <linux/bitops.h>
8 #include <linux/err.h>
9 #include <linux/platform_device.h>
10 #include <linux/module.h>
11 #include <linux/of.h>
12 #include <linux/clk-provider.h>
13 #include <linux/regmap.h>
14
15 #include <dt-bindings/clock/qcom,lcc-ipq806x.h>
16
17 #include "common.h"
18 #include "clk-regmap.h"
19 #include "clk-pll.h"
20 #include "clk-rcg.h"
21 #include "clk-branch.h"
22 #include "clk-regmap-divider.h"
23 #include "clk-regmap-mux.h"
24 #include "reset.h"
25
26 static struct clk_pll pll4 = {
27         .l_reg = 0x4,
28         .m_reg = 0x8,
29         .n_reg = 0xc,
30         .config_reg = 0x14,
31         .mode_reg = 0x0,
32         .status_reg = 0x18,
33         .status_bit = 16,
34         .clkr.hw.init = &(struct clk_init_data){
35                 .name = "pll4",
36                 .parent_data = &(const struct clk_parent_data) {
37                         .fw_name = "pxo", .name = "pxo_board",
38                 },
39                 .num_parents = 1,
40                 .ops = &clk_pll_ops,
41         },
42 };
43
44 static const struct pll_config pll4_config = {
45         .l = 0xf,
46         .m = 0x91,
47         .n = 0xc7,
48         .vco_val = 0x0,
49         .vco_mask = BIT(17) | BIT(16),
50         .pre_div_val = 0x0,
51         .pre_div_mask = BIT(19),
52         .post_div_val = 0x0,
53         .post_div_mask = BIT(21) | BIT(20),
54         .mn_ena_mask = BIT(22),
55         .main_output_mask = BIT(23),
56 };
57
58 enum {
59         P_PXO,
60         P_PLL4,
61 };
62
63 static const struct parent_map lcc_pxo_pll4_map[] = {
64         { P_PXO, 0 },
65         { P_PLL4, 2 }
66 };
67
68 static const struct clk_parent_data lcc_pxo_pll4[] = {
69         { .fw_name = "pxo", .name = "pxo_board" },
70         { .fw_name = "pll4_vote", .name = "pll4_vote" },
71 };
72
73 static struct freq_tbl clk_tbl_aif_mi2s[] = {
74         {  1024000, P_PLL4, 4,  1,  96 },
75         {  1411200, P_PLL4, 4,  2, 139 },
76         {  1536000, P_PLL4, 4,  1,  64 },
77         {  2048000, P_PLL4, 4,  1,  48 },
78         {  2116800, P_PLL4, 4,  2,  93 },
79         {  2304000, P_PLL4, 4,  2,  85 },
80         {  2822400, P_PLL4, 4,  6, 209 },
81         {  3072000, P_PLL4, 4,  1,  32 },
82         {  3175200, P_PLL4, 4,  1,  31 },
83         {  4096000, P_PLL4, 4,  1,  24 },
84         {  4233600, P_PLL4, 4,  9, 209 },
85         {  4608000, P_PLL4, 4,  3,  64 },
86         {  5644800, P_PLL4, 4, 12, 209 },
87         {  6144000, P_PLL4, 4,  1,  16 },
88         {  6350400, P_PLL4, 4,  2,  31 },
89         {  8192000, P_PLL4, 4,  1,  12 },
90         {  8467200, P_PLL4, 4, 18, 209 },
91         {  9216000, P_PLL4, 4,  3,  32 },
92         { 11289600, P_PLL4, 4, 24, 209 },
93         { 12288000, P_PLL4, 4,  1,   8 },
94         { 12700800, P_PLL4, 4, 27, 209 },
95         { 13824000, P_PLL4, 4,  9,  64 },
96         { 16384000, P_PLL4, 4,  1,   6 },
97         { 16934400, P_PLL4, 4, 41, 238 },
98         { 18432000, P_PLL4, 4,  3,  16 },
99         { 22579200, P_PLL4, 2, 24, 209 },
100         { 24576000, P_PLL4, 4,  1,   4 },
101         { 27648000, P_PLL4, 4,  9,  32 },
102         { 33868800, P_PLL4, 4, 41, 119 },
103         { 36864000, P_PLL4, 4,  3,   8 },
104         { 45158400, P_PLL4, 1, 24, 209 },
105         { 49152000, P_PLL4, 4,  1,   2 },
106         { 50803200, P_PLL4, 1, 27, 209 },
107         { }
108 };
109
110 static struct clk_rcg mi2s_osr_src = {
111         .ns_reg = 0x48,
112         .md_reg = 0x4c,
113         .mn = {
114                 .mnctr_en_bit = 8,
115                 .mnctr_reset_bit = 7,
116                 .mnctr_mode_shift = 5,
117                 .n_val_shift = 24,
118                 .m_val_shift = 8,
119                 .width = 8,
120         },
121         .p = {
122                 .pre_div_shift = 3,
123                 .pre_div_width = 2,
124         },
125         .s = {
126                 .src_sel_shift = 0,
127                 .parent_map = lcc_pxo_pll4_map,
128         },
129         .freq_tbl = clk_tbl_aif_mi2s,
130         .clkr = {
131                 .enable_reg = 0x48,
132                 .enable_mask = BIT(9),
133                 .hw.init = &(struct clk_init_data){
134                         .name = "mi2s_osr_src",
135                         .parent_data = lcc_pxo_pll4,
136                         .num_parents = ARRAY_SIZE(lcc_pxo_pll4),
137                         .ops = &clk_rcg_ops,
138                         .flags = CLK_SET_RATE_GATE,
139                 },
140         },
141 };
142
143 static struct clk_branch mi2s_osr_clk = {
144         .halt_reg = 0x50,
145         .halt_bit = 1,
146         .halt_check = BRANCH_HALT_ENABLE,
147         .clkr = {
148                 .enable_reg = 0x48,
149                 .enable_mask = BIT(17),
150                 .hw.init = &(struct clk_init_data){
151                         .name = "mi2s_osr_clk",
152                         .parent_hws = (const struct clk_hw*[]) {
153                                 &mi2s_osr_src.clkr.hw,
154                         },
155                         .num_parents = 1,
156                         .ops = &clk_branch_ops,
157                         .flags = CLK_SET_RATE_PARENT,
158                 },
159         },
160 };
161
162 static struct clk_regmap_div mi2s_div_clk = {
163         .reg = 0x48,
164         .shift = 10,
165         .width = 4,
166         .clkr = {
167                 .hw.init = &(struct clk_init_data){
168                         .name = "mi2s_div_clk",
169                         .parent_hws = (const struct clk_hw*[]) {
170                                 &mi2s_osr_src.clkr.hw,
171                         },
172                         .num_parents = 1,
173                         .ops = &clk_regmap_div_ops,
174                 },
175         },
176 };
177
178 static struct clk_branch mi2s_bit_div_clk = {
179         .halt_reg = 0x50,
180         .halt_bit = 0,
181         .halt_check = BRANCH_HALT_ENABLE,
182         .clkr = {
183                 .enable_reg = 0x48,
184                 .enable_mask = BIT(15),
185                 .hw.init = &(struct clk_init_data){
186                         .name = "mi2s_bit_div_clk",
187                         .parent_hws = (const struct clk_hw*[]) {
188                                 &mi2s_div_clk.clkr.hw,
189                         },
190                         .num_parents = 1,
191                         .ops = &clk_branch_ops,
192                         .flags = CLK_SET_RATE_PARENT,
193                 },
194         },
195 };
196
197 static const struct clk_parent_data lcc_mi2s_bit_div_codec_clk[] = {
198         { .hw = &mi2s_bit_div_clk.clkr.hw, },
199         { .fw_name = "mi2s_codec", .name = "mi2s_codec_clk" },
200 };
201
202 static struct clk_regmap_mux mi2s_bit_clk = {
203         .reg = 0x48,
204         .shift = 14,
205         .width = 1,
206         .clkr = {
207                 .hw.init = &(struct clk_init_data){
208                         .name = "mi2s_bit_clk",
209                         .parent_data = lcc_mi2s_bit_div_codec_clk,
210                         .num_parents = ARRAY_SIZE(lcc_mi2s_bit_div_codec_clk),
211                         .ops = &clk_regmap_mux_closest_ops,
212                         .flags = CLK_SET_RATE_PARENT,
213                 },
214         },
215 };
216
217 static struct freq_tbl clk_tbl_pcm[] = {
218         {   64000, P_PLL4, 4, 1, 1536 },
219         {  128000, P_PLL4, 4, 1,  768 },
220         {  256000, P_PLL4, 4, 1,  384 },
221         {  512000, P_PLL4, 4, 1,  192 },
222         { 1024000, P_PLL4, 4, 1,   96 },
223         { 2048000, P_PLL4, 4, 1,   48 },
224         { },
225 };
226
227 static struct clk_rcg pcm_src = {
228         .ns_reg = 0x54,
229         .md_reg = 0x58,
230         .mn = {
231                 .mnctr_en_bit = 8,
232                 .mnctr_reset_bit = 7,
233                 .mnctr_mode_shift = 5,
234                 .n_val_shift = 16,
235                 .m_val_shift = 16,
236                 .width = 16,
237         },
238         .p = {
239                 .pre_div_shift = 3,
240                 .pre_div_width = 2,
241         },
242         .s = {
243                 .src_sel_shift = 0,
244                 .parent_map = lcc_pxo_pll4_map,
245         },
246         .freq_tbl = clk_tbl_pcm,
247         .clkr = {
248                 .enable_reg = 0x54,
249                 .enable_mask = BIT(9),
250                 .hw.init = &(struct clk_init_data){
251                         .name = "pcm_src",
252                         .parent_data = lcc_pxo_pll4,
253                         .num_parents = ARRAY_SIZE(lcc_pxo_pll4),
254                         .ops = &clk_rcg_ops,
255                         .flags = CLK_SET_RATE_GATE,
256                 },
257         },
258 };
259
260 static struct clk_branch pcm_clk_out = {
261         .halt_reg = 0x5c,
262         .halt_bit = 0,
263         .halt_check = BRANCH_HALT_ENABLE,
264         .clkr = {
265                 .enable_reg = 0x54,
266                 .enable_mask = BIT(11),
267                 .hw.init = &(struct clk_init_data){
268                         .name = "pcm_clk_out",
269                         .parent_hws = (const struct clk_hw*[]) {
270                                 &pcm_src.clkr.hw,
271                         },
272                         .num_parents = 1,
273                         .ops = &clk_branch_ops,
274                         .flags = CLK_SET_RATE_PARENT,
275                 },
276         },
277 };
278
279 static const struct clk_parent_data lcc_pcm_clk_out_codec_clk[] = {
280         { .hw = &pcm_clk_out.clkr.hw, },
281         { .fw_name = "pcm_codec_clk", .name = "pcm_codec_clk" },
282 };
283
284 static struct clk_regmap_mux pcm_clk = {
285         .reg = 0x54,
286         .shift = 10,
287         .width = 1,
288         .clkr = {
289                 .hw.init = &(struct clk_init_data){
290                         .name = "pcm_clk",
291                         .parent_data = lcc_pcm_clk_out_codec_clk,
292                         .num_parents = ARRAY_SIZE(lcc_pcm_clk_out_codec_clk),
293                         .ops = &clk_regmap_mux_closest_ops,
294                         .flags = CLK_SET_RATE_PARENT,
295                 },
296         },
297 };
298
299 static struct freq_tbl clk_tbl_aif_osr[] = {
300         {  2822400, P_PLL4, 1, 147, 20480 },
301         {  4096000, P_PLL4, 1,   1,    96 },
302         {  5644800, P_PLL4, 1, 147, 10240 },
303         {  6144000, P_PLL4, 1,   1,    64 },
304         { 11289600, P_PLL4, 1, 147,  5120 },
305         { 12288000, P_PLL4, 1,   1,    32 },
306         { 22579200, P_PLL4, 1, 147,  2560 },
307         { 24576000, P_PLL4, 1,   1,    16 },
308         { },
309 };
310
311 static struct clk_rcg spdif_src = {
312         .ns_reg = 0xcc,
313         .md_reg = 0xd0,
314         .mn = {
315                 .mnctr_en_bit = 8,
316                 .mnctr_reset_bit = 7,
317                 .mnctr_mode_shift = 5,
318                 .n_val_shift = 16,
319                 .m_val_shift = 16,
320                 .width = 8,
321         },
322         .p = {
323                 .pre_div_shift = 3,
324                 .pre_div_width = 2,
325         },
326         .s = {
327                 .src_sel_shift = 0,
328                 .parent_map = lcc_pxo_pll4_map,
329         },
330         .freq_tbl = clk_tbl_aif_osr,
331         .clkr = {
332                 .enable_reg = 0xcc,
333                 .enable_mask = BIT(9),
334                 .hw.init = &(struct clk_init_data){
335                         .name = "spdif_src",
336                         .parent_data = lcc_pxo_pll4,
337                         .num_parents = ARRAY_SIZE(lcc_pxo_pll4),
338                         .ops = &clk_rcg_ops,
339                         .flags = CLK_SET_RATE_GATE,
340                 },
341         },
342 };
343
344 static struct clk_branch spdif_clk = {
345         .halt_reg = 0xd4,
346         .halt_bit = 1,
347         .halt_check = BRANCH_HALT_ENABLE,
348         .clkr = {
349                 .enable_reg = 0xcc,
350                 .enable_mask = BIT(12),
351                 .hw.init = &(struct clk_init_data){
352                         .name = "spdif_clk",
353                         .parent_hws = (const struct clk_hw*[]) {
354                                 &spdif_src.clkr.hw,
355                         },
356                         .num_parents = 1,
357                         .ops = &clk_branch_ops,
358                         .flags = CLK_SET_RATE_PARENT,
359                 },
360         },
361 };
362
363 static struct freq_tbl clk_tbl_ahbix[] = {
364         { 131072000, P_PLL4, 1, 1, 3 },
365         { },
366 };
367
368 static struct clk_rcg ahbix_clk = {
369         .ns_reg = 0x38,
370         .md_reg = 0x3c,
371         .mn = {
372                 .mnctr_en_bit = 8,
373                 .mnctr_reset_bit = 7,
374                 .mnctr_mode_shift = 5,
375                 .n_val_shift = 24,
376                 .m_val_shift = 8,
377                 .width = 8,
378         },
379         .p = {
380                 .pre_div_shift = 3,
381                 .pre_div_width = 2,
382         },
383         .s = {
384                 .src_sel_shift = 0,
385                 .parent_map = lcc_pxo_pll4_map,
386         },
387         .freq_tbl = clk_tbl_ahbix,
388         .clkr = {
389                 .enable_reg = 0x38,
390                 .enable_mask = BIT(11),
391                 .hw.init = &(struct clk_init_data){
392                         .name = "ahbix",
393                         .parent_data = lcc_pxo_pll4,
394                         .num_parents = ARRAY_SIZE(lcc_pxo_pll4),
395                         .ops = &clk_rcg_lcc_ops,
396                 },
397         },
398 };
399
400 static struct clk_regmap *lcc_ipq806x_clks[] = {
401         [PLL4] = &pll4.clkr,
402         [MI2S_OSR_SRC] = &mi2s_osr_src.clkr,
403         [MI2S_OSR_CLK] = &mi2s_osr_clk.clkr,
404         [MI2S_DIV_CLK] = &mi2s_div_clk.clkr,
405         [MI2S_BIT_DIV_CLK] = &mi2s_bit_div_clk.clkr,
406         [MI2S_BIT_CLK] = &mi2s_bit_clk.clkr,
407         [PCM_SRC] = &pcm_src.clkr,
408         [PCM_CLK_OUT] = &pcm_clk_out.clkr,
409         [PCM_CLK] = &pcm_clk.clkr,
410         [SPDIF_SRC] = &spdif_src.clkr,
411         [SPDIF_CLK] = &spdif_clk.clkr,
412         [AHBIX_CLK] = &ahbix_clk.clkr,
413 };
414
415 static const struct qcom_reset_map lcc_ipq806x_resets[] = {
416         [LCC_PCM_RESET] = { 0x54, 13 },
417 };
418
419 static const struct regmap_config lcc_ipq806x_regmap_config = {
420         .reg_bits       = 32,
421         .reg_stride     = 4,
422         .val_bits       = 32,
423         .max_register   = 0xfc,
424         .fast_io        = true,
425 };
426
427 static const struct qcom_cc_desc lcc_ipq806x_desc = {
428         .config = &lcc_ipq806x_regmap_config,
429         .clks = lcc_ipq806x_clks,
430         .num_clks = ARRAY_SIZE(lcc_ipq806x_clks),
431         .resets = lcc_ipq806x_resets,
432         .num_resets = ARRAY_SIZE(lcc_ipq806x_resets),
433 };
434
435 static const struct of_device_id lcc_ipq806x_match_table[] = {
436         { .compatible = "qcom,lcc-ipq8064" },
437         { }
438 };
439 MODULE_DEVICE_TABLE(of, lcc_ipq806x_match_table);
440
441 static int lcc_ipq806x_probe(struct platform_device *pdev)
442 {
443         u32 val;
444         struct regmap *regmap;
445
446         regmap = qcom_cc_map(pdev, &lcc_ipq806x_desc);
447         if (IS_ERR(regmap))
448                 return PTR_ERR(regmap);
449
450         /* Configure the rate of PLL4 if the bootloader hasn't already */
451         regmap_read(regmap, 0x0, &val);
452         if (!val)
453                 clk_pll_configure_sr(&pll4, regmap, &pll4_config, true);
454         /* Enable PLL4 source on the LPASS Primary PLL Mux */
455         regmap_write(regmap, 0xc4, 0x1);
456
457         return qcom_cc_really_probe(pdev, &lcc_ipq806x_desc, regmap);
458 }
459
460 static struct platform_driver lcc_ipq806x_driver = {
461         .probe          = lcc_ipq806x_probe,
462         .driver         = {
463                 .name   = "lcc-ipq806x",
464                 .of_match_table = lcc_ipq806x_match_table,
465         },
466 };
467 module_platform_driver(lcc_ipq806x_driver);
468
469 MODULE_DESCRIPTION("QCOM LCC IPQ806x Driver");
470 MODULE_LICENSE("GPL v2");
471 MODULE_ALIAS("platform:lcc-ipq806x");