xref: /optee_os/core/drivers/clk/sam/sama5d2_clk.c (revision 9aab6fb2f2635a1b29c8ba66483c3b53bb1ca1a3)
116521289SClément Léger // SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause
216521289SClément Léger /*
316521289SClément Léger  * Copyright (c) 2021, Microchip
416521289SClément Léger  */
516521289SClément Léger #include <assert.h>
616521289SClément Léger #include <kernel/boot.h>
716521289SClément Léger #include <libfdt.h>
816521289SClément Léger #include <kernel/dt.h>
916521289SClément Léger #include <kernel/panic.h>
1016521289SClément Léger #include <matrix.h>
1116521289SClément Léger #include <sama5d2.h>
1216521289SClément Léger #include <stdint.h>
1316521289SClément Léger #include <util.h>
1416521289SClément Léger 
1516521289SClément Léger #include "at91_clk.h"
1616521289SClément Léger 
1716521289SClément Léger #include <dt-bindings/clock/at91.h>
1816521289SClément Léger 
1916521289SClément Léger #define PROGCK_PARENT_COUNT	6
2016521289SClément Léger #define PARENT_SIZE		ARRAY_SIZE(sama5d2_systemck)
2116521289SClément Léger 
2216521289SClément Léger struct sam_clk {
2316521289SClément Léger 	const char *n;
2416521289SClément Léger 	uint8_t id;
2516521289SClément Léger };
2616521289SClément Léger 
2716521289SClément Léger static const struct clk_master_charac mck_charac = {
2816521289SClément Léger 	.output = { .min = 124000000, .max = 166000000 },
2916521289SClément Léger 	.divisors = { 1, 2, 4, 3 },
3016521289SClément Léger };
3116521289SClément Léger 
3216521289SClément Léger static uint8_t plla_out[1];
3316521289SClément Léger 
3416521289SClément Léger static uint16_t plla_icpll[1];
3516521289SClément Léger 
3616521289SClément Léger static const struct clk_range plla_outputs[] = {
3716521289SClément Léger 	{ .min = 600000000, .max = 1200000000 },
3816521289SClément Léger };
3916521289SClément Léger 
4016521289SClément Léger static const struct clk_pll_charac plla_charac = {
4116521289SClément Léger 	.input = { .min = 12000000, .max = 24000000 },
4216521289SClément Léger 	.num_output = ARRAY_SIZE(plla_outputs),
4316521289SClément Léger 	.output = plla_outputs,
4416521289SClément Léger 	.icpll = plla_icpll,
4516521289SClément Léger 	.out = plla_out,
4616521289SClément Léger };
4716521289SClément Léger 
4816521289SClément Léger static const struct clk_pcr_layout sama5d2_pcr_layout = {
4916521289SClément Léger 	.offset = 0x10c,
5016521289SClément Léger 	.cmd = BIT(12),
5116521289SClément Léger 	.gckcss_mask = GENMASK_32(10, 8),
5216521289SClément Léger 	.pid_mask = GENMASK_32(6, 0),
5316521289SClément Léger };
5416521289SClément Léger 
5516521289SClément Léger static const struct clk_programmable_layout sama5d2_prog_layout = {
5616521289SClément Léger 	.pres_mask = 0xff,
5716521289SClément Léger 	.pres_shift = 4,
5816521289SClément Léger 	.css_mask = 0x7,
5916521289SClément Léger 	.have_slck_mck = 0,
6016521289SClément Léger 	.is_pres_direct = 1,
6116521289SClément Léger };
6216521289SClément Léger 
6316521289SClément Léger static const struct sam_clk sama5d2_systemck[] = {
6416521289SClément Léger 	{ .n = "ddrck", .id = 2 },
6516521289SClément Léger 	{ .n = "lcdck", .id = 3 },
6616521289SClément Léger 	{ .n = "uhpck", .id = 6 },
6716521289SClément Léger 	{ .n = "udpck", .id = 7 },
6816521289SClément Léger 	{ .n = "pck0",  .id = 8 },
6916521289SClément Léger 	{ .n = "pck1",  .id = 9 },
7016521289SClément Léger 	{ .n = "pck2",  .id = 10 },
7116521289SClément Léger 	{ .n = "iscck", .id = 18 },
7216521289SClément Léger };
7316521289SClément Léger 
7416521289SClément Léger static const struct {
7516521289SClément Léger 	struct sam_clk clk;
7616521289SClément Léger 	struct clk_range r;
7716521289SClément Léger } sama5d2_peri32ck[] = {
7816521289SClément Léger 	{
7916521289SClément Léger 		.clk = { .n = "macb0_clk", .id = 5 },
8016521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
8116521289SClément Léger 	},
8216521289SClément Léger 	{
8316521289SClément Léger 		.clk = { .n = "tdes_clk", .id = 11 },
8416521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
8516521289SClément Léger 	},
8616521289SClément Léger 	{
8716521289SClément Léger 		.clk = { .n = "matrix1_clk", .id = 14 },
8816521289SClément Léger 	},
8916521289SClément Léger 	{
9016521289SClément Léger 		.clk = { .n = "hsmc_clk", .id = 17 },
9116521289SClément Léger 	},
9216521289SClément Léger 	{
9316521289SClément Léger 		.clk = { .n = "pioA_clk", .id = 18 },
9416521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
9516521289SClément Léger 	},
9616521289SClément Léger 	{
9716521289SClément Léger 		.clk = { .n = "flx0_clk", .id = 19 },
9816521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
9916521289SClément Léger 	},
10016521289SClément Léger 	{
10116521289SClément Léger 		.clk = { .n = "flx1_clk", .id = 20 },
10216521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
10316521289SClément Léger 	},
10416521289SClément Léger 	{
10516521289SClément Léger 		.clk = { .n = "flx2_clk", .id = 21 },
10616521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
10716521289SClément Léger 	},
10816521289SClément Léger 	{
10916521289SClément Léger 		.clk = { .n = "flx3_clk", .id = 22 },
11016521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
11116521289SClément Léger 	},
11216521289SClément Léger 	{
11316521289SClément Léger 		.clk = { .n = "flx4_clk", .id = 23 },
11416521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
11516521289SClément Léger 	},
11616521289SClément Léger 	{
11716521289SClément Léger 		.clk = { .n = "uart0_clk", .id = 24 },
11816521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
11916521289SClément Léger 	},
12016521289SClément Léger 	{
12116521289SClément Léger 		.clk = { .n = "uart1_clk", .id = 25 },
12216521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
12316521289SClément Léger 	},
12416521289SClément Léger 	{
12516521289SClément Léger 		.clk = { .n = "uart2_clk", .id = 26 },
12616521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
12716521289SClément Léger 	},
12816521289SClément Léger 	{
12916521289SClément Léger 		.clk = { .n = "uart3_clk", .id = 27 },
13016521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
13116521289SClément Léger 	},
13216521289SClément Léger 	{
13316521289SClément Léger 		.clk = { .n = "uart4_clk", .id = 28 },
13416521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
13516521289SClément Léger 	},
13616521289SClément Léger 	{
13716521289SClément Léger 		.clk = { .n = "twi0_clk", .id = 29 },
13816521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
13916521289SClément Léger 	},
14016521289SClément Léger 	{
14116521289SClément Léger 		.clk = { .n = "twi1_clk", .id = 30 },
14216521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
14316521289SClément Léger 	},
14416521289SClément Léger 	{
14516521289SClément Léger 		.clk = { .n = "spi0_clk", .id = 33 },
14616521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
14716521289SClément Léger 	},
14816521289SClément Léger 	{
14916521289SClément Léger 		.clk = { .n = "spi1_clk", .id = 34 },
15016521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
15116521289SClément Léger 	},
15216521289SClément Léger 	{
15316521289SClément Léger 		.clk = { .n = "tcb0_clk", .id = 35 },
15416521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
15516521289SClément Léger 	},
15616521289SClément Léger 	{
15716521289SClément Léger 		.clk = { .n = "tcb1_clk", .id = 36 },
15816521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
15916521289SClément Léger 	},
16016521289SClément Léger 	{
16116521289SClément Léger 		.clk = { .n = "pwm_clk", .id = 38 },
16216521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
16316521289SClément Léger 	},
16416521289SClément Léger 	{
16516521289SClément Léger 		.clk = { .n = "adc_clk", .id = 40 },
16616521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
16716521289SClément Léger 	},
16816521289SClément Léger 	{
16916521289SClément Léger 		.clk = { .n = "uhphs_clk", .id = 41 },
17016521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
17116521289SClément Léger 	},
17216521289SClément Léger 	{
17316521289SClément Léger 		.clk = { .n = "udphs_clk", .id = 42 },
17416521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
17516521289SClément Léger 	},
17616521289SClément Léger 	{
17716521289SClément Léger 		.clk = { .n = "ssc0_clk", .id = 43 },
17816521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
17916521289SClément Léger 	},
18016521289SClément Léger 	{
18116521289SClément Léger 		.clk = { .n = "ssc1_clk", .id = 44 },
18216521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
18316521289SClément Léger 	},
18416521289SClément Léger 	{
18516521289SClément Léger 		.clk = { .n = "trng_clk", .id = 47 },
18616521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
18716521289SClément Léger 	},
18816521289SClément Léger 	{
18916521289SClément Léger 		.clk = { .n = "pdmic_clk", .id = 48 },
19016521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
19116521289SClément Léger 	},
19216521289SClément Léger 	{
19316521289SClément Léger 		.clk = { .n = "securam_clk", .id = 51 }, },
19416521289SClément Léger 	{
19516521289SClément Léger 		.clk = { .n = "i2s0_clk", .id = 54 },
19616521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
19716521289SClément Léger 	},
19816521289SClément Léger 	{
19916521289SClément Léger 		.clk = { .n = "i2s1_clk", .id = 55 },
20016521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
20116521289SClément Léger 	},
20216521289SClément Léger 	{
20316521289SClément Léger 		.clk = { .n = "can0_clk", .id = 56 },
20416521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
20516521289SClément Léger 	},
20616521289SClément Léger 	{
20716521289SClément Léger 		.clk = { .n = "can1_clk", .id = 57 },
20816521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
20916521289SClément Léger 	},
21016521289SClément Léger 	{
21116521289SClément Léger 		.clk = { .n = "ptc_clk", .id = 58 },
21216521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
21316521289SClément Léger 	},
21416521289SClément Léger 	{
21516521289SClément Léger 		.clk = { .n = "classd_clk", .id = 59 },
21616521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
21716521289SClément Léger 	},
21816521289SClément Léger };
21916521289SClément Léger 
22016521289SClément Léger static const struct sam_clk sama5d2_perick[] = {
22116521289SClément Léger 	{ .n = "dma0_clk",    .id = 6 },
22216521289SClément Léger 	{ .n = "dma1_clk",    .id = 7 },
22316521289SClément Léger 	{ .n = "aes_clk",     .id = 9 },
22416521289SClément Léger 	{ .n = "aesb_clk",    .id = 10 },
22516521289SClément Léger 	{ .n = "sha_clk",     .id = 12 },
22616521289SClément Léger 	{ .n = "mpddr_clk",   .id = 13 },
22716521289SClément Léger 	{ .n = "matrix0_clk", .id = 15 },
22816521289SClément Léger 	{ .n = "sdmmc0_hclk", .id = 31 },
22916521289SClément Léger 	{ .n = "sdmmc1_hclk", .id = 32 },
23016521289SClément Léger 	{ .n = "lcdc_clk",    .id = 45 },
23116521289SClément Léger 	{ .n = "isc_clk",     .id = 46 },
23216521289SClément Léger 	{ .n = "qspi0_clk",   .id = 52 },
23316521289SClément Léger 	{ .n = "qspi1_clk",   .id = 53 },
23416521289SClément Léger };
23516521289SClément Léger 
23616521289SClément Léger static const struct {
23716521289SClément Léger 	struct sam_clk clk;
23816521289SClément Léger 	struct clk_range r;
23916521289SClément Léger 	int chg_pid;
24016521289SClément Léger } sama5d2_gck[] = {
24116521289SClément Léger 	{
24216521289SClément Léger 		.clk = { .n = "sdmmc0_gclk", .id = 31 },
24316521289SClément Léger 		.chg_pid = INT_MIN,
24416521289SClément Léger 	},
24516521289SClément Léger 	{
24616521289SClément Léger 		.clk = { .n = "sdmmc1_gclk", .id = 32 },
24716521289SClément Léger 		.chg_pid = INT_MIN,
24816521289SClément Léger 	},
24916521289SClément Léger 	{
25016521289SClément Léger 		.clk = { .n = "tcb0_gclk", .id = 35 },
25116521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
25216521289SClément Léger 		.chg_pid = INT_MIN,
25316521289SClément Léger 	},
25416521289SClément Léger 	{
25516521289SClément Léger 		.clk = { .n = "tcb1_gclk", .id = 36 },
25616521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
25716521289SClément Léger 		.chg_pid = INT_MIN,
25816521289SClément Léger 	},
25916521289SClément Léger 	{
26016521289SClément Léger 		.clk = { .n = "pwm_gclk", .id = 38 },
26116521289SClément Léger 		.r = { .min = 0, .max = 83000000 },
26216521289SClément Léger 		.chg_pid = INT_MIN,
26316521289SClément Léger 	},
26416521289SClément Léger 	{
26516521289SClément Léger 		.clk = { .n = "isc_gclk", .id = 46 },
26616521289SClément Léger 		.chg_pid = INT_MIN,
26716521289SClément Léger 	},
26816521289SClément Léger 	{
26916521289SClément Léger 		.clk = { .n = "pdmic_gclk", .id = 48 },
27016521289SClément Léger 		.chg_pid = INT_MIN,
27116521289SClément Léger 	},
27216521289SClément Léger 	{
27316521289SClément Léger 		.clk = { .n = "i2s0_gclk", .id = 54 },
27416521289SClément Léger 		.chg_pid = 5,
27516521289SClément Léger 	},
27616521289SClément Léger 	{
27716521289SClément Léger 		.clk = { .n = "i2s1_gclk", .id = 55 },
27816521289SClément Léger 		.chg_pid = 5,
27916521289SClément Léger 	},
28016521289SClément Léger 	{
28116521289SClément Léger 		.clk = { .n = "can0_gclk", .id = 56 },
28216521289SClément Léger 		.r = { .min = 0, .max = 80000000 },
28316521289SClément Léger 		.chg_pid = INT_MIN,
28416521289SClément Léger 	},
28516521289SClément Léger 	{
28616521289SClément Léger 		.clk = { .n = "can1_gclk",   .id = 57 },
28716521289SClément Léger 		.r = { .min = 0, .max = 80000000 },
28816521289SClément Léger 		.chg_pid = INT_MIN,
28916521289SClément Léger 	},
29016521289SClément Léger 	{
29116521289SClément Léger 		.clk = { .n = "classd_gclk", .id = 59 },
29216521289SClément Léger 		.chg_pid = 5,
29316521289SClément Léger 		.r = { .min = 0, .max = 100000000 },
29416521289SClément Léger 	},
29516521289SClément Léger };
29616521289SClément Léger 
29716521289SClément Léger static const struct sam_clk sama5d2_progck[] = {
29816521289SClément Léger 	{ .n = "prog0", .id = 0 },
29916521289SClément Léger 	{ .n = "prog1", .id = 1 },
30016521289SClément Léger 	{ .n = "prog2", .id = 2 },
30116521289SClément Léger };
30216521289SClément Léger 
303c2e7ca16SClément Léger static struct pmc_data *pmc;
304c2e7ca16SClément Léger 
at91_pmc_get_base(void)305c2e7ca16SClément Léger vaddr_t at91_pmc_get_base(void)
306c2e7ca16SClément Léger {
307c2e7ca16SClément Léger 	assert(pmc);
308c2e7ca16SClément Léger 
309c2e7ca16SClément Léger 	return pmc->base;
310c2e7ca16SClément Léger }
311c2e7ca16SClément Léger 
at91_pmc_clk_get(unsigned int type,unsigned int idx,struct clk ** clk)3125943d3b9SClément Léger TEE_Result at91_pmc_clk_get(unsigned int type, unsigned int idx,
3135943d3b9SClément Léger 			    struct clk **clk)
3145943d3b9SClément Léger {
3155943d3b9SClément Léger 	return pmc_clk_get(pmc, type, idx, clk);
3165943d3b9SClément Léger }
3175943d3b9SClément Léger 
pmc_setup(const void * fdt,int nodeoffset,const void * data __unused)31816521289SClément Léger static TEE_Result pmc_setup(const void *fdt, int nodeoffset,
31916521289SClément Léger 			    const void *data __unused)
32016521289SClément Léger {
32116521289SClément Léger 	size_t size = 0;
32216521289SClément Léger 	vaddr_t base = 0;
32316521289SClément Léger 	unsigned int i = 0;
32416521289SClément Léger 	int bypass = 0;
32516521289SClément Léger 	const uint32_t *fdt_prop = NULL;
32616521289SClément Léger 	struct pmc_clk *pmc_clk = NULL;
32716521289SClément Léger 	const struct sam_clk *sam_clk = NULL;
32816521289SClément Léger 	struct clk_range range = CLK_RANGE(0, 0);
32916521289SClément Léger 	struct clk *h32mxck = NULL;
33016521289SClément Léger 	struct clk *mckdivck = NULL;
33116521289SClément Léger 	struct clk *plladivck = NULL;
33216521289SClément Léger 	struct clk *usbck = NULL;
33316521289SClément Léger 	struct clk *audiopll_pmcck = NULL;
33416521289SClément Léger 	struct clk *parents[PARENT_SIZE] = {NULL};
33516521289SClément Léger 	struct clk *main_clk = NULL;
33616521289SClément Léger 	struct clk *utmi_clk = NULL;
33716521289SClément Léger 	struct clk *slow_clk = NULL;
33816521289SClément Léger 	struct clk *clk = NULL;
33916521289SClément Léger 	struct clk *main_rc_osc = NULL;
34016521289SClément Léger 	struct clk *main_osc = NULL;
34116521289SClément Léger 	struct clk *main_xtal_clk = NULL;
34216521289SClément Léger 	struct clk *audiopll_fracck = NULL;
34316521289SClément Léger 	TEE_Result res = TEE_ERROR_GENERIC;
34416521289SClément Léger 
34516521289SClément Léger 	/*
34616521289SClément Léger 	 * We want PARENT_SIZE to be MAX(ARRAY_SIZE(sama5d2_systemck),6)
34716521289SClément Léger 	 * but using this define won't allow static initialization of parents
34816521289SClément Léger 	 * due to dynamic size.
34916521289SClément Léger 	 */
35016521289SClément Léger 	COMPILE_TIME_ASSERT(ARRAY_SIZE(sama5d2_systemck) == PARENT_SIZE);
35116521289SClément Léger 	COMPILE_TIME_ASSERT(PARENT_SIZE >= 6);
35216521289SClément Léger 
353a5d5bbc8SVesa Jääskeläinen 	if (dt_map_dev(fdt, nodeoffset, &base, &size, DT_MAP_AUTO) < 0)
35416521289SClément Léger 		panic();
35516521289SClément Léger 
356f354a5d8SGatien Chevallier 	if (fdt_get_status(fdt, nodeoffset) == DT_STATUS_OK_SEC)
35716521289SClément Léger 		matrix_configure_periph_secure(AT91C_ID_PMC);
35816521289SClément Léger 
359056e7438SEtienne Carriere 	res = clk_dt_get_by_name(fdt, nodeoffset, "slow_clk", &slow_clk);
36016521289SClément Léger 	if (res)
36116521289SClément Léger 		panic();
36216521289SClément Léger 
363056e7438SEtienne Carriere 	res = clk_dt_get_by_name(fdt, nodeoffset, "main_xtal", &main_xtal_clk);
36416521289SClément Léger 	if (res)
36516521289SClément Léger 		panic();
36616521289SClément Léger 
367c0e9e857SClément Léger 	pmc = pmc_data_allocate(PMC_SAMA5D2_CORE_CLK_COUNT,
36816521289SClément Léger 				ARRAY_SIZE(sama5d2_systemck),
36916521289SClément Léger 				ARRAY_SIZE(sama5d2_perick) +
37016521289SClément Léger 				ARRAY_SIZE(sama5d2_peri32ck),
37116521289SClément Léger 				ARRAY_SIZE(sama5d2_gck),
37216521289SClément Léger 				ARRAY_SIZE(sama5d2_progck));
37316521289SClément Léger 	if (!pmc)
37416521289SClément Léger 		panic();
37516521289SClément Léger 	pmc->base = base;
37616521289SClément Léger 
37716521289SClément Léger 	main_rc_osc = pmc_register_main_rc_osc(pmc, "main_rc_osc", 12000000);
37816521289SClément Léger 	if (!main_rc_osc)
37916521289SClément Léger 		panic();
38016521289SClément Léger 
38116521289SClément Léger 	fdt_prop = fdt_getprop(fdt, nodeoffset, "atmel,osc-bypass", NULL);
38216521289SClément Léger 	if (fdt_prop)
38316521289SClément Léger 		bypass = fdt32_to_cpu(*fdt_prop);
38416521289SClément Léger 
38516521289SClément Léger 	main_osc = pmc_register_main_osc(pmc, "main_osc", main_xtal_clk,
38616521289SClément Léger 					 bypass);
38716521289SClément Léger 	if (!main_osc)
38816521289SClément Léger 		panic();
38916521289SClément Léger 
39016521289SClément Léger 	parents[0] = main_rc_osc;
39116521289SClément Léger 	parents[1] = main_osc;
39216521289SClément Léger 	main_clk = at91_clk_register_sam9x5_main(pmc, "mainck", parents, 2);
39316521289SClément Léger 	if (!main_clk)
39416521289SClément Léger 		panic();
39516521289SClément Léger 
39616521289SClément Léger 	pmc_clk = &pmc->chws[PMC_MAIN];
39716521289SClément Léger 	pmc_clk->clk = main_clk;
39816521289SClément Léger 	pmc_clk->id = PMC_MAIN;
39916521289SClément Léger 
40016521289SClément Léger 	clk = at91_clk_register_pll(pmc, "pllack", main_clk, 0,
40116521289SClément Léger 				    &sama5d3_pll_layout, &plla_charac);
40216521289SClément Léger 	if (!clk)
40316521289SClément Léger 		panic();
40416521289SClément Léger 
40516521289SClément Léger 	plladivck = at91_clk_register_plldiv(pmc, "plladivck", clk);
40616521289SClément Léger 	if (!plladivck)
40716521289SClément Léger 		panic();
40816521289SClément Léger 
40916521289SClément Léger 	pmc_clk = &pmc->chws[PMC_PLLACK];
41016521289SClément Léger 	pmc_clk->clk = plladivck;
41116521289SClément Léger 	pmc_clk->id = PMC_PLLACK;
41216521289SClément Léger 
41316521289SClément Léger 	audiopll_fracck = at91_clk_register_audio_pll_frac(pmc,
41416521289SClément Léger 							   "audiopll_fracck",
41516521289SClément Léger 							   main_clk);
41616521289SClément Léger 	if (!audiopll_fracck)
41716521289SClément Léger 		panic();
41816521289SClément Léger 
41990dee57aSClément Léger 	pmc_clk = &pmc->chws[PMC_AUDIOPLL_FRACCK];
42090dee57aSClément Léger 	pmc_clk->clk = audiopll_fracck;
42190dee57aSClément Léger 	pmc_clk->id = PMC_AUDIOPLL_FRACCK;
42290dee57aSClément Léger 
42316521289SClément Léger 	clk = at91_clk_register_audio_pll_pad(pmc, "audiopll_padck",
42416521289SClément Léger 					      audiopll_fracck);
42516521289SClément Léger 	if (!clk)
42616521289SClément Léger 		panic();
42716521289SClément Léger 
42816521289SClément Léger 	audiopll_pmcck = at91_clk_register_audio_pll_pmc(pmc, "audiopll_pmcck",
42916521289SClément Léger 							 audiopll_fracck);
43016521289SClément Léger 	if (!audiopll_pmcck)
43116521289SClément Léger 		panic();
43216521289SClément Léger 
43316521289SClément Léger 	pmc_clk = &pmc->chws[PMC_AUDIOPLLCK];
43416521289SClément Léger 	pmc_clk->clk = audiopll_pmcck;
43516521289SClément Léger 	pmc_clk->id = PMC_AUDIOPLLCK;
43616521289SClément Léger 
43716521289SClément Léger 	utmi_clk = at91_clk_register_utmi(pmc, "utmick", main_clk);
43816521289SClément Léger 	if (!utmi_clk)
43916521289SClément Léger 		panic();
44016521289SClément Léger 
44116521289SClément Léger 	pmc_clk = &pmc->chws[PMC_UTMI];
44216521289SClément Léger 	pmc_clk->clk = utmi_clk;
44316521289SClément Léger 	pmc_clk->id = PMC_UTMI;
44416521289SClément Léger 
44516521289SClément Léger 	parents[0] = slow_clk;
44616521289SClément Léger 	parents[1] = main_clk;
44716521289SClément Léger 	parents[2] = plladivck;
44816521289SClément Léger 	parents[3] = utmi_clk;
44916521289SClément Léger 
45016521289SClément Léger 	clk = at91_clk_register_master_pres(pmc, "masterck_pres", 4,
45116521289SClément Léger 					    parents,
45216521289SClément Léger 					    &at91sam9x5_master_layout,
45316521289SClément Léger 					    &mck_charac, INT_MIN);
45416521289SClément Léger 	if (!clk)
45516521289SClément Léger 		panic();
45616521289SClément Léger 
45716521289SClément Léger 	pmc_clk = &pmc->chws[PMC_MCK_PRES];
45816521289SClément Léger 	pmc_clk->clk = clk;
45916521289SClément Léger 	pmc_clk->id = PMC_MCK_PRES;
46016521289SClément Léger 
46116521289SClément Léger 	mckdivck = at91_clk_register_master_div(pmc, "masterck_div",
46216521289SClément Léger 						clk,
46316521289SClément Léger 						&at91sam9x5_master_layout,
46416521289SClément Léger 						&mck_charac);
46516521289SClément Léger 	if (!mckdivck)
46616521289SClément Léger 		panic();
46716521289SClément Léger 
46816521289SClément Léger 	pmc_clk = &pmc->chws[PMC_MCK];
46916521289SClément Léger 	pmc_clk->clk = mckdivck;
47016521289SClément Léger 	pmc_clk->id = PMC_MCK;
47116521289SClément Léger 
47216521289SClément Léger 	h32mxck = at91_clk_register_h32mx(pmc, "h32mxck", mckdivck);
47316521289SClément Léger 	if (!h32mxck)
47416521289SClément Léger 		panic();
47516521289SClément Léger 
47616521289SClément Léger 	pmc_clk = &pmc->chws[PMC_MCK2];
47716521289SClément Léger 	pmc_clk->clk = h32mxck;
47816521289SClément Léger 	pmc_clk->id = PMC_MCK2;
47916521289SClément Léger 
48016521289SClément Léger 	parents[0] = plladivck;
48116521289SClément Léger 	parents[1] = utmi_clk;
48216521289SClément Léger 	usbck = at91sam9x5_clk_register_usb(pmc, "usbck", parents, 2);
48316521289SClément Léger 	if (!usbck)
48416521289SClément Léger 		panic();
48516521289SClément Léger 
48690dee57aSClément Léger 	pmc_clk = &pmc->chws[PMC_USBCK];
48790dee57aSClément Léger 	pmc_clk->clk = usbck;
48890dee57aSClément Léger 	pmc_clk->id = PMC_USBCK;
48990dee57aSClément Léger 
49016521289SClément Léger 	parents[0] = slow_clk;
49116521289SClément Léger 	parents[1] = main_clk;
49216521289SClément Léger 	parents[2] = plladivck;
49316521289SClément Léger 	parents[3] = utmi_clk;
49416521289SClément Léger 	parents[4] = mckdivck;
49516521289SClément Léger 	parents[5] = audiopll_pmcck;
49616521289SClément Léger 	for (i = 0; i < ARRAY_SIZE(sama5d2_progck); i++) {
49716521289SClément Léger 		sam_clk = &sama5d2_progck[i];
49816521289SClément Léger 		clk = at91_clk_register_programmable(pmc, sam_clk->n,
49916521289SClément Léger 						     parents,
50016521289SClément Léger 						     PROGCK_PARENT_COUNT, i,
50116521289SClément Léger 						     &sama5d2_prog_layout);
50216521289SClément Léger 		if (!clk)
50316521289SClément Léger 			panic();
50416521289SClément Léger 
50516521289SClément Léger 		pmc_clk = &pmc->pchws[i];
50616521289SClément Léger 		pmc_clk->clk = clk;
50716521289SClément Léger 		pmc_clk->id = sam_clk->id;
50816521289SClément Léger 	}
50916521289SClément Léger 
51016521289SClément Léger 	/* This array order must match the one in sama5d2_systemck */
51116521289SClément Léger 	parents[0] = mckdivck;
51216521289SClément Léger 	parents[1] = mckdivck;
51316521289SClément Léger 	parents[2] = usbck;
51416521289SClément Léger 	parents[3] = usbck;
51516521289SClément Léger 	parents[4] = pmc->pchws[0].clk;
51616521289SClément Léger 	parents[5] = pmc->pchws[1].clk;
51716521289SClément Léger 	parents[6] = pmc->pchws[2].clk;
51816521289SClément Léger 	parents[7] = mckdivck;
51916521289SClément Léger 	for (i = 0; i < ARRAY_SIZE(sama5d2_systemck); i++) {
52016521289SClément Léger 		sam_clk = &sama5d2_systemck[i];
52116521289SClément Léger 		clk = at91_clk_register_system(pmc, sam_clk->n,
52216521289SClément Léger 					       parents[i],
52316521289SClément Léger 					       sam_clk->id);
52416521289SClément Léger 		if (!clk)
52516521289SClément Léger 			panic();
52616521289SClément Léger 
52716521289SClément Léger 		pmc_clk = &pmc->shws[i];
52816521289SClément Léger 		pmc_clk->clk = clk;
52916521289SClément Léger 		pmc_clk->id = sam_clk->id;
53016521289SClément Léger 	}
53116521289SClément Léger 
53216521289SClément Léger 	for (i = 0; i < ARRAY_SIZE(sama5d2_perick); i++) {
53316521289SClément Léger 		sam_clk = &sama5d2_perick[i];
53416521289SClément Léger 		clk = at91_clk_register_sam9x5_periph(pmc,
53516521289SClément Léger 						      &sama5d2_pcr_layout,
53616521289SClément Léger 						      sam_clk->n,
53716521289SClément Léger 						      mckdivck,
53816521289SClément Léger 						      sam_clk->id,
53916521289SClément Léger 						      &range);
54016521289SClément Léger 		if (!clk)
54116521289SClément Léger 			panic();
54216521289SClément Léger 
54316521289SClément Léger 		pmc_clk = &pmc->phws[i];
54416521289SClément Léger 		pmc_clk->clk = clk;
54516521289SClément Léger 		pmc_clk->id = sam_clk->id;
54616521289SClément Léger 	}
54716521289SClément Léger 
54816521289SClément Léger 	for (i = 0; i < ARRAY_SIZE(sama5d2_peri32ck); i++) {
54916521289SClément Léger 		sam_clk = &sama5d2_peri32ck[i].clk;
55016521289SClément Léger 		clk = at91_clk_register_sam9x5_periph(pmc,
55116521289SClément Léger 						      &sama5d2_pcr_layout,
55216521289SClément Léger 						      sam_clk->n,
55316521289SClément Léger 						      h32mxck,
55416521289SClément Léger 						      sam_clk->id,
55516521289SClément Léger 						      &sama5d2_peri32ck[i].r);
55616521289SClément Léger 		if (!clk)
55716521289SClément Léger 			panic();
55816521289SClément Léger 
55916521289SClément Léger 		pmc_clk = &pmc->phws[ARRAY_SIZE(sama5d2_perick) + i];
56016521289SClément Léger 		pmc_clk->clk = clk;
56116521289SClément Léger 		pmc_clk->id = sam_clk->id;
56216521289SClément Léger 	}
56316521289SClément Léger 
56416521289SClément Léger 	parents[0] = slow_clk;
56516521289SClément Léger 	parents[1] = main_clk;
56616521289SClément Léger 	parents[2] = plladivck;
56716521289SClément Léger 	parents[3] = utmi_clk;
56816521289SClément Léger 	parents[4] = mckdivck;
56916521289SClément Léger 	parents[5] = audiopll_pmcck;
57016521289SClément Léger 	for (i = 0; i < ARRAY_SIZE(sama5d2_gck); i++) {
57116521289SClément Léger 		sam_clk = &sama5d2_gck[i].clk;
57216521289SClément Léger 		clk = at91_clk_register_generated(pmc,
57316521289SClément Léger 						  &sama5d2_pcr_layout,
57416521289SClément Léger 						  sam_clk->n,
575*9aab6fb2STony Han 						  parents, NULL, 6,
57616521289SClément Léger 						  sam_clk->id,
57716521289SClément Léger 						  &sama5d2_gck[i].r,
57816521289SClément Léger 						  sama5d2_gck[i].chg_pid);
57916521289SClément Léger 		if (!clk)
58016521289SClément Léger 			panic();
58116521289SClément Léger 
58216521289SClément Léger 		pmc_clk = &pmc->ghws[i];
58316521289SClément Léger 		pmc_clk->clk = clk;
58416521289SClément Léger 		pmc_clk->id = sam_clk->id;
58516521289SClément Léger 	}
58616521289SClément Léger 
58716521289SClément Léger 	parents[0] = pmc_clk_get_by_name(pmc->phws, pmc->nperiph, "i2s0_clk");
58816521289SClément Léger 	parents[1] = pmc_clk_get_by_name(pmc->ghws, pmc->ngck, "i2s0_gclk");
58916521289SClément Léger 	clk = at91_clk_i2s_mux_register("i2s0_muxclk", parents, 2, 0);
59016521289SClément Léger 	if (!clk)
59116521289SClément Léger 		panic();
59216521289SClément Léger 
59316521289SClément Léger 	pmc->chws[PMC_I2S0_MUX].clk = clk;
59416521289SClément Léger 	pmc->chws[PMC_I2S0_MUX].id = PMC_I2S0_MUX;
59516521289SClément Léger 
59616521289SClément Léger 	parents[0] = pmc_clk_get_by_name(pmc->phws, pmc->nperiph, "i2s1_clk");
59716521289SClément Léger 	parents[1] = pmc_clk_get_by_name(pmc->ghws, pmc->ngck, "i2s1_gclk");
59816521289SClément Léger 	clk = at91_clk_i2s_mux_register("i2s1_muxclk", parents, 2, 1);
59916521289SClément Léger 	if (!clk)
60016521289SClément Léger 		panic();
60116521289SClément Léger 
60216521289SClément Léger 	pmc->chws[PMC_I2S1_MUX].clk = clk;
60316521289SClément Léger 	pmc->chws[PMC_I2S1_MUX].id = PMC_I2S1_MUX;
60416521289SClément Léger 
60516521289SClément Léger 	clk_dt_register_clk_provider(fdt, nodeoffset, clk_dt_pmc_get, pmc);
60616521289SClément Léger 
6075e6f824bSClément Léger 	pmc_register_pm();
6085e6f824bSClément Léger 
60916521289SClément Léger 	return TEE_SUCCESS;
61016521289SClément Léger }
61116521289SClément Léger 
61216521289SClément Léger CLK_DT_DECLARE(sama5d2_clk, "atmel,sama5d2-pmc", pmc_setup);
613