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 static TEE_Result pmc_setup(const void *fdt, int nodeoffset, 313 const void *data __unused) 314 { 315 size_t size = 0; 316 vaddr_t base = 0; 317 unsigned int i = 0; 318 int bypass = 0; 319 const uint32_t *fdt_prop = NULL; 320 struct pmc_clk *pmc_clk = NULL; 321 const struct sam_clk *sam_clk = NULL; 322 struct clk_range range = CLK_RANGE(0, 0); 323 struct clk *h32mxck = NULL; 324 struct clk *mckdivck = NULL; 325 struct clk *plladivck = NULL; 326 struct clk *usbck = NULL; 327 struct clk *audiopll_pmcck = NULL; 328 struct clk *parents[PARENT_SIZE] = {NULL}; 329 struct clk *main_clk = NULL; 330 struct clk *utmi_clk = NULL; 331 struct clk *slow_clk = NULL; 332 struct clk *clk = NULL; 333 struct clk *main_rc_osc = NULL; 334 struct clk *main_osc = NULL; 335 struct clk *main_xtal_clk = NULL; 336 struct clk *audiopll_fracck = NULL; 337 TEE_Result res = TEE_ERROR_GENERIC; 338 339 /* 340 * We want PARENT_SIZE to be MAX(ARRAY_SIZE(sama5d2_systemck),6) 341 * but using this define won't allow static initialization of parents 342 * due to dynamic size. 343 */ 344 COMPILE_TIME_ASSERT(ARRAY_SIZE(sama5d2_systemck) == PARENT_SIZE); 345 COMPILE_TIME_ASSERT(PARENT_SIZE >= 6); 346 347 if (dt_map_dev(fdt, nodeoffset, &base, &size, DT_MAP_AUTO) < 0) 348 panic(); 349 350 if (_fdt_get_status(fdt, nodeoffset) == DT_STATUS_OK_SEC) 351 matrix_configure_periph_secure(AT91C_ID_PMC); 352 353 res = clk_dt_get_by_name(fdt, nodeoffset, "slow_clk", &slow_clk); 354 if (res) 355 panic(); 356 357 res = clk_dt_get_by_name(fdt, nodeoffset, "main_xtal", &main_xtal_clk); 358 if (res) 359 panic(); 360 361 pmc = pmc_data_allocate(PMC_MCK_PRES + 1, 362 ARRAY_SIZE(sama5d2_systemck), 363 ARRAY_SIZE(sama5d2_perick) + 364 ARRAY_SIZE(sama5d2_peri32ck), 365 ARRAY_SIZE(sama5d2_gck), 366 ARRAY_SIZE(sama5d2_progck)); 367 if (!pmc) 368 panic(); 369 pmc->base = base; 370 371 main_rc_osc = pmc_register_main_rc_osc(pmc, "main_rc_osc", 12000000); 372 if (!main_rc_osc) 373 panic(); 374 375 fdt_prop = fdt_getprop(fdt, nodeoffset, "atmel,osc-bypass", NULL); 376 if (fdt_prop) 377 bypass = fdt32_to_cpu(*fdt_prop); 378 379 main_osc = pmc_register_main_osc(pmc, "main_osc", main_xtal_clk, 380 bypass); 381 if (!main_osc) 382 panic(); 383 384 parents[0] = main_rc_osc; 385 parents[1] = main_osc; 386 main_clk = at91_clk_register_sam9x5_main(pmc, "mainck", parents, 2); 387 if (!main_clk) 388 panic(); 389 390 pmc_clk = &pmc->chws[PMC_MAIN]; 391 pmc_clk->clk = main_clk; 392 pmc_clk->id = PMC_MAIN; 393 394 clk = at91_clk_register_pll(pmc, "pllack", main_clk, 0, 395 &sama5d3_pll_layout, &plla_charac); 396 if (!clk) 397 panic(); 398 399 plladivck = at91_clk_register_plldiv(pmc, "plladivck", clk); 400 if (!plladivck) 401 panic(); 402 403 pmc_clk = &pmc->chws[PMC_PLLACK]; 404 pmc_clk->clk = plladivck; 405 pmc_clk->id = PMC_PLLACK; 406 407 audiopll_fracck = at91_clk_register_audio_pll_frac(pmc, 408 "audiopll_fracck", 409 main_clk); 410 if (!audiopll_fracck) 411 panic(); 412 413 clk = at91_clk_register_audio_pll_pad(pmc, "audiopll_padck", 414 audiopll_fracck); 415 if (!clk) 416 panic(); 417 418 audiopll_pmcck = at91_clk_register_audio_pll_pmc(pmc, "audiopll_pmcck", 419 audiopll_fracck); 420 if (!audiopll_pmcck) 421 panic(); 422 423 pmc_clk = &pmc->chws[PMC_AUDIOPLLCK]; 424 pmc_clk->clk = audiopll_pmcck; 425 pmc_clk->id = PMC_AUDIOPLLCK; 426 427 utmi_clk = at91_clk_register_utmi(pmc, "utmick", main_clk); 428 if (!utmi_clk) 429 panic(); 430 431 pmc_clk = &pmc->chws[PMC_UTMI]; 432 pmc_clk->clk = utmi_clk; 433 pmc_clk->id = PMC_UTMI; 434 435 parents[0] = slow_clk; 436 parents[1] = main_clk; 437 parents[2] = plladivck; 438 parents[3] = utmi_clk; 439 440 clk = at91_clk_register_master_pres(pmc, "masterck_pres", 4, 441 parents, 442 &at91sam9x5_master_layout, 443 &mck_charac, INT_MIN); 444 if (!clk) 445 panic(); 446 447 pmc_clk = &pmc->chws[PMC_MCK_PRES]; 448 pmc_clk->clk = clk; 449 pmc_clk->id = PMC_MCK_PRES; 450 451 mckdivck = at91_clk_register_master_div(pmc, "masterck_div", 452 clk, 453 &at91sam9x5_master_layout, 454 &mck_charac); 455 if (!mckdivck) 456 panic(); 457 458 pmc_clk = &pmc->chws[PMC_MCK]; 459 pmc_clk->clk = mckdivck; 460 pmc_clk->id = PMC_MCK; 461 462 h32mxck = at91_clk_register_h32mx(pmc, "h32mxck", mckdivck); 463 if (!h32mxck) 464 panic(); 465 466 pmc_clk = &pmc->chws[PMC_MCK2]; 467 pmc_clk->clk = h32mxck; 468 pmc_clk->id = PMC_MCK2; 469 470 parents[0] = plladivck; 471 parents[1] = utmi_clk; 472 usbck = at91sam9x5_clk_register_usb(pmc, "usbck", parents, 2); 473 if (!usbck) 474 panic(); 475 476 if (clk_set_parent(usbck, utmi_clk) != TEE_SUCCESS) 477 panic(); 478 479 clk_set_rate(usbck, 48000000); 480 481 parents[0] = slow_clk; 482 parents[1] = main_clk; 483 parents[2] = plladivck; 484 parents[3] = utmi_clk; 485 parents[4] = mckdivck; 486 parents[5] = audiopll_pmcck; 487 for (i = 0; i < ARRAY_SIZE(sama5d2_progck); i++) { 488 sam_clk = &sama5d2_progck[i]; 489 clk = at91_clk_register_programmable(pmc, sam_clk->n, 490 parents, 491 PROGCK_PARENT_COUNT, i, 492 &sama5d2_prog_layout); 493 if (!clk) 494 panic(); 495 496 pmc_clk = &pmc->pchws[i]; 497 pmc_clk->clk = clk; 498 pmc_clk->id = sam_clk->id; 499 } 500 501 /* This array order must match the one in sama5d2_systemck */ 502 parents[0] = mckdivck; 503 parents[1] = mckdivck; 504 parents[2] = usbck; 505 parents[3] = usbck; 506 parents[4] = pmc->pchws[0].clk; 507 parents[5] = pmc->pchws[1].clk; 508 parents[6] = pmc->pchws[2].clk; 509 parents[7] = mckdivck; 510 for (i = 0; i < ARRAY_SIZE(sama5d2_systemck); i++) { 511 sam_clk = &sama5d2_systemck[i]; 512 clk = at91_clk_register_system(pmc, sam_clk->n, 513 parents[i], 514 sam_clk->id); 515 if (!clk) 516 panic(); 517 518 pmc_clk = &pmc->shws[i]; 519 pmc_clk->clk = clk; 520 pmc_clk->id = sam_clk->id; 521 } 522 523 for (i = 0; i < ARRAY_SIZE(sama5d2_perick); i++) { 524 sam_clk = &sama5d2_perick[i]; 525 clk = at91_clk_register_sam9x5_periph(pmc, 526 &sama5d2_pcr_layout, 527 sam_clk->n, 528 mckdivck, 529 sam_clk->id, 530 &range); 531 if (!clk) 532 panic(); 533 534 pmc_clk = &pmc->phws[i]; 535 pmc_clk->clk = clk; 536 pmc_clk->id = sam_clk->id; 537 } 538 539 for (i = 0; i < ARRAY_SIZE(sama5d2_peri32ck); i++) { 540 sam_clk = &sama5d2_peri32ck[i].clk; 541 clk = at91_clk_register_sam9x5_periph(pmc, 542 &sama5d2_pcr_layout, 543 sam_clk->n, 544 h32mxck, 545 sam_clk->id, 546 &sama5d2_peri32ck[i].r); 547 if (!clk) 548 panic(); 549 550 pmc_clk = &pmc->phws[ARRAY_SIZE(sama5d2_perick) + i]; 551 pmc_clk->clk = clk; 552 pmc_clk->id = sam_clk->id; 553 } 554 555 parents[0] = slow_clk; 556 parents[1] = main_clk; 557 parents[2] = plladivck; 558 parents[3] = utmi_clk; 559 parents[4] = mckdivck; 560 parents[5] = audiopll_pmcck; 561 for (i = 0; i < ARRAY_SIZE(sama5d2_gck); i++) { 562 sam_clk = &sama5d2_gck[i].clk; 563 clk = at91_clk_register_generated(pmc, 564 &sama5d2_pcr_layout, 565 sam_clk->n, 566 parents, 6, 567 sam_clk->id, 568 &sama5d2_gck[i].r, 569 sama5d2_gck[i].chg_pid); 570 if (!clk) 571 panic(); 572 573 pmc_clk = &pmc->ghws[i]; 574 pmc_clk->clk = clk; 575 pmc_clk->id = sam_clk->id; 576 } 577 578 parents[0] = pmc_clk_get_by_name(pmc->phws, pmc->nperiph, "i2s0_clk"); 579 parents[1] = pmc_clk_get_by_name(pmc->ghws, pmc->ngck, "i2s0_gclk"); 580 clk = at91_clk_i2s_mux_register("i2s0_muxclk", parents, 2, 0); 581 if (!clk) 582 panic(); 583 584 pmc->chws[PMC_I2S0_MUX].clk = clk; 585 pmc->chws[PMC_I2S0_MUX].id = PMC_I2S0_MUX; 586 587 parents[0] = pmc_clk_get_by_name(pmc->phws, pmc->nperiph, "i2s1_clk"); 588 parents[1] = pmc_clk_get_by_name(pmc->ghws, pmc->ngck, "i2s1_gclk"); 589 clk = at91_clk_i2s_mux_register("i2s1_muxclk", parents, 2, 1); 590 if (!clk) 591 panic(); 592 593 pmc->chws[PMC_I2S1_MUX].clk = clk; 594 pmc->chws[PMC_I2S1_MUX].id = PMC_I2S1_MUX; 595 596 clk_dt_register_clk_provider(fdt, nodeoffset, clk_dt_pmc_get, pmc); 597 598 pmc_register_pm(); 599 600 return TEE_SUCCESS; 601 } 602 603 CLK_DT_DECLARE(sama5d2_clk, "atmel,sama5d2-pmc", pmc_setup); 604