xref: /optee_os/core/drivers/clk/sam/at91_pmc.c (revision ba2a6adb764f1310ad3c3091d89de84274f86b02)
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 TEE_Result clk_dt_pmc_get(struct dt_pargs *clkspec, void *data,
84 			  struct clk **out_clk)
85 {
86 	unsigned int type = clkspec->args[0];
87 	unsigned int idx = clkspec->args[1];
88 	struct pmc_data *pmc_data = data;
89 
90 	if (clkspec->args_count != 2)
91 		return TEE_ERROR_BAD_PARAMETERS;
92 
93 	return pmc_clk_get(pmc_data, type, idx, out_clk);
94 }
95 
96 struct pmc_data *pmc_data_allocate(unsigned int ncore, unsigned int nsystem,
97 				   unsigned int nperiph, unsigned int ngck,
98 				   unsigned int npck)
99 {
100 	unsigned int num_clks = ncore + nsystem + nperiph + ngck + npck;
101 	unsigned int alloc_size = sizeof(struct pmc_data) +
102 				  num_clks * sizeof(struct pmc_clk);
103 	struct pmc_data *pmc_data = NULL;
104 
105 	pmc_data = calloc(1, alloc_size);
106 	if (!pmc_data)
107 		return NULL;
108 
109 	pmc_data->ncore = ncore;
110 	pmc_data->chws = pmc_data->hwtable;
111 
112 	pmc_data->nsystem = nsystem;
113 	pmc_data->shws = pmc_data->chws + ncore;
114 
115 	pmc_data->nperiph = nperiph;
116 	pmc_data->phws = pmc_data->shws + nsystem;
117 
118 	pmc_data->ngck = ngck;
119 	pmc_data->ghws = pmc_data->phws + nperiph;
120 
121 	pmc_data->npck = npck;
122 	pmc_data->pchws = pmc_data->ghws + ngck;
123 
124 	return pmc_data;
125 }
126 
127 #ifdef CFG_PM_ARM32
128 static uint8_t registered_ids[PMC_MAX_IDS];
129 static uint8_t registered_pcks[PMC_MAX_PCKS];
130 
131 static struct
132 {
133 	uint32_t scsr;
134 	uint32_t pcsr0;
135 	uint32_t uckr;
136 	uint32_t mor;
137 	uint32_t mcfr;
138 	uint32_t pllar;
139 	uint32_t mckr;
140 	uint32_t usb;
141 	uint32_t imr;
142 	uint32_t pcsr1;
143 	uint32_t pcr[PMC_MAX_IDS];
144 	uint32_t audio_pll0;
145 	uint32_t audio_pll1;
146 	uint32_t pckr[PMC_MAX_PCKS];
147 } pmc_cache;
148 
149 /*
150  * As Peripheral ID 0 is invalid on AT91 chips, the identifier is stored
151  * without alteration in the table, and 0 is for unused clocks.
152  */
153 void pmc_register_id(uint8_t id)
154 {
155 	int i = 0;
156 
157 	for (i = 0; i < PMC_MAX_IDS; i++) {
158 		if (registered_ids[i] == 0) {
159 			registered_ids[i] = id;
160 			return;
161 		}
162 		if (registered_ids[i] == id)
163 			return;
164 	}
165 
166 	panic("Invalid clock ID");
167 }
168 
169 /*
170  * As Programmable Clock 0 is valid on AT91 chips, there is an offset
171  * of 1 between the stored value and the real clock ID.
172  */
173 void pmc_register_pck(uint8_t pck)
174 {
175 	int i = 0;
176 
177 	for (i = 0; i < PMC_MAX_PCKS; i++) {
178 		if (registered_pcks[i] == 0) {
179 			registered_pcks[i] = pck + 1;
180 			return;
181 		}
182 		if (registered_pcks[i] == pck + 1)
183 			return;
184 	}
185 
186 	panic("Invalid clock ID");
187 }
188 
189 static void pmc_suspend(void)
190 {
191 	int i = 0;
192 	uint8_t num = 0;
193 	vaddr_t pmc_base = at91_pmc_get_base();
194 
195 	pmc_cache.scsr = io_read32(pmc_base + AT91_PMC_SCSR);
196 	pmc_cache.pcsr0 = io_read32(pmc_base + AT91_PMC_PCSR);
197 	pmc_cache.uckr = io_read32(pmc_base + AT91_CKGR_UCKR);
198 	pmc_cache.mor = io_read32(pmc_base + AT91_CKGR_MOR);
199 	pmc_cache.mcfr = io_read32(pmc_base + AT91_CKGR_MCFR);
200 	pmc_cache.pllar = io_read32(pmc_base + AT91_CKGR_PLLAR);
201 	pmc_cache.mckr = io_read32(pmc_base + AT91_PMC_MCKR);
202 	pmc_cache.usb = io_read32(pmc_base + AT91_PMC_USB);
203 	pmc_cache.imr = io_read32(pmc_base + AT91_PMC_IMR);
204 	pmc_cache.pcsr1 = io_read32(pmc_base + AT91_PMC_PCSR1);
205 
206 	for (i = 0; registered_ids[i]; i++) {
207 		io_write32(pmc_base + AT91_PMC_PCR,
208 			   registered_ids[i] & AT91_PMC_PCR_PID_MASK);
209 		pmc_cache.pcr[registered_ids[i]] = io_read32(pmc_base +
210 							     AT91_PMC_PCR);
211 	}
212 	for (i = 0; registered_pcks[i]; i++) {
213 		num = registered_pcks[i] - 1;
214 		pmc_cache.pckr[num] = io_read32(pmc_base + AT91_PMC_PCKR(num));
215 	}
216 }
217 
218 static bool pmc_ready(vaddr_t pmc_base, unsigned int mask)
219 {
220 	uint32_t status = 0;
221 
222 	status = io_read32(pmc_base + AT91_PMC_SR);
223 
224 	return (status & mask) == mask;
225 }
226 
227 static void pmc_resume(void)
228 {
229 	int i = 0;
230 	uint8_t num = 0;
231 	uint32_t tmp = 0;
232 	vaddr_t pmc_base = at91_pmc_get_base();
233 	uint32_t mask = AT91_PMC_MCKRDY | AT91_PMC_LOCKA;
234 
235 	tmp = io_read32(pmc_base + AT91_PMC_MCKR);
236 	if (pmc_cache.mckr != tmp)
237 		panic("MCKR was not configured properly by the previous bootstage");
238 	tmp = io_read32(pmc_base + AT91_CKGR_PLLAR);
239 	if (pmc_cache.pllar != tmp)
240 		panic("PLLAR was not configured properly by the previous bootstage");
241 
242 	io_write32(pmc_base + AT91_PMC_SCER, pmc_cache.scsr);
243 	io_write32(pmc_base + AT91_PMC_PCER, pmc_cache.pcsr0);
244 	io_write32(pmc_base + AT91_CKGR_UCKR, pmc_cache.uckr);
245 	io_write32(pmc_base + AT91_CKGR_MOR, pmc_cache.mor);
246 	io_write32(pmc_base + AT91_CKGR_MCFR, pmc_cache.mcfr);
247 	io_write32(pmc_base + AT91_PMC_USB, pmc_cache.usb);
248 	io_write32(pmc_base + AT91_PMC_IMR, pmc_cache.imr);
249 	io_write32(pmc_base + AT91_PMC_PCER1, pmc_cache.pcsr1);
250 
251 	for (i = 0; registered_ids[i]; i++) {
252 		io_write32(pmc_base + AT91_PMC_PCR,
253 			   pmc_cache.pcr[registered_ids[i]] | AT91_PMC_PCR_CMD);
254 	}
255 	for (i = 0; registered_pcks[i]; i++) {
256 		num = registered_pcks[i] - 1;
257 		io_write32(pmc_base + AT91_PMC_PCKR(num), pmc_cache.pckr[num]);
258 	}
259 
260 	if (pmc_cache.uckr & AT91_PMC_UPLLEN)
261 		mask |= AT91_PMC_LOCKU;
262 
263 	while (!pmc_ready(pmc_base, mask))
264 		;
265 }
266 
267 static TEE_Result pmc_pm(enum pm_op op, uint32_t pm_hint __unused,
268 			 const struct pm_callback_handle *hdl __unused)
269 {
270 	switch (op) {
271 	case PM_OP_RESUME:
272 		pmc_resume();
273 		break;
274 	case PM_OP_SUSPEND:
275 		pmc_suspend();
276 		break;
277 	default:
278 		panic("Invalid PM operation");
279 	}
280 
281 	return TEE_SUCCESS;
282 }
283 
284 void pmc_register_pm(void)
285 {
286 	/*
287 	 * We register the clock as a core service since clocks must be
288 	 * re-enable prior to accessing devices
289 	 */
290 	register_pm_core_service_cb(pmc_pm, NULL, "pmc");
291 }
292 
293 #endif
294