blob: 9e9a643d62d7af32de13f621b214846c4c7cb3c1 [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;
Claudiu Bezneabaf5b522020-10-07 18:17:08 +0300385 int ret, muxallocindex = 0, clkmuxallocindex = 0, i;
386 static const struct clk_range r = { 0, 0 };
387
388 if (!base)
389 return -EINVAL;
390
391 memset(muxallocs, 0, ARRAY_SIZE(muxallocs));
392 memset(clkmuxallocs, 0, ARRAY_SIZE(clkmuxallocs));
393
394 ret = clk_get_by_index(dev, 0, &clk);
395 if (ret)
396 return ret;
397
398 ret = clk_get_by_id(clk.id, &c);
399 if (ret)
400 return ret;
401
402 clk_names[ID_TD_SLCK] = kmemdup(clk_hw_get_name(c),
403 strlen(clk_hw_get_name(c)) + 1,
404 GFP_KERNEL);
405 if (!clk_names[ID_TD_SLCK])
406 return -ENOMEM;
407
408 ret = clk_get_by_index(dev, 1, &clk);
409 if (ret)
410 return ret;
411
412 ret = clk_get_by_id(clk.id, &c);
413 if (ret)
414 return ret;
415
416 clk_names[ID_MD_SLCK] = kmemdup(clk_hw_get_name(c),
417 strlen(clk_hw_get_name(c)) + 1,
418 GFP_KERNEL);
419 if (!clk_names[ID_MD_SLCK])
420 return -ENOMEM;
421
422 ret = clk_get_by_index(dev, 2, &clk);
423 if (ret)
424 return ret;
425
426 clk_names[ID_MAIN_XTAL] = kmemdup(clk_hw_get_name(&clk),
427 strlen(clk_hw_get_name(&clk)) + 1,
428 GFP_KERNEL);
429 if (!clk_names[ID_MAIN_XTAL])
430 return -ENOMEM;
431
432 ret = clk_get_by_index(dev, 3, &clk);
433 if (ret)
434 goto fail;
435
436 clk_names[ID_MAIN_RC] = kmemdup(clk_hw_get_name(&clk),
437 strlen(clk_hw_get_name(&clk)) + 1,
438 GFP_KERNEL);
439 if (ret)
440 goto fail;
441
Claudiu Bezneabaf5b522020-10-07 18:17:08 +0300442 /* Register main rc oscillator. */
443 c = at91_clk_main_rc(base, clk_names[ID_MAIN_RC_OSC],
444 clk_names[ID_MAIN_RC]);
445 if (IS_ERR(c)) {
446 ret = PTR_ERR(c);
447 goto fail;
448 }
449 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAIN_RC_OSC), c);
450
451 /* Register main oscillator. */
452 c = at91_clk_main_osc(base, clk_names[ID_MAIN_OSC],
Claudiu Beznea84503cd2020-12-02 13:39:33 +0200453 clk_names[ID_MAIN_XTAL], false);
Claudiu Bezneabaf5b522020-10-07 18:17:08 +0300454 if (IS_ERR(c)) {
455 ret = PTR_ERR(c);
456 goto fail;
457 }
458 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAIN_OSC), c);
459
460 /* Register mainck. */
461 p[0] = clk_names[ID_MAIN_RC_OSC];
462 p[1] = clk_names[ID_MAIN_OSC];
463 cm[0] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAIN_RC_OSC);
464 cm[1] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAIN_OSC);
465 prepare_mux_table(clkmuxallocs, clkmuxallocindex, tmpclkmux, cm, 2,
466 fail);
467 c = at91_clk_sam9x5_main(base, clk_names[ID_MAINCK], p,
468 2, tmpclkmux, PMC_TYPE_CORE);
469 if (IS_ERR(c)) {
470 ret = PTR_ERR(c);
471 goto fail;
472 }
473 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAINCK), c);
474
475 /* Register PLL fracs clocks. */
476 for (i = 0; i < ARRAY_SIZE(sam9x60_plls); i++) {
477 if (sam9x60_plls[i].t != PLL_TYPE_FRAC)
478 continue;
479
480 c = sam9x60_clk_register_frac_pll(base, sam9x60_plls[i].n,
481 sam9x60_plls[i].p,
482 sam9x60_plls[i].id,
483 sam9x60_plls[i].c,
484 sam9x60_plls[i].l,
485 sam9x60_plls[i].f);
486 if (IS_ERR(c)) {
487 ret = PTR_ERR(c);
488 goto fail;
489 }
490 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, sam9x60_plls[i].cid), c);
491 }
492
493 /* Register PLL div clocks. */
494 for (i = 0; i < ARRAY_SIZE(sam9x60_plls); i++) {
495 if (sam9x60_plls[i].t != PLL_TYPE_DIV)
496 continue;
497
498 c = sam9x60_clk_register_div_pll(base, sam9x60_plls[i].n,
499 sam9x60_plls[i].p,
500 sam9x60_plls[i].id,
501 sam9x60_plls[i].c,
502 sam9x60_plls[i].l,
503 sam9x60_plls[i].f);
504 if (IS_ERR(c)) {
505 ret = PTR_ERR(c);
506 goto fail;
507 }
508 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, sam9x60_plls[i].cid), c);
509 }
510
511 /* Register MCK clock. */
512 p[0] = clk_names[ID_MD_SLCK];
513 p[1] = clk_names[ID_MAINCK];
514 p[2] = clk_names[ID_PLL_A_DIV];
515 p[3] = clk_names[ID_PLL_U_DIV];
516 cm[0] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MD_SLCK);
517 cm[1] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAINCK);
518 cm[2] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_A_DIV);
519 cm[3] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_U_DIV);
520 prepare_mux_table(clkmuxallocs, clkmuxallocindex, tmpclkmux, cm, 4,
521 fail);
522 c = at91_clk_register_master(base, clk_names[ID_MCK], p, 4, &mck_layout,
523 &mck_characteristics, tmpclkmux);
524 if (IS_ERR(c)) {
525 ret = PTR_ERR(c);
526 goto fail;
527 }
528 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MCK), c);
529
530 /* Register programmable clocks. */
531 p[0] = clk_names[ID_MD_SLCK];
532 p[1] = clk_names[ID_TD_SLCK];
533 p[2] = clk_names[ID_MAINCK];
534 p[3] = clk_names[ID_MCK];
535 p[4] = clk_names[ID_PLL_A_DIV];
536 p[5] = clk_names[ID_PLL_U_DIV];
537 cm[0] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MD_SLCK);
538 cm[1] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_TD_SLCK);
539 cm[2] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAINCK);
540 cm[3] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MCK);
541 cm[4] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_A_DIV);
542 cm[5] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_U_DIV);
543 for (i = 0; i < ARRAY_SIZE(sam9x60_prog); i++) {
544 prepare_mux_table(clkmuxallocs, clkmuxallocindex, tmpclkmux, cm,
545 6, fail);
546
547 c = at91_clk_register_programmable(base, sam9x60_prog[i].n, p,
548 10, i, &programmable_layout,
549 tmpclkmux,
550 sam9x60_prog_mux_table);
551 if (IS_ERR(c)) {
552 ret = PTR_ERR(c);
553 goto fail;
554 }
555 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, sam9x60_prog[i].cid), c);
556 }
557
558 /* System clocks. */
559 for (i = 0; i < ARRAY_SIZE(sam9x60_systemck); i++) {
560 c = at91_clk_register_system(base, sam9x60_systemck[i].n,
561 sam9x60_systemck[i].p,
562 sam9x60_systemck[i].id);
563 if (IS_ERR(c)) {
564 ret = PTR_ERR(c);
565 goto fail;
566 }
567 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_SYSTEM, sam9x60_systemck[i].cid),
568 c);
569 }
570
571 /* Peripheral clocks. */
572 for (i = 0; i < ARRAY_SIZE(sam9x60_periphck); i++) {
573 c = at91_clk_register_sam9x5_peripheral(base, &pcr_layout,
574 sam9x60_periphck[i].n,
575 clk_names[ID_MCK],
576 sam9x60_periphck[i].id,
577 &r);
578 if (IS_ERR(c)) {
579 ret = PTR_ERR(c);
580 goto fail;
581 }
582 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_PERIPHERAL,
583 sam9x60_periphck[i].id), c);
584 }
585
586 /* Generic clocks. */
587 p[0] = clk_names[ID_MD_SLCK];
588 p[1] = clk_names[ID_TD_SLCK];
589 p[2] = clk_names[ID_MAINCK];
590 p[3] = clk_names[ID_MCK];
591 p[4] = clk_names[ID_PLL_A_DIV];
592 p[5] = clk_names[ID_PLL_U_DIV];
593 m[0] = 0;
594 m[1] = 1;
595 m[2] = 2;
596 m[3] = 3;
597 m[4] = 4;
598 m[5] = 5;
599 cm[0] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MD_SLCK);
600 cm[1] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_TD_SLCK);
601 cm[2] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAINCK);
602 cm[3] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MCK);
603 cm[4] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_A_DIV);
604 cm[5] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_U_DIV);
605 for (i = 0; i < ARRAY_SIZE(sam9x60_gck); i++) {
606 prepare_mux_table(clkmuxallocs, clkmuxallocindex, tmpclkmux, cm,
607 6, fail);
608 prepare_mux_table(muxallocs, muxallocindex, tmpmux, m,
609 6, fail);
610
611 c = at91_clk_register_generic(base, &pcr_layout,
612 sam9x60_gck[i].n, p, tmpclkmux,
613 tmpmux, 6, sam9x60_gck[i].id,
614 &sam9x60_gck[i].r);
615 if (IS_ERR(c)) {
616 ret = PTR_ERR(c);
617 goto fail;
618 }
619 clk_dm(AT91_TO_CLK_ID(PMC_TYPE_GCK, sam9x60_gck[i].id), c);
620 }
621
622 return 0;
623
624fail:
625 for (i = 0; i < ARRAY_SIZE(muxallocs); i++)
626 kfree(muxallocs[i]);
627
628 for (i = 0; i < ARRAY_SIZE(clkmuxallocs); i++)
629 kfree(clkmuxallocs[i]);
630
631 return ret;
632}
633
634static const struct udevice_id sam9x60_clk_ids[] = {
635 { .compatible = "microchip,sam9x60-pmc" },
636 { /* Sentinel. */ },
637};
638
639U_BOOT_DRIVER(at91_sam9x60_pmc) = {
640 .name = "at91-sam9x60-pmc",
641 .id = UCLASS_CLK,
642 .of_match = sam9x60_clk_ids,
643 .ops = &at91_clk_ops,
644 .probe = sam9x60_clk_probe,
645 .flags = DM_FLAG_PRE_RELOC,
646};