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