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_mckX_lock); 36 37 /** 38 * PLL clocks identifiers 39 * @PLL_ID_CPU: CPU PLL identifier 40 * @PLL_ID_SYS: System PLL identifier 41 * @PLL_ID_DDR: DDR PLL identifier 42 * @PLL_ID_IMG: Image subsystem PLL identifier 43 * @PLL_ID_BAUD: Baud PLL identifier 44 * @PLL_ID_AUDIO: Audio PLL identifier 45 * @PLL_ID_ETH: Ethernet PLL identifier 46 */ 47 enum pll_ids { 48 PLL_ID_CPU, 49 PLL_ID_SYS, 50 PLL_ID_DDR, 51 PLL_ID_IMG, 52 PLL_ID_BAUD, 53 PLL_ID_AUDIO, 54 PLL_ID_ETH, 55 PLL_ID_MAX, 56 }; 57 58 /** 59 * PLL type identifiers 60 * @PLL_TYPE_FRAC: fractional PLL identifier 61 * @PLL_TYPE_DIV: divider PLL identifier 62 */ 63 enum pll_type { 64 PLL_TYPE_FRAC, 65 PLL_TYPE_DIV, 66 }; 67 68 /* Layout for fractional PLLs. */ 69 static const struct clk_pll_layout pll_layout_frac = { 70 .mul_mask = GENMASK(31, 24), 71 .frac_mask = GENMASK(21, 0), 72 .mul_shift = 24, 73 .frac_shift = 0, 74 }; 75 76 /* Layout for DIVPMC dividers. */ 77 static const struct clk_pll_layout pll_layout_divpmc = { 78 .div_mask = GENMASK(7, 0), 79 .endiv_mask = BIT(29), 80 .div_shift = 0, 81 .endiv_shift = 29, 82 }; 83 84 /* Layout for DIVIO dividers. */ 85 static const struct clk_pll_layout pll_layout_divio = { 86 .div_mask = GENMASK(19, 12), 87 .endiv_mask = BIT(30), 88 .div_shift = 12, 89 .endiv_shift = 30, 90 }; 91 92 /** 93 * PLL clocks description 94 * @n: clock name 95 * @p: clock parent 96 * @l: clock layout 97 * @t: clock type 98 * @f: true if clock is critical and cannot be disabled 99 * @eid: export index in sama7g5->chws[] array 100 */ 101 static const struct { 102 const char *n; 103 const char *p; 104 const struct clk_pll_layout *l; 105 u8 t; 106 u8 c; 107 u8 eid; 108 } sama7g5_plls[][PLL_ID_MAX] = { 109 [PLL_ID_CPU] = { 110 { .n = "cpupll_fracck", 111 .p = "mainck", 112 .l = &pll_layout_frac, 113 .t = PLL_TYPE_FRAC, 114 .c = 1, }, 115 116 { .n = "cpupll_divpmcck", 117 .p = "cpupll_fracck", 118 .l = &pll_layout_divpmc, 119 .t = PLL_TYPE_DIV, 120 .c = 1, }, 121 }, 122 123 [PLL_ID_SYS] = { 124 { .n = "syspll_fracck", 125 .p = "mainck", 126 .l = &pll_layout_frac, 127 .t = PLL_TYPE_FRAC, 128 .c = 1, }, 129 130 { .n = "syspll_divpmcck", 131 .p = "syspll_fracck", 132 .l = &pll_layout_divpmc, 133 .t = PLL_TYPE_DIV, 134 .c = 1, }, 135 }, 136 137 [PLL_ID_DDR] = { 138 { .n = "ddrpll_fracck", 139 .p = "mainck", 140 .l = &pll_layout_frac, 141 .t = PLL_TYPE_FRAC, 142 .c = 1, }, 143 144 { .n = "ddrpll_divpmcck", 145 .p = "ddrpll_fracck", 146 .l = &pll_layout_divpmc, 147 .t = PLL_TYPE_DIV, 148 .c = 1, }, 149 }, 150 151 [PLL_ID_IMG] = { 152 { .n = "imgpll_fracck", 153 .p = "mainck", 154 .l = &pll_layout_frac, 155 .t = PLL_TYPE_FRAC, }, 156 157 { .n = "imgpll_divpmcck", 158 .p = "imgpll_fracck", 159 .l = &pll_layout_divpmc, 160 .t = PLL_TYPE_DIV, }, 161 }, 162 163 [PLL_ID_BAUD] = { 164 { .n = "baudpll_fracck", 165 .p = "mainck", 166 .l = &pll_layout_frac, 167 .t = PLL_TYPE_FRAC, }, 168 169 { .n = "baudpll_divpmcck", 170 .p = "baudpll_fracck", 171 .l = &pll_layout_divpmc, 172 .t = PLL_TYPE_DIV, }, 173 }, 174 175 [PLL_ID_AUDIO] = { 176 { .n = "audiopll_fracck", 177 .p = "main_xtal", 178 .l = &pll_layout_frac, 179 .t = PLL_TYPE_FRAC, }, 180 181 { .n = "audiopll_divpmcck", 182 .p = "audiopll_fracck", 183 .l = &pll_layout_divpmc, 184 .t = PLL_TYPE_DIV, 185 .eid = PMC_I2S0_MUX, }, 186 187 { .n = "audiopll_diviock", 188 .p = "audiopll_fracck", 189 .l = &pll_layout_divio, 190 .t = PLL_TYPE_DIV, 191 .eid = PMC_I2S1_MUX, }, 192 }, 193 194 [PLL_ID_ETH] = { 195 { .n = "ethpll_fracck", 196 .p = "main_xtal", 197 .l = &pll_layout_frac, 198 .t = PLL_TYPE_FRAC, }, 199 200 { .n = "ethpll_divpmcck", 201 .p = "ethpll_fracck", 202 .l = &pll_layout_divpmc, 203 .t = PLL_TYPE_DIV, }, 204 }, 205 }; 206 207 /** 208 * Master clock (MCK[1..4]) description 209 * @n: clock name 210 * @ep: extra parents names array 211 * @ep_chg_chg_id: index in parents array that specifies the changeable 212 * parent 213 * @ep_count: extra parents count 214 * @ep_mux_table: mux table for extra parents 215 * @id: clock id 216 * @c: true if clock is critical and cannot be disabled 217 */ 218 static const struct { 219 const char *n; 220 const char *ep[4]; 221 int ep_chg_id; 222 u8 ep_count; 223 u8 ep_mux_table[4]; 224 u8 id; 225 u8 c; 226 } sama7g5_mckx[] = { 227 { .n = "mck1", 228 .id = 1, 229 .ep = { "syspll_divpmcck", }, 230 .ep_mux_table = { 5, }, 231 .ep_count = 1, 232 .ep_chg_id = INT_MIN, 233 .c = 1, }, 234 235 { .n = "mck2", 236 .id = 2, 237 .ep = { "ddrpll_divpmcck", }, 238 .ep_mux_table = { 6, }, 239 .ep_count = 1, 240 .ep_chg_id = INT_MIN, 241 .c = 1, }, 242 243 { .n = "mck3", 244 .id = 3, 245 .ep = { "syspll_divpmcck", "ddrpll_divpmcck", "imgpll_divpmcck", }, 246 .ep_mux_table = { 5, 6, 7, }, 247 .ep_count = 3, 248 .ep_chg_id = 6, }, 249 250 { .n = "mck4", 251 .id = 4, 252 .ep = { "syspll_divpmcck", }, 253 .ep_mux_table = { 5, }, 254 .ep_count = 1, 255 .ep_chg_id = INT_MIN, 256 .c = 1, }, 257 }; 258 259 /** 260 * System clock description 261 * @n: clock name 262 * @p: clock parent name 263 * @id: clock id 264 */ 265 static const struct { 266 const char *n; 267 const char *p; 268 u8 id; 269 } sama7g5_systemck[] = { 270 { .n = "pck0", .p = "prog0", .id = 8, }, 271 { .n = "pck1", .p = "prog1", .id = 9, }, 272 { .n = "pck2", .p = "prog2", .id = 10, }, 273 { .n = "pck3", .p = "prog3", .id = 11, }, 274 { .n = "pck4", .p = "prog4", .id = 12, }, 275 { .n = "pck5", .p = "prog5", .id = 13, }, 276 { .n = "pck6", .p = "prog6", .id = 14, }, 277 { .n = "pck7", .p = "prog7", .id = 15, }, 278 }; 279 280 /* Mux table for programmable clocks. */ 281 static u32 sama7g5_prog_mux_table[] = { 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, }; 282 283 /** 284 * Peripheral clock description 285 * @n: clock name 286 * @p: clock parent name 287 * @r: clock range values 288 * @id: clock id 289 * @chgp: index in parent array of the changeable parent 290 */ 291 static const struct { 292 const char *n; 293 const char *p; 294 struct clk_range r; 295 u8 chgp; 296 u8 id; 297 } sama7g5_periphck[] = { 298 { .n = "pioA_clk", .p = "mck0", .id = 11, }, 299 { .n = "sfr_clk", .p = "mck1", .id = 19, }, 300 { .n = "hsmc_clk", .p = "mck1", .id = 21, }, 301 { .n = "xdmac0_clk", .p = "mck1", .id = 22, }, 302 { .n = "xdmac1_clk", .p = "mck1", .id = 23, }, 303 { .n = "xdmac2_clk", .p = "mck1", .id = 24, }, 304 { .n = "acc_clk", .p = "mck1", .id = 25, }, 305 { .n = "aes_clk", .p = "mck1", .id = 27, }, 306 { .n = "tzaesbasc_clk", .p = "mck1", .id = 28, }, 307 { .n = "asrc_clk", .p = "mck1", .id = 30, .r = { .max = 200000000, }, }, 308 { .n = "cpkcc_clk", .p = "mck0", .id = 32, }, 309 { .n = "csi_clk", .p = "mck3", .id = 33, .r = { .max = 266000000, }, .chgp = 1, }, 310 { .n = "csi2dc_clk", .p = "mck3", .id = 34, .r = { .max = 266000000, }, .chgp = 1, }, 311 { .n = "eic_clk", .p = "mck1", .id = 37, }, 312 { .n = "flex0_clk", .p = "mck1", .id = 38, }, 313 { .n = "flex1_clk", .p = "mck1", .id = 39, }, 314 { .n = "flex2_clk", .p = "mck1", .id = 40, }, 315 { .n = "flex3_clk", .p = "mck1", .id = 41, }, 316 { .n = "flex4_clk", .p = "mck1", .id = 42, }, 317 { .n = "flex5_clk", .p = "mck1", .id = 43, }, 318 { .n = "flex6_clk", .p = "mck1", .id = 44, }, 319 { .n = "flex7_clk", .p = "mck1", .id = 45, }, 320 { .n = "flex8_clk", .p = "mck1", .id = 46, }, 321 { .n = "flex9_clk", .p = "mck1", .id = 47, }, 322 { .n = "flex10_clk", .p = "mck1", .id = 48, }, 323 { .n = "flex11_clk", .p = "mck1", .id = 49, }, 324 { .n = "gmac0_clk", .p = "mck1", .id = 51, }, 325 { .n = "gmac1_clk", .p = "mck1", .id = 52, }, 326 { .n = "icm_clk", .p = "mck1", .id = 55, }, 327 { .n = "isc_clk", .p = "mck3", .id = 56, .r = { .max = 266000000, }, .chgp = 1, }, 328 { .n = "i2smcc0_clk", .p = "mck1", .id = 57, .r = { .max = 200000000, }, }, 329 { .n = "i2smcc1_clk", .p = "mck1", .id = 58, .r = { .max = 200000000, }, }, 330 { .n = "matrix_clk", .p = "mck1", .id = 60, }, 331 { .n = "mcan0_clk", .p = "mck1", .id = 61, .r = { .max = 200000000, }, }, 332 { .n = "mcan1_clk", .p = "mck1", .id = 62, .r = { .max = 200000000, }, }, 333 { .n = "mcan2_clk", .p = "mck1", .id = 63, .r = { .max = 200000000, }, }, 334 { .n = "mcan3_clk", .p = "mck1", .id = 64, .r = { .max = 200000000, }, }, 335 { .n = "mcan4_clk", .p = "mck1", .id = 65, .r = { .max = 200000000, }, }, 336 { .n = "mcan5_clk", .p = "mck1", .id = 66, .r = { .max = 200000000, }, }, 337 { .n = "pdmc0_clk", .p = "mck1", .id = 68, .r = { .max = 200000000, }, }, 338 { .n = "pdmc1_clk", .p = "mck1", .id = 69, .r = { .max = 200000000, }, }, 339 { .n = "pit64b0_clk", .p = "mck1", .id = 70, }, 340 { .n = "pit64b1_clk", .p = "mck1", .id = 71, }, 341 { .n = "pit64b2_clk", .p = "mck1", .id = 72, }, 342 { .n = "pit64b3_clk", .p = "mck1", .id = 73, }, 343 { .n = "pit64b4_clk", .p = "mck1", .id = 74, }, 344 { .n = "pit64b5_clk", .p = "mck1", .id = 75, }, 345 { .n = "pwm_clk", .p = "mck1", .id = 77, }, 346 { .n = "qspi0_clk", .p = "mck1", .id = 78, }, 347 { .n = "qspi1_clk", .p = "mck1", .id = 79, }, 348 { .n = "sdmmc0_clk", .p = "mck1", .id = 80, }, 349 { .n = "sdmmc1_clk", .p = "mck1", .id = 81, }, 350 { .n = "sdmmc2_clk", .p = "mck1", .id = 82, }, 351 { .n = "sha_clk", .p = "mck1", .id = 83, }, 352 { .n = "spdifrx_clk", .p = "mck1", .id = 84, .r = { .max = 200000000, }, }, 353 { .n = "spdiftx_clk", .p = "mck1", .id = 85, .r = { .max = 200000000, }, }, 354 { .n = "ssc0_clk", .p = "mck1", .id = 86, .r = { .max = 200000000, }, }, 355 { .n = "ssc1_clk", .p = "mck1", .id = 87, .r = { .max = 200000000, }, }, 356 { .n = "tcb0_ch0_clk", .p = "mck1", .id = 88, .r = { .max = 200000000, }, }, 357 { .n = "tcb0_ch1_clk", .p = "mck1", .id = 89, .r = { .max = 200000000, }, }, 358 { .n = "tcb0_ch2_clk", .p = "mck1", .id = 90, .r = { .max = 200000000, }, }, 359 { .n = "tcb1_ch0_clk", .p = "mck1", .id = 91, .r = { .max = 200000000, }, }, 360 { .n = "tcb1_ch1_clk", .p = "mck1", .id = 92, .r = { .max = 200000000, }, }, 361 { .n = "tcb1_ch2_clk", .p = "mck1", .id = 93, .r = { .max = 200000000, }, }, 362 { .n = "tcpca_clk", .p = "mck1", .id = 94, }, 363 { .n = "tcpcb_clk", .p = "mck1", .id = 95, }, 364 { .n = "tdes_clk", .p = "mck1", .id = 96, }, 365 { .n = "trng_clk", .p = "mck1", .id = 97, }, 366 { .n = "udphsa_clk", .p = "mck1", .id = 104, }, 367 { .n = "udphsb_clk", .p = "mck1", .id = 105, }, 368 { .n = "uhphs_clk", .p = "mck1", .id = 106, }, 369 }; 370 371 /** 372 * Generic clock description 373 * @n: clock name 374 * @pp: PLL parents 375 * @pp_mux_table: PLL parents mux table 376 * @r: clock output range 377 * @pp_chg_id: id in parrent array of changeable PLL parent 378 * @pp_count: PLL parents count 379 * @id: clock id 380 */ 381 static const struct { 382 const char *n; 383 const char *pp[8]; 384 const char pp_mux_table[8]; 385 struct clk_range r; 386 int pp_chg_id; 387 u8 pp_count; 388 u8 id; 389 } sama7g5_gck[] = { 390 { .n = "adc_gclk", 391 .id = 26, 392 .r = { .max = 100000000, }, 393 .pp = { "syspll_divpmcck", "imgpll_divpmcck", "audiopll_divpmcck", }, 394 .pp_mux_table = { 5, 7, 9, }, 395 .pp_count = 3, 396 .pp_chg_id = INT_MIN, }, 397 398 { .n = "asrc_gclk", 399 .id = 30, 400 .r = { .max = 200000000 }, 401 .pp = { "audiopll_divpmcck", }, 402 .pp_mux_table = { 9, }, 403 .pp_count = 1, 404 .pp_chg_id = 4, }, 405 406 { .n = "csi_gclk", 407 .id = 33, 408 .r = { .max = 27000000 }, 409 .pp = { "ddrpll_divpmcck", "imgpll_divpmcck", }, 410 .pp_mux_table = { 6, 7, }, 411 .pp_count = 2, 412 .pp_chg_id = INT_MIN, }, 413 414 { .n = "flex0_gclk", 415 .id = 38, 416 .r = { .max = 200000000 }, 417 .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, 418 .pp_mux_table = { 5, 8, }, 419 .pp_count = 2, 420 .pp_chg_id = INT_MIN, }, 421 422 { .n = "flex1_gclk", 423 .id = 39, 424 .r = { .max = 200000000 }, 425 .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, 426 .pp_mux_table = { 5, 8, }, 427 .pp_count = 2, 428 .pp_chg_id = INT_MIN, }, 429 430 { .n = "flex2_gclk", 431 .id = 40, 432 .r = { .max = 200000000 }, 433 .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, 434 .pp_mux_table = { 5, 8, }, 435 .pp_count = 2, 436 .pp_chg_id = INT_MIN, }, 437 438 { .n = "flex3_gclk", 439 .id = 41, 440 .r = { .max = 200000000 }, 441 .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, 442 .pp_mux_table = { 5, 8, }, 443 .pp_count = 2, 444 .pp_chg_id = INT_MIN, }, 445 446 { .n = "flex4_gclk", 447 .id = 42, 448 .r = { .max = 200000000 }, 449 .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, 450 .pp_mux_table = { 5, 8, }, 451 .pp_count = 2, 452 .pp_chg_id = INT_MIN, }, 453 454 { .n = "flex5_gclk", 455 .id = 43, 456 .r = { .max = 200000000 }, 457 .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, 458 .pp_mux_table = { 5, 8, }, 459 .pp_count = 2, 460 .pp_chg_id = INT_MIN, }, 461 462 { .n = "flex6_gclk", 463 .id = 44, 464 .r = { .max = 200000000 }, 465 .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, 466 .pp_mux_table = { 5, 8, }, 467 .pp_count = 2, 468 .pp_chg_id = INT_MIN, }, 469 470 { .n = "flex7_gclk", 471 .id = 45, 472 .r = { .max = 200000000 }, 473 .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, 474 .pp_mux_table = { 5, 8, }, 475 .pp_count = 2, 476 .pp_chg_id = INT_MIN, }, 477 478 { .n = "flex8_gclk", 479 .id = 46, 480 .r = { .max = 200000000 }, 481 .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, 482 .pp_mux_table = { 5, 8, }, 483 .pp_count = 2, 484 .pp_chg_id = INT_MIN, }, 485 486 { .n = "flex9_gclk", 487 .id = 47, 488 .r = { .max = 200000000 }, 489 .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, 490 .pp_mux_table = { 5, 8, }, 491 .pp_count = 2, 492 .pp_chg_id = INT_MIN, }, 493 494 { .n = "flex10_gclk", 495 .id = 48, 496 .r = { .max = 200000000 }, 497 .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, 498 .pp_mux_table = { 5, 8, }, 499 .pp_count = 2, 500 .pp_chg_id = INT_MIN, }, 501 502 { .n = "flex11_gclk", 503 .id = 49, 504 .r = { .max = 200000000 }, 505 .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, 506 .pp_mux_table = { 5, 8, }, 507 .pp_count = 2, 508 .pp_chg_id = INT_MIN, }, 509 510 { .n = "gmac0_gclk", 511 .id = 51, 512 .r = { .max = 125000000 }, 513 .pp = { "ethpll_divpmcck", }, 514 .pp_mux_table = { 10, }, 515 .pp_count = 1, 516 .pp_chg_id = 4, }, 517 518 { .n = "gmac1_gclk", 519 .id = 52, 520 .r = { .max = 50000000 }, 521 .pp = { "ethpll_divpmcck", }, 522 .pp_mux_table = { 10, }, 523 .pp_count = 1, 524 .pp_chg_id = INT_MIN, }, 525 526 { .n = "gmac0_tsu_gclk", 527 .id = 53, 528 .r = { .max = 300000000 }, 529 .pp = { "audiopll_divpmcck", "ethpll_divpmcck", }, 530 .pp_mux_table = { 9, 10, }, 531 .pp_count = 2, 532 .pp_chg_id = INT_MIN, }, 533 534 { .n = "gmac1_tsu_gclk", 535 .id = 54, 536 .r = { .max = 300000000 }, 537 .pp = { "audiopll_divpmcck", "ethpll_divpmcck", }, 538 .pp_mux_table = { 9, 10, }, 539 .pp_count = 2, 540 .pp_chg_id = INT_MIN, }, 541 542 { .n = "i2smcc0_gclk", 543 .id = 57, 544 .r = { .max = 100000000 }, 545 .pp = { "syspll_divpmcck", "audiopll_divpmcck", }, 546 .pp_mux_table = { 5, 9, }, 547 .pp_count = 2, 548 .pp_chg_id = 5, }, 549 550 { .n = "i2smcc1_gclk", 551 .id = 58, 552 .r = { .max = 100000000 }, 553 .pp = { "syspll_divpmcck", "audiopll_divpmcck", }, 554 .pp_mux_table = { 5, 9, }, 555 .pp_count = 2, 556 .pp_chg_id = 5, }, 557 558 { .n = "mcan0_gclk", 559 .id = 61, 560 .r = { .max = 200000000 }, 561 .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, 562 .pp_mux_table = { 5, 8, }, 563 .pp_count = 2, 564 .pp_chg_id = INT_MIN, }, 565 566 { .n = "mcan1_gclk", 567 .id = 62, 568 .r = { .max = 200000000 }, 569 .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, 570 .pp_mux_table = { 5, 8, }, 571 .pp_count = 2, 572 .pp_chg_id = INT_MIN, }, 573 574 { .n = "mcan2_gclk", 575 .id = 63, 576 .r = { .max = 200000000 }, 577 .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, 578 .pp_mux_table = { 5, 8, }, 579 .pp_count = 2, 580 .pp_chg_id = INT_MIN, }, 581 582 { .n = "mcan3_gclk", 583 .id = 64, 584 .r = { .max = 200000000 }, 585 .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, 586 .pp_mux_table = { 5, 8, }, 587 .pp_count = 2, 588 .pp_chg_id = INT_MIN, }, 589 590 { .n = "mcan4_gclk", 591 .id = 65, 592 .r = { .max = 200000000 }, 593 .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, 594 .pp_mux_table = { 5, 8, }, 595 .pp_count = 2, 596 .pp_chg_id = INT_MIN, }, 597 598 { .n = "mcan5_gclk", 599 .id = 66, 600 .r = { .max = 200000000 }, 601 .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, 602 .pp_mux_table = { 5, 8, }, 603 .pp_count = 2, 604 .pp_chg_id = INT_MIN, }, 605 606 { .n = "pdmc0_gclk", 607 .id = 68, 608 .r = { .max = 50000000 }, 609 .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, 610 .pp_mux_table = { 5, 8, }, 611 .pp_count = 2, 612 .pp_chg_id = INT_MIN, }, 613 614 { .n = "pdmc1_gclk", 615 .id = 69, 616 .r = { .max = 50000000, }, 617 .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, 618 .pp_mux_table = { 5, 8, }, 619 .pp_count = 2, 620 .pp_chg_id = INT_MIN, }, 621 622 { .n = "pit64b0_gclk", 623 .id = 70, 624 .r = { .max = 200000000 }, 625 .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck", 626 "audiopll_divpmcck", "ethpll_divpmcck", }, 627 .pp_mux_table = { 5, 7, 8, 9, 10, }, 628 .pp_count = 5, 629 .pp_chg_id = INT_MIN, }, 630 631 { .n = "pit64b1_gclk", 632 .id = 71, 633 .r = { .max = 200000000 }, 634 .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck", 635 "audiopll_divpmcck", "ethpll_divpmcck", }, 636 .pp_mux_table = { 5, 7, 8, 9, 10, }, 637 .pp_count = 5, 638 .pp_chg_id = INT_MIN, }, 639 640 { .n = "pit64b2_gclk", 641 .id = 72, 642 .r = { .max = 200000000 }, 643 .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck", 644 "audiopll_divpmcck", "ethpll_divpmcck", }, 645 .pp_mux_table = { 5, 7, 8, 9, 10, }, 646 .pp_count = 5, 647 .pp_chg_id = INT_MIN, }, 648 649 { .n = "pit64b3_gclk", 650 .id = 73, 651 .r = { .max = 200000000 }, 652 .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck", 653 "audiopll_divpmcck", "ethpll_divpmcck", }, 654 .pp_mux_table = { 5, 7, 8, 9, 10, }, 655 .pp_count = 5, 656 .pp_chg_id = INT_MIN, }, 657 658 { .n = "pit64b4_gclk", 659 .id = 74, 660 .r = { .max = 200000000 }, 661 .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck", 662 "audiopll_divpmcck", "ethpll_divpmcck", }, 663 .pp_mux_table = { 5, 7, 8, 9, 10, }, 664 .pp_count = 5, 665 .pp_chg_id = INT_MIN, }, 666 667 { .n = "pit64b5_gclk", 668 .id = 75, 669 .r = { .max = 200000000 }, 670 .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck", 671 "audiopll_divpmcck", "ethpll_divpmcck", }, 672 .pp_mux_table = { 5, 7, 8, 9, 10, }, 673 .pp_count = 5, 674 .pp_chg_id = INT_MIN, }, 675 676 { .n = "qspi0_gclk", 677 .id = 78, 678 .r = { .max = 200000000 }, 679 .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, 680 .pp_mux_table = { 5, 8, }, 681 .pp_count = 2, 682 .pp_chg_id = INT_MIN, }, 683 684 { .n = "qspi1_gclk", 685 .id = 79, 686 .r = { .max = 200000000 }, 687 .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, 688 .pp_mux_table = { 5, 8, }, 689 .pp_count = 2, 690 .pp_chg_id = INT_MIN, }, 691 692 { .n = "sdmmc0_gclk", 693 .id = 80, 694 .r = { .max = 208000000 }, 695 .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, 696 .pp_mux_table = { 5, 8, }, 697 .pp_count = 2, 698 .pp_chg_id = 5, }, 699 700 { .n = "sdmmc1_gclk", 701 .id = 81, 702 .r = { .max = 208000000 }, 703 .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, 704 .pp_mux_table = { 5, 8, }, 705 .pp_count = 2, 706 .pp_chg_id = 5, }, 707 708 { .n = "sdmmc2_gclk", 709 .id = 82, 710 .r = { .max = 208000000 }, 711 .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, 712 .pp_mux_table = { 5, 8, }, 713 .pp_count = 2, 714 .pp_chg_id = 5, }, 715 716 { .n = "spdifrx_gclk", 717 .id = 84, 718 .r = { .max = 150000000 }, 719 .pp = { "syspll_divpmcck", "audiopll_divpmcck", }, 720 .pp_mux_table = { 5, 9, }, 721 .pp_count = 2, 722 .pp_chg_id = 5, }, 723 724 { .n = "spdiftx_gclk", 725 .id = 85, 726 .r = { .max = 25000000 }, 727 .pp = { "syspll_divpmcck", "audiopll_divpmcck", }, 728 .pp_mux_table = { 5, 9, }, 729 .pp_count = 2, 730 .pp_chg_id = 5, }, 731 732 { .n = "tcb0_ch0_gclk", 733 .id = 88, 734 .r = { .max = 200000000 }, 735 .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck", 736 "audiopll_divpmcck", "ethpll_divpmcck", }, 737 .pp_mux_table = { 5, 7, 8, 9, 10, }, 738 .pp_count = 5, 739 .pp_chg_id = INT_MIN, }, 740 741 { .n = "tcb1_ch0_gclk", 742 .id = 91, 743 .r = { .max = 200000000 }, 744 .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck", 745 "audiopll_divpmcck", "ethpll_divpmcck", }, 746 .pp_mux_table = { 5, 7, 8, 9, 10, }, 747 .pp_count = 5, 748 .pp_chg_id = INT_MIN, }, 749 750 { .n = "tcpca_gclk", 751 .id = 94, 752 .r = { .max = 32768, }, 753 .pp_chg_id = INT_MIN, }, 754 755 { .n = "tcpcb_gclk", 756 .id = 95, 757 .r = { .max = 32768, }, 758 .pp_chg_id = INT_MIN, }, 759 }; 760 761 /* PLL output range. */ 762 static const struct clk_range pll_outputs[] = { 763 { .min = 2343750, .max = 1200000000 }, 764 }; 765 766 /* PLL characteristics. */ 767 static const struct clk_pll_characteristics pll_characteristics = { 768 .input = { .min = 12000000, .max = 50000000 }, 769 .num_output = ARRAY_SIZE(pll_outputs), 770 .output = pll_outputs, 771 }; 772 773 /* MCK0 characteristics. */ 774 static const struct clk_master_characteristics mck0_characteristics = { 775 .output = { .min = 140000000, .max = 200000000 }, 776 .divisors = { 1, 2, 4, 3 }, 777 .have_div3_pres = 1, 778 }; 779 780 /* MCK0 layout. */ 781 static const struct clk_master_layout mck0_layout = { 782 .mask = 0x373, 783 .pres_shift = 4, 784 .offset = 0x28, 785 }; 786 787 /* Programmable clock layout. */ 788 static const struct clk_programmable_layout programmable_layout = { 789 .pres_mask = 0xff, 790 .pres_shift = 8, 791 .css_mask = 0x1f, 792 .have_slck_mck = 0, 793 .is_pres_direct = 1, 794 }; 795 796 /* Peripheral clock layout. */ 797 static const struct clk_pcr_layout sama7g5_pcr_layout = { 798 .offset = 0x88, 799 .cmd = BIT(31), 800 .gckcss_mask = GENMASK(12, 8), 801 .pid_mask = GENMASK(6, 0), 802 }; 803 804 static void __init sama7g5_pmc_setup(struct device_node *np) 805 { 806 const char *td_slck_name, *md_slck_name, *mainxtal_name; 807 struct pmc_data *sama7g5_pmc; 808 const char *parent_names[10]; 809 void **alloc_mem = NULL; 810 int alloc_mem_size = 0; 811 struct regmap *regmap; 812 struct clk_hw *hw; 813 bool bypass; 814 int i, j; 815 816 i = of_property_match_string(np, "clock-names", "td_slck"); 817 if (i < 0) 818 return; 819 820 td_slck_name = of_clk_get_parent_name(np, i); 821 822 i = of_property_match_string(np, "clock-names", "md_slck"); 823 if (i < 0) 824 return; 825 826 md_slck_name = of_clk_get_parent_name(np, i); 827 828 i = of_property_match_string(np, "clock-names", "main_xtal"); 829 if (i < 0) 830 return; 831 832 mainxtal_name = of_clk_get_parent_name(np, i); 833 834 regmap = device_node_to_regmap(np); 835 if (IS_ERR(regmap)) 836 return; 837 838 sama7g5_pmc = pmc_data_allocate(PMC_I2S1_MUX + 1, 839 nck(sama7g5_systemck), 840 nck(sama7g5_periphck), 841 nck(sama7g5_gck)); 842 if (!sama7g5_pmc) 843 return; 844 845 alloc_mem = kmalloc(sizeof(void *) * 846 (ARRAY_SIZE(sama7g5_mckx) + ARRAY_SIZE(sama7g5_gck)), 847 GFP_KERNEL); 848 if (!alloc_mem) 849 goto err_free; 850 851 hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000, 852 50000000); 853 if (IS_ERR(hw)) 854 goto err_free; 855 856 bypass = of_property_read_bool(np, "atmel,osc-bypass"); 857 858 hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, 859 bypass); 860 if (IS_ERR(hw)) 861 goto err_free; 862 863 parent_names[0] = "main_rc_osc"; 864 parent_names[1] = "main_osc"; 865 hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2); 866 if (IS_ERR(hw)) 867 goto err_free; 868 869 sama7g5_pmc->chws[PMC_MAIN] = hw; 870 871 for (i = 0; i < PLL_ID_MAX; i++) { 872 for (j = 0; j < 3; j++) { 873 struct clk_hw *parent_hw; 874 875 if (!sama7g5_plls[i][j].n) 876 continue; 877 878 switch (sama7g5_plls[i][j].t) { 879 case PLL_TYPE_FRAC: 880 if (!strcmp(sama7g5_plls[i][j].p, "mainck")) 881 parent_hw = sama7g5_pmc->chws[PMC_MAIN]; 882 else 883 parent_hw = __clk_get_hw(of_clk_get_by_name(np, 884 sama7g5_plls[i][j].p)); 885 886 hw = sam9x60_clk_register_frac_pll(regmap, 887 &pmc_pll_lock, sama7g5_plls[i][j].n, 888 sama7g5_plls[i][j].p, parent_hw, i, 889 &pll_characteristics, 890 sama7g5_plls[i][j].l, 891 sama7g5_plls[i][j].c); 892 break; 893 894 case PLL_TYPE_DIV: 895 hw = sam9x60_clk_register_div_pll(regmap, 896 &pmc_pll_lock, sama7g5_plls[i][j].n, 897 sama7g5_plls[i][j].p, i, 898 &pll_characteristics, 899 sama7g5_plls[i][j].l, 900 sama7g5_plls[i][j].c); 901 break; 902 903 default: 904 continue; 905 } 906 907 if (IS_ERR(hw)) 908 goto err_free; 909 910 if (sama7g5_plls[i][j].eid) 911 sama7g5_pmc->chws[sama7g5_plls[i][j].eid] = hw; 912 } 913 } 914 915 parent_names[0] = md_slck_name; 916 parent_names[1] = "mainck"; 917 parent_names[2] = "cpupll_divpmcck"; 918 parent_names[3] = "syspll_divpmcck"; 919 hw = at91_clk_register_master(regmap, "mck0", 4, parent_names, 920 &mck0_layout, &mck0_characteristics); 921 if (IS_ERR(hw)) 922 goto err_free; 923 924 sama7g5_pmc->chws[PMC_MCK] = hw; 925 926 parent_names[0] = md_slck_name; 927 parent_names[1] = td_slck_name; 928 parent_names[2] = "mainck"; 929 parent_names[3] = "mck0"; 930 for (i = 0; i < ARRAY_SIZE(sama7g5_mckx); i++) { 931 u8 num_parents = 4 + sama7g5_mckx[i].ep_count; 932 u32 *mux_table; 933 934 mux_table = kmalloc_array(num_parents, sizeof(*mux_table), 935 GFP_KERNEL); 936 if (!mux_table) 937 goto err_free; 938 939 SAMA7G5_INIT_TABLE(mux_table, 4); 940 SAMA7G5_FILL_TABLE(&mux_table[4], sama7g5_mckx[i].ep_mux_table, 941 sama7g5_mckx[i].ep_count); 942 SAMA7G5_FILL_TABLE(&parent_names[4], sama7g5_mckx[i].ep, 943 sama7g5_mckx[i].ep_count); 944 945 hw = at91_clk_sama7g5_register_master(regmap, sama7g5_mckx[i].n, 946 num_parents, parent_names, mux_table, 947 &pmc_mckX_lock, sama7g5_mckx[i].id, 948 sama7g5_mckx[i].c, 949 sama7g5_mckx[i].ep_chg_id); 950 if (IS_ERR(hw)) 951 goto err_free; 952 953 alloc_mem[alloc_mem_size++] = mux_table; 954 } 955 956 hw = at91_clk_sama7g5_register_utmi(regmap, "utmick", "main_xtal"); 957 if (IS_ERR(hw)) 958 goto err_free; 959 960 sama7g5_pmc->chws[PMC_UTMI] = hw; 961 962 parent_names[0] = md_slck_name; 963 parent_names[1] = td_slck_name; 964 parent_names[2] = "mainck"; 965 parent_names[3] = "mck0"; 966 parent_names[4] = "syspll_divpmcck"; 967 parent_names[5] = "ddrpll_divpmcck"; 968 parent_names[6] = "imgpll_divpmcck"; 969 parent_names[7] = "baudpll_divpmcck"; 970 parent_names[8] = "audiopll_divpmcck"; 971 parent_names[9] = "ethpll_divpmcck"; 972 for (i = 0; i < 8; i++) { 973 char name[6]; 974 975 snprintf(name, sizeof(name), "prog%d", i); 976 977 hw = at91_clk_register_programmable(regmap, name, parent_names, 978 10, i, 979 &programmable_layout, 980 sama7g5_prog_mux_table); 981 if (IS_ERR(hw)) 982 goto err_free; 983 } 984 985 for (i = 0; i < ARRAY_SIZE(sama7g5_systemck); i++) { 986 hw = at91_clk_register_system(regmap, sama7g5_systemck[i].n, 987 sama7g5_systemck[i].p, 988 sama7g5_systemck[i].id); 989 if (IS_ERR(hw)) 990 goto err_free; 991 992 sama7g5_pmc->shws[sama7g5_systemck[i].id] = hw; 993 } 994 995 for (i = 0; i < ARRAY_SIZE(sama7g5_periphck); i++) { 996 hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock, 997 &sama7g5_pcr_layout, 998 sama7g5_periphck[i].n, 999 sama7g5_periphck[i].p, 1000 sama7g5_periphck[i].id, 1001 &sama7g5_periphck[i].r, 1002 sama7g5_periphck[i].chgp ? 0 : 1003 INT_MIN); 1004 if (IS_ERR(hw)) 1005 goto err_free; 1006 1007 sama7g5_pmc->phws[sama7g5_periphck[i].id] = hw; 1008 } 1009 1010 parent_names[0] = md_slck_name; 1011 parent_names[1] = td_slck_name; 1012 parent_names[2] = "mainck"; 1013 parent_names[3] = "mck0"; 1014 for (i = 0; i < ARRAY_SIZE(sama7g5_gck); i++) { 1015 u8 num_parents = 4 + sama7g5_gck[i].pp_count; 1016 u32 *mux_table; 1017 1018 mux_table = kmalloc_array(num_parents, sizeof(*mux_table), 1019 GFP_KERNEL); 1020 if (!mux_table) 1021 goto err_free; 1022 1023 SAMA7G5_INIT_TABLE(mux_table, 4); 1024 SAMA7G5_FILL_TABLE(&mux_table[4], sama7g5_gck[i].pp_mux_table, 1025 sama7g5_gck[i].pp_count); 1026 SAMA7G5_FILL_TABLE(&parent_names[4], sama7g5_gck[i].pp, 1027 sama7g5_gck[i].pp_count); 1028 1029 hw = at91_clk_register_generated(regmap, &pmc_pcr_lock, 1030 &sama7g5_pcr_layout, 1031 sama7g5_gck[i].n, 1032 parent_names, mux_table, 1033 num_parents, 1034 sama7g5_gck[i].id, 1035 &sama7g5_gck[i].r, 1036 sama7g5_gck[i].pp_chg_id); 1037 if (IS_ERR(hw)) 1038 goto err_free; 1039 1040 sama7g5_pmc->ghws[sama7g5_gck[i].id] = hw; 1041 alloc_mem[alloc_mem_size++] = mux_table; 1042 } 1043 1044 of_clk_add_hw_provider(np, of_clk_hw_pmc_get, sama7g5_pmc); 1045 1046 return; 1047 1048 err_free: 1049 if (alloc_mem) { 1050 for (i = 0; i < alloc_mem_size; i++) 1051 kfree(alloc_mem[i]); 1052 kfree(alloc_mem); 1053 } 1054 1055 pmc_data_free(sama7g5_pmc); 1056 } 1057 1058 /* Some clks are used for a clocksource */ 1059 CLK_OF_DECLARE(sama7g5_pmc, "microchip,sama7g5-pmc", sama7g5_pmc_setup); 1060