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