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