xref: /linux/drivers/clk/at91/sama7g5.c (revision 55d0969c451159cff86949b38c39171cab962069)
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 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);
1247