blob: 63b2c6474679282bd136017cbc8ca4075323eabc [file] [log] [blame]
Claudiu Beznea57db4c42020-09-07 17:46:52 +03001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * SAMA7G5 PMC clock support.
4 *
5 * Copyright (C) 2020 Microchip Technology Inc. and its subsidiaries
6 *
7 * Author: Claudiu Beznea <claudiu.beznea@microchip.com>
8 *
9 * Based on drivers/clk/at91/sama7g5.c from Linux.
10 */
11
Claudiu Beznea57db4c42020-09-07 17:46:52 +030012#include <clk-uclass.h>
13#include <dm.h>
14#include <dt-bindings/clk/at91.h>
15#include <linux/clk-provider.h>
16
17#include "pmc.h"
18
19/**
20 * Clock identifiers to be used in conjunction with macros like
21 * AT91_TO_CLK_ID()
22 *
23 * @ID_MD_SLCK: TD slow clock identifier
24 * @ID_TD_SLCK: MD slow clock identifier
25 * @ID_MAIN_XTAL: Main Xtal clock identifier
26 * @ID_MAIN_RC: Main RC clock identifier
27 * @ID_MAIN_RC_OSC: Main RC Oscillator clock identifier
28 * @ID_MAIN_OSC: Main Oscillator clock identifier
29 * @ID_MAINCK: MAINCK clock identifier
30 * @ID_PLL_CPU_FRAC: CPU PLL fractional clock identifier
31 * @ID_PLL_CPU_DIV: CPU PLL divider clock identifier
32 * @ID_PLL_SYS_FRAC: SYS PLL fractional clock identifier
33 * @ID_PLL_SYS_DIV: SYS PLL divider clock identifier
34 * @ID_PLL_DDR_FRAC: DDR PLL fractional clock identifier
35 * @ID_PLL_DDR_DIV: DDR PLL divider clock identifier
36 * @ID_PLL_IMG_FRAC: IMC PLL fractional clock identifier
37 * @ID_PLL_IMG_DIV: IMG PLL divider clock identifier
38 * @ID_PLL_BAUD_FRAC: Baud PLL fractional clock identifier
39 * @ID_PLL_BAUD_DIV: Baud PLL divider clock identifier
40 * @ID_PLL_AUDIO_FRAC: Audio PLL fractional clock identifier
41 * @ID_PLL_AUDIO_DIVPMC: Audio PLL PMC divider clock identifier
42 * @ID_PLL_AUDIO_DIVIO: Audio PLL IO divider clock identifier
43 * @ID_PLL_ETH_FRAC: Ethernet PLL fractional clock identifier
44 * @ID_PLL_ETH_DIV: Ethernet PLL divider clock identifier
45
Claudiu Beznea8b5bbad2021-07-16 08:43:48 +030046 * @ID_MCK0_PRES: MCK0 PRES clock identifier
47 * @ID_MCK0_DIV: MCK0 DIV clock identifier
Claudiu Beznea57db4c42020-09-07 17:46:52 +030048 * @ID_MCK1: MCK1 clock identifier
49 * @ID_MCK2: MCK2 clock identifier
50 * @ID_MCK3: MCK3 clock identifier
51 * @ID_MCK4: MCK4 clock identifier
52
53 * @ID_UTMI: UTMI clock identifier
54
55 * @ID_PROG0: Programmable 0 clock identifier
56 * @ID_PROG1: Programmable 1 clock identifier
57 * @ID_PROG2: Programmable 2 clock identifier
58 * @ID_PROG3: Programmable 3 clock identifier
59 * @ID_PROG4: Programmable 4 clock identifier
60 * @ID_PROG5: Programmable 5 clock identifier
61 * @ID_PROG6: Programmable 6 clock identifier
62 * @ID_PROG7: Programmable 7 clock identifier
63
64 * @ID_PCK0: System clock 0 clock identifier
65 * @ID_PCK1: System clock 1 clock identifier
66 * @ID_PCK2: System clock 2 clock identifier
67 * @ID_PCK3: System clock 3 clock identifier
68 * @ID_PCK4: System clock 4 clock identifier
69 * @ID_PCK5: System clock 5 clock identifier
70 * @ID_PCK6: System clock 6 clock identifier
71 * @ID_PCK7: System clock 7 clock identifier
72 */
73enum pmc_clk_ids {
74 ID_MD_SLCK = 0,
75 ID_TD_SLCK = 1,
76 ID_MAIN_XTAL = 2,
77 ID_MAIN_RC = 3,
78 ID_MAIN_RC_OSC = 4,
79 ID_MAIN_OSC = 5,
80 ID_MAINCK = 6,
81
82 ID_PLL_CPU_FRAC = 7,
83 ID_PLL_CPU_DIV = 8,
84 ID_PLL_SYS_FRAC = 9,
85 ID_PLL_SYS_DIV = 10,
86 ID_PLL_DDR_FRAC = 11,
87 ID_PLL_DDR_DIV = 12,
88 ID_PLL_IMG_FRAC = 13,
89 ID_PLL_IMG_DIV = 14,
90 ID_PLL_BAUD_FRAC = 15,
91 ID_PLL_BAUD_DIV = 16,
92 ID_PLL_AUDIO_FRAC = 17,
93 ID_PLL_AUDIO_DIVPMC = 18,
94 ID_PLL_AUDIO_DIVIO = 19,
95 ID_PLL_ETH_FRAC = 20,
96 ID_PLL_ETH_DIV = 21,
97
Claudiu Beznea8b5bbad2021-07-16 08:43:48 +030098 ID_MCK0_DIV = 22,
Claudiu Beznea57db4c42020-09-07 17:46:52 +030099 ID_MCK1 = 23,
100 ID_MCK2 = 24,
101 ID_MCK3 = 25,
102 ID_MCK4 = 26,
103
104 ID_UTMI = 27,
105
106 ID_PROG0 = 28,
107 ID_PROG1 = 29,
108 ID_PROG2 = 30,
109 ID_PROG3 = 31,
110 ID_PROG4 = 32,
111 ID_PROG5 = 33,
112 ID_PROG6 = 34,
113 ID_PROG7 = 35,
114
115 ID_PCK0 = 36,
116 ID_PCK1 = 37,
117 ID_PCK2 = 38,
118 ID_PCK3 = 39,
119 ID_PCK4 = 40,
120 ID_PCK5 = 41,
121 ID_PCK6 = 42,
122 ID_PCK7 = 43,
123
Claudiu Beznea8b5bbad2021-07-16 08:43:48 +0300124 ID_MCK0_PRES = 44,
125
Claudiu Beznea57db4c42020-09-07 17:46:52 +0300126 ID_MAX,
127};
128
129/**
130 * PLL type identifiers
131 * @PLL_TYPE_FRAC: fractional PLL identifier
132 * @PLL_TYPE_DIV: divider PLL identifier
133 */
134enum pll_type {
135 PLL_TYPE_FRAC,
136 PLL_TYPE_DIV,
137};
138
139/* Clock names used as parents for multiple clocks. */
140static const char *clk_names[] = {
141 [ID_MAIN_RC_OSC] = "main_rc_osc",
142 [ID_MAIN_OSC] = "main_osc",
143 [ID_MAINCK] = "mainck",
144 [ID_PLL_CPU_DIV] = "cpupll_divpmcck",
145 [ID_PLL_SYS_DIV] = "syspll_divpmcck",
146 [ID_PLL_DDR_DIV] = "ddrpll_divpmcck",
147 [ID_PLL_IMG_DIV] = "imgpll_divpmcck",
148 [ID_PLL_BAUD_DIV] = "baudpll_divpmcck",
149 [ID_PLL_AUDIO_DIVPMC] = "audiopll_divpmcck",
150 [ID_PLL_AUDIO_DIVIO] = "audiopll_diviock",
151 [ID_PLL_ETH_DIV] = "ethpll_divpmcck",
Claudiu Beznea8b5bbad2021-07-16 08:43:48 +0300152 [ID_MCK0_DIV] = "mck0_div",
153 [ID_MCK0_PRES] = "mck0_pres",
Claudiu Beznea57db4c42020-09-07 17:46:52 +0300154};
155
156/* Fractional PLL output range. */
157static const struct clk_range pll_outputs[] = {
158 { .min = 2343750, .max = 1200000000 },
159};
160
161/* PLL characteristics. */
162static const struct clk_pll_characteristics pll_characteristics = {
163 .input = { .min = 12000000, .max = 50000000 },
164 .num_output = ARRAY_SIZE(pll_outputs),
165 .output = pll_outputs,
166};
167
168/* Layout for fractional PLLs. */
169static const struct clk_pll_layout pll_layout_frac = {
170 .mul_mask = GENMASK(31, 24),
171 .frac_mask = GENMASK(21, 0),
172 .mul_shift = 24,
173 .frac_shift = 0,
174};
175
176/* Layout for DIVPMC dividers. */
177static const struct clk_pll_layout pll_layout_divpmc = {
178 .div_mask = GENMASK(7, 0),
179 .endiv_mask = BIT(29),
180 .div_shift = 0,
181 .endiv_shift = 29,
182};
183
184/* Layout for DIVIO dividers. */
185static const struct clk_pll_layout pll_layout_divio = {
186 .div_mask = GENMASK(19, 12),
187 .endiv_mask = BIT(30),
188 .div_shift = 12,
189 .endiv_shift = 30,
190};
191
192/* MCK0 characteristics. */
193static const struct clk_master_characteristics mck0_characteristics = {
194 .output = { .min = 140000000, .max = 200000000 },
Eugen Hristev4eea0882020-07-01 10:44:21 +0300195 .divisors = { 1, 2, 4, 3, 5 },
Claudiu Beznea57db4c42020-09-07 17:46:52 +0300196 .have_div3_pres = 1,
197};
198
199/* MCK0 layout. */
200static const struct clk_master_layout mck0_layout = {
Eugen Hristev4eea0882020-07-01 10:44:21 +0300201 .mask = 0x773,
Claudiu Beznea57db4c42020-09-07 17:46:52 +0300202 .pres_shift = 4,
203 .offset = 0x28,
204};
205
206/* Programmable clock layout. */
207static const struct clk_programmable_layout programmable_layout = {
208 .pres_mask = 0xff,
209 .pres_shift = 8,
210 .css_mask = 0x1f,
211 .have_slck_mck = 0,
212 .is_pres_direct = 1,
213};
214
215/* Peripheral clock layout. */
216static const struct clk_pcr_layout sama7g5_pcr_layout = {
217 .offset = 0x88,
218 .cmd = BIT(31),
219 .gckcss_mask = GENMASK(12, 8),
220 .pid_mask = GENMASK(6, 0),
221 .div_mask = GENMASK(15, 14),
222};
223
224/**
225 * PLL clocks description
226 * @n: clock name
227 * @p: clock parent
228 * @l: clock layout
229 * @t: clock type
230 * @c: true if clock is critical and cannot be disabled
231 * @id: clock id corresponding to PLL driver
232 * @cid: clock id corresponding to clock subsystem
233 */
234static const struct {
235 const char *n;
236 const char *p;
237 const struct clk_pll_layout *l;
238 u8 t;
239 u8 c;
240 u8 id;
241 u8 cid;
242} sama7g5_plls[] = {
243 {
244 .n = "cpupll_fracck",
245 .p = "mainck",
246 .l = &pll_layout_frac,
247 .t = PLL_TYPE_FRAC,
248 .c = 1,
249 .id = 0,
250 .cid = ID_PLL_CPU_FRAC,
251 },
252
253 {
254 .n = "cpupll_divpmcck",
255 .p = "cpupll_fracck",
256 .l = &pll_layout_divpmc,
257 .t = PLL_TYPE_DIV,
258 .c = 1,
259 .id = 0,
260 .cid = ID_PLL_CPU_DIV,
261 },
262
263 {
264 .n = "syspll_fracck",
265 .p = "mainck",
266 .l = &pll_layout_frac,
267 .t = PLL_TYPE_FRAC,
268 .c = 1,
269 .id = 1,
270 .cid = ID_PLL_SYS_FRAC,
271 },
272
273 {
274 .n = "syspll_divpmcck",
275 .p = "syspll_fracck",
276 .l = &pll_layout_divpmc,
277 .t = PLL_TYPE_DIV,
278 .c = 1,
279 .id = 1,
280 .cid = ID_PLL_SYS_DIV,
281 },
282
283 {
284 .n = "ddrpll_fracck",
285 .p = "mainck",
286 .l = &pll_layout_frac,
287 .t = PLL_TYPE_FRAC,
288 .c = 1,
289 .id = 2,
290 .cid = ID_PLL_DDR_FRAC,
291 },
292
293 {
294 .n = "ddrpll_divpmcck",
295 .p = "ddrpll_fracck",
296 .l = &pll_layout_divpmc,
297 .t = PLL_TYPE_DIV,
298 .c = 1,
299 .id = 2,
300 .cid = ID_PLL_DDR_DIV,
301 },
302
303 {
304 .n = "imgpll_fracck",
305 .p = "mainck",
306 .l = &pll_layout_frac,
307 .t = PLL_TYPE_FRAC,
308 .id = 3,
309 .cid = ID_PLL_IMG_FRAC,
310 },
311
312 {
313 .n = "imgpll_divpmcck",
314 .p = "imgpll_fracck",
315 .l = &pll_layout_divpmc,
316 .t = PLL_TYPE_DIV,
317 .id = 3,
318 .cid = ID_PLL_IMG_DIV
319 },
320
321 {
322 .n = "baudpll_fracck",
323 .p = "mainck",
324 .l = &pll_layout_frac,
325 .t = PLL_TYPE_FRAC,
326 .id = 4,
327 .cid = ID_PLL_BAUD_FRAC,
328 },
329
330 {
331 .n = "baudpll_divpmcck",
332 .p = "baudpll_fracck",
333 .l = &pll_layout_divpmc,
334 .t = PLL_TYPE_DIV,
335 .id = 4,
336 .cid = ID_PLL_BAUD_DIV,
337 },
338
339 {
340 .n = "audiopll_fracck",
341 .p = "main_osc",
342 .l = &pll_layout_frac,
343 .t = PLL_TYPE_FRAC,
344 .id = 5,
345 .cid = ID_PLL_AUDIO_FRAC,
346 },
347
348 {
349 .n = "audiopll_divpmcck",
350 .p = "audiopll_fracck",
351 .l = &pll_layout_divpmc,
352 .t = PLL_TYPE_DIV,
353 .id = 5,
354 .cid = ID_PLL_AUDIO_DIVPMC,
355 },
356
357 {
358 .n = "audiopll_diviock",
359 .p = "audiopll_fracck",
360 .l = &pll_layout_divio,
361 .t = PLL_TYPE_DIV,
362 .id = 5,
363 .cid = ID_PLL_AUDIO_DIVIO,
364 },
365
366 {
367 .n = "ethpll_fracck",
368 .p = "main_osc",
369 .l = &pll_layout_frac,
370 .t = PLL_TYPE_FRAC,
371 .id = 6,
372 .cid = ID_PLL_ETH_FRAC,
373 },
374
375 {
376 .n = "ethpll_divpmcck",
377 .p = "ethpll_fracck",
378 .l = &pll_layout_divpmc,
379 .t = PLL_TYPE_DIV,
380 .id = 6,
381 .cid = ID_PLL_ETH_DIV,
382 },
383};
384
385/**
386 * Master clock (MCK[1..4]) description
387 * @n: clock name
388 * @ep: extra parents names array
389 * @ep_chg_chg_id: index in parents array that specifies the changeable
390 * parent
391 * @ep_count: extra parents count
392 * @ep_mux_table: mux table for extra parents
393 * @ep_clk_mux_table: mux table to deal with subsystem clock ids
394 * @id: clock id corresponding to MCK driver
395 * @cid: clock id corresponding to clock subsystem
396 * @c: true if clock is critical and cannot be disabled
397 */
398static const struct {
399 const char *n;
400 const char *ep[4];
401 u8 ep_count;
402 u8 ep_mux_table[4];
403 u8 ep_clk_mux_table[4];
404 u8 id;
405 u8 cid;
406 u8 c;
407} sama7g5_mckx[] = {
408 {
409 .n = "mck1",
410 .id = 1,
411 .cid = ID_MCK1,
412 .ep = { "syspll_divpmcck", },
413 .ep_mux_table = { 5, },
414 .ep_clk_mux_table = { ID_PLL_SYS_DIV, },
415 .ep_count = 1,
416 .c = 1,
417 },
418
419 {
420 .n = "mck2",
421 .id = 2,
422 .cid = ID_MCK2,
423 .ep = { "ddrpll_divpmcck", },
424 .ep_mux_table = { 6, },
425 .ep_clk_mux_table = { ID_PLL_DDR_DIV, },
426 .ep_count = 1,
427 .c = 1,
428 },
429
430 {
431 .n = "mck3",
432 .id = 3,
433 .cid = ID_MCK3,
434 .ep = { "syspll_divpmcck", "ddrpll_divpmcck", "imgpll_divpmcck", },
435 .ep_mux_table = { 5, 6, 7, },
436 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_DDR_DIV, ID_PLL_IMG_DIV, },
437 .ep_count = 3,
438 },
439
440 {
441 .n = "mck4",
442 .id = 4,
443 .cid = ID_MCK4,
444 .ep = { "syspll_divpmcck", },
445 .ep_mux_table = { 5, },
446 .ep_clk_mux_table = { ID_PLL_SYS_DIV, },
447 .ep_count = 1,
448 .c = 1,
449 },
450};
451
452/**
453 * Programmable clock description
454 * @n: clock name
455 * @cid: clock id corresponding to clock subsystem
456 */
457static const struct {
458 const char *n;
459 u8 cid;
460} sama7g5_prog[] = {
461 { .n = "prog0", .cid = ID_PROG0, },
462 { .n = "prog1", .cid = ID_PROG1, },
463 { .n = "prog2", .cid = ID_PROG2, },
464 { .n = "prog3", .cid = ID_PROG3, },
465 { .n = "prog4", .cid = ID_PROG4, },
466 { .n = "prog5", .cid = ID_PROG5, },
467 { .n = "prog6", .cid = ID_PROG6, },
468 { .n = "prog7", .cid = ID_PROG7, },
469};
470
471/* Mux table for programmable clocks. */
472static u32 sama7g5_prog_mux_table[] = { 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, };
473
474/**
475 * System clock description
476 * @n: clock name
477 * @p: parent clock name
478 * @id: clock id corresponding to system clock driver
479 * @cid: clock id corresponding to clock subsystem
480 */
481static const struct {
482 const char *n;
483 const char *p;
484 u8 id;
485 u8 cid;
486} sama7g5_systemck[] = {
487 { .n = "pck0", .p = "prog0", .id = 8, .cid = ID_PCK0, },
488 { .n = "pck1", .p = "prog1", .id = 9, .cid = ID_PCK1, },
489 { .n = "pck2", .p = "prog2", .id = 10, .cid = ID_PCK2, },
490 { .n = "pck3", .p = "prog3", .id = 11, .cid = ID_PCK3, },
491 { .n = "pck4", .p = "prog4", .id = 12, .cid = ID_PCK4, },
492 { .n = "pck5", .p = "prog5", .id = 13, .cid = ID_PCK5, },
493 { .n = "pck6", .p = "prog6", .id = 14, .cid = ID_PCK6, },
494 { .n = "pck7", .p = "prog7", .id = 15, .cid = ID_PCK7, },
495};
496
497/**
498 * Peripheral clock description
499 * @n: clock name
500 * @p: clock parent name
501 * @r: clock range values
502 * @id: clock id
503 */
504static const struct {
505 const char *n;
506 const char *p;
507 struct clk_range r;
508 u8 id;
509} sama7g5_periphck[] = {
Claudiu Beznea8b5bbad2021-07-16 08:43:48 +0300510 { .n = "pioA_clk", .p = "mck0_div", .id = 11, },
Claudiu Beznea57db4c42020-09-07 17:46:52 +0300511 { .n = "sfr_clk", .p = "mck1", .id = 19, },
512 { .n = "hsmc_clk", .p = "mck1", .id = 21, },
513 { .n = "xdmac0_clk", .p = "mck1", .id = 22, },
514 { .n = "xdmac1_clk", .p = "mck1", .id = 23, },
515 { .n = "xdmac2_clk", .p = "mck1", .id = 24, },
516 { .n = "acc_clk", .p = "mck1", .id = 25, },
517 { .n = "aes_clk", .p = "mck1", .id = 27, },
518 { .n = "tzaesbasc_clk", .p = "mck1", .id = 28, },
519 { .n = "asrc_clk", .p = "mck1", .id = 30, .r = { .max = 200000000, }, },
Claudiu Beznea8b5bbad2021-07-16 08:43:48 +0300520 { .n = "cpkcc_clk", .p = "mck0_div", .id = 32, },
Claudiu Beznea57db4c42020-09-07 17:46:52 +0300521 { .n = "csi_clk", .p = "mck3", .id = 33, .r = { .max = 266000000, }, },
522 { .n = "csi2dc_clk", .p = "mck3", .id = 34, .r = { .max = 266000000, }, },
523 { .n = "eic_clk", .p = "mck1", .id = 37, },
524 { .n = "flex0_clk", .p = "mck1", .id = 38, },
525 { .n = "flex1_clk", .p = "mck1", .id = 39, },
526 { .n = "flex2_clk", .p = "mck1", .id = 40, },
527 { .n = "flex3_clk", .p = "mck1", .id = 41, },
528 { .n = "flex4_clk", .p = "mck1", .id = 42, },
529 { .n = "flex5_clk", .p = "mck1", .id = 43, },
530 { .n = "flex6_clk", .p = "mck1", .id = 44, },
531 { .n = "flex7_clk", .p = "mck1", .id = 45, },
532 { .n = "flex8_clk", .p = "mck1", .id = 46, },
533 { .n = "flex9_clk", .p = "mck1", .id = 47, },
534 { .n = "flex10_clk", .p = "mck1", .id = 48, },
535 { .n = "flex11_clk", .p = "mck1", .id = 49, },
536 { .n = "gmac0_clk", .p = "mck1", .id = 51, },
537 { .n = "gmac1_clk", .p = "mck1", .id = 52, },
538 { .n = "gmac0_tsu_clk", .p = "mck1", .id = 53, },
539 { .n = "gmac1_tsu_clk", .p = "mck1", .id = 54, },
540 { .n = "icm_clk", .p = "mck1", .id = 55, },
541 { .n = "isc_clk", .p = "mck3", .id = 56, .r = { .max = 266000000, }, },
542 { .n = "i2smcc0_clk", .p = "mck1", .id = 57, .r = { .max = 200000000, }, },
543 { .n = "i2smcc1_clk", .p = "mck1", .id = 58, .r = { .max = 200000000, }, },
544 { .n = "matrix_clk", .p = "mck1", .id = 60, },
545 { .n = "mcan0_clk", .p = "mck1", .id = 61, .r = { .max = 200000000, }, },
546 { .n = "mcan1_clk", .p = "mck1", .id = 62, .r = { .max = 200000000, }, },
547 { .n = "mcan2_clk", .p = "mck1", .id = 63, .r = { .max = 200000000, }, },
548 { .n = "mcan3_clk", .p = "mck1", .id = 64, .r = { .max = 200000000, }, },
549 { .n = "mcan4_clk", .p = "mck1", .id = 65, .r = { .max = 200000000, }, },
550 { .n = "mcan5_clk", .p = "mck1", .id = 66, .r = { .max = 200000000, }, },
551 { .n = "pdmc0_clk", .p = "mck1", .id = 68, .r = { .max = 200000000, }, },
552 { .n = "pdmc1_clk", .p = "mck1", .id = 69, .r = { .max = 200000000, }, },
553 { .n = "pit64b0_clk", .p = "mck1", .id = 70, },
554 { .n = "pit64b1_clk", .p = "mck1", .id = 71, },
555 { .n = "pit64b2_clk", .p = "mck1", .id = 72, },
556 { .n = "pit64b3_clk", .p = "mck1", .id = 73, },
557 { .n = "pit64b4_clk", .p = "mck1", .id = 74, },
558 { .n = "pit64b5_clk", .p = "mck1", .id = 75, },
559 { .n = "pwm_clk", .p = "mck1", .id = 77, },
560 { .n = "qspi0_clk", .p = "mck1", .id = 78, },
561 { .n = "qspi1_clk", .p = "mck1", .id = 79, },
562 { .n = "sdmmc0_clk", .p = "mck1", .id = 80, },
563 { .n = "sdmmc1_clk", .p = "mck1", .id = 81, },
564 { .n = "sdmmc2_clk", .p = "mck1", .id = 82, },
565 { .n = "sha_clk", .p = "mck1", .id = 83, },
566 { .n = "spdifrx_clk", .p = "mck1", .id = 84, .r = { .max = 200000000, }, },
567 { .n = "spdiftx_clk", .p = "mck1", .id = 85, .r = { .max = 200000000, }, },
568 { .n = "ssc0_clk", .p = "mck1", .id = 86, .r = { .max = 200000000, }, },
569 { .n = "ssc1_clk", .p = "mck1", .id = 87, .r = { .max = 200000000, }, },
570 { .n = "tcb0_ch0_clk", .p = "mck1", .id = 88, .r = { .max = 200000000, }, },
571 { .n = "tcb0_ch1_clk", .p = "mck1", .id = 89, .r = { .max = 200000000, }, },
572 { .n = "tcb0_ch2_clk", .p = "mck1", .id = 90, .r = { .max = 200000000, }, },
573 { .n = "tcb1_ch0_clk", .p = "mck1", .id = 91, .r = { .max = 200000000, }, },
574 { .n = "tcb1_ch1_clk", .p = "mck1", .id = 92, .r = { .max = 200000000, }, },
575 { .n = "tcb1_ch2_clk", .p = "mck1", .id = 93, .r = { .max = 200000000, }, },
576 { .n = "tcpca_clk", .p = "mck1", .id = 94, },
577 { .n = "tcpcb_clk", .p = "mck1", .id = 95, },
578 { .n = "tdes_clk", .p = "mck1", .id = 96, },
579 { .n = "trng_clk", .p = "mck1", .id = 97, },
580 { .n = "udphsa_clk", .p = "mck1", .id = 104, },
581 { .n = "udphsb_clk", .p = "mck1", .id = 105, },
582 { .n = "uhphs_clk", .p = "mck1", .id = 106, },
583};
584
585/**
586 * Generic clock description
587 * @n: clock name
588 * @ep: extra parents names
589 * @ep_mux_table: extra parents mux table
590 * @ep_clk_mux_table: extra parents clock mux table (for CCF)
591 * @r: clock output range
592 * @ep_count: extra parents count
593 * @id: clock id
594 */
595static const struct {
596 const char *n;
597 const char *ep[8];
598 const char ep_mux_table[8];
599 const char ep_clk_mux_table[8];
600 struct clk_range r;
601 u8 ep_count;
602 u8 id;
603} sama7g5_gck[] = {
604 {
605 .n = "adc_gclk",
606 .id = 26,
607 .r = { .max = 100000000, },
608 .ep = { "syspll_divpmcck", "imgpll_divpmcck", "audiopll_divpmcck", },
609 .ep_mux_table = { 5, 7, 9, },
610 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_IMG_DIV,
611 ID_PLL_AUDIO_DIVPMC, },
612 .ep_count = 3,
613 },
614
615 {
616 .n = "asrc_gclk",
617 .id = 30,
618 .r = { .max = 200000000 },
619 .ep = { "audiopll_divpmcck", },
620 .ep_mux_table = { 9, },
621 .ep_clk_mux_table = { ID_PLL_AUDIO_DIVPMC, },
622 .ep_count = 1,
623 },
624
625 {
626 .n = "csi_gclk",
627 .id = 33,
628 .r = { .max = 27000000 },
629 .ep = { "ddrpll_divpmcck", "imgpll_divpmcck", },
630 .ep_clk_mux_table = { ID_PLL_DDR_DIV, ID_PLL_IMG_DIV, },
631 .ep_mux_table = { 6, 7, },
632 .ep_count = 2,
633 },
634
635 {
636 .n = "flex0_gclk",
637 .id = 38,
638 .r = { .max = 200000000 },
639 .ep = { "syspll_divpmcck", "baudpll_divpmcck", },
640 .ep_mux_table = { 5, 8, },
641 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_BAUD_DIV, },
642 .ep_count = 2,
643 },
644
645 {
646 .n = "flex1_gclk",
647 .id = 39,
648 .r = { .max = 200000000 },
649 .ep = { "syspll_divpmcck", "baudpll_divpmcck", },
650 .ep_mux_table = { 5, 8, },
651 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_BAUD_DIV, },
652 .ep_count = 2,
653 },
654
655 {
656 .n = "flex2_gclk",
657 .id = 40,
658 .r = { .max = 200000000 },
659 .ep = { "syspll_divpmcck", "baudpll_divpmcck", },
660 .ep_mux_table = { 5, 8, },
661 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_BAUD_DIV, },
662 .ep_count = 2,
663 },
664
665 {
666 .n = "flex3_gclk",
667 .id = 41,
668 .r = { .max = 200000000 },
669 .ep = { "syspll_divpmcck", "baudpll_divpmcck", },
670 .ep_mux_table = { 5, 8, },
671 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_BAUD_DIV, },
672 .ep_count = 2,
673 },
674
675 {
676 .n = "flex4_gclk",
677 .id = 42,
678 .r = { .max = 200000000 },
679 .ep = { "syspll_divpmcck", "baudpll_divpmcck", },
680 .ep_mux_table = { 5, 8, },
681 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_BAUD_DIV, },
682 .ep_count = 2,
683 },
684
685 {
686 .n = "flex5_gclk",
687 .id = 43,
688 .r = { .max = 200000000 },
689 .ep = { "syspll_divpmcck", "baudpll_divpmcck", },
690 .ep_mux_table = { 5, 8, },
691 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_BAUD_DIV, },
692 .ep_count = 2,
693 },
694
695 {
696 .n = "flex6_gclk",
697 .id = 44,
698 .r = { .max = 200000000 },
699 .ep = { "syspll_divpmcck", "baudpll_divpmcck", },
700 .ep_mux_table = { 5, 8, },
701 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_BAUD_DIV, },
702 .ep_count = 2,
703 },
704
705 {
706 .n = "flex7_gclk",
707 .id = 45,
708 .r = { .max = 200000000 },
709 .ep = { "syspll_divpmcck", "baudpll_divpmcck", },
710 .ep_mux_table = { 5, 8, },
711 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_BAUD_DIV, },
712 .ep_count = 2,
713 },
714
715 {
716 .n = "flex8_gclk",
717 .id = 46,
718 .r = { .max = 200000000 },
719 .ep = { "syspll_divpmcck", "baudpll_divpmcck", },
720 .ep_mux_table = { 5, 8, },
721 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_BAUD_DIV, },
722 .ep_count = 2,
723 },
724
725 {
726 .n = "flex9_gclk",
727 .id = 47,
728 .r = { .max = 200000000 },
729 .ep = { "syspll_divpmcck", "baudpll_divpmcck", },
730 .ep_mux_table = { 5, 8, },
731 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_BAUD_DIV, },
732 .ep_count = 2,
733 },
734
735 {
736 .n = "flex10_gclk",
737 .id = 48,
738 .r = { .max = 200000000 },
739 .ep = { "syspll_divpmcck", "baudpll_divpmcck", },
740 .ep_mux_table = { 5, 8, },
741 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_BAUD_DIV, },
742 .ep_count = 2,
743 },
744
745 {
746 .n = "flex11_gclk",
747 .id = 49,
748 .r = { .max = 200000000 },
749 .ep = { "syspll_divpmcck", "baudpll_divpmcck", },
750 .ep_mux_table = { 5, 8, },
751 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_BAUD_DIV, },
752 .ep_count = 2,
753 },
754
755 {
756 .n = "gmac0_gclk",
757 .id = 51,
758 .r = { .max = 125000000 },
759 .ep = { "ethpll_divpmcck", },
760 .ep_clk_mux_table = { ID_PLL_ETH_DIV, },
761 .ep_mux_table = { 10, },
762 .ep_count = 1,
763 },
764
765 {
766 .n = "gmac1_gclk",
767 .id = 52,
768 .r = { .max = 50000000 },
769 .ep = { "ethpll_divpmcck", },
770 .ep_mux_table = { 10, },
771 .ep_clk_mux_table = { ID_PLL_ETH_DIV, },
772 .ep_count = 1,
773 },
774
775 {
776 .n = "gmac0_tsu_gclk",
777 .id = 53,
778 .r = { .max = 300000000 },
779 .ep = { "audiopll_divpmcck", "ethpll_divpmcck", },
780 .ep_mux_table = { 9, 10, },
781 .ep_clk_mux_table = { ID_PLL_AUDIO_DIVPMC, ID_PLL_ETH_DIV, },
782 .ep_count = 2,
783 },
784
785 {
786 .n = "gmac1_tsu_gclk",
787 .id = 54,
788 .r = { .max = 300000000 },
789 .ep = { "audiopll_divpmcck", "ethpll_divpmcck", },
790 .ep_mux_table = { 9, 10, },
791 .ep_clk_mux_table = { ID_PLL_AUDIO_DIVPMC, ID_PLL_ETH_DIV, },
792 .ep_count = 2,
793 },
794
795 {
796 .n = "i2smcc0_gclk",
797 .id = 57,
798 .r = { .max = 100000000 },
799 .ep = { "syspll_divpmcck", "audiopll_divpmcck", },
800 .ep_mux_table = { 5, 9, },
801 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_AUDIO_DIVPMC, },
802 .ep_count = 2,
803 },
804
805 {
806 .n = "i2smcc1_gclk",
807 .id = 58,
808 .r = { .max = 100000000 },
809 .ep = { "syspll_divpmcck", "audiopll_divpmcck", },
810 .ep_mux_table = { 5, 9, },
811 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_AUDIO_DIVPMC, },
812 .ep_count = 2,
813 },
814
815 {
816 .n = "mcan0_gclk",
817 .id = 61,
818 .r = { .max = 200000000 },
819 .ep = { "syspll_divpmcck", "baudpll_divpmcck", },
820 .ep_mux_table = { 5, 8, },
821 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_BAUD_DIV, },
822 .ep_count = 2,
823 },
824
825 {
826 .n = "mcan1_gclk",
827 .id = 62,
828 .r = { .max = 200000000 },
829 .ep = { "syspll_divpmcck", "baudpll_divpmcck", },
830 .ep_mux_table = { 5, 8, },
831 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_BAUD_DIV, },
832 .ep_count = 2,
833 },
834
835 {
836 .n = "mcan2_gclk",
837 .id = 63,
838 .r = { .max = 200000000 },
839 .ep = { "syspll_divpmcck", "baudpll_divpmcck", },
840 .ep_mux_table = { 5, 8, },
841 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_BAUD_DIV, },
842 .ep_count = 2,
843 },
844
845 {
846 .n = "mcan3_gclk",
847 .id = 64,
848 .r = { .max = 200000000 },
849 .ep = { "syspll_divpmcck", "baudpll_divpmcck", },
850 .ep_mux_table = { 5, 8, },
851 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_BAUD_DIV, },
852 .ep_count = 2,
853 },
854
855 {
856 .n = "mcan4_gclk",
857 .id = 65,
858 .r = { .max = 200000000 },
859 .ep = { "syspll_divpmcck", "baudpll_divpmcck", },
860 .ep_mux_table = { 5, 8, },
861 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_BAUD_DIV, },
862 .ep_count = 2,
863 },
864
865 {
866 .n = "mcan5_gclk",
867 .id = 66,
868 .r = { .max = 200000000 },
869 .ep = { "syspll_divpmcck", "baudpll_divpmcck", },
870 .ep_mux_table = { 5, 8, },
871 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_BAUD_DIV, },
872 .ep_count = 2,
873 },
874
875 {
876 .n = "pdmc0_gclk",
877 .id = 68,
878 .r = { .max = 50000000 },
879 .ep = { "syspll_divpmcck", "baudpll_divpmcck", },
880 .ep_mux_table = { 5, 8, },
881 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_BAUD_DIV, },
882 .ep_count = 2,
883 },
884
885 {
886 .n = "pdmc1_gclk",
887 .id = 69,
888 .r = { .max = 50000000, },
889 .ep = { "syspll_divpmcck", "baudpll_divpmcck", },
890 .ep_mux_table = { 5, 8, },
891 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_BAUD_DIV, },
892 .ep_count = 2,
893 },
894
895 {
896 .n = "pit64b0_gclk",
897 .id = 70,
898 .r = { .max = 200000000 },
899 .ep = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
900 "audiopll_divpmcck", "ethpll_divpmcck", },
901 .ep_mux_table = { 5, 7, 8, 9, 10, },
902 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_IMG_DIV,
903 ID_PLL_BAUD_DIV, ID_PLL_AUDIO_DIVPMC,
904 ID_PLL_ETH_DIV, },
905 .ep_count = 5,
906 },
907
908 {
909 .n = "pit64b1_gclk",
910 .id = 71,
911 .r = { .max = 200000000 },
912 .ep = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
913 "audiopll_divpmcck", "ethpll_divpmcck", },
914 .ep_mux_table = { 5, 7, 8, 9, 10, },
915 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_IMG_DIV,
916 ID_PLL_BAUD_DIV, ID_PLL_AUDIO_DIVPMC,
917 ID_PLL_ETH_DIV, },
918 .ep_count = 5,
919 },
920
921 {
922 .n = "pit64b2_gclk",
923 .id = 72,
924 .r = { .max = 200000000 },
925 .ep = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
926 "audiopll_divpmcck", "ethpll_divpmcck", },
927 .ep_mux_table = { 5, 7, 8, 9, 10, },
928 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_IMG_DIV,
929 ID_PLL_BAUD_DIV, ID_PLL_AUDIO_DIVPMC,
930 ID_PLL_ETH_DIV, },
931 .ep_count = 5,
932 },
933
934 {
935 .n = "pit64b3_gclk",
936 .id = 73,
937 .r = { .max = 200000000 },
938 .ep = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
939 "audiopll_divpmcck", "ethpll_divpmcck", },
940 .ep_mux_table = { 5, 7, 8, 9, 10, },
941 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_IMG_DIV,
942 ID_PLL_BAUD_DIV, ID_PLL_AUDIO_DIVPMC,
943 ID_PLL_ETH_DIV, },
944 .ep_count = 5,
945 },
946
947 {
948 .n = "pit64b4_gclk",
949 .id = 74,
950 .r = { .max = 200000000 },
951 .ep = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
952 "audiopll_divpmcck", "ethpll_divpmcck", },
953 .ep_mux_table = { 5, 7, 8, 9, 10, },
954 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_IMG_DIV,
955 ID_PLL_BAUD_DIV, ID_PLL_AUDIO_DIVPMC,
956 ID_PLL_ETH_DIV, },
957 .ep_count = 5,
958 },
959
960 {
961 .n = "pit64b5_gclk",
962 .id = 75,
963 .r = { .max = 200000000 },
964 .ep = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
965 "audiopll_divpmcck", "ethpll_divpmcck", },
966 .ep_mux_table = { 5, 7, 8, 9, 10, },
967 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_IMG_DIV,
968 ID_PLL_BAUD_DIV, ID_PLL_AUDIO_DIVPMC,
969 ID_PLL_ETH_DIV, },
970 .ep_count = 5,
971 },
972
973 {
974 .n = "qspi0_gclk",
975 .id = 78,
976 .r = { .max = 200000000 },
977 .ep = { "syspll_divpmcck", "baudpll_divpmcck", },
978 .ep_mux_table = { 5, 8, },
979 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_IMG_DIV,
980 ID_PLL_BAUD_DIV, ID_PLL_AUDIO_DIVPMC,
981 ID_PLL_ETH_DIV, },
982 .ep_count = 2,
983 },
984
985 {
986 .n = "qspi1_gclk",
987 .id = 79,
988 .r = { .max = 200000000 },
989 .ep = { "syspll_divpmcck", "baudpll_divpmcck", },
990 .ep_mux_table = { 5, 8, },
991 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_BAUD_DIV, },
992 .ep_count = 2,
993 },
994
995 {
996 .n = "sdmmc0_gclk",
997 .id = 80,
998 .r = { .max = 208000000 },
999 .ep = { "syspll_divpmcck", "baudpll_divpmcck", },
1000 .ep_mux_table = { 5, 8, },
1001 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_BAUD_DIV, },
1002 .ep_count = 2,
1003 },
1004
1005 {
1006 .n = "sdmmc1_gclk",
1007 .id = 81,
1008 .r = { .max = 208000000 },
1009 .ep = { "syspll_divpmcck", "baudpll_divpmcck", },
1010 .ep_mux_table = { 5, 8, },
1011 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_BAUD_DIV, },
1012 .ep_count = 2,
1013 },
1014
1015 {
1016 .n = "sdmmc2_gclk",
1017 .id = 82,
1018 .r = { .max = 208000000 },
1019 .ep = { "syspll_divpmcck", "baudpll_divpmcck", },
1020 .ep_mux_table = { 5, 8, },
1021 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_BAUD_DIV, },
1022 .ep_count = 2,
1023 },
1024
1025 {
1026 .n = "spdifrx_gclk",
1027 .id = 84,
1028 .r = { .max = 150000000 },
1029 .ep = { "syspll_divpmcck", "audiopll_divpmcck", },
1030 .ep_mux_table = { 5, 9, },
1031 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_AUDIO_DIVPMC, },
1032 .ep_count = 2,
1033 },
1034
1035 {
1036 .n = "spdiftx_gclk",
1037 .id = 85,
1038 .r = { .max = 25000000 },
1039 .ep = { "syspll_divpmcck", "audiopll_divpmcck", },
1040 .ep_mux_table = { 5, 9, },
1041 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_AUDIO_DIVPMC, },
1042 .ep_count = 2,
1043 },
1044
1045 {
1046 .n = "tcb0_ch0_gclk",
1047 .id = 88,
1048 .r = { .max = 200000000 },
1049 .ep = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
1050 "audiopll_divpmcck", "ethpll_divpmcck", },
1051 .ep_mux_table = { 5, 7, 8, 9, 10, },
1052 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_IMG_DIV,
1053 ID_PLL_BAUD_DIV, ID_PLL_AUDIO_DIVPMC,
1054 ID_PLL_ETH_DIV, },
1055 .ep_count = 5,
1056 },
1057
1058 {
1059 .n = "tcb1_ch0_gclk",
1060 .id = 91,
1061 .r = { .max = 200000000 },
1062 .ep = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
1063 "audiopll_divpmcck", "ethpll_divpmcck", },
1064 .ep_mux_table = { 5, 7, 8, 9, 10, },
1065 .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_IMG_DIV,
1066 ID_PLL_BAUD_DIV, ID_PLL_AUDIO_DIVPMC,
1067 ID_PLL_ETH_DIV, },
1068 .ep_count = 5,
1069 },
1070};
1071
Claudiu Bezneac32688f2023-03-08 16:39:52 +02001072/* Clock setup description */
1073static const struct pmc_clk_setup sama7g5_clk_setup[] = {
Claudiu Beznea57db4c42020-09-07 17:46:52 +03001074 {
1075 .cid = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_ETH_FRAC),
1076 .rate = 625000000,
1077 },
1078
1079 {
1080 .cid = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_ETH_DIV),
1081 .rate = 625000000,
1082 },
1083};
1084
1085#define SAMA7G5_MAX_MUX_ALLOCS (64)
1086
1087#define prepare_mux_table(_allocs, _index, _dst, _src, _num, _label) \
1088 do { \
1089 int _i; \
1090 if ((_index) >= SAMA7G5_MAX_MUX_ALLOCS) { \
1091 debug("%s(): AT91: MUX: insufficient space\n", \
1092 __func__); \
1093 goto _label; \
1094 } \
1095 (_dst) = kzalloc(sizeof(*(_dst)) * (_num), GFP_KERNEL); \
1096 if (!(_dst)) \
1097 goto _label; \
1098 (_allocs)[(_index)++] = (_dst); \
1099 for (_i = 0; _i < (_num); _i++) \
1100 (_dst)[_i] = (_src)[_i]; \
1101 } while (0)
1102
1103static int sama7g5_clk_probe(struct udevice *dev)
1104{
Johan Jonker2f9f7752023-03-13 01:32:44 +01001105 void __iomem *base = devfdt_get_addr_ptr(dev);
Claudiu Beznea57db4c42020-09-07 17:46:52 +03001106 unsigned int *clkmuxallocs[SAMA7G5_MAX_MUX_ALLOCS];
1107 unsigned int *muxallocs[SAMA7G5_MAX_MUX_ALLOCS];
1108 const char *p[10];
1109 unsigned int cm[10], m[10], *tmpclkmux, *tmpmux;
Claudiu Bezneac32688f2023-03-08 16:39:52 +02001110 struct clk clk, *c;
Claudiu Beznea57db4c42020-09-07 17:46:52 +03001111 bool main_osc_bypass;
1112 int ret, muxallocindex = 0, clkmuxallocindex = 0, i, j;
1113
1114 if (IS_ERR(base))
1115 return PTR_ERR(base);
1116
Francois Berder14f9b112023-09-24 11:58:54 +02001117 memset(muxallocs, 0, sizeof(muxallocs));
1118 memset(clkmuxallocs, 0, sizeof(clkmuxallocs));
Claudiu Beznea57db4c42020-09-07 17:46:52 +03001119
1120 ret = clk_get_by_index(dev, 0, &clk);
1121 if (ret)
1122 return ret;
1123 ret = clk_get_by_id(clk.id, &c);
1124 if (ret)
1125 return ret;
1126 clk_names[ID_TD_SLCK] = kmemdup(clk_hw_get_name(c),
1127 strlen(clk_hw_get_name(c)) + 1, GFP_KERNEL);
1128 if (!clk_names[ID_TD_SLCK])
1129 return -ENOMEM;
1130
1131 ret = clk_get_by_index(dev, 1, &clk);
1132 if (ret)
1133 return ret;
1134 ret = clk_get_by_id(clk.id, &c);
1135 if (ret)
1136 return ret;
1137 clk_names[ID_MD_SLCK] = kmemdup(clk_hw_get_name(c),
1138 strlen(clk_hw_get_name(c)) + 1, GFP_KERNEL);
1139 if (!clk_names[ID_MD_SLCK])
1140 return -ENOMEM;
1141
1142 ret = clk_get_by_index(dev, 2, &clk);
1143 if (ret)
1144 return ret;
1145 clk_names[ID_MAIN_XTAL] = kmemdup(clk_hw_get_name(&clk),
1146 strlen(clk_hw_get_name(&clk)) + 1, GFP_KERNEL);
1147 if (!clk_names[ID_MAIN_XTAL])
1148 return -ENOMEM;
1149
1150 ret = clk_get_by_index(dev, 3, &clk);
1151 if (ret)
1152 goto fail;
1153 clk_names[ID_MAIN_RC] = kmemdup(clk_hw_get_name(&clk),
1154 strlen(clk_hw_get_name(&clk)) + 1, GFP_KERNEL);
1155 if (ret)
1156 goto fail;
1157
1158 main_osc_bypass = dev_read_bool(dev, "atmel,main-osc-bypass");
1159
1160 /* Register main rc oscillator. */
1161 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAIN_RC_OSC),
1162 at91_clk_main_rc(base, clk_names[ID_MAIN_RC_OSC],
1163 clk_names[ID_MAIN_RC]));
1164
1165 /* Register main oscillator. */
1166 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAIN_OSC),
1167 at91_clk_main_osc(base, clk_names[ID_MAIN_OSC],
1168 clk_names[ID_MAIN_XTAL], main_osc_bypass));
1169
1170 /* Register mainck. */
1171 p[0] = clk_names[ID_MAIN_RC_OSC];
1172 p[1] = clk_names[ID_MAIN_OSC];
1173 cm[0] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAIN_RC_OSC);
1174 cm[1] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAIN_OSC);
1175 prepare_mux_table(clkmuxallocs, clkmuxallocindex, tmpclkmux, cm, 2,
1176 fail);
1177 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAINCK),
1178 at91_clk_sam9x5_main(base, clk_names[ID_MAINCK], p,
1179 2, tmpclkmux, PMC_TYPE_CORE));
1180
1181 /* Register PLL fracs clocks. */
1182 for (i = 0; i < ARRAY_SIZE(sama7g5_plls); i++) {
1183 if (sama7g5_plls[i].t != PLL_TYPE_FRAC)
1184 continue;
1185
1186 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, sama7g5_plls[i].cid),
1187 sam9x60_clk_register_frac_pll(base, sama7g5_plls[i].n,
1188 sama7g5_plls[i].p, sama7g5_plls[i].id,
1189 &pll_characteristics, sama7g5_plls[i].l,
1190 sama7g5_plls[i].c));
1191 }
1192
1193 /* Register PLL div clocks. */
1194 for (i = 0; i < ARRAY_SIZE(sama7g5_plls); i++) {
1195 if (sama7g5_plls[i].t != PLL_TYPE_DIV)
1196 continue;
1197
1198 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, sama7g5_plls[i].cid),
1199 sam9x60_clk_register_div_pll(base, sama7g5_plls[i].n,
1200 sama7g5_plls[i].p, sama7g5_plls[i].id,
1201 &pll_characteristics, sama7g5_plls[i].l,
1202 sama7g5_plls[i].c));
1203 }
1204
Claudiu Beznea8b5bbad2021-07-16 08:43:48 +03001205 /* Register MCK0_PRES clock. */
Claudiu Beznea57db4c42020-09-07 17:46:52 +03001206 p[0] = clk_names[ID_MD_SLCK];
1207 p[1] = clk_names[ID_MAINCK];
1208 p[2] = clk_names[ID_PLL_CPU_DIV];
1209 p[3] = clk_names[ID_PLL_SYS_DIV];
1210 cm[0] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MD_SLCK);
1211 cm[1] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAINCK);
1212 cm[2] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_CPU_DIV);
1213 cm[3] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_SYS_DIV);
1214 prepare_mux_table(clkmuxallocs, clkmuxallocindex, tmpclkmux, cm, 2,
1215 fail);
Claudiu Beznea8b5bbad2021-07-16 08:43:48 +03001216 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MCK0_PRES),
1217 at91_clk_register_master_pres(base, clk_names[ID_MCK0_PRES], p,
Claudiu Beznea57db4c42020-09-07 17:46:52 +03001218 4, &mck0_layout, &mck0_characteristics, tmpclkmux));
1219
Claudiu Beznea8b5bbad2021-07-16 08:43:48 +03001220 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MCK0_DIV),
1221 at91_clk_register_master_div(base, clk_names[ID_MCK0_DIV],
1222 clk_names[ID_MCK0_PRES], &mck0_layout, &mck0_characteristics));
1223
Claudiu Beznea57db4c42020-09-07 17:46:52 +03001224 /* Register MCK1-4 clocks. */
1225 p[0] = clk_names[ID_MD_SLCK];
1226 p[1] = clk_names[ID_TD_SLCK];
1227 p[2] = clk_names[ID_MAINCK];
Claudiu Beznea8b5bbad2021-07-16 08:43:48 +03001228 p[3] = clk_names[ID_MCK0_DIV];
Claudiu Beznea57db4c42020-09-07 17:46:52 +03001229 m[0] = 0;
1230 m[1] = 1;
1231 m[2] = 2;
1232 m[3] = 3;
1233 cm[0] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MD_SLCK);
1234 cm[1] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_TD_SLCK);
1235 cm[2] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAINCK);
Claudiu Beznea8b5bbad2021-07-16 08:43:48 +03001236 cm[3] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MCK0_DIV);
Claudiu Beznea57db4c42020-09-07 17:46:52 +03001237 for (i = 0; i < ARRAY_SIZE(sama7g5_mckx); i++) {
1238 for (j = 0; j < sama7g5_mckx[i].ep_count; j++) {
1239 p[4 + j] = sama7g5_mckx[i].ep[j];
1240 m[4 + j] = sama7g5_mckx[i].ep_mux_table[j];
1241 cm[4 + j] = AT91_TO_CLK_ID(PMC_TYPE_CORE,
1242 sama7g5_mckx[i].ep_clk_mux_table[j]);
1243 }
1244
1245 prepare_mux_table(clkmuxallocs, clkmuxallocindex, tmpclkmux, cm,
1246 4 + sama7g5_mckx[i].ep_count, fail);
1247 prepare_mux_table(muxallocs, muxallocindex, tmpmux, m,
1248 4 + sama7g5_mckx[i].ep_count, fail);
1249
1250 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, sama7g5_mckx[i].cid),
1251 at91_clk_sama7g5_register_master(base,
1252 sama7g5_mckx[i].n, p, 4 + sama7g5_mckx[i].ep_count,
1253 tmpmux, tmpclkmux, sama7g5_mckx[i].c,
1254 sama7g5_mckx[i].id));
1255 }
1256
1257 /* Register UTMI clock. */
1258 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_UTMI),
1259 at91_clk_sama7g5_register_utmi(base, "utmick",
1260 clk_names[ID_MAIN_XTAL]));
1261
1262 /* Register programmable clocks. */
1263 p[0] = clk_names[ID_MD_SLCK];
1264 p[1] = clk_names[ID_TD_SLCK];
1265 p[2] = clk_names[ID_MAINCK];
Claudiu Beznea8b5bbad2021-07-16 08:43:48 +03001266 p[3] = clk_names[ID_MCK0_DIV];
Claudiu Beznea57db4c42020-09-07 17:46:52 +03001267 p[4] = clk_names[ID_PLL_SYS_DIV];
1268 p[5] = clk_names[ID_PLL_DDR_DIV];
1269 p[6] = clk_names[ID_PLL_IMG_DIV];
1270 p[7] = clk_names[ID_PLL_BAUD_DIV];
1271 p[8] = clk_names[ID_PLL_AUDIO_DIVPMC];
1272 p[9] = clk_names[ID_PLL_ETH_DIV];
1273 cm[0] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MD_SLCK);
1274 cm[1] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_TD_SLCK);
1275 cm[2] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAINCK);
Claudiu Beznea8b5bbad2021-07-16 08:43:48 +03001276 cm[3] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MCK0_DIV);
Claudiu Beznea57db4c42020-09-07 17:46:52 +03001277 cm[4] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_SYS_DIV);
1278 cm[5] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_DDR_DIV);
1279 cm[6] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_IMG_DIV);
1280 cm[7] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_BAUD_DIV);
1281 cm[8] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_AUDIO_DIVPMC);
1282 cm[9] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_ETH_DIV);
1283 for (i = 0; i < ARRAY_SIZE(sama7g5_prog); i++) {
1284 prepare_mux_table(clkmuxallocs, clkmuxallocindex, tmpclkmux, cm,
1285 10, fail);
1286
1287 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, sama7g5_prog[i].cid),
1288 at91_clk_register_programmable(base, sama7g5_prog[i].n,
1289 p, 10, i, &programmable_layout, tmpclkmux,
1290 sama7g5_prog_mux_table));
1291 }
1292
1293 /* System clocks. */
1294 for (i = 0; i < ARRAY_SIZE(sama7g5_systemck); i++) {
1295 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_SYSTEM, sama7g5_systemck[i].cid),
1296 at91_clk_register_system(base, sama7g5_systemck[i].n,
1297 sama7g5_systemck[i].p, sama7g5_systemck[i].id));
1298 }
1299
1300 /* Peripheral clocks. */
1301 for (i = 0; i < ARRAY_SIZE(sama7g5_periphck); i++) {
1302 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_PERIPHERAL,
1303 sama7g5_periphck[i].id),
1304 at91_clk_register_sam9x5_peripheral(base,
1305 &sama7g5_pcr_layout, sama7g5_periphck[i].n,
1306 sama7g5_periphck[i].p, sama7g5_periphck[i].id,
1307 &sama7g5_periphck[i].r));
1308 }
1309
1310 /* Generic clocks. */
1311 p[0] = clk_names[ID_MD_SLCK];
1312 p[1] = clk_names[ID_TD_SLCK];
1313 p[2] = clk_names[ID_MAINCK];
Claudiu Beznea8b5bbad2021-07-16 08:43:48 +03001314 p[3] = clk_names[ID_MCK0_DIV];
Claudiu Beznea57db4c42020-09-07 17:46:52 +03001315 m[0] = 0;
1316 m[1] = 1;
1317 m[2] = 2;
1318 m[3] = 3;
1319 cm[0] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MD_SLCK);
1320 cm[1] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_TD_SLCK);
1321 cm[2] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAINCK);
Claudiu Beznea8b5bbad2021-07-16 08:43:48 +03001322 cm[3] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MCK0_DIV);
Claudiu Beznea57db4c42020-09-07 17:46:52 +03001323 for (i = 0; i < ARRAY_SIZE(sama7g5_gck); i++) {
1324 for (j = 0; j < sama7g5_gck[i].ep_count; j++) {
1325 p[4 + j] = sama7g5_gck[i].ep[j];
1326 m[4 + j] = sama7g5_gck[i].ep_mux_table[j];
1327 cm[4 + j] = AT91_TO_CLK_ID(PMC_TYPE_CORE,
1328 sama7g5_gck[i].ep_clk_mux_table[j]);
1329 }
1330
1331 prepare_mux_table(clkmuxallocs, clkmuxallocindex, tmpclkmux, cm,
1332 4 + sama7g5_gck[i].ep_count, fail);
1333 prepare_mux_table(muxallocs, muxallocindex, tmpmux, m,
1334 4 + sama7g5_gck[i].ep_count, fail);
1335
1336 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_GCK, sama7g5_gck[i].id),
1337 at91_clk_register_generic(base, &sama7g5_pcr_layout,
1338 sama7g5_gck[i].n, p, tmpclkmux, tmpmux,
1339 4 + sama7g5_gck[i].ep_count, sama7g5_gck[i].id,
1340 &sama7g5_gck[i].r));
1341 }
1342
1343 /* Setup clocks. */
Claudiu Bezneac32688f2023-03-08 16:39:52 +02001344 ret = at91_clk_setup(sama7g5_clk_setup, ARRAY_SIZE(sama7g5_clk_setup));
1345 if (ret)
1346 goto fail;
Claudiu Beznea57db4c42020-09-07 17:46:52 +03001347
1348 return 0;
1349
1350fail:
1351 for (i = 0; i < ARRAY_SIZE(muxallocs); i++)
1352 kfree(muxallocs[i]);
1353
1354 for (i = 0; i < ARRAY_SIZE(clkmuxallocs); i++)
1355 kfree(clkmuxallocs[i]);
1356
1357 return -ENOMEM;
1358}
1359
1360static const struct udevice_id sama7g5_clk_ids[] = {
1361 { .compatible = "microchip,sama7g5-pmc" },
1362 { /* Sentinel. */ },
1363};
1364
1365U_BOOT_DRIVER(at91_sama7g5_pmc) = {
1366 .name = "at91-sama7g5-pmc",
1367 .id = UCLASS_CLK,
1368 .of_match = sama7g5_clk_ids,
1369 .ops = &at91_clk_ops,
1370 .probe = sama7g5_clk_probe,
1371 .flags = DM_FLAG_PRE_RELOC,
1372};