xref: /optee_os/core/drivers/remoteproc/stm32_remoteproc.c (revision ef3bc69c72b8d46493eab724eab6e018423088e1)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2023, STMicroelectronics
4  */
5 
6 #include <assert.h>
7 #include <config.h>
8 #include <drivers/rstctrl.h>
9 #include <drivers/stm32_remoteproc.h>
10 #ifdef CFG_STM32MP15
11 #include <drivers/stm32mp1_rcc.h>
12 #endif
13 #include <kernel/cache_helpers.h>
14 #include <kernel/dt_driver.h>
15 #include <kernel/tee_misc.h>
16 #include <libfdt.h>
17 #include <mm/core_memprot.h>
18 #include <mm/core_mmu.h>
19 #include <stm32_util.h>
20 
21 #define TIMEOUT_US_1MS	U(1000)
22 
23 /**
24  * struct stm32_rproc_mem - Memory regions used by the remote processor
25  *
26  * @addr:	physical base address from the CPU space perspective
27  * @da:		device address corresponding to the physical base address
28  *		from remote processor space perspective
29  * @size:	size of the region
30  */
31 struct stm32_rproc_mem {
32 	paddr_t addr;
33 	paddr_t da;
34 	size_t size;
35 };
36 
37 /**
38  * struct stm32_rproc_instance - rproc instance context
39  *
40  * @cdata:	pointer to the device compatible data
41  * @link:	the node in the rproc_list
42  * @n_regions:	number of memory regions
43  * @regions:	memory regions used
44  * @mcu_rst:	remote processor reset control
45  * @hold_boot:	remote processor hold boot control
46  * @ns_loading: True if supports non-secure firmware loading, false otherwise
47  */
48 struct stm32_rproc_instance {
49 	const struct stm32_rproc_compat_data *cdata;
50 	SLIST_ENTRY(stm32_rproc_instance) link;
51 	size_t n_regions;
52 	struct stm32_rproc_mem *regions;
53 	struct rstctrl *mcu_rst;
54 	struct rstctrl *hold_boot;
55 	bool ns_loading;
56 };
57 
58 /**
59  * struct stm32_rproc_compat_data - rproc associated data for compatible list
60  *
61  * @rproc_id:	identifies the remote processor
62  */
63 struct stm32_rproc_compat_data {
64 	uint32_t rproc_id;
65 };
66 
67 static SLIST_HEAD(, stm32_rproc_instance) rproc_list =
68 		SLIST_HEAD_INITIALIZER(rproc_list);
69 
70 void *stm32_rproc_get(uint32_t rproc_id)
71 {
72 	struct stm32_rproc_instance *rproc = NULL;
73 
74 	SLIST_FOREACH(rproc, &rproc_list, link)
75 		if (rproc->cdata->rproc_id == rproc_id)
76 			break;
77 
78 	return rproc;
79 }
80 
81 bool stm32_rproc_is_secure(uint32_t rproc_id)
82 {
83 	struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id);
84 
85 	if (rproc)
86 		return !rproc->cdata->ns_loading;
87 
88 	return false;
89 }
90 
91 TEE_Result stm32_rproc_start(uint32_t rproc_id)
92 {
93 	struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id);
94 	TEE_Result res = TEE_ERROR_GENERIC;
95 
96 	if (!rproc || !rproc->hold_boot)
97 		return TEE_ERROR_GENERIC;
98 
99 	/*
100 	 * The firmware is started by de-asserting the hold boot and
101 	 * asserting it back to avoid auto restart on a crash.
102 	 * No need to release the MCU reset as it is automatically released by
103 	 * the hardware.
104 	 */
105 	res = rstctrl_deassert_to(rproc->hold_boot, TIMEOUT_US_1MS);
106 	if (!res)
107 		res = rstctrl_assert_to(rproc->hold_boot, TIMEOUT_US_1MS);
108 
109 	return res;
110 }
111 
112 static TEE_Result rproc_stop(struct stm32_rproc_instance *rproc)
113 {
114 	TEE_Result res = TEE_ERROR_GENERIC;
115 
116 	if (!rproc->hold_boot || !rproc->mcu_rst)
117 		return TEE_ERROR_GENERIC;
118 
119 	res = rstctrl_assert_to(rproc->hold_boot, TIMEOUT_US_1MS);
120 	if (!res)
121 		res = rstctrl_assert_to(rproc->mcu_rst, TIMEOUT_US_1MS);
122 
123 	return res;
124 }
125 
126 TEE_Result stm32_rproc_stop(uint32_t rproc_id)
127 {
128 	struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id);
129 
130 	if (!rproc)
131 		return TEE_ERROR_BAD_PARAMETERS;
132 
133 	return rproc_stop(rproc);
134 }
135 
136 TEE_Result stm32_rproc_da_to_pa(uint32_t rproc_id, paddr_t da, size_t size,
137 				paddr_t *pa)
138 {
139 	struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id);
140 	struct stm32_rproc_mem *mems = NULL;
141 	unsigned int i = 0;
142 
143 	if (!rproc)
144 		return TEE_ERROR_BAD_PARAMETERS;
145 
146 	mems = rproc->regions;
147 
148 	for (i = 0; i < rproc->n_regions; i++) {
149 		if (core_is_buffer_inside(da, size, mems[i].da, mems[i].size)) {
150 			/*
151 			 * A match between the requested DA memory area and the
152 			 * registered regions has been found.
153 			 * The PA is the reserved-memory PA address plus the
154 			 * delta between the requested DA and the
155 			 * reserved-memory DA address.
156 			 */
157 			*pa = mems[i].addr + da - mems[i].da;
158 			return TEE_SUCCESS;
159 		}
160 	}
161 
162 	return TEE_ERROR_ACCESS_DENIED;
163 }
164 
165 TEE_Result stm32_rproc_map(uint32_t rproc_id, paddr_t pa, size_t size,
166 			   void **va)
167 {
168 	struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id);
169 	struct stm32_rproc_mem *mems = NULL;
170 	unsigned int i = 0;
171 
172 	if (!rproc)
173 		return TEE_ERROR_BAD_PARAMETERS;
174 
175 	mems = rproc->regions;
176 
177 	for (i = 0; i < rproc->n_regions; i++) {
178 		if (!core_is_buffer_inside(pa, size, mems[i].addr,
179 					   mems[i].size))
180 			continue;
181 		*va = core_mmu_add_mapping(MEM_AREA_RAM_NSEC, pa, size);
182 		if (!*va) {
183 			EMSG("Can't map region %#"PRIxPA" size %zu", pa, size);
184 			return TEE_ERROR_GENERIC;
185 		}
186 
187 		return TEE_SUCCESS;
188 	}
189 
190 	return TEE_ERROR_ACCESS_DENIED;
191 }
192 
193 TEE_Result stm32_rproc_unmap(uint32_t rproc_id, void *va, size_t size)
194 {
195 	struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id);
196 	struct stm32_rproc_mem *mems = NULL;
197 	paddr_t pa = virt_to_phys(va);
198 	unsigned int i = 0;
199 
200 	if (!rproc || !pa)
201 		return TEE_ERROR_BAD_PARAMETERS;
202 
203 	mems = rproc->regions;
204 
205 	for (i = 0; i < rproc->n_regions; i++) {
206 		if (!core_is_buffer_inside(pa, size, mems[i].addr,
207 					   mems[i].size))
208 			continue;
209 
210 		/* Flush the cache before unmapping the memory */
211 		dcache_clean_range(va, size);
212 
213 		if (core_mmu_remove_mapping(MEM_AREA_RAM_NSEC, va, size)) {
214 			EMSG("Can't unmap region %#"PRIxPA" size %zu",
215 			     pa, size);
216 			return TEE_ERROR_GENERIC;
217 		}
218 
219 		return TEE_SUCCESS;
220 	}
221 
222 	return TEE_ERROR_ACCESS_DENIED;
223 }
224 
225 static TEE_Result stm32_rproc_get_dma_range(struct stm32_rproc_mem *region,
226 					    const void *fdt, int node)
227 {
228 	const fdt32_t *list = NULL;
229 	int ahb_node = 0;
230 	int len = 0;
231 	int nranges = 0;
232 	int i = 0;
233 
234 	/*
235 	 * The match between local and remote processor memory mapping is
236 	 * described in the dma-ranges defined by the bus parent node.
237 	 */
238 	ahb_node = fdt_parent_offset(fdt, node);
239 
240 	list = fdt_getprop(fdt, ahb_node, "dma-ranges", &len);
241 	if (!list) {
242 		if (len != -FDT_ERR_NOTFOUND)
243 			return TEE_ERROR_GENERIC;
244 		/* Same memory mapping */
245 		DMSG("No dma-ranges found in DT");
246 		region->da = region->addr;
247 		return TEE_SUCCESS;
248 	}
249 
250 	if ((len % (sizeof(uint32_t) * 3)))
251 		return TEE_ERROR_GENERIC;
252 
253 	nranges = len / sizeof(uint32_t);
254 
255 	for (i = 0; i < nranges; i += 3) {
256 		uint32_t da = fdt32_to_cpu(list[i]);
257 		uint32_t pa = fdt32_to_cpu(list[i + 1]);
258 		uint32_t size = fdt32_to_cpu(list[i + 2]);
259 
260 		if (core_is_buffer_inside(region->addr, region->size,
261 					  pa, size)) {
262 			region->da = da + (region->addr - pa);
263 			return TEE_SUCCESS;
264 		}
265 	}
266 
267 	return TEE_ERROR_BAD_PARAMETERS;
268 }
269 
270 /* Get device tree memory regions reserved for the Cortex-M and the IPC */
271 static TEE_Result stm32_rproc_parse_mems(struct stm32_rproc_instance *rproc,
272 					 const void *fdt, int node)
273 {
274 	const fdt32_t *list = NULL;
275 	TEE_Result res = TEE_ERROR_GENERIC;
276 	struct stm32_rproc_mem *regions = NULL;
277 	int len = 0;
278 	int n_regions = 0;
279 	int i = 0;
280 
281 	list = fdt_getprop(fdt, node, "memory-region", &len);
282 	if (!list) {
283 		EMSG("No memory regions found in DT");
284 		return TEE_ERROR_GENERIC;
285 	}
286 
287 	n_regions = len / sizeof(uint32_t);
288 
289 	regions = calloc(n_regions, sizeof(*regions));
290 	if (!regions)
291 		return TEE_ERROR_OUT_OF_MEMORY;
292 
293 	for (i = 0; i < n_regions; i++) {
294 		int pnode = 0;
295 
296 		pnode = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(list[i]));
297 		if (pnode < 0) {
298 			res = TEE_ERROR_GENERIC;
299 			goto err;
300 		}
301 
302 		if (fdt_reg_info(fdt, pnode, &regions[i].addr,
303 				 &regions[i].size)) {
304 			res = TEE_ERROR_GENERIC;
305 			goto err;
306 		}
307 
308 #if defined(CFG_STM32MP15)
309 		if (stm32mp1_ram_intersect_pager_ram(regions[i].addr,
310 						     regions[i].size)) {
311 			EMSG("Region %#"PRIxPA"..%#"PRIxPA" intersects pager secure memory",
312 			     regions[i].addr,
313 			     regions[i].addr + regions[i].size);
314 			return TEE_ERROR_GENERIC;
315 		}
316 #endif
317 
318 		res = stm32_rproc_get_dma_range(&regions[i], fdt, node);
319 		if (res)
320 			goto err;
321 
322 		if (!regions[i].addr || !regions[i].size) {
323 			res = TEE_ERROR_BAD_PARAMETERS;
324 			goto err;
325 		}
326 
327 		DMSG("register region %#"PRIxPA" size %#zx",
328 		     regions[i].addr, regions[i].size);
329 	}
330 
331 	rproc->n_regions = n_regions;
332 	rproc->regions = regions;
333 
334 	return TEE_SUCCESS;
335 
336 err:
337 	free(regions);
338 
339 	return res;
340 }
341 
342 TEE_Result stm32_rproc_clean_up_memories(uint32_t rproc_id)
343 {
344 	struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id);
345 	struct stm32_rproc_mem *mems = NULL;
346 	TEE_Result res = TEE_ERROR_GENERIC;
347 	unsigned int i = 0;
348 	void *va = NULL;
349 	size_t size = 0;
350 	paddr_t pa = 0;
351 
352 	if (!rproc)
353 		return TEE_ERROR_BAD_PARAMETERS;
354 
355 	mems = rproc->regions;
356 	for (i = 0; i < rproc->n_regions; i++) {
357 		pa = mems[i].addr;
358 		size = mems[i].size;
359 		res = stm32_rproc_map(rproc_id, pa, size, &va);
360 		if (res)
361 			break;
362 		memset(va, 0, size);
363 		res = stm32_rproc_unmap(rproc_id, va, size);
364 		if (res)
365 			break;
366 	}
367 
368 	return res;
369 }
370 
371 static void stm32_rproc_cleanup(struct stm32_rproc_instance *rproc)
372 {
373 	free(rproc->regions);
374 	free(rproc);
375 }
376 
377 static TEE_Result stm32_rproc_probe(const void *fdt, int node,
378 				    const void *comp_data)
379 {
380 	struct stm32_rproc_instance *rproc = NULL;
381 	TEE_Result res = TEE_ERROR_GENERIC;
382 
383 	rproc = calloc(1, sizeof(*rproc));
384 	if (!rproc)
385 		return TEE_ERROR_OUT_OF_MEMORY;
386 
387 	rproc->cdata = comp_data;
388 
389 	res = stm32_rproc_parse_mems(rproc, fdt, node);
390 	if (res)
391 		goto err;
392 
393 	res = rstctrl_dt_get_by_name(fdt, node, "mcu_rst", &rproc->mcu_rst);
394 	if (res)
395 		goto err;
396 
397 	res = rstctrl_dt_get_by_name(fdt, node, "hold_boot", &rproc->hold_boot);
398 	if (res)
399 		goto err;
400 
401 	/* Ensure that the MCU is HOLD */
402 	if (rproc->mcu_rst) {
403 		res = rproc_stop(rproc);
404 		if (res)
405 			goto err;
406 	}
407 
408 	if (!stm32_rcc_is_secure()) {
409 		IMSG("WARNING: insecure rproc isolation, RCC is not secure");
410 		if (!IS_ENABLED(CFG_INSECURE))
411 			panic();
412 	} else {
413 		stm32_rcc_set_mckprot(true);
414 	}
415 
416 	/*
417 	 * The memory management should be enhance with firewall
418 	 * mechanism to map the memory in secure area for the firmware
419 	 * loading and then to give exclusive access right to the
420 	 * coprocessor (except for the shared memory).
421 	 */
422 	IMSG("Warning: the remoteproc memories are not protected by firewall");
423 
424 	SLIST_INSERT_HEAD(&rproc_list, rproc, link);
425 
426 	return TEE_SUCCESS;
427 
428 err:
429 	stm32_rproc_cleanup(rproc);
430 	return res;
431 }
432 
433 static const struct stm32_rproc_compat_data stm32_rproc_m4_compat = {
434 	.rproc_id = STM32_M4_RPROC_ID,
435 	.ns_loading = false,
436 };
437 
438 static const struct dt_device_match stm32_rproc_match_table[] = {
439 	{
440 		.compatible = "st,stm32mp1-m4-tee",
441 		.compat_data = &stm32_rproc_m4_compat,
442 	},
443 	{ }
444 };
445 
446 DEFINE_DT_DRIVER(stm32_rproc_dt_driver) = {
447 	.name = "stm32-rproc",
448 	.match_table = stm32_rproc_match_table,
449 	.probe = &stm32_rproc_probe,
450 };
451