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