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