xref: /optee_os/core/drivers/clk/sam/at91_pmc.c (revision 12fc37711783247b0d05fdc271ef007f4930767b)
1 // SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause
2 /*
3  *  Copyright (C) 2021 Microchip
4  */
5 
6 #include <dt-bindings/clock/at91.h>
7 #include <io.h>
8 #include <kernel/panic.h>
9 #include <kernel/pm.h>
10 #include <malloc.h>
11 #include <string.h>
12 #include <trace.h>
13 #include <types_ext.h>
14 
15 #include "at91_clk.h"
16 
17 #define PMC_MAX_IDS 128
18 #define PMC_MAX_PCKS 8
19 
20 static struct clk *pmc_clk_get_by_id(struct pmc_clk *clks, unsigned int nclk,
21 				     unsigned int id)
22 {
23 	unsigned int i = 0;
24 
25 	for (i = 0; i < nclk; i++) {
26 		if (clks[i].clk && clks[i].id == id)
27 			return clks[i].clk;
28 	}
29 
30 	return NULL;
31 }
32 
33 struct clk *pmc_clk_get_by_name(struct pmc_clk *clks, unsigned int nclk,
34 				const char *name)
35 {
36 	unsigned int i = 0;
37 
38 	for (i = 0; i < nclk; i++)
39 		if (strcmp(clks[i].clk->name, name) == 0)
40 			return clks[i].clk;
41 
42 	return NULL;
43 }
44 
45 TEE_Result pmc_clk_get(struct pmc_data *pmc, unsigned int type,
46 		       unsigned int idx, struct clk **clk)
47 {
48 	unsigned int nclk = 0;
49 	struct pmc_clk *clks = NULL;
50 
51 	switch (type) {
52 	case PMC_TYPE_CORE:
53 		nclk = pmc->ncore;
54 		clks = pmc->chws;
55 		break;
56 	case PMC_TYPE_SYSTEM:
57 		nclk = pmc->nsystem;
58 		clks = pmc->shws;
59 		break;
60 	case PMC_TYPE_PERIPHERAL:
61 		nclk = pmc->nperiph;
62 		clks = pmc->phws;
63 		break;
64 	case PMC_TYPE_GCK:
65 		nclk = pmc->ngck;
66 		clks = pmc->ghws;
67 		break;
68 	case PMC_TYPE_PROGRAMMABLE:
69 		nclk = pmc->npck;
70 		clks = pmc->pchws;
71 		break;
72 	default:
73 		return TEE_ERROR_BAD_PARAMETERS;
74 	}
75 
76 	*clk = pmc_clk_get_by_id(clks, nclk, idx);
77 	if (!*clk)
78 		return TEE_ERROR_BAD_PARAMETERS;
79 
80 	return TEE_SUCCESS;
81 }
82 
83 struct clk *clk_dt_pmc_get(struct dt_pargs *clkspec, void *data,
84 			   TEE_Result *res)
85 {
86 	unsigned int type = clkspec->args[0];
87 	unsigned int idx = clkspec->args[1];
88 	struct pmc_data *pmc_data = data;
89 	struct clk *clk = NULL;
90 
91 	if (clkspec->args_count != 2) {
92 		*res = TEE_ERROR_BAD_PARAMETERS;
93 		return NULL;
94 	}
95 
96 	*res = pmc_clk_get(pmc_data, type, idx, &clk);
97 
98 	return clk;
99 }
100 
101 struct pmc_data *pmc_data_allocate(unsigned int ncore, unsigned int nsystem,
102 				   unsigned int nperiph, unsigned int ngck,
103 				   unsigned int npck)
104 {
105 	unsigned int num_clks = ncore + nsystem + nperiph + ngck + npck;
106 	unsigned int alloc_size = sizeof(struct pmc_data) +
107 				  num_clks * sizeof(struct pmc_clk);
108 	struct pmc_data *pmc_data = NULL;
109 
110 	pmc_data = calloc(1, alloc_size);
111 	if (!pmc_data)
112 		return NULL;
113 
114 	pmc_data->ncore = ncore;
115 	pmc_data->chws = pmc_data->hwtable;
116 
117 	pmc_data->nsystem = nsystem;
118 	pmc_data->shws = pmc_data->chws + ncore;
119 
120 	pmc_data->nperiph = nperiph;
121 	pmc_data->phws = pmc_data->shws + nsystem;
122 
123 	pmc_data->ngck = ngck;
124 	pmc_data->ghws = pmc_data->phws + nperiph;
125 
126 	pmc_data->npck = npck;
127 	pmc_data->pchws = pmc_data->ghws + ngck;
128 
129 	return pmc_data;
130 }
131 
132 #ifdef CFG_PM_ARM32
133 static uint8_t registered_ids[PMC_MAX_IDS];
134 static uint8_t registered_pcks[PMC_MAX_PCKS];
135 
136 static struct
137 {
138 	uint32_t scsr;
139 	uint32_t pcsr0;
140 	uint32_t uckr;
141 	uint32_t mor;
142 	uint32_t mcfr;
143 	uint32_t pllar;
144 	uint32_t mckr;
145 	uint32_t usb;
146 	uint32_t imr;
147 	uint32_t pcsr1;
148 	uint32_t pcr[PMC_MAX_IDS];
149 	uint32_t audio_pll0;
150 	uint32_t audio_pll1;
151 	uint32_t pckr[PMC_MAX_PCKS];
152 } pmc_cache;
153 
154 /*
155  * As Peripheral ID 0 is invalid on AT91 chips, the identifier is stored
156  * without alteration in the table, and 0 is for unused clocks.
157  */
158 void pmc_register_id(uint8_t id)
159 {
160 	int i = 0;
161 
162 	for (i = 0; i < PMC_MAX_IDS; i++) {
163 		if (registered_ids[i] == 0) {
164 			registered_ids[i] = id;
165 			return;
166 		}
167 		if (registered_ids[i] == id)
168 			return;
169 	}
170 
171 	panic("Invalid clock ID");
172 }
173 
174 /*
175  * As Programmable Clock 0 is valid on AT91 chips, there is an offset
176  * of 1 between the stored value and the real clock ID.
177  */
178 void pmc_register_pck(uint8_t pck)
179 {
180 	int i = 0;
181 
182 	for (i = 0; i < PMC_MAX_PCKS; i++) {
183 		if (registered_pcks[i] == 0) {
184 			registered_pcks[i] = pck + 1;
185 			return;
186 		}
187 		if (registered_pcks[i] == pck + 1)
188 			return;
189 	}
190 
191 	panic("Invalid clock ID");
192 }
193 
194 static void pmc_suspend(void)
195 {
196 	int i = 0;
197 	uint8_t num = 0;
198 	vaddr_t pmc_base = at91_pmc_get_base();
199 
200 	pmc_cache.scsr = io_read32(pmc_base + AT91_PMC_SCSR);
201 	pmc_cache.pcsr0 = io_read32(pmc_base + AT91_PMC_PCSR);
202 	pmc_cache.uckr = io_read32(pmc_base + AT91_CKGR_UCKR);
203 	pmc_cache.mor = io_read32(pmc_base + AT91_CKGR_MOR);
204 	pmc_cache.mcfr = io_read32(pmc_base + AT91_CKGR_MCFR);
205 	pmc_cache.pllar = io_read32(pmc_base + AT91_CKGR_PLLAR);
206 	pmc_cache.mckr = io_read32(pmc_base + AT91_PMC_MCKR);
207 	pmc_cache.usb = io_read32(pmc_base + AT91_PMC_USB);
208 	pmc_cache.imr = io_read32(pmc_base + AT91_PMC_IMR);
209 	pmc_cache.pcsr1 = io_read32(pmc_base + AT91_PMC_PCSR1);
210 
211 	for (i = 0; registered_ids[i]; i++) {
212 		io_write32(pmc_base + AT91_PMC_PCR,
213 			   registered_ids[i] & AT91_PMC_PCR_PID_MASK);
214 		pmc_cache.pcr[registered_ids[i]] = io_read32(pmc_base +
215 							     AT91_PMC_PCR);
216 	}
217 	for (i = 0; registered_pcks[i]; i++) {
218 		num = registered_pcks[i] - 1;
219 		pmc_cache.pckr[num] = io_read32(pmc_base + AT91_PMC_PCKR(num));
220 	}
221 }
222 
223 static bool pmc_ready(vaddr_t pmc_base, unsigned int mask)
224 {
225 	uint32_t status = 0;
226 
227 	status = io_read32(pmc_base + AT91_PMC_SR);
228 
229 	return (status & mask) == mask;
230 }
231 
232 static void pmc_resume(void)
233 {
234 	int i = 0;
235 	uint8_t num = 0;
236 	uint32_t tmp = 0;
237 	vaddr_t pmc_base = at91_pmc_get_base();
238 	uint32_t mask = AT91_PMC_MCKRDY | AT91_PMC_LOCKA;
239 
240 	tmp = io_read32(pmc_base + AT91_PMC_MCKR);
241 	if (pmc_cache.mckr != tmp)
242 		panic("MCKR was not configured properly by the previous bootstage");
243 	tmp = io_read32(pmc_base + AT91_CKGR_PLLAR);
244 	if (pmc_cache.pllar != tmp)
245 		panic("PLLAR was not configured properly by the previous bootstage");
246 
247 	io_write32(pmc_base + AT91_PMC_SCER, pmc_cache.scsr);
248 	io_write32(pmc_base + AT91_PMC_PCER, pmc_cache.pcsr0);
249 	io_write32(pmc_base + AT91_CKGR_UCKR, pmc_cache.uckr);
250 	io_write32(pmc_base + AT91_CKGR_MOR, pmc_cache.mor);
251 	io_write32(pmc_base + AT91_CKGR_MCFR, pmc_cache.mcfr);
252 	io_write32(pmc_base + AT91_PMC_USB, pmc_cache.usb);
253 	io_write32(pmc_base + AT91_PMC_IMR, pmc_cache.imr);
254 	io_write32(pmc_base + AT91_PMC_PCER1, pmc_cache.pcsr1);
255 
256 	for (i = 0; registered_ids[i]; i++) {
257 		io_write32(pmc_base + AT91_PMC_PCR,
258 			   pmc_cache.pcr[registered_ids[i]] | AT91_PMC_PCR_CMD);
259 	}
260 	for (i = 0; registered_pcks[i]; i++) {
261 		num = registered_pcks[i] - 1;
262 		io_write32(pmc_base + AT91_PMC_PCKR(num), pmc_cache.pckr[num]);
263 	}
264 
265 	if (pmc_cache.uckr & AT91_PMC_UPLLEN)
266 		mask |= AT91_PMC_LOCKU;
267 
268 	while (!pmc_ready(pmc_base, mask))
269 		;
270 }
271 
272 static TEE_Result pmc_pm(enum pm_op op, uint32_t pm_hint __unused,
273 			 const struct pm_callback_handle *hdl __unused)
274 {
275 	switch (op) {
276 	case PM_OP_RESUME:
277 		pmc_resume();
278 		break;
279 	case PM_OP_SUSPEND:
280 		pmc_suspend();
281 		break;
282 	default:
283 		panic("Invalid PM operation");
284 	}
285 
286 	return TEE_SUCCESS;
287 }
288 
289 void pmc_register_pm(void)
290 {
291 	/*
292 	 * We register the clock as a core service since clocks must be
293 	 * re-enable prior to accessing devices
294 	 */
295 	register_pm_core_service_cb(pmc_pm, NULL, "pmc");
296 }
297 
298 #endif
299