Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/clk/at91/sam9x7.c
50903 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* SAM9X7 PMC code.
4
*
5
* Copyright (C) 2023 Microchip Technology Inc. and its subsidiaries
6
*
7
* Author: Varshini Rajendran <[email protected]>
8
*
9
*/
10
#include <linux/clk.h>
11
#include <linux/clk-provider.h>
12
#include <linux/mfd/syscon.h>
13
#include <linux/slab.h>
14
15
#include <dt-bindings/clock/at91.h>
16
17
#include "pmc.h"
18
19
static DEFINE_SPINLOCK(pmc_pll_lock);
20
static DEFINE_SPINLOCK(mck_lock);
21
22
/**
23
* enum pll_ids - PLL clocks identifiers
24
* @PLL_ID_PLLA: PLLA identifier
25
* @PLL_ID_UPLL: UPLL identifier
26
* @PLL_ID_AUDIO: Audio PLL identifier
27
* @PLL_ID_LVDS: LVDS PLL identifier
28
* @PLL_ID_PLLA_DIV2: PLLA DIV2 identifier
29
* @PLL_ID_MAX: Max PLL Identifier
30
*/
31
enum pll_ids {
32
PLL_ID_PLLA,
33
PLL_ID_UPLL,
34
PLL_ID_AUDIO,
35
PLL_ID_LVDS,
36
PLL_ID_PLLA_DIV2,
37
PLL_ID_MAX,
38
};
39
40
/**
41
* enum pll_type - PLL type identifiers
42
* @PLL_TYPE_FRAC: fractional PLL identifier
43
* @PLL_TYPE_DIV: divider PLL identifier
44
*/
45
enum pll_type {
46
PLL_TYPE_FRAC,
47
PLL_TYPE_DIV,
48
};
49
50
static const struct clk_master_characteristics mck_characteristics = {
51
.output = { .min = 32000000, .max = 266666667 },
52
.divisors = { 1, 2, 4, 3, 5},
53
.have_div3_pres = 1,
54
};
55
56
static const struct clk_master_layout sam9x7_master_layout = {
57
.mask = 0x373,
58
.pres_shift = 4,
59
.offset = 0x28,
60
};
61
62
/* Fractional PLL core output range. */
63
static const struct clk_range plla_core_outputs[] = {
64
{ .min = 800000000, .max = 1600000000 },
65
};
66
67
static const struct clk_range upll_core_outputs[] = {
68
{ .min = 600000000, .max = 960000000 },
69
};
70
71
static const struct clk_range lvdspll_core_outputs[] = {
72
{ .min = 600000000, .max = 1200000000 },
73
};
74
75
static const struct clk_range audiopll_core_outputs[] = {
76
{ .min = 600000000, .max = 1200000000 },
77
};
78
79
static const struct clk_range plladiv2_core_outputs[] = {
80
{ .min = 800000000, .max = 1600000000 },
81
};
82
83
/* Fractional PLL output range. */
84
static const struct clk_range plla_outputs[] = {
85
{ .min = 400000000, .max = 800000000 },
86
};
87
88
static const struct clk_range upll_outputs[] = {
89
{ .min = 300000000, .max = 480000000 },
90
};
91
92
static const struct clk_range lvdspll_outputs[] = {
93
{ .min = 175000000, .max = 550000000 },
94
};
95
96
static const struct clk_range audiopll_outputs[] = {
97
{ .min = 0, .max = 300000000 },
98
};
99
100
static const struct clk_range plladiv2_outputs[] = {
101
{ .min = 200000000, .max = 400000000 },
102
};
103
104
/* PLL characteristics. */
105
static const struct clk_pll_characteristics plla_characteristics = {
106
.input = { .min = 20000000, .max = 50000000 },
107
.num_output = ARRAY_SIZE(plla_outputs),
108
.output = plla_outputs,
109
.core_output = plla_core_outputs,
110
.acr = UL(0x00020010), /* Old ACR_DEFAULT_PLLA value */
111
};
112
113
static const struct clk_pll_characteristics upll_characteristics = {
114
.input = { .min = 20000000, .max = 50000000 },
115
.num_output = ARRAY_SIZE(upll_outputs),
116
.output = upll_outputs,
117
.core_output = upll_core_outputs,
118
.upll = true,
119
.acr = UL(0x12023010), /* fIN=[20 MHz, 32 MHz] */
120
};
121
122
static const struct clk_pll_characteristics lvdspll_characteristics = {
123
.input = { .min = 20000000, .max = 50000000 },
124
.num_output = ARRAY_SIZE(lvdspll_outputs),
125
.output = lvdspll_outputs,
126
.core_output = lvdspll_core_outputs,
127
.acr = UL(0x12023010), /* fIN=[20 MHz, 32 MHz] */
128
};
129
130
static const struct clk_pll_characteristics audiopll_characteristics = {
131
.input = { .min = 20000000, .max = 50000000 },
132
.num_output = ARRAY_SIZE(audiopll_outputs),
133
.output = audiopll_outputs,
134
.core_output = audiopll_core_outputs,
135
.acr = UL(0x12023010), /* fIN=[20 MHz, 32 MHz] */
136
};
137
138
static const struct clk_pll_characteristics plladiv2_characteristics = {
139
.input = { .min = 20000000, .max = 50000000 },
140
.num_output = ARRAY_SIZE(plladiv2_outputs),
141
.output = plladiv2_outputs,
142
.core_output = plladiv2_core_outputs,
143
.acr = UL(0x00020010), /* Old ACR_DEFAULT_PLLA value */
144
};
145
146
/* Layout for fractional PLL ID PLLA. */
147
static const struct clk_pll_layout plla_frac_layout = {
148
.mul_mask = GENMASK(31, 24),
149
.frac_mask = GENMASK(21, 0),
150
.mul_shift = 24,
151
.frac_shift = 0,
152
.div2 = 1,
153
};
154
155
/* Layout for fractional PLLs. */
156
static const struct clk_pll_layout pll_frac_layout = {
157
.mul_mask = GENMASK(31, 24),
158
.frac_mask = GENMASK(21, 0),
159
.mul_shift = 24,
160
.frac_shift = 0,
161
};
162
163
/* Layout for DIV PLLs. */
164
static const struct clk_pll_layout pll_divpmc_layout = {
165
.div_mask = GENMASK(7, 0),
166
.endiv_mask = BIT(29),
167
.div_shift = 0,
168
.endiv_shift = 29,
169
};
170
171
/* Layout for DIV PLL ID PLLADIV2. */
172
static const struct clk_pll_layout plladiv2_divpmc_layout = {
173
.div_mask = GENMASK(7, 0),
174
.endiv_mask = BIT(29),
175
.div_shift = 0,
176
.endiv_shift = 29,
177
.div2 = 1,
178
};
179
180
/* Layout for DIVIO dividers. */
181
static const struct clk_pll_layout pll_divio_layout = {
182
.div_mask = GENMASK(19, 12),
183
.endiv_mask = BIT(30),
184
.div_shift = 12,
185
.endiv_shift = 30,
186
};
187
188
/*
189
* PLL clocks description
190
* @n: clock name
191
* @p: clock parent
192
* @l: clock layout
193
* @t: clock type
194
* @c: pll characteristics
195
* @f: clock flags
196
* @eid: export index in sam9x7->chws[] array
197
*/
198
static const struct {
199
const char *n;
200
const char *p;
201
const struct clk_pll_layout *l;
202
u8 t;
203
const struct clk_pll_characteristics *c;
204
unsigned long f;
205
u8 eid;
206
} sam9x7_plls[][3] = {
207
[PLL_ID_PLLA] = {
208
{
209
.n = "plla_fracck",
210
.p = "mainck",
211
.l = &plla_frac_layout,
212
.t = PLL_TYPE_FRAC,
213
/*
214
* This feeds plla_divpmcck which feeds CPU. It should
215
* not be disabled.
216
*/
217
.f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,
218
.c = &plla_characteristics,
219
},
220
221
{
222
.n = "plla_divpmcck",
223
.p = "plla_fracck",
224
.l = &pll_divpmc_layout,
225
.t = PLL_TYPE_DIV,
226
/* This feeds CPU. It should not be disabled */
227
.f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,
228
.eid = PMC_PLLACK,
229
.c = &plla_characteristics,
230
},
231
},
232
233
[PLL_ID_UPLL] = {
234
{
235
.n = "upll_fracck",
236
.p = "main_osc",
237
.l = &pll_frac_layout,
238
.t = PLL_TYPE_FRAC,
239
.f = CLK_SET_RATE_GATE,
240
.c = &upll_characteristics,
241
},
242
243
{
244
.n = "upll_divpmcck",
245
.p = "upll_fracck",
246
.l = &pll_divpmc_layout,
247
.t = PLL_TYPE_DIV,
248
.f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
249
CLK_SET_RATE_PARENT,
250
.eid = PMC_UTMI,
251
.c = &upll_characteristics,
252
},
253
},
254
255
[PLL_ID_AUDIO] = {
256
{
257
.n = "audiopll_fracck",
258
.p = "main_osc",
259
.l = &pll_frac_layout,
260
.f = CLK_SET_RATE_GATE,
261
.c = &audiopll_characteristics,
262
.t = PLL_TYPE_FRAC,
263
},
264
265
{
266
.n = "audiopll_divpmcck",
267
.p = "audiopll_fracck",
268
.l = &pll_divpmc_layout,
269
.f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
270
CLK_SET_RATE_PARENT,
271
.c = &audiopll_characteristics,
272
.eid = PMC_AUDIOPMCPLL,
273
.t = PLL_TYPE_DIV,
274
},
275
276
{
277
.n = "audiopll_diviock",
278
.p = "audiopll_fracck",
279
.l = &pll_divio_layout,
280
.f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
281
CLK_SET_RATE_PARENT,
282
.c = &audiopll_characteristics,
283
.eid = PMC_AUDIOIOPLL,
284
.t = PLL_TYPE_DIV,
285
},
286
},
287
288
[PLL_ID_LVDS] = {
289
{
290
.n = "lvdspll_fracck",
291
.p = "main_osc",
292
.l = &pll_frac_layout,
293
.f = CLK_SET_RATE_GATE,
294
.c = &lvdspll_characteristics,
295
.t = PLL_TYPE_FRAC,
296
},
297
298
{
299
.n = "lvdspll_divpmcck",
300
.p = "lvdspll_fracck",
301
.l = &pll_divpmc_layout,
302
.f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
303
CLK_SET_RATE_PARENT,
304
.c = &lvdspll_characteristics,
305
.eid = PMC_LVDSPLL,
306
.t = PLL_TYPE_DIV,
307
},
308
},
309
310
[PLL_ID_PLLA_DIV2] = {
311
{
312
.n = "plla_div2pmcck",
313
.p = "plla_fracck",
314
.l = &plladiv2_divpmc_layout,
315
/*
316
* This may feed critical parts of the system like timers.
317
* It should not be disabled.
318
*/
319
.f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,
320
.c = &plladiv2_characteristics,
321
.eid = PMC_PLLADIV2,
322
.t = PLL_TYPE_DIV,
323
},
324
},
325
};
326
327
static const struct clk_programmable_layout sam9x7_programmable_layout = {
328
.pres_mask = 0xff,
329
.pres_shift = 8,
330
.css_mask = 0x1f,
331
.have_slck_mck = 0,
332
.is_pres_direct = 1,
333
};
334
335
static const struct clk_pcr_layout sam9x7_pcr_layout = {
336
.offset = 0x88,
337
.cmd = BIT(31),
338
.gckcss_mask = GENMASK(12, 8),
339
.pid_mask = GENMASK(6, 0),
340
};
341
342
static const struct {
343
char *n;
344
char *p;
345
u8 id;
346
unsigned long flags;
347
} sam9x7_systemck[] = {
348
/*
349
* ddrck feeds DDR controller and is enabled by bootloader thus we need
350
* to keep it enabled in case there is no Linux consumer for it.
351
*/
352
{ .n = "ddrck", .p = "masterck_div", .id = 2, .flags = CLK_IS_CRITICAL },
353
{ .n = "uhpck", .p = "usbck", .id = 6 },
354
{ .n = "pck0", .p = "prog0", .id = 8 },
355
{ .n = "pck1", .p = "prog1", .id = 9 },
356
};
357
358
/*
359
* Peripheral clocks description
360
* @n: clock name
361
* @f: clock flags
362
* @id: peripheral id
363
*/
364
static const struct {
365
char *n;
366
unsigned long f;
367
u8 id;
368
} sam9x7_periphck[] = {
369
{ .n = "pioA_clk", .id = 2, },
370
{ .n = "pioB_clk", .id = 3, },
371
{ .n = "pioC_clk", .id = 4, },
372
{ .n = "flex0_clk", .id = 5, },
373
{ .n = "flex1_clk", .id = 6, },
374
{ .n = "flex2_clk", .id = 7, },
375
{ .n = "flex3_clk", .id = 8, },
376
{ .n = "flex6_clk", .id = 9, },
377
{ .n = "flex7_clk", .id = 10, },
378
{ .n = "flex8_clk", .id = 11, },
379
{ .n = "sdmmc0_clk", .id = 12, },
380
{ .n = "flex4_clk", .id = 13, },
381
{ .n = "flex5_clk", .id = 14, },
382
{ .n = "flex9_clk", .id = 15, },
383
{ .n = "flex10_clk", .id = 16, },
384
{ .n = "tcb0_clk", .id = 17, },
385
{ .n = "pwm_clk", .id = 18, },
386
{ .n = "adc_clk", .id = 19, },
387
{ .n = "dma0_clk", .id = 20, },
388
{ .n = "uhphs_clk", .id = 22, },
389
{ .n = "udphs_clk", .id = 23, },
390
{ .n = "macb0_clk", .id = 24, },
391
{ .n = "lcd_clk", .id = 25, },
392
{ .n = "sdmmc1_clk", .id = 26, },
393
{ .n = "ssc_clk", .id = 28, },
394
{ .n = "can0_clk", .id = 29, },
395
{ .n = "can1_clk", .id = 30, },
396
{ .n = "flex11_clk", .id = 32, },
397
{ .n = "flex12_clk", .id = 33, },
398
{ .n = "i2s_clk", .id = 34, },
399
{ .n = "qspi_clk", .id = 35, },
400
{ .n = "gfx2d_clk", .id = 36, },
401
{ .n = "pit64b0_clk", .id = 37, },
402
{ .n = "trng_clk", .id = 38, },
403
{ .n = "aes_clk", .id = 39, },
404
{ .n = "tdes_clk", .id = 40, },
405
{ .n = "sha_clk", .id = 41, },
406
{ .n = "classd_clk", .id = 42, },
407
{ .n = "isi_clk", .id = 43, },
408
{ .n = "pioD_clk", .id = 44, },
409
{ .n = "tcb1_clk", .id = 45, },
410
{ .n = "dbgu_clk", .id = 47, },
411
{ .n = "pmecc_clk", .id = 48, },
412
/*
413
* mpddr_clk feeds DDR controller and is enabled by bootloader thus we
414
* need to keep it enabled in case there is no Linux consumer for it.
415
*/
416
{ .n = "mpddr_clk", .id = 49, .f = CLK_IS_CRITICAL },
417
{ .n = "csi2dc_clk", .id = 52, },
418
{ .n = "csi4l_clk", .id = 53, },
419
{ .n = "dsi4l_clk", .id = 54, },
420
{ .n = "lvdsc_clk", .id = 56, },
421
{ .n = "pit64b1_clk", .id = 58, },
422
{ .n = "puf_clk", .id = 59, },
423
{ .n = "gmactsu_clk", .id = 67, },
424
};
425
426
/*
427
* Generic clock description
428
* @n: clock name
429
* @pp: PLL parents
430
* @pp_mux_table: PLL parents mux table
431
* @r: clock output range
432
* @pp_chg_id: id in parent array of changeable PLL parent
433
* @pp_count: PLL parents count
434
* @id: clock id
435
*/
436
static const struct {
437
const char *n;
438
const char *pp[8];
439
const char pp_mux_table[8];
440
struct clk_range r;
441
int pp_chg_id;
442
u8 pp_count;
443
u8 id;
444
} sam9x7_gck[] = {
445
{
446
.n = "flex0_gclk",
447
.id = 5,
448
.pp = { "plla_div2pmcck", },
449
.pp_mux_table = { 8, },
450
.pp_count = 1,
451
.pp_chg_id = INT_MIN,
452
},
453
454
{
455
.n = "flex1_gclk",
456
.id = 6,
457
.pp = { "plla_div2pmcck", },
458
.pp_mux_table = { 8, },
459
.pp_count = 1,
460
.pp_chg_id = INT_MIN,
461
},
462
463
{
464
.n = "flex2_gclk",
465
.id = 7,
466
.pp = { "plla_div2pmcck", },
467
.pp_mux_table = { 8, },
468
.pp_count = 1,
469
.pp_chg_id = INT_MIN,
470
},
471
472
{
473
.n = "flex3_gclk",
474
.id = 8,
475
.pp = { "plla_div2pmcck", },
476
.pp_mux_table = { 8, },
477
.pp_count = 1,
478
.pp_chg_id = INT_MIN,
479
},
480
481
{
482
.n = "flex6_gclk",
483
.id = 9,
484
.pp = { "plla_div2pmcck", },
485
.pp_mux_table = { 8, },
486
.pp_count = 1,
487
.pp_chg_id = INT_MIN,
488
},
489
490
{
491
.n = "flex7_gclk",
492
.id = 10,
493
.pp = { "plla_div2pmcck", },
494
.pp_mux_table = { 8, },
495
.pp_count = 1,
496
.pp_chg_id = INT_MIN,
497
},
498
499
{
500
.n = "flex8_gclk",
501
.id = 11,
502
.pp = { "plla_div2pmcck", },
503
.pp_mux_table = { 8, },
504
.pp_count = 1,
505
.pp_chg_id = INT_MIN,
506
},
507
508
{
509
.n = "sdmmc0_gclk",
510
.id = 12,
511
.r = { .max = 105000000 },
512
.pp = { "audiopll_divpmcck", "plla_div2pmcck", },
513
.pp_mux_table = { 6, 8, },
514
.pp_count = 2,
515
.pp_chg_id = INT_MIN,
516
},
517
518
{
519
.n = "flex4_gclk",
520
.id = 13,
521
.pp = { "plla_div2pmcck", },
522
.pp_mux_table = { 8, },
523
.pp_count = 1,
524
.pp_chg_id = INT_MIN,
525
},
526
527
{
528
.n = "flex5_gclk",
529
.id = 14,
530
.pp = { "plla_div2pmcck", },
531
.pp_mux_table = { 8, },
532
.pp_count = 1,
533
.pp_chg_id = INT_MIN,
534
},
535
536
{
537
.n = "flex9_gclk",
538
.id = 15,
539
.pp = { "plla_div2pmcck", },
540
.pp_mux_table = { 8, },
541
.pp_count = 1,
542
.pp_chg_id = INT_MIN,
543
},
544
545
{
546
.n = "flex10_gclk",
547
.id = 16,
548
.pp = { "plla_div2pmcck", },
549
.pp_mux_table = { 8, },
550
.pp_count = 1,
551
.pp_chg_id = INT_MIN,
552
},
553
554
{
555
.n = "tcb0_gclk",
556
.id = 17,
557
.pp = { "audiopll_divpmcck", "plla_div2pmcck", },
558
.pp_mux_table = { 6, 8, },
559
.pp_count = 2,
560
.pp_chg_id = INT_MIN,
561
},
562
563
{
564
.n = "adc_gclk",
565
.id = 19,
566
.pp = { "upll_divpmcck", "plla_div2pmcck", },
567
.pp_mux_table = { 5, 8, },
568
.pp_count = 2,
569
.pp_chg_id = INT_MIN,
570
},
571
572
{
573
.n = "lcd_gclk",
574
.id = 25,
575
.r = { .max = 75000000 },
576
.pp = { "audiopll_divpmcck", "plla_div2pmcck", },
577
.pp_mux_table = { 6, 8, },
578
.pp_count = 2,
579
.pp_chg_id = INT_MIN,
580
},
581
582
{
583
.n = "sdmmc1_gclk",
584
.id = 26,
585
.r = { .max = 105000000 },
586
.pp = { "audiopll_divpmcck", "plla_div2pmcck", },
587
.pp_mux_table = { 6, 8, },
588
.pp_count = 2,
589
.pp_chg_id = INT_MIN,
590
},
591
592
{
593
.n = "mcan0_gclk",
594
.id = 29,
595
.r = { .max = 80000000 },
596
.pp = { "upll_divpmcck", "plla_div2pmcck", },
597
.pp_mux_table = { 5, 8, },
598
.pp_count = 2,
599
.pp_chg_id = INT_MIN,
600
},
601
602
{
603
.n = "mcan1_gclk",
604
.id = 30,
605
.r = { .max = 80000000 },
606
.pp = { "upll_divpmcck", "plla_div2pmcck", },
607
.pp_mux_table = { 5, 8, },
608
.pp_count = 2,
609
.pp_chg_id = INT_MIN,
610
},
611
612
{
613
.n = "flex11_gclk",
614
.id = 32,
615
.pp = { "plla_div2pmcck", },
616
.pp_mux_table = { 8, },
617
.pp_count = 1,
618
.pp_chg_id = INT_MIN,
619
},
620
621
{
622
.n = "flex12_gclk",
623
.id = 33,
624
.pp = { "plla_div2pmcck", },
625
.pp_mux_table = { 8, },
626
.pp_count = 1,
627
.pp_chg_id = INT_MIN,
628
},
629
630
{
631
.n = "i2s_gclk",
632
.id = 34,
633
.r = { .max = 100000000 },
634
.pp = { "audiopll_divpmcck", "plla_div2pmcck", },
635
.pp_mux_table = { 6, 8, },
636
.pp_count = 2,
637
.pp_chg_id = INT_MIN,
638
},
639
640
{
641
.n = "qspi_gclk",
642
.id = 35,
643
.r = { .max = 200000000 },
644
.pp = { "audiopll_divpmcck", "plla_div2pmcck", },
645
.pp_mux_table = { 6, 8, },
646
.pp_count = 2,
647
.pp_chg_id = INT_MIN,
648
},
649
650
{
651
.n = "pit64b0_gclk",
652
.id = 37,
653
.pp = { "plla_div2pmcck", },
654
.pp_mux_table = { 8, },
655
.pp_count = 1,
656
.pp_chg_id = INT_MIN,
657
},
658
659
{
660
.n = "classd_gclk",
661
.id = 42,
662
.r = { .max = 100000000 },
663
.pp = { "audiopll_divpmcck", "plla_div2pmcck", },
664
.pp_mux_table = { 6, 8, },
665
.pp_count = 2,
666
.pp_chg_id = INT_MIN,
667
},
668
669
{
670
.n = "tcb1_gclk",
671
.id = 45,
672
.pp = { "audiopll_divpmcck", "plla_div2pmcck", },
673
.pp_mux_table = { 6, 8, },
674
.pp_count = 2,
675
.pp_chg_id = INT_MIN,
676
},
677
678
{
679
.n = "dbgu_gclk",
680
.id = 47,
681
.pp = { "plla_div2pmcck", },
682
.pp_mux_table = { 8, },
683
.pp_count = 1,
684
.pp_chg_id = INT_MIN,
685
},
686
687
{
688
.n = "mipiphy_gclk",
689
.id = 55,
690
.r = { .max = 27000000 },
691
.pp = { "plla_div2pmcck", },
692
.pp_mux_table = { 8, },
693
.pp_count = 1,
694
.pp_chg_id = INT_MIN,
695
},
696
697
{
698
.n = "pit64b1_gclk",
699
.id = 58,
700
.pp = { "plla_div2pmcck", },
701
.pp_mux_table = { 8, },
702
.pp_count = 1,
703
.pp_chg_id = INT_MIN,
704
},
705
706
{
707
.n = "gmac_gclk",
708
.id = 67,
709
.pp = { "audiopll_divpmcck", "plla_div2pmcck", },
710
.pp_mux_table = { 6, 8, },
711
.pp_count = 2,
712
.pp_chg_id = INT_MIN,
713
},
714
};
715
716
static void __init sam9x7_pmc_setup(struct device_node *np)
717
{
718
struct clk_range range = CLK_RANGE(0, 0);
719
const char *td_slck_name, *md_slck_name, *mainxtal_name;
720
struct pmc_data *sam9x7_pmc;
721
const char *parent_names[9];
722
void **clk_mux_buffer = NULL;
723
int clk_mux_buffer_size = 0;
724
struct clk_hw *main_osc_hw;
725
struct regmap *regmap;
726
struct clk_hw *hw;
727
int i, j;
728
729
i = of_property_match_string(np, "clock-names", "td_slck");
730
if (i < 0)
731
return;
732
733
td_slck_name = of_clk_get_parent_name(np, i);
734
735
i = of_property_match_string(np, "clock-names", "md_slck");
736
if (i < 0)
737
return;
738
739
md_slck_name = of_clk_get_parent_name(np, i);
740
741
i = of_property_match_string(np, "clock-names", "main_xtal");
742
if (i < 0)
743
return;
744
mainxtal_name = of_clk_get_parent_name(np, i);
745
746
regmap = device_node_to_regmap(np);
747
if (IS_ERR(regmap))
748
return;
749
750
sam9x7_pmc = pmc_data_allocate(PMC_LVDSPLL + 1,
751
nck(sam9x7_systemck),
752
nck(sam9x7_periphck),
753
nck(sam9x7_gck), 8);
754
if (!sam9x7_pmc)
755
return;
756
757
clk_mux_buffer = kmalloc(sizeof(void *) *
758
(ARRAY_SIZE(sam9x7_gck)),
759
GFP_KERNEL);
760
if (!clk_mux_buffer)
761
goto err_free;
762
763
hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000,
764
50000000);
765
if (IS_ERR(hw))
766
goto err_free;
767
768
hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, NULL, 0);
769
if (IS_ERR(hw))
770
goto err_free;
771
main_osc_hw = hw;
772
773
parent_names[0] = "main_rc_osc";
774
parent_names[1] = "main_osc";
775
hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, NULL, 2);
776
if (IS_ERR(hw))
777
goto err_free;
778
779
sam9x7_pmc->chws[PMC_MAIN] = hw;
780
781
for (i = 0; i < PLL_ID_MAX; i++) {
782
for (j = 0; j < 3; j++) {
783
struct clk_hw *parent_hw;
784
785
if (!sam9x7_plls[i][j].n)
786
continue;
787
788
switch (sam9x7_plls[i][j].t) {
789
case PLL_TYPE_FRAC:
790
if (!strcmp(sam9x7_plls[i][j].p, "mainck"))
791
parent_hw = sam9x7_pmc->chws[PMC_MAIN];
792
else if (!strcmp(sam9x7_plls[i][j].p, "main_osc"))
793
parent_hw = main_osc_hw;
794
else
795
parent_hw = __clk_get_hw(of_clk_get_by_name
796
(np, sam9x7_plls[i][j].p));
797
798
hw = sam9x60_clk_register_frac_pll(regmap,
799
&pmc_pll_lock,
800
sam9x7_plls[i][j].n,
801
sam9x7_plls[i][j].p,
802
parent_hw, i,
803
sam9x7_plls[i][j].c,
804
sam9x7_plls[i][j].l,
805
sam9x7_plls[i][j].f);
806
break;
807
808
case PLL_TYPE_DIV:
809
hw = sam9x60_clk_register_div_pll(regmap,
810
&pmc_pll_lock,
811
sam9x7_plls[i][j].n,
812
sam9x7_plls[i][j].p, NULL, i,
813
sam9x7_plls[i][j].c,
814
sam9x7_plls[i][j].l,
815
sam9x7_plls[i][j].f, 0);
816
break;
817
818
default:
819
continue;
820
}
821
822
if (IS_ERR(hw))
823
goto err_free;
824
825
if (sam9x7_plls[i][j].eid)
826
sam9x7_pmc->chws[sam9x7_plls[i][j].eid] = hw;
827
}
828
}
829
830
parent_names[0] = md_slck_name;
831
parent_names[1] = "mainck";
832
parent_names[2] = "plla_divpmcck";
833
parent_names[3] = "upll_divpmcck";
834
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
835
parent_names, NULL, &sam9x7_master_layout,
836
&mck_characteristics, &mck_lock);
837
if (IS_ERR(hw))
838
goto err_free;
839
840
hw = at91_clk_register_master_div(regmap, "masterck_div",
841
"masterck_pres", NULL, &sam9x7_master_layout,
842
&mck_characteristics, &mck_lock,
843
CLK_SET_RATE_GATE, 0);
844
if (IS_ERR(hw))
845
goto err_free;
846
847
sam9x7_pmc->chws[PMC_MCK] = hw;
848
849
parent_names[0] = "plla_divpmcck";
850
parent_names[1] = "upll_divpmcck";
851
parent_names[2] = "main_osc";
852
hw = sam9x60_clk_register_usb(regmap, "usbck", parent_names, 3);
853
if (IS_ERR(hw))
854
goto err_free;
855
856
parent_names[0] = md_slck_name;
857
parent_names[1] = td_slck_name;
858
parent_names[2] = "mainck";
859
parent_names[3] = "masterck_div";
860
parent_names[4] = "plla_divpmcck";
861
parent_names[5] = "upll_divpmcck";
862
parent_names[6] = "audiopll_divpmcck";
863
for (i = 0; i < 2; i++) {
864
char name[6];
865
866
snprintf(name, sizeof(name), "prog%d", i);
867
868
hw = at91_clk_register_programmable(regmap, name,
869
parent_names, NULL, 7, i,
870
&sam9x7_programmable_layout,
871
NULL);
872
if (IS_ERR(hw))
873
goto err_free;
874
875
sam9x7_pmc->pchws[i] = hw;
876
}
877
878
for (i = 0; i < ARRAY_SIZE(sam9x7_systemck); i++) {
879
hw = at91_clk_register_system(regmap, sam9x7_systemck[i].n,
880
sam9x7_systemck[i].p, NULL,
881
sam9x7_systemck[i].id,
882
sam9x7_systemck[i].flags);
883
if (IS_ERR(hw))
884
goto err_free;
885
886
sam9x7_pmc->shws[sam9x7_systemck[i].id] = hw;
887
}
888
889
for (i = 0; i < ARRAY_SIZE(sam9x7_periphck); i++) {
890
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
891
&sam9x7_pcr_layout,
892
sam9x7_periphck[i].n,
893
"masterck_div", NULL,
894
sam9x7_periphck[i].id,
895
&range, INT_MIN,
896
sam9x7_periphck[i].f);
897
if (IS_ERR(hw))
898
goto err_free;
899
900
sam9x7_pmc->phws[sam9x7_periphck[i].id] = hw;
901
}
902
903
parent_names[0] = md_slck_name;
904
parent_names[1] = td_slck_name;
905
parent_names[2] = "mainck";
906
parent_names[3] = "masterck_div";
907
for (i = 0; i < ARRAY_SIZE(sam9x7_gck); i++) {
908
u8 num_parents = 4 + sam9x7_gck[i].pp_count;
909
u32 *mux_table;
910
911
mux_table = kmalloc_array(num_parents, sizeof(*mux_table),
912
GFP_KERNEL);
913
if (!mux_table)
914
goto err_free;
915
916
PMC_INIT_TABLE(mux_table, 4);
917
PMC_FILL_TABLE(&mux_table[4], sam9x7_gck[i].pp_mux_table,
918
sam9x7_gck[i].pp_count);
919
PMC_FILL_TABLE(&parent_names[4], sam9x7_gck[i].pp,
920
sam9x7_gck[i].pp_count);
921
922
hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
923
&sam9x7_pcr_layout,
924
sam9x7_gck[i].n,
925
parent_names, NULL, mux_table,
926
num_parents,
927
sam9x7_gck[i].id,
928
&sam9x7_gck[i].r,
929
sam9x7_gck[i].pp_chg_id);
930
if (IS_ERR(hw))
931
goto err_free;
932
933
sam9x7_pmc->ghws[sam9x7_gck[i].id] = hw;
934
clk_mux_buffer[clk_mux_buffer_size++] = mux_table;
935
}
936
937
of_clk_add_hw_provider(np, of_clk_hw_pmc_get, sam9x7_pmc);
938
kfree(clk_mux_buffer);
939
940
return;
941
942
err_free:
943
if (clk_mux_buffer) {
944
for (i = 0; i < clk_mux_buffer_size; i++)
945
kfree(clk_mux_buffer[i]);
946
kfree(clk_mux_buffer);
947
}
948
kfree(sam9x7_pmc);
949
}
950
951
/* Some clks are used for a clocksource */
952
CLK_OF_DECLARE(sam9x7_pmc, "microchip,sam9x7-pmc", sam9x7_pmc_setup);
953
954