1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * SAMA7D65 PMC code. 4 * 5 * Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries 6 * 7 * Author: Ryan Wanner <ryan.wanner@microchip.com> 8 */ 9 #include <linux/clk.h> 10 #include <linux/clk-provider.h> 11 #include <linux/mfd/syscon.h> 12 #include <linux/slab.h> 13 14 #include <dt-bindings/clock/at91.h> 15 16 #include "pmc.h" 17 18 static DEFINE_SPINLOCK(pmc_pll_lock); 19 static DEFINE_SPINLOCK(pmc_mck0_lock); 20 static DEFINE_SPINLOCK(pmc_mckX_lock); 21 22 #define PMC_INDEX_MAX 25 23 24 /* 25 * PLL clocks identifiers 26 * @PLL_ID_CPU: CPU PLL identifier 27 * @PLL_ID_SYS: System PLL identifier 28 * @PLL_ID_DDR: DDR PLL identifier 29 * @PLL_ID_GPU: Graphics subsystem PLL identifier 30 * @PLL_ID_BAUD: Baud PLL identifier 31 * @PLL_ID_AUDIO: Audio PLL identifier 32 * @PLL_ID_ETH: Ethernet PLL identifier 33 * @PLL_ID_LVDS: LVDS PLL identifier 34 * @PLL_ID_USB: USB PLL identifier 35 */ 36 enum pll_ids { 37 PLL_ID_CPU, 38 PLL_ID_SYS, 39 PLL_ID_DDR, 40 PLL_ID_GPU, 41 PLL_ID_BAUD, 42 PLL_ID_AUDIO, 43 PLL_ID_ETH, 44 PLL_ID_LVDS, 45 PLL_ID_USB, 46 PLL_ID_MAX 47 }; 48 49 /* 50 * PLL component identifier 51 * @PLL_COMPID_FRAC: Fractional PLL component identifier 52 * @PLL_COMPID_DIV0: 1st PLL divider component identifier 53 * @PLL_COMPID_DIV1: 2nd PLL divider component identifier 54 */ 55 enum pll_component_id { 56 PLL_COMPID_FRAC, 57 PLL_COMPID_DIV0, 58 PLL_COMPID_DIV1, 59 PLL_COMPID_MAX 60 }; 61 62 /* 63 * PLL type identifiers 64 * @PLL_TYPE_FRAC: fractional PLL identifier 65 * @PLL_TYPE_DIV: divider PLL identifier 66 */ 67 enum pll_type { 68 PLL_TYPE_FRAC, 69 PLL_TYPE_DIV 70 }; 71 72 /* Layout for fractional PLLs. */ 73 static const struct clk_pll_layout pll_layout_frac = { 74 .mul_mask = GENMASK(31, 24), 75 .frac_mask = GENMASK(21, 0), 76 .mul_shift = 24, 77 .frac_shift = 0, 78 }; 79 80 /* Layout for DIVPMC dividers. */ 81 static const struct clk_pll_layout pll_layout_divpmc = { 82 .div_mask = GENMASK(7, 0), 83 .endiv_mask = BIT(29), 84 .div_shift = 0, 85 .endiv_shift = 29, 86 }; 87 88 /* Layout for DIVIO dividers. */ 89 static const struct clk_pll_layout pll_layout_divio = { 90 .div_mask = GENMASK(19, 12), 91 .endiv_mask = BIT(30), 92 .div_shift = 12, 93 .endiv_shift = 30, 94 }; 95 96 /* 97 * CPU PLL output range. 98 * Notice: The upper limit has been setup to 1000000002 due to hardware 99 * block which cannot output exactly 1GHz. 100 */ 101 static const struct clk_range cpu_pll_outputs[] = { 102 { .min = 2343750, .max = 1000000002 }, 103 }; 104 105 /* PLL output range. */ 106 static const struct clk_range pll_outputs[] = { 107 { .min = 2343750, .max = 1200000000 }, 108 }; 109 110 /* 111 * Min: fCOREPLLCK = 600 MHz, PMC_PLL_CTRL0.DIVPMC = 255 112 * Max: fCOREPLLCK = 800 MHz, PMC_PLL_CTRL0.DIVPMC = 0 113 */ 114 static const struct clk_range lvdspll_outputs[] = { 115 { .min = 16406250, .max = 800000000 }, 116 }; 117 118 static const struct clk_range upll_outputs[] = { 119 { .min = 480000000, .max = 480000000 }, 120 }; 121 122 /* Fractional PLL core output range. */ 123 static const struct clk_range core_outputs[] = { 124 { .min = 600000000, .max = 1200000000 }, 125 }; 126 127 static const struct clk_range lvdspll_core_outputs[] = { 128 { .min = 600000000, .max = 1200000000 }, 129 }; 130 131 static const struct clk_range upll_core_outputs[] = { 132 { .min = 600000000, .max = 1200000000 }, 133 }; 134 135 /* CPU PLL characteristics. */ 136 static const struct clk_pll_characteristics cpu_pll_characteristics = { 137 .input = { .min = 12000000, .max = 50000000 }, 138 .num_output = ARRAY_SIZE(cpu_pll_outputs), 139 .output = cpu_pll_outputs, 140 .core_output = core_outputs, 141 }; 142 143 /* PLL characteristics. */ 144 static const struct clk_pll_characteristics pll_characteristics = { 145 .input = { .min = 12000000, .max = 50000000 }, 146 .num_output = ARRAY_SIZE(pll_outputs), 147 .output = pll_outputs, 148 .core_output = core_outputs, 149 }; 150 151 static const struct clk_pll_characteristics lvdspll_characteristics = { 152 .input = { .min = 12000000, .max = 50000000 }, 153 .num_output = ARRAY_SIZE(lvdspll_outputs), 154 .output = lvdspll_outputs, 155 .core_output = lvdspll_core_outputs, 156 }; 157 158 static const struct clk_pll_characteristics upll_characteristics = { 159 .input = { .min = 20000000, .max = 50000000 }, 160 .num_output = ARRAY_SIZE(upll_outputs), 161 .output = upll_outputs, 162 .core_output = upll_core_outputs, 163 .upll = true, 164 }; 165 166 /* 167 * SAMA7D65 PLL possible parents 168 * @SAMA7D65_PLL_PARENT_MAINCK: MAINCK is PLL a parent 169 * @SAMA7D65_PLL_PARENT_MAIN_XTAL: MAIN XTAL is a PLL parent 170 * @SAMA7D65_PLL_PARENT_FRACCK: Frac PLL is a PLL parent (for PLL dividers) 171 */ 172 enum sama7d65_pll_parent { 173 SAMA7D65_PLL_PARENT_MAINCK, 174 SAMA7D65_PLL_PARENT_MAIN_XTAL, 175 SAMA7D65_PLL_PARENT_FRACCK 176 }; 177 178 /* 179 * PLL clocks description 180 * @n: clock name 181 * @l: clock layout 182 * @c: clock characteristics 183 * @hw: pointer to clk_hw 184 * @t: clock type 185 * @f: clock flags 186 * @p: clock parent 187 * @eid: export index in sama7d65->chws[] array 188 * @safe_div: intermediate divider need to be set on PRE_RATE_CHANGE 189 * notification 190 */ 191 static struct sama7d65_pll { 192 const char *n; 193 const struct clk_pll_layout *l; 194 const struct clk_pll_characteristics *c; 195 struct clk_hw *hw; 196 unsigned long f; 197 enum sama7d65_pll_parent p; 198 u8 t; 199 u8 eid; 200 u8 safe_div; 201 } sama7d65_plls[][PLL_COMPID_MAX] = { 202 [PLL_ID_CPU] = { 203 [PLL_COMPID_FRAC] = { 204 .n = "cpupll_fracck", 205 .p = SAMA7D65_PLL_PARENT_MAINCK, 206 .l = &pll_layout_frac, 207 .c = &cpu_pll_characteristics, 208 .t = PLL_TYPE_FRAC, 209 /* 210 * This feeds cpupll_divpmcck which feeds CPU. It should 211 * not be disabled. 212 */ 213 .f = CLK_IS_CRITICAL, 214 }, 215 216 [PLL_COMPID_DIV0] = { 217 .n = "cpupll_divpmcck", 218 .p = SAMA7D65_PLL_PARENT_FRACCK, 219 .l = &pll_layout_divpmc, 220 .c = &cpu_pll_characteristics, 221 .t = PLL_TYPE_DIV, 222 /* This feeds CPU. It should not be disabled. */ 223 .f = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 224 .eid = PMC_CPUPLL, 225 /* 226 * Safe div=15 should be safe even for switching b/w 1GHz and 227 * 90MHz (frac pll might go up to 1.2GHz). 228 */ 229 .safe_div = 15, 230 }, 231 }, 232 233 [PLL_ID_SYS] = { 234 [PLL_COMPID_FRAC] = { 235 .n = "syspll_fracck", 236 .p = SAMA7D65_PLL_PARENT_MAINCK, 237 .l = &pll_layout_frac, 238 .c = &pll_characteristics, 239 .t = PLL_TYPE_FRAC, 240 /* 241 * This feeds syspll_divpmcck which may feed critical parts 242 * of the systems like timers. Therefore it should not be 243 * disabled. 244 */ 245 .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, 246 }, 247 248 [PLL_COMPID_DIV0] = { 249 .n = "syspll_divpmcck", 250 .p = SAMA7D65_PLL_PARENT_FRACCK, 251 .l = &pll_layout_divpmc, 252 .c = &pll_characteristics, 253 .t = PLL_TYPE_DIV, 254 /* 255 * This may feed critical parts of the systems like timers. 256 * Therefore it should not be disabled. 257 */ 258 .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, 259 .eid = PMC_SYSPLL, 260 }, 261 }, 262 263 [PLL_ID_DDR] = { 264 [PLL_COMPID_FRAC] = { 265 .n = "ddrpll_fracck", 266 .p = SAMA7D65_PLL_PARENT_MAINCK, 267 .l = &pll_layout_frac, 268 .c = &pll_characteristics, 269 .t = PLL_TYPE_FRAC, 270 /* 271 * This feeds ddrpll_divpmcck which feeds DDR. It should not 272 * be disabled. 273 */ 274 .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, 275 }, 276 277 [PLL_COMPID_DIV0] = { 278 .n = "ddrpll_divpmcck", 279 .p = SAMA7D65_PLL_PARENT_FRACCK, 280 .l = &pll_layout_divpmc, 281 .c = &pll_characteristics, 282 .t = PLL_TYPE_DIV, 283 /* This feeds DDR. It should not be disabled. */ 284 .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, 285 }, 286 }, 287 288 [PLL_ID_GPU] = { 289 [PLL_COMPID_FRAC] = { 290 .n = "gpupll_fracck", 291 .p = SAMA7D65_PLL_PARENT_MAINCK, 292 .l = &pll_layout_frac, 293 .c = &pll_characteristics, 294 .t = PLL_TYPE_FRAC, 295 .f = CLK_SET_RATE_GATE, 296 }, 297 298 [PLL_COMPID_DIV0] = { 299 .n = "gpupll_divpmcck", 300 .p = SAMA7D65_PLL_PARENT_FRACCK, 301 .l = &pll_layout_divpmc, 302 .c = &pll_characteristics, 303 .t = PLL_TYPE_DIV, 304 .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | 305 CLK_SET_RATE_PARENT, 306 }, 307 }, 308 309 [PLL_ID_BAUD] = { 310 [PLL_COMPID_FRAC] = { 311 .n = "baudpll_fracck", 312 .p = SAMA7D65_PLL_PARENT_MAINCK, 313 .l = &pll_layout_frac, 314 .c = &pll_characteristics, 315 .t = PLL_TYPE_FRAC, 316 .f = CLK_SET_RATE_GATE, 317 }, 318 319 [PLL_COMPID_DIV0] = { 320 .n = "baudpll_divpmcck", 321 .p = SAMA7D65_PLL_PARENT_FRACCK, 322 .l = &pll_layout_divpmc, 323 .c = &pll_characteristics, 324 .t = PLL_TYPE_DIV, 325 .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | 326 CLK_SET_RATE_PARENT, 327 .eid = PMC_BAUDPLL, 328 }, 329 }, 330 331 [PLL_ID_AUDIO] = { 332 [PLL_COMPID_FRAC] = { 333 .n = "audiopll_fracck", 334 .p = SAMA7D65_PLL_PARENT_MAIN_XTAL, 335 .l = &pll_layout_frac, 336 .c = &pll_characteristics, 337 .t = PLL_TYPE_FRAC, 338 .f = CLK_SET_RATE_GATE, 339 }, 340 341 [PLL_COMPID_DIV0] = { 342 .n = "audiopll_divpmcck", 343 .p = SAMA7D65_PLL_PARENT_FRACCK, 344 .l = &pll_layout_divpmc, 345 .c = &pll_characteristics, 346 .t = PLL_TYPE_DIV, 347 .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | 348 CLK_SET_RATE_PARENT, 349 .eid = PMC_AUDIOPMCPLL, 350 }, 351 352 [PLL_COMPID_DIV1] = { 353 .n = "audiopll_diviock", 354 .p = SAMA7D65_PLL_PARENT_FRACCK, 355 .l = &pll_layout_divio, 356 .c = &pll_characteristics, 357 .t = PLL_TYPE_DIV, 358 .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | 359 CLK_SET_RATE_PARENT, 360 .eid = PMC_AUDIOIOPLL, 361 }, 362 }, 363 364 [PLL_ID_ETH] = { 365 [PLL_COMPID_FRAC] = { 366 .n = "ethpll_fracck", 367 .p = SAMA7D65_PLL_PARENT_MAIN_XTAL, 368 .l = &pll_layout_frac, 369 .c = &pll_characteristics, 370 .t = PLL_TYPE_FRAC, 371 .f = CLK_SET_RATE_GATE, 372 }, 373 374 [PLL_COMPID_DIV0] = { 375 .n = "ethpll_divpmcck", 376 .p = SAMA7D65_PLL_PARENT_FRACCK, 377 .l = &pll_layout_divpmc, 378 .c = &pll_characteristics, 379 .t = PLL_TYPE_DIV, 380 .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | 381 CLK_SET_RATE_PARENT, 382 .eid = PMC_ETHPLL, 383 }, 384 }, 385 386 [PLL_ID_LVDS] = { 387 [PLL_COMPID_FRAC] = { 388 .n = "lvdspll_fracck", 389 .p = SAMA7D65_PLL_PARENT_MAIN_XTAL, 390 .l = &pll_layout_frac, 391 .c = &lvdspll_characteristics, 392 .t = PLL_TYPE_FRAC, 393 .f = CLK_SET_RATE_GATE, 394 }, 395 396 [PLL_COMPID_DIV0] = { 397 .n = "lvdspll_divpmcck", 398 .p = SAMA7D65_PLL_PARENT_FRACCK, 399 .l = &pll_layout_divpmc, 400 .c = &lvdspll_characteristics, 401 .t = PLL_TYPE_DIV, 402 .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | 403 CLK_SET_RATE_PARENT, 404 .eid = PMC_LVDSPLL, 405 }, 406 }, 407 408 [PLL_ID_USB] = { 409 [PLL_COMPID_FRAC] = { 410 .n = "usbpll_fracck", 411 .p = SAMA7D65_PLL_PARENT_MAIN_XTAL, 412 .l = &pll_layout_frac, 413 .c = &upll_characteristics, 414 .t = PLL_TYPE_FRAC, 415 .f = CLK_SET_RATE_GATE, 416 }, 417 418 [PLL_COMPID_DIV0] = { 419 .n = "usbpll_divpmcck", 420 .p = SAMA7D65_PLL_PARENT_FRACCK, 421 .l = &pll_layout_divpmc, 422 .c = &upll_characteristics, 423 .t = PLL_TYPE_DIV, 424 .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | 425 CLK_SET_RATE_PARENT, 426 .eid = PMC_UTMI, 427 }, 428 }, 429 }; 430 431 /* Used to create an array entry identifying a PLL by its components. */ 432 #define PLL_IDS_TO_ARR_ENTRY(_id, _comp) { PLL_ID_##_id, PLL_COMPID_##_comp} 433 434 /* 435 * Master clock (MCK[0..9]) description 436 * @n: clock name 437 * @ep_chg_chg_id: index in parents array that specifies the changeable 438 * @ep: extra parents names array (entry formed by PLL components 439 * identifiers (see enum pll_component_id)) 440 * @hw: pointer to clk_hw 441 * parent 442 * @ep_count: extra parents count 443 * @ep_mux_table: mux table for extra parents 444 * @id: clock id 445 * @eid: export index in sama7d65->chws[] array 446 * @c: true if clock is critical and cannot be disabled 447 */ 448 static struct { 449 const char *n; 450 struct { 451 int pll_id; 452 int pll_compid; 453 } ep[4]; 454 struct clk_hw *hw; 455 int ep_chg_id; 456 u8 ep_count; 457 u8 ep_mux_table[4]; 458 u8 id; 459 u8 eid; 460 u8 c; 461 } sama7d65_mckx[] = { 462 { .n = "mck0", }, /* Dummy entry for MCK0 to store hw in probe. */ 463 { .n = "mck1", 464 .id = 1, 465 .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), }, 466 .ep_mux_table = { 5, }, 467 .ep_count = 1, 468 .ep_chg_id = INT_MIN, 469 .eid = PMC_MCK1, 470 .c = 1, }, 471 472 { .n = "mck2", 473 .id = 2, 474 .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(DDR, DIV0), }, 475 .ep_mux_table = { 5, 6, }, 476 .ep_count = 2, 477 .ep_chg_id = INT_MIN, 478 .c = 1, }, 479 480 { .n = "mck3", 481 .id = 3, 482 .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(DDR, DIV0), }, 483 .ep_mux_table = { 5, 6, }, 484 .ep_count = 2, 485 .ep_chg_id = INT_MIN, 486 .eid = PMC_MCK3, 487 .c = 1, }, 488 489 { .n = "mck4", 490 .id = 4, 491 .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), }, 492 .ep_mux_table = { 5, }, 493 .ep_count = 1, 494 .ep_chg_id = INT_MIN, 495 .c = 1, }, 496 497 { .n = "mck5", 498 .id = 5, 499 .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), }, 500 .ep_mux_table = { 5, }, 501 .ep_count = 1, 502 .ep_chg_id = INT_MIN, 503 .eid = PMC_MCK5, 504 .c = 1, }, 505 506 { .n = "mck6", 507 .id = 6, 508 .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), }, 509 .ep_mux_table = { 5, }, 510 .ep_chg_id = INT_MIN, 511 .ep_count = 1, 512 .c = 1, }, 513 514 { .n = "mck7", 515 .id = 7, 516 .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), }, 517 .ep_mux_table = { 5, }, 518 .ep_chg_id = INT_MIN, 519 .ep_count = 1, }, 520 521 { .n = "mck8", 522 .id = 8, 523 .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), }, 524 .ep_mux_table = { 5, }, 525 .ep_chg_id = INT_MIN, 526 .ep_count = 1, }, 527 528 { .n = "mck9", 529 .id = 9, 530 .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), }, 531 .ep_mux_table = { 5, }, 532 .ep_chg_id = INT_MIN, 533 .ep_count = 1, }, 534 }; 535 536 /* 537 * System clock description 538 * @n: clock name 539 * @p: clock parent name 540 * @id: clock id 541 */ 542 static const struct { 543 const char *n; 544 const char *p; 545 u8 id; 546 } sama7d65_systemck[] = { 547 { .n = "uhpck", .p = "usbck", .id = 6 }, 548 { .n = "pck0", .p = "prog0", .id = 8, }, 549 { .n = "pck1", .p = "prog1", .id = 9, }, 550 { .n = "pck2", .p = "prog2", .id = 10, }, 551 { .n = "pck3", .p = "prog3", .id = 11, }, 552 { .n = "pck4", .p = "prog4", .id = 12, }, 553 { .n = "pck5", .p = "prog5", .id = 13, }, 554 { .n = "pck6", .p = "prog6", .id = 14, }, 555 { .n = "pck7", .p = "prog7", .id = 15, }, 556 }; 557 558 /* Mux table for programmable clocks. */ 559 static u32 sama7d65_prog_mux_table[] = { 0, 1, 2, 5, 7, 8, 9, 10, 12 }; 560 561 /* 562 * Peripheral clock parent hw identifier (used to index in sama7d65_mckx[]) 563 * @PCK_PARENT_HW_MCK0: pck parent hw identifier is MCK0 564 * @PCK_PARENT_HW_MCK1: pck parent hw identifier is MCK1 565 * @PCK_PARENT_HW_MCK2: pck parent hw identifier is MCK2 566 * @PCK_PARENT_HW_MCK3: pck parent hw identifier is MCK3 567 * @PCK_PARENT_HW_MCK4: pck parent hw identifier is MCK4 568 * @PCK_PARENT_HW_MCK5: pck parent hw identifier is MCK5 569 * @PCK_PARENT_HW_MCK6: pck parent hw identifier is MCK6 570 * @PCK_PARENT_HW_MCK7: pck parent hw identifier is MCK7 571 * @PCK_PARENT_HW_MCK8: pck parent hw identifier is MCK8 572 * @PCK_PARENT_HW_MCK9: pck parent hw identifier is MCK9 573 * @PCK_PARENT_HW_MAX: max identifier 574 */ 575 enum sama7d65_pck_parent_hw_id { 576 PCK_PARENT_HW_MCK0, 577 PCK_PARENT_HW_MCK1, 578 PCK_PARENT_HW_MCK2, 579 PCK_PARENT_HW_MCK3, 580 PCK_PARENT_HW_MCK4, 581 PCK_PARENT_HW_MCK5, 582 PCK_PARENT_HW_MCK6, 583 PCK_PARENT_HW_MCK7, 584 PCK_PARENT_HW_MCK8, 585 PCK_PARENT_HW_MCK9, 586 PCK_PARENT_HW_MAX 587 }; 588 589 /* 590 * Peripheral clock description 591 * @n: clock name 592 * @p: clock parent hw id 593 * @r: clock range values 594 * @id: clock id 595 * @chgp: index in parent array of the changeable parent 596 */ 597 static struct { 598 const char *n; 599 enum sama7d65_pck_parent_hw_id p; 600 struct clk_range r; 601 u8 chgp; 602 u8 id; 603 } sama7d65_periphck[] = { 604 { .n = "pioA_clk", .p = PCK_PARENT_HW_MCK0, .id = 10, }, 605 { .n = "securam_clk", .p = PCK_PARENT_HW_MCK0, .id = 17, }, 606 { .n = "sfr_clk", .p = PCK_PARENT_HW_MCK7, .id = 18, }, 607 { .n = "hsmc_clk", .p = PCK_PARENT_HW_MCK5, .id = 20, }, 608 { .n = "xdmac0_clk", .p = PCK_PARENT_HW_MCK6, .id = 21, }, 609 { .n = "xdmac1_clk", .p = PCK_PARENT_HW_MCK6, .id = 22, }, 610 { .n = "xdmac2_clk", .p = PCK_PARENT_HW_MCK1, .id = 23, }, 611 { .n = "acc_clk", .p = PCK_PARENT_HW_MCK7, .id = 24, }, 612 { .n = "aes_clk", .p = PCK_PARENT_HW_MCK6, .id = 26, }, 613 { .n = "tzaesbasc_clk", .p = PCK_PARENT_HW_MCK8, .id = 27, }, 614 { .n = "asrc_clk", .p = PCK_PARENT_HW_MCK9, .id = 29, .r = { .max = 200000000, }, }, 615 { .n = "cpkcc_clk", .p = PCK_PARENT_HW_MCK0, .id = 30, }, 616 { .n = "eic_clk", .p = PCK_PARENT_HW_MCK7, .id = 33, }, 617 { .n = "flex0_clk", .p = PCK_PARENT_HW_MCK7, .id = 34, }, 618 { .n = "flex1_clk", .p = PCK_PARENT_HW_MCK7, .id = 35, }, 619 { .n = "flex2_clk", .p = PCK_PARENT_HW_MCK7, .id = 36, }, 620 { .n = "flex3_clk", .p = PCK_PARENT_HW_MCK7, .id = 37, }, 621 { .n = "flex4_clk", .p = PCK_PARENT_HW_MCK8, .id = 38, }, 622 { .n = "flex5_clk", .p = PCK_PARENT_HW_MCK8, .id = 39, }, 623 { .n = "flex6_clk", .p = PCK_PARENT_HW_MCK8, .id = 40, }, 624 { .n = "flex7_clk", .p = PCK_PARENT_HW_MCK8, .id = 41, }, 625 { .n = "flex8_clk", .p = PCK_PARENT_HW_MCK9, .id = 42, }, 626 { .n = "flex9_clk", .p = PCK_PARENT_HW_MCK9, .id = 43, }, 627 { .n = "flex10_clk", .p = PCK_PARENT_HW_MCK9, .id = 44, }, 628 { .n = "gmac0_clk", .p = PCK_PARENT_HW_MCK6, .id = 46, }, 629 { .n = "gmac1_clk", .p = PCK_PARENT_HW_MCK6, .id = 47, }, 630 { .n = "gmac0_tsu_clk", .p = PCK_PARENT_HW_MCK1, .id = 49, }, 631 { .n = "gmac1_tsu_clk", .p = PCK_PARENT_HW_MCK1, .id = 50, }, 632 { .n = "icm_clk", .p = PCK_PARENT_HW_MCK5, .id = 53, }, 633 { .n = "i2smcc0_clk", .p = PCK_PARENT_HW_MCK9, .id = 54, .r = { .max = 200000000, }, }, 634 { .n = "i2smcc1_clk", .p = PCK_PARENT_HW_MCK9, .id = 55, .r = { .max = 200000000, }, }, 635 { .n = "lcd_clk", .p = PCK_PARENT_HW_MCK3, .id = 56, }, 636 { .n = "matrix_clk", .p = PCK_PARENT_HW_MCK5, .id = 57, }, 637 { .n = "mcan0_clk", .p = PCK_PARENT_HW_MCK5, .id = 58, .r = { .max = 200000000, }, }, 638 { .n = "mcan1_clk", .p = PCK_PARENT_HW_MCK5, .id = 59, .r = { .max = 200000000, }, }, 639 { .n = "mcan2_clk", .p = PCK_PARENT_HW_MCK5, .id = 60, .r = { .max = 200000000, }, }, 640 { .n = "mcan3_clk", .p = PCK_PARENT_HW_MCK5, .id = 61, .r = { .max = 200000000, }, }, 641 { .n = "mcan4_clk", .p = PCK_PARENT_HW_MCK5, .id = 62, .r = { .max = 200000000, }, }, 642 { .n = "pdmc0_clk", .p = PCK_PARENT_HW_MCK9, .id = 64, .r = { .max = 200000000, }, }, 643 { .n = "pdmc1_clk", .p = PCK_PARENT_HW_MCK9, .id = 65, .r = { .max = 200000000, }, }, 644 { .n = "pit64b0_clk", .p = PCK_PARENT_HW_MCK7, .id = 66, }, 645 { .n = "pit64b1_clk", .p = PCK_PARENT_HW_MCK7, .id = 67, }, 646 { .n = "pit64b2_clk", .p = PCK_PARENT_HW_MCK7, .id = 68, }, 647 { .n = "pit64b3_clk", .p = PCK_PARENT_HW_MCK8, .id = 69, }, 648 { .n = "pit64b4_clk", .p = PCK_PARENT_HW_MCK8, .id = 70, }, 649 { .n = "pit64b5_clk", .p = PCK_PARENT_HW_MCK8, .id = 71, }, 650 { .n = "pwm_clk", .p = PCK_PARENT_HW_MCK7, .id = 72, }, 651 { .n = "qspi0_clk", .p = PCK_PARENT_HW_MCK5, .id = 73, }, 652 { .n = "qspi1_clk", .p = PCK_PARENT_HW_MCK5, .id = 74, }, 653 { .n = "sdmmc0_clk", .p = PCK_PARENT_HW_MCK1, .id = 75, }, 654 { .n = "sdmmc1_clk", .p = PCK_PARENT_HW_MCK1, .id = 76, }, 655 { .n = "sdmmc2_clk", .p = PCK_PARENT_HW_MCK1, .id = 77, }, 656 { .n = "sha_clk", .p = PCK_PARENT_HW_MCK6, .id = 78, }, 657 { .n = "spdifrx_clk", .p = PCK_PARENT_HW_MCK9, .id = 79, .r = { .max = 200000000, }, }, 658 { .n = "spdiftx_clk", .p = PCK_PARENT_HW_MCK9, .id = 80, .r = { .max = 200000000, }, }, 659 { .n = "ssc0_clk", .p = PCK_PARENT_HW_MCK7, .id = 81, .r = { .max = 200000000, }, }, 660 { .n = "ssc1_clk", .p = PCK_PARENT_HW_MCK8, .id = 82, .r = { .max = 200000000, }, }, 661 { .n = "tcb0_ch0_clk", .p = PCK_PARENT_HW_MCK8, .id = 83, .r = { .max = 200000000, }, }, 662 { .n = "tcb0_ch1_clk", .p = PCK_PARENT_HW_MCK8, .id = 84, .r = { .max = 200000000, }, }, 663 { .n = "tcb0_ch2_clk", .p = PCK_PARENT_HW_MCK8, .id = 85, .r = { .max = 200000000, }, }, 664 { .n = "tcb1_ch0_clk", .p = PCK_PARENT_HW_MCK5, .id = 86, .r = { .max = 200000000, }, }, 665 { .n = "tcb1_ch1_clk", .p = PCK_PARENT_HW_MCK5, .id = 87, .r = { .max = 200000000, }, }, 666 { .n = "tcb1_ch2_clk", .p = PCK_PARENT_HW_MCK5, .id = 88, .r = { .max = 200000000, }, }, 667 { .n = "tcpca_clk", .p = PCK_PARENT_HW_MCK5, .id = 89, }, 668 { .n = "tcpcb_clk", .p = PCK_PARENT_HW_MCK5, .id = 90, }, 669 { .n = "tdes_clk", .p = PCK_PARENT_HW_MCK6, .id = 91, }, 670 { .n = "trng_clk", .p = PCK_PARENT_HW_MCK6, .id = 92, }, 671 { .n = "udphsa_clk", .p = PCK_PARENT_HW_MCK5, .id = 99, }, 672 { .n = "udphsb_clk", .p = PCK_PARENT_HW_MCK5, .id = 100, }, 673 { .n = "uhphs_clk", .p = PCK_PARENT_HW_MCK5, .id = 101, }, 674 { .n = "dsi_clk", .p = PCK_PARENT_HW_MCK3, .id = 103, }, 675 { .n = "lvdsc_clk", .p = PCK_PARENT_HW_MCK3, .id = 104, }, 676 }; 677 678 /* 679 * Generic clock description 680 * @n: clock name 681 * @pp: PLL parents (entry formed by PLL components identifiers 682 * (see enum pll_component_id)) 683 * @pp_mux_table: PLL parents mux table 684 * @r: clock output range 685 * @pp_chg_id: id in parent array of changeable PLL parent 686 * @pp_count: PLL parents count 687 * @id: clock id 688 */ 689 static const struct { 690 const char *n; 691 struct { 692 int pll_id; 693 int pll_compid; 694 } pp[8]; 695 const char pp_mux_table[8]; 696 struct clk_range r; 697 int pp_chg_id; 698 u8 pp_count; 699 u8 id; 700 } sama7d65_gck[] = { 701 { .n = "adc_gclk", 702 .id = 25, 703 .r = { .max = 100000000, }, 704 .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), }, 705 .pp_mux_table = { 8, 9, }, 706 .pp_count = 2, 707 .pp_chg_id = INT_MIN, }, 708 709 { .n = "asrc_gclk", 710 .id = 29, 711 .r = { .max = 200000000 }, 712 .pp = { PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), }, 713 .pp_mux_table = { 9, }, 714 .pp_count = 1, 715 .pp_chg_id = INT_MIN, }, 716 717 { .n = "flex0_gclk", 718 .id = 34, 719 .r = { .max = 34000000 }, 720 .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, 721 .pp_mux_table = {8, }, 722 .pp_count = 1, 723 .pp_chg_id = INT_MIN, }, 724 725 { .n = "flex1_gclk", 726 .id = 35, 727 .r = { .max = 34000000 }, 728 .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, 729 .pp_mux_table = {8, }, 730 .pp_count = 1, 731 .pp_chg_id = INT_MIN, }, 732 733 { .n = "flex2_gclk", 734 .id = 36, 735 .r = { .max = 34000000 }, 736 .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, 737 .pp_mux_table = {8, }, 738 .pp_count = 1, 739 .pp_chg_id = INT_MIN, }, 740 741 { .n = "flex3_gclk", 742 .id = 37, 743 .r = { .max = 34000000 }, 744 .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, 745 .pp_mux_table = {8, }, 746 .pp_count = 1, 747 .pp_chg_id = INT_MIN, }, 748 749 { .n = "flex4_gclk", 750 .id = 38, 751 .r = { .max = 34000000 }, 752 .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, 753 .pp_mux_table = { 8, }, 754 .pp_count = 1, 755 .pp_chg_id = INT_MIN, }, 756 757 { .n = "flex5_gclk", 758 .id = 39, 759 .r = { .max = 34000000 }, 760 .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, 761 .pp_mux_table = { 8, }, 762 .pp_count = 1, 763 .pp_chg_id = INT_MIN, }, 764 765 { .n = "flex6_gclk", 766 .id = 40, 767 .r = { .max = 34000000 }, 768 .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, 769 .pp_mux_table = { 8, }, 770 .pp_count = 1, 771 .pp_chg_id = INT_MIN, }, 772 773 { .n = "flex7_gclk", 774 .id = 41, 775 .r = { .max = 34000000 }, 776 .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, 777 .pp_mux_table = { 8, }, 778 .pp_count = 1, 779 .pp_chg_id = INT_MIN, }, 780 781 { .n = "flex8_gclk", 782 .id = 42, 783 .r = { .max = 34000000 }, 784 .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, 785 .pp_mux_table = { 8, }, 786 .pp_count = 1, 787 .pp_chg_id = INT_MIN, }, 788 789 { .n = "flex9_gclk", 790 .id = 43, 791 .r = { .max = 34000000 }, 792 .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, 793 .pp_mux_table = { 8, }, 794 .pp_count = 1, 795 .pp_chg_id = INT_MIN, }, 796 797 { .n = "flex10_gclk", 798 .id = 44, 799 .r = { .max = 34000000 }, 800 .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, 801 .pp_mux_table = { 8, }, 802 .pp_count = 1, 803 .pp_chg_id = INT_MIN, }, 804 805 { .n = "gmac0_gclk", 806 .id = 46, 807 .r = { .max = 125000000 }, 808 .pp = { PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, 809 .pp_mux_table = { 10, }, 810 .pp_count = 1, 811 .pp_chg_id = 4, }, 812 813 { .n = "gmac1_gclk", 814 .id = 47, 815 .r = { .max = 125000000 }, 816 .pp = { PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, 817 .pp_mux_table = { 10, }, 818 .pp_count = 1, 819 .pp_chg_id = 4, }, 820 821 { .n = "gmac0_tsu_gclk", 822 .id = 49, 823 .r = { .max = 400000000 }, 824 .pp = { PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, 825 .pp_mux_table = {10, }, 826 .pp_count = 1, 827 .pp_chg_id = INT_MIN, }, 828 829 { .n = "gmac1_tsu_gclk", 830 .id = 50, 831 .r = { .max = 400000000 }, 832 .pp = { PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, 833 .pp_mux_table = { 10, }, 834 .pp_count = 1, 835 .pp_chg_id = INT_MIN, }, 836 837 { .n = "i2smcc0_gclk", 838 .id = 54, 839 .r = { .max = 100000000 }, 840 .pp = { PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), }, 841 .pp_mux_table = { 9, }, 842 .pp_count = 1, 843 .pp_chg_id = INT_MIN, }, 844 845 { .n = "i2smcc1_gclk", 846 .id = 55, 847 .r = { .max = 100000000 }, 848 .pp = { PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), }, 849 .pp_mux_table = { 9, }, 850 .pp_count = 1, 851 .pp_chg_id = INT_MIN, }, 852 853 { .n = "lcdc_gclk", 854 .id = 56, 855 .r = { .max = 90000000 }, 856 .pp_count = 0, 857 .pp_chg_id = INT_MIN, 858 }, 859 860 { .n = "mcan0_gclk", 861 .id = 58, 862 .r = { .max = 80000000 }, 863 .pp = { PLL_IDS_TO_ARR_ENTRY(USB, DIV0), }, 864 .pp_mux_table = { 12 }, 865 .pp_count = 1, 866 .pp_chg_id = 4, }, 867 868 { .n = "mcan1_gclk", 869 .id = 59, 870 .r = { .max = 80000000 }, 871 .pp = { PLL_IDS_TO_ARR_ENTRY(USB, DIV0), }, 872 .pp_mux_table = { 12 }, 873 .pp_count = 1, 874 .pp_chg_id = 4, }, 875 876 { .n = "mcan2_gclk", 877 .id = 60, 878 .r = { .max = 80000000 }, 879 .pp = { PLL_IDS_TO_ARR_ENTRY(USB, DIV0), }, 880 .pp_mux_table = { 12 }, 881 .pp_count = 1, 882 .pp_chg_id = 4, }, 883 884 { .n = "mcan3_gclk", 885 .id = 61, 886 .r = { .max = 80000000 }, 887 .pp = { PLL_IDS_TO_ARR_ENTRY(USB, DIV0), }, 888 .pp_mux_table = { 12 }, 889 .pp_count = 1, 890 .pp_chg_id = 4, }, 891 892 { .n = "mcan4_gclk", 893 .id = 62, 894 .r = { .max = 80000000 }, 895 .pp = { PLL_IDS_TO_ARR_ENTRY(USB, DIV0), }, 896 .pp_mux_table = { 12 }, 897 .pp_count = 1, 898 .pp_chg_id = 4, }, 899 900 { .n = "pdmc0_gclk", 901 .id = 64, 902 .r = { .max = 80000000 }, 903 .pp = { PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), }, 904 .pp_mux_table = { 9 }, 905 .pp_count = 1, 906 .pp_chg_id = INT_MIN, }, 907 908 { .n = "pdmc1_gclk", 909 .id = 65, 910 .r = { .max = 80000000, }, 911 .pp = { PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), }, 912 .pp_mux_table = { 9, }, 913 .pp_count = 1, 914 .pp_chg_id = INT_MIN, }, 915 916 { .n = "pit64b0_gclk", 917 .id = 66, 918 .r = { .max = 34000000 }, 919 .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), 920 PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, 921 .pp_mux_table = { 8, 9, 10, }, 922 .pp_count = 3, 923 .pp_chg_id = INT_MIN, }, 924 925 { .n = "pit64b1_gclk", 926 .id = 67, 927 .r = { .max = 34000000 }, 928 .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), 929 PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, 930 .pp_mux_table = { 8, 9, 10, }, 931 .pp_count = 3, 932 .pp_chg_id = INT_MIN, }, 933 934 { .n = "pit64b2_gclk", 935 .id = 68, 936 .r = { .max = 34000000 }, 937 .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), 938 PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, 939 .pp_mux_table = { 8, 9, 10, }, 940 .pp_count = 3, 941 .pp_chg_id = INT_MIN, }, 942 943 { .n = "pit64b3_gclk", 944 .id = 69, 945 .r = { .max = 34000000 }, 946 .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), 947 PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, 948 .pp_mux_table = {8, 9, 10, }, 949 .pp_count = 3, 950 .pp_chg_id = INT_MIN, }, 951 952 { .n = "pit64b4_gclk", 953 .id = 70, 954 .r = { .max = 34000000 }, 955 .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), 956 PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, 957 .pp_mux_table = {8, 9, 10, }, 958 .pp_count = 3, 959 .pp_chg_id = INT_MIN, }, 960 961 { .n = "pit64b5_gclk", 962 .id = 71, 963 .r = { .max = 34000000 }, 964 .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), 965 PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, 966 .pp_mux_table = {8, 9, 10, }, 967 .pp_count = 3, 968 .pp_chg_id = INT_MIN, }, 969 970 { .n = "qspi0_gclk", 971 .id = 73, 972 .r = { .max = 400000000 }, 973 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, 974 .pp_mux_table = { 5, 8, }, 975 .pp_count = 2, 976 .pp_chg_id = INT_MIN, }, 977 978 { .n = "qspi1_gclk", 979 .id = 74, 980 .r = { .max = 266000000 }, 981 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, 982 .pp_mux_table = { 5, 8, }, 983 .pp_count = 2, 984 .pp_chg_id = INT_MIN, }, 985 986 { .n = "sdmmc0_gclk", 987 .id = 75, 988 .r = { .max = 208000000 }, 989 .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, 990 .pp_mux_table = { 8, 10, }, 991 .pp_count = 2, 992 .pp_chg_id = 4, }, 993 994 { .n = "sdmmc1_gclk", 995 .id = 76, 996 .r = { .max = 208000000 }, 997 .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, 998 .pp_mux_table = { 8, 10, }, 999 .pp_count = 2, 1000 .pp_chg_id = 4, }, 1001 1002 { .n = "sdmmc2_gclk", 1003 .id = 77, 1004 .r = { .max = 208000000 }, 1005 .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, 1006 .pp_mux_table = { 8, 10 }, 1007 .pp_count = 2, 1008 .pp_chg_id = 4, }, 1009 1010 { .n = "spdifrx_gclk", 1011 .id = 79, 1012 .r = { .max = 150000000 }, 1013 .pp = { PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), }, 1014 .pp_mux_table = { 9, }, 1015 .pp_count = 1, 1016 .pp_chg_id = INT_MIN, }, 1017 1018 { .n = "spdiftx_gclk", 1019 .id = 80, 1020 .r = { .max = 25000000 }, 1021 .pp = { PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), }, 1022 .pp_mux_table = { 9, }, 1023 .pp_count = 1, 1024 .pp_chg_id = INT_MIN, }, 1025 1026 { .n = "tcb0_ch0_gclk", 1027 .id = 83, 1028 .r = { .max = 34000000 }, 1029 .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), 1030 PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, 1031 .pp_mux_table = { 8, 9, 10, }, 1032 .pp_count = 3, 1033 .pp_chg_id = INT_MIN, }, 1034 1035 { .n = "tcb1_ch0_gclk", 1036 .id = 86, 1037 .r = { .max = 67000000 }, 1038 .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), 1039 PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, 1040 .pp_mux_table = { 8, 9, 10, }, 1041 .pp_count = 3, 1042 .pp_chg_id = INT_MIN, }, 1043 1044 { .n = "DSI_gclk", 1045 .id = 103, 1046 .r = {.max = 27000000}, 1047 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), }, 1048 .pp_mux_table = {5}, 1049 .pp_count = 1, 1050 .pp_chg_id = INT_MIN, }, 1051 1052 { .n = "I3CC_gclk", 1053 .id = 105, 1054 .r = {.max = 125000000}, 1055 .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), 1056 PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, 1057 .pp_mux_table = {8, 9, 10, }, 1058 .pp_count = 3, 1059 .pp_chg_id = INT_MIN, }, 1060 }; 1061 1062 /* MCK0 characteristics. */ 1063 static const struct clk_master_characteristics mck0_characteristics = { 1064 .output = { .min = 32768, .max = 200000000 }, 1065 .divisors = { 1, 2, 4, 3, 5 }, 1066 .have_div3_pres = 1, 1067 }; 1068 1069 /* MCK0 layout. */ 1070 static const struct clk_master_layout mck0_layout = { 1071 .mask = 0x773, 1072 .pres_shift = 4, 1073 .offset = 0x28, 1074 }; 1075 1076 /* Programmable clock layout. */ 1077 static const struct clk_programmable_layout programmable_layout = { 1078 .pres_mask = 0xff, 1079 .pres_shift = 8, 1080 .css_mask = 0x1f, 1081 .have_slck_mck = 0, 1082 .is_pres_direct = 1, 1083 }; 1084 1085 /* Peripheral clock layout. */ 1086 static const struct clk_pcr_layout sama7d65_pcr_layout = { 1087 .offset = 0x88, 1088 .cmd = BIT(31), 1089 .gckcss_mask = GENMASK(12, 8), 1090 .pid_mask = GENMASK(6, 0), 1091 }; 1092 1093 static void __init sama7d65_pmc_setup(struct device_node *np) 1094 { 1095 const char *main_xtal_name = "main_xtal"; 1096 struct pmc_data *sama7d65_pmc; 1097 const char *parent_names[11]; 1098 void **alloc_mem = NULL; 1099 int alloc_mem_size = 0; 1100 struct regmap *regmap; 1101 struct clk_hw *hw, *main_rc_hw, *main_osc_hw, *main_xtal_hw; 1102 struct clk_hw *td_slck_hw, *md_slck_hw; 1103 static struct clk_parent_data parent_data; 1104 struct clk_hw *parent_hws[10]; 1105 bool bypass; 1106 int i, j; 1107 1108 td_slck_hw = __clk_get_hw(of_clk_get_by_name(np, "td_slck")); 1109 md_slck_hw = __clk_get_hw(of_clk_get_by_name(np, "md_slck")); 1110 main_xtal_hw = __clk_get_hw(of_clk_get_by_name(np, main_xtal_name)); 1111 1112 if (!td_slck_hw || !md_slck_hw || !main_xtal_hw) 1113 return; 1114 1115 regmap = device_node_to_regmap(np); 1116 if (IS_ERR(regmap)) 1117 return; 1118 1119 sama7d65_pmc = pmc_data_allocate(PMC_INDEX_MAX, 1120 nck(sama7d65_systemck), 1121 nck(sama7d65_periphck), 1122 nck(sama7d65_gck), 8); 1123 if (!sama7d65_pmc) 1124 return; 1125 1126 alloc_mem = kmalloc(sizeof(void *) * 1127 (ARRAY_SIZE(sama7d65_mckx) + ARRAY_SIZE(sama7d65_gck)), 1128 GFP_KERNEL); 1129 if (!alloc_mem) 1130 goto err_free; 1131 1132 main_rc_hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000, 1133 50000000); 1134 if (IS_ERR(main_rc_hw)) 1135 goto err_free; 1136 1137 bypass = of_property_read_bool(np, "atmel,osc-bypass"); 1138 1139 parent_data.name = main_xtal_name; 1140 parent_data.fw_name = main_xtal_name; 1141 main_osc_hw = at91_clk_register_main_osc(regmap, "main_osc", NULL, 1142 &parent_data, bypass); 1143 if (IS_ERR(main_osc_hw)) 1144 goto err_free; 1145 1146 parent_hws[0] = main_rc_hw; 1147 parent_hws[1] = main_osc_hw; 1148 hw = at91_clk_register_sam9x5_main(regmap, "mainck", NULL, parent_hws, 2); 1149 if (IS_ERR(hw)) 1150 goto err_free; 1151 1152 sama7d65_pmc->chws[PMC_MAIN] = hw; 1153 1154 for (i = 0; i < PLL_ID_MAX; i++) { 1155 for (j = 0; j < PLL_COMPID_MAX; j++) { 1156 struct clk_hw *parent_hw; 1157 1158 if (!sama7d65_plls[i][j].n) 1159 continue; 1160 1161 switch (sama7d65_plls[i][j].t) { 1162 case PLL_TYPE_FRAC: 1163 switch (sama7d65_plls[i][j].p) { 1164 case SAMA7D65_PLL_PARENT_MAINCK: 1165 parent_hw = sama7d65_pmc->chws[PMC_MAIN]; 1166 break; 1167 case SAMA7D65_PLL_PARENT_MAIN_XTAL: 1168 parent_hw = main_xtal_hw; 1169 break; 1170 default: 1171 /* Should not happen. */ 1172 parent_hw = NULL; 1173 break; 1174 } 1175 1176 hw = sam9x60_clk_register_frac_pll(regmap, 1177 &pmc_pll_lock, sama7d65_plls[i][j].n, 1178 NULL, parent_hw, i, 1179 sama7d65_plls[i][j].c, 1180 sama7d65_plls[i][j].l, 1181 sama7d65_plls[i][j].f); 1182 break; 1183 1184 case PLL_TYPE_DIV: 1185 hw = sam9x60_clk_register_div_pll(regmap, 1186 &pmc_pll_lock, sama7d65_plls[i][j].n, 1187 NULL, sama7d65_plls[i][0].hw, i, 1188 sama7d65_plls[i][j].c, 1189 sama7d65_plls[i][j].l, 1190 sama7d65_plls[i][j].f, 1191 sama7d65_plls[i][j].safe_div); 1192 break; 1193 1194 default: 1195 continue; 1196 } 1197 1198 if (IS_ERR(hw)) 1199 goto err_free; 1200 1201 sama7d65_plls[i][j].hw = hw; 1202 if (sama7d65_plls[i][j].eid) 1203 sama7d65_pmc->chws[sama7d65_plls[i][j].eid] = hw; 1204 } 1205 } 1206 1207 hw = at91_clk_register_master_div(regmap, "mck0", NULL, 1208 sama7d65_plls[PLL_ID_CPU][1].hw, 1209 &mck0_layout, &mck0_characteristics, 1210 &pmc_mck0_lock, CLK_GET_RATE_NOCACHE, 5); 1211 if (IS_ERR(hw)) 1212 goto err_free; 1213 1214 sama7d65_pmc->chws[PMC_MCK] = hw; 1215 sama7d65_mckx[PCK_PARENT_HW_MCK0].hw = hw; 1216 1217 parent_hws[0] = md_slck_hw; 1218 parent_hws[1] = td_slck_hw; 1219 parent_hws[2] = sama7d65_pmc->chws[PMC_MAIN]; 1220 for (i = PCK_PARENT_HW_MCK1; i < ARRAY_SIZE(sama7d65_mckx); i++) { 1221 u8 num_parents = 3 + sama7d65_mckx[i].ep_count; 1222 struct clk_hw *tmp_parent_hws[8]; 1223 u32 *mux_table; 1224 1225 mux_table = kmalloc_array(num_parents, sizeof(*mux_table), 1226 GFP_KERNEL); 1227 if (!mux_table) 1228 goto err_free; 1229 1230 alloc_mem[alloc_mem_size++] = mux_table; 1231 1232 PMC_INIT_TABLE(mux_table, 3); 1233 PMC_FILL_TABLE(&mux_table[3], sama7d65_mckx[i].ep_mux_table, 1234 sama7d65_mckx[i].ep_count); 1235 for (j = 0; j < sama7d65_mckx[i].ep_count; j++) { 1236 u8 pll_id = sama7d65_mckx[i].ep[j].pll_id; 1237 u8 pll_compid = sama7d65_mckx[i].ep[j].pll_compid; 1238 1239 tmp_parent_hws[j] = sama7d65_plls[pll_id][pll_compid].hw; 1240 } 1241 PMC_FILL_TABLE(&parent_hws[3], tmp_parent_hws, 1242 sama7d65_mckx[i].ep_count); 1243 1244 hw = at91_clk_sama7g5_register_master(regmap, sama7d65_mckx[i].n, 1245 num_parents, NULL, parent_hws, 1246 mux_table, &pmc_mckX_lock, 1247 sama7d65_mckx[i].id, 1248 sama7d65_mckx[i].c, 1249 sama7d65_mckx[i].ep_chg_id); 1250 1251 if (IS_ERR(hw)) 1252 goto err_free; 1253 1254 sama7d65_mckx[i].hw = hw; 1255 if (sama7d65_mckx[i].eid) 1256 sama7d65_pmc->chws[sama7d65_mckx[i].eid] = hw; 1257 } 1258 1259 parent_names[0] = "syspll_divpmcck"; 1260 parent_names[1] = "usbpll_divpmcck"; 1261 parent_names[2] = "main_osc"; 1262 hw = sam9x60_clk_register_usb(regmap, "usbck", parent_names, 3); 1263 if (IS_ERR(hw)) 1264 goto err_free; 1265 1266 parent_hws[0] = md_slck_hw; 1267 parent_hws[1] = td_slck_hw; 1268 parent_hws[2] = sama7d65_pmc->chws[PMC_MAIN]; 1269 parent_hws[3] = sama7d65_plls[PLL_ID_SYS][PLL_COMPID_DIV0].hw; 1270 parent_hws[4] = sama7d65_plls[PLL_ID_DDR][PLL_COMPID_DIV0].hw; 1271 parent_hws[5] = sama7d65_plls[PLL_ID_GPU][PLL_COMPID_DIV0].hw; 1272 parent_hws[6] = sama7d65_plls[PLL_ID_BAUD][PLL_COMPID_DIV0].hw; 1273 parent_hws[7] = sama7d65_plls[PLL_ID_AUDIO][PLL_COMPID_DIV0].hw; 1274 parent_hws[8] = sama7d65_plls[PLL_ID_ETH][PLL_COMPID_DIV0].hw; 1275 1276 for (i = 0; i < 8; i++) { 1277 char name[6]; 1278 1279 snprintf(name, sizeof(name), "prog%d", i); 1280 1281 hw = at91_clk_register_programmable(regmap, name, NULL, parent_hws, 1282 9, i, 1283 &programmable_layout, 1284 sama7d65_prog_mux_table); 1285 if (IS_ERR(hw)) 1286 goto err_free; 1287 1288 sama7d65_pmc->pchws[i] = hw; 1289 } 1290 1291 for (i = 0; i < ARRAY_SIZE(sama7d65_systemck); i++) { 1292 hw = at91_clk_register_system(regmap, sama7d65_systemck[i].n, 1293 sama7d65_systemck[i].p, NULL, 1294 sama7d65_systemck[i].id, 0); 1295 if (IS_ERR(hw)) 1296 goto err_free; 1297 1298 sama7d65_pmc->shws[sama7d65_systemck[i].id] = hw; 1299 } 1300 1301 for (i = 0; i < ARRAY_SIZE(sama7d65_periphck); i++) { 1302 hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock, 1303 &sama7d65_pcr_layout, 1304 sama7d65_periphck[i].n, 1305 NULL, 1306 sama7d65_mckx[sama7d65_periphck[i].p].hw, 1307 sama7d65_periphck[i].id, 1308 &sama7d65_periphck[i].r, 1309 sama7d65_periphck[i].chgp ? 0 : 1310 INT_MIN, 0); 1311 if (IS_ERR(hw)) 1312 goto err_free; 1313 1314 sama7d65_pmc->phws[sama7d65_periphck[i].id] = hw; 1315 } 1316 1317 parent_hws[0] = md_slck_hw; 1318 parent_hws[1] = td_slck_hw; 1319 parent_hws[2] = sama7d65_pmc->chws[PMC_MAIN]; 1320 parent_hws[3] = sama7d65_pmc->chws[PMC_MCK1]; 1321 for (i = 0; i < ARRAY_SIZE(sama7d65_gck); i++) { 1322 u8 num_parents = 4 + sama7d65_gck[i].pp_count; 1323 struct clk_hw *tmp_parent_hws[8]; 1324 u32 *mux_table; 1325 1326 mux_table = kmalloc_array(num_parents, sizeof(*mux_table), 1327 GFP_KERNEL); 1328 if (!mux_table) 1329 goto err_free; 1330 1331 alloc_mem[alloc_mem_size++] = mux_table; 1332 1333 PMC_INIT_TABLE(mux_table, 4); 1334 PMC_FILL_TABLE(&mux_table[4], sama7d65_gck[i].pp_mux_table, 1335 sama7d65_gck[i].pp_count); 1336 for (j = 0; j < sama7d65_gck[i].pp_count; j++) { 1337 u8 pll_id = sama7d65_gck[i].pp[j].pll_id; 1338 u8 pll_compid = sama7d65_gck[i].pp[j].pll_compid; 1339 1340 tmp_parent_hws[j] = sama7d65_plls[pll_id][pll_compid].hw; 1341 } 1342 PMC_FILL_TABLE(&parent_hws[4], tmp_parent_hws, 1343 sama7d65_gck[i].pp_count); 1344 1345 hw = at91_clk_register_generated(regmap, &pmc_pcr_lock, 1346 &sama7d65_pcr_layout, 1347 sama7d65_gck[i].n, NULL, 1348 parent_hws, mux_table, 1349 num_parents, 1350 sama7d65_gck[i].id, 1351 &sama7d65_gck[i].r, 1352 sama7d65_gck[i].pp_chg_id); 1353 if (IS_ERR(hw)) 1354 goto err_free; 1355 1356 sama7d65_pmc->ghws[sama7d65_gck[i].id] = hw; 1357 } 1358 1359 of_clk_add_hw_provider(np, of_clk_hw_pmc_get, sama7d65_pmc); 1360 kfree(alloc_mem); 1361 1362 return; 1363 1364 err_free: 1365 if (alloc_mem) { 1366 for (i = 0; i < alloc_mem_size; i++) 1367 kfree(alloc_mem[i]); 1368 kfree(alloc_mem); 1369 } 1370 1371 kfree(sama7d65_pmc); 1372 } 1373 1374 /* Some clks are used for a clocksource */ 1375 CLK_OF_DECLARE(sama7d65_pmc, "microchip,sama7d65-pmc", sama7d65_pmc_setup); 1376