1 // SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause 2 /* 3 * Copyright (c) 2021, Microchip 4 */ 5 #include <assert.h> 6 #include <kernel/boot.h> 7 #include <libfdt.h> 8 #include <kernel/dt.h> 9 #include <kernel/panic.h> 10 #include <matrix.h> 11 #include <sama5d2.h> 12 #include <stdint.h> 13 #include <util.h> 14 15 #include "at91_clk.h" 16 17 #include <dt-bindings/clock/at91.h> 18 19 #define PROGCK_PARENT_COUNT 6 20 #define PARENT_SIZE ARRAY_SIZE(sama5d2_systemck) 21 22 struct sam_clk { 23 const char *n; 24 uint8_t id; 25 }; 26 27 static const struct clk_master_charac mck_charac = { 28 .output = { .min = 124000000, .max = 166000000 }, 29 .divisors = { 1, 2, 4, 3 }, 30 }; 31 32 static uint8_t plla_out[1]; 33 34 static uint16_t plla_icpll[1]; 35 36 static const struct clk_range plla_outputs[] = { 37 { .min = 600000000, .max = 1200000000 }, 38 }; 39 40 static const struct clk_pll_charac plla_charac = { 41 .input = { .min = 12000000, .max = 24000000 }, 42 .num_output = ARRAY_SIZE(plla_outputs), 43 .output = plla_outputs, 44 .icpll = plla_icpll, 45 .out = plla_out, 46 }; 47 48 static const struct clk_pcr_layout sama5d2_pcr_layout = { 49 .offset = 0x10c, 50 .cmd = BIT(12), 51 .gckcss_mask = GENMASK_32(10, 8), 52 .pid_mask = GENMASK_32(6, 0), 53 }; 54 55 static const struct clk_programmable_layout sama5d2_prog_layout = { 56 .pres_mask = 0xff, 57 .pres_shift = 4, 58 .css_mask = 0x7, 59 .have_slck_mck = 0, 60 .is_pres_direct = 1, 61 }; 62 63 static const struct sam_clk sama5d2_systemck[] = { 64 { .n = "ddrck", .id = 2 }, 65 { .n = "lcdck", .id = 3 }, 66 { .n = "uhpck", .id = 6 }, 67 { .n = "udpck", .id = 7 }, 68 { .n = "pck0", .id = 8 }, 69 { .n = "pck1", .id = 9 }, 70 { .n = "pck2", .id = 10 }, 71 { .n = "iscck", .id = 18 }, 72 }; 73 74 static const struct { 75 struct sam_clk clk; 76 struct clk_range r; 77 } sama5d2_peri32ck[] = { 78 { 79 .clk = { .n = "macb0_clk", .id = 5 }, 80 .r = { .min = 0, .max = 83000000 }, 81 }, 82 { 83 .clk = { .n = "tdes_clk", .id = 11 }, 84 .r = { .min = 0, .max = 83000000 }, 85 }, 86 { 87 .clk = { .n = "matrix1_clk", .id = 14 }, 88 }, 89 { 90 .clk = { .n = "hsmc_clk", .id = 17 }, 91 }, 92 { 93 .clk = { .n = "pioA_clk", .id = 18 }, 94 .r = { .min = 0, .max = 83000000 }, 95 }, 96 { 97 .clk = { .n = "flx0_clk", .id = 19 }, 98 .r = { .min = 0, .max = 83000000 }, 99 }, 100 { 101 .clk = { .n = "flx1_clk", .id = 20 }, 102 .r = { .min = 0, .max = 83000000 }, 103 }, 104 { 105 .clk = { .n = "flx2_clk", .id = 21 }, 106 .r = { .min = 0, .max = 83000000 }, 107 }, 108 { 109 .clk = { .n = "flx3_clk", .id = 22 }, 110 .r = { .min = 0, .max = 83000000 }, 111 }, 112 { 113 .clk = { .n = "flx4_clk", .id = 23 }, 114 .r = { .min = 0, .max = 83000000 }, 115 }, 116 { 117 .clk = { .n = "uart0_clk", .id = 24 }, 118 .r = { .min = 0, .max = 83000000 }, 119 }, 120 { 121 .clk = { .n = "uart1_clk", .id = 25 }, 122 .r = { .min = 0, .max = 83000000 }, 123 }, 124 { 125 .clk = { .n = "uart2_clk", .id = 26 }, 126 .r = { .min = 0, .max = 83000000 }, 127 }, 128 { 129 .clk = { .n = "uart3_clk", .id = 27 }, 130 .r = { .min = 0, .max = 83000000 }, 131 }, 132 { 133 .clk = { .n = "uart4_clk", .id = 28 }, 134 .r = { .min = 0, .max = 83000000 }, 135 }, 136 { 137 .clk = { .n = "twi0_clk", .id = 29 }, 138 .r = { .min = 0, .max = 83000000 }, 139 }, 140 { 141 .clk = { .n = "twi1_clk", .id = 30 }, 142 .r = { .min = 0, .max = 83000000 }, 143 }, 144 { 145 .clk = { .n = "spi0_clk", .id = 33 }, 146 .r = { .min = 0, .max = 83000000 }, 147 }, 148 { 149 .clk = { .n = "spi1_clk", .id = 34 }, 150 .r = { .min = 0, .max = 83000000 }, 151 }, 152 { 153 .clk = { .n = "tcb0_clk", .id = 35 }, 154 .r = { .min = 0, .max = 83000000 }, 155 }, 156 { 157 .clk = { .n = "tcb1_clk", .id = 36 }, 158 .r = { .min = 0, .max = 83000000 }, 159 }, 160 { 161 .clk = { .n = "pwm_clk", .id = 38 }, 162 .r = { .min = 0, .max = 83000000 }, 163 }, 164 { 165 .clk = { .n = "adc_clk", .id = 40 }, 166 .r = { .min = 0, .max = 83000000 }, 167 }, 168 { 169 .clk = { .n = "uhphs_clk", .id = 41 }, 170 .r = { .min = 0, .max = 83000000 }, 171 }, 172 { 173 .clk = { .n = "udphs_clk", .id = 42 }, 174 .r = { .min = 0, .max = 83000000 }, 175 }, 176 { 177 .clk = { .n = "ssc0_clk", .id = 43 }, 178 .r = { .min = 0, .max = 83000000 }, 179 }, 180 { 181 .clk = { .n = "ssc1_clk", .id = 44 }, 182 .r = { .min = 0, .max = 83000000 }, 183 }, 184 { 185 .clk = { .n = "trng_clk", .id = 47 }, 186 .r = { .min = 0, .max = 83000000 }, 187 }, 188 { 189 .clk = { .n = "pdmic_clk", .id = 48 }, 190 .r = { .min = 0, .max = 83000000 }, 191 }, 192 { 193 .clk = { .n = "securam_clk", .id = 51 }, }, 194 { 195 .clk = { .n = "i2s0_clk", .id = 54 }, 196 .r = { .min = 0, .max = 83000000 }, 197 }, 198 { 199 .clk = { .n = "i2s1_clk", .id = 55 }, 200 .r = { .min = 0, .max = 83000000 }, 201 }, 202 { 203 .clk = { .n = "can0_clk", .id = 56 }, 204 .r = { .min = 0, .max = 83000000 }, 205 }, 206 { 207 .clk = { .n = "can1_clk", .id = 57 }, 208 .r = { .min = 0, .max = 83000000 }, 209 }, 210 { 211 .clk = { .n = "ptc_clk", .id = 58 }, 212 .r = { .min = 0, .max = 83000000 }, 213 }, 214 { 215 .clk = { .n = "classd_clk", .id = 59 }, 216 .r = { .min = 0, .max = 83000000 }, 217 }, 218 }; 219 220 static const struct sam_clk sama5d2_perick[] = { 221 { .n = "dma0_clk", .id = 6 }, 222 { .n = "dma1_clk", .id = 7 }, 223 { .n = "aes_clk", .id = 9 }, 224 { .n = "aesb_clk", .id = 10 }, 225 { .n = "sha_clk", .id = 12 }, 226 { .n = "mpddr_clk", .id = 13 }, 227 { .n = "matrix0_clk", .id = 15 }, 228 { .n = "sdmmc0_hclk", .id = 31 }, 229 { .n = "sdmmc1_hclk", .id = 32 }, 230 { .n = "lcdc_clk", .id = 45 }, 231 { .n = "isc_clk", .id = 46 }, 232 { .n = "qspi0_clk", .id = 52 }, 233 { .n = "qspi1_clk", .id = 53 }, 234 }; 235 236 static const struct { 237 struct sam_clk clk; 238 struct clk_range r; 239 int chg_pid; 240 } sama5d2_gck[] = { 241 { 242 .clk = { .n = "sdmmc0_gclk", .id = 31 }, 243 .chg_pid = INT_MIN, 244 }, 245 { 246 .clk = { .n = "sdmmc1_gclk", .id = 32 }, 247 .chg_pid = INT_MIN, 248 }, 249 { 250 .clk = { .n = "tcb0_gclk", .id = 35 }, 251 .r = { .min = 0, .max = 83000000 }, 252 .chg_pid = INT_MIN, 253 }, 254 { 255 .clk = { .n = "tcb1_gclk", .id = 36 }, 256 .r = { .min = 0, .max = 83000000 }, 257 .chg_pid = INT_MIN, 258 }, 259 { 260 .clk = { .n = "pwm_gclk", .id = 38 }, 261 .r = { .min = 0, .max = 83000000 }, 262 .chg_pid = INT_MIN, 263 }, 264 { 265 .clk = { .n = "isc_gclk", .id = 46 }, 266 .chg_pid = INT_MIN, 267 }, 268 { 269 .clk = { .n = "pdmic_gclk", .id = 48 }, 270 .chg_pid = INT_MIN, 271 }, 272 { 273 .clk = { .n = "i2s0_gclk", .id = 54 }, 274 .chg_pid = 5, 275 }, 276 { 277 .clk = { .n = "i2s1_gclk", .id = 55 }, 278 .chg_pid = 5, 279 }, 280 { 281 .clk = { .n = "can0_gclk", .id = 56 }, 282 .r = { .min = 0, .max = 80000000 }, 283 .chg_pid = INT_MIN, 284 }, 285 { 286 .clk = { .n = "can1_gclk", .id = 57 }, 287 .r = { .min = 0, .max = 80000000 }, 288 .chg_pid = INT_MIN, 289 }, 290 { 291 .clk = { .n = "classd_gclk", .id = 59 }, 292 .chg_pid = 5, 293 .r = { .min = 0, .max = 100000000 }, 294 }, 295 }; 296 297 static const struct sam_clk sama5d2_progck[] = { 298 { .n = "prog0", .id = 0 }, 299 { .n = "prog1", .id = 1 }, 300 { .n = "prog2", .id = 2 }, 301 }; 302 303 static struct pmc_data *pmc; 304 305 vaddr_t at91_pmc_get_base(void) 306 { 307 assert(pmc); 308 309 return pmc->base; 310 } 311 312 TEE_Result at91_pmc_clk_get(unsigned int type, unsigned int idx, 313 struct clk **clk) 314 { 315 return pmc_clk_get(pmc, type, idx, clk); 316 } 317 318 static TEE_Result pmc_setup(const void *fdt, int nodeoffset, 319 const void *data __unused) 320 { 321 size_t size = 0; 322 vaddr_t base = 0; 323 unsigned int i = 0; 324 int bypass = 0; 325 const uint32_t *fdt_prop = NULL; 326 struct pmc_clk *pmc_clk = NULL; 327 const struct sam_clk *sam_clk = NULL; 328 struct clk_range range = CLK_RANGE(0, 0); 329 struct clk *h32mxck = NULL; 330 struct clk *mckdivck = NULL; 331 struct clk *plladivck = NULL; 332 struct clk *usbck = NULL; 333 struct clk *audiopll_pmcck = NULL; 334 struct clk *parents[PARENT_SIZE] = {NULL}; 335 struct clk *main_clk = NULL; 336 struct clk *utmi_clk = NULL; 337 struct clk *slow_clk = NULL; 338 struct clk *clk = NULL; 339 struct clk *main_rc_osc = NULL; 340 struct clk *main_osc = NULL; 341 struct clk *main_xtal_clk = NULL; 342 struct clk *audiopll_fracck = NULL; 343 TEE_Result res = TEE_ERROR_GENERIC; 344 345 /* 346 * We want PARENT_SIZE to be MAX(ARRAY_SIZE(sama5d2_systemck),6) 347 * but using this define won't allow static initialization of parents 348 * due to dynamic size. 349 */ 350 COMPILE_TIME_ASSERT(ARRAY_SIZE(sama5d2_systemck) == PARENT_SIZE); 351 COMPILE_TIME_ASSERT(PARENT_SIZE >= 6); 352 353 if (dt_map_dev(fdt, nodeoffset, &base, &size, DT_MAP_AUTO) < 0) 354 panic(); 355 356 if (fdt_get_status(fdt, nodeoffset) == DT_STATUS_OK_SEC) 357 matrix_configure_periph_secure(AT91C_ID_PMC); 358 359 res = clk_dt_get_by_name(fdt, nodeoffset, "slow_clk", &slow_clk); 360 if (res) 361 panic(); 362 363 res = clk_dt_get_by_name(fdt, nodeoffset, "main_xtal", &main_xtal_clk); 364 if (res) 365 panic(); 366 367 pmc = pmc_data_allocate(PMC_SAMA5D2_CORE_CLK_COUNT, 368 ARRAY_SIZE(sama5d2_systemck), 369 ARRAY_SIZE(sama5d2_perick) + 370 ARRAY_SIZE(sama5d2_peri32ck), 371 ARRAY_SIZE(sama5d2_gck), 372 ARRAY_SIZE(sama5d2_progck)); 373 if (!pmc) 374 panic(); 375 pmc->base = base; 376 377 main_rc_osc = pmc_register_main_rc_osc(pmc, "main_rc_osc", 12000000); 378 if (!main_rc_osc) 379 panic(); 380 381 fdt_prop = fdt_getprop(fdt, nodeoffset, "atmel,osc-bypass", NULL); 382 if (fdt_prop) 383 bypass = fdt32_to_cpu(*fdt_prop); 384 385 main_osc = pmc_register_main_osc(pmc, "main_osc", main_xtal_clk, 386 bypass); 387 if (!main_osc) 388 panic(); 389 390 parents[0] = main_rc_osc; 391 parents[1] = main_osc; 392 main_clk = at91_clk_register_sam9x5_main(pmc, "mainck", parents, 2); 393 if (!main_clk) 394 panic(); 395 396 pmc_clk = &pmc->chws[PMC_MAIN]; 397 pmc_clk->clk = main_clk; 398 pmc_clk->id = PMC_MAIN; 399 400 clk = at91_clk_register_pll(pmc, "pllack", main_clk, 0, 401 &sama5d3_pll_layout, &plla_charac); 402 if (!clk) 403 panic(); 404 405 plladivck = at91_clk_register_plldiv(pmc, "plladivck", clk); 406 if (!plladivck) 407 panic(); 408 409 pmc_clk = &pmc->chws[PMC_PLLACK]; 410 pmc_clk->clk = plladivck; 411 pmc_clk->id = PMC_PLLACK; 412 413 audiopll_fracck = at91_clk_register_audio_pll_frac(pmc, 414 "audiopll_fracck", 415 main_clk); 416 if (!audiopll_fracck) 417 panic(); 418 419 pmc_clk = &pmc->chws[PMC_AUDIOPLL_FRACCK]; 420 pmc_clk->clk = audiopll_fracck; 421 pmc_clk->id = PMC_AUDIOPLL_FRACCK; 422 423 clk = at91_clk_register_audio_pll_pad(pmc, "audiopll_padck", 424 audiopll_fracck); 425 if (!clk) 426 panic(); 427 428 audiopll_pmcck = at91_clk_register_audio_pll_pmc(pmc, "audiopll_pmcck", 429 audiopll_fracck); 430 if (!audiopll_pmcck) 431 panic(); 432 433 pmc_clk = &pmc->chws[PMC_AUDIOPLLCK]; 434 pmc_clk->clk = audiopll_pmcck; 435 pmc_clk->id = PMC_AUDIOPLLCK; 436 437 utmi_clk = at91_clk_register_utmi(pmc, "utmick", main_clk); 438 if (!utmi_clk) 439 panic(); 440 441 pmc_clk = &pmc->chws[PMC_UTMI]; 442 pmc_clk->clk = utmi_clk; 443 pmc_clk->id = PMC_UTMI; 444 445 parents[0] = slow_clk; 446 parents[1] = main_clk; 447 parents[2] = plladivck; 448 parents[3] = utmi_clk; 449 450 clk = at91_clk_register_master_pres(pmc, "masterck_pres", 4, 451 parents, 452 &at91sam9x5_master_layout, 453 &mck_charac, INT_MIN); 454 if (!clk) 455 panic(); 456 457 pmc_clk = &pmc->chws[PMC_MCK_PRES]; 458 pmc_clk->clk = clk; 459 pmc_clk->id = PMC_MCK_PRES; 460 461 mckdivck = at91_clk_register_master_div(pmc, "masterck_div", 462 clk, 463 &at91sam9x5_master_layout, 464 &mck_charac); 465 if (!mckdivck) 466 panic(); 467 468 pmc_clk = &pmc->chws[PMC_MCK]; 469 pmc_clk->clk = mckdivck; 470 pmc_clk->id = PMC_MCK; 471 472 h32mxck = at91_clk_register_h32mx(pmc, "h32mxck", mckdivck); 473 if (!h32mxck) 474 panic(); 475 476 pmc_clk = &pmc->chws[PMC_MCK2]; 477 pmc_clk->clk = h32mxck; 478 pmc_clk->id = PMC_MCK2; 479 480 parents[0] = plladivck; 481 parents[1] = utmi_clk; 482 usbck = at91sam9x5_clk_register_usb(pmc, "usbck", parents, 2); 483 if (!usbck) 484 panic(); 485 486 pmc_clk = &pmc->chws[PMC_USBCK]; 487 pmc_clk->clk = usbck; 488 pmc_clk->id = PMC_USBCK; 489 490 parents[0] = slow_clk; 491 parents[1] = main_clk; 492 parents[2] = plladivck; 493 parents[3] = utmi_clk; 494 parents[4] = mckdivck; 495 parents[5] = audiopll_pmcck; 496 for (i = 0; i < ARRAY_SIZE(sama5d2_progck); i++) { 497 sam_clk = &sama5d2_progck[i]; 498 clk = at91_clk_register_programmable(pmc, sam_clk->n, 499 parents, 500 PROGCK_PARENT_COUNT, i, 501 &sama5d2_prog_layout); 502 if (!clk) 503 panic(); 504 505 pmc_clk = &pmc->pchws[i]; 506 pmc_clk->clk = clk; 507 pmc_clk->id = sam_clk->id; 508 } 509 510 /* This array order must match the one in sama5d2_systemck */ 511 parents[0] = mckdivck; 512 parents[1] = mckdivck; 513 parents[2] = usbck; 514 parents[3] = usbck; 515 parents[4] = pmc->pchws[0].clk; 516 parents[5] = pmc->pchws[1].clk; 517 parents[6] = pmc->pchws[2].clk; 518 parents[7] = mckdivck; 519 for (i = 0; i < ARRAY_SIZE(sama5d2_systemck); i++) { 520 sam_clk = &sama5d2_systemck[i]; 521 clk = at91_clk_register_system(pmc, sam_clk->n, 522 parents[i], 523 sam_clk->id); 524 if (!clk) 525 panic(); 526 527 pmc_clk = &pmc->shws[i]; 528 pmc_clk->clk = clk; 529 pmc_clk->id = sam_clk->id; 530 } 531 532 for (i = 0; i < ARRAY_SIZE(sama5d2_perick); i++) { 533 sam_clk = &sama5d2_perick[i]; 534 clk = at91_clk_register_sam9x5_periph(pmc, 535 &sama5d2_pcr_layout, 536 sam_clk->n, 537 mckdivck, 538 sam_clk->id, 539 &range); 540 if (!clk) 541 panic(); 542 543 pmc_clk = &pmc->phws[i]; 544 pmc_clk->clk = clk; 545 pmc_clk->id = sam_clk->id; 546 } 547 548 for (i = 0; i < ARRAY_SIZE(sama5d2_peri32ck); i++) { 549 sam_clk = &sama5d2_peri32ck[i].clk; 550 clk = at91_clk_register_sam9x5_periph(pmc, 551 &sama5d2_pcr_layout, 552 sam_clk->n, 553 h32mxck, 554 sam_clk->id, 555 &sama5d2_peri32ck[i].r); 556 if (!clk) 557 panic(); 558 559 pmc_clk = &pmc->phws[ARRAY_SIZE(sama5d2_perick) + i]; 560 pmc_clk->clk = clk; 561 pmc_clk->id = sam_clk->id; 562 } 563 564 parents[0] = slow_clk; 565 parents[1] = main_clk; 566 parents[2] = plladivck; 567 parents[3] = utmi_clk; 568 parents[4] = mckdivck; 569 parents[5] = audiopll_pmcck; 570 for (i = 0; i < ARRAY_SIZE(sama5d2_gck); i++) { 571 sam_clk = &sama5d2_gck[i].clk; 572 clk = at91_clk_register_generated(pmc, 573 &sama5d2_pcr_layout, 574 sam_clk->n, 575 parents, NULL, 6, 576 sam_clk->id, 577 &sama5d2_gck[i].r, 578 sama5d2_gck[i].chg_pid); 579 if (!clk) 580 panic(); 581 582 pmc_clk = &pmc->ghws[i]; 583 pmc_clk->clk = clk; 584 pmc_clk->id = sam_clk->id; 585 } 586 587 parents[0] = pmc_clk_get_by_name(pmc->phws, pmc->nperiph, "i2s0_clk"); 588 parents[1] = pmc_clk_get_by_name(pmc->ghws, pmc->ngck, "i2s0_gclk"); 589 clk = at91_clk_i2s_mux_register("i2s0_muxclk", parents, 2, 0); 590 if (!clk) 591 panic(); 592 593 pmc->chws[PMC_I2S0_MUX].clk = clk; 594 pmc->chws[PMC_I2S0_MUX].id = PMC_I2S0_MUX; 595 596 parents[0] = pmc_clk_get_by_name(pmc->phws, pmc->nperiph, "i2s1_clk"); 597 parents[1] = pmc_clk_get_by_name(pmc->ghws, pmc->ngck, "i2s1_gclk"); 598 clk = at91_clk_i2s_mux_register("i2s1_muxclk", parents, 2, 1); 599 if (!clk) 600 panic(); 601 602 pmc->chws[PMC_I2S1_MUX].clk = clk; 603 pmc->chws[PMC_I2S1_MUX].id = PMC_I2S1_MUX; 604 605 clk_dt_register_clk_provider(fdt, nodeoffset, clk_dt_pmc_get, pmc); 606 607 pmc_register_pm(); 608 609 return TEE_SUCCESS; 610 } 611 612 CLK_DT_DECLARE(sama5d2_clk, "atmel,sama5d2-pmc", pmc_setup); 613