File Index
Files and directories
Sign in
FILE

sama7g5.c

File preview with syntax highlighting.

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