]> Git Repo - J-linux.git/blob - drivers/clk/meson/s4-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 / s4-pll.c
1 // SPDX-License-Identifier: (GPL-2.0-only OR MIT)
2 /*
3  * Amlogic S4 PLL Clock Controller Driver
4  *
5  * Copyright (c) 2022-2023 Amlogic, inc. All rights reserved
6  * Author: Yu Tu <[email protected]>
7  */
8
9 #include <linux/clk-provider.h>
10 #include <linux/of_device.h>
11 #include <linux/platform_device.h>
12
13 #include "clk-mpll.h"
14 #include "clk-pll.h"
15 #include "clk-regmap.h"
16 #include "s4-pll.h"
17 #include "meson-clkc-utils.h"
18 #include <dt-bindings/clock/amlogic,s4-pll-clkc.h>
19
20 /*
21  * These clock are a fixed value (fixed_pll is 2GHz) that is initialized by ROMcode.
22  * The chip was changed fixed pll for security reasons. Fixed PLL registers are not writable
23  * in the kernel phase. Write of fixed PLL-related register will cause the system to crash.
24  * Meanwhile, these clock won't ever change at runtime.
25  * For the above reasons, we can only use ro_ops for fixed PLL related clocks.
26  */
27 static struct clk_regmap s4_fixed_pll_dco = {
28         .data = &(struct meson_clk_pll_data){
29                 .en = {
30                         .reg_off = ANACTRL_FIXPLL_CTRL0,
31                         .shift   = 28,
32                         .width   = 1,
33                 },
34                 .m = {
35                         .reg_off = ANACTRL_FIXPLL_CTRL0,
36                         .shift   = 0,
37                         .width   = 8,
38                 },
39                 .frac = {
40                         .reg_off = ANACTRL_FIXPLL_CTRL1,
41                         .shift   = 0,
42                         .width   = 17,
43                 },
44                 .n = {
45                         .reg_off = ANACTRL_FIXPLL_CTRL0,
46                         .shift   = 10,
47                         .width   = 5,
48                 },
49                 .l = {
50                         .reg_off = ANACTRL_FIXPLL_CTRL0,
51                         .shift   = 31,
52                         .width   = 1,
53                 },
54                 .rst = {
55                         .reg_off = ANACTRL_FIXPLL_CTRL0,
56                         .shift   = 29,
57                         .width   = 1,
58                 },
59         },
60         .hw.init = &(struct clk_init_data){
61                 .name = "fixed_pll_dco",
62                 .ops = &meson_clk_pll_ro_ops,
63                 .parent_data = (const struct clk_parent_data []) {
64                         { .fw_name = "xtal", }
65                 },
66                 .num_parents = 1,
67         },
68 };
69
70 static struct clk_regmap s4_fixed_pll = {
71         .data = &(struct clk_regmap_div_data){
72                 .offset = ANACTRL_FIXPLL_CTRL0,
73                 .shift = 16,
74                 .width = 2,
75                 .flags = CLK_DIVIDER_POWER_OF_TWO,
76         },
77         .hw.init = &(struct clk_init_data){
78                 .name = "fixed_pll",
79                 .ops = &clk_regmap_divider_ro_ops,
80                 .parent_hws = (const struct clk_hw *[]) {
81                         &s4_fixed_pll_dco.hw
82                 },
83                 .num_parents = 1,
84                 /*
85                  * This clock won't ever change at runtime so
86                  * CLK_SET_RATE_PARENT is not required
87                  */
88         },
89 };
90
91 static struct clk_fixed_factor s4_fclk_div2_div = {
92         .mult = 1,
93         .div = 2,
94         .hw.init = &(struct clk_init_data){
95                 .name = "fclk_div2_div",
96                 .ops = &clk_fixed_factor_ops,
97                 .parent_hws = (const struct clk_hw *[]) { &s4_fixed_pll.hw },
98                 .num_parents = 1,
99         },
100 };
101
102 static struct clk_regmap s4_fclk_div2 = {
103         .data = &(struct clk_regmap_gate_data){
104                 .offset = ANACTRL_FIXPLL_CTRL1,
105                 .bit_idx = 24,
106         },
107         .hw.init = &(struct clk_init_data){
108                 .name = "fclk_div2",
109                 .ops = &clk_regmap_gate_ro_ops,
110                 .parent_hws = (const struct clk_hw *[]) {
111                         &s4_fclk_div2_div.hw
112                 },
113                 .num_parents = 1,
114         },
115 };
116
117 static struct clk_fixed_factor s4_fclk_div3_div = {
118         .mult = 1,
119         .div = 3,
120         .hw.init = &(struct clk_init_data){
121                 .name = "fclk_div3_div",
122                 .ops = &clk_fixed_factor_ops,
123                 .parent_hws = (const struct clk_hw *[]) { &s4_fixed_pll.hw },
124                 .num_parents = 1,
125         },
126 };
127
128 static struct clk_regmap s4_fclk_div3 = {
129         .data = &(struct clk_regmap_gate_data){
130                 .offset = ANACTRL_FIXPLL_CTRL1,
131                 .bit_idx = 20,
132         },
133         .hw.init = &(struct clk_init_data){
134                 .name = "fclk_div3",
135                 .ops = &clk_regmap_gate_ro_ops,
136                 .parent_hws = (const struct clk_hw *[]) {
137                         &s4_fclk_div3_div.hw
138                 },
139                 .num_parents = 1,
140         },
141 };
142
143 static struct clk_fixed_factor s4_fclk_div4_div = {
144         .mult = 1,
145         .div = 4,
146         .hw.init = &(struct clk_init_data){
147                 .name = "fclk_div4_div",
148                 .ops = &clk_fixed_factor_ops,
149                 .parent_hws = (const struct clk_hw *[]) { &s4_fixed_pll.hw },
150                 .num_parents = 1,
151         },
152 };
153
154 static struct clk_regmap s4_fclk_div4 = {
155         .data = &(struct clk_regmap_gate_data){
156                 .offset = ANACTRL_FIXPLL_CTRL1,
157                 .bit_idx = 21,
158         },
159         .hw.init = &(struct clk_init_data){
160                 .name = "fclk_div4",
161                 .ops = &clk_regmap_gate_ro_ops,
162                 .parent_hws = (const struct clk_hw *[]) {
163                         &s4_fclk_div4_div.hw
164                 },
165                 .num_parents = 1,
166         },
167 };
168
169 static struct clk_fixed_factor s4_fclk_div5_div = {
170         .mult = 1,
171         .div = 5,
172         .hw.init = &(struct clk_init_data){
173                 .name = "fclk_div5_div",
174                 .ops = &clk_fixed_factor_ops,
175                 .parent_hws = (const struct clk_hw *[]) { &s4_fixed_pll.hw },
176                 .num_parents = 1,
177         },
178 };
179
180 static struct clk_regmap s4_fclk_div5 = {
181         .data = &(struct clk_regmap_gate_data){
182                 .offset = ANACTRL_FIXPLL_CTRL1,
183                 .bit_idx = 22,
184         },
185         .hw.init = &(struct clk_init_data){
186                 .name = "fclk_div5",
187                 .ops = &clk_regmap_gate_ro_ops,
188                 .parent_hws = (const struct clk_hw *[]) {
189                         &s4_fclk_div5_div.hw
190                 },
191                 .num_parents = 1,
192         },
193 };
194
195 static struct clk_fixed_factor s4_fclk_div7_div = {
196         .mult = 1,
197         .div = 7,
198         .hw.init = &(struct clk_init_data){
199                 .name = "fclk_div7_div",
200                 .ops = &clk_fixed_factor_ops,
201                 .parent_hws = (const struct clk_hw *[]) { &s4_fixed_pll.hw },
202                 .num_parents = 1,
203         },
204 };
205
206 static struct clk_regmap s4_fclk_div7 = {
207         .data = &(struct clk_regmap_gate_data){
208                 .offset = ANACTRL_FIXPLL_CTRL1,
209                 .bit_idx = 23,
210         },
211         .hw.init = &(struct clk_init_data){
212                 .name = "fclk_div7",
213                 .ops = &clk_regmap_gate_ro_ops,
214                 .parent_hws = (const struct clk_hw *[]) {
215                         &s4_fclk_div7_div.hw
216                 },
217                 .num_parents = 1,
218         },
219 };
220
221 static struct clk_fixed_factor s4_fclk_div2p5_div = {
222         .mult = 2,
223         .div = 5,
224         .hw.init = &(struct clk_init_data){
225                 .name = "fclk_div2p5_div",
226                 .ops = &clk_fixed_factor_ops,
227                 .parent_hws = (const struct clk_hw *[]) {
228                         &s4_fixed_pll.hw
229                 },
230                 .num_parents = 1,
231         },
232 };
233
234 static struct clk_regmap s4_fclk_div2p5 = {
235         .data = &(struct clk_regmap_gate_data){
236                 .offset = ANACTRL_FIXPLL_CTRL1,
237                 .bit_idx = 25,
238         },
239         .hw.init = &(struct clk_init_data){
240                 .name = "fclk_div2p5",
241                 .ops = &clk_regmap_gate_ro_ops,
242                 .parent_hws = (const struct clk_hw *[]) {
243                         &s4_fclk_div2p5_div.hw
244                 },
245                 .num_parents = 1,
246         },
247 };
248
249 static const struct pll_mult_range s4_gp0_pll_mult_range = {
250         .min = 125,
251         .max = 250,
252 };
253
254 /*
255  * Internal gp0 pll emulation configuration parameters
256  */
257 static const struct reg_sequence s4_gp0_init_regs[] = {
258         { .reg = ANACTRL_GP0PLL_CTRL1,  .def = 0x00000000 },
259         { .reg = ANACTRL_GP0PLL_CTRL2,  .def = 0x00000000 },
260         { .reg = ANACTRL_GP0PLL_CTRL3,  .def = 0x48681c00 },
261         { .reg = ANACTRL_GP0PLL_CTRL4,  .def = 0x88770290 },
262         { .reg = ANACTRL_GP0PLL_CTRL5,  .def = 0x39272000 },
263         { .reg = ANACTRL_GP0PLL_CTRL6,  .def = 0x56540000 }
264 };
265
266 static struct clk_regmap s4_gp0_pll_dco = {
267         .data = &(struct meson_clk_pll_data){
268                 .en = {
269                         .reg_off = ANACTRL_GP0PLL_CTRL0,
270                         .shift   = 28,
271                         .width   = 1,
272                 },
273                 .m = {
274                         .reg_off = ANACTRL_GP0PLL_CTRL0,
275                         .shift   = 0,
276                         .width   = 8,
277                 },
278                 .n = {
279                         .reg_off = ANACTRL_GP0PLL_CTRL0,
280                         .shift   = 10,
281                         .width   = 5,
282                 },
283                 .l = {
284                         .reg_off = ANACTRL_GP0PLL_CTRL0,
285                         .shift   = 31,
286                         .width   = 1,
287                 },
288                 .rst = {
289                         .reg_off = ANACTRL_GP0PLL_CTRL0,
290                         .shift   = 29,
291                         .width   = 1,
292                 },
293                 .range = &s4_gp0_pll_mult_range,
294                 .init_regs = s4_gp0_init_regs,
295                 .init_count = ARRAY_SIZE(s4_gp0_init_regs),
296         },
297         .hw.init = &(struct clk_init_data){
298                 .name = "gp0_pll_dco",
299                 .ops = &meson_clk_pll_ops,
300                 .parent_data = (const struct clk_parent_data []) {
301                         { .fw_name = "xtal", }
302                 },
303                 .num_parents = 1,
304         },
305 };
306
307 static struct clk_regmap s4_gp0_pll = {
308         .data = &(struct clk_regmap_div_data){
309                 .offset = ANACTRL_GP0PLL_CTRL0,
310                 .shift = 16,
311                 .width = 3,
312                 .flags = (CLK_DIVIDER_POWER_OF_TWO |
313                           CLK_DIVIDER_ROUND_CLOSEST),
314         },
315         .hw.init = &(struct clk_init_data){
316                 .name = "gp0_pll",
317                 .ops = &clk_regmap_divider_ops,
318                 .parent_hws = (const struct clk_hw *[]) {
319                         &s4_gp0_pll_dco.hw
320                 },
321                 .num_parents = 1,
322                 .flags = CLK_SET_RATE_PARENT,
323         },
324 };
325
326 /*
327  * Internal hifi pll emulation configuration parameters
328  */
329 static const struct reg_sequence s4_hifi_init_regs[] = {
330         { .reg = ANACTRL_HIFIPLL_CTRL2, .def = 0x00000000 },
331         { .reg = ANACTRL_HIFIPLL_CTRL3, .def = 0x6a285c00 },
332         { .reg = ANACTRL_HIFIPLL_CTRL4, .def = 0x65771290 },
333         { .reg = ANACTRL_HIFIPLL_CTRL5, .def = 0x39272000 },
334         { .reg = ANACTRL_HIFIPLL_CTRL6, .def = 0x56540000 }
335 };
336
337 static struct clk_regmap s4_hifi_pll_dco = {
338         .data = &(struct meson_clk_pll_data){
339                 .en = {
340                         .reg_off = ANACTRL_HIFIPLL_CTRL0,
341                         .shift   = 28,
342                         .width   = 1,
343                 },
344                 .m = {
345                         .reg_off = ANACTRL_HIFIPLL_CTRL0,
346                         .shift   = 0,
347                         .width   = 8,
348                 },
349                 .n = {
350                         .reg_off = ANACTRL_HIFIPLL_CTRL0,
351                         .shift   = 10,
352                         .width   = 5,
353                 },
354                 .frac = {
355                         .reg_off = ANACTRL_HIFIPLL_CTRL1,
356                         .shift   = 0,
357                         .width   = 17,
358                 },
359                 .l = {
360                         .reg_off = ANACTRL_HIFIPLL_CTRL0,
361                         .shift   = 31,
362                         .width   = 1,
363                 },
364                 .rst = {
365                         .reg_off = ANACTRL_HIFIPLL_CTRL0,
366                         .shift   = 29,
367                         .width   = 1,
368                 },
369                 .range = &s4_gp0_pll_mult_range,
370                 .init_regs = s4_hifi_init_regs,
371                 .init_count = ARRAY_SIZE(s4_hifi_init_regs),
372                 .frac_max = 100000,
373                 .flags = CLK_MESON_PLL_ROUND_CLOSEST,
374         },
375         .hw.init = &(struct clk_init_data){
376                 .name = "hifi_pll_dco",
377                 .ops = &meson_clk_pll_ops,
378                 .parent_data = (const struct clk_parent_data []) {
379                         { .fw_name = "xtal", }
380                 },
381                 .num_parents = 1,
382         },
383 };
384
385 static struct clk_regmap s4_hifi_pll = {
386         .data = &(struct clk_regmap_div_data){
387                 .offset = ANACTRL_HIFIPLL_CTRL0,
388                 .shift = 16,
389                 .width = 2,
390                 .flags = (CLK_DIVIDER_POWER_OF_TWO |
391                           CLK_DIVIDER_ROUND_CLOSEST),
392         },
393         .hw.init = &(struct clk_init_data){
394                 .name = "hifi_pll",
395                 .ops = &clk_regmap_divider_ops,
396                 .parent_hws = (const struct clk_hw *[]) {
397                         &s4_hifi_pll_dco.hw
398                 },
399                 .num_parents = 1,
400                 .flags = CLK_SET_RATE_PARENT,
401         },
402 };
403
404 static struct clk_regmap s4_hdmi_pll_dco = {
405         .data = &(struct meson_clk_pll_data){
406                 .en = {
407                         .reg_off = ANACTRL_HDMIPLL_CTRL0,
408                         .shift   = 28,
409                         .width   = 1,
410                 },
411                 .m = {
412                         .reg_off = ANACTRL_HDMIPLL_CTRL0,
413                         .shift   = 0,
414                         .width   = 8,
415                 },
416                 .n = {
417                         .reg_off = ANACTRL_HDMIPLL_CTRL0,
418                         .shift   = 10,
419                         .width   = 5,
420                 },
421                 .l = {
422                         .reg_off = ANACTRL_HDMIPLL_CTRL0,
423                         .shift   = 31,
424                         .width   = 1,
425                 },
426                 .rst = {
427                         .reg_off = ANACTRL_HDMIPLL_CTRL0,
428                         .shift   = 29,
429                         .width   = 1,
430                 },
431                 .range = &s4_gp0_pll_mult_range,
432         },
433         .hw.init = &(struct clk_init_data){
434                 .name = "hdmi_pll_dco",
435                 .ops = &meson_clk_pll_ops,
436                 .parent_data = (const struct clk_parent_data []) {
437                         { .fw_name = "xtal", }
438                 },
439                 .num_parents = 1,
440         },
441 };
442
443 static struct clk_regmap s4_hdmi_pll_od = {
444         .data = &(struct clk_regmap_div_data){
445                 .offset = ANACTRL_HDMIPLL_CTRL0,
446                 .shift = 16,
447                 .width = 4,
448                 .flags = CLK_DIVIDER_POWER_OF_TWO,
449         },
450         .hw.init = &(struct clk_init_data){
451                 .name = "hdmi_pll_od",
452                 .ops = &clk_regmap_divider_ops,
453                 .parent_hws = (const struct clk_hw *[]) {
454                         &s4_hdmi_pll_dco.hw
455                 },
456                 .num_parents = 1,
457                 .flags = CLK_SET_RATE_PARENT,
458         },
459 };
460
461 static struct clk_regmap s4_hdmi_pll = {
462         .data = &(struct clk_regmap_div_data){
463                 .offset = ANACTRL_HDMIPLL_CTRL0,
464                 .shift = 20,
465                 .width = 2,
466                 .flags = CLK_DIVIDER_POWER_OF_TWO,
467         },
468         .hw.init = &(struct clk_init_data){
469                 .name = "hdmi_pll",
470                 .ops = &clk_regmap_divider_ops,
471                 .parent_hws = (const struct clk_hw *[]) {
472                         &s4_hdmi_pll_od.hw
473                 },
474                 .num_parents = 1,
475                 .flags = CLK_SET_RATE_PARENT,
476         },
477 };
478
479 static struct clk_fixed_factor s4_mpll_50m_div = {
480         .mult = 1,
481         .div = 80,
482         .hw.init = &(struct clk_init_data){
483                 .name = "mpll_50m_div",
484                 .ops = &clk_fixed_factor_ops,
485                 .parent_hws = (const struct clk_hw *[]) {
486                         &s4_fixed_pll_dco.hw
487                 },
488                 .num_parents = 1,
489         },
490 };
491
492 static struct clk_regmap s4_mpll_50m = {
493         .data = &(struct clk_regmap_mux_data){
494                 .offset = ANACTRL_FIXPLL_CTRL3,
495                 .mask = 0x1,
496                 .shift = 5,
497         },
498         .hw.init = &(struct clk_init_data){
499                 .name = "mpll_50m",
500                 .ops = &clk_regmap_mux_ro_ops,
501                 .parent_data = (const struct clk_parent_data []) {
502                         { .fw_name = "xtal", },
503                         { .hw = &s4_mpll_50m_div.hw },
504                 },
505                 .num_parents = 2,
506         },
507 };
508
509 static struct clk_fixed_factor s4_mpll_prediv = {
510         .mult = 1,
511         .div = 2,
512         .hw.init = &(struct clk_init_data){
513                 .name = "mpll_prediv",
514                 .ops = &clk_fixed_factor_ops,
515                 .parent_hws = (const struct clk_hw *[]) {
516                         &s4_fixed_pll_dco.hw
517                 },
518                 .num_parents = 1,
519         },
520 };
521
522 static const struct reg_sequence s4_mpll0_init_regs[] = {
523         { .reg = ANACTRL_MPLL_CTRL2, .def = 0x40000033 }
524 };
525
526 static struct clk_regmap s4_mpll0_div = {
527         .data = &(struct meson_clk_mpll_data){
528                 .sdm = {
529                         .reg_off = ANACTRL_MPLL_CTRL1,
530                         .shift   = 0,
531                         .width   = 14,
532                 },
533                 .sdm_en = {
534                         .reg_off = ANACTRL_MPLL_CTRL1,
535                         .shift   = 30,
536                         .width   = 1,
537                 },
538                 .n2 = {
539                         .reg_off = ANACTRL_MPLL_CTRL1,
540                         .shift   = 20,
541                         .width   = 9,
542                 },
543                 .ssen = {
544                         .reg_off = ANACTRL_MPLL_CTRL1,
545                         .shift   = 29,
546                         .width   = 1,
547                 },
548                 .init_regs = s4_mpll0_init_regs,
549                 .init_count = ARRAY_SIZE(s4_mpll0_init_regs),
550         },
551         .hw.init = &(struct clk_init_data){
552                 .name = "mpll0_div",
553                 .ops = &meson_clk_mpll_ops,
554                 .parent_hws = (const struct clk_hw *[]) {
555                         &s4_mpll_prediv.hw
556                 },
557                 .num_parents = 1,
558         },
559 };
560
561 static struct clk_regmap s4_mpll0 = {
562         .data = &(struct clk_regmap_gate_data){
563                 .offset = ANACTRL_MPLL_CTRL1,
564                 .bit_idx = 31,
565         },
566         .hw.init = &(struct clk_init_data){
567                 .name = "mpll0",
568                 .ops = &clk_regmap_gate_ops,
569                 .parent_hws = (const struct clk_hw *[]) { &s4_mpll0_div.hw },
570                 .num_parents = 1,
571                 .flags = CLK_SET_RATE_PARENT,
572         },
573 };
574
575 static const struct reg_sequence s4_mpll1_init_regs[] = {
576         { .reg = ANACTRL_MPLL_CTRL4,    .def = 0x40000033 }
577 };
578
579 static struct clk_regmap s4_mpll1_div = {
580         .data = &(struct meson_clk_mpll_data){
581                 .sdm = {
582                         .reg_off = ANACTRL_MPLL_CTRL3,
583                         .shift   = 0,
584                         .width   = 14,
585                 },
586                 .sdm_en = {
587                         .reg_off = ANACTRL_MPLL_CTRL3,
588                         .shift   = 30,
589                         .width   = 1,
590                 },
591                 .n2 = {
592                         .reg_off = ANACTRL_MPLL_CTRL3,
593                         .shift   = 20,
594                         .width   = 9,
595                 },
596                 .ssen = {
597                         .reg_off = ANACTRL_MPLL_CTRL3,
598                         .shift   = 29,
599                         .width   = 1,
600                 },
601                 .init_regs = s4_mpll1_init_regs,
602                 .init_count = ARRAY_SIZE(s4_mpll1_init_regs),
603         },
604         .hw.init = &(struct clk_init_data){
605                 .name = "mpll1_div",
606                 .ops = &meson_clk_mpll_ops,
607                 .parent_hws = (const struct clk_hw *[]) {
608                         &s4_mpll_prediv.hw
609                 },
610                 .num_parents = 1,
611         },
612 };
613
614 static struct clk_regmap s4_mpll1 = {
615         .data = &(struct clk_regmap_gate_data){
616                 .offset = ANACTRL_MPLL_CTRL3,
617                 .bit_idx = 31,
618         },
619         .hw.init = &(struct clk_init_data){
620                 .name = "mpll1",
621                 .ops = &clk_regmap_gate_ops,
622                 .parent_hws = (const struct clk_hw *[]) { &s4_mpll1_div.hw },
623                 .num_parents = 1,
624                 .flags = CLK_SET_RATE_PARENT,
625         },
626 };
627
628 static const struct reg_sequence s4_mpll2_init_regs[] = {
629         { .reg = ANACTRL_MPLL_CTRL6, .def = 0x40000033 }
630 };
631
632 static struct clk_regmap s4_mpll2_div = {
633         .data = &(struct meson_clk_mpll_data){
634                 .sdm = {
635                         .reg_off = ANACTRL_MPLL_CTRL5,
636                         .shift   = 0,
637                         .width   = 14,
638                 },
639                 .sdm_en = {
640                         .reg_off = ANACTRL_MPLL_CTRL5,
641                         .shift   = 30,
642                         .width   = 1,
643                 },
644                 .n2 = {
645                         .reg_off = ANACTRL_MPLL_CTRL5,
646                         .shift   = 20,
647                         .width   = 9,
648                 },
649                 .ssen = {
650                         .reg_off = ANACTRL_MPLL_CTRL5,
651                         .shift   = 29,
652                         .width   = 1,
653                 },
654                 .init_regs = s4_mpll2_init_regs,
655                 .init_count = ARRAY_SIZE(s4_mpll2_init_regs),
656         },
657         .hw.init = &(struct clk_init_data){
658                 .name = "mpll2_div",
659                 .ops = &meson_clk_mpll_ops,
660                 .parent_hws = (const struct clk_hw *[]) {
661                         &s4_mpll_prediv.hw
662                 },
663                 .num_parents = 1,
664         },
665 };
666
667 static struct clk_regmap s4_mpll2 = {
668         .data = &(struct clk_regmap_gate_data){
669                 .offset = ANACTRL_MPLL_CTRL5,
670                 .bit_idx = 31,
671         },
672         .hw.init = &(struct clk_init_data){
673                 .name = "mpll2",
674                 .ops = &clk_regmap_gate_ops,
675                 .parent_hws = (const struct clk_hw *[]) { &s4_mpll2_div.hw },
676                 .num_parents = 1,
677                 .flags = CLK_SET_RATE_PARENT,
678         },
679 };
680
681 static const struct reg_sequence s4_mpll3_init_regs[] = {
682         { .reg = ANACTRL_MPLL_CTRL8, .def = 0x40000033 }
683 };
684
685 static struct clk_regmap s4_mpll3_div = {
686         .data = &(struct meson_clk_mpll_data){
687                 .sdm = {
688                         .reg_off = ANACTRL_MPLL_CTRL7,
689                         .shift   = 0,
690                         .width   = 14,
691                 },
692                 .sdm_en = {
693                         .reg_off = ANACTRL_MPLL_CTRL7,
694                         .shift   = 30,
695                         .width   = 1,
696                 },
697                 .n2 = {
698                         .reg_off = ANACTRL_MPLL_CTRL7,
699                         .shift   = 20,
700                         .width   = 9,
701                 },
702                 .ssen = {
703                         .reg_off = ANACTRL_MPLL_CTRL7,
704                         .shift   = 29,
705                         .width   = 1,
706                 },
707                 .init_regs = s4_mpll3_init_regs,
708                 .init_count = ARRAY_SIZE(s4_mpll3_init_regs),
709         },
710         .hw.init = &(struct clk_init_data){
711                 .name = "mpll3_div",
712                 .ops = &meson_clk_mpll_ops,
713                 .parent_hws = (const struct clk_hw *[]) {
714                         &s4_mpll_prediv.hw
715                 },
716                 .num_parents = 1,
717         },
718 };
719
720 static struct clk_regmap s4_mpll3 = {
721         .data = &(struct clk_regmap_gate_data){
722                 .offset = ANACTRL_MPLL_CTRL7,
723                 .bit_idx = 31,
724         },
725         .hw.init = &(struct clk_init_data){
726                 .name = "mpll3",
727                 .ops = &clk_regmap_gate_ops,
728                 .parent_hws = (const struct clk_hw *[]) { &s4_mpll3_div.hw },
729                 .num_parents = 1,
730                 .flags = CLK_SET_RATE_PARENT,
731         },
732 };
733
734 /* Array of all clocks provided by this provider */
735 static struct clk_hw *s4_pll_hw_clks[] = {
736         [CLKID_FIXED_PLL_DCO]           = &s4_fixed_pll_dco.hw,
737         [CLKID_FIXED_PLL]               = &s4_fixed_pll.hw,
738         [CLKID_FCLK_DIV2_DIV]           = &s4_fclk_div2_div.hw,
739         [CLKID_FCLK_DIV2]               = &s4_fclk_div2.hw,
740         [CLKID_FCLK_DIV3_DIV]           = &s4_fclk_div3_div.hw,
741         [CLKID_FCLK_DIV3]               = &s4_fclk_div3.hw,
742         [CLKID_FCLK_DIV4_DIV]           = &s4_fclk_div4_div.hw,
743         [CLKID_FCLK_DIV4]               = &s4_fclk_div4.hw,
744         [CLKID_FCLK_DIV5_DIV]           = &s4_fclk_div5_div.hw,
745         [CLKID_FCLK_DIV5]               = &s4_fclk_div5.hw,
746         [CLKID_FCLK_DIV7_DIV]           = &s4_fclk_div7_div.hw,
747         [CLKID_FCLK_DIV7]               = &s4_fclk_div7.hw,
748         [CLKID_FCLK_DIV2P5_DIV]         = &s4_fclk_div2p5_div.hw,
749         [CLKID_FCLK_DIV2P5]             = &s4_fclk_div2p5.hw,
750         [CLKID_GP0_PLL_DCO]             = &s4_gp0_pll_dco.hw,
751         [CLKID_GP0_PLL]                 = &s4_gp0_pll.hw,
752         [CLKID_HIFI_PLL_DCO]            = &s4_hifi_pll_dco.hw,
753         [CLKID_HIFI_PLL]                = &s4_hifi_pll.hw,
754         [CLKID_HDMI_PLL_DCO]            = &s4_hdmi_pll_dco.hw,
755         [CLKID_HDMI_PLL_OD]             = &s4_hdmi_pll_od.hw,
756         [CLKID_HDMI_PLL]                = &s4_hdmi_pll.hw,
757         [CLKID_MPLL_50M_DIV]            = &s4_mpll_50m_div.hw,
758         [CLKID_MPLL_50M]                = &s4_mpll_50m.hw,
759         [CLKID_MPLL_PREDIV]             = &s4_mpll_prediv.hw,
760         [CLKID_MPLL0_DIV]               = &s4_mpll0_div.hw,
761         [CLKID_MPLL0]                   = &s4_mpll0.hw,
762         [CLKID_MPLL1_DIV]               = &s4_mpll1_div.hw,
763         [CLKID_MPLL1]                   = &s4_mpll1.hw,
764         [CLKID_MPLL2_DIV]               = &s4_mpll2_div.hw,
765         [CLKID_MPLL2]                   = &s4_mpll2.hw,
766         [CLKID_MPLL3_DIV]               = &s4_mpll3_div.hw,
767         [CLKID_MPLL3]                   = &s4_mpll3.hw,
768 };
769
770 static struct clk_regmap *const s4_pll_clk_regmaps[] = {
771         &s4_fixed_pll_dco,
772         &s4_fixed_pll,
773         &s4_fclk_div2,
774         &s4_fclk_div3,
775         &s4_fclk_div4,
776         &s4_fclk_div5,
777         &s4_fclk_div7,
778         &s4_fclk_div2p5,
779         &s4_gp0_pll_dco,
780         &s4_gp0_pll,
781         &s4_hifi_pll_dco,
782         &s4_hifi_pll,
783         &s4_hdmi_pll_dco,
784         &s4_hdmi_pll_od,
785         &s4_hdmi_pll,
786         &s4_mpll_50m,
787         &s4_mpll0_div,
788         &s4_mpll0,
789         &s4_mpll1_div,
790         &s4_mpll1,
791         &s4_mpll2_div,
792         &s4_mpll2,
793         &s4_mpll3_div,
794         &s4_mpll3,
795 };
796
797 static const struct reg_sequence s4_init_regs[] = {
798         { .reg = ANACTRL_MPLL_CTRL0,    .def = 0x00000543 },
799 };
800
801 static const struct regmap_config clkc_regmap_config = {
802         .reg_bits       = 32,
803         .val_bits       = 32,
804         .reg_stride     = 4,
805         .max_register   = ANACTRL_HDMIPLL_CTRL0,
806 };
807
808 static struct meson_clk_hw_data s4_pll_clks = {
809         .hws = s4_pll_hw_clks,
810         .num = ARRAY_SIZE(s4_pll_hw_clks),
811 };
812
813 static int meson_s4_pll_probe(struct platform_device *pdev)
814 {
815         struct device *dev = &pdev->dev;
816         struct regmap *regmap;
817         void __iomem *base;
818         int ret, i;
819
820         base = devm_platform_ioremap_resource(pdev, 0);
821         if (IS_ERR(base))
822                 return dev_err_probe(dev, PTR_ERR(base),
823                                      "can't ioremap resource\n");
824
825         regmap = devm_regmap_init_mmio(dev, base, &clkc_regmap_config);
826         if (IS_ERR(regmap))
827                 return dev_err_probe(dev, PTR_ERR(regmap),
828                                      "can't init regmap mmio region\n");
829
830         ret = regmap_multi_reg_write(regmap, s4_init_regs, ARRAY_SIZE(s4_init_regs));
831         if (ret)
832                 return dev_err_probe(dev, ret,
833                                      "Failed to init registers\n");
834
835         /* Populate regmap for the regmap backed clocks */
836         for (i = 0; i < ARRAY_SIZE(s4_pll_clk_regmaps); i++)
837                 s4_pll_clk_regmaps[i]->map = regmap;
838
839         /* Register clocks */
840         for (i = 0; i < s4_pll_clks.num; i++) {
841                 /* array might be sparse */
842                 if (!s4_pll_clks.hws[i])
843                         continue;
844
845                 ret = devm_clk_hw_register(dev, s4_pll_clks.hws[i]);
846                 if (ret)
847                         return dev_err_probe(dev, ret,
848                                              "clock[%d] registration failed\n", i);
849         }
850
851         return devm_of_clk_add_hw_provider(dev, meson_clk_hw_get,
852                                            &s4_pll_clks);
853 }
854
855 static const struct of_device_id clkc_match_table[] = {
856         {
857                 .compatible = "amlogic,s4-pll-clkc",
858         },
859         {}
860 };
861 MODULE_DEVICE_TABLE(of, clkc_match_table);
862
863 static struct platform_driver s4_driver = {
864         .probe          = meson_s4_pll_probe,
865         .driver         = {
866                 .name   = "s4-pll-clkc",
867                 .of_match_table = clkc_match_table,
868         },
869 };
870 module_platform_driver(s4_driver);
871
872 MODULE_DESCRIPTION("Amlogic S4 PLL Clock Controller driver");
873 MODULE_AUTHOR("Yu Tu <[email protected]>");
874 MODULE_LICENSE("GPL");
875 MODULE_IMPORT_NS("CLK_MESON");
This page took 0.07795 seconds and 4 git commands to generate.