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