blob: c3235f565d7ed8f681474bb167263fd503b6c6b9 [file] [log] [blame]
Claudiu Bezneabaf5b522020-10-07 18:17:08 +03001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2020 Microchip Technology Inc. and its subsidiaries
4 *
5 * Author: Claudiu Beznea <claudiu.beznea@microchip.com>
6 *
7 * Based on sam9x60.c on Linux.
8 */
9
10#include <common.h>
11#include <clk-uclass.h>
12#include <dm.h>
13#include <dt-bindings/clk/at91.h>
14#include <linux/clk-provider.h>
15
16#include "pmc.h"
17
18/**
19 * Clock identifiers to be used in conjunction with macros like
20 * AT91_TO_CLK_ID()
21 *
22 * @ID_MD_SLCK: TD slow clock identifier
23 * @ID_TD_SLCK: MD slow clock identifier
24 * @ID_MAIN_XTAL: Main Xtal clock identifier
25 * @ID_MAIN_RC: Main RC clock identifier
26 * @ID_MAIN_RC_OSC: Main RC Oscillator clock identifier
27 * @ID_MAIN_OSC: Main Oscillator clock identifier
28 * @ID_MAINCK: MAINCK clock identifier
29 * @ID_PLL_U_FRAC: UPLL fractional clock identifier
30 * @ID_PLL_U_DIV: UPLL divider clock identifier
31 * @ID_PLL_A_FRAC: APLL fractional clock identifier
32 * @ID_PLL_A_DIV: APLL divider clock identifier
33
34 * @ID_MCK: MCK clock identifier
35
36 * @ID_UTMI: UTMI clock identifier
37
38 * @ID_PROG0: Programmable 0 clock identifier
39 * @ID_PROG1: Programmable 1 clock identifier
40
41 * @ID_PCK0: PCK0 system clock identifier
42 * @ID_PCK1: PCK1 system clock identifier
43 * @ID_DDR: DDR system clock identifier
44 * @ID_QSPI: QSPI system clock identifier
45 *
46 * Note: if changing the values of this enums please sync them with
47 * device tree
48 */
49enum pmc_clk_ids {
50 ID_MD_SLCK = 0,
51 ID_TD_SLCK = 1,
52 ID_MAIN_XTAL = 2,
53 ID_MAIN_RC = 3,
54 ID_MAIN_RC_OSC = 4,
55 ID_MAIN_OSC = 5,
56 ID_MAINCK = 6,
57
58 ID_PLL_U_FRAC = 7,
59 ID_PLL_U_DIV = 8,
60 ID_PLL_A_FRAC = 9,
61 ID_PLL_A_DIV = 10,
62
63 ID_MCK = 11,
64
65 ID_UTMI = 12,
66
67 ID_PROG0 = 13,
68 ID_PROG1 = 14,
69
70 ID_PCK0 = 15,
71 ID_PCK1 = 16,
72
73 ID_DDR = 17,
74 ID_QSPI = 18,
75
76 ID_MAX,
77};
78
79/**
80 * PLL type identifiers
81 * @PLL_TYPE_FRAC: fractional PLL identifier
82 * @PLL_TYPE_DIV: divider PLL identifier
83 */
84enum pll_type {
85 PLL_TYPE_FRAC,
86 PLL_TYPE_DIV,
87};
88
89/* Clock names used as parents for multiple clocks. */
90static const char *clk_names[] = {
91 [ID_MAIN_RC_OSC] = "main_rc_osc",
92 [ID_MAIN_OSC] = "main_osc",
93 [ID_MAINCK] = "mainck",
94 [ID_PLL_U_DIV] = "upll_divpmcck",
95 [ID_PLL_A_DIV] = "plla_divpmcck",
96 [ID_MCK] = "mck",
97};
98
99/* Fractional PLL output range. */
100static const struct clk_range plla_outputs[] = {
101 { .min = 2343750, .max = 1200000000 },
102};
103
104static const struct clk_range upll_outputs[] = {
105 { .min = 300000000, .max = 500000000 },
106};
107
108/* PLL characteristics. */
109static const struct clk_pll_characteristics apll_characteristics = {
110 .input = { .min = 12000000, .max = 48000000 },
111 .num_output = ARRAY_SIZE(plla_outputs),
112 .output = plla_outputs,
113};
114
115static const struct clk_pll_characteristics upll_characteristics = {
116 .input = { .min = 12000000, .max = 48000000 },
117 .num_output = ARRAY_SIZE(upll_outputs),
118 .output = upll_outputs,
119 .upll = true,
120};
121
122/* Layout for fractional PLLs. */
123static const struct clk_pll_layout pll_layout_frac = {
124 .mul_mask = GENMASK(31, 24),
125 .frac_mask = GENMASK(21, 0),
126 .mul_shift = 24,
127 .frac_shift = 0,
128};
129
130/* Layout for DIV PLLs. */
131static const struct clk_pll_layout pll_layout_div = {
132 .div_mask = GENMASK(7, 0),
133 .endiv_mask = BIT(29),
134 .div_shift = 0,
135 .endiv_shift = 29,
136};
137
138/* MCK characteristics. */
139static const struct clk_master_characteristics mck_characteristics = {
140 .output = { .min = 140000000, .max = 200000000 },
141 .divisors = { 1, 2, 4, 3 },
142 .have_div3_pres = 1,
143};
144
145/* MCK layout. */
146static const struct clk_master_layout mck_layout = {
147 .mask = 0x373,
148 .pres_shift = 4,
149 .offset = 0x28,
150};
151
152/* Programmable clock layout. */
153static const struct clk_programmable_layout programmable_layout = {
154 .pres_mask = 0xff,
155 .pres_shift = 8,
156 .css_mask = 0x1f,
157 .have_slck_mck = 0,
158 .is_pres_direct = 1,
159};
160
161/* Peripheral clock layout. */
162static const struct clk_pcr_layout pcr_layout = {
163 .offset = 0x88,
164 .cmd = BIT(31),
165 .gckcss_mask = GENMASK(12, 8),
166 .pid_mask = GENMASK(6, 0),
167};
168
169/**
170 * PLL clocks description
171 * @n: clock name
172 * @p: clock parent
173 * @l: clock layout
174 * @t: clock type
175 * @f: true if clock is fixed and not changeable by driver
176 * @id: clock id corresponding to PLL driver
177 * @cid: clock id corresponding to clock subsystem
178 */
179static const struct {
180 const char *n;
181 const char *p;
182 const struct clk_pll_layout *l;
183 const struct clk_pll_characteristics *c;
184 u8 t;
185 u8 f;
186 u8 id;
187 u8 cid;
188} sam9x60_plls[] = {
189 {
190 .n = "plla_fracck",
191 .p = "mainck",
192 .l = &pll_layout_frac,
193 .c = &apll_characteristics,
194 .t = PLL_TYPE_FRAC,
195 .f = 1,
196 .id = 0,
197 .cid = ID_PLL_A_FRAC,
198 },
199
200 {
201 .n = "plla_divpmcck",
202 .p = "plla_fracck",
203 .l = &pll_layout_div,
204 .c = &apll_characteristics,
205 .t = PLL_TYPE_DIV,
206 .f = 1,
207 .id = 0,
208 .cid = ID_PLL_A_DIV,
209 },
210
211 {
212 .n = "upll_fracck",
213 .p = "main_osc",
214 .l = &pll_layout_frac,
215 .c = &upll_characteristics,
216 .t = PLL_TYPE_FRAC,
217 .f = 1,
218 .id = 1,
219 .cid = ID_PLL_U_FRAC,
220 },
221
222 {
223 .n = "upll_divpmcck",
224 .p = "upll_fracck",
225 .l = &pll_layout_div,
226 .c = &upll_characteristics,
227 .t = PLL_TYPE_DIV,
228 .f = 1,
229 .id = 1,
230 .cid = ID_PLL_U_DIV,
231 },
232};
233
234/**
235 * Programmable clock description
236 * @n: clock name
237 * @cid: clock id corresponding to clock subsystem
238 */
239static const struct {
240 const char *n;
241 u8 cid;
242} sam9x60_prog[] = {
243 { .n = "prog0", .cid = ID_PROG0, },
244 { .n = "prog1", .cid = ID_PROG1, },
245};
246
247/* Mux table for programmable clocks. */
248static u32 sam9x60_prog_mux_table[] = { 0, 1, 2, 3, 4, 5, };
249
250/**
251 * System clock description
252 * @n: clock name
253 * @p: parent clock name
254 * @id: clock id corresponding to system clock driver
255 * @cid: clock id corresponding to clock subsystem
256 */
257static const struct {
258 const char *n;
259 const char *p;
260 u8 id;
261 u8 cid;
262} sam9x60_systemck[] = {
263 { .n = "ddrck", .p = "mck", .id = 2, .cid = ID_DDR, },
264 { .n = "pck0", .p = "prog0", .id = 8, .cid = ID_PCK0, },
265 { .n = "pck1", .p = "prog1", .id = 9, .cid = ID_PCK1, },
266 { .n = "qspick", .p = "mck", .id = 19, .cid = ID_QSPI, },
267};
268
269/**
270 * Peripheral clock description
271 * @n: clock name
272 * @id: clock id
273 */
274static const struct {
275 const char *n;
276 u8 id;
277} sam9x60_periphck[] = {
278 { .n = "pioA_clk", .id = 2, },
279 { .n = "pioB_clk", .id = 3, },
280 { .n = "pioC_clk", .id = 4, },
281 { .n = "flex0_clk", .id = 5, },
282 { .n = "flex1_clk", .id = 6, },
283 { .n = "flex2_clk", .id = 7, },
284 { .n = "flex3_clk", .id = 8, },
285 { .n = "flex6_clk", .id = 9, },
286 { .n = "flex7_clk", .id = 10, },
287 { .n = "flex8_clk", .id = 11, },
288 { .n = "sdmmc0_clk", .id = 12, },
289 { .n = "flex4_clk", .id = 13, },
290 { .n = "flex5_clk", .id = 14, },
291 { .n = "flex9_clk", .id = 15, },
292 { .n = "flex10_clk", .id = 16, },
293 { .n = "tcb0_clk", .id = 17, },
294 { .n = "pwm_clk", .id = 18, },
295 { .n = "adc_clk", .id = 19, },
296 { .n = "dma0_clk", .id = 20, },
297 { .n = "matrix_clk", .id = 21, },
298 { .n = "uhphs_clk", .id = 22, },
299 { .n = "udphs_clk", .id = 23, },
300 { .n = "macb0_clk", .id = 24, },
301 { .n = "lcd_clk", .id = 25, },
302 { .n = "sdmmc1_clk", .id = 26, },
303 { .n = "macb1_clk", .id = 27, },
304 { .n = "ssc_clk", .id = 28, },
305 { .n = "can0_clk", .id = 29, },
306 { .n = "can1_clk", .id = 30, },
307 { .n = "flex11_clk", .id = 32, },
308 { .n = "flex12_clk", .id = 33, },
309 { .n = "i2s_clk", .id = 34, },
310 { .n = "qspi_clk", .id = 35, },
311 { .n = "gfx2d_clk", .id = 36, },
312 { .n = "pit64b_clk", .id = 37, },
313 { .n = "trng_clk", .id = 38, },
314 { .n = "aes_clk", .id = 39, },
315 { .n = "tdes_clk", .id = 40, },
316 { .n = "sha_clk", .id = 41, },
317 { .n = "classd_clk", .id = 42, },
318 { .n = "isi_clk", .id = 43, },
319 { .n = "pioD_clk", .id = 44, },
320 { .n = "tcb1_clk", .id = 45, },
321 { .n = "dbgu_clk", .id = 47, },
322 { .n = "mpddr_clk", .id = 49, },
323};
324
325/**
326 * Generic clock description
327 * @n: clock name
328 * @ep: extra parents parents names
329 * @ep_mux_table: extra parents mux table
330 * @ep_clk_mux_table: extra parents clock mux table (for CCF)
331 * @r: clock output range
332 * @ep_count: extra parents count
333 * @id: clock id
334 */
335static const struct {
336 const char *n;
337 struct clk_range r;
338 u8 id;
339} sam9x60_gck[] = {
340 { .n = "flex0_gclk", .id = 5, },
341 { .n = "flex1_gclk", .id = 6, },
342 { .n = "flex2_gclk", .id = 7, },
343 { .n = "flex3_gclk", .id = 8, },
344 { .n = "flex6_gclk", .id = 9, },
345 { .n = "flex7_gclk", .id = 10, },
346 { .n = "flex8_gclk", .id = 11, },
347 { .n = "sdmmc0_gclk", .id = 12, .r = { .min = 0, .max = 105000000 }, },
348 { .n = "flex4_gclk", .id = 13, },
349 { .n = "flex5_gclk", .id = 14, },
350 { .n = "flex9_gclk", .id = 15, },
351 { .n = "flex10_gclk", .id = 16, },
352 { .n = "tcb0_gclk", .id = 17, },
353 { .n = "adc_gclk", .id = 19, },
354 { .n = "lcd_gclk", .id = 25, .r = { .min = 0, .max = 140000000 }, },
355 { .n = "sdmmc1_gclk", .id = 26, .r = { .min = 0, .max = 105000000 }, },
356 { .n = "flex11_gclk", .id = 32, },
357 { .n = "flex12_gclk", .id = 33, },
358 { .n = "i2s_gclk", .id = 34, .r = { .min = 0, .max = 105000000 }, },
359 { .n = "pit64b_gclk", .id = 37, },
360 { .n = "classd_gclk", .id = 42, .r = { .min = 0, .max = 100000000 }, },
361 { .n = "tcb1_gclk", .id = 45, },
362 { .n = "dbgu_gclk", .id = 47, },
363};
364
365#define prepare_mux_table(_allocs, _index, _dst, _src, _num, _label) \
366 do { \
367 int _i; \
368 (_dst) = kzalloc(sizeof(*(_dst)) * (_num), GFP_KERNEL); \
369 if (!(_dst)) { \
370 ret = -ENOMEM; \
371 goto _label; \
372 } \
373 (_allocs)[(_index)++] = (_dst); \
374 for (_i = 0; _i < (_num); _i++) \
375 (_dst)[_i] = (_src)[_i]; \
376 } while (0)
377
378static int sam9x60_clk_probe(struct udevice *dev)
379{
380 void __iomem *base = (void *)devfdt_get_addr_ptr(dev);
381 unsigned int *clkmuxallocs[64], *muxallocs[64];
382 const char *p[10];
383 unsigned int cm[10], m[10], *tmpclkmux, *tmpmux;
384 struct clk clk, *c;
385 bool main_osc_bypass;
386 int ret, muxallocindex = 0, clkmuxallocindex = 0, i;
387 static const struct clk_range r = { 0, 0 };
388
389 if (!base)
390 return -EINVAL;
391
392 memset(muxallocs, 0, ARRAY_SIZE(muxallocs));
393 memset(clkmuxallocs, 0, ARRAY_SIZE(clkmuxallocs));
394
395 ret = clk_get_by_index(dev, 0, &clk);
396 if (ret)
397 return ret;
398
399 ret = clk_get_by_id(clk.id, &c);
400 if (ret)
401 return ret;
402
403 clk_names[ID_TD_SLCK] = kmemdup(clk_hw_get_name(c),
404 strlen(clk_hw_get_name(c)) + 1,
405 GFP_KERNEL);
406 if (!clk_names[ID_TD_SLCK])
407 return -ENOMEM;
408
409 ret = clk_get_by_index(dev, 1, &clk);
410 if (ret)
411 return ret;
412
413 ret = clk_get_by_id(clk.id, &c);
414 if (ret)
415 return ret;
416
417 clk_names[ID_MD_SLCK] = kmemdup(clk_hw_get_name(c),
418 strlen(clk_hw_get_name(c)) + 1,
419 GFP_KERNEL);
420 if (!clk_names[ID_MD_SLCK])
421 return -ENOMEM;
422
423 ret = clk_get_by_index(dev, 2, &clk);
424 if (ret)
425 return ret;
426
427 clk_names[ID_MAIN_XTAL] = kmemdup(clk_hw_get_name(&clk),
428 strlen(clk_hw_get_name(&clk)) + 1,
429 GFP_KERNEL);
430 if (!clk_names[ID_MAIN_XTAL])
431 return -ENOMEM;
432
433 ret = clk_get_by_index(dev, 3, &clk);
434 if (ret)
435 goto fail;
436
437 clk_names[ID_MAIN_RC] = kmemdup(clk_hw_get_name(&clk),
438 strlen(clk_hw_get_name(&clk)) + 1,
439 GFP_KERNEL);
440 if (ret)
441 goto fail;
442
443 main_osc_bypass = dev_read_bool(dev, "atmel,main-osc-bypass");
444
445 /* Register main rc oscillator. */
446 c = at91_clk_main_rc(base, clk_names[ID_MAIN_RC_OSC],
447 clk_names[ID_MAIN_RC]);
448 if (IS_ERR(c)) {
449 ret = PTR_ERR(c);
450 goto fail;
451 }
452 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAIN_RC_OSC), c);
453
454 /* Register main oscillator. */
455 c = at91_clk_main_osc(base, clk_names[ID_MAIN_OSC],
456 clk_names[ID_MAIN_XTAL], main_osc_bypass);
457 if (IS_ERR(c)) {
458 ret = PTR_ERR(c);
459 goto fail;
460 }
461 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAIN_OSC), c);
462
463 /* Register mainck. */
464 p[0] = clk_names[ID_MAIN_RC_OSC];
465 p[1] = clk_names[ID_MAIN_OSC];
466 cm[0] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAIN_RC_OSC);
467 cm[1] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAIN_OSC);
468 prepare_mux_table(clkmuxallocs, clkmuxallocindex, tmpclkmux, cm, 2,
469 fail);
470 c = at91_clk_sam9x5_main(base, clk_names[ID_MAINCK], p,
471 2, tmpclkmux, PMC_TYPE_CORE);
472 if (IS_ERR(c)) {
473 ret = PTR_ERR(c);
474 goto fail;
475 }
476 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAINCK), c);
477
478 /* Register PLL fracs clocks. */
479 for (i = 0; i < ARRAY_SIZE(sam9x60_plls); i++) {
480 if (sam9x60_plls[i].t != PLL_TYPE_FRAC)
481 continue;
482
483 c = sam9x60_clk_register_frac_pll(base, sam9x60_plls[i].n,
484 sam9x60_plls[i].p,
485 sam9x60_plls[i].id,
486 sam9x60_plls[i].c,
487 sam9x60_plls[i].l,
488 sam9x60_plls[i].f);
489 if (IS_ERR(c)) {
490 ret = PTR_ERR(c);
491 goto fail;
492 }
493 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, sam9x60_plls[i].cid), c);
494 }
495
496 /* Register PLL div clocks. */
497 for (i = 0; i < ARRAY_SIZE(sam9x60_plls); i++) {
498 if (sam9x60_plls[i].t != PLL_TYPE_DIV)
499 continue;
500
501 c = sam9x60_clk_register_div_pll(base, sam9x60_plls[i].n,
502 sam9x60_plls[i].p,
503 sam9x60_plls[i].id,
504 sam9x60_plls[i].c,
505 sam9x60_plls[i].l,
506 sam9x60_plls[i].f);
507 if (IS_ERR(c)) {
508 ret = PTR_ERR(c);
509 goto fail;
510 }
511 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, sam9x60_plls[i].cid), c);
512 }
513
514 /* Register MCK clock. */
515 p[0] = clk_names[ID_MD_SLCK];
516 p[1] = clk_names[ID_MAINCK];
517 p[2] = clk_names[ID_PLL_A_DIV];
518 p[3] = clk_names[ID_PLL_U_DIV];
519 cm[0] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MD_SLCK);
520 cm[1] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAINCK);
521 cm[2] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_A_DIV);
522 cm[3] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_U_DIV);
523 prepare_mux_table(clkmuxallocs, clkmuxallocindex, tmpclkmux, cm, 4,
524 fail);
525 c = at91_clk_register_master(base, clk_names[ID_MCK], p, 4, &mck_layout,
526 &mck_characteristics, tmpclkmux);
527 if (IS_ERR(c)) {
528 ret = PTR_ERR(c);
529 goto fail;
530 }
531 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MCK), c);
532
533 /* Register programmable clocks. */
534 p[0] = clk_names[ID_MD_SLCK];
535 p[1] = clk_names[ID_TD_SLCK];
536 p[2] = clk_names[ID_MAINCK];
537 p[3] = clk_names[ID_MCK];
538 p[4] = clk_names[ID_PLL_A_DIV];
539 p[5] = clk_names[ID_PLL_U_DIV];
540 cm[0] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MD_SLCK);
541 cm[1] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_TD_SLCK);
542 cm[2] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAINCK);
543 cm[3] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MCK);
544 cm[4] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_A_DIV);
545 cm[5] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_U_DIV);
546 for (i = 0; i < ARRAY_SIZE(sam9x60_prog); i++) {
547 prepare_mux_table(clkmuxallocs, clkmuxallocindex, tmpclkmux, cm,
548 6, fail);
549
550 c = at91_clk_register_programmable(base, sam9x60_prog[i].n, p,
551 10, i, &programmable_layout,
552 tmpclkmux,
553 sam9x60_prog_mux_table);
554 if (IS_ERR(c)) {
555 ret = PTR_ERR(c);
556 goto fail;
557 }
558 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, sam9x60_prog[i].cid), c);
559 }
560
561 /* System clocks. */
562 for (i = 0; i < ARRAY_SIZE(sam9x60_systemck); i++) {
563 c = at91_clk_register_system(base, sam9x60_systemck[i].n,
564 sam9x60_systemck[i].p,
565 sam9x60_systemck[i].id);
566 if (IS_ERR(c)) {
567 ret = PTR_ERR(c);
568 goto fail;
569 }
570 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_SYSTEM, sam9x60_systemck[i].cid),
571 c);
572 }
573
574 /* Peripheral clocks. */
575 for (i = 0; i < ARRAY_SIZE(sam9x60_periphck); i++) {
576 c = at91_clk_register_sam9x5_peripheral(base, &pcr_layout,
577 sam9x60_periphck[i].n,
578 clk_names[ID_MCK],
579 sam9x60_periphck[i].id,
580 &r);
581 if (IS_ERR(c)) {
582 ret = PTR_ERR(c);
583 goto fail;
584 }
585 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_PERIPHERAL,
586 sam9x60_periphck[i].id), c);
587 }
588
589 /* Generic clocks. */
590 p[0] = clk_names[ID_MD_SLCK];
591 p[1] = clk_names[ID_TD_SLCK];
592 p[2] = clk_names[ID_MAINCK];
593 p[3] = clk_names[ID_MCK];
594 p[4] = clk_names[ID_PLL_A_DIV];
595 p[5] = clk_names[ID_PLL_U_DIV];
596 m[0] = 0;
597 m[1] = 1;
598 m[2] = 2;
599 m[3] = 3;
600 m[4] = 4;
601 m[5] = 5;
602 cm[0] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MD_SLCK);
603 cm[1] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_TD_SLCK);
604 cm[2] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAINCK);
605 cm[3] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MCK);
606 cm[4] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_A_DIV);
607 cm[5] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_U_DIV);
608 for (i = 0; i < ARRAY_SIZE(sam9x60_gck); i++) {
609 prepare_mux_table(clkmuxallocs, clkmuxallocindex, tmpclkmux, cm,
610 6, fail);
611 prepare_mux_table(muxallocs, muxallocindex, tmpmux, m,
612 6, fail);
613
614 c = at91_clk_register_generic(base, &pcr_layout,
615 sam9x60_gck[i].n, p, tmpclkmux,
616 tmpmux, 6, sam9x60_gck[i].id,
617 &sam9x60_gck[i].r);
618 if (IS_ERR(c)) {
619 ret = PTR_ERR(c);
620 goto fail;
621 }
622 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_GCK, sam9x60_gck[i].id), c);
623 }
624
625 return 0;
626
627fail:
628 for (i = 0; i < ARRAY_SIZE(muxallocs); i++)
629 kfree(muxallocs[i]);
630
631 for (i = 0; i < ARRAY_SIZE(clkmuxallocs); i++)
632 kfree(clkmuxallocs[i]);
633
634 return ret;
635}
636
637static const struct udevice_id sam9x60_clk_ids[] = {
638 { .compatible = "microchip,sam9x60-pmc" },
639 { /* Sentinel. */ },
640};
641
642U_BOOT_DRIVER(at91_sam9x60_pmc) = {
643 .name = "at91-sam9x60-pmc",
644 .id = UCLASS_CLK,
645 .of_match = sam9x60_clk_ids,
646 .ops = &at91_clk_ops,
647 .probe = sam9x60_clk_probe,
648 .flags = DM_FLAG_PRE_RELOC,
649};