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