1 // SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause
2 /*
3  *  Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
4  *  Copyright (C) 2021 Microchip
5  */
6 
7 #include <io.h>
8 #include <kernel/delay.h>
9 #include <mm/core_memprot.h>
10 #include <sam_sfr.h>
11 #include <types_ext.h>
12 
13 #include "at91_clk.h"
14 
15 /*
16  * The purpose of this clock is to generate a 480 MHz signal. A different
17  * rate can't be configured.
18  */
19 #define UTMI_RATE	480000000
20 
21 struct clk_utmi {
22 	vaddr_t pmc_base;
23 	vaddr_t sfr_base;
24 };
25 
clk_utmi_ready(vaddr_t pmc_base)26 static bool clk_utmi_ready(vaddr_t pmc_base)
27 {
28 	uint32_t status = io_read32(pmc_base + AT91_PMC_SR);
29 
30 	return status & AT91_PMC_LOCKU;
31 }
32 
clk_utmi_enable(struct clk * clk)33 static TEE_Result clk_utmi_enable(struct clk *clk)
34 {
35 	struct clk *clk_parent = NULL;
36 	struct clk_utmi *utmi = clk->priv;
37 	unsigned int uckr = AT91_PMC_UPLLEN | AT91_PMC_UPLLCOUNT |
38 			    AT91_PMC_BIASEN;
39 	unsigned int utmi_ref_clk_freq = 0;
40 	unsigned long parent_rate = 0;
41 
42 	/*
43 	 * If mainck rate is different from 12 MHz, we have to configure the
44 	 * FREQ field of the SFR_UTMICKTRIM register to generate properly
45 	 * the utmi clock.
46 	 */
47 	clk_parent = clk_get_parent(clk);
48 	parent_rate = clk_get_rate(clk_parent);
49 
50 	switch (parent_rate) {
51 	case 12000000:
52 		utmi_ref_clk_freq = 0;
53 		break;
54 	case 16000000:
55 		utmi_ref_clk_freq = 1;
56 		break;
57 	case 24000000:
58 		utmi_ref_clk_freq = 2;
59 		break;
60 	/*
61 	 * Not supported on SAMA5D2 but it's not an issue since MAINCK
62 	 * maximum value is 24 MHz.
63 	 */
64 	case 48000000:
65 		utmi_ref_clk_freq = 3;
66 		break;
67 	default:
68 		EMSG("UTMICK: unsupported mainck rate");
69 		return TEE_ERROR_BAD_PARAMETERS;
70 	}
71 
72 	if (utmi->sfr_base) {
73 		io_clrsetbits32(utmi->sfr_base + AT91_SFR_UTMICKTRIM,
74 				AT91_UTMICKTRIM_FREQ, utmi_ref_clk_freq);
75 	} else if (utmi_ref_clk_freq) {
76 		EMSG("UTMICK: sfr node required");
77 		return TEE_ERROR_BAD_STATE;
78 	}
79 
80 	io_clrsetbits32(utmi->pmc_base + AT91_CKGR_UCKR, uckr, uckr);
81 
82 	while (!clk_utmi_ready(utmi->pmc_base))
83 		;
84 
85 	return TEE_SUCCESS;
86 }
87 
clk_utmi_disable(struct clk * clk)88 static void clk_utmi_disable(struct clk *clk)
89 {
90 	struct clk_utmi *utmi = clk->priv;
91 
92 	io_clrbits32(utmi->pmc_base + AT91_CKGR_UCKR, AT91_PMC_UPLLEN);
93 }
94 
clk_utmi_get_rate(struct clk * clk __unused,unsigned long parent_rate __unused)95 static unsigned long clk_utmi_get_rate(struct clk *clk __unused,
96 				       unsigned long parent_rate __unused)
97 {
98 	/* UTMI clk rate is fixed. */
99 	return UTMI_RATE;
100 }
101 
102 static const struct clk_ops utmi_ops = {
103 	.enable = clk_utmi_enable,
104 	.disable = clk_utmi_disable,
105 	.get_rate = clk_utmi_get_rate,
106 };
107 
108 struct clk *
at91_clk_register_utmi(struct pmc_data * pmc,const char * name,struct clk * parent)109 at91_clk_register_utmi(struct pmc_data *pmc, const char *name,
110 		       struct clk *parent)
111 {
112 	struct clk_utmi *utmi = NULL;
113 	struct clk *clk = NULL;
114 
115 	clk = clk_alloc(name, &utmi_ops, &parent, 1);
116 	if (!clk)
117 		return NULL;
118 
119 	utmi = calloc(1, sizeof(*utmi));
120 	if (!utmi) {
121 		clk_free(clk);
122 		return NULL;
123 	}
124 
125 	utmi->pmc_base = pmc->base;
126 	utmi->sfr_base = sam_sfr_base();
127 	clk->flags = CLK_SET_RATE_GATE;
128 
129 	clk->priv = utmi;
130 
131 	if (clk_register(clk)) {
132 		clk_free(clk);
133 		free(utmi);
134 		return NULL;
135 	}
136 
137 	return clk;
138 }
139