linux/drivers/clk/at91/sama7g5.c
<<
>>
Prefs
   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
  34static DEFINE_SPINLOCK(pmc_pll_lock);
  35static 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 */
  47enum 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 */
  63enum pll_type {
  64        PLL_TYPE_FRAC,
  65        PLL_TYPE_DIV,
  66};
  67
  68/* Layout for fractional PLLs. */
  69static 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. */
  77static 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. */
  85static 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 */
 101static 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 */
 218static 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 */
 265static 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. */
 281static 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 */
 291static 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 */
 381static 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. */
 762static const struct clk_range pll_outputs[] = {
 763        { .min = 2343750, .max = 1200000000 },
 764};
 765
 766/* PLL characteristics. */
 767static 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. */
 774static 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. */
 781static const struct clk_master_layout mck0_layout = {
 782        .mask = 0x373,
 783        .pres_shift = 4,
 784        .offset = 0x28,
 785};
 786
 787/* Programmable clock layout. */
 788static 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. */
 797static 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
 804static 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
1048err_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 */
1059CLK_OF_DECLARE(sama7g5_pmc, "microchip,sama7g5-pmc", sama7g5_pmc_setup);
1060