0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/clk.h>
0011 #include <linux/clk-provider.h>
0012 #include <linux/mfd/syscon.h>
0013 #include <linux/slab.h>
0014
0015 #include <dt-bindings/clock/at91.h>
0016
0017 #include "pmc.h"
0018
0019 #define SAMA7G5_INIT_TABLE(_table, _count) \
0020 do { \
0021 u8 _i; \
0022 for (_i = 0; _i < (_count); _i++) \
0023 (_table)[_i] = _i; \
0024 } while (0)
0025
0026 #define SAMA7G5_FILL_TABLE(_to, _from, _count) \
0027 do { \
0028 u8 _i; \
0029 for (_i = 0; _i < (_count); _i++) { \
0030 (_to)[_i] = (_from)[_i]; \
0031 } \
0032 } while (0)
0033
0034 static DEFINE_SPINLOCK(pmc_pll_lock);
0035 static DEFINE_SPINLOCK(pmc_mck0_lock);
0036 static DEFINE_SPINLOCK(pmc_mckX_lock);
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048 enum pll_ids {
0049 PLL_ID_CPU,
0050 PLL_ID_SYS,
0051 PLL_ID_DDR,
0052 PLL_ID_IMG,
0053 PLL_ID_BAUD,
0054 PLL_ID_AUDIO,
0055 PLL_ID_ETH,
0056 PLL_ID_MAX,
0057 };
0058
0059
0060
0061
0062
0063
0064 enum pll_type {
0065 PLL_TYPE_FRAC,
0066 PLL_TYPE_DIV,
0067 };
0068
0069
0070 static const struct clk_pll_layout pll_layout_frac = {
0071 .mul_mask = GENMASK(31, 24),
0072 .frac_mask = GENMASK(21, 0),
0073 .mul_shift = 24,
0074 .frac_shift = 0,
0075 };
0076
0077
0078 static const struct clk_pll_layout pll_layout_divpmc = {
0079 .div_mask = GENMASK(7, 0),
0080 .endiv_mask = BIT(29),
0081 .div_shift = 0,
0082 .endiv_shift = 29,
0083 };
0084
0085
0086 static const struct clk_pll_layout pll_layout_divio = {
0087 .div_mask = GENMASK(19, 12),
0088 .endiv_mask = BIT(30),
0089 .div_shift = 12,
0090 .endiv_shift = 30,
0091 };
0092
0093
0094
0095
0096
0097
0098 static const struct clk_range cpu_pll_outputs[] = {
0099 { .min = 2343750, .max = 1000000002 },
0100 };
0101
0102
0103 static const struct clk_range pll_outputs[] = {
0104 { .min = 2343750, .max = 1200000000 },
0105 };
0106
0107
0108 static const struct clk_pll_characteristics cpu_pll_characteristics = {
0109 .input = { .min = 12000000, .max = 50000000 },
0110 .num_output = ARRAY_SIZE(cpu_pll_outputs),
0111 .output = cpu_pll_outputs,
0112 };
0113
0114
0115 static const struct clk_pll_characteristics pll_characteristics = {
0116 .input = { .min = 12000000, .max = 50000000 },
0117 .num_output = ARRAY_SIZE(pll_outputs),
0118 .output = pll_outputs,
0119 };
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133 static const struct {
0134 const char *n;
0135 const char *p;
0136 const struct clk_pll_layout *l;
0137 const struct clk_pll_characteristics *c;
0138 unsigned long f;
0139 u8 t;
0140 u8 eid;
0141 u8 safe_div;
0142 } sama7g5_plls[][PLL_ID_MAX] = {
0143 [PLL_ID_CPU] = {
0144 { .n = "cpupll_fracck",
0145 .p = "mainck",
0146 .l = &pll_layout_frac,
0147 .c = &cpu_pll_characteristics,
0148 .t = PLL_TYPE_FRAC,
0149
0150
0151
0152
0153 .f = CLK_IS_CRITICAL, },
0154
0155 { .n = "cpupll_divpmcck",
0156 .p = "cpupll_fracck",
0157 .l = &pll_layout_divpmc,
0158 .c = &cpu_pll_characteristics,
0159 .t = PLL_TYPE_DIV,
0160
0161 .f = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT,
0162 .eid = PMC_CPUPLL,
0163
0164
0165
0166
0167 .safe_div = 15, },
0168 },
0169
0170 [PLL_ID_SYS] = {
0171 { .n = "syspll_fracck",
0172 .p = "mainck",
0173 .l = &pll_layout_frac,
0174 .c = &pll_characteristics,
0175 .t = PLL_TYPE_FRAC,
0176
0177
0178
0179
0180
0181 .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, },
0182
0183 { .n = "syspll_divpmcck",
0184 .p = "syspll_fracck",
0185 .l = &pll_layout_divpmc,
0186 .c = &pll_characteristics,
0187 .t = PLL_TYPE_DIV,
0188
0189
0190
0191
0192 .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,
0193 .eid = PMC_SYSPLL, },
0194 },
0195
0196 [PLL_ID_DDR] = {
0197 { .n = "ddrpll_fracck",
0198 .p = "mainck",
0199 .l = &pll_layout_frac,
0200 .c = &pll_characteristics,
0201 .t = PLL_TYPE_FRAC,
0202
0203
0204
0205
0206 .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, },
0207
0208 { .n = "ddrpll_divpmcck",
0209 .p = "ddrpll_fracck",
0210 .l = &pll_layout_divpmc,
0211 .c = &pll_characteristics,
0212 .t = PLL_TYPE_DIV,
0213
0214 .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, },
0215 },
0216
0217 [PLL_ID_IMG] = {
0218 { .n = "imgpll_fracck",
0219 .p = "mainck",
0220 .l = &pll_layout_frac,
0221 .c = &pll_characteristics,
0222 .t = PLL_TYPE_FRAC,
0223 .f = CLK_SET_RATE_GATE, },
0224
0225 { .n = "imgpll_divpmcck",
0226 .p = "imgpll_fracck",
0227 .l = &pll_layout_divpmc,
0228 .c = &pll_characteristics,
0229 .t = PLL_TYPE_DIV,
0230 .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
0231 CLK_SET_RATE_PARENT, },
0232 },
0233
0234 [PLL_ID_BAUD] = {
0235 { .n = "baudpll_fracck",
0236 .p = "mainck",
0237 .l = &pll_layout_frac,
0238 .c = &pll_characteristics,
0239 .t = PLL_TYPE_FRAC,
0240 .f = CLK_SET_RATE_GATE, },
0241
0242 { .n = "baudpll_divpmcck",
0243 .p = "baudpll_fracck",
0244 .l = &pll_layout_divpmc,
0245 .c = &pll_characteristics,
0246 .t = PLL_TYPE_DIV,
0247 .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
0248 CLK_SET_RATE_PARENT, },
0249 },
0250
0251 [PLL_ID_AUDIO] = {
0252 { .n = "audiopll_fracck",
0253 .p = "main_xtal",
0254 .l = &pll_layout_frac,
0255 .c = &pll_characteristics,
0256 .t = PLL_TYPE_FRAC,
0257 .f = CLK_SET_RATE_GATE, },
0258
0259 { .n = "audiopll_divpmcck",
0260 .p = "audiopll_fracck",
0261 .l = &pll_layout_divpmc,
0262 .c = &pll_characteristics,
0263 .t = PLL_TYPE_DIV,
0264 .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
0265 CLK_SET_RATE_PARENT,
0266 .eid = PMC_AUDIOPMCPLL, },
0267
0268 { .n = "audiopll_diviock",
0269 .p = "audiopll_fracck",
0270 .l = &pll_layout_divio,
0271 .c = &pll_characteristics,
0272 .t = PLL_TYPE_DIV,
0273 .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
0274 CLK_SET_RATE_PARENT,
0275 .eid = PMC_AUDIOIOPLL, },
0276 },
0277
0278 [PLL_ID_ETH] = {
0279 { .n = "ethpll_fracck",
0280 .p = "main_xtal",
0281 .l = &pll_layout_frac,
0282 .c = &pll_characteristics,
0283 .t = PLL_TYPE_FRAC,
0284 .f = CLK_SET_RATE_GATE, },
0285
0286 { .n = "ethpll_divpmcck",
0287 .p = "ethpll_fracck",
0288 .l = &pll_layout_divpmc,
0289 .c = &pll_characteristics,
0290 .t = PLL_TYPE_DIV,
0291 .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
0292 CLK_SET_RATE_PARENT, },
0293 },
0294 };
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308 static const struct {
0309 const char *n;
0310 const char *ep[4];
0311 int ep_chg_id;
0312 u8 ep_count;
0313 u8 ep_mux_table[4];
0314 u8 id;
0315 u8 eid;
0316 u8 c;
0317 } sama7g5_mckx[] = {
0318 { .n = "mck1",
0319 .id = 1,
0320 .ep = { "syspll_divpmcck", },
0321 .ep_mux_table = { 5, },
0322 .ep_count = 1,
0323 .ep_chg_id = INT_MIN,
0324 .eid = PMC_MCK1,
0325 .c = 1, },
0326
0327 { .n = "mck2",
0328 .id = 2,
0329 .ep = { "ddrpll_divpmcck", },
0330 .ep_mux_table = { 6, },
0331 .ep_count = 1,
0332 .ep_chg_id = INT_MIN,
0333 .c = 1, },
0334
0335 { .n = "mck3",
0336 .id = 3,
0337 .ep = { "syspll_divpmcck", "ddrpll_divpmcck", "imgpll_divpmcck", },
0338 .ep_mux_table = { 5, 6, 7, },
0339 .ep_count = 3,
0340 .ep_chg_id = 5, },
0341
0342 { .n = "mck4",
0343 .id = 4,
0344 .ep = { "syspll_divpmcck", },
0345 .ep_mux_table = { 5, },
0346 .ep_count = 1,
0347 .ep_chg_id = INT_MIN,
0348 .c = 1, },
0349 };
0350
0351
0352
0353
0354
0355
0356
0357 static const struct {
0358 const char *n;
0359 const char *p;
0360 u8 id;
0361 } sama7g5_systemck[] = {
0362 { .n = "pck0", .p = "prog0", .id = 8, },
0363 { .n = "pck1", .p = "prog1", .id = 9, },
0364 { .n = "pck2", .p = "prog2", .id = 10, },
0365 { .n = "pck3", .p = "prog3", .id = 11, },
0366 { .n = "pck4", .p = "prog4", .id = 12, },
0367 { .n = "pck5", .p = "prog5", .id = 13, },
0368 { .n = "pck6", .p = "prog6", .id = 14, },
0369 { .n = "pck7", .p = "prog7", .id = 15, },
0370 };
0371
0372
0373 static u32 sama7g5_prog_mux_table[] = { 0, 1, 2, 5, 6, 7, 8, 9, 10, };
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383 static const struct {
0384 const char *n;
0385 const char *p;
0386 struct clk_range r;
0387 u8 chgp;
0388 u8 id;
0389 } sama7g5_periphck[] = {
0390 { .n = "pioA_clk", .p = "mck0", .id = 11, },
0391 { .n = "securam_clk", .p = "mck0", .id = 18, },
0392 { .n = "sfr_clk", .p = "mck1", .id = 19, },
0393 { .n = "hsmc_clk", .p = "mck1", .id = 21, },
0394 { .n = "xdmac0_clk", .p = "mck1", .id = 22, },
0395 { .n = "xdmac1_clk", .p = "mck1", .id = 23, },
0396 { .n = "xdmac2_clk", .p = "mck1", .id = 24, },
0397 { .n = "acc_clk", .p = "mck1", .id = 25, },
0398 { .n = "aes_clk", .p = "mck1", .id = 27, },
0399 { .n = "tzaesbasc_clk", .p = "mck1", .id = 28, },
0400 { .n = "asrc_clk", .p = "mck1", .id = 30, .r = { .max = 200000000, }, },
0401 { .n = "cpkcc_clk", .p = "mck0", .id = 32, },
0402 { .n = "csi_clk", .p = "mck3", .id = 33, .r = { .max = 266000000, }, .chgp = 1, },
0403 { .n = "csi2dc_clk", .p = "mck3", .id = 34, .r = { .max = 266000000, }, .chgp = 1, },
0404 { .n = "eic_clk", .p = "mck1", .id = 37, },
0405 { .n = "flex0_clk", .p = "mck1", .id = 38, },
0406 { .n = "flex1_clk", .p = "mck1", .id = 39, },
0407 { .n = "flex2_clk", .p = "mck1", .id = 40, },
0408 { .n = "flex3_clk", .p = "mck1", .id = 41, },
0409 { .n = "flex4_clk", .p = "mck1", .id = 42, },
0410 { .n = "flex5_clk", .p = "mck1", .id = 43, },
0411 { .n = "flex6_clk", .p = "mck1", .id = 44, },
0412 { .n = "flex7_clk", .p = "mck1", .id = 45, },
0413 { .n = "flex8_clk", .p = "mck1", .id = 46, },
0414 { .n = "flex9_clk", .p = "mck1", .id = 47, },
0415 { .n = "flex10_clk", .p = "mck1", .id = 48, },
0416 { .n = "flex11_clk", .p = "mck1", .id = 49, },
0417 { .n = "gmac0_clk", .p = "mck1", .id = 51, },
0418 { .n = "gmac1_clk", .p = "mck1", .id = 52, },
0419 { .n = "icm_clk", .p = "mck1", .id = 55, },
0420 { .n = "isc_clk", .p = "mck3", .id = 56, .r = { .max = 266000000, }, .chgp = 1, },
0421 { .n = "i2smcc0_clk", .p = "mck1", .id = 57, .r = { .max = 200000000, }, },
0422 { .n = "i2smcc1_clk", .p = "mck1", .id = 58, .r = { .max = 200000000, }, },
0423 { .n = "matrix_clk", .p = "mck1", .id = 60, },
0424 { .n = "mcan0_clk", .p = "mck1", .id = 61, .r = { .max = 200000000, }, },
0425 { .n = "mcan1_clk", .p = "mck1", .id = 62, .r = { .max = 200000000, }, },
0426 { .n = "mcan2_clk", .p = "mck1", .id = 63, .r = { .max = 200000000, }, },
0427 { .n = "mcan3_clk", .p = "mck1", .id = 64, .r = { .max = 200000000, }, },
0428 { .n = "mcan4_clk", .p = "mck1", .id = 65, .r = { .max = 200000000, }, },
0429 { .n = "mcan5_clk", .p = "mck1", .id = 66, .r = { .max = 200000000, }, },
0430 { .n = "pdmc0_clk", .p = "mck1", .id = 68, .r = { .max = 200000000, }, },
0431 { .n = "pdmc1_clk", .p = "mck1", .id = 69, .r = { .max = 200000000, }, },
0432 { .n = "pit64b0_clk", .p = "mck1", .id = 70, },
0433 { .n = "pit64b1_clk", .p = "mck1", .id = 71, },
0434 { .n = "pit64b2_clk", .p = "mck1", .id = 72, },
0435 { .n = "pit64b3_clk", .p = "mck1", .id = 73, },
0436 { .n = "pit64b4_clk", .p = "mck1", .id = 74, },
0437 { .n = "pit64b5_clk", .p = "mck1", .id = 75, },
0438 { .n = "pwm_clk", .p = "mck1", .id = 77, },
0439 { .n = "qspi0_clk", .p = "mck1", .id = 78, },
0440 { .n = "qspi1_clk", .p = "mck1", .id = 79, },
0441 { .n = "sdmmc0_clk", .p = "mck1", .id = 80, },
0442 { .n = "sdmmc1_clk", .p = "mck1", .id = 81, },
0443 { .n = "sdmmc2_clk", .p = "mck1", .id = 82, },
0444 { .n = "sha_clk", .p = "mck1", .id = 83, },
0445 { .n = "spdifrx_clk", .p = "mck1", .id = 84, .r = { .max = 200000000, }, },
0446 { .n = "spdiftx_clk", .p = "mck1", .id = 85, .r = { .max = 200000000, }, },
0447 { .n = "ssc0_clk", .p = "mck1", .id = 86, .r = { .max = 200000000, }, },
0448 { .n = "ssc1_clk", .p = "mck1", .id = 87, .r = { .max = 200000000, }, },
0449 { .n = "tcb0_ch0_clk", .p = "mck1", .id = 88, .r = { .max = 200000000, }, },
0450 { .n = "tcb0_ch1_clk", .p = "mck1", .id = 89, .r = { .max = 200000000, }, },
0451 { .n = "tcb0_ch2_clk", .p = "mck1", .id = 90, .r = { .max = 200000000, }, },
0452 { .n = "tcb1_ch0_clk", .p = "mck1", .id = 91, .r = { .max = 200000000, }, },
0453 { .n = "tcb1_ch1_clk", .p = "mck1", .id = 92, .r = { .max = 200000000, }, },
0454 { .n = "tcb1_ch2_clk", .p = "mck1", .id = 93, .r = { .max = 200000000, }, },
0455 { .n = "tcpca_clk", .p = "mck1", .id = 94, },
0456 { .n = "tcpcb_clk", .p = "mck1", .id = 95, },
0457 { .n = "tdes_clk", .p = "mck1", .id = 96, },
0458 { .n = "trng_clk", .p = "mck1", .id = 97, },
0459 { .n = "udphsa_clk", .p = "mck1", .id = 104, },
0460 { .n = "udphsb_clk", .p = "mck1", .id = 105, },
0461 { .n = "uhphs_clk", .p = "mck1", .id = 106, },
0462 };
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474 static const struct {
0475 const char *n;
0476 const char *pp[8];
0477 const char pp_mux_table[8];
0478 struct clk_range r;
0479 int pp_chg_id;
0480 u8 pp_count;
0481 u8 id;
0482 } sama7g5_gck[] = {
0483 { .n = "adc_gclk",
0484 .id = 26,
0485 .r = { .max = 100000000, },
0486 .pp = { "syspll_divpmcck", "imgpll_divpmcck", "audiopll_divpmcck", },
0487 .pp_mux_table = { 5, 7, 9, },
0488 .pp_count = 3,
0489 .pp_chg_id = INT_MIN, },
0490
0491 { .n = "asrc_gclk",
0492 .id = 30,
0493 .r = { .max = 200000000 },
0494 .pp = { "audiopll_divpmcck", },
0495 .pp_mux_table = { 9, },
0496 .pp_count = 1,
0497 .pp_chg_id = 3, },
0498
0499 { .n = "csi_gclk",
0500 .id = 33,
0501 .r = { .max = 27000000 },
0502 .pp = { "ddrpll_divpmcck", "imgpll_divpmcck", },
0503 .pp_mux_table = { 6, 7, },
0504 .pp_count = 2,
0505 .pp_chg_id = INT_MIN, },
0506
0507 { .n = "flex0_gclk",
0508 .id = 38,
0509 .r = { .max = 200000000 },
0510 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
0511 .pp_mux_table = { 5, 8, },
0512 .pp_count = 2,
0513 .pp_chg_id = INT_MIN, },
0514
0515 { .n = "flex1_gclk",
0516 .id = 39,
0517 .r = { .max = 200000000 },
0518 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
0519 .pp_mux_table = { 5, 8, },
0520 .pp_count = 2,
0521 .pp_chg_id = INT_MIN, },
0522
0523 { .n = "flex2_gclk",
0524 .id = 40,
0525 .r = { .max = 200000000 },
0526 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
0527 .pp_mux_table = { 5, 8, },
0528 .pp_count = 2,
0529 .pp_chg_id = INT_MIN, },
0530
0531 { .n = "flex3_gclk",
0532 .id = 41,
0533 .r = { .max = 200000000 },
0534 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
0535 .pp_mux_table = { 5, 8, },
0536 .pp_count = 2,
0537 .pp_chg_id = INT_MIN, },
0538
0539 { .n = "flex4_gclk",
0540 .id = 42,
0541 .r = { .max = 200000000 },
0542 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
0543 .pp_mux_table = { 5, 8, },
0544 .pp_count = 2,
0545 .pp_chg_id = INT_MIN, },
0546
0547 { .n = "flex5_gclk",
0548 .id = 43,
0549 .r = { .max = 200000000 },
0550 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
0551 .pp_mux_table = { 5, 8, },
0552 .pp_count = 2,
0553 .pp_chg_id = INT_MIN, },
0554
0555 { .n = "flex6_gclk",
0556 .id = 44,
0557 .r = { .max = 200000000 },
0558 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
0559 .pp_mux_table = { 5, 8, },
0560 .pp_count = 2,
0561 .pp_chg_id = INT_MIN, },
0562
0563 { .n = "flex7_gclk",
0564 .id = 45,
0565 .r = { .max = 200000000 },
0566 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
0567 .pp_mux_table = { 5, 8, },
0568 .pp_count = 2,
0569 .pp_chg_id = INT_MIN, },
0570
0571 { .n = "flex8_gclk",
0572 .id = 46,
0573 .r = { .max = 200000000 },
0574 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
0575 .pp_mux_table = { 5, 8, },
0576 .pp_count = 2,
0577 .pp_chg_id = INT_MIN, },
0578
0579 { .n = "flex9_gclk",
0580 .id = 47,
0581 .r = { .max = 200000000 },
0582 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
0583 .pp_mux_table = { 5, 8, },
0584 .pp_count = 2,
0585 .pp_chg_id = INT_MIN, },
0586
0587 { .n = "flex10_gclk",
0588 .id = 48,
0589 .r = { .max = 200000000 },
0590 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
0591 .pp_mux_table = { 5, 8, },
0592 .pp_count = 2,
0593 .pp_chg_id = INT_MIN, },
0594
0595 { .n = "flex11_gclk",
0596 .id = 49,
0597 .r = { .max = 200000000 },
0598 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
0599 .pp_mux_table = { 5, 8, },
0600 .pp_count = 2,
0601 .pp_chg_id = INT_MIN, },
0602
0603 { .n = "gmac0_gclk",
0604 .id = 51,
0605 .r = { .max = 125000000 },
0606 .pp = { "ethpll_divpmcck", },
0607 .pp_mux_table = { 10, },
0608 .pp_count = 1,
0609 .pp_chg_id = 3, },
0610
0611 { .n = "gmac1_gclk",
0612 .id = 52,
0613 .r = { .max = 50000000 },
0614 .pp = { "ethpll_divpmcck", },
0615 .pp_mux_table = { 10, },
0616 .pp_count = 1,
0617 .pp_chg_id = INT_MIN, },
0618
0619 { .n = "gmac0_tsu_gclk",
0620 .id = 53,
0621 .r = { .max = 300000000 },
0622 .pp = { "audiopll_divpmcck", "ethpll_divpmcck", },
0623 .pp_mux_table = { 9, 10, },
0624 .pp_count = 2,
0625 .pp_chg_id = INT_MIN, },
0626
0627 { .n = "gmac1_tsu_gclk",
0628 .id = 54,
0629 .r = { .max = 300000000 },
0630 .pp = { "audiopll_divpmcck", "ethpll_divpmcck", },
0631 .pp_mux_table = { 9, 10, },
0632 .pp_count = 2,
0633 .pp_chg_id = INT_MIN, },
0634
0635 { .n = "i2smcc0_gclk",
0636 .id = 57,
0637 .r = { .max = 100000000 },
0638 .pp = { "syspll_divpmcck", "audiopll_divpmcck", },
0639 .pp_mux_table = { 5, 9, },
0640 .pp_count = 2,
0641 .pp_chg_id = 4, },
0642
0643 { .n = "i2smcc1_gclk",
0644 .id = 58,
0645 .r = { .max = 100000000 },
0646 .pp = { "syspll_divpmcck", "audiopll_divpmcck", },
0647 .pp_mux_table = { 5, 9, },
0648 .pp_count = 2,
0649 .pp_chg_id = 4, },
0650
0651 { .n = "mcan0_gclk",
0652 .id = 61,
0653 .r = { .max = 200000000 },
0654 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
0655 .pp_mux_table = { 5, 8, },
0656 .pp_count = 2,
0657 .pp_chg_id = INT_MIN, },
0658
0659 { .n = "mcan1_gclk",
0660 .id = 62,
0661 .r = { .max = 200000000 },
0662 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
0663 .pp_mux_table = { 5, 8, },
0664 .pp_count = 2,
0665 .pp_chg_id = INT_MIN, },
0666
0667 { .n = "mcan2_gclk",
0668 .id = 63,
0669 .r = { .max = 200000000 },
0670 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
0671 .pp_mux_table = { 5, 8, },
0672 .pp_count = 2,
0673 .pp_chg_id = INT_MIN, },
0674
0675 { .n = "mcan3_gclk",
0676 .id = 64,
0677 .r = { .max = 200000000 },
0678 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
0679 .pp_mux_table = { 5, 8, },
0680 .pp_count = 2,
0681 .pp_chg_id = INT_MIN, },
0682
0683 { .n = "mcan4_gclk",
0684 .id = 65,
0685 .r = { .max = 200000000 },
0686 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
0687 .pp_mux_table = { 5, 8, },
0688 .pp_count = 2,
0689 .pp_chg_id = INT_MIN, },
0690
0691 { .n = "mcan5_gclk",
0692 .id = 66,
0693 .r = { .max = 200000000 },
0694 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
0695 .pp_mux_table = { 5, 8, },
0696 .pp_count = 2,
0697 .pp_chg_id = INT_MIN, },
0698
0699 { .n = "pdmc0_gclk",
0700 .id = 68,
0701 .r = { .max = 50000000 },
0702 .pp = { "syspll_divpmcck", "audiopll_divpmcck", },
0703 .pp_mux_table = { 5, 9, },
0704 .pp_count = 2,
0705 .pp_chg_id = INT_MIN, },
0706
0707 { .n = "pdmc1_gclk",
0708 .id = 69,
0709 .r = { .max = 50000000, },
0710 .pp = { "syspll_divpmcck", "audiopll_divpmcck", },
0711 .pp_mux_table = { 5, 9, },
0712 .pp_count = 2,
0713 .pp_chg_id = INT_MIN, },
0714
0715 { .n = "pit64b0_gclk",
0716 .id = 70,
0717 .r = { .max = 200000000 },
0718 .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
0719 "audiopll_divpmcck", "ethpll_divpmcck", },
0720 .pp_mux_table = { 5, 7, 8, 9, 10, },
0721 .pp_count = 5,
0722 .pp_chg_id = INT_MIN, },
0723
0724 { .n = "pit64b1_gclk",
0725 .id = 71,
0726 .r = { .max = 200000000 },
0727 .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
0728 "audiopll_divpmcck", "ethpll_divpmcck", },
0729 .pp_mux_table = { 5, 7, 8, 9, 10, },
0730 .pp_count = 5,
0731 .pp_chg_id = INT_MIN, },
0732
0733 { .n = "pit64b2_gclk",
0734 .id = 72,
0735 .r = { .max = 200000000 },
0736 .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
0737 "audiopll_divpmcck", "ethpll_divpmcck", },
0738 .pp_mux_table = { 5, 7, 8, 9, 10, },
0739 .pp_count = 5,
0740 .pp_chg_id = INT_MIN, },
0741
0742 { .n = "pit64b3_gclk",
0743 .id = 73,
0744 .r = { .max = 200000000 },
0745 .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
0746 "audiopll_divpmcck", "ethpll_divpmcck", },
0747 .pp_mux_table = { 5, 7, 8, 9, 10, },
0748 .pp_count = 5,
0749 .pp_chg_id = INT_MIN, },
0750
0751 { .n = "pit64b4_gclk",
0752 .id = 74,
0753 .r = { .max = 200000000 },
0754 .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
0755 "audiopll_divpmcck", "ethpll_divpmcck", },
0756 .pp_mux_table = { 5, 7, 8, 9, 10, },
0757 .pp_count = 5,
0758 .pp_chg_id = INT_MIN, },
0759
0760 { .n = "pit64b5_gclk",
0761 .id = 75,
0762 .r = { .max = 200000000 },
0763 .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
0764 "audiopll_divpmcck", "ethpll_divpmcck", },
0765 .pp_mux_table = { 5, 7, 8, 9, 10, },
0766 .pp_count = 5,
0767 .pp_chg_id = INT_MIN, },
0768
0769 { .n = "qspi0_gclk",
0770 .id = 78,
0771 .r = { .max = 200000000 },
0772 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
0773 .pp_mux_table = { 5, 8, },
0774 .pp_count = 2,
0775 .pp_chg_id = INT_MIN, },
0776
0777 { .n = "qspi1_gclk",
0778 .id = 79,
0779 .r = { .max = 200000000 },
0780 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
0781 .pp_mux_table = { 5, 8, },
0782 .pp_count = 2,
0783 .pp_chg_id = INT_MIN, },
0784
0785 { .n = "sdmmc0_gclk",
0786 .id = 80,
0787 .r = { .max = 208000000 },
0788 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
0789 .pp_mux_table = { 5, 8, },
0790 .pp_count = 2,
0791 .pp_chg_id = 4, },
0792
0793 { .n = "sdmmc1_gclk",
0794 .id = 81,
0795 .r = { .max = 208000000 },
0796 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
0797 .pp_mux_table = { 5, 8, },
0798 .pp_count = 2,
0799 .pp_chg_id = 4, },
0800
0801 { .n = "sdmmc2_gclk",
0802 .id = 82,
0803 .r = { .max = 208000000 },
0804 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
0805 .pp_mux_table = { 5, 8, },
0806 .pp_count = 2,
0807 .pp_chg_id = 4, },
0808
0809 { .n = "spdifrx_gclk",
0810 .id = 84,
0811 .r = { .max = 150000000 },
0812 .pp = { "syspll_divpmcck", "audiopll_divpmcck", },
0813 .pp_mux_table = { 5, 9, },
0814 .pp_count = 2,
0815 .pp_chg_id = 4, },
0816
0817 { .n = "spdiftx_gclk",
0818 .id = 85,
0819 .r = { .max = 25000000 },
0820 .pp = { "syspll_divpmcck", "audiopll_divpmcck", },
0821 .pp_mux_table = { 5, 9, },
0822 .pp_count = 2,
0823 .pp_chg_id = 4, },
0824
0825 { .n = "tcb0_ch0_gclk",
0826 .id = 88,
0827 .r = { .max = 200000000 },
0828 .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
0829 "audiopll_divpmcck", "ethpll_divpmcck", },
0830 .pp_mux_table = { 5, 7, 8, 9, 10, },
0831 .pp_count = 5,
0832 .pp_chg_id = INT_MIN, },
0833
0834 { .n = "tcb1_ch0_gclk",
0835 .id = 91,
0836 .r = { .max = 200000000 },
0837 .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
0838 "audiopll_divpmcck", "ethpll_divpmcck", },
0839 .pp_mux_table = { 5, 7, 8, 9, 10, },
0840 .pp_count = 5,
0841 .pp_chg_id = INT_MIN, },
0842
0843 { .n = "tcpca_gclk",
0844 .id = 94,
0845 .r = { .max = 32768, },
0846 .pp_chg_id = INT_MIN, },
0847
0848 { .n = "tcpcb_gclk",
0849 .id = 95,
0850 .r = { .max = 32768, },
0851 .pp_chg_id = INT_MIN, },
0852 };
0853
0854
0855 static const struct clk_master_characteristics mck0_characteristics = {
0856 .output = { .min = 32768, .max = 200000000 },
0857 .divisors = { 1, 2, 4, 3, 5 },
0858 .have_div3_pres = 1,
0859 };
0860
0861
0862 static const struct clk_master_layout mck0_layout = {
0863 .mask = 0x773,
0864 .pres_shift = 4,
0865 .offset = 0x28,
0866 };
0867
0868
0869 static const struct clk_programmable_layout programmable_layout = {
0870 .pres_mask = 0xff,
0871 .pres_shift = 8,
0872 .css_mask = 0x1f,
0873 .have_slck_mck = 0,
0874 .is_pres_direct = 1,
0875 };
0876
0877
0878 static const struct clk_pcr_layout sama7g5_pcr_layout = {
0879 .offset = 0x88,
0880 .cmd = BIT(31),
0881 .gckcss_mask = GENMASK(12, 8),
0882 .pid_mask = GENMASK(6, 0),
0883 };
0884
0885 static void __init sama7g5_pmc_setup(struct device_node *np)
0886 {
0887 const char *td_slck_name, *md_slck_name, *mainxtal_name;
0888 struct pmc_data *sama7g5_pmc;
0889 const char *parent_names[10];
0890 void **alloc_mem = NULL;
0891 int alloc_mem_size = 0;
0892 struct regmap *regmap;
0893 struct clk_hw *hw;
0894 bool bypass;
0895 int i, j;
0896
0897 i = of_property_match_string(np, "clock-names", "td_slck");
0898 if (i < 0)
0899 return;
0900
0901 td_slck_name = of_clk_get_parent_name(np, i);
0902
0903 i = of_property_match_string(np, "clock-names", "md_slck");
0904 if (i < 0)
0905 return;
0906
0907 md_slck_name = of_clk_get_parent_name(np, i);
0908
0909 i = of_property_match_string(np, "clock-names", "main_xtal");
0910 if (i < 0)
0911 return;
0912
0913 mainxtal_name = of_clk_get_parent_name(np, i);
0914
0915 regmap = device_node_to_regmap(np);
0916 if (IS_ERR(regmap))
0917 return;
0918
0919 sama7g5_pmc = pmc_data_allocate(PMC_MCK1 + 1,
0920 nck(sama7g5_systemck),
0921 nck(sama7g5_periphck),
0922 nck(sama7g5_gck), 8);
0923 if (!sama7g5_pmc)
0924 return;
0925
0926 alloc_mem = kmalloc(sizeof(void *) *
0927 (ARRAY_SIZE(sama7g5_mckx) + ARRAY_SIZE(sama7g5_gck)),
0928 GFP_KERNEL);
0929 if (!alloc_mem)
0930 goto err_free;
0931
0932 hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000,
0933 50000000);
0934 if (IS_ERR(hw))
0935 goto err_free;
0936
0937 bypass = of_property_read_bool(np, "atmel,osc-bypass");
0938
0939 hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
0940 bypass);
0941 if (IS_ERR(hw))
0942 goto err_free;
0943
0944 parent_names[0] = "main_rc_osc";
0945 parent_names[1] = "main_osc";
0946 hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2);
0947 if (IS_ERR(hw))
0948 goto err_free;
0949
0950 sama7g5_pmc->chws[PMC_MAIN] = hw;
0951
0952 for (i = 0; i < PLL_ID_MAX; i++) {
0953 for (j = 0; j < 3; j++) {
0954 struct clk_hw *parent_hw;
0955
0956 if (!sama7g5_plls[i][j].n)
0957 continue;
0958
0959 switch (sama7g5_plls[i][j].t) {
0960 case PLL_TYPE_FRAC:
0961 if (!strcmp(sama7g5_plls[i][j].p, "mainck"))
0962 parent_hw = sama7g5_pmc->chws[PMC_MAIN];
0963 else
0964 parent_hw = __clk_get_hw(of_clk_get_by_name(np,
0965 sama7g5_plls[i][j].p));
0966
0967 hw = sam9x60_clk_register_frac_pll(regmap,
0968 &pmc_pll_lock, sama7g5_plls[i][j].n,
0969 sama7g5_plls[i][j].p, parent_hw, i,
0970 sama7g5_plls[i][j].c,
0971 sama7g5_plls[i][j].l,
0972 sama7g5_plls[i][j].f);
0973 break;
0974
0975 case PLL_TYPE_DIV:
0976 hw = sam9x60_clk_register_div_pll(regmap,
0977 &pmc_pll_lock, sama7g5_plls[i][j].n,
0978 sama7g5_plls[i][j].p, i,
0979 sama7g5_plls[i][j].c,
0980 sama7g5_plls[i][j].l,
0981 sama7g5_plls[i][j].f,
0982 sama7g5_plls[i][j].safe_div);
0983 break;
0984
0985 default:
0986 continue;
0987 }
0988
0989 if (IS_ERR(hw))
0990 goto err_free;
0991
0992 if (sama7g5_plls[i][j].eid)
0993 sama7g5_pmc->chws[sama7g5_plls[i][j].eid] = hw;
0994 }
0995 }
0996
0997 parent_names[0] = "cpupll_divpmcck";
0998 hw = at91_clk_register_master_div(regmap, "mck0", "cpupll_divpmcck",
0999 &mck0_layout, &mck0_characteristics,
1000 &pmc_mck0_lock, CLK_GET_RATE_NOCACHE, 5);
1001 if (IS_ERR(hw))
1002 goto err_free;
1003
1004 sama7g5_pmc->chws[PMC_MCK] = hw;
1005
1006 parent_names[0] = md_slck_name;
1007 parent_names[1] = td_slck_name;
1008 parent_names[2] = "mainck";
1009 for (i = 0; i < ARRAY_SIZE(sama7g5_mckx); i++) {
1010 u8 num_parents = 3 + sama7g5_mckx[i].ep_count;
1011 u32 *mux_table;
1012
1013 mux_table = kmalloc_array(num_parents, sizeof(*mux_table),
1014 GFP_KERNEL);
1015 if (!mux_table)
1016 goto err_free;
1017
1018 SAMA7G5_INIT_TABLE(mux_table, 3);
1019 SAMA7G5_FILL_TABLE(&mux_table[3], sama7g5_mckx[i].ep_mux_table,
1020 sama7g5_mckx[i].ep_count);
1021 SAMA7G5_FILL_TABLE(&parent_names[3], sama7g5_mckx[i].ep,
1022 sama7g5_mckx[i].ep_count);
1023
1024 hw = at91_clk_sama7g5_register_master(regmap, sama7g5_mckx[i].n,
1025 num_parents, parent_names, mux_table,
1026 &pmc_mckX_lock, sama7g5_mckx[i].id,
1027 sama7g5_mckx[i].c,
1028 sama7g5_mckx[i].ep_chg_id);
1029 if (IS_ERR(hw))
1030 goto err_free;
1031
1032 alloc_mem[alloc_mem_size++] = mux_table;
1033
1034 if (sama7g5_mckx[i].eid)
1035 sama7g5_pmc->chws[sama7g5_mckx[i].eid] = hw;
1036 }
1037
1038 hw = at91_clk_sama7g5_register_utmi(regmap, "utmick", "main_xtal");
1039 if (IS_ERR(hw))
1040 goto err_free;
1041
1042 sama7g5_pmc->chws[PMC_UTMI] = hw;
1043
1044 parent_names[0] = md_slck_name;
1045 parent_names[1] = td_slck_name;
1046 parent_names[2] = "mainck";
1047 parent_names[3] = "syspll_divpmcck";
1048 parent_names[4] = "ddrpll_divpmcck";
1049 parent_names[5] = "imgpll_divpmcck";
1050 parent_names[6] = "baudpll_divpmcck";
1051 parent_names[7] = "audiopll_divpmcck";
1052 parent_names[8] = "ethpll_divpmcck";
1053 for (i = 0; i < 8; i++) {
1054 char name[6];
1055
1056 snprintf(name, sizeof(name), "prog%d", i);
1057
1058 hw = at91_clk_register_programmable(regmap, name, parent_names,
1059 9, i,
1060 &programmable_layout,
1061 sama7g5_prog_mux_table);
1062 if (IS_ERR(hw))
1063 goto err_free;
1064
1065 sama7g5_pmc->pchws[i] = hw;
1066 }
1067
1068 for (i = 0; i < ARRAY_SIZE(sama7g5_systemck); i++) {
1069 hw = at91_clk_register_system(regmap, sama7g5_systemck[i].n,
1070 sama7g5_systemck[i].p,
1071 sama7g5_systemck[i].id);
1072 if (IS_ERR(hw))
1073 goto err_free;
1074
1075 sama7g5_pmc->shws[sama7g5_systemck[i].id] = hw;
1076 }
1077
1078 for (i = 0; i < ARRAY_SIZE(sama7g5_periphck); i++) {
1079 hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
1080 &sama7g5_pcr_layout,
1081 sama7g5_periphck[i].n,
1082 sama7g5_periphck[i].p,
1083 sama7g5_periphck[i].id,
1084 &sama7g5_periphck[i].r,
1085 sama7g5_periphck[i].chgp ? 0 :
1086 INT_MIN);
1087 if (IS_ERR(hw))
1088 goto err_free;
1089
1090 sama7g5_pmc->phws[sama7g5_periphck[i].id] = hw;
1091 }
1092
1093 parent_names[0] = md_slck_name;
1094 parent_names[1] = td_slck_name;
1095 parent_names[2] = "mainck";
1096 for (i = 0; i < ARRAY_SIZE(sama7g5_gck); i++) {
1097 u8 num_parents = 3 + sama7g5_gck[i].pp_count;
1098 u32 *mux_table;
1099
1100 mux_table = kmalloc_array(num_parents, sizeof(*mux_table),
1101 GFP_KERNEL);
1102 if (!mux_table)
1103 goto err_free;
1104
1105 SAMA7G5_INIT_TABLE(mux_table, 3);
1106 SAMA7G5_FILL_TABLE(&mux_table[3], sama7g5_gck[i].pp_mux_table,
1107 sama7g5_gck[i].pp_count);
1108 SAMA7G5_FILL_TABLE(&parent_names[3], sama7g5_gck[i].pp,
1109 sama7g5_gck[i].pp_count);
1110
1111 hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
1112 &sama7g5_pcr_layout,
1113 sama7g5_gck[i].n,
1114 parent_names, mux_table,
1115 num_parents,
1116 sama7g5_gck[i].id,
1117 &sama7g5_gck[i].r,
1118 sama7g5_gck[i].pp_chg_id);
1119 if (IS_ERR(hw))
1120 goto err_free;
1121
1122 sama7g5_pmc->ghws[sama7g5_gck[i].id] = hw;
1123 alloc_mem[alloc_mem_size++] = mux_table;
1124 }
1125
1126 of_clk_add_hw_provider(np, of_clk_hw_pmc_get, sama7g5_pmc);
1127
1128 return;
1129
1130 err_free:
1131 if (alloc_mem) {
1132 for (i = 0; i < alloc_mem_size; i++)
1133 kfree(alloc_mem[i]);
1134 kfree(alloc_mem);
1135 }
1136
1137 kfree(sama7g5_pmc);
1138 }
1139
1140
1141 CLK_OF_DECLARE(sama7g5_pmc, "microchip,sama7g5-pmc", sama7g5_pmc_setup);