Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[linux-block.git] / drivers / clk / at91 / sama7g5.c
CommitLineData
cb783bbb
CB
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
cb783bbb 19static DEFINE_SPINLOCK(pmc_pll_lock);
7a110b91 20static DEFINE_SPINLOCK(pmc_mck0_lock);
cb783bbb
CB
21static DEFINE_SPINLOCK(pmc_mckX_lock);
22
a3ef91f5 23/*
cb783bbb
CB
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 */
33enum 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
de3383e9
CB
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 */
50enum pll_component_id {
51 PLL_COMPID_FRAC,
52 PLL_COMPID_DIV0,
53 PLL_COMPID_DIV1,
2d6e9ee7 54 PLL_COMPID_MAX,
de3383e9
CB
55};
56
a3ef91f5 57/*
cb783bbb
CB
58 * PLL type identifiers
59 * @PLL_TYPE_FRAC: fractional PLL identifier
60 * @PLL_TYPE_DIV: divider PLL identifier
61 */
62enum pll_type {
63 PLL_TYPE_FRAC,
64 PLL_TYPE_DIV,
65};
66
67/* Layout for fractional PLLs. */
68static 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. */
76static 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. */
84static 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
120d5d8b
CB
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 */
96static const struct clk_range cpu_pll_outputs[] = {
97 { .min = 2343750, .max = 1000000002 },
98};
99
100/* PLL output range. */
101static const struct clk_range pll_outputs[] = {
102 { .min = 2343750, .max = 1200000000 },
103};
104
a402c663
VR
105/* Fractional PLL core output range. */
106static const struct clk_range core_outputs[] = {
107 { .min = 600000000, .max = 1200000000 },
108};
109
120d5d8b
CB
110/* CPU PLL characteristics. */
111static 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,
a402c663 115 .core_output = core_outputs,
120d5d8b
CB
116};
117
118/* PLL characteristics. */
119static const struct clk_pll_characteristics pll_characteristics = {
120 .input = { .min = 12000000, .max = 50000000 },
121 .num_output = ARRAY_SIZE(pll_outputs),
122 .output = pll_outputs,
a402c663 123 .core_output = core_outputs,
120d5d8b
CB
124};
125
de3383e9
CB
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 */
132enum sama7g5_pll_parent {
133 SAMA7G5_PLL_PARENT_MAINCK,
134 SAMA7G5_PLL_PARENT_MAIN_XTAL,
135 SAMA7G5_PLL_PARENT_FRACCK,
136};
137
a3ef91f5 138/*
cb783bbb
CB
139 * PLL clocks description
140 * @n: clock name
cb783bbb 141 * @l: clock layout
120d5d8b 142 * @c: clock characteristics
de3383e9 143 * @hw: pointer to clk_hw
cb783bbb 144 * @t: clock type
8dc4af8b 145 * @f: clock flags
de3383e9 146 * @p: clock parent
cb783bbb 147 * @eid: export index in sama7g5->chws[] array
1e229c21
CB
148 * @safe_div: intermediate divider need to be set on PRE_RATE_CHANGE
149 * notification
cb783bbb 150 */
de3383e9 151static struct sama7g5_pll {
cb783bbb 152 const char *n;
cb783bbb 153 const struct clk_pll_layout *l;
120d5d8b 154 const struct clk_pll_characteristics *c;
de3383e9 155 struct clk_hw *hw;
8dc4af8b 156 unsigned long f;
de3383e9 157 enum sama7g5_pll_parent p;
cb783bbb 158 u8 t;
cb783bbb 159 u8 eid;
1e229c21 160 u8 safe_div;
2d6e9ee7 161} sama7g5_plls[][PLL_COMPID_MAX] = {
cb783bbb 162 [PLL_ID_CPU] = {
de3383e9
CB
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 },
cb783bbb
CB
191 },
192
193 [PLL_ID_SYS] = {
de3383e9
CB
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 },
cb783bbb
CB
221 },
222
223 [PLL_ID_DDR] = {
de3383e9
CB
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 },
cb783bbb
CB
246 },
247
248 [PLL_ID_IMG] = {
de3383e9
CB
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 },
cb783bbb
CB
267 },
268
269 [PLL_ID_BAUD] = {
de3383e9
CB
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 },
cb783bbb
CB
287 },
288
289 [PLL_ID_AUDIO] = {
de3383e9
CB
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 },
cb783bbb
CB
320 },
321
322 [PLL_ID_ETH] = {
de3383e9
CB
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 },
cb783bbb
CB
341 },
342};
343
de3383e9
CB
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
a3ef91f5 347/*
cb783bbb
CB
348 * Master clock (MCK[1..4]) description
349 * @n: clock name
de3383e9
CB
350 * @ep: extra parents names array (entry formed by PLL components
351 * identifiers (see enum pll_component_id))
352 * @hw: pointer to clk_hw
5619c2dd 353 * @ep_chg_id: index in parents array that specifies the changeable
cb783bbb
CB
354 * parent
355 * @ep_count: extra parents count
356 * @ep_mux_table: mux table for extra parents
357 * @id: clock id
a5ab04af 358 * @eid: export index in sama7g5->chws[] array
cb783bbb
CB
359 * @c: true if clock is critical and cannot be disabled
360 */
de3383e9 361static struct {
cb783bbb 362 const char *n;
de3383e9
CB
363 struct {
364 int pll_id;
365 int pll_compid;
366 } ep[4];
367 struct clk_hw *hw;
cb783bbb
CB
368 int ep_chg_id;
369 u8 ep_count;
370 u8 ep_mux_table[4];
371 u8 id;
a5ab04af 372 u8 eid;
cb783bbb
CB
373 u8 c;
374} sama7g5_mckx[] = {
de3383e9 375 { .n = "mck0", }, /* Dummy entry for MCK0 to store hw in probe. */
cb783bbb
CB
376 { .n = "mck1",
377 .id = 1,
de3383e9 378 .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), },
cb783bbb
CB
379 .ep_mux_table = { 5, },
380 .ep_count = 1,
381 .ep_chg_id = INT_MIN,
a5ab04af 382 .eid = PMC_MCK1,
cb783bbb
CB
383 .c = 1, },
384
385 { .n = "mck2",
386 .id = 2,
de3383e9 387 .ep = { PLL_IDS_TO_ARR_ENTRY(DDR, DIV0), },
cb783bbb
CB
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,
de3383e9
CB
395 .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(DDR, DIV0),
396 PLL_IDS_TO_ARR_ENTRY(IMG, DIV0), },
cb783bbb
CB
397 .ep_mux_table = { 5, 6, 7, },
398 .ep_count = 3,
4011f03e 399 .ep_chg_id = 5, },
cb783bbb
CB
400
401 { .n = "mck4",
402 .id = 4,
de3383e9 403 .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), },
cb783bbb
CB
404 .ep_mux_table = { 5, },
405 .ep_count = 1,
406 .ep_chg_id = INT_MIN,
407 .c = 1, },
408};
409
a3ef91f5 410/*
cb783bbb
CB
411 * System clock description
412 * @n: clock name
cb783bbb
CB
413 * @id: clock id
414 */
415static const struct {
416 const char *n;
cb783bbb
CB
417 u8 id;
418} sama7g5_systemck[] = {
de3383e9
CB
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, },
cb783bbb
CB
427};
428
429/* Mux table for programmable clocks. */
4011f03e 430static u32 sama7g5_prog_mux_table[] = { 0, 1, 2, 5, 6, 7, 8, 9, 10, };
cb783bbb 431
de3383e9
CB
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 */
441enum 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
a3ef91f5 450/*
cb783bbb
CB
451 * Peripheral clock description
452 * @n: clock name
de3383e9 453 * @p: clock parent hw id
cb783bbb
CB
454 * @r: clock range values
455 * @id: clock id
456 * @chgp: index in parent array of the changeable parent
457 */
de3383e9 458static struct {
cb783bbb 459 const char *n;
de3383e9 460 enum sama7g5_pck_parent_hw_id p;
cb783bbb
CB
461 struct clk_range r;
462 u8 chgp;
463 u8 id;
464} sama7g5_periphck[] = {
de3383e9
CB
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, },
cb783bbb
CB
537};
538
a3ef91f5 539/*
cb783bbb
CB
540 * Generic clock description
541 * @n: clock name
de3383e9
CB
542 * @pp: PLL parents (entry formed by PLL components identifiers
543 * (see enum pll_component_id))
cb783bbb
CB
544 * @pp_mux_table: PLL parents mux table
545 * @r: clock output range
7996dfd6 546 * @pp_chg_id: id in parent array of changeable PLL parent
cb783bbb
CB
547 * @pp_count: PLL parents count
548 * @id: clock id
549 */
550static const struct {
551 const char *n;
de3383e9
CB
552 struct {
553 int pll_id;
554 int pll_compid;
555 } pp[8];
cb783bbb
CB
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, },
de3383e9
CB
565 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0),
566 PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },
cb783bbb
CB
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 },
de3383e9 574 .pp = { PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },
cb783bbb
CB
575 .pp_mux_table = { 9, },
576 .pp_count = 1,
4011f03e 577 .pp_chg_id = 3, },
cb783bbb
CB
578
579 { .n = "csi_gclk",
580 .id = 33,
581 .r = { .max = 27000000 },
de3383e9 582 .pp = { PLL_IDS_TO_ARR_ENTRY(DDR, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0), },
cb783bbb
CB
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 },
de3383e9 590 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
cb783bbb
CB
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 },
de3383e9 598 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
cb783bbb
CB
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 },
de3383e9 606 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
cb783bbb
CB
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 },
de3383e9 614 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
cb783bbb
CB
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 },
de3383e9 622 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
cb783bbb
CB
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 },
de3383e9 630 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
cb783bbb
CB
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 },
de3383e9 638 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
cb783bbb
CB
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 },
de3383e9 646 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
cb783bbb
CB
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 },
de3383e9 654 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
cb783bbb
CB
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 },
de3383e9 662 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
cb783bbb
CB
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 },
de3383e9 670 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
cb783bbb
CB
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 },
de3383e9 678 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
cb783bbb
CB
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 },
de3383e9 686 .pp = { PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },
cb783bbb
CB
687 .pp_mux_table = { 10, },
688 .pp_count = 1,
4011f03e 689 .pp_chg_id = 3, },
cb783bbb
CB
690
691 { .n = "gmac1_gclk",
692 .id = 52,
693 .r = { .max = 50000000 },
de3383e9 694 .pp = { PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },
cb783bbb
CB
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 },
de3383e9 702 .pp = { PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },
cb783bbb
CB
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 },
de3383e9 710 .pp = { PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },
cb783bbb
CB
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 },
de3383e9 718 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },
cb783bbb
CB
719 .pp_mux_table = { 5, 9, },
720 .pp_count = 2,
4011f03e 721 .pp_chg_id = 4, },
cb783bbb
CB
722
723 { .n = "i2smcc1_gclk",
724 .id = 58,
725 .r = { .max = 100000000 },
de3383e9 726 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },
cb783bbb
CB
727 .pp_mux_table = { 5, 9, },
728 .pp_count = 2,
4011f03e 729 .pp_chg_id = 4, },
cb783bbb
CB
730
731 { .n = "mcan0_gclk",
732 .id = 61,
733 .r = { .max = 200000000 },
de3383e9 734 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
cb783bbb
CB
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 },
de3383e9 742 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
cb783bbb
CB
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 },
de3383e9 750 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
cb783bbb
CB
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 },
de3383e9 758 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
cb783bbb
CB
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 },
de3383e9 766 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
cb783bbb
CB
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 },
de3383e9 774 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
cb783bbb
CB
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 },
de3383e9 782 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },
1a944729 783 .pp_mux_table = { 5, 9, },
cb783bbb
CB
784 .pp_count = 2,
785 .pp_chg_id = INT_MIN, },
786
787 { .n = "pdmc1_gclk",
788 .id = 69,
789 .r = { .max = 50000000, },
de3383e9 790 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },
1a944729 791 .pp_mux_table = { 5, 9, },
cb783bbb
CB
792 .pp_count = 2,
793 .pp_chg_id = INT_MIN, },
794
795 { .n = "pit64b0_gclk",
796 .id = 70,
797 .r = { .max = 200000000 },
de3383e9
CB
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), },
cb783bbb
CB
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 },
de3383e9
CB
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), },
cb783bbb
CB
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 },
de3383e9
CB
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), },
cb783bbb
CB
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 },
de3383e9
CB
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), },
cb783bbb
CB
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 },
de3383e9
CB
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), },
cb783bbb
CB
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 },
de3383e9
CB
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), },
cb783bbb
CB
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 },
de3383e9 858 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
cb783bbb
CB
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 },
de3383e9 866 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
cb783bbb
CB
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 },
de3383e9 874 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
cb783bbb
CB
875 .pp_mux_table = { 5, 8, },
876 .pp_count = 2,
4011f03e 877 .pp_chg_id = 4, },
cb783bbb
CB
878
879 { .n = "sdmmc1_gclk",
880 .id = 81,
881 .r = { .max = 208000000 },
de3383e9 882 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
cb783bbb
CB
883 .pp_mux_table = { 5, 8, },
884 .pp_count = 2,
4011f03e 885 .pp_chg_id = 4, },
cb783bbb
CB
886
887 { .n = "sdmmc2_gclk",
888 .id = 82,
889 .r = { .max = 208000000 },
de3383e9 890 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
cb783bbb
CB
891 .pp_mux_table = { 5, 8, },
892 .pp_count = 2,
4011f03e 893 .pp_chg_id = 4, },
cb783bbb
CB
894
895 { .n = "spdifrx_gclk",
896 .id = 84,
897 .r = { .max = 150000000 },
de3383e9 898 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },
cb783bbb
CB
899 .pp_mux_table = { 5, 9, },
900 .pp_count = 2,
4011f03e 901 .pp_chg_id = 4, },
cb783bbb
CB
902
903 { .n = "spdiftx_gclk",
904 .id = 85,
905 .r = { .max = 25000000 },
de3383e9 906 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },
cb783bbb
CB
907 .pp_mux_table = { 5, 9, },
908 .pp_count = 2,
4011f03e 909 .pp_chg_id = 4, },
cb783bbb
CB
910
911 { .n = "tcb0_ch0_gclk",
912 .id = 88,
913 .r = { .max = 200000000 },
de3383e9
CB
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), },
cb783bbb
CB
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 },
de3383e9
CB
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), },
cb783bbb
CB
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
cb783bbb
CB
942/* MCK0 characteristics. */
943static const struct clk_master_characteristics mck0_characteristics = {
0b59e619 944 .output = { .min = 32768, .max = 200000000 },
0bb4623f 945 .divisors = { 1, 2, 4, 3, 5 },
cb783bbb
CB
946 .have_div3_pres = 1,
947};
948
949/* MCK0 layout. */
950static const struct clk_master_layout mck0_layout = {
0bb4623f 951 .mask = 0x773,
cb783bbb
CB
952 .pres_shift = 4,
953 .offset = 0x28,
954};
955
956/* Programmable clock layout. */
957static 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. */
966static 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
973static void __init sama7g5_pmc_setup(struct device_node *np)
974{
de3383e9 975 const char *main_xtal_name = "main_xtal";
cb783bbb 976 struct pmc_data *sama7g5_pmc;
cb783bbb
CB
977 void **alloc_mem = NULL;
978 int alloc_mem_size = 0;
979 struct regmap *regmap;
de3383e9
CB
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];
cb783bbb
CB
984 bool bypass;
985 int i, j;
986
de3383e9
CB
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));
cb783bbb 990
de3383e9 991 if (!td_slck_hw || !md_slck_hw || !main_xtal_hw)
cb783bbb
CB
992 return;
993
cb783bbb
CB
994 regmap = device_node_to_regmap(np);
995 if (IS_ERR(regmap))
996 return;
997
a5ab04af 998 sama7g5_pmc = pmc_data_allocate(PMC_MCK1 + 1,
cb783bbb
CB
999 nck(sama7g5_systemck),
1000 nck(sama7g5_periphck),
91274497 1001 nck(sama7g5_gck), 8);
cb783bbb
CB
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
de3383e9
CB
1011 main_rc_hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000,
1012 50000000);
1013 if (IS_ERR(main_rc_hw))
cb783bbb
CB
1014 goto err_free;
1015
1016 bypass = of_property_read_bool(np, "atmel,osc-bypass");
1017
de3383e9
CB
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))
cb783bbb
CB
1023 goto err_free;
1024
de3383e9
CB
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);
cb783bbb
CB
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++) {
2d6e9ee7 1034 for (j = 0; j < PLL_COMPID_MAX; j++) {
cb783bbb
CB
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:
de3383e9
CB
1042 switch (sama7g5_plls[i][j].p) {
1043 case SAMA7G5_PLL_PARENT_MAINCK:
cb783bbb 1044 parent_hw = sama7g5_pmc->chws[PMC_MAIN];
de3383e9
CB
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 }
cb783bbb
CB
1054
1055 hw = sam9x60_clk_register_frac_pll(regmap,
1056 &pmc_pll_lock, sama7g5_plls[i][j].n,
de3383e9 1057 NULL, parent_hw, i,
120d5d8b 1058 sama7g5_plls[i][j].c,
cb783bbb 1059 sama7g5_plls[i][j].l,
8dc4af8b 1060 sama7g5_plls[i][j].f);
cb783bbb
CB
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,
de3383e9 1066 NULL, sama7g5_plls[i][0].hw, i,
120d5d8b 1067 sama7g5_plls[i][j].c,
cb783bbb 1068 sama7g5_plls[i][j].l,
1e229c21
CB
1069 sama7g5_plls[i][j].f,
1070 sama7g5_plls[i][j].safe_div);
cb783bbb
CB
1071 break;
1072
1073 default:
1074 continue;
1075 }
1076
1077 if (IS_ERR(hw))
1078 goto err_free;
1079
de3383e9 1080 sama7g5_plls[i][j].hw = hw;
cb783bbb
CB
1081 if (sama7g5_plls[i][j].eid)
1082 sama7g5_pmc->chws[sama7g5_plls[i][j].eid] = hw;
1083 }
1084 }
1085
de3383e9
CB
1086 hw = at91_clk_register_master_div(regmap, "mck0", NULL,
1087 sama7g5_plls[PLL_ID_CPU][1].hw,
7a110b91 1088 &mck0_layout, &mck0_characteristics,
7029db09 1089 &pmc_mck0_lock, CLK_GET_RATE_NOCACHE, 5);
cb783bbb
CB
1090 if (IS_ERR(hw))
1091 goto err_free;
1092
de3383e9 1093 sama7g5_mckx[PCK_PARENT_HW_MCK0].hw = sama7g5_pmc->chws[PMC_MCK] = hw;
cb783bbb 1094
de3383e9
CB
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++) {
4011f03e 1099 u8 num_parents = 3 + sama7g5_mckx[i].ep_count;
de3383e9 1100 struct clk_hw *tmp_parent_hws[8];
cb783bbb
CB
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
5bf194ad
VR
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);
de3383e9
CB
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 }
5bf194ad
VR
1117 PMC_FILL_TABLE(&parent_hws[3], tmp_parent_hws,
1118 sama7g5_mckx[i].ep_count);
cb783bbb
CB
1119
1120 hw = at91_clk_sama7g5_register_master(regmap, sama7g5_mckx[i].n,
de3383e9 1121 num_parents, NULL, parent_hws, mux_table,
cb783bbb
CB
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;
a5ab04af 1129
de3383e9 1130 sama7g5_mckx[i].hw = hw;
a5ab04af
TA
1131 if (sama7g5_mckx[i].eid)
1132 sama7g5_pmc->chws[sama7g5_mckx[i].eid] = hw;
cb783bbb
CB
1133 }
1134
de3383e9 1135 hw = at91_clk_sama7g5_register_utmi(regmap, "utmick", NULL, main_xtal_hw);
cb783bbb
CB
1136 if (IS_ERR(hw))
1137 goto err_free;
1138
1139 sama7g5_pmc->chws[PMC_UTMI] = hw;
1140
de3383e9
CB
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;
cb783bbb
CB
1150 for (i = 0; i < 8; i++) {
1151 char name[6];
1152
1153 snprintf(name, sizeof(name), "prog%d", i);
1154
de3383e9
CB
1155 hw = at91_clk_register_programmable(regmap, name, NULL, parent_hws,
1156 9, i,
cb783bbb
CB
1157 &programmable_layout,
1158 sama7g5_prog_mux_table);
1159 if (IS_ERR(hw))
1160 goto err_free;
91274497
CB
1161
1162 sama7g5_pmc->pchws[i] = hw;
cb783bbb
CB
1163 }
1164
1165 for (i = 0; i < ARRAY_SIZE(sama7g5_systemck); i++) {
1166 hw = at91_clk_register_system(regmap, sama7g5_systemck[i].n,
de3383e9 1167 NULL, sama7g5_pmc->pchws[i],
68b3b6f1 1168 sama7g5_systemck[i].id, 0);
cb783bbb
CB
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,
de3383e9
CB
1179 NULL,
1180 sama7g5_mckx[sama7g5_periphck[i].p].hw,
cb783bbb
CB
1181 sama7g5_periphck[i].id,
1182 &sama7g5_periphck[i].r,
1183 sama7g5_periphck[i].chgp ? 0 :
68b3b6f1 1184 INT_MIN, 0);
cb783bbb
CB
1185 if (IS_ERR(hw))
1186 goto err_free;
1187
1188 sama7g5_pmc->phws[sama7g5_periphck[i].id] = hw;
1189 }
1190
de3383e9
CB
1191 parent_hws[0] = md_slck_hw;
1192 parent_hws[1] = td_slck_hw;
1193 parent_hws[2] = sama7g5_pmc->chws[PMC_MAIN];
cb783bbb 1194 for (i = 0; i < ARRAY_SIZE(sama7g5_gck); i++) {
4011f03e 1195 u8 num_parents = 3 + sama7g5_gck[i].pp_count;
de3383e9 1196 struct clk_hw *tmp_parent_hws[8];
cb783bbb
CB
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
5bf194ad
VR
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);
de3383e9
CB
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 }
5bf194ad
VR
1213 PMC_FILL_TABLE(&parent_hws[3], tmp_parent_hws,
1214 sama7g5_gck[i].pp_count);
cb783bbb
CB
1215
1216 hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
1217 &sama7g5_pcr_layout,
de3383e9
CB
1218 sama7g5_gck[i].n, NULL,
1219 parent_hws, mux_table,
cb783bbb
CB
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
1235err_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
91274497 1242 kfree(sama7g5_pmc);
cb783bbb
CB
1243}
1244
1245/* Some clks are used for a clocksource */
1246CLK_OF_DECLARE(sama7g5_pmc, "microchip,sama7g5-pmc", sama7g5_pmc_setup);