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