xref: /optee_os/core/drivers/clk/sam/sama7g5_clk.c (revision 6b1c18580069a7c71e32deb57f609031fffb6e68)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2024, Microchip
4  */
5 
6 #include <assert.h>
7 #include <dt-bindings/clock/at91.h>
8 #include <io.h>
9 #include <kernel/boot.h>
10 #include <kernel/dt.h>
11 #include <kernel/panic.h>
12 #include <libfdt.h>
13 #include <matrix.h>
14 #include <sama7g5.h>
15 #include <stdint.h>
16 #include <util.h>
17 #include "at91_clk.h"
18 
19 #define CLK_IS_CRITICAL 0
20 
21 /* PLL clocks identifiers */
22 enum pll_ids {
23 	PLL_ID_CPU,
24 	PLL_ID_SYS,
25 	PLL_ID_DDR,
26 	PLL_ID_IMG,
27 	PLL_ID_BAUD,
28 	PLL_ID_AUDIO,
29 	PLL_ID_ETH,
30 	PLL_ID_MAX,
31 };
32 
33 /* PLL type identifiers */
34 enum pll_type {
35 	PLL_TYPE_FRAC,
36 	PLL_TYPE_DIV,
37 	PLL_TYPE_CNT,
38 };
39 
40 /* Layout for fractional PLLs */
41 static const struct clk_pll_layout pll_layout_frac = {
42 	.mul_mask	= GENMASK_32(31, 24),
43 	.frac_mask	= GENMASK_32(21, 0),
44 	.mul_shift	= 24,
45 	.frac_shift	= 0,
46 };
47 
48 /* Layout for DIVPMC dividers */
49 static const struct clk_pll_layout pll_layout_divpmc = {
50 	.div_mask	= GENMASK_32(7, 0),
51 	.endiv_mask	= BIT(29),
52 	.div_shift	= 0,
53 	.endiv_shift	= 29,
54 };
55 
56 /* Layout for DIVIO dividers */
57 static const struct clk_pll_layout pll_layout_divio = {
58 	.div_mask	= GENMASK_32(19, 12),
59 	.endiv_mask	= BIT(30),
60 	.div_shift	= 12,
61 	.endiv_shift	= 30,
62 };
63 
64 /*
65  * CPU PLL output range
66  * Notice: The upper limit has been setup to 1000000002 due to hardware
67  * block which cannot output exactly 1GHz.
68  */
69 static const struct clk_range cpu_pll_output[] = {
70 	{ .min = 2343750, .max = 1000000002 },
71 };
72 
73 /* PLL output range */
74 static const struct clk_range pll_output[] = {
75 	{ .min = 2343750, .max = 1200000000 },
76 };
77 
78 /* CPU PLL characteristics */
79 static const struct clk_pll_charac cpu_pll_characteristics = {
80 	.input = { .min = 12000000, .max = 50000000 },
81 	.num_output = ARRAY_SIZE(cpu_pll_output),
82 	.output = cpu_pll_output,
83 };
84 
85 /* PLL characteristics */
86 static const struct clk_pll_charac pll_characteristics = {
87 	.input = { .min = 12000000, .max = 50000000 },
88 	.num_output = ARRAY_SIZE(pll_output),
89 	.output = pll_output,
90 };
91 
92 /* PLL clocks description */
93 struct sama7g5_pll {
94 	const char *name;
95 	const char *parent;
96 	const struct clk_pll_layout *layout;
97 	const struct clk_pll_charac *charac;
98 	unsigned long flags;
99 	uint8_t type;
100 	uint8_t eid; /* export index in sama7g5->chws[] array */
101 	uint8_t safe_div; /* intermediate divider need to be set on
102 			   * PRE_RATE_CHANGE notification
103 			   */
104 };
105 
106 static const struct sama7g5_pll sama7g5_plls[][PLL_ID_MAX] = {
107 	[PLL_ID_CPU] = {
108 		{
109 			.name = "cpupll_fracck",
110 			.parent = "mainck",
111 			.layout = &pll_layout_frac,
112 			.charac = &cpu_pll_characteristics,
113 			.type = PLL_TYPE_FRAC,
114 			/*
115 			 * This feeds cpupll_divpmcck which feeds CPU. It
116 			 * should not be disabled.
117 			 */
118 			.flags = CLK_IS_CRITICAL,
119 		},
120 		{
121 			.name = "cpupll_divpmcck",
122 			.parent = "cpupll_fracck",
123 			.layout = &pll_layout_divpmc,
124 			.charac = &cpu_pll_characteristics,
125 			.type = PLL_TYPE_DIV,
126 			/* This feeds CPU. It should not be disabled. */
127 			.flags = CLK_IS_CRITICAL,
128 			.eid = PMC_CPUPLL,
129 			/*
130 			 * Safe div=15 should be safe even for switching b/w
131 			 * 1GHz and 90MHz (frac pll might go up to 1.2GHz).
132 			 */
133 			.safe_div = 15,
134 		},
135 	},
136 
137 	[PLL_ID_SYS] = {
138 		{
139 			.name = "syspll_fracck",
140 			.parent = "mainck",
141 			.layout = &pll_layout_frac,
142 			.charac = &pll_characteristics,
143 			.type = PLL_TYPE_FRAC,
144 			/*
145 			 * This feeds syspll_divpmcck which may feed critical
146 			 * parts of the systems like timers. Therefore it
147 			 * should not be disabled.
148 			 */
149 			.flags = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,
150 		},
151 		{
152 			.name = "syspll_divpmcck",
153 			.parent = "syspll_fracck",
154 			.layout = &pll_layout_divpmc,
155 			.charac = &pll_characteristics,
156 			.type = PLL_TYPE_DIV,
157 			/*
158 			 * This may feed critical parts of the systems like
159 			 * timers. Therefore it should not be disabled.
160 			 */
161 			.flags = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,
162 			.eid = PMC_SYSPLL,
163 		},
164 	},
165 
166 	[PLL_ID_DDR] = {
167 		{
168 			.name = "ddrpll_fracck",
169 			.parent = "mainck",
170 			.layout = &pll_layout_frac,
171 			.charac = &pll_characteristics,
172 			.type = PLL_TYPE_FRAC,
173 			/*
174 			 * This feeds ddrpll_divpmcck which feeds DDR. It
175 			 * should not be disabled.
176 			 */
177 			.flags = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,
178 		},
179 		{
180 			.name = "ddrpll_divpmcck",
181 			.parent = "ddrpll_fracck",
182 			.layout = &pll_layout_divpmc,
183 			.charac = &pll_characteristics,
184 			.type = PLL_TYPE_DIV,
185 			/* This feeds DDR. It should not be disabled. */
186 			.flags = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,
187 			.eid = PMC_DDRPLL,
188 		},
189 	},
190 
191 	[PLL_ID_IMG] = {
192 		{
193 			.name = "imgpll_fracck",
194 			.parent = "mainck",
195 			.layout = &pll_layout_frac,
196 			.charac = &pll_characteristics,
197 			.type = PLL_TYPE_FRAC,
198 			.flags = CLK_SET_RATE_GATE,
199 		},
200 		{
201 			.name = "imgpll_divpmcck",
202 			.parent = "imgpll_fracck",
203 			.layout = &pll_layout_divpmc,
204 			.charac = &pll_characteristics,
205 			.type = PLL_TYPE_DIV,
206 			.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE,
207 			.eid = PMC_IMGPLL,
208 		},
209 	},
210 
211 	[PLL_ID_BAUD] = {
212 		{
213 			.name = "baudpll_fracck",
214 			.parent = "mainck",
215 			.layout = &pll_layout_frac,
216 			.charac = &pll_characteristics,
217 			.type = PLL_TYPE_FRAC,
218 			.flags = CLK_SET_RATE_GATE,
219 		},
220 		{
221 			.name = "baudpll_divpmcck",
222 			.parent = "baudpll_fracck",
223 			.layout = &pll_layout_divpmc,
224 			.charac = &pll_characteristics,
225 			.type = PLL_TYPE_DIV,
226 			.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE,
227 			.eid = PMC_BAUDPLL,
228 		},
229 	},
230 
231 	[PLL_ID_AUDIO] = {
232 		{
233 			.name = "audiopll_fracck",
234 			.parent = "main_xtal",
235 			.layout = &pll_layout_frac,
236 			.charac = &pll_characteristics,
237 			.type = PLL_TYPE_FRAC,
238 			.flags = CLK_SET_RATE_GATE,
239 		},
240 		{
241 			.name = "audiopll_divck",
242 			.parent = "audiopll_fracck",
243 			.layout = &pll_layout_divpmc,
244 			.charac = &pll_characteristics,
245 			.type = PLL_TYPE_DIV,
246 			.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE,
247 			.eid = PMC_AUDIOPMCPLL,
248 		},
249 		{
250 			.name = "audiopll_diviock",
251 			.parent = "audiopll_fracck",
252 			.layout = &pll_layout_divio,
253 			.charac = &pll_characteristics,
254 			.type = PLL_TYPE_DIV,
255 			.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE,
256 			.eid = PMC_AUDIOIOPLL,
257 		},
258 	},
259 
260 	[PLL_ID_ETH] = {
261 		{
262 			.name = "ethpll_fracck",
263 			.parent = "main_xtal",
264 			.layout = &pll_layout_frac,
265 			.charac = &pll_characteristics,
266 			.type = PLL_TYPE_FRAC,
267 			.flags = CLK_SET_RATE_GATE,
268 		},
269 		{
270 			.name = "ethpll_divpmcck",
271 			.parent = "ethpll_fracck",
272 			.layout = &pll_layout_divpmc,
273 			.charac = &pll_characteristics,
274 			.type = PLL_TYPE_DIV,
275 			.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE,
276 			.eid = PMC_ETHPLL,
277 		},
278 	},
279 };
280 
281 /*
282  * Master clock (MCK[1..4]) description
283  * @eparents:		extra parents names array
284  * @eparents_chg_id:	index in parents array that specifies the changeable
285  *			parent
286  * @eparents_count:	extra parents count
287  * @eparents_mux_table:	mux table for extra parents
288  * @id:			clock id
289  * @eid:		export index in sama7g5->chws[] array
290  */
291 struct sama7g5_mck {
292 	const char *name;
293 	const char *eparents[4];
294 	int eparents_chg_id;
295 	uint8_t eparents_count;
296 	uint8_t eparents_mux_table[4];
297 	uint8_t id;
298 	uint8_t eid;
299 };
300 
301 static const struct sama7g5_mck sama7g5_mckx[] = {
302 	{
303 		.name = "mck1",
304 		.id = 1,
305 		.eparents = { "syspll_divpmcck", },
306 		.eparents_mux_table = { 5, },
307 		.eparents_count = 1,
308 		.eparents_chg_id = INT_MIN,
309 		.eid = PMC_MCK1,
310 	},
311 	{
312 		.name = "mck2",
313 		.id = 2,
314 		.eparents = { "ddrpll_divpmcck", },
315 		.eparents_mux_table = { 6, },
316 		.eparents_count = 1,
317 		.eparents_chg_id = INT_MIN,
318 	},
319 	{
320 		.name = "mck3",
321 		.id = 3,
322 		.eparents = { "syspll_divpmcck",
323 			"ddrpll_divpmcck",
324 			"imgpll_divpmcck", },
325 		.eparents_mux_table = { 5, 6, 7, },
326 		.eparents_count = 3,
327 		.eparents_chg_id = 5,
328 	},
329 	{
330 		.name = "mck4",
331 		.id = 4,
332 		.eparents = { "syspll_divpmcck", },
333 		.eparents_mux_table = { 5, },
334 		.eparents_count = 1,
335 		.eparents_chg_id = INT_MIN,
336 	},
337 };
338 
339 /* System clock description */
340 static const struct {
341 	const char *name;
342 	const char *parent;
343 	uint8_t id;
344 } sama7g5_systemck[] = {
345 	{ .name = "pck0", .parent = "prog0", .id = 8, },
346 	{ .name = "pck1", .parent = "prog1", .id = 9, },
347 	{ .name = "pck2", .parent = "prog2", .id = 10, },
348 	{ .name = "pck3", .parent = "prog3", .id = 11, },
349 	{ .name = "pck4", .parent = "prog4", .id = 12, },
350 	{ .name = "pck5", .parent = "prog5", .id = 13, },
351 	{ .name = "pck6", .parent = "prog6", .id = 14, },
352 	{ .name = "pck7", .parent = "prog7", .id = 15, },
353 };
354 
355 /* Peripheral clock description */
356 static const struct {
357 	const char *name;
358 	const char *parent;
359 	struct clk_range output;
360 	uint8_t id;
361 } peri_clks[] = {
362 	{
363 		.name = "pioA_clk",
364 		.parent = "mck0",
365 		.id = 11,
366 	},
367 	{
368 		.name = "securam_clk",
369 		.parent = "mck0",
370 		.id = 18,
371 	},
372 	{
373 		.name = "sfr_clk",
374 		.parent = "mck1",
375 		.id = 19,
376 	},
377 	{
378 		.name = "hsmc_clk",
379 		.parent = "mck1",
380 		.id = 21,
381 	},
382 	{
383 		.name = "xdmac0_clk",
384 		.parent = "mck1",
385 		.id = 22,
386 	},
387 	{
388 		.name = "xdmac1_clk",
389 		.parent = "mck1",
390 		.id = 23,
391 	},
392 	{
393 		.name = "xdmac2_clk",
394 		.parent = "mck1",
395 		.id = 24,
396 	},
397 	{
398 		.name = "acc_clk",
399 		.parent = "mck1",
400 		.id = 25,
401 	},
402 	{
403 		.name = "aes_clk",
404 		.parent = "mck1",
405 		.id = 27,
406 	},
407 	{
408 		.name = "tzaesbasc_clk",
409 		.parent = "mck1",
410 		.id = 28,
411 	},
412 	{
413 		.name = "asrc_clk",
414 		.parent = "mck1",
415 		.id = 30,
416 		.output = { .max = 200000000, },
417 	},
418 	{
419 		.name = "cpkcc_clk",
420 		.parent = "mck0",
421 		.id = 32,
422 	},
423 	{
424 		.name = "csi_clk",
425 		.parent = "mck3",
426 		.id = 33,
427 		.output = { .max = 266000000, },
428 	},
429 	{
430 		.name = "csi2dc_clk",
431 		.parent = "mck3",
432 		.id = 34,
433 		.output = { .max = 266000000, },
434 	},
435 	{
436 		.name = "eic_clk",
437 		.parent = "mck1",
438 		.id = 37,
439 	},
440 	{
441 		.name = "flex0_clk",
442 		.parent = "mck1",
443 		.id = 38,
444 	},
445 	{
446 		.name = "flex1_clk",
447 		.parent = "mck1",
448 		.id = 39,
449 	},
450 	{
451 		.name = "flex2_clk",
452 		.parent = "mck1",
453 		.id = 40,
454 	},
455 	{
456 		.name = "flex3_clk",
457 		.parent = "mck1",
458 		.id = 41,
459 	},
460 	{
461 		.name = "flex4_clk",
462 		.parent = "mck1",
463 		.id = 42,
464 	},
465 	{
466 		.name = "flex5_clk",
467 		.parent = "mck1",
468 		.id = 43,
469 	},
470 	{
471 		.name = "flex6_clk",
472 		.parent = "mck1",
473 		.id = 44,
474 	},
475 	{
476 		.name = "flex7_clk",
477 		.parent = "mck1",
478 		.id = 45,
479 	},
480 	{
481 		.name = "flex8_clk",
482 		.parent = "mck1",
483 		.id = 46,
484 	},
485 	{
486 		.name = "flex9_clk",
487 		.parent = "mck1",
488 		.id = 47,
489 	},
490 	{
491 		.name = "flex10_clk",
492 		.parent = "mck1",
493 		.id = 48,
494 	},
495 	{
496 		.name = "flex11_clk",
497 		.parent = "mck1",
498 		.id = 49,
499 	},
500 	{
501 		.name = "gmac0_clk",
502 		.parent = "mck1",
503 		.id = 51,
504 	},
505 	{
506 		.name = "gmac1_clk",
507 		.parent = "mck1",
508 		.id = 52,
509 	},
510 	{
511 		.name = "icm_clk",
512 		.parent = "mck1",
513 		.id = 55,
514 	},
515 	{
516 		.name = "isc_clk",
517 		.parent = "mck3",
518 		.id = 56,
519 		.output = { .max = 266000000, },
520 	},
521 	{
522 		.name = "i2smcc0_clk",
523 		.parent = "mck1",
524 		.id = 57,
525 		.output = { .max = 200000000, },
526 	},
527 	{
528 		.name = "i2smcc1_clk",
529 		.parent = "mck1",
530 		.id = 58,
531 		.output = { .max = 200000000, },
532 	},
533 	{
534 		.name = "matrix_clk",
535 		.parent = "mck1",
536 		.id = 60, },
537 	{
538 		.name = "mcan0_clk",
539 		.parent = "mck1",
540 		.id = 61,
541 		.output = { .max = 200000000, },
542 	},
543 	{
544 		.name = "mcan1_clk",
545 		.parent = "mck1",
546 		.id = 62,
547 		.output = { .max = 200000000, },
548 	},
549 	{
550 		.name = "mcan2_clk",
551 		.parent = "mck1",
552 		.id = 63,
553 		.output = { .max = 200000000, },
554 	},
555 	{
556 		.name = "mcan3_clk",
557 		.parent = "mck1",
558 		.id = 64,
559 		.output = { .max = 200000000, },
560 	},
561 	{
562 		.name = "mcan4_clk",
563 		.parent = "mck1",
564 		.id = 65,
565 		.output = { .max = 200000000, },
566 	},
567 	{
568 		.name = "mcan5_clk",
569 		.parent = "mck1",
570 		.id = 66,
571 		.output = { .max = 200000000, },
572 	},
573 	{
574 		.name = "pdmc0_clk",
575 		.parent = "mck1",
576 		.id = 68,
577 		.output = { .max = 200000000, },
578 	},
579 	{
580 		.name = "pdmc1_clk",
581 		.parent = "mck1",
582 		.id = 69,
583 		.output = { .max = 200000000, },
584 	},
585 	{
586 		.name = "pit64b0_clk",
587 		.parent = "mck1",
588 		.id = 70,
589 	},
590 	{
591 		.name = "pit64b1_clk",
592 		.parent = "mck1",
593 		.id = 71,
594 	},
595 	{
596 		.name = "pit64b2_clk",
597 		.parent = "mck1",
598 		.id = 72,
599 	},
600 	{
601 		.name = "pit64b3_clk",
602 		.parent = "mck1",
603 		.id = 73,
604 	},
605 	{
606 		.name = "pit64b4_clk",
607 		.parent = "mck1",
608 		.id = 74,
609 	},
610 	{
611 		.name = "pit64b5_clk",
612 		.parent = "mck1",
613 		.id = 75,
614 	},
615 	{
616 		.name = "pwm_clk",
617 		.parent = "mck1",
618 		.id = 77,
619 	},
620 	{
621 		.name = "qspi0_clk",
622 		.parent = "mck1",
623 		.id = 78,
624 	},
625 	{
626 		.name = "qspi1_clk",
627 		.parent = "mck1",
628 		.id = 79,
629 	},
630 	{
631 		.name = "sdmmc0_clk",
632 		.parent = "mck1",
633 		.id = 80,
634 	},
635 	{
636 		.name = "sdmmc1_clk",
637 		.parent = "mck1",
638 		.id = 81,
639 	},
640 	{
641 		.name = "sdmmc2_clk",
642 		.parent = "mck1",
643 		.id = 82,
644 	},
645 	{
646 		.name = "sha_clk",
647 		.parent = "mck1",
648 		.id = 83,
649 	},
650 	{
651 		.name = "spdifrx_clk",
652 		.parent = "mck1",
653 		.id = 84,
654 		.output = { .max = 200000000, },
655 	},
656 	{
657 		.name = "spdiftx_clk",
658 		.parent = "mck1",
659 		.id = 85,
660 		.output = { .max = 200000000, },
661 	},
662 	{
663 		.name = "ssc0_clk",
664 		.parent = "mck1",
665 		.id = 86,
666 		.output = { .max = 200000000, },
667 	},
668 	{
669 		.name = "ssc1_clk",
670 		.parent = "mck1",
671 		.id = 87,
672 		.output = { .max = 200000000, },
673 	},
674 	{
675 		.name = "tcb0_ch0_clk",
676 		.parent = "mck1",
677 		.id = 88,
678 		.output = { .max = 200000000, },
679 	},
680 	{
681 		.name = "tcb0_ch1_clk",
682 		.parent = "mck1",
683 		.id = 89,
684 		.output = { .max = 200000000, },
685 	},
686 	{
687 		.name = "tcb0_ch2_clk",
688 		.parent = "mck1",
689 		.id = 90,
690 		.output = { .max = 200000000, },
691 	},
692 	{
693 		.name = "tcb1_ch0_clk",
694 		.parent = "mck1",
695 		.id = 91,
696 		.output = { .max = 200000000, },
697 	},
698 	{
699 		.name = "tcb1_ch1_clk",
700 		.parent = "mck1",
701 		.id = 92,
702 		.output = { .max = 200000000, },
703 	},
704 	{
705 		.name = "tcb1_ch2_clk",
706 		.parent = "mck1",
707 		.id = 93,
708 		.output = { .max = 200000000, },
709 	},
710 	{
711 		.name = "tcpca_clk",
712 		.parent = "mck1",
713 		.id = 94,
714 	},
715 	{
716 		.name = "tcpcb_clk",
717 		.parent = "mck1",
718 		.id = 95,
719 	},
720 	{
721 		.name = "tdes_clk",
722 		.parent = "mck1",
723 		.id = 96,
724 	},
725 	{
726 		.name = "trng_clk",
727 		.parent = "mck1",
728 		.id = 97,
729 	},
730 	{
731 		.name = "udphsa_clk",
732 		.parent = "mck1",
733 		.id = 104,
734 	},
735 	{
736 		.name = "udphsb_clk",
737 		.parent = "mck1",
738 		.id = 105,
739 	},
740 	{
741 		.name = "uhphs_clk",
742 		.parent = "mck1",
743 		.id = 106,
744 	},
745 };
746 
747 /* UTMI clock description */
748 static struct {
749 	const char *name;
750 	const char *parent;
751 	uint8_t id;
752 } sama7_utmick[] = {
753 	{ .name = "utmi1ck", .parent = "utmick", .id = 0, },
754 	{ .name = "utmi2ck", .parent = "utmi1ck", .id = 1, },
755 	{ .name = "utmi3ck", .parent = "utmi1ck", .id = 2, },
756 };
757 
758 /* Generic clock description */
759 struct sama7g5_gck {
760 	const char *name;
761 	const char *parents[8];
762 	const char parents_mux_table[8];
763 	struct clk_range output;
764 	int parents_chg_id; /* id in parent array of changeable PLL parent */
765 	uint8_t parents_count;
766 	uint8_t id;
767 };
768 
769 static const struct sama7g5_gck sama7g5_gcks[] = {
770 	{
771 		.name  = "adc_gclk",
772 		.id = 26,
773 		.output = { .max = 100000000, },
774 		.parents = { "syspll_divpmcck",
775 			     "imgpll_divpmcck",
776 			     "audiopll_divck", },
777 		.parents_mux_table = { 5, 7, 9, },
778 		.parents_count = 3,
779 		.parents_chg_id = INT_MIN,
780 	},
781 	{
782 		.name  = "asrc_gclk",
783 		.id = 30,
784 		.output = { .max = 200000000 },
785 		.parents = { "audiopll_divck", },
786 		.parents_mux_table = { 9, },
787 		.parents_count = 1,
788 		.parents_chg_id = INT_MIN,
789 	},
790 	{
791 		.name  = "csi_gclk",
792 		.id = 33,
793 		.output = { .max = 27000000  },
794 		.parents = { "ddrpll_divpmcck", "imgpll_divpmcck", },
795 		.parents_mux_table = { 6, 7, },
796 		.parents_count = 2,
797 		.parents_chg_id = INT_MIN,
798 	},
799 	{
800 		.name  = "flex0_gclk",
801 		.id = 38,
802 		.output = { .max = 200000000 },
803 		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
804 		.parents_mux_table = { 5, 8, },
805 		.parents_count = 2,
806 		.parents_chg_id = INT_MIN,
807 	},
808 	{
809 		.name  = "flex1_gclk",
810 		.id = 39,
811 		.output = { .max = 200000000 },
812 		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
813 		.parents_mux_table = { 5, 8, },
814 		.parents_count = 2,
815 		.parents_chg_id = INT_MIN,
816 	},
817 	{
818 		.name  = "flex2_gclk",
819 		.id = 40,
820 		.output = { .max = 200000000 },
821 		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
822 		.parents_mux_table = { 5, 8, },
823 		.parents_count = 2,
824 		.parents_chg_id = INT_MIN,
825 	},
826 	{
827 		.name  = "flex3_gclk",
828 		.id = 41,
829 		.output = { .max = 200000000 },
830 		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
831 		.parents_mux_table = { 5, 8, },
832 		.parents_count = 2,
833 		.parents_chg_id = INT_MIN,
834 	},
835 	{
836 		.name  = "flex4_gclk",
837 		.id = 42,
838 		.output = { .max = 200000000 },
839 		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
840 		.parents_mux_table = { 5, 8, },
841 		.parents_count = 2,
842 		.parents_chg_id = INT_MIN,
843 	},
844 	{
845 		.name  = "flex5_gclk",
846 		.id = 43,
847 		.output = { .max = 200000000 },
848 		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
849 		.parents_mux_table = { 5, 8, },
850 		.parents_count = 2,
851 		.parents_chg_id = INT_MIN,
852 	},
853 	{
854 		.name  = "flex6_gclk",
855 		.id = 44,
856 		.output = { .max = 200000000 },
857 		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
858 		.parents_mux_table = { 5, 8, },
859 		.parents_count = 2,
860 		.parents_chg_id = INT_MIN,
861 	},
862 	{
863 		.name  = "flex7_gclk",
864 		.id = 45,
865 		.output = { .max = 200000000 },
866 		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
867 		.parents_mux_table = { 5, 8, },
868 		.parents_count = 2,
869 		.parents_chg_id = INT_MIN,
870 	},
871 	{
872 		.name  = "flex8_gclk",
873 		.id = 46,
874 		.output = { .max = 200000000 },
875 		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
876 		.parents_mux_table = { 5, 8, },
877 		.parents_count = 2,
878 		.parents_chg_id = INT_MIN,
879 	},
880 	{
881 		.name  = "flex9_gclk",
882 		.id = 47,
883 		.output = { .max = 200000000 },
884 		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
885 		.parents_mux_table = { 5, 8, },
886 		.parents_count = 2,
887 		.parents_chg_id = INT_MIN,
888 	},
889 	{
890 		.name  = "flex10_gclk",
891 		.id = 48,
892 		.output = { .max = 200000000 },
893 		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
894 		.parents_mux_table = { 5, 8, },
895 		.parents_count = 2,
896 		.parents_chg_id = INT_MIN,
897 	},
898 	{
899 		.name  = "flex11_gclk",
900 		.id = 49,
901 		.output = { .max = 200000000 },
902 		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
903 		.parents_mux_table = { 5, 8, },
904 		.parents_count = 2,
905 		.parents_chg_id = INT_MIN,
906 	},
907 	{
908 		.name  = "gmac0_gclk",
909 		.id = 51,
910 		.output = { .max = 125000000 },
911 		.parents = { "ethpll_divpmcck", },
912 		.parents_mux_table = { 10, },
913 		.parents_count = 1,
914 		.parents_chg_id = 3,
915 	},
916 	{
917 		.name  = "gmac1_gclk",
918 		.id = 52,
919 		.output = { .max = 50000000  },
920 		.parents = { "ethpll_divpmcck", },
921 		.parents_mux_table = { 10, },
922 		.parents_count = 1,
923 		.parents_chg_id = INT_MIN,
924 	},
925 	{
926 		.name  = "gmac0_tsu_gclk",
927 		.id = 53,
928 		.output = { .max = 300000000 },
929 		.parents = { "audiopll_divck", "ethpll_divpmcck", },
930 		.parents_mux_table = { 9, 10, },
931 		.parents_count = 2,
932 		.parents_chg_id = INT_MIN,
933 	},
934 	{
935 		.name  = "gmac1_tsu_gclk",
936 		.id = 54,
937 		.output = { .max = 300000000 },
938 		.parents = { "audiopll_divck", "ethpll_divpmcck", },
939 		.parents_mux_table = { 9, 10, },
940 		.parents_count = 2,
941 		.parents_chg_id = INT_MIN,
942 	},
943 	{
944 		.name  = "i2smcc0_gclk",
945 		.id = 57,
946 		.output = { .max = 100000000 },
947 		.parents = { "syspll_divpmcck", "audiopll_divck", },
948 		.parents_mux_table = { 5, 9, },
949 		.parents_count = 2,
950 		.parents_chg_id = INT_MIN,
951 	},
952 	{
953 		.name  = "i2smcc1_gclk",
954 		.id = 58,
955 		.output = { .max = 100000000 },
956 		.parents = { "syspll_divpmcck", "audiopll_divck", },
957 		.parents_mux_table = { 5, 9, },
958 		.parents_count = 2,
959 		.parents_chg_id = INT_MIN,
960 	},
961 	{
962 		.name  = "mcan0_gclk",
963 		.id = 61,
964 		.output = { .max = 200000000 },
965 		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
966 		.parents_mux_table = { 5, 8, },
967 		.parents_count = 2,
968 		.parents_chg_id = INT_MIN,
969 	},
970 	{
971 		.name  = "mcan1_gclk",
972 		.id = 62,
973 		.output = { .max = 200000000 },
974 		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
975 		.parents_mux_table = { 5, 8, },
976 		.parents_count = 2,
977 		.parents_chg_id = INT_MIN,
978 	},
979 	{
980 		.name  = "mcan2_gclk",
981 		.id = 63,
982 		.output = { .max = 200000000 },
983 		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
984 		.parents_mux_table = { 5, 8, },
985 		.parents_count = 2,
986 		.parents_chg_id = INT_MIN,
987 	},
988 	{
989 		.name  = "mcan3_gclk",
990 		.id = 64,
991 		.output = { .max = 200000000 },
992 		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
993 		.parents_mux_table = { 5, 8, },
994 		.parents_count = 2,
995 		.parents_chg_id = INT_MIN,
996 	},
997 	{
998 		.name  = "mcan4_gclk",
999 		.id = 65,
1000 		.output = { .max = 200000000 },
1001 		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
1002 		.parents_mux_table = { 5, 8, },
1003 		.parents_count = 2,
1004 		.parents_chg_id = INT_MIN,
1005 	},
1006 	{
1007 		.name  = "mcan5_gclk",
1008 		.id = 66,
1009 		.output = { .max = 200000000 },
1010 		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
1011 		.parents_mux_table = { 5, 8, },
1012 		.parents_count = 2,
1013 		.parents_chg_id = INT_MIN,
1014 	},
1015 	{
1016 		.name  = "pdmc0_gclk",
1017 		.id = 68,
1018 		.output = { .max = 50000000  },
1019 		.parents = { "syspll_divpmcck", "audiopll_divck", },
1020 		.parents_mux_table = { 5, 9, },
1021 		.parents_count = 2,
1022 		.parents_chg_id = INT_MIN,
1023 	},
1024 	{
1025 		.name  = "pdmc1_gclk",
1026 		.id = 69,
1027 		.output = { .max = 50000000, },
1028 		.parents = { "syspll_divpmcck", "audiopll_divck", },
1029 		.parents_mux_table = { 5, 9, },
1030 		.parents_count = 2,
1031 		.parents_chg_id = INT_MIN,
1032 	},
1033 	{
1034 		.name  = "pit64b0_gclk",
1035 		.id = 70,
1036 		.output = { .max = 200000000 },
1037 		.parents = { "syspll_divpmcck", "imgpll_divpmcck",
1038 			     "baudpll_divpmcck", "audiopll_divck",
1039 			     "ethpll_divpmcck", },
1040 		.parents_mux_table = { 5, 7, 8, 9, 10, },
1041 		.parents_count = 5,
1042 		.parents_chg_id = INT_MIN,
1043 	},
1044 	{
1045 		.name  = "pit64b1_gclk",
1046 		.id = 71,
1047 		.output = { .max = 200000000 },
1048 		.parents = { "syspll_divpmcck", "imgpll_divpmcck",
1049 			     "baudpll_divpmcck", "audiopll_divck",
1050 			     "ethpll_divpmcck", },
1051 		.parents_mux_table = { 5, 7, 8, 9, 10, },
1052 		.parents_count = 5,
1053 		.parents_chg_id = INT_MIN,
1054 	},
1055 	{
1056 		.name  = "pit64b2_gclk",
1057 		.id = 72,
1058 		.output = { .max = 200000000 },
1059 		.parents = { "syspll_divpmcck", "imgpll_divpmcck",
1060 			     "baudpll_divpmcck", "audiopll_divck",
1061 			     "ethpll_divpmcck", },
1062 		.parents_mux_table = { 5, 7, 8, 9, 10, },
1063 		.parents_count = 5,
1064 		.parents_chg_id = INT_MIN,
1065 	},
1066 	{
1067 		.name  = "pit64b3_gclk",
1068 		.id = 73,
1069 		.output = { .max = 200000000 },
1070 		.parents = { "syspll_divpmcck", "imgpll_divpmcck",
1071 			     "baudpll_divpmcck", "audiopll_divck",
1072 			     "ethpll_divpmcck", },
1073 		.parents_mux_table = { 5, 7, 8, 9, 10, },
1074 		.parents_count = 5,
1075 		.parents_chg_id = INT_MIN,
1076 	},
1077 	{
1078 		.name  = "pit64b4_gclk",
1079 		.id = 74,
1080 		.output = { .max = 200000000 },
1081 		.parents = { "syspll_divpmcck", "imgpll_divpmcck",
1082 			     "baudpll_divpmcck", "audiopll_divck",
1083 			     "ethpll_divpmcck", },
1084 		.parents_mux_table = { 5, 7, 8, 9, 10, },
1085 		.parents_count = 5,
1086 		.parents_chg_id = INT_MIN,
1087 	},
1088 	{
1089 		.name  = "pit64b5_gclk",
1090 		.id = 75,
1091 		.output = { .max = 200000000 },
1092 		.parents = { "syspll_divpmcck", "imgpll_divpmcck",
1093 			     "baudpll_divpmcck", "audiopll_divck",
1094 			     "ethpll_divpmcck", },
1095 		.parents_mux_table = { 5, 7, 8, 9, 10, },
1096 		.parents_count = 5,
1097 		.parents_chg_id = INT_MIN,
1098 	},
1099 	{
1100 		.name  = "qspi0_gclk",
1101 		.id = 78,
1102 		.output = { .max = 200000000 },
1103 		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
1104 		.parents_mux_table = { 5, 8, },
1105 		.parents_count = 2,
1106 		.parents_chg_id = INT_MIN,
1107 	},
1108 	{
1109 		.name  = "qspi1_gclk",
1110 		.id = 79,
1111 		.output = { .max = 200000000 },
1112 		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
1113 		.parents_mux_table = { 5, 8, },
1114 		.parents_count = 2,
1115 		.parents_chg_id = INT_MIN,
1116 	},
1117 	{
1118 		.name  = "sdmmc0_gclk",
1119 		.id = 80,
1120 		.output = { .max = 208000000 },
1121 		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
1122 		.parents_mux_table = { 5, 8, },
1123 		.parents_count = 2,
1124 		.parents_chg_id = 4,
1125 	},
1126 	{
1127 		.name  = "sdmmc1_gclk",
1128 		.id = 81,
1129 		.output = { .max = 208000000 },
1130 		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
1131 		.parents_mux_table = { 5, 8, },
1132 		.parents_count = 2,
1133 		.parents_chg_id = 4,
1134 	},
1135 	{
1136 		.name  = "sdmmc2_gclk",
1137 		.id = 82,
1138 		.output = { .max = 208000000 },
1139 		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
1140 		.parents_mux_table = { 5, 8, },
1141 		.parents_count = 2,
1142 		.parents_chg_id = 4,
1143 	},
1144 	{
1145 		.name  = "spdifrx_gclk",
1146 		.id = 84,
1147 		.output = { .max = 150000000 },
1148 		.parents = { "syspll_divpmcck", "audiopll_divck", },
1149 		.parents_mux_table = { 5, 9, },
1150 		.parents_count = 2,
1151 		.parents_chg_id = INT_MIN,
1152 	},
1153 	{
1154 		.name = "spdiftx_gclk",
1155 		.id = 85,
1156 		.output = { .max = 25000000  },
1157 		.parents = { "syspll_divpmcck", "audiopll_divck", },
1158 		.parents_mux_table = { 5, 9, },
1159 		.parents_count = 2,
1160 		.parents_chg_id = INT_MIN,
1161 	},
1162 	{
1163 		.name  = "tcb0_ch0_gclk",
1164 		.id = 88,
1165 		.output = { .max = 200000000 },
1166 		.parents = { "syspll_divpmcck", "imgpll_divpmcck",
1167 			     "baudpll_divpmcck", "audiopll_divck",
1168 			     "ethpll_divpmcck", },
1169 		.parents_mux_table = { 5, 7, 8, 9, 10, },
1170 		.parents_count = 5,
1171 		.parents_chg_id = INT_MIN,
1172 	},
1173 	{
1174 		.name  = "tcb1_ch0_gclk",
1175 		.id = 91,
1176 		.output = { .max = 200000000 },
1177 		.parents = { "syspll_divpmcck", "imgpll_divpmcck",
1178 			     "baudpll_divpmcck", "audiopll_divck",
1179 			     "ethpll_divpmcck", },
1180 		.parents_mux_table = { 5, 7, 8, 9, 10, },
1181 		.parents_count = 5,
1182 		.parents_chg_id = INT_MIN,
1183 	},
1184 	{
1185 		.name  = "tcpca_gclk",
1186 		.id = 94,
1187 		.output = { .max = 32768, },
1188 		.parents_chg_id = INT_MIN,
1189 	},
1190 	{
1191 		.name  = "tcpcb_gclk",
1192 		.id = 95,
1193 		.output = { .max = 32768, },
1194 		.parents_chg_id = INT_MIN,
1195 	},
1196 };
1197 
1198 /* MCK0 characteristics */
1199 static const struct clk_master_charac mck0_characteristics = {
1200 	.output = { .min = 32768, .max = 200000000 },
1201 	.divisors = { 1, 2, 4, 3, 5 },
1202 	.have_div3_pres = 1,
1203 };
1204 
1205 /* MCK0 layout */
1206 static const struct clk_master_layout mck0_layout = {
1207 	.mask = 0x773,
1208 	.pres_shift = 4,
1209 	.offset = 0x28,
1210 };
1211 
1212 /* Peripheral clock layout */
1213 static const struct clk_pcr_layout sama7g5_pcr_layout = {
1214 	.offset = 0x88,
1215 	.cmd = BIT(31),
1216 	.div_mask = GENMASK_32(27, 20),
1217 	.gckcss_mask = GENMASK_32(12, 8),
1218 	.pid_mask = GENMASK_32(6, 0),
1219 };
1220 
1221 static const struct clk_programmable_layout sama7g5_prog_layout = {
1222 	.pres_mask = 0xff,
1223 	.pres_shift = 8,
1224 	.css_mask = GENMASK_32(4, 0),
1225 	.have_slck_mck = 0,
1226 	.is_pres_direct = 1,
1227 };
1228 
1229 static const struct {
1230 	const char *name;
1231 	uint8_t id;
1232 } sama7g5_progck[] = {
1233 	{ .name = "prog0", .id = 0 },
1234 	{ .name = "prog1", .id = 1 },
1235 	{ .name = "prog2", .id = 2 },
1236 	{ .name = "prog3", .id = 3 },
1237 	{ .name = "prog4", .id = 4 },
1238 	{ .name = "prog5", .id = 5 },
1239 	{ .name = "prog6", .id = 6 },
1240 	{ .name = "prog7", .id = 7 },
1241 };
1242 
1243 static struct pmc_data *sama7g5_pmc;
1244 
1245 vaddr_t at91_pmc_get_base(void)
1246 {
1247 	assert(sama7g5_pmc);
1248 
1249 	return sama7g5_pmc->base;
1250 }
1251 
1252 TEE_Result at91_pmc_clk_get(unsigned int type, unsigned int idx,
1253 			    struct clk **clk)
1254 {
1255 	return pmc_clk_get(sama7g5_pmc, type, idx, clk);
1256 }
1257 
1258 static TEE_Result pmc_setup_sama7g5(const void *fdt, int nodeoffset,
1259 				    const void *data __unused)
1260 {
1261 	struct clk *pll_frac_clk[PLL_ID_MAX] = { };
1262 	struct clk *pll_div_clk[PLL_ID_MAX] = { };
1263 	TEE_Result res = TEE_ERROR_GENERIC;
1264 	const uint32_t *fdt_prop = NULL;
1265 	struct pmc_clk *pmc_clk = NULL;
1266 	struct clk *parents[11] = { };
1267 	struct clk *main_xtal_clk = NULL;
1268 	struct clk *main_rc_osc = NULL;
1269 	struct clk *main_osc = NULL;
1270 	struct clk *mck0_clk = NULL;
1271 	struct clk *main_clk = NULL;
1272 	struct clk *md_slck = NULL;
1273 	struct clk *td_slck = NULL;
1274 	struct clk *parent = NULL;
1275 	struct clk *clk = NULL;
1276 	unsigned int i = 0;
1277 	unsigned int j = 0;
1278 	vaddr_t base = 0;
1279 	size_t size = 0;
1280 	int bypass = 0;
1281 
1282 	if (dt_map_dev(fdt, nodeoffset, &base, &size, DT_MAP_AUTO) < 0)
1283 		panic();
1284 
1285 	if (fdt_get_status(fdt, nodeoffset) == DT_STATUS_OK_SEC)
1286 		matrix_configure_periph_secure(ID_PMC);
1287 
1288 	res = clk_dt_get_by_name(fdt, nodeoffset, "md_slck", &md_slck);
1289 	if (res)
1290 		return res;
1291 
1292 	res = clk_dt_get_by_name(fdt, nodeoffset, "td_slck", &td_slck);
1293 	if (res)
1294 		return res;
1295 
1296 	res = clk_dt_get_by_name(fdt, nodeoffset, "main_xtal", &main_xtal_clk);
1297 	if (res)
1298 		return res;
1299 
1300 	sama7g5_pmc = pmc_data_allocate(PMC_SAMA7G5_CORE_CLK_COUNT,
1301 					ARRAY_SIZE(sama7g5_systemck),
1302 					ARRAY_SIZE(peri_clks),
1303 					ARRAY_SIZE(sama7g5_gcks), 8);
1304 	if (!sama7g5_pmc)
1305 		panic();
1306 
1307 	sama7g5_pmc->base = base;
1308 
1309 	main_rc_osc = pmc_register_main_rc_osc(sama7g5_pmc, "main_rc_osc",
1310 					       12000000);
1311 	if (!main_rc_osc)
1312 		panic();
1313 
1314 	fdt_prop = fdt_getprop(fdt, nodeoffset, "atmel,osc-bypass", NULL);
1315 	if (fdt_prop)
1316 		bypass = fdt32_to_cpu(*fdt_prop);
1317 
1318 	main_osc = pmc_register_main_osc(sama7g5_pmc, "main_osc",
1319 					 main_xtal_clk, bypass);
1320 	if (!main_osc)
1321 		panic();
1322 
1323 	parents[0] = main_rc_osc;
1324 	parents[1] = main_osc;
1325 	main_clk = at91_clk_register_sam9x5_main(sama7g5_pmc, "mainck",
1326 						 parents, 2);
1327 	if (!main_clk)
1328 		panic();
1329 	pmc_clk = &sama7g5_pmc->chws[PMC_MAIN];
1330 	pmc_clk->clk = main_clk;
1331 	pmc_clk->id = PMC_MAIN;
1332 
1333 	for (i = 0; i < PLL_ID_MAX; i++) {
1334 		struct pmc_data *pmc = sama7g5_pmc;
1335 		const struct sama7g5_pll *p = NULL;
1336 
1337 		for (j = 0; j < 3; j++) {
1338 			p = &sama7g5_plls[i][j];
1339 			if (!p->name)
1340 				continue;
1341 
1342 			switch (p->type) {
1343 			case PLL_TYPE_FRAC:
1344 				if (!strcmp(p->parent, "mainck"))
1345 					parent = main_clk;
1346 				else if (!strcmp(p->parent, "main_xtal"))
1347 					parent = main_xtal_clk;
1348 				else
1349 					parent = pmc_clk_get_by_name(pmc->chws,
1350 								     pmc->ncore,
1351 								     p->parent);
1352 				assert(parent);
1353 
1354 				clk = sam9x60_clk_register_frac_pll(sama7g5_pmc,
1355 								    p->name,
1356 								    parent, i,
1357 								    p->charac,
1358 								    p->layout,
1359 								    p->flags);
1360 				pll_frac_clk[i] = clk;
1361 				break;
1362 
1363 			case PLL_TYPE_DIV:
1364 				parent = clk;
1365 				clk = sam9x60_clk_register_div_pll(sama7g5_pmc,
1366 								   p->name,
1367 								   parent, i,
1368 								   p->charac,
1369 								   p->layout,
1370 								   p->flags,
1371 								   p->safe_div);
1372 				break;
1373 
1374 			default:
1375 				continue;
1376 			}
1377 			if (!clk)
1378 				panic();
1379 
1380 			if (p->eid) {
1381 				sama7g5_pmc->chws[p->eid].clk = clk;
1382 				sama7g5_pmc->chws[p->eid].id = p->eid;
1383 				sam_set_clock_range(PMC_TYPE_CORE, p->eid,
1384 						    p->charac->output);
1385 			}
1386 		}
1387 		p = &sama7g5_plls[i][PLL_TYPE_DIV];
1388 		pll_div_clk[i] = sama7g5_pmc->chws[p->eid].clk;
1389 	}
1390 
1391 	parents[0] = md_slck;
1392 	parents[1] = main_clk;
1393 	parents[2] = pll_div_clk[PLL_ID_CPU];
1394 	parents[3] = pll_div_clk[PLL_ID_SYS];
1395 	clk = at91_clk_register_master_pres(sama7g5_pmc, "fclk", 4,
1396 					    parents,
1397 					    &mck0_layout,
1398 					    &mck0_characteristics, INT_MIN);
1399 	if (!clk)
1400 		panic();
1401 	pmc_clk = &sama7g5_pmc->chws[PMC_MCK_PRES];
1402 	pmc_clk->clk = clk;
1403 	pmc_clk->id = PMC_MCK_PRES;
1404 
1405 	mck0_clk = at91_clk_register_master_div(sama7g5_pmc, "mck0",
1406 						clk,
1407 						&mck0_layout,
1408 						&mck0_characteristics);
1409 	if (!mck0_clk)
1410 		panic();
1411 	pmc_clk = &sama7g5_pmc->chws[PMC_MCK];
1412 	pmc_clk->clk = mck0_clk;
1413 	pmc_clk->id = PMC_MCK;
1414 	sam_set_clock_range(PMC_TYPE_SYSTEM, PMC_MCK,
1415 			    &mck0_characteristics.output);
1416 
1417 	parents[0] = md_slck;
1418 	parents[1] = td_slck;
1419 	parents[2] = main_clk;
1420 	parents[3] = mck0_clk;
1421 	for (i = 0; i < ARRAY_SIZE(sama7g5_mckx); i++) {
1422 		const struct sama7g5_mck *mck = &sama7g5_mckx[i];
1423 		uint8_t num_parents = 4 + mck->eparents_count;
1424 		uint32_t *mux_table = calloc(num_parents, sizeof(*mux_table));
1425 
1426 		if (!mux_table)
1427 			panic();
1428 
1429 		mux_table[0] = 0;
1430 		mux_table[1] = 1;
1431 		mux_table[2] = 2;
1432 		mux_table[3] = 3;
1433 		for (j = 0; j < mck->eparents_count; j++) {
1434 			parents[4 + j] = pmc_clk_get_by_name(sama7g5_pmc->chws,
1435 							     sama7g5_pmc->ncore,
1436 							     mck->eparents[j]);
1437 			assert(parents[4 + j]);
1438 			mux_table[4 + j] = mck->eparents_mux_table[j];
1439 		}
1440 
1441 		clk = at91_clk_sama7g5_register_master(sama7g5_pmc,
1442 						       mck->name,
1443 						       num_parents, parents,
1444 						       mux_table,
1445 						       mck->id,
1446 						       mck->eparents_chg_id);
1447 		if (!clk)
1448 			panic();
1449 
1450 		sama7g5_pmc->chws[PMC_MCK1 + i].clk = clk;
1451 	}
1452 
1453 	clk = at91_clk_sama7g5_register_utmi(sama7g5_pmc, "utmick", main_clk);
1454 	if (!clk)
1455 		panic();
1456 	sama7g5_pmc->chws[PMC_UTMI].clk = clk;
1457 	sama7g5_pmc->chws[PMC_UTMI].id = PMC_UTMI;
1458 
1459 	for (i = 0; i < ARRAY_SIZE(sama7_utmick); i++) {
1460 		if (strcmp("utmick", sama7_utmick[i].parent) == 0)
1461 			parent = clk;
1462 		else if (strcmp("utmi1ck", sama7_utmick[i].parent) == 0)
1463 			parent = sama7g5_pmc->chws[PMC_UTMI1].clk;
1464 		else
1465 			panic();
1466 		clk = sama7_utmi_clk_register(sama7_utmick[i].name, parent,
1467 					      sama7_utmick[i].id);
1468 		if (!clk)
1469 			panic();
1470 
1471 		pmc_clk = &sama7g5_pmc->chws[PMC_UTMI1 + i];
1472 		pmc_clk->clk = clk;
1473 		pmc_clk->id = PMC_UTMI1 + i;
1474 	}
1475 
1476 	parents[0] = md_slck;
1477 	parents[1] = td_slck;
1478 	parents[2] = main_clk;
1479 	parents[3] = pll_div_clk[PLL_ID_SYS];
1480 	parents[4] = pll_div_clk[PLL_ID_DDR];
1481 	parents[5] = pll_div_clk[PLL_ID_IMG];
1482 	parents[6] = pll_div_clk[PLL_ID_BAUD];
1483 	parents[7] = pll_div_clk[PLL_ID_AUDIO];
1484 	parents[8] = pll_div_clk[PLL_ID_ETH];
1485 	for (i = 0; i < ARRAY_SIZE(sama7g5_progck); i++) {
1486 		clk = at91_clk_register_programmable(sama7g5_pmc,
1487 						     sama7g5_progck[i].name,
1488 						     parents, 9, i,
1489 						     &sama7g5_prog_layout);
1490 		if (!clk)
1491 			panic();
1492 
1493 		pmc_clk = &sama7g5_pmc->pchws[i];
1494 		pmc_clk->clk = clk;
1495 		pmc_clk->id = sama7g5_progck[i].id;
1496 	}
1497 
1498 	for (i = 0; i < ARRAY_SIZE(sama7g5_systemck); i++) {
1499 		clk = at91_clk_register_system(sama7g5_pmc,
1500 					       sama7g5_systemck[i].name,
1501 					       sama7g5_pmc->pchws[i].clk,
1502 					       sama7g5_systemck[i].id);
1503 		if (!clk)
1504 			panic();
1505 
1506 		pmc_clk = &sama7g5_pmc->shws[i];
1507 		pmc_clk->clk = clk;
1508 		pmc_clk->id = sama7g5_systemck[i].id;
1509 	}
1510 
1511 	for (i = 0; i < ARRAY_SIZE(peri_clks); i++) {
1512 		parent = pmc_clk_get_by_name(sama7g5_pmc->chws,
1513 					     sama7g5_pmc->ncore,
1514 					     peri_clks[i].parent);
1515 		clk = at91_clk_register_sam9x5_periph(sama7g5_pmc,
1516 						      &sama7g5_pcr_layout,
1517 						      peri_clks[i].name,
1518 						      parent,
1519 						      peri_clks[i].id,
1520 						      &peri_clks[i].output);
1521 		if (!clk)
1522 			panic();
1523 
1524 		pmc_clk = &sama7g5_pmc->phws[i];
1525 		pmc_clk->clk = clk;
1526 		pmc_clk->id = peri_clks[i].id;
1527 
1528 		sam_set_clock_range(PMC_TYPE_PERIPHERAL, peri_clks[i].id,
1529 				    &peri_clks[i].output);
1530 	}
1531 
1532 	parents[0] = md_slck;
1533 	parents[1] = td_slck;
1534 	parents[2] = main_clk;
1535 	for (i = 0; i < ARRAY_SIZE(sama7g5_gcks); i++) {
1536 		const struct sama7g5_gck *gck = sama7g5_gcks + i;
1537 		uint8_t num_parents = 3 + gck->parents_count;
1538 		uint32_t *mux_table = calloc(num_parents, sizeof(*mux_table));
1539 
1540 		if (!mux_table)
1541 			panic();
1542 
1543 		mux_table[0] = 0;
1544 		mux_table[1] = 1;
1545 		mux_table[2] = 2;
1546 		for (j = 0; j < gck->parents_count; j++) {
1547 			parents[3 + j] = pmc_clk_get_by_name(sama7g5_pmc->chws,
1548 							     sama7g5_pmc->ncore,
1549 							     gck->parents[j]);
1550 			assert(parents[3 + j]);
1551 			mux_table[3 + j] = gck->parents_mux_table[j];
1552 		}
1553 
1554 		clk = at91_clk_register_generated(sama7g5_pmc,
1555 						  &sama7g5_pcr_layout,
1556 						  gck->name, parents,
1557 						  mux_table,
1558 						  num_parents, gck->id,
1559 						  &gck->output,
1560 						  gck->parents_chg_id);
1561 		if (!clk)
1562 			panic();
1563 
1564 		pmc_clk = &sama7g5_pmc->ghws[i];
1565 		pmc_clk->clk = clk;
1566 		pmc_clk->id = gck->id;
1567 
1568 		sam_set_clock_range(PMC_TYPE_GCK, gck->id, &gck->output);
1569 	}
1570 
1571 	res = clk_set_rate(pll_frac_clk[PLL_ID_ETH], 625000000);
1572 	if (res)
1573 		panic();
1574 
1575 	res = clk_set_rate(pll_div_clk[PLL_ID_ETH], 625000000);
1576 	if (res)
1577 		panic();
1578 
1579 	res = clk_set_rate(pll_frac_clk[PLL_ID_AUDIO], 983040000);
1580 	if (res)
1581 		panic();
1582 
1583 	res = clk_set_rate(pll_div_clk[PLL_ID_AUDIO], 196608000);
1584 	if (res)
1585 		panic();
1586 
1587 	clk = pmc_clk_get_by_name(sama7g5_pmc->ghws, sama7g5_pmc->ngck,
1588 				  "pdmc0_gclk");
1589 	assert(clk);
1590 	res = clk_set_parent(clk, pll_div_clk[PLL_ID_AUDIO]);
1591 	if (res)
1592 		panic();
1593 
1594 	clk = pmc_clk_get_by_name(sama7g5_pmc->ghws, sama7g5_pmc->ngck,
1595 				  "i2smcc0_gclk");
1596 	assert(clk);
1597 	res = clk_set_parent(clk, pll_div_clk[PLL_ID_AUDIO]);
1598 	if (res)
1599 		panic();
1600 
1601 	res = clk_dt_register_clk_provider(fdt, nodeoffset, clk_dt_pmc_get,
1602 					   sama7g5_pmc);
1603 	if (res)
1604 		panic();
1605 
1606 	pmc_register_pm();
1607 
1608 	return TEE_SUCCESS;
1609 }
1610 
1611 CLK_DT_DECLARE(sama7g5_clk, "microchip,sama7g5-pmc", pmc_setup_sama7g5);
1612