Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * SAM9X7 PMC code.
  4 *
  5 * Copyright (C) 2023 Microchip Technology Inc. and its subsidiaries
  6 *
  7 * Author: Varshini Rajendran <varshini.rajendran@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(mck_lock);
 21
 22/**
 23 * enum pll_ids - PLL clocks identifiers
 24 * @PLL_ID_PLLA:	PLLA identifier
 25 * @PLL_ID_UPLL:	UPLL identifier
 26 * @PLL_ID_AUDIO:	Audio PLL identifier
 27 * @PLL_ID_LVDS:	LVDS PLL identifier
 28 * @PLL_ID_PLLA_DIV2:	PLLA DIV2 identifier
 29 * @PLL_ID_MAX:		Max PLL Identifier
 30 */
 31enum pll_ids {
 32	PLL_ID_PLLA,
 33	PLL_ID_UPLL,
 34	PLL_ID_AUDIO,
 35	PLL_ID_LVDS,
 36	PLL_ID_PLLA_DIV2,
 37	PLL_ID_MAX,
 38};
 39
 40/**
 41 * enum pll_type - PLL type identifiers
 42 * @PLL_TYPE_FRAC:	fractional PLL identifier
 43 * @PLL_TYPE_DIV:	divider PLL identifier
 44 */
 45enum pll_type {
 46	PLL_TYPE_FRAC,
 47	PLL_TYPE_DIV,
 48};
 49
 50static const struct clk_master_characteristics mck_characteristics = {
 51	.output = { .min = 32000000, .max = 266666667 },
 52	.divisors = { 1, 2, 4, 3, 5},
 53	.have_div3_pres = 1,
 54};
 55
 56static const struct clk_master_layout sam9x7_master_layout = {
 57	.mask = 0x373,
 58	.pres_shift = 4,
 59	.offset = 0x28,
 60};
 61
 62/* Fractional PLL core output range. */
 63static const struct clk_range plla_core_outputs[] = {
 64	{ .min = 375000000, .max = 1600000000 },
 65};
 66
 67static const struct clk_range upll_core_outputs[] = {
 68	{ .min = 600000000, .max = 1200000000 },
 69};
 70
 71static const struct clk_range lvdspll_core_outputs[] = {
 72	{ .min = 400000000, .max = 800000000 },
 73};
 74
 75static const struct clk_range audiopll_core_outputs[] = {
 76	{ .min = 400000000, .max = 800000000 },
 77};
 78
 79static const struct clk_range plladiv2_core_outputs[] = {
 80	{ .min = 375000000, .max = 1600000000 },
 81};
 82
 83/* Fractional PLL output range. */
 84static const struct clk_range plla_outputs[] = {
 85	{ .min = 732421, .max = 800000000 },
 86};
 87
 88static const struct clk_range upll_outputs[] = {
 89	{ .min = 300000000, .max = 600000000 },
 90};
 91
 92static const struct clk_range lvdspll_outputs[] = {
 93	{ .min = 10000000, .max = 800000000 },
 94};
 95
 96static const struct clk_range audiopll_outputs[] = {
 97	{ .min = 10000000, .max = 800000000 },
 98};
 99
100static const struct clk_range plladiv2_outputs[] = {
101	{ .min = 366210, .max = 400000000 },
102};
103
104/* PLL characteristics. */
105static const struct clk_pll_characteristics plla_characteristics = {
106	.input = { .min = 20000000, .max = 50000000 },
107	.num_output = ARRAY_SIZE(plla_outputs),
108	.output = plla_outputs,
109	.core_output = plla_core_outputs,
110};
111
112static const struct clk_pll_characteristics upll_characteristics = {
113	.input = { .min = 20000000, .max = 50000000 },
114	.num_output = ARRAY_SIZE(upll_outputs),
115	.output = upll_outputs,
116	.core_output = upll_core_outputs,
117	.upll = true,
118};
119
120static const struct clk_pll_characteristics lvdspll_characteristics = {
121	.input = { .min = 20000000, .max = 50000000 },
122	.num_output = ARRAY_SIZE(lvdspll_outputs),
123	.output = lvdspll_outputs,
124	.core_output = lvdspll_core_outputs,
125};
126
127static const struct clk_pll_characteristics audiopll_characteristics = {
128	.input = { .min = 20000000, .max = 50000000 },
129	.num_output = ARRAY_SIZE(audiopll_outputs),
130	.output = audiopll_outputs,
131	.core_output = audiopll_core_outputs,
132};
133
134static const struct clk_pll_characteristics plladiv2_characteristics = {
135	.input = { .min = 20000000, .max = 50000000 },
136	.num_output = ARRAY_SIZE(plladiv2_outputs),
137	.output = plladiv2_outputs,
138	.core_output = plladiv2_core_outputs,
139};
140
141/* Layout for fractional PLL ID PLLA. */
142static const struct clk_pll_layout plla_frac_layout = {
143	.mul_mask = GENMASK(31, 24),
144	.frac_mask = GENMASK(21, 0),
145	.mul_shift = 24,
146	.frac_shift = 0,
147	.div2 = 1,
148};
149
150/* Layout for fractional PLLs. */
151static const struct clk_pll_layout pll_frac_layout = {
152	.mul_mask = GENMASK(31, 24),
153	.frac_mask = GENMASK(21, 0),
154	.mul_shift = 24,
155	.frac_shift = 0,
156};
157
158/* Layout for DIV PLLs. */
159static const struct clk_pll_layout pll_divpmc_layout = {
160	.div_mask = GENMASK(7, 0),
161	.endiv_mask = BIT(29),
162	.div_shift = 0,
163	.endiv_shift = 29,
164};
165
166/* Layout for DIV PLL ID PLLADIV2. */
167static const struct clk_pll_layout plladiv2_divpmc_layout = {
168	.div_mask = GENMASK(7, 0),
169	.endiv_mask = BIT(29),
170	.div_shift = 0,
171	.endiv_shift = 29,
172	.div2 = 1,
173};
174
175/* Layout for DIVIO dividers. */
176static const struct clk_pll_layout pll_divio_layout = {
177	.div_mask	= GENMASK(19, 12),
178	.endiv_mask	= BIT(30),
179	.div_shift	= 12,
180	.endiv_shift	= 30,
181};
182
183/*
184 * PLL clocks description
185 * @n:		clock name
186 * @p:		clock parent
187 * @l:		clock layout
188 * @t:		clock type
189 * @c:		pll characteristics
190 * @f:		clock flags
191 * @eid:	export index in sam9x7->chws[] array
192 */
193static const struct {
194	const char *n;
195	const char *p;
196	const struct clk_pll_layout *l;
197	u8 t;
198	const struct clk_pll_characteristics *c;
199	unsigned long f;
200	u8 eid;
201} sam9x7_plls[][3] = {
202	[PLL_ID_PLLA] = {
203		{
204			.n = "plla_fracck",
205			.p = "mainck",
206			.l = &plla_frac_layout,
207			.t = PLL_TYPE_FRAC,
208			/*
209			 * This feeds plla_divpmcck which feeds CPU. It should
210			 * not be disabled.
211			 */
212			.f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,
213			.c = &plla_characteristics,
214		},
215
216		{
217			.n = "plla_divpmcck",
218			.p = "plla_fracck",
219			.l = &pll_divpmc_layout,
220			.t = PLL_TYPE_DIV,
221			/* This feeds CPU. It should not be disabled */
222			.f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,
223			.eid = PMC_PLLACK,
224			.c = &plla_characteristics,
225		},
226	},
227
228	[PLL_ID_UPLL] = {
229		{
230			.n = "upll_fracck",
231			.p = "main_osc",
232			.l = &pll_frac_layout,
233			.t = PLL_TYPE_FRAC,
234			.f = CLK_SET_RATE_GATE,
235			.c = &upll_characteristics,
236		},
237
238		{
239			.n = "upll_divpmcck",
240			.p = "upll_fracck",
241			.l = &pll_divpmc_layout,
242			.t = PLL_TYPE_DIV,
243			.f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
244			     CLK_SET_RATE_PARENT,
245			.eid = PMC_UTMI,
246			.c = &upll_characteristics,
247		},
248	},
249
250	[PLL_ID_AUDIO] = {
251		{
252			.n = "audiopll_fracck",
253			.p = "main_osc",
254			.l = &pll_frac_layout,
255			.f = CLK_SET_RATE_GATE,
256			.c = &audiopll_characteristics,
257			.t = PLL_TYPE_FRAC,
258		},
259
260		{
261			.n = "audiopll_divpmcck",
262			.p = "audiopll_fracck",
263			.l = &pll_divpmc_layout,
264			.f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
265			     CLK_SET_RATE_PARENT,
266			.c = &audiopll_characteristics,
267			.eid = PMC_AUDIOPMCPLL,
268			.t = PLL_TYPE_DIV,
269		},
270
271		{
272			.n = "audiopll_diviock",
273			.p = "audiopll_fracck",
274			.l = &pll_divio_layout,
275			.f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
276			     CLK_SET_RATE_PARENT,
277			.c = &audiopll_characteristics,
278			.eid = PMC_AUDIOIOPLL,
279			.t = PLL_TYPE_DIV,
280		},
281	},
282
283	[PLL_ID_LVDS] = {
284		{
285			.n = "lvdspll_fracck",
286			.p = "main_osc",
287			.l = &pll_frac_layout,
288			.f = CLK_SET_RATE_GATE,
289			.c = &lvdspll_characteristics,
290			.t = PLL_TYPE_FRAC,
291		},
292
293		{
294			.n = "lvdspll_divpmcck",
295			.p = "lvdspll_fracck",
296			.l = &pll_divpmc_layout,
297			.f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
298			     CLK_SET_RATE_PARENT,
299			.c = &lvdspll_characteristics,
300			.eid = PMC_LVDSPLL,
301			.t = PLL_TYPE_DIV,
302		},
303	},
304
305	[PLL_ID_PLLA_DIV2] = {
306		{
307			.n = "plla_div2pmcck",
308			.p = "plla_fracck",
309			.l = &plladiv2_divpmc_layout,
310			/*
311			 * This may feed critical parts of the system like timers.
312			 * It should not be disabled.
313			 */
314			.f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,
315			.c = &plladiv2_characteristics,
316			.eid = PMC_PLLADIV2,
317			.t = PLL_TYPE_DIV,
318		},
319	},
320};
321
322static const struct clk_programmable_layout sam9x7_programmable_layout = {
323	.pres_mask = 0xff,
324	.pres_shift = 8,
325	.css_mask = 0x1f,
326	.have_slck_mck = 0,
327	.is_pres_direct = 1,
328};
329
330static const struct clk_pcr_layout sam9x7_pcr_layout = {
331	.offset = 0x88,
332	.cmd = BIT(31),
333	.gckcss_mask = GENMASK(12, 8),
334	.pid_mask = GENMASK(6, 0),
335};
336
337static const struct {
338	char *n;
339	char *p;
340	u8 id;
341	unsigned long flags;
342} sam9x7_systemck[] = {
343	/*
344	 * ddrck feeds DDR controller and is enabled by bootloader thus we need
345	 * to keep it enabled in case there is no Linux consumer for it.
346	 */
347	{ .n = "ddrck",		.p = "masterck_div",	.id = 2,	.flags = CLK_IS_CRITICAL },
348	{ .n = "uhpck",		.p = "usbck",		.id = 6 },
349	{ .n = "pck0",		.p = "prog0",		.id = 8 },
350	{ .n = "pck1",		.p = "prog1",		.id = 9 },
351};
352
353/*
354 * Peripheral clocks description
355 * @n:		clock name
356 * @f:		clock flags
357 * @id:		peripheral id
358 */
359static const struct {
360	char *n;
361	unsigned long f;
362	u8 id;
363} sam9x7_periphck[] = {
364	{ .n = "pioA_clk",	.id = 2, },
365	{ .n = "pioB_clk",	.id = 3, },
366	{ .n = "pioC_clk",	.id = 4, },
367	{ .n = "flex0_clk",	.id = 5, },
368	{ .n = "flex1_clk",	.id = 6, },
369	{ .n = "flex2_clk",	.id = 7, },
370	{ .n = "flex3_clk",	.id = 8, },
371	{ .n = "flex6_clk",	.id = 9, },
372	{ .n = "flex7_clk",	.id = 10, },
373	{ .n = "flex8_clk",	.id = 11, },
374	{ .n = "sdmmc0_clk",	.id = 12, },
375	{ .n = "flex4_clk",	.id = 13, },
376	{ .n = "flex5_clk",	.id = 14, },
377	{ .n = "flex9_clk",	.id = 15, },
378	{ .n = "flex10_clk",	.id = 16, },
379	{ .n = "tcb0_clk",	.id = 17, },
380	{ .n = "pwm_clk",	.id = 18, },
381	{ .n = "adc_clk",	.id = 19, },
382	{ .n = "dma0_clk",	.id = 20, },
383	{ .n = "uhphs_clk",	.id = 22, },
384	{ .n = "udphs_clk",	.id = 23, },
385	{ .n = "macb0_clk",	.id = 24, },
386	{ .n = "lcd_clk",	.id = 25, },
387	{ .n = "sdmmc1_clk",	.id = 26, },
388	{ .n = "ssc_clk",	.id = 28, },
389	{ .n = "can0_clk",	.id = 29, },
390	{ .n = "can1_clk",	.id = 30, },
391	{ .n = "flex11_clk",	.id = 32, },
392	{ .n = "flex12_clk",	.id = 33, },
393	{ .n = "i2s_clk",	.id = 34, },
394	{ .n = "qspi_clk",	.id = 35, },
395	{ .n = "gfx2d_clk",	.id = 36, },
396	{ .n = "pit64b0_clk",	.id = 37, },
397	{ .n = "trng_clk",	.id = 38, },
398	{ .n = "aes_clk",	.id = 39, },
399	{ .n = "tdes_clk",	.id = 40, },
400	{ .n = "sha_clk",	.id = 41, },
401	{ .n = "classd_clk",	.id = 42, },
402	{ .n = "isi_clk",	.id = 43, },
403	{ .n = "pioD_clk",	.id = 44, },
404	{ .n = "tcb1_clk",	.id = 45, },
405	{ .n = "dbgu_clk",	.id = 47, },
406	/*
407	 * mpddr_clk feeds DDR controller and is enabled by bootloader thus we
408	 * need to keep it enabled in case there is no Linux consumer for it.
409	 */
410	{ .n = "mpddr_clk",	.id = 49,	.f = CLK_IS_CRITICAL },
411	{ .n = "csi2dc_clk",	.id = 52, },
412	{ .n = "csi4l_clk",	.id = 53, },
413	{ .n = "dsi4l_clk",	.id = 54, },
414	{ .n = "lvdsc_clk",	.id = 56, },
415	{ .n = "pit64b1_clk",	.id = 58, },
416	{ .n = "puf_clk",	.id = 59, },
417	{ .n = "gmactsu_clk",	.id = 67, },
418};
419
420/*
421 * Generic clock description
422 * @n:			clock name
423 * @pp:			PLL parents
424 * @pp_mux_table:	PLL parents mux table
425 * @r:			clock output range
426 * @pp_chg_id:		id in parent array of changeable PLL parent
427 * @pp_count:		PLL parents count
428 * @id:			clock id
429 */
430static const struct {
431	const char *n;
432	const char *pp[8];
433	const char pp_mux_table[8];
434	struct clk_range r;
435	int pp_chg_id;
436	u8 pp_count;
437	u8 id;
438} sam9x7_gck[] = {
439	{
440		.n = "flex0_gclk",
441		.id = 5,
442		.pp = { "plla_div2pmcck", },
443		.pp_mux_table = { 8, },
444		.pp_count = 1,
445		.pp_chg_id = INT_MIN,
446	},
447
448	{
449		.n = "flex1_gclk",
450		.id = 6,
451		.pp = { "plla_div2pmcck", },
452		.pp_mux_table = { 8, },
453		.pp_count = 1,
454		.pp_chg_id = INT_MIN,
455	},
456
457	{
458		.n = "flex2_gclk",
459		.id = 7,
460		.pp = { "plla_div2pmcck", },
461		.pp_mux_table = { 8, },
462		.pp_count = 1,
463		.pp_chg_id = INT_MIN,
464	},
465
466	{
467		.n = "flex3_gclk",
468		.id = 8,
469		.pp = { "plla_div2pmcck", },
470		.pp_mux_table = { 8, },
471		.pp_count = 1,
472		.pp_chg_id = INT_MIN,
473	},
474
475	{
476		.n = "flex6_gclk",
477		.id = 9,
478		.pp = { "plla_div2pmcck", },
479		.pp_mux_table = { 8, },
480		.pp_count = 1,
481		.pp_chg_id = INT_MIN,
482	},
483
484	{
485		.n = "flex7_gclk",
486		.id = 10,
487		.pp = { "plla_div2pmcck", },
488		.pp_mux_table = { 8, },
489		.pp_count = 1,
490		.pp_chg_id = INT_MIN,
491	},
492
493	{
494		.n = "flex8_gclk",
495		.id = 11,
496		.pp = { "plla_div2pmcck", },
497		.pp_mux_table = { 8, },
498		.pp_count = 1,
499		.pp_chg_id = INT_MIN,
500	},
501
502	{
503		.n = "sdmmc0_gclk",
504		.id = 12,
505		.r = { .max = 105000000 },
506		.pp = { "audiopll_divpmcck", "plla_div2pmcck", },
507		.pp_mux_table = { 6, 8, },
508		.pp_count = 2,
509		.pp_chg_id = INT_MIN,
510	},
511
512	{
513		.n = "flex4_gclk",
514		.id = 13,
515		.pp = { "plla_div2pmcck", },
516		.pp_mux_table = { 8, },
517		.pp_count = 1,
518		.pp_chg_id = INT_MIN,
519	},
520
521	{
522		.n = "flex5_gclk",
523		.id = 14,
524		.pp = { "plla_div2pmcck", },
525		.pp_mux_table = { 8, },
526		.pp_count = 1,
527		.pp_chg_id = INT_MIN,
528	},
529
530	{
531		.n = "flex9_gclk",
532		.id = 15,
533		.pp = { "plla_div2pmcck", },
534		.pp_mux_table = { 8, },
535		.pp_count = 1,
536		.pp_chg_id = INT_MIN,
537	},
538
539	{
540		.n = "flex10_gclk",
541		.id = 16,
542		.pp = { "plla_div2pmcck", },
543		.pp_mux_table = { 8, },
544		.pp_count = 1,
545		.pp_chg_id = INT_MIN,
546	},
547
548	{
549		.n = "tcb0_gclk",
550		.id = 17,
551		.pp = { "audiopll_divpmcck", "plla_div2pmcck", },
552		.pp_mux_table = { 6, 8, },
553		.pp_count = 2,
554		.pp_chg_id = INT_MIN,
555	},
556
557	{
558		.n = "adc_gclk",
559		.id = 19,
560		.pp = { "upll_divpmcck", "plla_div2pmcck", },
561		.pp_mux_table = { 5, 8, },
562		.pp_count = 2,
563		.pp_chg_id = INT_MIN,
564	},
565
566	{
567		.n = "lcd_gclk",
568		.id = 25,
569		.r = { .max = 75000000 },
570		.pp = { "audiopll_divpmcck", "plla_div2pmcck", },
571		.pp_mux_table = { 6, 8, },
572		.pp_count = 2,
573		.pp_chg_id = INT_MIN,
574	},
575
576	{
577		.n = "sdmmc1_gclk",
578		.id = 26,
579		.r = { .max = 105000000 },
580		.pp = { "audiopll_divpmcck", "plla_div2pmcck", },
581		.pp_mux_table = { 6, 8, },
582		.pp_count = 2,
583		.pp_chg_id = INT_MIN,
584	},
585
586	{
587		.n = "mcan0_gclk",
588		.id = 29,
589		.r = { .max = 80000000 },
590		.pp = { "upll_divpmcck", "plla_div2pmcck", },
591		.pp_mux_table = { 5, 8, },
592		.pp_count = 2,
593		.pp_chg_id = INT_MIN,
594	},
595
596	{
597		.n = "mcan1_gclk",
598		.id = 30,
599		.r = { .max = 80000000 },
600		.pp = { "upll_divpmcck", "plla_div2pmcck", },
601		.pp_mux_table = { 5, 8, },
602		.pp_count = 2,
603		.pp_chg_id = INT_MIN,
604	},
605
606	{
607		.n = "flex11_gclk",
608		.id = 32,
609		.pp = { "plla_div2pmcck", },
610		.pp_mux_table = { 8, },
611		.pp_count = 1,
612		.pp_chg_id = INT_MIN,
613	},
614
615	{
616		.n = "flex12_gclk",
617		.id = 33,
618		.pp = { "plla_div2pmcck", },
619		.pp_mux_table = { 8, },
620		.pp_count = 1,
621		.pp_chg_id = INT_MIN,
622	},
623
624	{
625		.n = "i2s_gclk",
626		.id = 34,
627		.r = { .max = 100000000 },
628		.pp = { "audiopll_divpmcck", "plla_div2pmcck", },
629		.pp_mux_table = { 6, 8, },
630		.pp_count = 2,
631		.pp_chg_id = INT_MIN,
632	},
633
634	{
635		.n = "qspi_gclk",
636		.id = 35,
637		.r = { .max = 200000000 },
638		.pp = { "audiopll_divpmcck", "plla_div2pmcck", },
639		.pp_mux_table = { 6, 8, },
640		.pp_count = 2,
641		.pp_chg_id = INT_MIN,
642	},
643
644	{
645		.n = "pit64b0_gclk",
646		.id = 37,
647		.pp = { "plla_div2pmcck", },
648		.pp_mux_table = { 8, },
649		.pp_count = 1,
650		.pp_chg_id = INT_MIN,
651	},
652
653	{
654		.n = "classd_gclk",
655		.id = 42,
656		.r = { .max = 100000000 },
657		.pp = { "audiopll_divpmcck", "plla_div2pmcck", },
658		.pp_mux_table = { 6, 8, },
659		.pp_count = 2,
660		.pp_chg_id = INT_MIN,
661	},
662
663	{
664		.n = "tcb1_gclk",
665		.id = 45,
666		.pp = { "audiopll_divpmcck", "plla_div2pmcck", },
667		.pp_mux_table = { 6, 8, },
668		.pp_count = 2,
669		.pp_chg_id = INT_MIN,
670	},
671
672	{
673		.n = "dbgu_gclk",
674		.id = 47,
675		.pp = { "plla_div2pmcck", },
676		.pp_mux_table = { 8, },
677		.pp_count = 1,
678		.pp_chg_id = INT_MIN,
679	},
680
681	{
682		.n = "mipiphy_gclk",
683		.id = 55,
684		.r = { .max = 27000000 },
685		.pp = { "plla_div2pmcck", },
686		.pp_mux_table = { 8, },
687		.pp_count = 1,
688		.pp_chg_id = INT_MIN,
689	},
690
691	{
692		.n = "pit64b1_gclk",
693		.id = 58,
694		.pp = { "plla_div2pmcck", },
695		.pp_mux_table = { 8, },
696		.pp_count = 1,
697		.pp_chg_id = INT_MIN,
698	},
699
700	{
701		.n = "gmac_gclk",
702		.id = 67,
703		.pp = { "audiopll_divpmcck", "plla_div2pmcck", },
704		.pp_mux_table = { 6, 8, },
705		.pp_count = 2,
706		.pp_chg_id = INT_MIN,
707	},
708};
709
710static void __init sam9x7_pmc_setup(struct device_node *np)
711{
712	struct clk_range range = CLK_RANGE(0, 0);
713	const char *td_slck_name, *md_slck_name, *mainxtal_name;
714	struct pmc_data *sam9x7_pmc;
715	const char *parent_names[9];
716	void **clk_mux_buffer = NULL;
717	int clk_mux_buffer_size = 0;
718	struct clk_hw *main_osc_hw;
719	struct regmap *regmap;
720	struct clk_hw *hw;
721	int i, j;
722
723	i = of_property_match_string(np, "clock-names", "td_slck");
724	if (i < 0)
725		return;
726
727	td_slck_name = of_clk_get_parent_name(np, i);
728
729	i = of_property_match_string(np, "clock-names", "md_slck");
730	if (i < 0)
731		return;
732
733	md_slck_name = of_clk_get_parent_name(np, i);
734
735	i = of_property_match_string(np, "clock-names", "main_xtal");
736	if (i < 0)
737		return;
738	mainxtal_name = of_clk_get_parent_name(np, i);
739
740	regmap = device_node_to_regmap(np);
741	if (IS_ERR(regmap))
742		return;
743
744	sam9x7_pmc = pmc_data_allocate(PMC_LVDSPLL + 1,
745				       nck(sam9x7_systemck),
746				       nck(sam9x7_periphck),
747				       nck(sam9x7_gck), 8);
748	if (!sam9x7_pmc)
749		return;
750
751	clk_mux_buffer = kmalloc(sizeof(void *) *
752				 (ARRAY_SIZE(sam9x7_gck)),
753				 GFP_KERNEL);
754	if (!clk_mux_buffer)
755		goto err_free;
756
757	hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000,
758					   50000000);
759	if (IS_ERR(hw))
760		goto err_free;
761
762	hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, NULL, 0);
763	if (IS_ERR(hw))
764		goto err_free;
765	main_osc_hw = hw;
766
767	parent_names[0] = "main_rc_osc";
768	parent_names[1] = "main_osc";
769	hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, NULL, 2);
770	if (IS_ERR(hw))
771		goto err_free;
772
773	sam9x7_pmc->chws[PMC_MAIN] = hw;
774
775	for (i = 0; i < PLL_ID_MAX; i++) {
776		for (j = 0; j < 3; j++) {
777			struct clk_hw *parent_hw;
778
779			if (!sam9x7_plls[i][j].n)
780				continue;
781
782			switch (sam9x7_plls[i][j].t) {
783			case PLL_TYPE_FRAC:
784				if (!strcmp(sam9x7_plls[i][j].p, "mainck"))
785					parent_hw = sam9x7_pmc->chws[PMC_MAIN];
786				else if (!strcmp(sam9x7_plls[i][j].p, "main_osc"))
787					parent_hw = main_osc_hw;
788				else
789					parent_hw = __clk_get_hw(of_clk_get_by_name
790								 (np, sam9x7_plls[i][j].p));
791
792				hw = sam9x60_clk_register_frac_pll(regmap,
793								   &pmc_pll_lock,
794								   sam9x7_plls[i][j].n,
795								   sam9x7_plls[i][j].p,
796								   parent_hw, i,
797								   sam9x7_plls[i][j].c,
798								   sam9x7_plls[i][j].l,
799								   sam9x7_plls[i][j].f);
800				break;
801
802			case PLL_TYPE_DIV:
803				hw = sam9x60_clk_register_div_pll(regmap,
804								  &pmc_pll_lock,
805								  sam9x7_plls[i][j].n,
806								  sam9x7_plls[i][j].p, NULL, i,
807								  sam9x7_plls[i][j].c,
808								  sam9x7_plls[i][j].l,
809								  sam9x7_plls[i][j].f, 0);
810				break;
811
812			default:
813				continue;
814			}
815
816			if (IS_ERR(hw))
817				goto err_free;
818
819			if (sam9x7_plls[i][j].eid)
820				sam9x7_pmc->chws[sam9x7_plls[i][j].eid] = hw;
821		}
822	}
823
824	parent_names[0] = md_slck_name;
825	parent_names[1] = "mainck";
826	parent_names[2] = "plla_divpmcck";
827	parent_names[3] = "upll_divpmcck";
828	hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
829					   parent_names, NULL, &sam9x7_master_layout,
830					   &mck_characteristics, &mck_lock);
831	if (IS_ERR(hw))
832		goto err_free;
833
834	hw = at91_clk_register_master_div(regmap, "masterck_div",
835					  "masterck_pres", NULL, &sam9x7_master_layout,
836					  &mck_characteristics, &mck_lock,
837					  CLK_SET_RATE_GATE, 0);
838	if (IS_ERR(hw))
839		goto err_free;
840
841	sam9x7_pmc->chws[PMC_MCK] = hw;
842
843	parent_names[0] = "plla_divpmcck";
844	parent_names[1] = "upll_divpmcck";
845	parent_names[2] = "main_osc";
846	hw = sam9x60_clk_register_usb(regmap, "usbck", parent_names, 3);
847	if (IS_ERR(hw))
848		goto err_free;
849
850	parent_names[0] = md_slck_name;
851	parent_names[1] = td_slck_name;
852	parent_names[2] = "mainck";
853	parent_names[3] = "masterck_div";
854	parent_names[4] = "plla_divpmcck";
855	parent_names[5] = "upll_divpmcck";
856	parent_names[6] = "audiopll_divpmcck";
857	for (i = 0; i < 2; i++) {
858		char name[6];
859
860		snprintf(name, sizeof(name), "prog%d", i);
861
862		hw = at91_clk_register_programmable(regmap, name,
863						    parent_names, NULL, 7, i,
864						    &sam9x7_programmable_layout,
865						    NULL);
866		if (IS_ERR(hw))
867			goto err_free;
868
869		sam9x7_pmc->pchws[i] = hw;
870	}
871
872	for (i = 0; i < ARRAY_SIZE(sam9x7_systemck); i++) {
873		hw = at91_clk_register_system(regmap, sam9x7_systemck[i].n,
874					      sam9x7_systemck[i].p, NULL,
875					      sam9x7_systemck[i].id,
876					      sam9x7_systemck[i].flags);
877		if (IS_ERR(hw))
878			goto err_free;
879
880		sam9x7_pmc->shws[sam9x7_systemck[i].id] = hw;
881	}
882
883	for (i = 0; i < ARRAY_SIZE(sam9x7_periphck); i++) {
884		hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
885							 &sam9x7_pcr_layout,
886							 sam9x7_periphck[i].n,
887							 "masterck_div", NULL,
888							 sam9x7_periphck[i].id,
889							 &range, INT_MIN,
890							 sam9x7_periphck[i].f);
891		if (IS_ERR(hw))
892			goto err_free;
893
894		sam9x7_pmc->phws[sam9x7_periphck[i].id] = hw;
895	}
896
897	parent_names[0] = md_slck_name;
898	parent_names[1] = td_slck_name;
899	parent_names[2] = "mainck";
900	parent_names[3] = "masterck_div";
901	for (i = 0; i < ARRAY_SIZE(sam9x7_gck); i++) {
902		u8 num_parents = 4 + sam9x7_gck[i].pp_count;
903		u32 *mux_table;
904
905		mux_table = kmalloc_array(num_parents, sizeof(*mux_table),
906					  GFP_KERNEL);
907		if (!mux_table)
908			goto err_free;
909
910		PMC_INIT_TABLE(mux_table, 4);
911		PMC_FILL_TABLE(&mux_table[4], sam9x7_gck[i].pp_mux_table,
912			       sam9x7_gck[i].pp_count);
913		PMC_FILL_TABLE(&parent_names[4], sam9x7_gck[i].pp,
914			       sam9x7_gck[i].pp_count);
915
916		hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
917						 &sam9x7_pcr_layout,
918						 sam9x7_gck[i].n,
919						 parent_names, NULL, mux_table,
920						 num_parents,
921						 sam9x7_gck[i].id,
922						 &sam9x7_gck[i].r,
923						 sam9x7_gck[i].pp_chg_id);
924		if (IS_ERR(hw))
925			goto err_free;
926
927		sam9x7_pmc->ghws[sam9x7_gck[i].id] = hw;
928		clk_mux_buffer[clk_mux_buffer_size++] = mux_table;
929	}
930
931	of_clk_add_hw_provider(np, of_clk_hw_pmc_get, sam9x7_pmc);
932	kfree(clk_mux_buffer);
933
934	return;
935
936err_free:
937	if (clk_mux_buffer) {
938		for (i = 0; i < clk_mux_buffer_size; i++)
939			kfree(clk_mux_buffer[i]);
940		kfree(clk_mux_buffer);
941	}
942	kfree(sam9x7_pmc);
943}
944
945/* Some clks are used for a clocksource */
946CLK_OF_DECLARE(sam9x7_pmc, "microchip,sam9x7-pmc", sam9x7_pmc_setup);