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