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

source code of linux/drivers/clk/at91/sama7g5.c