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