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