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