]> Git Repo - J-linux.git/blob - drivers/clk/meson/c3-pll.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / drivers / clk / meson / c3-pll.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Amlogic C3 PLL Controller Driver
4  *
5  * Copyright (c) 2023 Amlogic, inc.
6  * Author: Chuan Liu <[email protected]>
7  */
8
9 #include <linux/clk-provider.h>
10 #include <linux/platform_device.h>
11 #include "clk-regmap.h"
12 #include "clk-pll.h"
13 #include "meson-clkc-utils.h"
14 #include <dt-bindings/clock/amlogic,c3-pll-clkc.h>
15
16 #define ANACTRL_FIXPLL_CTRL4                    0x50
17 #define ANACTRL_GP0PLL_CTRL0                    0x80
18 #define ANACTRL_GP0PLL_CTRL1                    0x84
19 #define ANACTRL_GP0PLL_CTRL2                    0x88
20 #define ANACTRL_GP0PLL_CTRL3                    0x8c
21 #define ANACTRL_GP0PLL_CTRL4                    0x90
22 #define ANACTRL_GP0PLL_CTRL5                    0x94
23 #define ANACTRL_GP0PLL_CTRL6                    0x98
24 #define ANACTRL_HIFIPLL_CTRL0                   0x100
25 #define ANACTRL_HIFIPLL_CTRL1                   0x104
26 #define ANACTRL_HIFIPLL_CTRL2                   0x108
27 #define ANACTRL_HIFIPLL_CTRL3                   0x10c
28 #define ANACTRL_HIFIPLL_CTRL4                   0x110
29 #define ANACTRL_HIFIPLL_CTRL5                   0x114
30 #define ANACTRL_HIFIPLL_CTRL6                   0x118
31 #define ANACTRL_MPLL_CTRL0                      0x180
32 #define ANACTRL_MPLL_CTRL1                      0x184
33 #define ANACTRL_MPLL_CTRL2                      0x188
34 #define ANACTRL_MPLL_CTRL3                      0x18c
35 #define ANACTRL_MPLL_CTRL4                      0x190
36
37 static struct clk_regmap fclk_50m_en = {
38         .data = &(struct clk_regmap_gate_data) {
39                 .offset = ANACTRL_FIXPLL_CTRL4,
40                 .bit_idx = 0,
41         },
42         .hw.init = &(struct clk_init_data) {
43                 .name = "fclk_50m_en",
44                 .ops = &clk_regmap_gate_ro_ops,
45                 .parent_data = &(const struct clk_parent_data) {
46                         .fw_name = "fix"
47                 },
48                 .num_parents = 1,
49         },
50 };
51
52 static struct clk_fixed_factor fclk_50m = {
53         .mult = 1,
54         .div = 40,
55         .hw.init = &(struct clk_init_data) {
56                 .name = "fclk_50m",
57                 .ops = &clk_fixed_factor_ops,
58                 .parent_hws = (const struct clk_hw *[]) {
59                         &fclk_50m_en.hw
60                 },
61                 .num_parents = 1,
62         },
63 };
64
65 static struct clk_fixed_factor fclk_div2_div = {
66         .mult = 1,
67         .div = 2,
68         .hw.init = &(struct clk_init_data) {
69                 .name = "fclk_div2_div",
70                 .ops = &clk_fixed_factor_ops,
71                 .parent_data = &(const struct clk_parent_data) {
72                         .fw_name = "fix"
73                 },
74                 .num_parents = 1,
75         },
76 };
77
78 static struct clk_regmap fclk_div2 = {
79         .data = &(struct clk_regmap_gate_data) {
80                 .offset = ANACTRL_FIXPLL_CTRL4,
81                 .bit_idx = 24,
82         },
83         .hw.init = &(struct clk_init_data) {
84                 .name = "fclk_div2",
85                 .ops = &clk_regmap_gate_ro_ops,
86                 .parent_hws = (const struct clk_hw *[]) {
87                         &fclk_div2_div.hw
88                 },
89                 .num_parents = 1,
90         },
91 };
92
93 static struct clk_fixed_factor fclk_div2p5_div = {
94         .mult = 2,
95         .div = 5,
96         .hw.init = &(struct clk_init_data) {
97                 .name = "fclk_div2p5_div",
98                 .ops = &clk_fixed_factor_ops,
99                 .parent_data = &(const struct clk_parent_data) {
100                         .fw_name = "fix"
101                 },
102                 .num_parents = 1,
103         },
104 };
105
106 static struct clk_regmap fclk_div2p5 = {
107         .data = &(struct clk_regmap_gate_data) {
108                 .offset = ANACTRL_FIXPLL_CTRL4,
109                 .bit_idx = 4,
110         },
111         .hw.init = &(struct clk_init_data) {
112                 .name = "fclk_div2p5",
113                 .ops = &clk_regmap_gate_ro_ops,
114                 .parent_hws = (const struct clk_hw *[]) {
115                         &fclk_div2p5_div.hw
116                 },
117                 .num_parents = 1,
118         },
119 };
120
121 static struct clk_fixed_factor fclk_div3_div = {
122         .mult = 1,
123         .div = 3,
124         .hw.init = &(struct clk_init_data) {
125                 .name = "fclk_div3_div",
126                 .ops = &clk_fixed_factor_ops,
127                 .parent_data = &(const struct clk_parent_data) {
128                         .fw_name = "fix"
129                 },
130                 .num_parents = 1,
131         },
132 };
133
134 static struct clk_regmap fclk_div3 = {
135         .data = &(struct clk_regmap_gate_data) {
136                 .offset = ANACTRL_FIXPLL_CTRL4,
137                 .bit_idx = 20,
138         },
139         .hw.init = &(struct clk_init_data) {
140                 .name = "fclk_div3",
141                 .ops = &clk_regmap_gate_ro_ops,
142                 .parent_hws = (const struct clk_hw *[]) {
143                         &fclk_div3_div.hw
144                 },
145                 .num_parents = 1,
146         },
147 };
148
149 static struct clk_fixed_factor fclk_div4_div = {
150         .mult = 1,
151         .div = 4,
152         .hw.init = &(struct clk_init_data) {
153                 .name = "fclk_div4_div",
154                 .ops = &clk_fixed_factor_ops,
155                 .parent_data = &(const struct clk_parent_data) {
156                         .fw_name = "fix"
157                 },
158                 .num_parents = 1,
159         },
160 };
161
162 static struct clk_regmap fclk_div4 = {
163         .data = &(struct clk_regmap_gate_data) {
164                 .offset = ANACTRL_FIXPLL_CTRL4,
165                 .bit_idx = 21,
166         },
167         .hw.init = &(struct clk_init_data) {
168                 .name = "fclk_div4",
169                 .ops = &clk_regmap_gate_ro_ops,
170                 .parent_hws = (const struct clk_hw *[]) {
171                         &fclk_div4_div.hw
172                 },
173                 .num_parents = 1,
174         },
175 };
176
177 static struct clk_fixed_factor fclk_div5_div = {
178         .mult = 1,
179         .div = 5,
180         .hw.init = &(struct clk_init_data) {
181                 .name = "fclk_div5_div",
182                 .ops = &clk_fixed_factor_ops,
183                 .parent_data = &(const struct clk_parent_data) {
184                         .fw_name = "fix"
185                 },
186                 .num_parents = 1,
187         },
188 };
189
190 static struct clk_regmap fclk_div5 = {
191         .data = &(struct clk_regmap_gate_data) {
192                 .offset = ANACTRL_FIXPLL_CTRL4,
193                 .bit_idx = 22,
194         },
195         .hw.init = &(struct clk_init_data) {
196                 .name = "fclk_div5",
197                 .ops = &clk_regmap_gate_ro_ops,
198                 .parent_hws = (const struct clk_hw *[]) {
199                         &fclk_div5_div.hw
200                 },
201                 .num_parents = 1,
202         },
203 };
204
205 static struct clk_fixed_factor fclk_div7_div = {
206         .mult = 1,
207         .div = 7,
208         .hw.init = &(struct clk_init_data) {
209                 .name = "fclk_div7_div",
210                 .ops = &clk_fixed_factor_ops,
211                 .parent_data = &(const struct clk_parent_data) {
212                         .fw_name = "fix"
213                 },
214                 .num_parents = 1,
215         },
216 };
217
218 static struct clk_regmap fclk_div7 = {
219         .data = &(struct clk_regmap_gate_data) {
220                 .offset = ANACTRL_FIXPLL_CTRL4,
221                 .bit_idx = 23,
222         },
223         .hw.init = &(struct clk_init_data) {
224                 .name = "fclk_div7",
225                 .ops = &clk_regmap_gate_ro_ops,
226                 .parent_hws = (const struct clk_hw *[]) {
227                         &fclk_div7_div.hw
228                 },
229                 .num_parents = 1,
230         },
231 };
232
233 static const struct reg_sequence c3_gp0_init_regs[] = {
234         { .reg = ANACTRL_GP0PLL_CTRL2,  .def = 0x0 },
235         { .reg = ANACTRL_GP0PLL_CTRL3,  .def = 0x48681c00 },
236         { .reg = ANACTRL_GP0PLL_CTRL4,  .def = 0x88770290 },
237         { .reg = ANACTRL_GP0PLL_CTRL5,  .def = 0x3927200a },
238         { .reg = ANACTRL_GP0PLL_CTRL6,  .def = 0x56540000 },
239 };
240
241 static const struct pll_mult_range c3_gp0_pll_mult_range = {
242         .min = 125,
243         .max = 250,
244 };
245
246 static struct clk_regmap gp0_pll_dco = {
247         .data = &(struct meson_clk_pll_data) {
248                 .en = {
249                         .reg_off = ANACTRL_GP0PLL_CTRL0,
250                         .shift   = 28,
251                         .width   = 1,
252                 },
253                 .m = {
254                         .reg_off = ANACTRL_GP0PLL_CTRL0,
255                         .shift   = 0,
256                         .width   = 9,
257                 },
258                 .frac = {
259                         .reg_off = ANACTRL_GP0PLL_CTRL1,
260                         .shift   = 0,
261                         .width   = 19,
262                 },
263                 .n = {
264                         .reg_off = ANACTRL_GP0PLL_CTRL0,
265                         .shift   = 10,
266                         .width   = 5,
267                 },
268                 .l = {
269                         .reg_off = ANACTRL_GP0PLL_CTRL0,
270                         .shift   = 31,
271                         .width   = 1,
272                 },
273                 .rst = {
274                         .reg_off = ANACTRL_GP0PLL_CTRL0,
275                         .shift   = 29,
276                         .width   = 1,
277                 },
278                 .range = &c3_gp0_pll_mult_range,
279                 .init_regs = c3_gp0_init_regs,
280                 .init_count = ARRAY_SIZE(c3_gp0_init_regs),
281         },
282         .hw.init = &(struct clk_init_data) {
283                 .name = "gp0_pll_dco",
284                 .ops = &meson_clk_pll_ops,
285                 .parent_data = &(const struct clk_parent_data) {
286                         .fw_name = "top",
287                 },
288                 .num_parents = 1,
289         },
290 };
291
292 /* The maximum frequency divider supports is 32, not 128(2^7) */
293 static const struct clk_div_table c3_gp0_pll_od_table[] = {
294         { 0,  1 },
295         { 1,  2 },
296         { 2,  4 },
297         { 3,  8 },
298         { 4, 16 },
299         { 5, 32 },
300         { /* sentinel */ }
301 };
302
303 static struct clk_regmap gp0_pll = {
304         .data = &(struct clk_regmap_div_data) {
305                 .offset = ANACTRL_GP0PLL_CTRL0,
306                 .shift = 16,
307                 .width = 3,
308                 .table = c3_gp0_pll_od_table,
309         },
310         .hw.init = &(struct clk_init_data) {
311                 .name = "gp0_pll",
312                 .ops = &clk_regmap_divider_ops,
313                 .parent_hws = (const struct clk_hw *[]) {
314                         &gp0_pll_dco.hw
315                 },
316                 .num_parents = 1,
317                 .flags = CLK_SET_RATE_PARENT,
318         },
319 };
320
321 static const struct reg_sequence c3_hifi_init_regs[] = {
322         { .reg = ANACTRL_HIFIPLL_CTRL2, .def = 0x0 },
323         { .reg = ANACTRL_HIFIPLL_CTRL3, .def = 0x6a285c00 },
324         { .reg = ANACTRL_HIFIPLL_CTRL4, .def = 0x65771290 },
325         { .reg = ANACTRL_HIFIPLL_CTRL5, .def = 0x3927200a },
326         { .reg = ANACTRL_HIFIPLL_CTRL6, .def = 0x56540000 },
327 };
328
329 static struct clk_regmap hifi_pll_dco = {
330         .data = &(struct meson_clk_pll_data) {
331                 .en = {
332                         .reg_off = ANACTRL_HIFIPLL_CTRL0,
333                         .shift   = 28,
334                         .width   = 1,
335                 },
336                 .m = {
337                         .reg_off = ANACTRL_HIFIPLL_CTRL0,
338                         .shift   = 0,
339                         .width   = 8,
340                 },
341                 .frac = {
342                         .reg_off = ANACTRL_HIFIPLL_CTRL1,
343                         .shift   = 0,
344                         .width   = 19,
345                 },
346                 .n = {
347                         .reg_off = ANACTRL_HIFIPLL_CTRL0,
348                         .shift   = 10,
349                         .width   = 5,
350                 },
351                 .l = {
352                         .reg_off = ANACTRL_HIFIPLL_CTRL0,
353                         .shift   = 31,
354                         .width   = 1,
355                 },
356                 .rst = {
357                         .reg_off = ANACTRL_HIFIPLL_CTRL0,
358                         .shift   = 29,
359                         .width   = 1,
360                 },
361                 .range = &c3_gp0_pll_mult_range,
362                 .init_regs = c3_hifi_init_regs,
363                 .init_count = ARRAY_SIZE(c3_hifi_init_regs),
364                 .frac_max = 100000,
365         },
366         .hw.init = &(struct clk_init_data) {
367                 .name = "hifi_pll_dco",
368                 .ops = &meson_clk_pll_ops,
369                 .parent_data = &(const struct clk_parent_data) {
370                         .fw_name = "top",
371                 },
372                 .num_parents = 1,
373         },
374 };
375
376 static struct clk_regmap hifi_pll = {
377         .data = &(struct clk_regmap_div_data) {
378                 .offset = ANACTRL_HIFIPLL_CTRL0,
379                 .shift = 16,
380                 .width = 2,
381                 .flags = CLK_DIVIDER_POWER_OF_TWO,
382         },
383         .hw.init = &(struct clk_init_data) {
384                 .name = "hifi_pll",
385                 .ops = &clk_regmap_divider_ops,
386                 .parent_hws = (const struct clk_hw *[]) {
387                         &hifi_pll_dco.hw
388                 },
389                 .num_parents = 1,
390                 .flags = CLK_SET_RATE_PARENT,
391         },
392 };
393
394 static const struct reg_sequence c3_mclk_init_regs[] = {
395         { .reg = ANACTRL_MPLL_CTRL1,    .def = 0x1420500f },
396         { .reg = ANACTRL_MPLL_CTRL2,    .def = 0x00023041 },
397         { .reg = ANACTRL_MPLL_CTRL3,    .def = 0x18180000 },
398         { .reg = ANACTRL_MPLL_CTRL2,    .def = 0x00023001 }
399 };
400
401 static const struct pll_mult_range c3_mclk_pll_mult_range = {
402         .min = 67,
403         .max = 133,
404 };
405
406 static struct clk_regmap mclk_pll_dco = {
407         .data = &(struct meson_clk_pll_data) {
408                 .en = {
409                         .reg_off = ANACTRL_MPLL_CTRL0,
410                         .shift   = 28,
411                         .width   = 1,
412                 },
413                 .m = {
414                         .reg_off = ANACTRL_MPLL_CTRL0,
415                         .shift   = 0,
416                         .width   = 8,
417                 },
418                 .n = {
419                         .reg_off = ANACTRL_MPLL_CTRL0,
420                         .shift   = 16,
421                         .width   = 5,
422                 },
423                 .l = {
424                         .reg_off = ANACTRL_MPLL_CTRL0,
425                         .shift   = 31,
426                         .width   = 1,
427                 },
428                 .rst = {
429                         .reg_off = ANACTRL_MPLL_CTRL0,
430                         .shift   = 29,
431                         .width   = 1,
432                 },
433                 .range = &c3_mclk_pll_mult_range,
434                 .init_regs = c3_mclk_init_regs,
435                 .init_count = ARRAY_SIZE(c3_mclk_init_regs),
436         },
437         .hw.init = &(struct clk_init_data) {
438                 .name = "mclk_pll_dco",
439                 .ops = &meson_clk_pll_ops,
440                 .parent_data = &(const struct clk_parent_data) {
441                         .fw_name = "mclk",
442                 },
443                 .num_parents = 1,
444         },
445 };
446
447 static const struct clk_div_table c3_mpll_od_table[] = {
448         { 0,  1 },
449         { 1,  2 },
450         { 2,  4 },
451         { 3,  8 },
452         { 4, 16 },
453         { /* sentinel */ }
454 };
455
456 static struct clk_regmap mclk_pll_od = {
457         .data = &(struct clk_regmap_div_data) {
458                 .offset = ANACTRL_MPLL_CTRL0,
459                 .shift = 12,
460                 .width = 3,
461                 .table = c3_mpll_od_table,
462         },
463         .hw.init = &(struct clk_init_data) {
464                 .name = "mclk_pll_od",
465                 .ops = &clk_regmap_divider_ops,
466                 .parent_hws = (const struct clk_hw *[]) {
467                         &mclk_pll_dco.hw },
468                 .num_parents = 1,
469                 .flags = CLK_SET_RATE_PARENT,
470         },
471 };
472
473 /* both value 0 and 1 gives divide the input rate by one */
474 static struct clk_regmap mclk_pll = {
475         .data = &(struct clk_regmap_div_data) {
476                 .offset = ANACTRL_MPLL_CTRL4,
477                 .shift = 16,
478                 .width = 5,
479                 .flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
480         },
481         .hw.init = &(struct clk_init_data) {
482                 .name = "mclk_pll",
483                 .ops = &clk_regmap_divider_ops,
484                 .parent_hws = (const struct clk_hw *[]) {
485                         &mclk_pll_od.hw
486                 },
487                 .num_parents = 1,
488                 .flags = CLK_SET_RATE_PARENT,
489         },
490 };
491
492 static const struct clk_parent_data mclk_parent[] = {
493         { .hw = &mclk_pll.hw },
494         { .fw_name = "mclk" },
495         { .hw = &fclk_50m.hw }
496 };
497
498 static struct clk_regmap mclk0_sel = {
499         .data = &(struct clk_regmap_mux_data) {
500                 .offset = ANACTRL_MPLL_CTRL4,
501                 .mask = 0x3,
502                 .shift = 4,
503         },
504         .hw.init = &(struct clk_init_data) {
505                 .name = "mclk0_sel",
506                 .ops = &clk_regmap_mux_ops,
507                 .parent_data = mclk_parent,
508                 .num_parents = ARRAY_SIZE(mclk_parent),
509         },
510 };
511
512 static struct clk_regmap mclk0_div_en = {
513         .data = &(struct clk_regmap_gate_data) {
514                 .offset = ANACTRL_MPLL_CTRL4,
515                 .bit_idx = 1,
516         },
517         .hw.init = &(struct clk_init_data) {
518                 .name = "mclk0_div_en",
519                 .ops = &clk_regmap_gate_ops,
520                 .parent_hws = (const struct clk_hw *[]) {
521                         &mclk0_sel.hw
522                 },
523                 .num_parents = 1,
524                 .flags = CLK_SET_RATE_PARENT,
525         },
526 };
527
528 static struct clk_regmap mclk0_div = {
529         .data = &(struct clk_regmap_div_data) {
530                 .offset = ANACTRL_MPLL_CTRL4,
531                 .shift = 2,
532                 .width = 1,
533         },
534         .hw.init = &(struct clk_init_data) {
535                 .name = "mclk0_div",
536                 .ops = &clk_regmap_divider_ops,
537                 .parent_hws = (const struct clk_hw *[]) {
538                         &mclk0_div_en.hw
539                 },
540                 .num_parents = 1,
541                 .flags = CLK_SET_RATE_PARENT,
542         },
543 };
544
545 static struct clk_regmap mclk0 = {
546         .data = &(struct clk_regmap_gate_data) {
547                 .offset = ANACTRL_MPLL_CTRL4,
548                 .bit_idx = 0,
549         },
550         .hw.init = &(struct clk_init_data) {
551                 .name = "mclk0",
552                 .ops = &clk_regmap_gate_ops,
553                 .parent_hws = (const struct clk_hw *[]) {
554                         &mclk0_div.hw
555                 },
556                 .num_parents = 1,
557                 .flags = CLK_SET_RATE_PARENT,
558         },
559 };
560
561 static struct clk_regmap mclk1_sel = {
562         .data = &(struct clk_regmap_mux_data) {
563                 .offset = ANACTRL_MPLL_CTRL4,
564                 .mask = 0x3,
565                 .shift = 12,
566         },
567         .hw.init = &(struct clk_init_data) {
568                 .name = "mclk1_sel",
569                 .ops = &clk_regmap_mux_ops,
570                 .parent_data = mclk_parent,
571                 .num_parents = ARRAY_SIZE(mclk_parent),
572         },
573 };
574
575 static struct clk_regmap mclk1_div_en = {
576         .data = &(struct clk_regmap_gate_data) {
577                 .offset = ANACTRL_MPLL_CTRL4,
578                 .bit_idx = 9,
579         },
580         .hw.init = &(struct clk_init_data) {
581                 .name = "mclk1_div_en",
582                 .ops = &clk_regmap_gate_ops,
583                 .parent_hws = (const struct clk_hw *[]) {
584                         &mclk1_sel.hw
585                 },
586                 .num_parents = 1,
587                 .flags = CLK_SET_RATE_PARENT,
588         },
589 };
590
591 static struct clk_regmap mclk1_div = {
592         .data = &(struct clk_regmap_div_data) {
593                 .offset = ANACTRL_MPLL_CTRL4,
594                 .shift = 10,
595                 .width = 1,
596         },
597         .hw.init = &(struct clk_init_data) {
598                 .name = "mclk1_div",
599                 .ops = &clk_regmap_divider_ops,
600                 .parent_hws = (const struct clk_hw *[]) {
601                         &mclk1_div_en.hw
602                 },
603                 .num_parents = 1,
604                 .flags = CLK_SET_RATE_PARENT,
605         },
606 };
607
608 static struct clk_regmap mclk1 = {
609         .data = &(struct clk_regmap_gate_data) {
610                 .offset = ANACTRL_MPLL_CTRL4,
611                 .bit_idx = 8,
612         },
613         .hw.init = &(struct clk_init_data) {
614                 .name = "mclk1",
615                 .ops = &clk_regmap_gate_ops,
616                 .parent_hws = (const struct clk_hw *[]) {
617                         &mclk1_div.hw
618                 },
619                 .num_parents = 1,
620                 .flags = CLK_SET_RATE_PARENT,
621         },
622 };
623
624 static struct clk_hw *c3_pll_hw_clks[] = {
625         [CLKID_FCLK_50M_EN]     = &fclk_50m_en.hw,
626         [CLKID_FCLK_50M]        = &fclk_50m.hw,
627         [CLKID_FCLK_DIV2_DIV]   = &fclk_div2_div.hw,
628         [CLKID_FCLK_DIV2]       = &fclk_div2.hw,
629         [CLKID_FCLK_DIV2P5_DIV] = &fclk_div2p5_div.hw,
630         [CLKID_FCLK_DIV2P5]     = &fclk_div2p5.hw,
631         [CLKID_FCLK_DIV3_DIV]   = &fclk_div3_div.hw,
632         [CLKID_FCLK_DIV3]       = &fclk_div3.hw,
633         [CLKID_FCLK_DIV4_DIV]   = &fclk_div4_div.hw,
634         [CLKID_FCLK_DIV4]       = &fclk_div4.hw,
635         [CLKID_FCLK_DIV5_DIV]   = &fclk_div5_div.hw,
636         [CLKID_FCLK_DIV5]       = &fclk_div5.hw,
637         [CLKID_FCLK_DIV7_DIV]   = &fclk_div7_div.hw,
638         [CLKID_FCLK_DIV7]       = &fclk_div7.hw,
639         [CLKID_GP0_PLL_DCO]     = &gp0_pll_dco.hw,
640         [CLKID_GP0_PLL]         = &gp0_pll.hw,
641         [CLKID_HIFI_PLL_DCO]    = &hifi_pll_dco.hw,
642         [CLKID_HIFI_PLL]        = &hifi_pll.hw,
643         [CLKID_MCLK_PLL_DCO]    = &mclk_pll_dco.hw,
644         [CLKID_MCLK_PLL_OD]     = &mclk_pll_od.hw,
645         [CLKID_MCLK_PLL]        = &mclk_pll.hw,
646         [CLKID_MCLK0_SEL]       = &mclk0_sel.hw,
647         [CLKID_MCLK0_SEL_EN]    = &mclk0_div_en.hw,
648         [CLKID_MCLK0_DIV]       = &mclk0_div.hw,
649         [CLKID_MCLK0]           = &mclk0.hw,
650         [CLKID_MCLK1_SEL]       = &mclk1_sel.hw,
651         [CLKID_MCLK1_SEL_EN]    = &mclk1_div_en.hw,
652         [CLKID_MCLK1_DIV]       = &mclk1_div.hw,
653         [CLKID_MCLK1]           = &mclk1.hw
654 };
655
656 /* Convenience table to populate regmap in .probe */
657 static struct clk_regmap *const c3_pll_clk_regmaps[] = {
658         &fclk_50m_en,
659         &fclk_div2,
660         &fclk_div2p5,
661         &fclk_div3,
662         &fclk_div4,
663         &fclk_div5,
664         &fclk_div7,
665         &gp0_pll_dco,
666         &gp0_pll,
667         &hifi_pll_dco,
668         &hifi_pll,
669         &mclk_pll_dco,
670         &mclk_pll_od,
671         &mclk_pll,
672         &mclk0_sel,
673         &mclk0_div_en,
674         &mclk0_div,
675         &mclk0,
676         &mclk1_sel,
677         &mclk1_div_en,
678         &mclk1_div,
679         &mclk1,
680 };
681
682 static const struct regmap_config clkc_regmap_config = {
683         .reg_bits       = 32,
684         .val_bits       = 32,
685         .reg_stride     = 4,
686         .max_register   = ANACTRL_MPLL_CTRL4,
687 };
688
689 static struct meson_clk_hw_data c3_pll_clks = {
690         .hws = c3_pll_hw_clks,
691         .num = ARRAY_SIZE(c3_pll_hw_clks),
692 };
693
694 static int c3_pll_probe(struct platform_device *pdev)
695 {
696         struct device *dev = &pdev->dev;
697         struct regmap *regmap;
698         void __iomem *base;
699         int clkid, ret, i;
700
701         base = devm_platform_ioremap_resource(pdev, 0);
702         if (IS_ERR(base))
703                 return PTR_ERR(base);
704
705         regmap = devm_regmap_init_mmio(dev, base, &clkc_regmap_config);
706         if (IS_ERR(regmap))
707                 return PTR_ERR(regmap);
708
709         /* Populate regmap for the regmap backed clocks */
710         for (i = 0; i < ARRAY_SIZE(c3_pll_clk_regmaps); i++)
711                 c3_pll_clk_regmaps[i]->map = regmap;
712
713         for (clkid = 0; clkid < c3_pll_clks.num; clkid++) {
714                 /* array might be sparse */
715                 if (!c3_pll_clks.hws[clkid])
716                         continue;
717
718                 ret = devm_clk_hw_register(dev, c3_pll_clks.hws[clkid]);
719                 if (ret) {
720                         dev_err(dev, "Clock registration failed\n");
721                         return ret;
722                 }
723         }
724
725         return devm_of_clk_add_hw_provider(dev, meson_clk_hw_get,
726                                            &c3_pll_clks);
727 }
728
729 static const struct of_device_id c3_pll_clkc_match_table[] = {
730         {
731                 .compatible = "amlogic,c3-pll-clkc",
732         },
733         {}
734 };
735 MODULE_DEVICE_TABLE(of, c3_pll_clkc_match_table);
736
737 static struct platform_driver c3_pll_driver = {
738         .probe          = c3_pll_probe,
739         .driver         = {
740                 .name   = "c3-pll-clkc",
741                 .of_match_table = c3_pll_clkc_match_table,
742         },
743 };
744 module_platform_driver(c3_pll_driver);
745
746 MODULE_DESCRIPTION("Amlogic C3 PLL Clock Controller driver");
747 MODULE_AUTHOR("Chuan Liu <[email protected]>");
748 MODULE_LICENSE("GPL");
749 MODULE_IMPORT_NS("CLK_MESON");
This page took 0.105874 seconds and 4 git commands to generate.