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