1 // SPDX-License-Identifier: GPL-2.0
5 * Copyright (C) 2020 Microchip Technology Inc. and its subsidiaries
7 * Author: Claudiu Beznea <claudiu.beznea@microchip.com>
10 #include <linux/clk.h>
11 #include <linux/clk-provider.h>
12 #include <linux/mfd/syscon.h>
13 #include <linux/slab.h>
15 #include <dt-bindings/clock/at91.h>
19 static DEFINE_SPINLOCK(pmc_pll_lock
);
20 static DEFINE_SPINLOCK(pmc_mck0_lock
);
21 static DEFINE_SPINLOCK(pmc_mckX_lock
);
24 * PLL clocks identifiers
25 * @PLL_ID_CPU: CPU PLL identifier
26 * @PLL_ID_SYS: System PLL identifier
27 * @PLL_ID_DDR: DDR PLL identifier
28 * @PLL_ID_IMG: Image subsystem PLL identifier
29 * @PLL_ID_BAUD: Baud PLL identifier
30 * @PLL_ID_AUDIO: Audio PLL identifier
31 * @PLL_ID_ETH: Ethernet PLL identifier
45 * PLL component identifier
46 * @PLL_COMPID_FRAC: Fractional PLL component identifier
47 * @PLL_COMPID_DIV0: 1st PLL divider component identifier
48 * @PLL_COMPID_DIV1: 2nd PLL divider component identifier
50 enum pll_component_id
{
58 * PLL type identifiers
59 * @PLL_TYPE_FRAC: fractional PLL identifier
60 * @PLL_TYPE_DIV: divider PLL identifier
67 /* Layout for fractional PLLs. */
68 static const struct clk_pll_layout pll_layout_frac
= {
69 .mul_mask
= GENMASK(31, 24),
70 .frac_mask
= GENMASK(21, 0),
75 /* Layout for DIVPMC dividers. */
76 static const struct clk_pll_layout pll_layout_divpmc
= {
77 .div_mask
= GENMASK(7, 0),
78 .endiv_mask
= BIT(29),
83 /* Layout for DIVIO dividers. */
84 static const struct clk_pll_layout pll_layout_divio
= {
85 .div_mask
= GENMASK(19, 12),
86 .endiv_mask
= BIT(30),
92 * CPU PLL output range.
93 * Notice: The upper limit has been setup to 1000000002 due to hardware
94 * block which cannot output exactly 1GHz.
96 static const struct clk_range cpu_pll_outputs
[] = {
97 { .min
= 2343750, .max
= 1000000002 },
100 /* PLL output range. */
101 static const struct clk_range pll_outputs
[] = {
102 { .min
= 2343750, .max
= 1200000000 },
105 /* Fractional PLL core output range. */
106 static const struct clk_range core_outputs
[] = {
107 { .min
= 600000000, .max
= 1200000000 },
110 /* CPU PLL characteristics. */
111 static const struct clk_pll_characteristics cpu_pll_characteristics
= {
112 .input
= { .min
= 12000000, .max
= 50000000 },
113 .num_output
= ARRAY_SIZE(cpu_pll_outputs
),
114 .output
= cpu_pll_outputs
,
115 .core_output
= core_outputs
,
118 /* PLL characteristics. */
119 static const struct clk_pll_characteristics pll_characteristics
= {
120 .input
= { .min
= 12000000, .max
= 50000000 },
121 .num_output
= ARRAY_SIZE(pll_outputs
),
122 .output
= pll_outputs
,
123 .core_output
= core_outputs
,
127 * SAMA7G5 PLL possible parents
128 * @SAMA7G5_PLL_PARENT_MAINCK: MAINCK is PLL a parent
129 * @SAMA7G5_PLL_PARENT_MAIN_XTAL: MAIN XTAL is a PLL parent
130 * @SAMA7G5_PLL_PARENT_FRACCK: Frac PLL is a PLL parent (for PLL dividers)
132 enum sama7g5_pll_parent
{
133 SAMA7G5_PLL_PARENT_MAINCK
,
134 SAMA7G5_PLL_PARENT_MAIN_XTAL
,
135 SAMA7G5_PLL_PARENT_FRACCK
,
139 * PLL clocks description
142 * @c: clock characteristics
143 * @hw: pointer to clk_hw
147 * @eid: export index in sama7g5->chws[] array
148 * @safe_div: intermediate divider need to be set on PRE_RATE_CHANGE
151 static struct sama7g5_pll
{
153 const struct clk_pll_layout
*l
;
154 const struct clk_pll_characteristics
*c
;
157 enum sama7g5_pll_parent p
;
161 } sama7g5_plls
[][PLL_COMPID_MAX
] = {
163 [PLL_COMPID_FRAC
] = {
164 .n
= "cpupll_fracck",
165 .p
= SAMA7G5_PLL_PARENT_MAINCK
,
166 .l
= &pll_layout_frac
,
167 .c
= &cpu_pll_characteristics
,
170 * This feeds cpupll_divpmcck which feeds CPU. It should
173 .f
= CLK_IS_CRITICAL
,
176 [PLL_COMPID_DIV0
] = {
177 .n
= "cpupll_divpmcck",
178 .p
= SAMA7G5_PLL_PARENT_FRACCK
,
179 .l
= &pll_layout_divpmc
,
180 .c
= &cpu_pll_characteristics
,
182 /* This feeds CPU. It should not be disabled. */
183 .f
= CLK_IS_CRITICAL
| CLK_SET_RATE_PARENT
,
186 * Safe div=15 should be safe even for switching b/w 1GHz and
187 * 90MHz (frac pll might go up to 1.2GHz).
194 [PLL_COMPID_FRAC
] = {
195 .n
= "syspll_fracck",
196 .p
= SAMA7G5_PLL_PARENT_MAINCK
,
197 .l
= &pll_layout_frac
,
198 .c
= &pll_characteristics
,
201 * This feeds syspll_divpmcck which may feed critical parts
202 * of the systems like timers. Therefore it should not be
205 .f
= CLK_IS_CRITICAL
| CLK_SET_RATE_GATE
,
208 [PLL_COMPID_DIV0
] = {
209 .n
= "syspll_divpmcck",
210 .p
= SAMA7G5_PLL_PARENT_FRACCK
,
211 .l
= &pll_layout_divpmc
,
212 .c
= &pll_characteristics
,
215 * This may feed critical parts of the systems like timers.
216 * Therefore it should not be disabled.
218 .f
= CLK_IS_CRITICAL
| CLK_SET_RATE_GATE
,
224 [PLL_COMPID_FRAC
] = {
225 .n
= "ddrpll_fracck",
226 .p
= SAMA7G5_PLL_PARENT_MAINCK
,
227 .l
= &pll_layout_frac
,
228 .c
= &pll_characteristics
,
231 * This feeds ddrpll_divpmcck which feeds DDR. It should not
234 .f
= CLK_IS_CRITICAL
| CLK_SET_RATE_GATE
,
237 [PLL_COMPID_DIV0
] = {
238 .n
= "ddrpll_divpmcck",
239 .p
= SAMA7G5_PLL_PARENT_FRACCK
,
240 .l
= &pll_layout_divpmc
,
241 .c
= &pll_characteristics
,
243 /* This feeds DDR. It should not be disabled. */
244 .f
= CLK_IS_CRITICAL
| CLK_SET_RATE_GATE
,
249 [PLL_COMPID_FRAC
] = {
250 .n
= "imgpll_fracck",
251 .p
= SAMA7G5_PLL_PARENT_MAINCK
,
252 .l
= &pll_layout_frac
,
253 .c
= &pll_characteristics
,
255 .f
= CLK_SET_RATE_GATE
,
258 [PLL_COMPID_DIV0
] = {
259 .n
= "imgpll_divpmcck",
260 .p
= SAMA7G5_PLL_PARENT_FRACCK
,
261 .l
= &pll_layout_divpmc
,
262 .c
= &pll_characteristics
,
264 .f
= CLK_SET_RATE_GATE
| CLK_SET_PARENT_GATE
|
270 [PLL_COMPID_FRAC
] = {
271 .n
= "baudpll_fracck",
272 .p
= SAMA7G5_PLL_PARENT_MAINCK
,
273 .l
= &pll_layout_frac
,
274 .c
= &pll_characteristics
,
276 .f
= CLK_SET_RATE_GATE
, },
278 [PLL_COMPID_DIV0
] = {
279 .n
= "baudpll_divpmcck",
280 .p
= SAMA7G5_PLL_PARENT_FRACCK
,
281 .l
= &pll_layout_divpmc
,
282 .c
= &pll_characteristics
,
284 .f
= CLK_SET_RATE_GATE
| CLK_SET_PARENT_GATE
|
290 [PLL_COMPID_FRAC
] = {
291 .n
= "audiopll_fracck",
292 .p
= SAMA7G5_PLL_PARENT_MAIN_XTAL
,
293 .l
= &pll_layout_frac
,
294 .c
= &pll_characteristics
,
296 .f
= CLK_SET_RATE_GATE
,
299 [PLL_COMPID_DIV0
] = {
300 .n
= "audiopll_divpmcck",
301 .p
= SAMA7G5_PLL_PARENT_FRACCK
,
302 .l
= &pll_layout_divpmc
,
303 .c
= &pll_characteristics
,
305 .f
= CLK_SET_RATE_GATE
| CLK_SET_PARENT_GATE
|
307 .eid
= PMC_AUDIOPMCPLL
,
310 [PLL_COMPID_DIV1
] = {
311 .n
= "audiopll_diviock",
312 .p
= SAMA7G5_PLL_PARENT_FRACCK
,
313 .l
= &pll_layout_divio
,
314 .c
= &pll_characteristics
,
316 .f
= CLK_SET_RATE_GATE
| CLK_SET_PARENT_GATE
|
318 .eid
= PMC_AUDIOIOPLL
,
323 [PLL_COMPID_FRAC
] = {
324 .n
= "ethpll_fracck",
325 .p
= SAMA7G5_PLL_PARENT_MAIN_XTAL
,
326 .l
= &pll_layout_frac
,
327 .c
= &pll_characteristics
,
329 .f
= CLK_SET_RATE_GATE
,
332 [PLL_COMPID_DIV0
] = {
333 .n
= "ethpll_divpmcck",
334 .p
= SAMA7G5_PLL_PARENT_FRACCK
,
335 .l
= &pll_layout_divpmc
,
336 .c
= &pll_characteristics
,
338 .f
= CLK_SET_RATE_GATE
| CLK_SET_PARENT_GATE
|
344 /* Used to create an array entry identifying a PLL by its components. */
345 #define PLL_IDS_TO_ARR_ENTRY(_id, _comp) { PLL_ID_##_id, PLL_COMPID_##_comp}
348 * Master clock (MCK[1..4]) description
350 * @ep: extra parents names array (entry formed by PLL components
351 * identifiers (see enum pll_component_id))
352 * @hw: pointer to clk_hw
353 * @ep_chg_id: index in parents array that specifies the changeable
355 * @ep_count: extra parents count
356 * @ep_mux_table: mux table for extra parents
358 * @eid: export index in sama7g5->chws[] array
359 * @c: true if clock is critical and cannot be disabled
375 { .n
= "mck0", }, /* Dummy entry for MCK0 to store hw in probe. */
378 .ep
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), },
379 .ep_mux_table
= { 5, },
381 .ep_chg_id
= INT_MIN
,
387 .ep
= { PLL_IDS_TO_ARR_ENTRY(DDR
, DIV0
), },
388 .ep_mux_table
= { 6, },
390 .ep_chg_id
= INT_MIN
,
395 .ep
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(DDR
, DIV0
),
396 PLL_IDS_TO_ARR_ENTRY(IMG
, DIV0
), },
397 .ep_mux_table
= { 5, 6, 7, },
403 .ep
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), },
404 .ep_mux_table
= { 5, },
406 .ep_chg_id
= INT_MIN
,
411 * System clock description
415 static const struct {
418 } sama7g5_systemck
[] = {
419 { .n
= "pck0", .id
= 8, },
420 { .n
= "pck1", .id
= 9, },
421 { .n
= "pck2", .id
= 10, },
422 { .n
= "pck3", .id
= 11, },
423 { .n
= "pck4", .id
= 12, },
424 { .n
= "pck5", .id
= 13, },
425 { .n
= "pck6", .id
= 14, },
426 { .n
= "pck7", .id
= 15, },
429 /* Mux table for programmable clocks. */
430 static u32 sama7g5_prog_mux_table
[] = { 0, 1, 2, 5, 6, 7, 8, 9, 10, };
433 * Peripheral clock parent hw identifier (used to index in sama7g5_mckx[])
434 * @PCK_PARENT_HW_MCK0: pck parent hw identifier is MCK0
435 * @PCK_PARENT_HW_MCK1: pck parent hw identifier is MCK1
436 * @PCK_PARENT_HW_MCK2: pck parent hw identifier is MCK2
437 * @PCK_PARENT_HW_MCK3: pck parent hw identifier is MCK3
438 * @PCK_PARENT_HW_MCK4: pck parent hw identifier is MCK4
439 * @PCK_PARENT_HW_MAX: max identifier
441 enum sama7g5_pck_parent_hw_id
{
451 * Peripheral clock description
453 * @p: clock parent hw id
454 * @r: clock range values
456 * @chgp: index in parent array of the changeable parent
460 enum sama7g5_pck_parent_hw_id p
;
464 } sama7g5_periphck
[] = {
465 { .n
= "pioA_clk", .p
= PCK_PARENT_HW_MCK0
, .id
= 11, },
466 { .n
= "securam_clk", .p
= PCK_PARENT_HW_MCK0
, .id
= 18, },
467 { .n
= "sfr_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 19, },
468 { .n
= "hsmc_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 21, },
469 { .n
= "xdmac0_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 22, },
470 { .n
= "xdmac1_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 23, },
471 { .n
= "xdmac2_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 24, },
472 { .n
= "acc_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 25, },
473 { .n
= "aes_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 27, },
474 { .n
= "tzaesbasc_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 28, },
475 { .n
= "asrc_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 30, .r
= { .max
= 200000000, }, },
476 { .n
= "cpkcc_clk", .p
= PCK_PARENT_HW_MCK0
, .id
= 32, },
477 { .n
= "csi_clk", .p
= PCK_PARENT_HW_MCK3
, .id
= 33, .r
= { .max
= 266000000, }, .chgp
= 1, },
478 { .n
= "csi2dc_clk", .p
= PCK_PARENT_HW_MCK3
, .id
= 34, .r
= { .max
= 266000000, }, .chgp
= 1, },
479 { .n
= "eic_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 37, },
480 { .n
= "flex0_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 38, },
481 { .n
= "flex1_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 39, },
482 { .n
= "flex2_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 40, },
483 { .n
= "flex3_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 41, },
484 { .n
= "flex4_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 42, },
485 { .n
= "flex5_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 43, },
486 { .n
= "flex6_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 44, },
487 { .n
= "flex7_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 45, },
488 { .n
= "flex8_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 46, },
489 { .n
= "flex9_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 47, },
490 { .n
= "flex10_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 48, },
491 { .n
= "flex11_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 49, },
492 { .n
= "gmac0_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 51, },
493 { .n
= "gmac1_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 52, },
494 { .n
= "icm_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 55, },
495 { .n
= "isc_clk", .p
= PCK_PARENT_HW_MCK3
, .id
= 56, .r
= { .max
= 266000000, }, .chgp
= 1, },
496 { .n
= "i2smcc0_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 57, .r
= { .max
= 200000000, }, },
497 { .n
= "i2smcc1_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 58, .r
= { .max
= 200000000, }, },
498 { .n
= "matrix_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 60, },
499 { .n
= "mcan0_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 61, .r
= { .max
= 200000000, }, },
500 { .n
= "mcan1_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 62, .r
= { .max
= 200000000, }, },
501 { .n
= "mcan2_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 63, .r
= { .max
= 200000000, }, },
502 { .n
= "mcan3_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 64, .r
= { .max
= 200000000, }, },
503 { .n
= "mcan4_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 65, .r
= { .max
= 200000000, }, },
504 { .n
= "mcan5_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 66, .r
= { .max
= 200000000, }, },
505 { .n
= "pdmc0_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 68, .r
= { .max
= 200000000, }, },
506 { .n
= "pdmc1_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 69, .r
= { .max
= 200000000, }, },
507 { .n
= "pit64b0_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 70, },
508 { .n
= "pit64b1_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 71, },
509 { .n
= "pit64b2_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 72, },
510 { .n
= "pit64b3_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 73, },
511 { .n
= "pit64b4_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 74, },
512 { .n
= "pit64b5_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 75, },
513 { .n
= "pwm_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 77, },
514 { .n
= "qspi0_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 78, },
515 { .n
= "qspi1_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 79, },
516 { .n
= "sdmmc0_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 80, },
517 { .n
= "sdmmc1_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 81, },
518 { .n
= "sdmmc2_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 82, },
519 { .n
= "sha_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 83, },
520 { .n
= "spdifrx_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 84, .r
= { .max
= 200000000, }, },
521 { .n
= "spdiftx_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 85, .r
= { .max
= 200000000, }, },
522 { .n
= "ssc0_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 86, .r
= { .max
= 200000000, }, },
523 { .n
= "ssc1_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 87, .r
= { .max
= 200000000, }, },
524 { .n
= "tcb0_ch0_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 88, .r
= { .max
= 200000000, }, },
525 { .n
= "tcb0_ch1_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 89, .r
= { .max
= 200000000, }, },
526 { .n
= "tcb0_ch2_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 90, .r
= { .max
= 200000000, }, },
527 { .n
= "tcb1_ch0_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 91, .r
= { .max
= 200000000, }, },
528 { .n
= "tcb1_ch1_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 92, .r
= { .max
= 200000000, }, },
529 { .n
= "tcb1_ch2_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 93, .r
= { .max
= 200000000, }, },
530 { .n
= "tcpca_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 94, },
531 { .n
= "tcpcb_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 95, },
532 { .n
= "tdes_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 96, },
533 { .n
= "trng_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 97, },
534 { .n
= "udphsa_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 104, },
535 { .n
= "udphsb_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 105, },
536 { .n
= "uhphs_clk", .p
= PCK_PARENT_HW_MCK1
, .id
= 106, },
540 * Generic clock description
542 * @pp: PLL parents (entry formed by PLL components identifiers
543 * (see enum pll_component_id))
544 * @pp_mux_table: PLL parents mux table
545 * @r: clock output range
546 * @pp_chg_id: id in parent array of changeable PLL parent
547 * @pp_count: PLL parents count
550 static const struct {
556 const char pp_mux_table
[8];
564 .r
= { .max
= 100000000, },
565 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(IMG
, DIV0
),
566 PLL_IDS_TO_ARR_ENTRY(AUDIO
, DIV0
), },
567 .pp_mux_table
= { 5, 7, 9, },
569 .pp_chg_id
= INT_MIN
, },
573 .r
= { .max
= 200000000 },
574 .pp
= { PLL_IDS_TO_ARR_ENTRY(AUDIO
, DIV0
), },
575 .pp_mux_table
= { 9, },
581 .r
= { .max
= 27000000 },
582 .pp
= { PLL_IDS_TO_ARR_ENTRY(DDR
, DIV0
), PLL_IDS_TO_ARR_ENTRY(IMG
, DIV0
), },
583 .pp_mux_table
= { 6, 7, },
585 .pp_chg_id
= INT_MIN
, },
589 .r
= { .max
= 200000000 },
590 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), },
591 .pp_mux_table
= { 5, 8, },
593 .pp_chg_id
= INT_MIN
, },
597 .r
= { .max
= 200000000 },
598 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), },
599 .pp_mux_table
= { 5, 8, },
601 .pp_chg_id
= INT_MIN
, },
605 .r
= { .max
= 200000000 },
606 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), },
607 .pp_mux_table
= { 5, 8, },
609 .pp_chg_id
= INT_MIN
, },
613 .r
= { .max
= 200000000 },
614 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), },
615 .pp_mux_table
= { 5, 8, },
617 .pp_chg_id
= INT_MIN
, },
621 .r
= { .max
= 200000000 },
622 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), },
623 .pp_mux_table
= { 5, 8, },
625 .pp_chg_id
= INT_MIN
, },
629 .r
= { .max
= 200000000 },
630 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), },
631 .pp_mux_table
= { 5, 8, },
633 .pp_chg_id
= INT_MIN
, },
637 .r
= { .max
= 200000000 },
638 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), },
639 .pp_mux_table
= { 5, 8, },
641 .pp_chg_id
= INT_MIN
, },
645 .r
= { .max
= 200000000 },
646 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), },
647 .pp_mux_table
= { 5, 8, },
649 .pp_chg_id
= INT_MIN
, },
653 .r
= { .max
= 200000000 },
654 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), },
655 .pp_mux_table
= { 5, 8, },
657 .pp_chg_id
= INT_MIN
, },
661 .r
= { .max
= 200000000 },
662 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), },
663 .pp_mux_table
= { 5, 8, },
665 .pp_chg_id
= INT_MIN
, },
667 { .n
= "flex10_gclk",
669 .r
= { .max
= 200000000 },
670 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), },
671 .pp_mux_table
= { 5, 8, },
673 .pp_chg_id
= INT_MIN
, },
675 { .n
= "flex11_gclk",
677 .r
= { .max
= 200000000 },
678 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), },
679 .pp_mux_table
= { 5, 8, },
681 .pp_chg_id
= INT_MIN
, },
685 .r
= { .max
= 125000000 },
686 .pp
= { PLL_IDS_TO_ARR_ENTRY(ETH
, DIV0
), },
687 .pp_mux_table
= { 10, },
693 .r
= { .max
= 50000000 },
694 .pp
= { PLL_IDS_TO_ARR_ENTRY(ETH
, DIV0
), },
695 .pp_mux_table
= { 10, },
697 .pp_chg_id
= INT_MIN
, },
699 { .n
= "gmac0_tsu_gclk",
701 .r
= { .max
= 300000000 },
702 .pp
= { PLL_IDS_TO_ARR_ENTRY(AUDIO
, DIV0
), PLL_IDS_TO_ARR_ENTRY(ETH
, DIV0
), },
703 .pp_mux_table
= { 9, 10, },
705 .pp_chg_id
= INT_MIN
, },
707 { .n
= "gmac1_tsu_gclk",
709 .r
= { .max
= 300000000 },
710 .pp
= { PLL_IDS_TO_ARR_ENTRY(AUDIO
, DIV0
), PLL_IDS_TO_ARR_ENTRY(ETH
, DIV0
), },
711 .pp_mux_table
= { 9, 10, },
713 .pp_chg_id
= INT_MIN
, },
715 { .n
= "i2smcc0_gclk",
717 .r
= { .max
= 100000000 },
718 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(AUDIO
, DIV0
), },
719 .pp_mux_table
= { 5, 9, },
723 { .n
= "i2smcc1_gclk",
725 .r
= { .max
= 100000000 },
726 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(AUDIO
, DIV0
), },
727 .pp_mux_table
= { 5, 9, },
733 .r
= { .max
= 200000000 },
734 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), },
735 .pp_mux_table
= { 5, 8, },
737 .pp_chg_id
= INT_MIN
, },
741 .r
= { .max
= 200000000 },
742 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), },
743 .pp_mux_table
= { 5, 8, },
745 .pp_chg_id
= INT_MIN
, },
749 .r
= { .max
= 200000000 },
750 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), },
751 .pp_mux_table
= { 5, 8, },
753 .pp_chg_id
= INT_MIN
, },
757 .r
= { .max
= 200000000 },
758 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), },
759 .pp_mux_table
= { 5, 8, },
761 .pp_chg_id
= INT_MIN
, },
765 .r
= { .max
= 200000000 },
766 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), },
767 .pp_mux_table
= { 5, 8, },
769 .pp_chg_id
= INT_MIN
, },
773 .r
= { .max
= 200000000 },
774 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), },
775 .pp_mux_table
= { 5, 8, },
777 .pp_chg_id
= INT_MIN
, },
781 .r
= { .max
= 50000000 },
782 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(AUDIO
, DIV0
), },
783 .pp_mux_table
= { 5, 9, },
785 .pp_chg_id
= INT_MIN
, },
789 .r
= { .max
= 50000000, },
790 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(AUDIO
, DIV0
), },
791 .pp_mux_table
= { 5, 9, },
793 .pp_chg_id
= INT_MIN
, },
795 { .n
= "pit64b0_gclk",
797 .r
= { .max
= 200000000 },
798 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(IMG
, DIV0
),
799 PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), PLL_IDS_TO_ARR_ENTRY(AUDIO
, DIV0
),
800 PLL_IDS_TO_ARR_ENTRY(ETH
, DIV0
), },
801 .pp_mux_table
= { 5, 7, 8, 9, 10, },
803 .pp_chg_id
= INT_MIN
, },
805 { .n
= "pit64b1_gclk",
807 .r
= { .max
= 200000000 },
808 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(IMG
, DIV0
),
809 PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), PLL_IDS_TO_ARR_ENTRY(AUDIO
, DIV0
),
810 PLL_IDS_TO_ARR_ENTRY(ETH
, DIV0
), },
811 .pp_mux_table
= { 5, 7, 8, 9, 10, },
813 .pp_chg_id
= INT_MIN
, },
815 { .n
= "pit64b2_gclk",
817 .r
= { .max
= 200000000 },
818 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(IMG
, DIV0
),
819 PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), PLL_IDS_TO_ARR_ENTRY(AUDIO
, DIV0
),
820 PLL_IDS_TO_ARR_ENTRY(ETH
, DIV0
), },
821 .pp_mux_table
= { 5, 7, 8, 9, 10, },
823 .pp_chg_id
= INT_MIN
, },
825 { .n
= "pit64b3_gclk",
827 .r
= { .max
= 200000000 },
828 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(IMG
, DIV0
),
829 PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), PLL_IDS_TO_ARR_ENTRY(AUDIO
, DIV0
),
830 PLL_IDS_TO_ARR_ENTRY(ETH
, DIV0
), },
831 .pp_mux_table
= { 5, 7, 8, 9, 10, },
833 .pp_chg_id
= INT_MIN
, },
835 { .n
= "pit64b4_gclk",
837 .r
= { .max
= 200000000 },
838 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(IMG
, DIV0
),
839 PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), PLL_IDS_TO_ARR_ENTRY(AUDIO
, DIV0
),
840 PLL_IDS_TO_ARR_ENTRY(ETH
, DIV0
), },
841 .pp_mux_table
= { 5, 7, 8, 9, 10, },
843 .pp_chg_id
= INT_MIN
, },
845 { .n
= "pit64b5_gclk",
847 .r
= { .max
= 200000000 },
848 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(IMG
, DIV0
),
849 PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), PLL_IDS_TO_ARR_ENTRY(AUDIO
, DIV0
),
850 PLL_IDS_TO_ARR_ENTRY(ETH
, DIV0
), },
851 .pp_mux_table
= { 5, 7, 8, 9, 10, },
853 .pp_chg_id
= INT_MIN
, },
857 .r
= { .max
= 200000000 },
858 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), },
859 .pp_mux_table
= { 5, 8, },
861 .pp_chg_id
= INT_MIN
, },
865 .r
= { .max
= 200000000 },
866 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), },
867 .pp_mux_table
= { 5, 8, },
869 .pp_chg_id
= INT_MIN
, },
871 { .n
= "sdmmc0_gclk",
873 .r
= { .max
= 208000000 },
874 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), },
875 .pp_mux_table
= { 5, 8, },
879 { .n
= "sdmmc1_gclk",
881 .r
= { .max
= 208000000 },
882 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), },
883 .pp_mux_table
= { 5, 8, },
887 { .n
= "sdmmc2_gclk",
889 .r
= { .max
= 208000000 },
890 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), },
891 .pp_mux_table
= { 5, 8, },
895 { .n
= "spdifrx_gclk",
897 .r
= { .max
= 150000000 },
898 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(AUDIO
, DIV0
), },
899 .pp_mux_table
= { 5, 9, },
903 { .n
= "spdiftx_gclk",
905 .r
= { .max
= 25000000 },
906 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(AUDIO
, DIV0
), },
907 .pp_mux_table
= { 5, 9, },
911 { .n
= "tcb0_ch0_gclk",
913 .r
= { .max
= 200000000 },
914 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(IMG
, DIV0
),
915 PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), PLL_IDS_TO_ARR_ENTRY(AUDIO
, DIV0
),
916 PLL_IDS_TO_ARR_ENTRY(ETH
, DIV0
), },
917 .pp_mux_table
= { 5, 7, 8, 9, 10, },
919 .pp_chg_id
= INT_MIN
, },
921 { .n
= "tcb1_ch0_gclk",
923 .r
= { .max
= 200000000 },
924 .pp
= { PLL_IDS_TO_ARR_ENTRY(SYS
, DIV0
), PLL_IDS_TO_ARR_ENTRY(IMG
, DIV0
),
925 PLL_IDS_TO_ARR_ENTRY(BAUD
, DIV0
), PLL_IDS_TO_ARR_ENTRY(AUDIO
, DIV0
),
926 PLL_IDS_TO_ARR_ENTRY(ETH
, DIV0
), },
927 .pp_mux_table
= { 5, 7, 8, 9, 10, },
929 .pp_chg_id
= INT_MIN
, },
933 .r
= { .max
= 32768, },
934 .pp_chg_id
= INT_MIN
, },
938 .r
= { .max
= 32768, },
939 .pp_chg_id
= INT_MIN
, },
942 /* MCK0 characteristics. */
943 static const struct clk_master_characteristics mck0_characteristics
= {
944 .output
= { .min
= 32768, .max
= 200000000 },
945 .divisors
= { 1, 2, 4, 3, 5 },
950 static const struct clk_master_layout mck0_layout
= {
956 /* Programmable clock layout. */
957 static const struct clk_programmable_layout programmable_layout
= {
965 /* Peripheral clock layout. */
966 static const struct clk_pcr_layout sama7g5_pcr_layout
= {
969 .gckcss_mask
= GENMASK(12, 8),
970 .pid_mask
= GENMASK(6, 0),
973 static void __init
sama7g5_pmc_setup(struct device_node
*np
)
975 const char *main_xtal_name
= "main_xtal";
976 struct pmc_data
*sama7g5_pmc
;
977 void **alloc_mem
= NULL
;
978 int alloc_mem_size
= 0;
979 struct regmap
*regmap
;
980 struct clk_hw
*hw
, *main_rc_hw
, *main_osc_hw
, *main_xtal_hw
;
981 struct clk_hw
*td_slck_hw
, *md_slck_hw
;
982 static struct clk_parent_data parent_data
;
983 struct clk_hw
*parent_hws
[10];
987 td_slck_hw
= __clk_get_hw(of_clk_get_by_name(np
, "td_slck"));
988 md_slck_hw
= __clk_get_hw(of_clk_get_by_name(np
, "md_slck"));
989 main_xtal_hw
= __clk_get_hw(of_clk_get_by_name(np
, main_xtal_name
));
991 if (!td_slck_hw
|| !md_slck_hw
|| !main_xtal_hw
)
994 regmap
= device_node_to_regmap(np
);
998 sama7g5_pmc
= pmc_data_allocate(PMC_MCK1
+ 1,
999 nck(sama7g5_systemck
),
1000 nck(sama7g5_periphck
),
1001 nck(sama7g5_gck
), 8);
1005 alloc_mem
= kmalloc(sizeof(void *) *
1006 (ARRAY_SIZE(sama7g5_mckx
) + ARRAY_SIZE(sama7g5_gck
)),
1011 main_rc_hw
= at91_clk_register_main_rc_osc(regmap
, "main_rc_osc", 12000000,
1013 if (IS_ERR(main_rc_hw
))
1016 bypass
= of_property_read_bool(np
, "atmel,osc-bypass");
1018 parent_data
.name
= main_xtal_name
;
1019 parent_data
.fw_name
= main_xtal_name
;
1020 main_osc_hw
= at91_clk_register_main_osc(regmap
, "main_osc", NULL
,
1021 &parent_data
, bypass
);
1022 if (IS_ERR(main_osc_hw
))
1025 parent_hws
[0] = main_rc_hw
;
1026 parent_hws
[1] = main_osc_hw
;
1027 hw
= at91_clk_register_sam9x5_main(regmap
, "mainck", NULL
, parent_hws
, 2);
1031 sama7g5_pmc
->chws
[PMC_MAIN
] = hw
;
1033 for (i
= 0; i
< PLL_ID_MAX
; i
++) {
1034 for (j
= 0; j
< PLL_COMPID_MAX
; j
++) {
1035 struct clk_hw
*parent_hw
;
1037 if (!sama7g5_plls
[i
][j
].n
)
1040 switch (sama7g5_plls
[i
][j
].t
) {
1042 switch (sama7g5_plls
[i
][j
].p
) {
1043 case SAMA7G5_PLL_PARENT_MAINCK
:
1044 parent_hw
= sama7g5_pmc
->chws
[PMC_MAIN
];
1046 case SAMA7G5_PLL_PARENT_MAIN_XTAL
:
1047 parent_hw
= main_xtal_hw
;
1050 /* Should not happen. */
1055 hw
= sam9x60_clk_register_frac_pll(regmap
,
1056 &pmc_pll_lock
, sama7g5_plls
[i
][j
].n
,
1058 sama7g5_plls
[i
][j
].c
,
1059 sama7g5_plls
[i
][j
].l
,
1060 sama7g5_plls
[i
][j
].f
);
1064 hw
= sam9x60_clk_register_div_pll(regmap
,
1065 &pmc_pll_lock
, sama7g5_plls
[i
][j
].n
,
1066 NULL
, sama7g5_plls
[i
][0].hw
, i
,
1067 sama7g5_plls
[i
][j
].c
,
1068 sama7g5_plls
[i
][j
].l
,
1069 sama7g5_plls
[i
][j
].f
,
1070 sama7g5_plls
[i
][j
].safe_div
);
1080 sama7g5_plls
[i
][j
].hw
= hw
;
1081 if (sama7g5_plls
[i
][j
].eid
)
1082 sama7g5_pmc
->chws
[sama7g5_plls
[i
][j
].eid
] = hw
;
1086 hw
= at91_clk_register_master_div(regmap
, "mck0", NULL
,
1087 sama7g5_plls
[PLL_ID_CPU
][1].hw
,
1088 &mck0_layout
, &mck0_characteristics
,
1089 &pmc_mck0_lock
, CLK_GET_RATE_NOCACHE
, 5);
1093 sama7g5_mckx
[PCK_PARENT_HW_MCK0
].hw
= sama7g5_pmc
->chws
[PMC_MCK
] = hw
;
1095 parent_hws
[0] = md_slck_hw
;
1096 parent_hws
[1] = td_slck_hw
;
1097 parent_hws
[2] = sama7g5_pmc
->chws
[PMC_MAIN
];
1098 for (i
= PCK_PARENT_HW_MCK1
; i
< ARRAY_SIZE(sama7g5_mckx
); i
++) {
1099 u8 num_parents
= 3 + sama7g5_mckx
[i
].ep_count
;
1100 struct clk_hw
*tmp_parent_hws
[8];
1103 mux_table
= kmalloc_array(num_parents
, sizeof(*mux_table
),
1108 PMC_INIT_TABLE(mux_table
, 3);
1109 PMC_FILL_TABLE(&mux_table
[3], sama7g5_mckx
[i
].ep_mux_table
,
1110 sama7g5_mckx
[i
].ep_count
);
1111 for (j
= 0; j
< sama7g5_mckx
[i
].ep_count
; j
++) {
1112 u8 pll_id
= sama7g5_mckx
[i
].ep
[j
].pll_id
;
1113 u8 pll_compid
= sama7g5_mckx
[i
].ep
[j
].pll_compid
;
1115 tmp_parent_hws
[j
] = sama7g5_plls
[pll_id
][pll_compid
].hw
;
1117 PMC_FILL_TABLE(&parent_hws
[3], tmp_parent_hws
,
1118 sama7g5_mckx
[i
].ep_count
);
1120 hw
= at91_clk_sama7g5_register_master(regmap
, sama7g5_mckx
[i
].n
,
1121 num_parents
, NULL
, parent_hws
, mux_table
,
1122 &pmc_mckX_lock
, sama7g5_mckx
[i
].id
,
1124 sama7g5_mckx
[i
].ep_chg_id
);
1128 alloc_mem
[alloc_mem_size
++] = mux_table
;
1130 sama7g5_mckx
[i
].hw
= hw
;
1131 if (sama7g5_mckx
[i
].eid
)
1132 sama7g5_pmc
->chws
[sama7g5_mckx
[i
].eid
] = hw
;
1135 hw
= at91_clk_sama7g5_register_utmi(regmap
, "utmick", NULL
, main_xtal_hw
);
1139 sama7g5_pmc
->chws
[PMC_UTMI
] = hw
;
1141 parent_hws
[0] = md_slck_hw
;
1142 parent_hws
[1] = td_slck_hw
;
1143 parent_hws
[2] = sama7g5_pmc
->chws
[PMC_MAIN
];
1144 parent_hws
[3] = sama7g5_plls
[PLL_ID_SYS
][PLL_COMPID_DIV0
].hw
;
1145 parent_hws
[4] = sama7g5_plls
[PLL_ID_DDR
][PLL_COMPID_DIV0
].hw
;
1146 parent_hws
[5] = sama7g5_plls
[PLL_ID_IMG
][PLL_COMPID_DIV0
].hw
;
1147 parent_hws
[6] = sama7g5_plls
[PLL_ID_BAUD
][PLL_COMPID_DIV0
].hw
;
1148 parent_hws
[7] = sama7g5_plls
[PLL_ID_AUDIO
][PLL_COMPID_DIV0
].hw
;
1149 parent_hws
[8] = sama7g5_plls
[PLL_ID_ETH
][PLL_COMPID_DIV0
].hw
;
1150 for (i
= 0; i
< 8; i
++) {
1153 snprintf(name
, sizeof(name
), "prog%d", i
);
1155 hw
= at91_clk_register_programmable(regmap
, name
, NULL
, parent_hws
,
1157 &programmable_layout
,
1158 sama7g5_prog_mux_table
);
1162 sama7g5_pmc
->pchws
[i
] = hw
;
1165 for (i
= 0; i
< ARRAY_SIZE(sama7g5_systemck
); i
++) {
1166 hw
= at91_clk_register_system(regmap
, sama7g5_systemck
[i
].n
,
1167 NULL
, sama7g5_pmc
->pchws
[i
],
1168 sama7g5_systemck
[i
].id
, 0);
1172 sama7g5_pmc
->shws
[sama7g5_systemck
[i
].id
] = hw
;
1175 for (i
= 0; i
< ARRAY_SIZE(sama7g5_periphck
); i
++) {
1176 hw
= at91_clk_register_sam9x5_peripheral(regmap
, &pmc_pcr_lock
,
1177 &sama7g5_pcr_layout
,
1178 sama7g5_periphck
[i
].n
,
1180 sama7g5_mckx
[sama7g5_periphck
[i
].p
].hw
,
1181 sama7g5_periphck
[i
].id
,
1182 &sama7g5_periphck
[i
].r
,
1183 sama7g5_periphck
[i
].chgp
? 0 :
1188 sama7g5_pmc
->phws
[sama7g5_periphck
[i
].id
] = hw
;
1191 parent_hws
[0] = md_slck_hw
;
1192 parent_hws
[1] = td_slck_hw
;
1193 parent_hws
[2] = sama7g5_pmc
->chws
[PMC_MAIN
];
1194 for (i
= 0; i
< ARRAY_SIZE(sama7g5_gck
); i
++) {
1195 u8 num_parents
= 3 + sama7g5_gck
[i
].pp_count
;
1196 struct clk_hw
*tmp_parent_hws
[8];
1199 mux_table
= kmalloc_array(num_parents
, sizeof(*mux_table
),
1204 PMC_INIT_TABLE(mux_table
, 3);
1205 PMC_FILL_TABLE(&mux_table
[3], sama7g5_gck
[i
].pp_mux_table
,
1206 sama7g5_gck
[i
].pp_count
);
1207 for (j
= 0; j
< sama7g5_gck
[i
].pp_count
; j
++) {
1208 u8 pll_id
= sama7g5_gck
[i
].pp
[j
].pll_id
;
1209 u8 pll_compid
= sama7g5_gck
[i
].pp
[j
].pll_compid
;
1211 tmp_parent_hws
[j
] = sama7g5_plls
[pll_id
][pll_compid
].hw
;
1213 PMC_FILL_TABLE(&parent_hws
[3], tmp_parent_hws
,
1214 sama7g5_gck
[i
].pp_count
);
1216 hw
= at91_clk_register_generated(regmap
, &pmc_pcr_lock
,
1217 &sama7g5_pcr_layout
,
1218 sama7g5_gck
[i
].n
, NULL
,
1219 parent_hws
, mux_table
,
1223 sama7g5_gck
[i
].pp_chg_id
);
1227 sama7g5_pmc
->ghws
[sama7g5_gck
[i
].id
] = hw
;
1228 alloc_mem
[alloc_mem_size
++] = mux_table
;
1231 of_clk_add_hw_provider(np
, of_clk_hw_pmc_get
, sama7g5_pmc
);
1237 for (i
= 0; i
< alloc_mem_size
; i
++)
1238 kfree(alloc_mem
[i
]);
1245 /* Some clks are used for a clocksource */
1246 CLK_OF_DECLARE(sama7g5_pmc
, "microchip,sama7g5-pmc", sama7g5_pmc_setup
);