]> Git Repo - J-linux.git/blob - drivers/clk/at91/sama7g5.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 / at91 / sama7g5.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * SAMA7G5 PMC code.
4  *
5  * Copyright (C) 2020 Microchip Technology Inc. and its subsidiaries
6  *
7  * Author: Claudiu Beznea <[email protected]>
8  *
9  */
10 #include <linux/clk.h>
11 #include <linux/clk-provider.h>
12 #include <linux/mfd/syscon.h>
13 #include <linux/slab.h>
14
15 #include <dt-bindings/clock/at91.h>
16
17 #include "pmc.h"
18
19 static DEFINE_SPINLOCK(pmc_pll_lock);
20 static DEFINE_SPINLOCK(pmc_mck0_lock);
21 static DEFINE_SPINLOCK(pmc_mckX_lock);
22
23 /*
24  * PLL clocks identifiers
25  * @PLL_ID_CPU:         CPU PLL identifier
26  * @PLL_ID_SYS:         System PLL identifier
27  * @PLL_ID_DDR:         DDR PLL identifier
28  * @PLL_ID_IMG:         Image subsystem PLL identifier
29  * @PLL_ID_BAUD:        Baud PLL identifier
30  * @PLL_ID_AUDIO:       Audio PLL identifier
31  * @PLL_ID_ETH:         Ethernet PLL identifier
32  */
33 enum pll_ids {
34         PLL_ID_CPU,
35         PLL_ID_SYS,
36         PLL_ID_DDR,
37         PLL_ID_IMG,
38         PLL_ID_BAUD,
39         PLL_ID_AUDIO,
40         PLL_ID_ETH,
41         PLL_ID_MAX,
42 };
43
44 /*
45  * PLL component identifier
46  * @PLL_COMPID_FRAC: Fractional PLL component identifier
47  * @PLL_COMPID_DIV0: 1st PLL divider component identifier
48  * @PLL_COMPID_DIV1: 2nd PLL divider component identifier
49  */
50 enum pll_component_id {
51         PLL_COMPID_FRAC,
52         PLL_COMPID_DIV0,
53         PLL_COMPID_DIV1,
54         PLL_COMPID_MAX,
55 };
56
57 /*
58  * PLL type identifiers
59  * @PLL_TYPE_FRAC:      fractional PLL identifier
60  * @PLL_TYPE_DIV:       divider PLL identifier
61  */
62 enum pll_type {
63         PLL_TYPE_FRAC,
64         PLL_TYPE_DIV,
65 };
66
67 /* Layout for fractional PLLs. */
68 static const struct clk_pll_layout pll_layout_frac = {
69         .mul_mask       = GENMASK(31, 24),
70         .frac_mask      = GENMASK(21, 0),
71         .mul_shift      = 24,
72         .frac_shift     = 0,
73 };
74
75 /* Layout for DIVPMC dividers. */
76 static const struct clk_pll_layout pll_layout_divpmc = {
77         .div_mask       = GENMASK(7, 0),
78         .endiv_mask     = BIT(29),
79         .div_shift      = 0,
80         .endiv_shift    = 29,
81 };
82
83 /* Layout for DIVIO dividers. */
84 static const struct clk_pll_layout pll_layout_divio = {
85         .div_mask       = GENMASK(19, 12),
86         .endiv_mask     = BIT(30),
87         .div_shift      = 12,
88         .endiv_shift    = 30,
89 };
90
91 /*
92  * CPU PLL output range.
93  * Notice: The upper limit has been setup to 1000000002 due to hardware
94  * block which cannot output exactly 1GHz.
95  */
96 static const struct clk_range cpu_pll_outputs[] = {
97         { .min = 2343750, .max = 1000000002 },
98 };
99
100 /* PLL output range. */
101 static const struct clk_range pll_outputs[] = {
102         { .min = 2343750, .max = 1200000000 },
103 };
104
105 /* Fractional PLL core output range. */
106 static const struct clk_range core_outputs[] = {
107         { .min = 600000000, .max = 1200000000 },
108 };
109
110 /* CPU PLL characteristics. */
111 static const struct clk_pll_characteristics cpu_pll_characteristics = {
112         .input = { .min = 12000000, .max = 50000000 },
113         .num_output = ARRAY_SIZE(cpu_pll_outputs),
114         .output = cpu_pll_outputs,
115         .core_output = core_outputs,
116 };
117
118 /* PLL characteristics. */
119 static const struct clk_pll_characteristics pll_characteristics = {
120         .input = { .min = 12000000, .max = 50000000 },
121         .num_output = ARRAY_SIZE(pll_outputs),
122         .output = pll_outputs,
123         .core_output = core_outputs,
124 };
125
126 /*
127  * SAMA7G5 PLL possible parents
128  * @SAMA7G5_PLL_PARENT_MAINCK: MAINCK is PLL a parent
129  * @SAMA7G5_PLL_PARENT_MAIN_XTAL: MAIN XTAL is a PLL parent
130  * @SAMA7G5_PLL_PARENT_FRACCK: Frac PLL is a PLL parent (for PLL dividers)
131  */
132 enum sama7g5_pll_parent {
133         SAMA7G5_PLL_PARENT_MAINCK,
134         SAMA7G5_PLL_PARENT_MAIN_XTAL,
135         SAMA7G5_PLL_PARENT_FRACCK,
136 };
137
138 /*
139  * PLL clocks description
140  * @n:          clock name
141  * @l:          clock layout
142  * @c:          clock characteristics
143  * @hw:         pointer to clk_hw
144  * @t:          clock type
145  * @f:          clock flags
146  * @p:          clock parent
147  * @eid:        export index in sama7g5->chws[] array
148  * @safe_div:   intermediate divider need to be set on PRE_RATE_CHANGE
149  *              notification
150  */
151 static struct sama7g5_pll {
152         const char *n;
153         const struct clk_pll_layout *l;
154         const struct clk_pll_characteristics *c;
155         struct clk_hw *hw;
156         unsigned long f;
157         enum sama7g5_pll_parent p;
158         u8 t;
159         u8 eid;
160         u8 safe_div;
161 } sama7g5_plls[][PLL_COMPID_MAX] = {
162         [PLL_ID_CPU] = {
163                 [PLL_COMPID_FRAC] = {
164                         .n = "cpupll_fracck",
165                         .p = SAMA7G5_PLL_PARENT_MAINCK,
166                         .l = &pll_layout_frac,
167                         .c = &cpu_pll_characteristics,
168                         .t = PLL_TYPE_FRAC,
169                         /*
170                          * This feeds cpupll_divpmcck which feeds CPU. It should
171                          * not be disabled.
172                          */
173                         .f = CLK_IS_CRITICAL,
174                 },
175
176                 [PLL_COMPID_DIV0] = {
177                         .n = "cpupll_divpmcck",
178                         .p = SAMA7G5_PLL_PARENT_FRACCK,
179                         .l = &pll_layout_divpmc,
180                         .c = &cpu_pll_characteristics,
181                         .t = PLL_TYPE_DIV,
182                         /* This feeds CPU. It should not be disabled. */
183                         .f = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT,
184                         .eid = PMC_CPUPLL,
185                         /*
186                          * Safe div=15 should be safe even for switching b/w 1GHz and
187                          * 90MHz (frac pll might go up to 1.2GHz).
188                          */
189                         .safe_div = 15,
190                 },
191         },
192
193         [PLL_ID_SYS] = {
194                 [PLL_COMPID_FRAC] = {
195                         .n = "syspll_fracck",
196                         .p = SAMA7G5_PLL_PARENT_MAINCK,
197                         .l = &pll_layout_frac,
198                         .c = &pll_characteristics,
199                         .t = PLL_TYPE_FRAC,
200                         /*
201                          * This feeds syspll_divpmcck which may feed critical parts
202                          * of the systems like timers. Therefore it should not be
203                          * disabled.
204                          */
205                         .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,
206                 },
207
208                 [PLL_COMPID_DIV0] = {
209                         .n = "syspll_divpmcck",
210                         .p = SAMA7G5_PLL_PARENT_FRACCK,
211                         .l = &pll_layout_divpmc,
212                         .c = &pll_characteristics,
213                         .t = PLL_TYPE_DIV,
214                         /*
215                          * This may feed critical parts of the systems like timers.
216                          * Therefore it should not be disabled.
217                          */
218                         .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,
219                         .eid = PMC_SYSPLL,
220                 },
221         },
222
223         [PLL_ID_DDR] = {
224                 [PLL_COMPID_FRAC] = {
225                         .n = "ddrpll_fracck",
226                         .p = SAMA7G5_PLL_PARENT_MAINCK,
227                         .l = &pll_layout_frac,
228                         .c = &pll_characteristics,
229                         .t = PLL_TYPE_FRAC,
230                         /*
231                          * This feeds ddrpll_divpmcck which feeds DDR. It should not
232                          * be disabled.
233                          */
234                         .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,
235                 },
236
237                 [PLL_COMPID_DIV0] = {
238                         .n = "ddrpll_divpmcck",
239                         .p = SAMA7G5_PLL_PARENT_FRACCK,
240                         .l = &pll_layout_divpmc,
241                         .c = &pll_characteristics,
242                         .t = PLL_TYPE_DIV,
243                         /* This feeds DDR. It should not be disabled. */
244                         .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,
245                 },
246         },
247
248         [PLL_ID_IMG] = {
249                 [PLL_COMPID_FRAC] = {
250                         .n = "imgpll_fracck",
251                         .p = SAMA7G5_PLL_PARENT_MAINCK,
252                         .l = &pll_layout_frac,
253                         .c = &pll_characteristics,
254                         .t = PLL_TYPE_FRAC,
255                         .f = CLK_SET_RATE_GATE,
256                 },
257
258                 [PLL_COMPID_DIV0] = {
259                         .n = "imgpll_divpmcck",
260                         .p = SAMA7G5_PLL_PARENT_FRACCK,
261                         .l = &pll_layout_divpmc,
262                         .c = &pll_characteristics,
263                         .t = PLL_TYPE_DIV,
264                         .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
265                              CLK_SET_RATE_PARENT,
266                 },
267         },
268
269         [PLL_ID_BAUD] = {
270                 [PLL_COMPID_FRAC] = {
271                         .n = "baudpll_fracck",
272                         .p = SAMA7G5_PLL_PARENT_MAINCK,
273                         .l = &pll_layout_frac,
274                         .c = &pll_characteristics,
275                         .t = PLL_TYPE_FRAC,
276                         .f = CLK_SET_RATE_GATE, },
277
278                 [PLL_COMPID_DIV0] = {
279                         .n = "baudpll_divpmcck",
280                         .p = SAMA7G5_PLL_PARENT_FRACCK,
281                         .l = &pll_layout_divpmc,
282                         .c = &pll_characteristics,
283                         .t = PLL_TYPE_DIV,
284                         .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
285                              CLK_SET_RATE_PARENT,
286                 },
287         },
288
289         [PLL_ID_AUDIO] = {
290                 [PLL_COMPID_FRAC] = {
291                         .n = "audiopll_fracck",
292                         .p = SAMA7G5_PLL_PARENT_MAIN_XTAL,
293                         .l = &pll_layout_frac,
294                         .c = &pll_characteristics,
295                         .t = PLL_TYPE_FRAC,
296                         .f = CLK_SET_RATE_GATE,
297                 },
298
299                 [PLL_COMPID_DIV0] = {
300                         .n = "audiopll_divpmcck",
301                         .p = SAMA7G5_PLL_PARENT_FRACCK,
302                         .l = &pll_layout_divpmc,
303                         .c = &pll_characteristics,
304                         .t = PLL_TYPE_DIV,
305                         .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
306                              CLK_SET_RATE_PARENT,
307                         .eid = PMC_AUDIOPMCPLL,
308                 },
309
310                 [PLL_COMPID_DIV1] = {
311                         .n = "audiopll_diviock",
312                         .p = SAMA7G5_PLL_PARENT_FRACCK,
313                         .l = &pll_layout_divio,
314                         .c = &pll_characteristics,
315                         .t = PLL_TYPE_DIV,
316                         .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
317                              CLK_SET_RATE_PARENT,
318                         .eid = PMC_AUDIOIOPLL,
319                 },
320         },
321
322         [PLL_ID_ETH] = {
323                 [PLL_COMPID_FRAC] = {
324                         .n = "ethpll_fracck",
325                         .p = SAMA7G5_PLL_PARENT_MAIN_XTAL,
326                         .l = &pll_layout_frac,
327                         .c = &pll_characteristics,
328                         .t = PLL_TYPE_FRAC,
329                         .f = CLK_SET_RATE_GATE,
330                 },
331
332                 [PLL_COMPID_DIV0] = {
333                         .n = "ethpll_divpmcck",
334                         .p = SAMA7G5_PLL_PARENT_FRACCK,
335                         .l = &pll_layout_divpmc,
336                         .c = &pll_characteristics,
337                         .t = PLL_TYPE_DIV,
338                         .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
339                              CLK_SET_RATE_PARENT,
340                 },
341         },
342 };
343
344 /* Used to create an array entry identifying a PLL by its components. */
345 #define PLL_IDS_TO_ARR_ENTRY(_id, _comp) { PLL_ID_##_id, PLL_COMPID_##_comp}
346
347 /*
348  * Master clock (MCK[1..4]) description
349  * @n:                  clock name
350  * @ep:                 extra parents names array (entry formed by PLL components
351  *                      identifiers (see enum pll_component_id))
352  * @hw:                 pointer to clk_hw
353  * @ep_chg_id:          index in parents array that specifies the changeable
354  *                      parent
355  * @ep_count:           extra parents count
356  * @ep_mux_table:       mux table for extra parents
357  * @id:                 clock id
358  * @eid:                export index in sama7g5->chws[] array
359  * @c:                  true if clock is critical and cannot be disabled
360  */
361 static struct {
362         const char *n;
363         struct {
364                 int pll_id;
365                 int pll_compid;
366         } ep[4];
367         struct clk_hw *hw;
368         int ep_chg_id;
369         u8 ep_count;
370         u8 ep_mux_table[4];
371         u8 id;
372         u8 eid;
373         u8 c;
374 } sama7g5_mckx[] = {
375         { .n = "mck0", }, /* Dummy entry for MCK0 to store hw in probe. */
376         { .n = "mck1",
377           .id = 1,
378           .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), },
379           .ep_mux_table = { 5, },
380           .ep_count = 1,
381           .ep_chg_id = INT_MIN,
382           .eid = PMC_MCK1,
383           .c = 1, },
384
385         { .n = "mck2",
386           .id = 2,
387           .ep = { PLL_IDS_TO_ARR_ENTRY(DDR, DIV0), },
388           .ep_mux_table = { 6, },
389           .ep_count = 1,
390           .ep_chg_id = INT_MIN,
391           .c = 1, },
392
393         { .n = "mck3",
394           .id = 3,
395           .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(DDR, DIV0),
396                   PLL_IDS_TO_ARR_ENTRY(IMG, DIV0), },
397           .ep_mux_table = { 5, 6, 7, },
398           .ep_count = 3,
399           .ep_chg_id = 5, },
400
401         { .n = "mck4",
402           .id = 4,
403           .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), },
404           .ep_mux_table = { 5, },
405           .ep_count = 1,
406           .ep_chg_id = INT_MIN,
407           .c = 1, },
408 };
409
410 /*
411  * System clock description
412  * @n:  clock name
413  * @id: clock id
414  */
415 static const struct {
416         const char *n;
417         u8 id;
418 } sama7g5_systemck[] = {
419         { .n = "pck0", .id = 8, },
420         { .n = "pck1", .id = 9, },
421         { .n = "pck2", .id = 10, },
422         { .n = "pck3", .id = 11, },
423         { .n = "pck4", .id = 12, },
424         { .n = "pck5", .id = 13, },
425         { .n = "pck6", .id = 14, },
426         { .n = "pck7", .id = 15, },
427 };
428
429 /* Mux table for programmable clocks. */
430 static u32 sama7g5_prog_mux_table[] = { 0, 1, 2, 5, 6, 7, 8, 9, 10, };
431
432 /*
433  * Peripheral clock parent hw identifier (used to index in sama7g5_mckx[])
434  * @PCK_PARENT_HW_MCK0: pck parent hw identifier is MCK0
435  * @PCK_PARENT_HW_MCK1: pck parent hw identifier is MCK1
436  * @PCK_PARENT_HW_MCK2: pck parent hw identifier is MCK2
437  * @PCK_PARENT_HW_MCK3: pck parent hw identifier is MCK3
438  * @PCK_PARENT_HW_MCK4: pck parent hw identifier is MCK4
439  * @PCK_PARENT_HW_MAX: max identifier
440  */
441 enum sama7g5_pck_parent_hw_id {
442         PCK_PARENT_HW_MCK0,
443         PCK_PARENT_HW_MCK1,
444         PCK_PARENT_HW_MCK2,
445         PCK_PARENT_HW_MCK3,
446         PCK_PARENT_HW_MCK4,
447         PCK_PARENT_HW_MAX,
448 };
449
450 /*
451  * Peripheral clock description
452  * @n:          clock name
453  * @p:          clock parent hw id
454  * @r:          clock range values
455  * @id:         clock id
456  * @chgp:       index in parent array of the changeable parent
457  */
458 static struct {
459         const char *n;
460         enum sama7g5_pck_parent_hw_id p;
461         struct clk_range r;
462         u8 chgp;
463         u8 id;
464 } sama7g5_periphck[] = {
465         { .n = "pioA_clk",      .p = PCK_PARENT_HW_MCK0, .id = 11, },
466         { .n = "securam_clk",   .p = PCK_PARENT_HW_MCK0, .id = 18, },
467         { .n = "sfr_clk",       .p = PCK_PARENT_HW_MCK1, .id = 19, },
468         { .n = "hsmc_clk",      .p = PCK_PARENT_HW_MCK1, .id = 21, },
469         { .n = "xdmac0_clk",    .p = PCK_PARENT_HW_MCK1, .id = 22, },
470         { .n = "xdmac1_clk",    .p = PCK_PARENT_HW_MCK1, .id = 23, },
471         { .n = "xdmac2_clk",    .p = PCK_PARENT_HW_MCK1, .id = 24, },
472         { .n = "acc_clk",       .p = PCK_PARENT_HW_MCK1, .id = 25, },
473         { .n = "aes_clk",       .p = PCK_PARENT_HW_MCK1, .id = 27, },
474         { .n = "tzaesbasc_clk", .p = PCK_PARENT_HW_MCK1, .id = 28, },
475         { .n = "asrc_clk",      .p = PCK_PARENT_HW_MCK1, .id = 30, .r = { .max = 200000000, }, },
476         { .n = "cpkcc_clk",     .p = PCK_PARENT_HW_MCK0, .id = 32, },
477         { .n = "csi_clk",       .p = PCK_PARENT_HW_MCK3, .id = 33, .r = { .max = 266000000, }, .chgp = 1, },
478         { .n = "csi2dc_clk",    .p = PCK_PARENT_HW_MCK3, .id = 34, .r = { .max = 266000000, }, .chgp = 1, },
479         { .n = "eic_clk",       .p = PCK_PARENT_HW_MCK1, .id = 37, },
480         { .n = "flex0_clk",     .p = PCK_PARENT_HW_MCK1, .id = 38, },
481         { .n = "flex1_clk",     .p = PCK_PARENT_HW_MCK1, .id = 39, },
482         { .n = "flex2_clk",     .p = PCK_PARENT_HW_MCK1, .id = 40, },
483         { .n = "flex3_clk",     .p = PCK_PARENT_HW_MCK1, .id = 41, },
484         { .n = "flex4_clk",     .p = PCK_PARENT_HW_MCK1, .id = 42, },
485         { .n = "flex5_clk",     .p = PCK_PARENT_HW_MCK1, .id = 43, },
486         { .n = "flex6_clk",     .p = PCK_PARENT_HW_MCK1, .id = 44, },
487         { .n = "flex7_clk",     .p = PCK_PARENT_HW_MCK1, .id = 45, },
488         { .n = "flex8_clk",     .p = PCK_PARENT_HW_MCK1, .id = 46, },
489         { .n = "flex9_clk",     .p = PCK_PARENT_HW_MCK1, .id = 47, },
490         { .n = "flex10_clk",    .p = PCK_PARENT_HW_MCK1, .id = 48, },
491         { .n = "flex11_clk",    .p = PCK_PARENT_HW_MCK1, .id = 49, },
492         { .n = "gmac0_clk",     .p = PCK_PARENT_HW_MCK1, .id = 51, },
493         { .n = "gmac1_clk",     .p = PCK_PARENT_HW_MCK1, .id = 52, },
494         { .n = "icm_clk",       .p = PCK_PARENT_HW_MCK1, .id = 55, },
495         { .n = "isc_clk",       .p = PCK_PARENT_HW_MCK3, .id = 56, .r = { .max = 266000000, }, .chgp = 1, },
496         { .n = "i2smcc0_clk",   .p = PCK_PARENT_HW_MCK1, .id = 57, .r = { .max = 200000000, }, },
497         { .n = "i2smcc1_clk",   .p = PCK_PARENT_HW_MCK1, .id = 58, .r = { .max = 200000000, }, },
498         { .n = "matrix_clk",    .p = PCK_PARENT_HW_MCK1, .id = 60, },
499         { .n = "mcan0_clk",     .p = PCK_PARENT_HW_MCK1, .id = 61, .r = { .max = 200000000, }, },
500         { .n = "mcan1_clk",     .p = PCK_PARENT_HW_MCK1, .id = 62, .r = { .max = 200000000, }, },
501         { .n = "mcan2_clk",     .p = PCK_PARENT_HW_MCK1, .id = 63, .r = { .max = 200000000, }, },
502         { .n = "mcan3_clk",     .p = PCK_PARENT_HW_MCK1, .id = 64, .r = { .max = 200000000, }, },
503         { .n = "mcan4_clk",     .p = PCK_PARENT_HW_MCK1, .id = 65, .r = { .max = 200000000, }, },
504         { .n = "mcan5_clk",     .p = PCK_PARENT_HW_MCK1, .id = 66, .r = { .max = 200000000, }, },
505         { .n = "pdmc0_clk",     .p = PCK_PARENT_HW_MCK1, .id = 68, .r = { .max = 200000000, }, },
506         { .n = "pdmc1_clk",     .p = PCK_PARENT_HW_MCK1, .id = 69, .r = { .max = 200000000, }, },
507         { .n = "pit64b0_clk",   .p = PCK_PARENT_HW_MCK1, .id = 70, },
508         { .n = "pit64b1_clk",   .p = PCK_PARENT_HW_MCK1, .id = 71, },
509         { .n = "pit64b2_clk",   .p = PCK_PARENT_HW_MCK1, .id = 72, },
510         { .n = "pit64b3_clk",   .p = PCK_PARENT_HW_MCK1, .id = 73, },
511         { .n = "pit64b4_clk",   .p = PCK_PARENT_HW_MCK1, .id = 74, },
512         { .n = "pit64b5_clk",   .p = PCK_PARENT_HW_MCK1, .id = 75, },
513         { .n = "pwm_clk",       .p = PCK_PARENT_HW_MCK1, .id = 77, },
514         { .n = "qspi0_clk",     .p = PCK_PARENT_HW_MCK1, .id = 78, },
515         { .n = "qspi1_clk",     .p = PCK_PARENT_HW_MCK1, .id = 79, },
516         { .n = "sdmmc0_clk",    .p = PCK_PARENT_HW_MCK1, .id = 80, },
517         { .n = "sdmmc1_clk",    .p = PCK_PARENT_HW_MCK1, .id = 81, },
518         { .n = "sdmmc2_clk",    .p = PCK_PARENT_HW_MCK1, .id = 82, },
519         { .n = "sha_clk",       .p = PCK_PARENT_HW_MCK1, .id = 83, },
520         { .n = "spdifrx_clk",   .p = PCK_PARENT_HW_MCK1, .id = 84, .r = { .max = 200000000, }, },
521         { .n = "spdiftx_clk",   .p = PCK_PARENT_HW_MCK1, .id = 85, .r = { .max = 200000000, }, },
522         { .n = "ssc0_clk",      .p = PCK_PARENT_HW_MCK1, .id = 86, .r = { .max = 200000000, }, },
523         { .n = "ssc1_clk",      .p = PCK_PARENT_HW_MCK1, .id = 87, .r = { .max = 200000000, }, },
524         { .n = "tcb0_ch0_clk",  .p = PCK_PARENT_HW_MCK1, .id = 88, .r = { .max = 200000000, }, },
525         { .n = "tcb0_ch1_clk",  .p = PCK_PARENT_HW_MCK1, .id = 89, .r = { .max = 200000000, }, },
526         { .n = "tcb0_ch2_clk",  .p = PCK_PARENT_HW_MCK1, .id = 90, .r = { .max = 200000000, }, },
527         { .n = "tcb1_ch0_clk",  .p = PCK_PARENT_HW_MCK1, .id = 91, .r = { .max = 200000000, }, },
528         { .n = "tcb1_ch1_clk",  .p = PCK_PARENT_HW_MCK1, .id = 92, .r = { .max = 200000000, }, },
529         { .n = "tcb1_ch2_clk",  .p = PCK_PARENT_HW_MCK1, .id = 93, .r = { .max = 200000000, }, },
530         { .n = "tcpca_clk",     .p = PCK_PARENT_HW_MCK1, .id = 94, },
531         { .n = "tcpcb_clk",     .p = PCK_PARENT_HW_MCK1, .id = 95, },
532         { .n = "tdes_clk",      .p = PCK_PARENT_HW_MCK1, .id = 96, },
533         { .n = "trng_clk",      .p = PCK_PARENT_HW_MCK1, .id = 97, },
534         { .n = "udphsa_clk",    .p = PCK_PARENT_HW_MCK1, .id = 104, },
535         { .n = "udphsb_clk",    .p = PCK_PARENT_HW_MCK1, .id = 105, },
536         { .n = "uhphs_clk",     .p = PCK_PARENT_HW_MCK1, .id = 106, },
537 };
538
539 /*
540  * Generic clock description
541  * @n:                  clock name
542  * @pp:                 PLL parents (entry formed by PLL components identifiers
543  *                      (see enum pll_component_id))
544  * @pp_mux_table:       PLL parents mux table
545  * @r:                  clock output range
546  * @pp_chg_id:          id in parent array of changeable PLL parent
547  * @pp_count:           PLL parents count
548  * @id:                 clock id
549  */
550 static const struct {
551         const char *n;
552         struct {
553                 int pll_id;
554                 int pll_compid;
555         } pp[8];
556         const char pp_mux_table[8];
557         struct clk_range r;
558         int pp_chg_id;
559         u8 pp_count;
560         u8 id;
561 } sama7g5_gck[] = {
562         { .n  = "adc_gclk",
563           .id = 26,
564           .r = { .max = 100000000, },
565           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0),
566                   PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },
567           .pp_mux_table = { 5, 7, 9, },
568           .pp_count = 3,
569           .pp_chg_id = INT_MIN, },
570
571         { .n  = "asrc_gclk",
572           .id = 30,
573           .r = { .max = 200000000 },
574           .pp = { PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },
575           .pp_mux_table = { 9, },
576           .pp_count = 1,
577           .pp_chg_id = 3, },
578
579         { .n  = "csi_gclk",
580           .id = 33,
581           .r = { .max = 27000000  },
582           .pp = { PLL_IDS_TO_ARR_ENTRY(DDR, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0), },
583           .pp_mux_table = { 6, 7, },
584           .pp_count = 2,
585           .pp_chg_id = INT_MIN, },
586
587         { .n  = "flex0_gclk",
588           .id = 38,
589           .r = { .max = 200000000 },
590           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
591           .pp_mux_table = { 5, 8, },
592           .pp_count = 2,
593           .pp_chg_id = INT_MIN, },
594
595         { .n  = "flex1_gclk",
596           .id = 39,
597           .r = { .max = 200000000 },
598           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
599           .pp_mux_table = { 5, 8, },
600           .pp_count = 2,
601           .pp_chg_id = INT_MIN, },
602
603         { .n  = "flex2_gclk",
604           .id = 40,
605           .r = { .max = 200000000 },
606           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
607           .pp_mux_table = { 5, 8, },
608           .pp_count = 2,
609           .pp_chg_id = INT_MIN, },
610
611         { .n  = "flex3_gclk",
612           .id = 41,
613           .r = { .max = 200000000 },
614           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
615           .pp_mux_table = { 5, 8, },
616           .pp_count = 2,
617           .pp_chg_id = INT_MIN, },
618
619         { .n  = "flex4_gclk",
620           .id = 42,
621           .r = { .max = 200000000 },
622           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
623           .pp_mux_table = { 5, 8, },
624           .pp_count = 2,
625           .pp_chg_id = INT_MIN, },
626
627         { .n  = "flex5_gclk",
628           .id = 43,
629           .r = { .max = 200000000 },
630           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
631           .pp_mux_table = { 5, 8, },
632           .pp_count = 2,
633           .pp_chg_id = INT_MIN, },
634
635         { .n  = "flex6_gclk",
636           .id = 44,
637           .r = { .max = 200000000 },
638           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
639           .pp_mux_table = { 5, 8, },
640           .pp_count = 2,
641           .pp_chg_id = INT_MIN, },
642
643         { .n  = "flex7_gclk",
644           .id = 45,
645           .r = { .max = 200000000 },
646           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
647           .pp_mux_table = { 5, 8, },
648           .pp_count = 2,
649           .pp_chg_id = INT_MIN, },
650
651         { .n  = "flex8_gclk",
652           .id = 46,
653           .r = { .max = 200000000 },
654           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
655           .pp_mux_table = { 5, 8, },
656           .pp_count = 2,
657           .pp_chg_id = INT_MIN, },
658
659         { .n  = "flex9_gclk",
660           .id = 47,
661           .r = { .max = 200000000 },
662           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
663           .pp_mux_table = { 5, 8, },
664           .pp_count = 2,
665           .pp_chg_id = INT_MIN, },
666
667         { .n  = "flex10_gclk",
668           .id = 48,
669           .r = { .max = 200000000 },
670           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
671           .pp_mux_table = { 5, 8, },
672           .pp_count = 2,
673           .pp_chg_id = INT_MIN, },
674
675         { .n  = "flex11_gclk",
676           .id = 49,
677           .r = { .max = 200000000 },
678           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
679           .pp_mux_table = { 5, 8, },
680           .pp_count = 2,
681           .pp_chg_id = INT_MIN, },
682
683         { .n  = "gmac0_gclk",
684           .id = 51,
685           .r = { .max = 125000000 },
686           .pp = { PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },
687           .pp_mux_table = { 10, },
688           .pp_count = 1,
689           .pp_chg_id = 3, },
690
691         { .n  = "gmac1_gclk",
692           .id = 52,
693           .r = { .max = 50000000  },
694           .pp = { PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },
695           .pp_mux_table = { 10, },
696           .pp_count = 1,
697           .pp_chg_id = INT_MIN, },
698
699         { .n  = "gmac0_tsu_gclk",
700           .id = 53,
701           .r = { .max = 300000000 },
702           .pp = { PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },
703           .pp_mux_table = { 9, 10, },
704           .pp_count = 2,
705           .pp_chg_id = INT_MIN, },
706
707         { .n  = "gmac1_tsu_gclk",
708           .id = 54,
709           .r = { .max = 300000000 },
710           .pp = { PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },
711           .pp_mux_table = { 9, 10, },
712           .pp_count = 2,
713           .pp_chg_id = INT_MIN, },
714
715         { .n  = "i2smcc0_gclk",
716           .id = 57,
717           .r = { .max = 100000000 },
718           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },
719           .pp_mux_table = { 5, 9, },
720           .pp_count = 2,
721           .pp_chg_id = 4, },
722
723         { .n  = "i2smcc1_gclk",
724           .id = 58,
725           .r = { .max = 100000000 },
726           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },
727           .pp_mux_table = { 5, 9, },
728           .pp_count = 2,
729           .pp_chg_id = 4, },
730
731         { .n  = "mcan0_gclk",
732           .id = 61,
733           .r = { .max = 200000000 },
734           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
735           .pp_mux_table = { 5, 8, },
736           .pp_count = 2,
737           .pp_chg_id = INT_MIN, },
738
739         { .n  = "mcan1_gclk",
740           .id = 62,
741           .r = { .max = 200000000 },
742           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
743           .pp_mux_table = { 5, 8, },
744           .pp_count = 2,
745           .pp_chg_id = INT_MIN, },
746
747         { .n  = "mcan2_gclk",
748           .id = 63,
749           .r = { .max = 200000000 },
750           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
751           .pp_mux_table = { 5, 8, },
752           .pp_count = 2,
753           .pp_chg_id = INT_MIN, },
754
755         { .n  = "mcan3_gclk",
756           .id = 64,
757           .r = { .max = 200000000 },
758           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
759           .pp_mux_table = { 5, 8, },
760           .pp_count = 2,
761           .pp_chg_id = INT_MIN, },
762
763         { .n  = "mcan4_gclk",
764           .id = 65,
765           .r = { .max = 200000000 },
766           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
767           .pp_mux_table = { 5, 8, },
768           .pp_count = 2,
769           .pp_chg_id = INT_MIN, },
770
771         { .n  = "mcan5_gclk",
772           .id = 66,
773           .r = { .max = 200000000 },
774           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
775           .pp_mux_table = { 5, 8, },
776           .pp_count = 2,
777           .pp_chg_id = INT_MIN, },
778
779         { .n  = "pdmc0_gclk",
780           .id = 68,
781           .r = { .max = 50000000  },
782           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },
783           .pp_mux_table = { 5, 9, },
784           .pp_count = 2,
785           .pp_chg_id = INT_MIN, },
786
787         { .n  = "pdmc1_gclk",
788           .id = 69,
789           .r = { .max = 50000000, },
790           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },
791           .pp_mux_table = { 5, 9, },
792           .pp_count = 2,
793           .pp_chg_id = INT_MIN, },
794
795         { .n  = "pit64b0_gclk",
796           .id = 70,
797           .r = { .max = 200000000 },
798           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0),
799                   PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0),
800                   PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },
801           .pp_mux_table = { 5, 7, 8, 9, 10, },
802           .pp_count = 5,
803           .pp_chg_id = INT_MIN, },
804
805         { .n  = "pit64b1_gclk",
806           .id = 71,
807           .r = { .max = 200000000 },
808           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0),
809                   PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0),
810                   PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },
811           .pp_mux_table = { 5, 7, 8, 9, 10, },
812           .pp_count = 5,
813           .pp_chg_id = INT_MIN, },
814
815         { .n  = "pit64b2_gclk",
816           .id = 72,
817           .r = { .max = 200000000 },
818           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0),
819                   PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0),
820                   PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },
821           .pp_mux_table = { 5, 7, 8, 9, 10, },
822           .pp_count = 5,
823           .pp_chg_id = INT_MIN, },
824
825         { .n  = "pit64b3_gclk",
826           .id = 73,
827           .r = { .max = 200000000 },
828           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0),
829                   PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0),
830                   PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },
831           .pp_mux_table = { 5, 7, 8, 9, 10, },
832           .pp_count = 5,
833           .pp_chg_id = INT_MIN, },
834
835         { .n  = "pit64b4_gclk",
836           .id = 74,
837           .r = { .max = 200000000 },
838           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0),
839                   PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0),
840                   PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },
841           .pp_mux_table = { 5, 7, 8, 9, 10, },
842           .pp_count = 5,
843           .pp_chg_id = INT_MIN, },
844
845         { .n  = "pit64b5_gclk",
846           .id = 75,
847           .r = { .max = 200000000 },
848           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0),
849                   PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0),
850                   PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },
851           .pp_mux_table = { 5, 7, 8, 9, 10, },
852           .pp_count = 5,
853           .pp_chg_id = INT_MIN, },
854
855         { .n  = "qspi0_gclk",
856           .id = 78,
857           .r = { .max = 200000000 },
858           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
859           .pp_mux_table = { 5, 8, },
860           .pp_count = 2,
861           .pp_chg_id = INT_MIN, },
862
863         { .n  = "qspi1_gclk",
864           .id = 79,
865           .r = { .max = 200000000 },
866           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
867           .pp_mux_table = { 5, 8, },
868           .pp_count = 2,
869           .pp_chg_id = INT_MIN, },
870
871         { .n  = "sdmmc0_gclk",
872           .id = 80,
873           .r = { .max = 208000000 },
874           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
875           .pp_mux_table = { 5, 8, },
876           .pp_count = 2,
877           .pp_chg_id = 4, },
878
879         { .n  = "sdmmc1_gclk",
880           .id = 81,
881           .r = { .max = 208000000 },
882           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
883           .pp_mux_table = { 5, 8, },
884           .pp_count = 2,
885           .pp_chg_id = 4, },
886
887         { .n  = "sdmmc2_gclk",
888           .id = 82,
889           .r = { .max = 208000000 },
890           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
891           .pp_mux_table = { 5, 8, },
892           .pp_count = 2,
893           .pp_chg_id = 4, },
894
895         { .n  = "spdifrx_gclk",
896           .id = 84,
897           .r = { .max = 150000000 },
898           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },
899           .pp_mux_table = { 5, 9, },
900           .pp_count = 2,
901           .pp_chg_id = 4, },
902
903         { .n = "spdiftx_gclk",
904           .id = 85,
905           .r = { .max = 25000000  },
906           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },
907           .pp_mux_table = { 5, 9, },
908           .pp_count = 2,
909           .pp_chg_id = 4, },
910
911         { .n  = "tcb0_ch0_gclk",
912           .id = 88,
913           .r = { .max = 200000000 },
914           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0),
915                   PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0),
916                   PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },
917           .pp_mux_table = { 5, 7, 8, 9, 10, },
918           .pp_count = 5,
919           .pp_chg_id = INT_MIN, },
920
921         { .n  = "tcb1_ch0_gclk",
922           .id = 91,
923           .r = { .max = 200000000 },
924           .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0),
925                   PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0),
926                   PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },
927           .pp_mux_table = { 5, 7, 8, 9, 10, },
928           .pp_count = 5,
929           .pp_chg_id = INT_MIN, },
930
931         { .n  = "tcpca_gclk",
932           .id = 94,
933           .r = { .max = 32768, },
934           .pp_chg_id = INT_MIN, },
935
936         { .n  = "tcpcb_gclk",
937           .id = 95,
938           .r = { .max = 32768, },
939           .pp_chg_id = INT_MIN, },
940 };
941
942 /* MCK0 characteristics. */
943 static const struct clk_master_characteristics mck0_characteristics = {
944         .output = { .min = 32768, .max = 200000000 },
945         .divisors = { 1, 2, 4, 3, 5 },
946         .have_div3_pres = 1,
947 };
948
949 /* MCK0 layout. */
950 static const struct clk_master_layout mck0_layout = {
951         .mask = 0x773,
952         .pres_shift = 4,
953         .offset = 0x28,
954 };
955
956 /* Programmable clock layout. */
957 static const struct clk_programmable_layout programmable_layout = {
958         .pres_mask = 0xff,
959         .pres_shift = 8,
960         .css_mask = 0x1f,
961         .have_slck_mck = 0,
962         .is_pres_direct = 1,
963 };
964
965 /* Peripheral clock layout. */
966 static const struct clk_pcr_layout sama7g5_pcr_layout = {
967         .offset = 0x88,
968         .cmd = BIT(31),
969         .gckcss_mask = GENMASK(12, 8),
970         .pid_mask = GENMASK(6, 0),
971 };
972
973 static void __init sama7g5_pmc_setup(struct device_node *np)
974 {
975         const char *main_xtal_name = "main_xtal";
976         struct pmc_data *sama7g5_pmc;
977         void **alloc_mem = NULL;
978         int alloc_mem_size = 0;
979         struct regmap *regmap;
980         struct clk_hw *hw, *main_rc_hw, *main_osc_hw, *main_xtal_hw;
981         struct clk_hw *td_slck_hw, *md_slck_hw;
982         static struct clk_parent_data parent_data;
983         struct clk_hw *parent_hws[10];
984         bool bypass;
985         int i, j;
986
987         td_slck_hw = __clk_get_hw(of_clk_get_by_name(np, "td_slck"));
988         md_slck_hw = __clk_get_hw(of_clk_get_by_name(np, "md_slck"));
989         main_xtal_hw = __clk_get_hw(of_clk_get_by_name(np, main_xtal_name));
990
991         if (!td_slck_hw || !md_slck_hw || !main_xtal_hw)
992                 return;
993
994         regmap = device_node_to_regmap(np);
995         if (IS_ERR(regmap))
996                 return;
997
998         sama7g5_pmc = pmc_data_allocate(PMC_MCK1 + 1,
999                                         nck(sama7g5_systemck),
1000                                         nck(sama7g5_periphck),
1001                                         nck(sama7g5_gck), 8);
1002         if (!sama7g5_pmc)
1003                 return;
1004
1005         alloc_mem = kmalloc(sizeof(void *) *
1006                             (ARRAY_SIZE(sama7g5_mckx) + ARRAY_SIZE(sama7g5_gck)),
1007                             GFP_KERNEL);
1008         if (!alloc_mem)
1009                 goto err_free;
1010
1011         main_rc_hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000,
1012                                                    50000000);
1013         if (IS_ERR(main_rc_hw))
1014                 goto err_free;
1015
1016         bypass = of_property_read_bool(np, "atmel,osc-bypass");
1017
1018         parent_data.name = main_xtal_name;
1019         parent_data.fw_name = main_xtal_name;
1020         main_osc_hw = at91_clk_register_main_osc(regmap, "main_osc", NULL,
1021                                                  &parent_data, bypass);
1022         if (IS_ERR(main_osc_hw))
1023                 goto err_free;
1024
1025         parent_hws[0] = main_rc_hw;
1026         parent_hws[1] = main_osc_hw;
1027         hw = at91_clk_register_sam9x5_main(regmap, "mainck", NULL, parent_hws, 2);
1028         if (IS_ERR(hw))
1029                 goto err_free;
1030
1031         sama7g5_pmc->chws[PMC_MAIN] = hw;
1032
1033         for (i = 0; i < PLL_ID_MAX; i++) {
1034                 for (j = 0; j < PLL_COMPID_MAX; j++) {
1035                         struct clk_hw *parent_hw;
1036
1037                         if (!sama7g5_plls[i][j].n)
1038                                 continue;
1039
1040                         switch (sama7g5_plls[i][j].t) {
1041                         case PLL_TYPE_FRAC:
1042                                 switch (sama7g5_plls[i][j].p) {
1043                                 case SAMA7G5_PLL_PARENT_MAINCK:
1044                                         parent_hw = sama7g5_pmc->chws[PMC_MAIN];
1045                                         break;
1046                                 case SAMA7G5_PLL_PARENT_MAIN_XTAL:
1047                                         parent_hw = main_xtal_hw;
1048                                         break;
1049                                 default:
1050                                         /* Should not happen. */
1051                                         parent_hw = NULL;
1052                                         break;
1053                                 }
1054
1055                                 hw = sam9x60_clk_register_frac_pll(regmap,
1056                                         &pmc_pll_lock, sama7g5_plls[i][j].n,
1057                                         NULL, parent_hw, i,
1058                                         sama7g5_plls[i][j].c,
1059                                         sama7g5_plls[i][j].l,
1060                                         sama7g5_plls[i][j].f);
1061                                 break;
1062
1063                         case PLL_TYPE_DIV:
1064                                 hw = sam9x60_clk_register_div_pll(regmap,
1065                                         &pmc_pll_lock, sama7g5_plls[i][j].n,
1066                                         NULL, sama7g5_plls[i][0].hw, i,
1067                                         sama7g5_plls[i][j].c,
1068                                         sama7g5_plls[i][j].l,
1069                                         sama7g5_plls[i][j].f,
1070                                         sama7g5_plls[i][j].safe_div);
1071                                 break;
1072
1073                         default:
1074                                 continue;
1075                         }
1076
1077                         if (IS_ERR(hw))
1078                                 goto err_free;
1079
1080                         sama7g5_plls[i][j].hw = hw;
1081                         if (sama7g5_plls[i][j].eid)
1082                                 sama7g5_pmc->chws[sama7g5_plls[i][j].eid] = hw;
1083                 }
1084         }
1085
1086         hw = at91_clk_register_master_div(regmap, "mck0", NULL,
1087                                           sama7g5_plls[PLL_ID_CPU][1].hw,
1088                                           &mck0_layout, &mck0_characteristics,
1089                                           &pmc_mck0_lock, CLK_GET_RATE_NOCACHE, 5);
1090         if (IS_ERR(hw))
1091                 goto err_free;
1092
1093         sama7g5_mckx[PCK_PARENT_HW_MCK0].hw = sama7g5_pmc->chws[PMC_MCK] = hw;
1094
1095         parent_hws[0] = md_slck_hw;
1096         parent_hws[1] = td_slck_hw;
1097         parent_hws[2] = sama7g5_pmc->chws[PMC_MAIN];
1098         for (i = PCK_PARENT_HW_MCK1; i < ARRAY_SIZE(sama7g5_mckx); i++) {
1099                 u8 num_parents = 3 + sama7g5_mckx[i].ep_count;
1100                 struct clk_hw *tmp_parent_hws[8];
1101                 u32 *mux_table;
1102
1103                 mux_table = kmalloc_array(num_parents, sizeof(*mux_table),
1104                                           GFP_KERNEL);
1105                 if (!mux_table)
1106                         goto err_free;
1107
1108                 PMC_INIT_TABLE(mux_table, 3);
1109                 PMC_FILL_TABLE(&mux_table[3], sama7g5_mckx[i].ep_mux_table,
1110                                sama7g5_mckx[i].ep_count);
1111                 for (j = 0; j < sama7g5_mckx[i].ep_count; j++) {
1112                         u8 pll_id = sama7g5_mckx[i].ep[j].pll_id;
1113                         u8 pll_compid = sama7g5_mckx[i].ep[j].pll_compid;
1114
1115                         tmp_parent_hws[j] = sama7g5_plls[pll_id][pll_compid].hw;
1116                 }
1117                 PMC_FILL_TABLE(&parent_hws[3], tmp_parent_hws,
1118                                sama7g5_mckx[i].ep_count);
1119
1120                 hw = at91_clk_sama7g5_register_master(regmap, sama7g5_mckx[i].n,
1121                                    num_parents, NULL, parent_hws, mux_table,
1122                                    &pmc_mckX_lock, sama7g5_mckx[i].id,
1123                                    sama7g5_mckx[i].c,
1124                                    sama7g5_mckx[i].ep_chg_id);
1125                 if (IS_ERR(hw))
1126                         goto err_free;
1127
1128                 alloc_mem[alloc_mem_size++] = mux_table;
1129
1130                 sama7g5_mckx[i].hw = hw;
1131                 if (sama7g5_mckx[i].eid)
1132                         sama7g5_pmc->chws[sama7g5_mckx[i].eid] = hw;
1133         }
1134
1135         hw = at91_clk_sama7g5_register_utmi(regmap, "utmick", NULL, main_xtal_hw);
1136         if (IS_ERR(hw))
1137                 goto err_free;
1138
1139         sama7g5_pmc->chws[PMC_UTMI] = hw;
1140
1141         parent_hws[0] = md_slck_hw;
1142         parent_hws[1] = td_slck_hw;
1143         parent_hws[2] = sama7g5_pmc->chws[PMC_MAIN];
1144         parent_hws[3] = sama7g5_plls[PLL_ID_SYS][PLL_COMPID_DIV0].hw;
1145         parent_hws[4] = sama7g5_plls[PLL_ID_DDR][PLL_COMPID_DIV0].hw;
1146         parent_hws[5] = sama7g5_plls[PLL_ID_IMG][PLL_COMPID_DIV0].hw;
1147         parent_hws[6] = sama7g5_plls[PLL_ID_BAUD][PLL_COMPID_DIV0].hw;
1148         parent_hws[7] = sama7g5_plls[PLL_ID_AUDIO][PLL_COMPID_DIV0].hw;
1149         parent_hws[8] = sama7g5_plls[PLL_ID_ETH][PLL_COMPID_DIV0].hw;
1150         for (i = 0; i < 8; i++) {
1151                 char name[6];
1152
1153                 snprintf(name, sizeof(name), "prog%d", i);
1154
1155                 hw = at91_clk_register_programmable(regmap, name, NULL, parent_hws,
1156                                                     9, i,
1157                                                     &programmable_layout,
1158                                                     sama7g5_prog_mux_table);
1159                 if (IS_ERR(hw))
1160                         goto err_free;
1161
1162                 sama7g5_pmc->pchws[i] = hw;
1163         }
1164
1165         for (i = 0; i < ARRAY_SIZE(sama7g5_systemck); i++) {
1166                 hw = at91_clk_register_system(regmap, sama7g5_systemck[i].n,
1167                                               NULL, sama7g5_pmc->pchws[i],
1168                                               sama7g5_systemck[i].id, 0);
1169                 if (IS_ERR(hw))
1170                         goto err_free;
1171
1172                 sama7g5_pmc->shws[sama7g5_systemck[i].id] = hw;
1173         }
1174
1175         for (i = 0; i < ARRAY_SIZE(sama7g5_periphck); i++) {
1176                 hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
1177                                                 &sama7g5_pcr_layout,
1178                                                 sama7g5_periphck[i].n,
1179                                                 NULL,
1180                                                 sama7g5_mckx[sama7g5_periphck[i].p].hw,
1181                                                 sama7g5_periphck[i].id,
1182                                                 &sama7g5_periphck[i].r,
1183                                                 sama7g5_periphck[i].chgp ? 0 :
1184                                                 INT_MIN, 0);
1185                 if (IS_ERR(hw))
1186                         goto err_free;
1187
1188                 sama7g5_pmc->phws[sama7g5_periphck[i].id] = hw;
1189         }
1190
1191         parent_hws[0] = md_slck_hw;
1192         parent_hws[1] = td_slck_hw;
1193         parent_hws[2] = sama7g5_pmc->chws[PMC_MAIN];
1194         for (i = 0; i < ARRAY_SIZE(sama7g5_gck); i++) {
1195                 u8 num_parents = 3 + sama7g5_gck[i].pp_count;
1196                 struct clk_hw *tmp_parent_hws[8];
1197                 u32 *mux_table;
1198
1199                 mux_table = kmalloc_array(num_parents, sizeof(*mux_table),
1200                                           GFP_KERNEL);
1201                 if (!mux_table)
1202                         goto err_free;
1203
1204                 PMC_INIT_TABLE(mux_table, 3);
1205                 PMC_FILL_TABLE(&mux_table[3], sama7g5_gck[i].pp_mux_table,
1206                                sama7g5_gck[i].pp_count);
1207                 for (j = 0; j < sama7g5_gck[i].pp_count; j++) {
1208                         u8 pll_id = sama7g5_gck[i].pp[j].pll_id;
1209                         u8 pll_compid = sama7g5_gck[i].pp[j].pll_compid;
1210
1211                         tmp_parent_hws[j] = sama7g5_plls[pll_id][pll_compid].hw;
1212                 }
1213                 PMC_FILL_TABLE(&parent_hws[3], tmp_parent_hws,
1214                                sama7g5_gck[i].pp_count);
1215
1216                 hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
1217                                                  &sama7g5_pcr_layout,
1218                                                  sama7g5_gck[i].n, NULL,
1219                                                  parent_hws, mux_table,
1220                                                  num_parents,
1221                                                  sama7g5_gck[i].id,
1222                                                  &sama7g5_gck[i].r,
1223                                                  sama7g5_gck[i].pp_chg_id);
1224                 if (IS_ERR(hw))
1225                         goto err_free;
1226
1227                 sama7g5_pmc->ghws[sama7g5_gck[i].id] = hw;
1228                 alloc_mem[alloc_mem_size++] = mux_table;
1229         }
1230
1231         of_clk_add_hw_provider(np, of_clk_hw_pmc_get, sama7g5_pmc);
1232
1233         return;
1234
1235 err_free:
1236         if (alloc_mem) {
1237                 for (i = 0; i < alloc_mem_size; i++)
1238                         kfree(alloc_mem[i]);
1239                 kfree(alloc_mem);
1240         }
1241
1242         kfree(sama7g5_pmc);
1243 }
1244
1245 /* Some clks are used for a clocksource */
1246 CLK_OF_DECLARE(sama7g5_pmc, "microchip,sama7g5-pmc", sama7g5_pmc_setup);
This page took 0.099588 seconds and 4 git commands to generate.