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