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