1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2024, Microchip 4 */ 5 6 #include <assert.h> 7 #include <dt-bindings/clock/at91.h> 8 #include <io.h> 9 #include <kernel/boot.h> 10 #include <kernel/dt.h> 11 #include <kernel/panic.h> 12 #include <libfdt.h> 13 #include <matrix.h> 14 #include <sama7g5.h> 15 #include <stdint.h> 16 #include <util.h> 17 #include "at91_clk.h" 18 19 #define CLK_IS_CRITICAL 0 20 21 /* PLL clocks identifiers */ 22 enum pll_ids { 23 PLL_ID_CPU, 24 PLL_ID_SYS, 25 PLL_ID_DDR, 26 PLL_ID_IMG, 27 PLL_ID_BAUD, 28 PLL_ID_AUDIO, 29 PLL_ID_ETH, 30 PLL_ID_MAX, 31 }; 32 33 /* PLL type identifiers */ 34 enum pll_type { 35 PLL_TYPE_FRAC, 36 PLL_TYPE_DIV, 37 PLL_TYPE_CNT, 38 }; 39 40 /* Layout for fractional PLLs */ 41 static const struct clk_pll_layout pll_layout_frac = { 42 .mul_mask = GENMASK_32(31, 24), 43 .frac_mask = GENMASK_32(21, 0), 44 .mul_shift = 24, 45 .frac_shift = 0, 46 }; 47 48 /* Layout for DIVPMC dividers */ 49 static const struct clk_pll_layout pll_layout_divpmc = { 50 .div_mask = GENMASK_32(7, 0), 51 .endiv_mask = BIT(29), 52 .div_shift = 0, 53 .endiv_shift = 29, 54 }; 55 56 /* Layout for DIVIO dividers */ 57 static const struct clk_pll_layout pll_layout_divio = { 58 .div_mask = GENMASK_32(19, 12), 59 .endiv_mask = BIT(30), 60 .div_shift = 12, 61 .endiv_shift = 30, 62 }; 63 64 /* 65 * CPU PLL output range 66 * Notice: The upper limit has been setup to 1000000002 due to hardware 67 * block which cannot output exactly 1GHz. 68 */ 69 static const struct clk_range cpu_pll_output[] = { 70 { .min = 2343750, .max = 1000000002 }, 71 }; 72 73 /* PLL output range */ 74 static const struct clk_range pll_output[] = { 75 { .min = 2343750, .max = 1200000000 }, 76 }; 77 78 /* CPU PLL characteristics */ 79 static const struct clk_pll_charac cpu_pll_characteristics = { 80 .input = { .min = 12000000, .max = 50000000 }, 81 .num_output = ARRAY_SIZE(cpu_pll_output), 82 .output = cpu_pll_output, 83 }; 84 85 /* PLL characteristics */ 86 static const struct clk_pll_charac pll_characteristics = { 87 .input = { .min = 12000000, .max = 50000000 }, 88 .num_output = ARRAY_SIZE(pll_output), 89 .output = pll_output, 90 }; 91 92 /* PLL clocks description */ 93 struct sama7g5_pll { 94 const char *name; 95 const char *parent; 96 const struct clk_pll_layout *layout; 97 const struct clk_pll_charac *charac; 98 unsigned long flags; 99 uint8_t type; 100 uint8_t eid; /* export index in sama7g5->chws[] array */ 101 uint8_t safe_div; /* intermediate divider need to be set on 102 * PRE_RATE_CHANGE notification 103 */ 104 }; 105 106 static const struct sama7g5_pll sama7g5_plls[][PLL_ID_MAX] = { 107 [PLL_ID_CPU] = { 108 { 109 .name = "cpupll_fracck", 110 .parent = "mainck", 111 .layout = &pll_layout_frac, 112 .charac = &cpu_pll_characteristics, 113 .type = PLL_TYPE_FRAC, 114 /* 115 * This feeds cpupll_divpmcck which feeds CPU. It 116 * should not be disabled. 117 */ 118 .flags = CLK_IS_CRITICAL, 119 }, 120 { 121 .name = "cpupll_divpmcck", 122 .parent = "cpupll_fracck", 123 .layout = &pll_layout_divpmc, 124 .charac = &cpu_pll_characteristics, 125 .type = PLL_TYPE_DIV, 126 /* This feeds CPU. It should not be disabled. */ 127 .flags = CLK_IS_CRITICAL, 128 .eid = PMC_CPUPLL, 129 /* 130 * Safe div=15 should be safe even for switching b/w 131 * 1GHz and 90MHz (frac pll might go up to 1.2GHz). 132 */ 133 .safe_div = 15, 134 }, 135 }, 136 137 [PLL_ID_SYS] = { 138 { 139 .name = "syspll_fracck", 140 .parent = "mainck", 141 .layout = &pll_layout_frac, 142 .charac = &pll_characteristics, 143 .type = PLL_TYPE_FRAC, 144 /* 145 * This feeds syspll_divpmcck which may feed critical 146 * parts of the systems like timers. Therefore it 147 * should not be disabled. 148 */ 149 .flags = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, 150 }, 151 { 152 .name = "syspll_divpmcck", 153 .parent = "syspll_fracck", 154 .layout = &pll_layout_divpmc, 155 .charac = &pll_characteristics, 156 .type = PLL_TYPE_DIV, 157 /* 158 * This may feed critical parts of the systems like 159 * timers. Therefore it should not be disabled. 160 */ 161 .flags = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, 162 .eid = PMC_SYSPLL, 163 }, 164 }, 165 166 [PLL_ID_DDR] = { 167 { 168 .name = "ddrpll_fracck", 169 .parent = "mainck", 170 .layout = &pll_layout_frac, 171 .charac = &pll_characteristics, 172 .type = PLL_TYPE_FRAC, 173 /* 174 * This feeds ddrpll_divpmcck which feeds DDR. It 175 * should not be disabled. 176 */ 177 .flags = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, 178 }, 179 { 180 .name = "ddrpll_divpmcck", 181 .parent = "ddrpll_fracck", 182 .layout = &pll_layout_divpmc, 183 .charac = &pll_characteristics, 184 .type = PLL_TYPE_DIV, 185 /* This feeds DDR. It should not be disabled. */ 186 .flags = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, 187 .eid = PMC_DDRPLL, 188 }, 189 }, 190 191 [PLL_ID_IMG] = { 192 { 193 .name = "imgpll_fracck", 194 .parent = "mainck", 195 .layout = &pll_layout_frac, 196 .charac = &pll_characteristics, 197 .type = PLL_TYPE_FRAC, 198 .flags = CLK_SET_RATE_GATE, 199 }, 200 { 201 .name = "imgpll_divpmcck", 202 .parent = "imgpll_fracck", 203 .layout = &pll_layout_divpmc, 204 .charac = &pll_characteristics, 205 .type = PLL_TYPE_DIV, 206 .flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE, 207 .eid = PMC_IMGPLL, 208 }, 209 }, 210 211 [PLL_ID_BAUD] = { 212 { 213 .name = "baudpll_fracck", 214 .parent = "mainck", 215 .layout = &pll_layout_frac, 216 .charac = &pll_characteristics, 217 .type = PLL_TYPE_FRAC, 218 .flags = CLK_SET_RATE_GATE, 219 }, 220 { 221 .name = "baudpll_divpmcck", 222 .parent = "baudpll_fracck", 223 .layout = &pll_layout_divpmc, 224 .charac = &pll_characteristics, 225 .type = PLL_TYPE_DIV, 226 .flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE, 227 .eid = PMC_BAUDPLL, 228 }, 229 }, 230 231 [PLL_ID_AUDIO] = { 232 { 233 .name = "audiopll_fracck", 234 .parent = "main_xtal", 235 .layout = &pll_layout_frac, 236 .charac = &pll_characteristics, 237 .type = PLL_TYPE_FRAC, 238 .flags = CLK_SET_RATE_GATE, 239 }, 240 { 241 .name = "audiopll_divck", 242 .parent = "audiopll_fracck", 243 .layout = &pll_layout_divpmc, 244 .charac = &pll_characteristics, 245 .type = PLL_TYPE_DIV, 246 .flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE, 247 .eid = PMC_AUDIOPMCPLL, 248 }, 249 { 250 .name = "audiopll_diviock", 251 .parent = "audiopll_fracck", 252 .layout = &pll_layout_divio, 253 .charac = &pll_characteristics, 254 .type = PLL_TYPE_DIV, 255 .flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE, 256 .eid = PMC_AUDIOIOPLL, 257 }, 258 }, 259 260 [PLL_ID_ETH] = { 261 { 262 .name = "ethpll_fracck", 263 .parent = "main_xtal", 264 .layout = &pll_layout_frac, 265 .charac = &pll_characteristics, 266 .type = PLL_TYPE_FRAC, 267 .flags = CLK_SET_RATE_GATE, 268 }, 269 { 270 .name = "ethpll_divpmcck", 271 .parent = "ethpll_fracck", 272 .layout = &pll_layout_divpmc, 273 .charac = &pll_characteristics, 274 .type = PLL_TYPE_DIV, 275 .flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE, 276 .eid = PMC_ETHPLL, 277 }, 278 }, 279 }; 280 281 /* 282 * Master clock (MCK[1..4]) description 283 * @eparents: extra parents names array 284 * @eparents_chg_id: index in parents array that specifies the changeable 285 * parent 286 * @eparents_count: extra parents count 287 * @eparents_mux_table: mux table for extra parents 288 * @id: clock id 289 * @eid: export index in sama7g5->chws[] array 290 */ 291 struct sama7g5_mck { 292 const char *name; 293 const char *eparents[4]; 294 int eparents_chg_id; 295 uint8_t eparents_count; 296 uint8_t eparents_mux_table[4]; 297 uint8_t id; 298 uint8_t eid; 299 }; 300 301 static const struct sama7g5_mck sama7g5_mckx[] = { 302 { 303 .name = "mck1", 304 .id = 1, 305 .eparents = { "syspll_divpmcck", }, 306 .eparents_mux_table = { 5, }, 307 .eparents_count = 1, 308 .eparents_chg_id = INT_MIN, 309 .eid = PMC_MCK1, 310 }, 311 { 312 .name = "mck2", 313 .id = 2, 314 .eparents = { "ddrpll_divpmcck", }, 315 .eparents_mux_table = { 6, }, 316 .eparents_count = 1, 317 .eparents_chg_id = INT_MIN, 318 }, 319 { 320 .name = "mck3", 321 .id = 3, 322 .eparents = { "syspll_divpmcck", 323 "ddrpll_divpmcck", 324 "imgpll_divpmcck", }, 325 .eparents_mux_table = { 5, 6, 7, }, 326 .eparents_count = 3, 327 .eparents_chg_id = 5, 328 }, 329 { 330 .name = "mck4", 331 .id = 4, 332 .eparents = { "syspll_divpmcck", }, 333 .eparents_mux_table = { 5, }, 334 .eparents_count = 1, 335 .eparents_chg_id = INT_MIN, 336 }, 337 }; 338 339 /* System clock description */ 340 static const struct { 341 const char *name; 342 const char *parent; 343 uint8_t id; 344 } sama7g5_systemck[] = { 345 { .name = "pck0", .parent = "prog0", .id = 8, }, 346 { .name = "pck1", .parent = "prog1", .id = 9, }, 347 { .name = "pck2", .parent = "prog2", .id = 10, }, 348 { .name = "pck3", .parent = "prog3", .id = 11, }, 349 { .name = "pck4", .parent = "prog4", .id = 12, }, 350 { .name = "pck5", .parent = "prog5", .id = 13, }, 351 { .name = "pck6", .parent = "prog6", .id = 14, }, 352 { .name = "pck7", .parent = "prog7", .id = 15, }, 353 }; 354 355 /* Peripheral clock description */ 356 static const struct { 357 const char *name; 358 const char *parent; 359 struct clk_range output; 360 uint8_t id; 361 } peri_clks[] = { 362 { 363 .name = "pioA_clk", 364 .parent = "mck0", 365 .id = 11, 366 }, 367 { 368 .name = "securam_clk", 369 .parent = "mck0", 370 .id = 18, 371 }, 372 { 373 .name = "sfr_clk", 374 .parent = "mck1", 375 .id = 19, 376 }, 377 { 378 .name = "hsmc_clk", 379 .parent = "mck1", 380 .id = 21, 381 }, 382 { 383 .name = "xdmac0_clk", 384 .parent = "mck1", 385 .id = 22, 386 }, 387 { 388 .name = "xdmac1_clk", 389 .parent = "mck1", 390 .id = 23, 391 }, 392 { 393 .name = "xdmac2_clk", 394 .parent = "mck1", 395 .id = 24, 396 }, 397 { 398 .name = "acc_clk", 399 .parent = "mck1", 400 .id = 25, 401 }, 402 { 403 .name = "aes_clk", 404 .parent = "mck1", 405 .id = 27, 406 }, 407 { 408 .name = "tzaesbasc_clk", 409 .parent = "mck1", 410 .id = 28, 411 }, 412 { 413 .name = "asrc_clk", 414 .parent = "mck1", 415 .id = 30, 416 .output = { .max = 200000000, }, 417 }, 418 { 419 .name = "cpkcc_clk", 420 .parent = "mck0", 421 .id = 32, 422 }, 423 { 424 .name = "csi_clk", 425 .parent = "mck3", 426 .id = 33, 427 .output = { .max = 266000000, }, 428 }, 429 { 430 .name = "csi2dc_clk", 431 .parent = "mck3", 432 .id = 34, 433 .output = { .max = 266000000, }, 434 }, 435 { 436 .name = "eic_clk", 437 .parent = "mck1", 438 .id = 37, 439 }, 440 { 441 .name = "flex0_clk", 442 .parent = "mck1", 443 .id = 38, 444 }, 445 { 446 .name = "flex1_clk", 447 .parent = "mck1", 448 .id = 39, 449 }, 450 { 451 .name = "flex2_clk", 452 .parent = "mck1", 453 .id = 40, 454 }, 455 { 456 .name = "flex3_clk", 457 .parent = "mck1", 458 .id = 41, 459 }, 460 { 461 .name = "flex4_clk", 462 .parent = "mck1", 463 .id = 42, 464 }, 465 { 466 .name = "flex5_clk", 467 .parent = "mck1", 468 .id = 43, 469 }, 470 { 471 .name = "flex6_clk", 472 .parent = "mck1", 473 .id = 44, 474 }, 475 { 476 .name = "flex7_clk", 477 .parent = "mck1", 478 .id = 45, 479 }, 480 { 481 .name = "flex8_clk", 482 .parent = "mck1", 483 .id = 46, 484 }, 485 { 486 .name = "flex9_clk", 487 .parent = "mck1", 488 .id = 47, 489 }, 490 { 491 .name = "flex10_clk", 492 .parent = "mck1", 493 .id = 48, 494 }, 495 { 496 .name = "flex11_clk", 497 .parent = "mck1", 498 .id = 49, 499 }, 500 { 501 .name = "gmac0_clk", 502 .parent = "mck1", 503 .id = 51, 504 }, 505 { 506 .name = "gmac1_clk", 507 .parent = "mck1", 508 .id = 52, 509 }, 510 { 511 .name = "icm_clk", 512 .parent = "mck1", 513 .id = 55, 514 }, 515 { 516 .name = "isc_clk", 517 .parent = "mck3", 518 .id = 56, 519 .output = { .max = 266000000, }, 520 }, 521 { 522 .name = "i2smcc0_clk", 523 .parent = "mck1", 524 .id = 57, 525 .output = { .max = 200000000, }, 526 }, 527 { 528 .name = "i2smcc1_clk", 529 .parent = "mck1", 530 .id = 58, 531 .output = { .max = 200000000, }, 532 }, 533 { 534 .name = "matrix_clk", 535 .parent = "mck1", 536 .id = 60, }, 537 { 538 .name = "mcan0_clk", 539 .parent = "mck1", 540 .id = 61, 541 .output = { .max = 200000000, }, 542 }, 543 { 544 .name = "mcan1_clk", 545 .parent = "mck1", 546 .id = 62, 547 .output = { .max = 200000000, }, 548 }, 549 { 550 .name = "mcan2_clk", 551 .parent = "mck1", 552 .id = 63, 553 .output = { .max = 200000000, }, 554 }, 555 { 556 .name = "mcan3_clk", 557 .parent = "mck1", 558 .id = 64, 559 .output = { .max = 200000000, }, 560 }, 561 { 562 .name = "mcan4_clk", 563 .parent = "mck1", 564 .id = 65, 565 .output = { .max = 200000000, }, 566 }, 567 { 568 .name = "mcan5_clk", 569 .parent = "mck1", 570 .id = 66, 571 .output = { .max = 200000000, }, 572 }, 573 { 574 .name = "pdmc0_clk", 575 .parent = "mck1", 576 .id = 68, 577 .output = { .max = 200000000, }, 578 }, 579 { 580 .name = "pdmc1_clk", 581 .parent = "mck1", 582 .id = 69, 583 .output = { .max = 200000000, }, 584 }, 585 { 586 .name = "pit64b0_clk", 587 .parent = "mck1", 588 .id = 70, 589 }, 590 { 591 .name = "pit64b1_clk", 592 .parent = "mck1", 593 .id = 71, 594 }, 595 { 596 .name = "pit64b2_clk", 597 .parent = "mck1", 598 .id = 72, 599 }, 600 { 601 .name = "pit64b3_clk", 602 .parent = "mck1", 603 .id = 73, 604 }, 605 { 606 .name = "pit64b4_clk", 607 .parent = "mck1", 608 .id = 74, 609 }, 610 { 611 .name = "pit64b5_clk", 612 .parent = "mck1", 613 .id = 75, 614 }, 615 { 616 .name = "pwm_clk", 617 .parent = "mck1", 618 .id = 77, 619 }, 620 { 621 .name = "qspi0_clk", 622 .parent = "mck1", 623 .id = 78, 624 }, 625 { 626 .name = "qspi1_clk", 627 .parent = "mck1", 628 .id = 79, 629 }, 630 { 631 .name = "sdmmc0_clk", 632 .parent = "mck1", 633 .id = 80, 634 }, 635 { 636 .name = "sdmmc1_clk", 637 .parent = "mck1", 638 .id = 81, 639 }, 640 { 641 .name = "sdmmc2_clk", 642 .parent = "mck1", 643 .id = 82, 644 }, 645 { 646 .name = "sha_clk", 647 .parent = "mck1", 648 .id = 83, 649 }, 650 { 651 .name = "spdifrx_clk", 652 .parent = "mck1", 653 .id = 84, 654 .output = { .max = 200000000, }, 655 }, 656 { 657 .name = "spdiftx_clk", 658 .parent = "mck1", 659 .id = 85, 660 .output = { .max = 200000000, }, 661 }, 662 { 663 .name = "ssc0_clk", 664 .parent = "mck1", 665 .id = 86, 666 .output = { .max = 200000000, }, 667 }, 668 { 669 .name = "ssc1_clk", 670 .parent = "mck1", 671 .id = 87, 672 .output = { .max = 200000000, }, 673 }, 674 { 675 .name = "tcb0_ch0_clk", 676 .parent = "mck1", 677 .id = 88, 678 .output = { .max = 200000000, }, 679 }, 680 { 681 .name = "tcb0_ch1_clk", 682 .parent = "mck1", 683 .id = 89, 684 .output = { .max = 200000000, }, 685 }, 686 { 687 .name = "tcb0_ch2_clk", 688 .parent = "mck1", 689 .id = 90, 690 .output = { .max = 200000000, }, 691 }, 692 { 693 .name = "tcb1_ch0_clk", 694 .parent = "mck1", 695 .id = 91, 696 .output = { .max = 200000000, }, 697 }, 698 { 699 .name = "tcb1_ch1_clk", 700 .parent = "mck1", 701 .id = 92, 702 .output = { .max = 200000000, }, 703 }, 704 { 705 .name = "tcb1_ch2_clk", 706 .parent = "mck1", 707 .id = 93, 708 .output = { .max = 200000000, }, 709 }, 710 { 711 .name = "tcpca_clk", 712 .parent = "mck1", 713 .id = 94, 714 }, 715 { 716 .name = "tcpcb_clk", 717 .parent = "mck1", 718 .id = 95, 719 }, 720 { 721 .name = "tdes_clk", 722 .parent = "mck1", 723 .id = 96, 724 }, 725 { 726 .name = "trng_clk", 727 .parent = "mck1", 728 .id = 97, 729 }, 730 { 731 .name = "udphsa_clk", 732 .parent = "mck1", 733 .id = 104, 734 }, 735 { 736 .name = "udphsb_clk", 737 .parent = "mck1", 738 .id = 105, 739 }, 740 { 741 .name = "uhphs_clk", 742 .parent = "mck1", 743 .id = 106, 744 }, 745 }; 746 747 /* UTMI clock description */ 748 static struct { 749 const char *name; 750 const char *parent; 751 uint8_t id; 752 } sama7_utmick[] = { 753 { .name = "utmi1ck", .parent = "utmick", .id = 0, }, 754 { .name = "utmi2ck", .parent = "utmi1ck", .id = 1, }, 755 { .name = "utmi3ck", .parent = "utmi1ck", .id = 2, }, 756 }; 757 758 /* Generic clock description */ 759 struct sama7g5_gck { 760 const char *name; 761 const char *parents[8]; 762 const char parents_mux_table[8]; 763 struct clk_range output; 764 int parents_chg_id; /* id in parent array of changeable PLL parent */ 765 uint8_t parents_count; 766 uint8_t id; 767 }; 768 769 static const struct sama7g5_gck sama7g5_gcks[] = { 770 { 771 .name = "adc_gclk", 772 .id = 26, 773 .output = { .max = 100000000, }, 774 .parents = { "syspll_divpmcck", 775 "imgpll_divpmcck", 776 "audiopll_divck", }, 777 .parents_mux_table = { 5, 7, 9, }, 778 .parents_count = 3, 779 .parents_chg_id = INT_MIN, 780 }, 781 { 782 .name = "asrc_gclk", 783 .id = 30, 784 .output = { .max = 200000000 }, 785 .parents = { "audiopll_divck", }, 786 .parents_mux_table = { 9, }, 787 .parents_count = 1, 788 .parents_chg_id = INT_MIN, 789 }, 790 { 791 .name = "csi_gclk", 792 .id = 33, 793 .output = { .max = 27000000 }, 794 .parents = { "ddrpll_divpmcck", "imgpll_divpmcck", }, 795 .parents_mux_table = { 6, 7, }, 796 .parents_count = 2, 797 .parents_chg_id = INT_MIN, 798 }, 799 { 800 .name = "flex0_gclk", 801 .id = 38, 802 .output = { .max = 200000000 }, 803 .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, 804 .parents_mux_table = { 5, 8, }, 805 .parents_count = 2, 806 .parents_chg_id = INT_MIN, 807 }, 808 { 809 .name = "flex1_gclk", 810 .id = 39, 811 .output = { .max = 200000000 }, 812 .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, 813 .parents_mux_table = { 5, 8, }, 814 .parents_count = 2, 815 .parents_chg_id = INT_MIN, 816 }, 817 { 818 .name = "flex2_gclk", 819 .id = 40, 820 .output = { .max = 200000000 }, 821 .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, 822 .parents_mux_table = { 5, 8, }, 823 .parents_count = 2, 824 .parents_chg_id = INT_MIN, 825 }, 826 { 827 .name = "flex3_gclk", 828 .id = 41, 829 .output = { .max = 200000000 }, 830 .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, 831 .parents_mux_table = { 5, 8, }, 832 .parents_count = 2, 833 .parents_chg_id = INT_MIN, 834 }, 835 { 836 .name = "flex4_gclk", 837 .id = 42, 838 .output = { .max = 200000000 }, 839 .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, 840 .parents_mux_table = { 5, 8, }, 841 .parents_count = 2, 842 .parents_chg_id = INT_MIN, 843 }, 844 { 845 .name = "flex5_gclk", 846 .id = 43, 847 .output = { .max = 200000000 }, 848 .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, 849 .parents_mux_table = { 5, 8, }, 850 .parents_count = 2, 851 .parents_chg_id = INT_MIN, 852 }, 853 { 854 .name = "flex6_gclk", 855 .id = 44, 856 .output = { .max = 200000000 }, 857 .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, 858 .parents_mux_table = { 5, 8, }, 859 .parents_count = 2, 860 .parents_chg_id = INT_MIN, 861 }, 862 { 863 .name = "flex7_gclk", 864 .id = 45, 865 .output = { .max = 200000000 }, 866 .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, 867 .parents_mux_table = { 5, 8, }, 868 .parents_count = 2, 869 .parents_chg_id = INT_MIN, 870 }, 871 { 872 .name = "flex8_gclk", 873 .id = 46, 874 .output = { .max = 200000000 }, 875 .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, 876 .parents_mux_table = { 5, 8, }, 877 .parents_count = 2, 878 .parents_chg_id = INT_MIN, 879 }, 880 { 881 .name = "flex9_gclk", 882 .id = 47, 883 .output = { .max = 200000000 }, 884 .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, 885 .parents_mux_table = { 5, 8, }, 886 .parents_count = 2, 887 .parents_chg_id = INT_MIN, 888 }, 889 { 890 .name = "flex10_gclk", 891 .id = 48, 892 .output = { .max = 200000000 }, 893 .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, 894 .parents_mux_table = { 5, 8, }, 895 .parents_count = 2, 896 .parents_chg_id = INT_MIN, 897 }, 898 { 899 .name = "flex11_gclk", 900 .id = 49, 901 .output = { .max = 200000000 }, 902 .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, 903 .parents_mux_table = { 5, 8, }, 904 .parents_count = 2, 905 .parents_chg_id = INT_MIN, 906 }, 907 { 908 .name = "gmac0_gclk", 909 .id = 51, 910 .output = { .max = 125000000 }, 911 .parents = { "ethpll_divpmcck", }, 912 .parents_mux_table = { 10, }, 913 .parents_count = 1, 914 .parents_chg_id = 3, 915 }, 916 { 917 .name = "gmac1_gclk", 918 .id = 52, 919 .output = { .max = 50000000 }, 920 .parents = { "ethpll_divpmcck", }, 921 .parents_mux_table = { 10, }, 922 .parents_count = 1, 923 .parents_chg_id = INT_MIN, 924 }, 925 { 926 .name = "gmac0_tsu_gclk", 927 .id = 53, 928 .output = { .max = 300000000 }, 929 .parents = { "audiopll_divck", "ethpll_divpmcck", }, 930 .parents_mux_table = { 9, 10, }, 931 .parents_count = 2, 932 .parents_chg_id = INT_MIN, 933 }, 934 { 935 .name = "gmac1_tsu_gclk", 936 .id = 54, 937 .output = { .max = 300000000 }, 938 .parents = { "audiopll_divck", "ethpll_divpmcck", }, 939 .parents_mux_table = { 9, 10, }, 940 .parents_count = 2, 941 .parents_chg_id = INT_MIN, 942 }, 943 { 944 .name = "i2smcc0_gclk", 945 .id = 57, 946 .output = { .max = 100000000 }, 947 .parents = { "syspll_divpmcck", "audiopll_divck", }, 948 .parents_mux_table = { 5, 9, }, 949 .parents_count = 2, 950 .parents_chg_id = INT_MIN, 951 }, 952 { 953 .name = "i2smcc1_gclk", 954 .id = 58, 955 .output = { .max = 100000000 }, 956 .parents = { "syspll_divpmcck", "audiopll_divck", }, 957 .parents_mux_table = { 5, 9, }, 958 .parents_count = 2, 959 .parents_chg_id = INT_MIN, 960 }, 961 { 962 .name = "mcan0_gclk", 963 .id = 61, 964 .output = { .max = 200000000 }, 965 .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, 966 .parents_mux_table = { 5, 8, }, 967 .parents_count = 2, 968 .parents_chg_id = INT_MIN, 969 }, 970 { 971 .name = "mcan1_gclk", 972 .id = 62, 973 .output = { .max = 200000000 }, 974 .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, 975 .parents_mux_table = { 5, 8, }, 976 .parents_count = 2, 977 .parents_chg_id = INT_MIN, 978 }, 979 { 980 .name = "mcan2_gclk", 981 .id = 63, 982 .output = { .max = 200000000 }, 983 .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, 984 .parents_mux_table = { 5, 8, }, 985 .parents_count = 2, 986 .parents_chg_id = INT_MIN, 987 }, 988 { 989 .name = "mcan3_gclk", 990 .id = 64, 991 .output = { .max = 200000000 }, 992 .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, 993 .parents_mux_table = { 5, 8, }, 994 .parents_count = 2, 995 .parents_chg_id = INT_MIN, 996 }, 997 { 998 .name = "mcan4_gclk", 999 .id = 65, 1000 .output = { .max = 200000000 }, 1001 .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, 1002 .parents_mux_table = { 5, 8, }, 1003 .parents_count = 2, 1004 .parents_chg_id = INT_MIN, 1005 }, 1006 { 1007 .name = "mcan5_gclk", 1008 .id = 66, 1009 .output = { .max = 200000000 }, 1010 .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, 1011 .parents_mux_table = { 5, 8, }, 1012 .parents_count = 2, 1013 .parents_chg_id = INT_MIN, 1014 }, 1015 { 1016 .name = "pdmc0_gclk", 1017 .id = 68, 1018 .output = { .max = 50000000 }, 1019 .parents = { "syspll_divpmcck", "audiopll_divck", }, 1020 .parents_mux_table = { 5, 9, }, 1021 .parents_count = 2, 1022 .parents_chg_id = INT_MIN, 1023 }, 1024 { 1025 .name = "pdmc1_gclk", 1026 .id = 69, 1027 .output = { .max = 50000000, }, 1028 .parents = { "syspll_divpmcck", "audiopll_divck", }, 1029 .parents_mux_table = { 5, 9, }, 1030 .parents_count = 2, 1031 .parents_chg_id = INT_MIN, 1032 }, 1033 { 1034 .name = "pit64b0_gclk", 1035 .id = 70, 1036 .output = { .max = 200000000 }, 1037 .parents = { "syspll_divpmcck", "imgpll_divpmcck", 1038 "baudpll_divpmcck", "audiopll_divck", 1039 "ethpll_divpmcck", }, 1040 .parents_mux_table = { 5, 7, 8, 9, 10, }, 1041 .parents_count = 5, 1042 .parents_chg_id = INT_MIN, 1043 }, 1044 { 1045 .name = "pit64b1_gclk", 1046 .id = 71, 1047 .output = { .max = 200000000 }, 1048 .parents = { "syspll_divpmcck", "imgpll_divpmcck", 1049 "baudpll_divpmcck", "audiopll_divck", 1050 "ethpll_divpmcck", }, 1051 .parents_mux_table = { 5, 7, 8, 9, 10, }, 1052 .parents_count = 5, 1053 .parents_chg_id = INT_MIN, 1054 }, 1055 { 1056 .name = "pit64b2_gclk", 1057 .id = 72, 1058 .output = { .max = 200000000 }, 1059 .parents = { "syspll_divpmcck", "imgpll_divpmcck", 1060 "baudpll_divpmcck", "audiopll_divck", 1061 "ethpll_divpmcck", }, 1062 .parents_mux_table = { 5, 7, 8, 9, 10, }, 1063 .parents_count = 5, 1064 .parents_chg_id = INT_MIN, 1065 }, 1066 { 1067 .name = "pit64b3_gclk", 1068 .id = 73, 1069 .output = { .max = 200000000 }, 1070 .parents = { "syspll_divpmcck", "imgpll_divpmcck", 1071 "baudpll_divpmcck", "audiopll_divck", 1072 "ethpll_divpmcck", }, 1073 .parents_mux_table = { 5, 7, 8, 9, 10, }, 1074 .parents_count = 5, 1075 .parents_chg_id = INT_MIN, 1076 }, 1077 { 1078 .name = "pit64b4_gclk", 1079 .id = 74, 1080 .output = { .max = 200000000 }, 1081 .parents = { "syspll_divpmcck", "imgpll_divpmcck", 1082 "baudpll_divpmcck", "audiopll_divck", 1083 "ethpll_divpmcck", }, 1084 .parents_mux_table = { 5, 7, 8, 9, 10, }, 1085 .parents_count = 5, 1086 .parents_chg_id = INT_MIN, 1087 }, 1088 { 1089 .name = "pit64b5_gclk", 1090 .id = 75, 1091 .output = { .max = 200000000 }, 1092 .parents = { "syspll_divpmcck", "imgpll_divpmcck", 1093 "baudpll_divpmcck", "audiopll_divck", 1094 "ethpll_divpmcck", }, 1095 .parents_mux_table = { 5, 7, 8, 9, 10, }, 1096 .parents_count = 5, 1097 .parents_chg_id = INT_MIN, 1098 }, 1099 { 1100 .name = "qspi0_gclk", 1101 .id = 78, 1102 .output = { .max = 200000000 }, 1103 .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, 1104 .parents_mux_table = { 5, 8, }, 1105 .parents_count = 2, 1106 .parents_chg_id = INT_MIN, 1107 }, 1108 { 1109 .name = "qspi1_gclk", 1110 .id = 79, 1111 .output = { .max = 200000000 }, 1112 .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, 1113 .parents_mux_table = { 5, 8, }, 1114 .parents_count = 2, 1115 .parents_chg_id = INT_MIN, 1116 }, 1117 { 1118 .name = "sdmmc0_gclk", 1119 .id = 80, 1120 .output = { .max = 208000000 }, 1121 .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, 1122 .parents_mux_table = { 5, 8, }, 1123 .parents_count = 2, 1124 .parents_chg_id = 4, 1125 }, 1126 { 1127 .name = "sdmmc1_gclk", 1128 .id = 81, 1129 .output = { .max = 208000000 }, 1130 .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, 1131 .parents_mux_table = { 5, 8, }, 1132 .parents_count = 2, 1133 .parents_chg_id = 4, 1134 }, 1135 { 1136 .name = "sdmmc2_gclk", 1137 .id = 82, 1138 .output = { .max = 208000000 }, 1139 .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, 1140 .parents_mux_table = { 5, 8, }, 1141 .parents_count = 2, 1142 .parents_chg_id = 4, 1143 }, 1144 { 1145 .name = "spdifrx_gclk", 1146 .id = 84, 1147 .output = { .max = 150000000 }, 1148 .parents = { "syspll_divpmcck", "audiopll_divck", }, 1149 .parents_mux_table = { 5, 9, }, 1150 .parents_count = 2, 1151 .parents_chg_id = INT_MIN, 1152 }, 1153 { 1154 .name = "spdiftx_gclk", 1155 .id = 85, 1156 .output = { .max = 25000000 }, 1157 .parents = { "syspll_divpmcck", "audiopll_divck", }, 1158 .parents_mux_table = { 5, 9, }, 1159 .parents_count = 2, 1160 .parents_chg_id = INT_MIN, 1161 }, 1162 { 1163 .name = "tcb0_ch0_gclk", 1164 .id = 88, 1165 .output = { .max = 200000000 }, 1166 .parents = { "syspll_divpmcck", "imgpll_divpmcck", 1167 "baudpll_divpmcck", "audiopll_divck", 1168 "ethpll_divpmcck", }, 1169 .parents_mux_table = { 5, 7, 8, 9, 10, }, 1170 .parents_count = 5, 1171 .parents_chg_id = INT_MIN, 1172 }, 1173 { 1174 .name = "tcb1_ch0_gclk", 1175 .id = 91, 1176 .output = { .max = 200000000 }, 1177 .parents = { "syspll_divpmcck", "imgpll_divpmcck", 1178 "baudpll_divpmcck", "audiopll_divck", 1179 "ethpll_divpmcck", }, 1180 .parents_mux_table = { 5, 7, 8, 9, 10, }, 1181 .parents_count = 5, 1182 .parents_chg_id = INT_MIN, 1183 }, 1184 { 1185 .name = "tcpca_gclk", 1186 .id = 94, 1187 .output = { .max = 32768, }, 1188 .parents_chg_id = INT_MIN, 1189 }, 1190 { 1191 .name = "tcpcb_gclk", 1192 .id = 95, 1193 .output = { .max = 32768, }, 1194 .parents_chg_id = INT_MIN, 1195 }, 1196 }; 1197 1198 /* MCK0 characteristics */ 1199 static const struct clk_master_charac mck0_characteristics = { 1200 .output = { .min = 32768, .max = 200000000 }, 1201 .divisors = { 1, 2, 4, 3, 5 }, 1202 .have_div3_pres = 1, 1203 }; 1204 1205 /* MCK0 layout */ 1206 static const struct clk_master_layout mck0_layout = { 1207 .mask = 0x773, 1208 .pres_shift = 4, 1209 .offset = 0x28, 1210 }; 1211 1212 /* Peripheral clock layout */ 1213 static const struct clk_pcr_layout sama7g5_pcr_layout = { 1214 .offset = 0x88, 1215 .cmd = BIT(31), 1216 .div_mask = GENMASK_32(27, 20), 1217 .gckcss_mask = GENMASK_32(12, 8), 1218 .pid_mask = GENMASK_32(6, 0), 1219 }; 1220 1221 static const struct clk_programmable_layout sama7g5_prog_layout = { 1222 .pres_mask = 0xff, 1223 .pres_shift = 8, 1224 .css_mask = GENMASK_32(4, 0), 1225 .have_slck_mck = 0, 1226 .is_pres_direct = 1, 1227 }; 1228 1229 static const struct { 1230 const char *name; 1231 uint8_t id; 1232 } sama7g5_progck[] = { 1233 { .name = "prog0", .id = 0 }, 1234 { .name = "prog1", .id = 1 }, 1235 { .name = "prog2", .id = 2 }, 1236 { .name = "prog3", .id = 3 }, 1237 { .name = "prog4", .id = 4 }, 1238 { .name = "prog5", .id = 5 }, 1239 { .name = "prog6", .id = 6 }, 1240 { .name = "prog7", .id = 7 }, 1241 }; 1242 1243 static struct pmc_data *sama7g5_pmc; 1244 1245 vaddr_t at91_pmc_get_base(void) 1246 { 1247 assert(sama7g5_pmc); 1248 1249 return sama7g5_pmc->base; 1250 } 1251 1252 TEE_Result at91_pmc_clk_get(unsigned int type, unsigned int idx, 1253 struct clk **clk) 1254 { 1255 return pmc_clk_get(sama7g5_pmc, type, idx, clk); 1256 } 1257 1258 static TEE_Result pmc_setup_sama7g5(const void *fdt, int nodeoffset, 1259 const void *data __unused) 1260 { 1261 struct clk *pll_frac_clk[PLL_ID_MAX] = { }; 1262 struct clk *pll_div_clk[PLL_ID_MAX] = { }; 1263 TEE_Result res = TEE_ERROR_GENERIC; 1264 const uint32_t *fdt_prop = NULL; 1265 struct pmc_clk *pmc_clk = NULL; 1266 struct clk *parents[11] = { }; 1267 struct clk *main_xtal_clk = NULL; 1268 struct clk *main_rc_osc = NULL; 1269 struct clk *main_osc = NULL; 1270 struct clk *mck0_clk = NULL; 1271 struct clk *main_clk = NULL; 1272 struct clk *md_slck = NULL; 1273 struct clk *td_slck = NULL; 1274 struct clk *parent = NULL; 1275 struct clk *clk = NULL; 1276 unsigned int i = 0; 1277 unsigned int j = 0; 1278 vaddr_t base = 0; 1279 size_t size = 0; 1280 int bypass = 0; 1281 1282 if (dt_map_dev(fdt, nodeoffset, &base, &size, DT_MAP_AUTO) < 0) 1283 panic(); 1284 1285 if (fdt_get_status(fdt, nodeoffset) == DT_STATUS_OK_SEC) 1286 matrix_configure_periph_secure(ID_PMC); 1287 1288 res = clk_dt_get_by_name(fdt, nodeoffset, "md_slck", &md_slck); 1289 if (res) 1290 return res; 1291 1292 res = clk_dt_get_by_name(fdt, nodeoffset, "td_slck", &td_slck); 1293 if (res) 1294 return res; 1295 1296 res = clk_dt_get_by_name(fdt, nodeoffset, "main_xtal", &main_xtal_clk); 1297 if (res) 1298 return res; 1299 1300 sama7g5_pmc = pmc_data_allocate(PMC_SAMA7G5_CORE_CLK_COUNT, 1301 ARRAY_SIZE(sama7g5_systemck), 1302 ARRAY_SIZE(peri_clks), 1303 ARRAY_SIZE(sama7g5_gcks), 8); 1304 if (!sama7g5_pmc) 1305 panic(); 1306 1307 sama7g5_pmc->base = base; 1308 1309 main_rc_osc = pmc_register_main_rc_osc(sama7g5_pmc, "main_rc_osc", 1310 12000000); 1311 if (!main_rc_osc) 1312 panic(); 1313 1314 fdt_prop = fdt_getprop(fdt, nodeoffset, "atmel,osc-bypass", NULL); 1315 if (fdt_prop) 1316 bypass = fdt32_to_cpu(*fdt_prop); 1317 1318 main_osc = pmc_register_main_osc(sama7g5_pmc, "main_osc", 1319 main_xtal_clk, bypass); 1320 if (!main_osc) 1321 panic(); 1322 1323 parents[0] = main_rc_osc; 1324 parents[1] = main_osc; 1325 main_clk = at91_clk_register_sam9x5_main(sama7g5_pmc, "mainck", 1326 parents, 2); 1327 if (!main_clk) 1328 panic(); 1329 pmc_clk = &sama7g5_pmc->chws[PMC_MAIN]; 1330 pmc_clk->clk = main_clk; 1331 pmc_clk->id = PMC_MAIN; 1332 1333 for (i = 0; i < PLL_ID_MAX; i++) { 1334 struct pmc_data *pmc = sama7g5_pmc; 1335 const struct sama7g5_pll *p = NULL; 1336 1337 for (j = 0; j < 3; j++) { 1338 p = &sama7g5_plls[i][j]; 1339 if (!p->name) 1340 continue; 1341 1342 switch (p->type) { 1343 case PLL_TYPE_FRAC: 1344 if (!strcmp(p->parent, "mainck")) 1345 parent = main_clk; 1346 else if (!strcmp(p->parent, "main_xtal")) 1347 parent = main_xtal_clk; 1348 else 1349 parent = pmc_clk_get_by_name(pmc->chws, 1350 pmc->ncore, 1351 p->parent); 1352 assert(parent); 1353 1354 clk = sam9x60_clk_register_frac_pll(sama7g5_pmc, 1355 p->name, 1356 parent, i, 1357 p->charac, 1358 p->layout, 1359 p->flags); 1360 pll_frac_clk[i] = clk; 1361 break; 1362 1363 case PLL_TYPE_DIV: 1364 parent = clk; 1365 clk = sam9x60_clk_register_div_pll(sama7g5_pmc, 1366 p->name, 1367 parent, i, 1368 p->charac, 1369 p->layout, 1370 p->flags, 1371 p->safe_div); 1372 break; 1373 1374 default: 1375 continue; 1376 } 1377 if (!clk) 1378 panic(); 1379 1380 if (p->eid) { 1381 sama7g5_pmc->chws[p->eid].clk = clk; 1382 sama7g5_pmc->chws[p->eid].id = p->eid; 1383 sam_set_clock_range(PMC_TYPE_CORE, p->eid, 1384 p->charac->output); 1385 } 1386 } 1387 p = &sama7g5_plls[i][PLL_TYPE_DIV]; 1388 pll_div_clk[i] = sama7g5_pmc->chws[p->eid].clk; 1389 } 1390 1391 parents[0] = md_slck; 1392 parents[1] = main_clk; 1393 parents[2] = pll_div_clk[PLL_ID_CPU]; 1394 parents[3] = pll_div_clk[PLL_ID_SYS]; 1395 clk = at91_clk_register_master_pres(sama7g5_pmc, "fclk", 4, 1396 parents, 1397 &mck0_layout, 1398 &mck0_characteristics, INT_MIN); 1399 if (!clk) 1400 panic(); 1401 pmc_clk = &sama7g5_pmc->chws[PMC_MCK_PRES]; 1402 pmc_clk->clk = clk; 1403 pmc_clk->id = PMC_MCK_PRES; 1404 1405 mck0_clk = at91_clk_register_master_div(sama7g5_pmc, "mck0", 1406 clk, 1407 &mck0_layout, 1408 &mck0_characteristics); 1409 if (!mck0_clk) 1410 panic(); 1411 pmc_clk = &sama7g5_pmc->chws[PMC_MCK]; 1412 pmc_clk->clk = mck0_clk; 1413 pmc_clk->id = PMC_MCK; 1414 sam_set_clock_range(PMC_TYPE_SYSTEM, PMC_MCK, 1415 &mck0_characteristics.output); 1416 1417 parents[0] = md_slck; 1418 parents[1] = td_slck; 1419 parents[2] = main_clk; 1420 parents[3] = mck0_clk; 1421 for (i = 0; i < ARRAY_SIZE(sama7g5_mckx); i++) { 1422 const struct sama7g5_mck *mck = &sama7g5_mckx[i]; 1423 uint8_t num_parents = 4 + mck->eparents_count; 1424 uint32_t *mux_table = calloc(num_parents, sizeof(*mux_table)); 1425 1426 if (!mux_table) 1427 panic(); 1428 1429 mux_table[0] = 0; 1430 mux_table[1] = 1; 1431 mux_table[2] = 2; 1432 mux_table[3] = 3; 1433 for (j = 0; j < mck->eparents_count; j++) { 1434 parents[4 + j] = pmc_clk_get_by_name(sama7g5_pmc->chws, 1435 sama7g5_pmc->ncore, 1436 mck->eparents[j]); 1437 assert(parents[4 + j]); 1438 mux_table[4 + j] = mck->eparents_mux_table[j]; 1439 } 1440 1441 clk = at91_clk_sama7g5_register_master(sama7g5_pmc, 1442 mck->name, 1443 num_parents, parents, 1444 mux_table, 1445 mck->id, 1446 mck->eparents_chg_id); 1447 if (!clk) 1448 panic(); 1449 1450 sama7g5_pmc->chws[PMC_MCK1 + i].clk = clk; 1451 } 1452 1453 clk = at91_clk_sama7g5_register_utmi(sama7g5_pmc, "utmick", main_clk); 1454 if (!clk) 1455 panic(); 1456 sama7g5_pmc->chws[PMC_UTMI].clk = clk; 1457 sama7g5_pmc->chws[PMC_UTMI].id = PMC_UTMI; 1458 1459 for (i = 0; i < ARRAY_SIZE(sama7_utmick); i++) { 1460 if (strcmp("utmick", sama7_utmick[i].parent) == 0) 1461 parent = clk; 1462 else if (strcmp("utmi1ck", sama7_utmick[i].parent) == 0) 1463 parent = sama7g5_pmc->chws[PMC_UTMI1].clk; 1464 else 1465 panic(); 1466 clk = sama7_utmi_clk_register(sama7_utmick[i].name, parent, 1467 sama7_utmick[i].id); 1468 if (!clk) 1469 panic(); 1470 1471 pmc_clk = &sama7g5_pmc->chws[PMC_UTMI1 + i]; 1472 pmc_clk->clk = clk; 1473 pmc_clk->id = PMC_UTMI1 + i; 1474 } 1475 1476 parents[0] = md_slck; 1477 parents[1] = td_slck; 1478 parents[2] = main_clk; 1479 parents[3] = pll_div_clk[PLL_ID_SYS]; 1480 parents[4] = pll_div_clk[PLL_ID_DDR]; 1481 parents[5] = pll_div_clk[PLL_ID_IMG]; 1482 parents[6] = pll_div_clk[PLL_ID_BAUD]; 1483 parents[7] = pll_div_clk[PLL_ID_AUDIO]; 1484 parents[8] = pll_div_clk[PLL_ID_ETH]; 1485 for (i = 0; i < ARRAY_SIZE(sama7g5_progck); i++) { 1486 clk = at91_clk_register_programmable(sama7g5_pmc, 1487 sama7g5_progck[i].name, 1488 parents, 9, i, 1489 &sama7g5_prog_layout); 1490 if (!clk) 1491 panic(); 1492 1493 pmc_clk = &sama7g5_pmc->pchws[i]; 1494 pmc_clk->clk = clk; 1495 pmc_clk->id = sama7g5_progck[i].id; 1496 } 1497 1498 for (i = 0; i < ARRAY_SIZE(sama7g5_systemck); i++) { 1499 clk = at91_clk_register_system(sama7g5_pmc, 1500 sama7g5_systemck[i].name, 1501 sama7g5_pmc->pchws[i].clk, 1502 sama7g5_systemck[i].id); 1503 if (!clk) 1504 panic(); 1505 1506 pmc_clk = &sama7g5_pmc->shws[i]; 1507 pmc_clk->clk = clk; 1508 pmc_clk->id = sama7g5_systemck[i].id; 1509 } 1510 1511 for (i = 0; i < ARRAY_SIZE(peri_clks); i++) { 1512 parent = pmc_clk_get_by_name(sama7g5_pmc->chws, 1513 sama7g5_pmc->ncore, 1514 peri_clks[i].parent); 1515 clk = at91_clk_register_sam9x5_periph(sama7g5_pmc, 1516 &sama7g5_pcr_layout, 1517 peri_clks[i].name, 1518 parent, 1519 peri_clks[i].id, 1520 &peri_clks[i].output); 1521 if (!clk) 1522 panic(); 1523 1524 pmc_clk = &sama7g5_pmc->phws[i]; 1525 pmc_clk->clk = clk; 1526 pmc_clk->id = peri_clks[i].id; 1527 1528 sam_set_clock_range(PMC_TYPE_PERIPHERAL, peri_clks[i].id, 1529 &peri_clks[i].output); 1530 } 1531 1532 parents[0] = md_slck; 1533 parents[1] = td_slck; 1534 parents[2] = main_clk; 1535 for (i = 0; i < ARRAY_SIZE(sama7g5_gcks); i++) { 1536 const struct sama7g5_gck *gck = sama7g5_gcks + i; 1537 uint8_t num_parents = 3 + gck->parents_count; 1538 uint32_t *mux_table = calloc(num_parents, sizeof(*mux_table)); 1539 1540 if (!mux_table) 1541 panic(); 1542 1543 mux_table[0] = 0; 1544 mux_table[1] = 1; 1545 mux_table[2] = 2; 1546 for (j = 0; j < gck->parents_count; j++) { 1547 parents[3 + j] = pmc_clk_get_by_name(sama7g5_pmc->chws, 1548 sama7g5_pmc->ncore, 1549 gck->parents[j]); 1550 assert(parents[3 + j]); 1551 mux_table[3 + j] = gck->parents_mux_table[j]; 1552 } 1553 1554 clk = at91_clk_register_generated(sama7g5_pmc, 1555 &sama7g5_pcr_layout, 1556 gck->name, parents, 1557 mux_table, 1558 num_parents, gck->id, 1559 &gck->output, 1560 gck->parents_chg_id); 1561 if (!clk) 1562 panic(); 1563 1564 pmc_clk = &sama7g5_pmc->ghws[i]; 1565 pmc_clk->clk = clk; 1566 pmc_clk->id = gck->id; 1567 1568 sam_set_clock_range(PMC_TYPE_GCK, gck->id, &gck->output); 1569 } 1570 1571 res = clk_set_rate(pll_frac_clk[PLL_ID_ETH], 625000000); 1572 if (res) 1573 panic(); 1574 1575 res = clk_set_rate(pll_div_clk[PLL_ID_ETH], 625000000); 1576 if (res) 1577 panic(); 1578 1579 res = clk_set_rate(pll_frac_clk[PLL_ID_AUDIO], 983040000); 1580 if (res) 1581 panic(); 1582 1583 res = clk_set_rate(pll_div_clk[PLL_ID_AUDIO], 196608000); 1584 if (res) 1585 panic(); 1586 1587 clk = pmc_clk_get_by_name(sama7g5_pmc->ghws, sama7g5_pmc->ngck, 1588 "pdmc0_gclk"); 1589 assert(clk); 1590 res = clk_set_parent(clk, pll_div_clk[PLL_ID_AUDIO]); 1591 if (res) 1592 panic(); 1593 1594 clk = pmc_clk_get_by_name(sama7g5_pmc->ghws, sama7g5_pmc->ngck, 1595 "i2smcc0_gclk"); 1596 assert(clk); 1597 res = clk_set_parent(clk, pll_div_clk[PLL_ID_AUDIO]); 1598 if (res) 1599 panic(); 1600 1601 res = clk_dt_register_clk_provider(fdt, nodeoffset, clk_dt_pmc_get, 1602 sama7g5_pmc); 1603 if (res) 1604 panic(); 1605 1606 pmc_register_pm(); 1607 1608 return TEE_SUCCESS; 1609 } 1610 1611 CLK_DT_DECLARE(sama7g5_clk, "microchip,sama7g5-pmc", pmc_setup_sama7g5); 1612