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