xref: /optee_os/core/drivers/remoteproc/stm32_remoteproc.c (revision fb2b4f6fe25cf4f4abf5b76baff8b1b32cc74fcd)
15a2d2237SArnaud Pouliquen // SPDX-License-Identifier: BSD-2-Clause
25a2d2237SArnaud Pouliquen /*
35a2d2237SArnaud Pouliquen  * Copyright (c) 2023, STMicroelectronics
45a2d2237SArnaud Pouliquen  */
55a2d2237SArnaud Pouliquen 
65a2d2237SArnaud Pouliquen #include <assert.h>
75a2d2237SArnaud Pouliquen #include <config.h>
85a2d2237SArnaud Pouliquen #include <drivers/rstctrl.h>
95a2d2237SArnaud Pouliquen #include <drivers/stm32_remoteproc.h>
100cc468d1SEtienne Carriere #ifdef CFG_STM32MP15
110cc468d1SEtienne Carriere #include <drivers/stm32mp1_rcc.h>
120cc468d1SEtienne Carriere #endif
135a2d2237SArnaud Pouliquen #include <kernel/cache_helpers.h>
145a2d2237SArnaud Pouliquen #include <kernel/dt_driver.h>
155a2d2237SArnaud Pouliquen #include <kernel/tee_misc.h>
165a2d2237SArnaud Pouliquen #include <libfdt.h>
175a2d2237SArnaud Pouliquen #include <mm/core_memprot.h>
185a2d2237SArnaud Pouliquen #include <mm/core_mmu.h>
19beedc460SEtienne Carriere #include <stm32_util.h>
205a2d2237SArnaud Pouliquen 
215a2d2237SArnaud Pouliquen #define TIMEOUT_US_1MS	U(1000)
225a2d2237SArnaud Pouliquen 
235a2d2237SArnaud Pouliquen /**
245a2d2237SArnaud Pouliquen  * struct stm32_rproc_mem - Memory regions used by the remote processor
255a2d2237SArnaud Pouliquen  *
265a2d2237SArnaud Pouliquen  * @addr:	physical base address from the CPU space perspective
275a2d2237SArnaud Pouliquen  * @da:		device address corresponding to the physical base address
285a2d2237SArnaud Pouliquen  *		from remote processor space perspective
295a2d2237SArnaud Pouliquen  * @size:	size of the region
305a2d2237SArnaud Pouliquen  */
315a2d2237SArnaud Pouliquen struct stm32_rproc_mem {
325a2d2237SArnaud Pouliquen 	paddr_t addr;
335a2d2237SArnaud Pouliquen 	paddr_t da;
345a2d2237SArnaud Pouliquen 	size_t size;
355a2d2237SArnaud Pouliquen };
365a2d2237SArnaud Pouliquen 
375a2d2237SArnaud Pouliquen /**
385a2d2237SArnaud Pouliquen  * struct stm32_rproc_instance - rproc instance context
395a2d2237SArnaud Pouliquen  *
405a2d2237SArnaud Pouliquen  * @cdata:	pointer to the device compatible data
415a2d2237SArnaud Pouliquen  * @link:	the node in the rproc_list
425a2d2237SArnaud Pouliquen  * @n_regions:	number of memory regions
435a2d2237SArnaud Pouliquen  * @regions:	memory regions used
445a2d2237SArnaud Pouliquen  * @mcu_rst:	remote processor reset control
455a2d2237SArnaud Pouliquen  * @hold_boot:	remote processor hold boot control
465a2d2237SArnaud Pouliquen  */
475a2d2237SArnaud Pouliquen struct stm32_rproc_instance {
485a2d2237SArnaud Pouliquen 	const struct stm32_rproc_compat_data *cdata;
495a2d2237SArnaud Pouliquen 	SLIST_ENTRY(stm32_rproc_instance) link;
505a2d2237SArnaud Pouliquen 	size_t n_regions;
515a2d2237SArnaud Pouliquen 	struct stm32_rproc_mem *regions;
525a2d2237SArnaud Pouliquen 	struct rstctrl *mcu_rst;
535a2d2237SArnaud Pouliquen 	struct rstctrl *hold_boot;
545a2d2237SArnaud Pouliquen };
555a2d2237SArnaud Pouliquen 
565a2d2237SArnaud Pouliquen /**
575a2d2237SArnaud Pouliquen  * struct stm32_rproc_compat_data - rproc associated data for compatible list
585a2d2237SArnaud Pouliquen  *
595a2d2237SArnaud Pouliquen  * @rproc_id:	identifies the remote processor
60*fb2b4f6fSThomas Bourgoin  * @ns_loading: True if supports non-secure firmware loading, false otherwise
615a2d2237SArnaud Pouliquen  */
625a2d2237SArnaud Pouliquen struct stm32_rproc_compat_data {
635a2d2237SArnaud Pouliquen 	uint32_t rproc_id;
64*fb2b4f6fSThomas Bourgoin 	bool ns_loading;
655a2d2237SArnaud Pouliquen };
665a2d2237SArnaud Pouliquen 
675a2d2237SArnaud Pouliquen static SLIST_HEAD(, stm32_rproc_instance) rproc_list =
685a2d2237SArnaud Pouliquen 		SLIST_HEAD_INITIALIZER(rproc_list);
695a2d2237SArnaud Pouliquen 
stm32_rproc_get(uint32_t rproc_id)705a2d2237SArnaud Pouliquen void *stm32_rproc_get(uint32_t rproc_id)
715a2d2237SArnaud Pouliquen {
725a2d2237SArnaud Pouliquen 	struct stm32_rproc_instance *rproc = NULL;
735a2d2237SArnaud Pouliquen 
745a2d2237SArnaud Pouliquen 	SLIST_FOREACH(rproc, &rproc_list, link)
755a2d2237SArnaud Pouliquen 		if (rproc->cdata->rproc_id == rproc_id)
765a2d2237SArnaud Pouliquen 			break;
775a2d2237SArnaud Pouliquen 
785a2d2237SArnaud Pouliquen 	return rproc;
795a2d2237SArnaud Pouliquen }
805a2d2237SArnaud Pouliquen 
stm32_rproc_is_secure(uint32_t rproc_id)81a0304431SEtienne Carriere bool stm32_rproc_is_secure(uint32_t rproc_id)
82a0304431SEtienne Carriere {
83a0304431SEtienne Carriere 	struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id);
84a0304431SEtienne Carriere 
85a0304431SEtienne Carriere 	if (rproc)
86a0304431SEtienne Carriere 		return !rproc->cdata->ns_loading;
87a0304431SEtienne Carriere 
88a0304431SEtienne Carriere 	return false;
89a0304431SEtienne Carriere }
90a0304431SEtienne Carriere 
stm32_rproc_start(uint32_t rproc_id)915a2d2237SArnaud Pouliquen TEE_Result stm32_rproc_start(uint32_t rproc_id)
925a2d2237SArnaud Pouliquen {
935a2d2237SArnaud Pouliquen 	struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id);
945a2d2237SArnaud Pouliquen 	TEE_Result res = TEE_ERROR_GENERIC;
955a2d2237SArnaud Pouliquen 
965a2d2237SArnaud Pouliquen 	if (!rproc || !rproc->hold_boot)
975a2d2237SArnaud Pouliquen 		return TEE_ERROR_GENERIC;
985a2d2237SArnaud Pouliquen 
995a2d2237SArnaud Pouliquen 	/*
1005a2d2237SArnaud Pouliquen 	 * The firmware is started by de-asserting the hold boot and
1015a2d2237SArnaud Pouliquen 	 * asserting it back to avoid auto restart on a crash.
1025a2d2237SArnaud Pouliquen 	 * No need to release the MCU reset as it is automatically released by
1035a2d2237SArnaud Pouliquen 	 * the hardware.
1045a2d2237SArnaud Pouliquen 	 */
1055a2d2237SArnaud Pouliquen 	res = rstctrl_deassert_to(rproc->hold_boot, TIMEOUT_US_1MS);
1065a2d2237SArnaud Pouliquen 	if (!res)
1075a2d2237SArnaud Pouliquen 		res = rstctrl_assert_to(rproc->hold_boot, TIMEOUT_US_1MS);
1085a2d2237SArnaud Pouliquen 
1095a2d2237SArnaud Pouliquen 	return res;
1105a2d2237SArnaud Pouliquen }
1115a2d2237SArnaud Pouliquen 
rproc_stop(struct stm32_rproc_instance * rproc)1125a2d2237SArnaud Pouliquen static TEE_Result rproc_stop(struct stm32_rproc_instance *rproc)
1135a2d2237SArnaud Pouliquen {
1145a2d2237SArnaud Pouliquen 	TEE_Result res = TEE_ERROR_GENERIC;
1155a2d2237SArnaud Pouliquen 
1165a2d2237SArnaud Pouliquen 	if (!rproc->hold_boot || !rproc->mcu_rst)
1175a2d2237SArnaud Pouliquen 		return TEE_ERROR_GENERIC;
1185a2d2237SArnaud Pouliquen 
1195a2d2237SArnaud Pouliquen 	res = rstctrl_assert_to(rproc->hold_boot, TIMEOUT_US_1MS);
1205a2d2237SArnaud Pouliquen 	if (!res)
1215a2d2237SArnaud Pouliquen 		res = rstctrl_assert_to(rproc->mcu_rst, TIMEOUT_US_1MS);
1225a2d2237SArnaud Pouliquen 
1235a2d2237SArnaud Pouliquen 	return res;
1245a2d2237SArnaud Pouliquen }
1255a2d2237SArnaud Pouliquen 
stm32_rproc_stop(uint32_t rproc_id)1265a2d2237SArnaud Pouliquen TEE_Result stm32_rproc_stop(uint32_t rproc_id)
1275a2d2237SArnaud Pouliquen {
1285a2d2237SArnaud Pouliquen 	struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id);
1295a2d2237SArnaud Pouliquen 
1305a2d2237SArnaud Pouliquen 	if (!rproc)
1315a2d2237SArnaud Pouliquen 		return TEE_ERROR_BAD_PARAMETERS;
1325a2d2237SArnaud Pouliquen 
1335a2d2237SArnaud Pouliquen 	return rproc_stop(rproc);
1345a2d2237SArnaud Pouliquen }
1355a2d2237SArnaud Pouliquen 
stm32_rproc_da_to_pa(uint32_t rproc_id,paddr_t da,size_t size,paddr_t * pa)1365a2d2237SArnaud Pouliquen TEE_Result stm32_rproc_da_to_pa(uint32_t rproc_id, paddr_t da, size_t size,
1375a2d2237SArnaud Pouliquen 				paddr_t *pa)
1385a2d2237SArnaud Pouliquen {
1395a2d2237SArnaud Pouliquen 	struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id);
1405a2d2237SArnaud Pouliquen 	struct stm32_rproc_mem *mems = NULL;
1415a2d2237SArnaud Pouliquen 	unsigned int i = 0;
1425a2d2237SArnaud Pouliquen 
1435a2d2237SArnaud Pouliquen 	if (!rproc)
1445a2d2237SArnaud Pouliquen 		return TEE_ERROR_BAD_PARAMETERS;
1455a2d2237SArnaud Pouliquen 
1465a2d2237SArnaud Pouliquen 	mems = rproc->regions;
1475a2d2237SArnaud Pouliquen 
1485a2d2237SArnaud Pouliquen 	for (i = 0; i < rproc->n_regions; i++) {
1495a2d2237SArnaud Pouliquen 		if (core_is_buffer_inside(da, size, mems[i].da, mems[i].size)) {
1505a2d2237SArnaud Pouliquen 			/*
1515a2d2237SArnaud Pouliquen 			 * A match between the requested DA memory area and the
1525a2d2237SArnaud Pouliquen 			 * registered regions has been found.
1535a2d2237SArnaud Pouliquen 			 * The PA is the reserved-memory PA address plus the
1545a2d2237SArnaud Pouliquen 			 * delta between the requested DA and the
1555a2d2237SArnaud Pouliquen 			 * reserved-memory DA address.
1565a2d2237SArnaud Pouliquen 			 */
1575a2d2237SArnaud Pouliquen 			*pa = mems[i].addr + da - mems[i].da;
1585a2d2237SArnaud Pouliquen 			return TEE_SUCCESS;
1595a2d2237SArnaud Pouliquen 		}
1605a2d2237SArnaud Pouliquen 	}
1615a2d2237SArnaud Pouliquen 
1625a2d2237SArnaud Pouliquen 	return TEE_ERROR_ACCESS_DENIED;
1635a2d2237SArnaud Pouliquen }
1645a2d2237SArnaud Pouliquen 
stm32_rproc_map(uint32_t rproc_id,paddr_t pa,size_t size,void ** va)1655a2d2237SArnaud Pouliquen TEE_Result stm32_rproc_map(uint32_t rproc_id, paddr_t pa, size_t size,
1665a2d2237SArnaud Pouliquen 			   void **va)
1675a2d2237SArnaud Pouliquen {
1685a2d2237SArnaud Pouliquen 	struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id);
1695a2d2237SArnaud Pouliquen 	struct stm32_rproc_mem *mems = NULL;
1705a2d2237SArnaud Pouliquen 	unsigned int i = 0;
1715a2d2237SArnaud Pouliquen 
1725a2d2237SArnaud Pouliquen 	if (!rproc)
1735a2d2237SArnaud Pouliquen 		return TEE_ERROR_BAD_PARAMETERS;
1745a2d2237SArnaud Pouliquen 
1755a2d2237SArnaud Pouliquen 	mems = rproc->regions;
1765a2d2237SArnaud Pouliquen 
1775a2d2237SArnaud Pouliquen 	for (i = 0; i < rproc->n_regions; i++) {
1785a2d2237SArnaud Pouliquen 		if (!core_is_buffer_inside(pa, size, mems[i].addr,
1795a2d2237SArnaud Pouliquen 					   mems[i].size))
1805a2d2237SArnaud Pouliquen 			continue;
1815a2d2237SArnaud Pouliquen 		*va = core_mmu_add_mapping(MEM_AREA_RAM_NSEC, pa, size);
1825a2d2237SArnaud Pouliquen 		if (!*va) {
1835a2d2237SArnaud Pouliquen 			EMSG("Can't map region %#"PRIxPA" size %zu", pa, size);
1845a2d2237SArnaud Pouliquen 			return TEE_ERROR_GENERIC;
1855a2d2237SArnaud Pouliquen 		}
1865a2d2237SArnaud Pouliquen 
1875a2d2237SArnaud Pouliquen 		return TEE_SUCCESS;
1885a2d2237SArnaud Pouliquen 	}
1895a2d2237SArnaud Pouliquen 
1905a2d2237SArnaud Pouliquen 	return TEE_ERROR_ACCESS_DENIED;
1915a2d2237SArnaud Pouliquen }
1925a2d2237SArnaud Pouliquen 
stm32_rproc_unmap(uint32_t rproc_id,void * va,size_t size)1935a2d2237SArnaud Pouliquen TEE_Result stm32_rproc_unmap(uint32_t rproc_id, void *va, size_t size)
1945a2d2237SArnaud Pouliquen {
1955a2d2237SArnaud Pouliquen 	struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id);
1965a2d2237SArnaud Pouliquen 	struct stm32_rproc_mem *mems = NULL;
1975a2d2237SArnaud Pouliquen 	paddr_t pa = virt_to_phys(va);
1985a2d2237SArnaud Pouliquen 	unsigned int i = 0;
1995a2d2237SArnaud Pouliquen 
2005a2d2237SArnaud Pouliquen 	if (!rproc || !pa)
2015a2d2237SArnaud Pouliquen 		return TEE_ERROR_BAD_PARAMETERS;
2025a2d2237SArnaud Pouliquen 
2035a2d2237SArnaud Pouliquen 	mems = rproc->regions;
2045a2d2237SArnaud Pouliquen 
2055a2d2237SArnaud Pouliquen 	for (i = 0; i < rproc->n_regions; i++) {
2065a2d2237SArnaud Pouliquen 		if (!core_is_buffer_inside(pa, size, mems[i].addr,
2075a2d2237SArnaud Pouliquen 					   mems[i].size))
2085a2d2237SArnaud Pouliquen 			continue;
2095a2d2237SArnaud Pouliquen 
2105a2d2237SArnaud Pouliquen 		/* Flush the cache before unmapping the memory */
2115a2d2237SArnaud Pouliquen 		dcache_clean_range(va, size);
2125a2d2237SArnaud Pouliquen 
2135a2d2237SArnaud Pouliquen 		if (core_mmu_remove_mapping(MEM_AREA_RAM_NSEC, va, size)) {
2145a2d2237SArnaud Pouliquen 			EMSG("Can't unmap region %#"PRIxPA" size %zu",
2155a2d2237SArnaud Pouliquen 			     pa, size);
2165a2d2237SArnaud Pouliquen 			return TEE_ERROR_GENERIC;
2175a2d2237SArnaud Pouliquen 		}
2185a2d2237SArnaud Pouliquen 
2195a2d2237SArnaud Pouliquen 		return TEE_SUCCESS;
2205a2d2237SArnaud Pouliquen 	}
2215a2d2237SArnaud Pouliquen 
2225a2d2237SArnaud Pouliquen 	return TEE_ERROR_ACCESS_DENIED;
2235a2d2237SArnaud Pouliquen }
2245a2d2237SArnaud Pouliquen 
stm32_rproc_get_dma_range(struct stm32_rproc_mem * region,const void * fdt,int node)2255a2d2237SArnaud Pouliquen static TEE_Result stm32_rproc_get_dma_range(struct stm32_rproc_mem *region,
2265a2d2237SArnaud Pouliquen 					    const void *fdt, int node)
2275a2d2237SArnaud Pouliquen {
2285a2d2237SArnaud Pouliquen 	const fdt32_t *list = NULL;
2295a2d2237SArnaud Pouliquen 	int ahb_node = 0;
2305a2d2237SArnaud Pouliquen 	int len = 0;
2315a2d2237SArnaud Pouliquen 	int nranges = 0;
2325a2d2237SArnaud Pouliquen 	int i = 0;
2335a2d2237SArnaud Pouliquen 
2345a2d2237SArnaud Pouliquen 	/*
2355a2d2237SArnaud Pouliquen 	 * The match between local and remote processor memory mapping is
2365a2d2237SArnaud Pouliquen 	 * described in the dma-ranges defined by the bus parent node.
2375a2d2237SArnaud Pouliquen 	 */
2385a2d2237SArnaud Pouliquen 	ahb_node = fdt_parent_offset(fdt, node);
2395a2d2237SArnaud Pouliquen 
2405a2d2237SArnaud Pouliquen 	list = fdt_getprop(fdt, ahb_node, "dma-ranges", &len);
2415a2d2237SArnaud Pouliquen 	if (!list) {
2425a2d2237SArnaud Pouliquen 		if (len != -FDT_ERR_NOTFOUND)
2435a2d2237SArnaud Pouliquen 			return TEE_ERROR_GENERIC;
2445a2d2237SArnaud Pouliquen 		/* Same memory mapping */
2455a2d2237SArnaud Pouliquen 		DMSG("No dma-ranges found in DT");
2465a2d2237SArnaud Pouliquen 		region->da = region->addr;
2475a2d2237SArnaud Pouliquen 		return TEE_SUCCESS;
2485a2d2237SArnaud Pouliquen 	}
2495a2d2237SArnaud Pouliquen 
2505a2d2237SArnaud Pouliquen 	if ((len % (sizeof(uint32_t) * 3)))
2515a2d2237SArnaud Pouliquen 		return TEE_ERROR_GENERIC;
2525a2d2237SArnaud Pouliquen 
2535a2d2237SArnaud Pouliquen 	nranges = len / sizeof(uint32_t);
2545a2d2237SArnaud Pouliquen 
2555a2d2237SArnaud Pouliquen 	for (i = 0; i < nranges; i += 3) {
2565a2d2237SArnaud Pouliquen 		uint32_t da = fdt32_to_cpu(list[i]);
2575a2d2237SArnaud Pouliquen 		uint32_t pa = fdt32_to_cpu(list[i + 1]);
2585a2d2237SArnaud Pouliquen 		uint32_t size = fdt32_to_cpu(list[i + 2]);
2595a2d2237SArnaud Pouliquen 
2605a2d2237SArnaud Pouliquen 		if (core_is_buffer_inside(region->addr, region->size,
2615a2d2237SArnaud Pouliquen 					  pa, size)) {
2625a2d2237SArnaud Pouliquen 			region->da = da + (region->addr - pa);
2635a2d2237SArnaud Pouliquen 			return TEE_SUCCESS;
2645a2d2237SArnaud Pouliquen 		}
2655a2d2237SArnaud Pouliquen 	}
2665a2d2237SArnaud Pouliquen 
2675a2d2237SArnaud Pouliquen 	return TEE_ERROR_BAD_PARAMETERS;
2685a2d2237SArnaud Pouliquen }
2695a2d2237SArnaud Pouliquen 
2705a2d2237SArnaud Pouliquen /* Get device tree memory regions reserved for the Cortex-M and the IPC */
stm32_rproc_parse_mems(struct stm32_rproc_instance * rproc,const void * fdt,int node)2715a2d2237SArnaud Pouliquen static TEE_Result stm32_rproc_parse_mems(struct stm32_rproc_instance *rproc,
2725a2d2237SArnaud Pouliquen 					 const void *fdt, int node)
2735a2d2237SArnaud Pouliquen {
2745a2d2237SArnaud Pouliquen 	const fdt32_t *list = NULL;
2755a2d2237SArnaud Pouliquen 	TEE_Result res = TEE_ERROR_GENERIC;
2765a2d2237SArnaud Pouliquen 	struct stm32_rproc_mem *regions = NULL;
2775a2d2237SArnaud Pouliquen 	int len = 0;
2785a2d2237SArnaud Pouliquen 	int n_regions = 0;
2795a2d2237SArnaud Pouliquen 	int i = 0;
2805a2d2237SArnaud Pouliquen 
2815a2d2237SArnaud Pouliquen 	list = fdt_getprop(fdt, node, "memory-region", &len);
2825a2d2237SArnaud Pouliquen 	if (!list) {
2835a2d2237SArnaud Pouliquen 		EMSG("No memory regions found in DT");
2845a2d2237SArnaud Pouliquen 		return TEE_ERROR_GENERIC;
2855a2d2237SArnaud Pouliquen 	}
2865a2d2237SArnaud Pouliquen 
2875a2d2237SArnaud Pouliquen 	n_regions = len / sizeof(uint32_t);
2885a2d2237SArnaud Pouliquen 
2895a2d2237SArnaud Pouliquen 	regions = calloc(n_regions, sizeof(*regions));
2905a2d2237SArnaud Pouliquen 	if (!regions)
2915a2d2237SArnaud Pouliquen 		return TEE_ERROR_OUT_OF_MEMORY;
2925a2d2237SArnaud Pouliquen 
2935a2d2237SArnaud Pouliquen 	for (i = 0; i < n_regions; i++) {
2945a2d2237SArnaud Pouliquen 		int pnode = 0;
2955a2d2237SArnaud Pouliquen 
2965a2d2237SArnaud Pouliquen 		pnode = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(list[i]));
2975a2d2237SArnaud Pouliquen 		if (pnode < 0) {
2985a2d2237SArnaud Pouliquen 			res = TEE_ERROR_GENERIC;
2995a2d2237SArnaud Pouliquen 			goto err;
3005a2d2237SArnaud Pouliquen 		}
3015a2d2237SArnaud Pouliquen 
3026a0116edSEtienne Carriere 		if (fdt_reg_info(fdt, pnode, &regions[i].addr,
3036a0116edSEtienne Carriere 				 &regions[i].size)) {
3045a2d2237SArnaud Pouliquen 			res = TEE_ERROR_GENERIC;
3055a2d2237SArnaud Pouliquen 			goto err;
3065a2d2237SArnaud Pouliquen 		}
3075a2d2237SArnaud Pouliquen 
308beedc460SEtienne Carriere #if defined(CFG_STM32MP15)
309beedc460SEtienne Carriere 		if (stm32mp1_ram_intersect_pager_ram(regions[i].addr,
310beedc460SEtienne Carriere 						     regions[i].size)) {
311beedc460SEtienne Carriere 			EMSG("Region %#"PRIxPA"..%#"PRIxPA" intersects pager secure memory",
312beedc460SEtienne Carriere 			     regions[i].addr,
313beedc460SEtienne Carriere 			     regions[i].addr + regions[i].size);
314beedc460SEtienne Carriere 			return TEE_ERROR_GENERIC;
315beedc460SEtienne Carriere 		}
316beedc460SEtienne Carriere #endif
317beedc460SEtienne Carriere 
3185a2d2237SArnaud Pouliquen 		res = stm32_rproc_get_dma_range(&regions[i], fdt, node);
3195a2d2237SArnaud Pouliquen 		if (res)
3205a2d2237SArnaud Pouliquen 			goto err;
3215a2d2237SArnaud Pouliquen 
3225a2d2237SArnaud Pouliquen 		if (!regions[i].addr || !regions[i].size) {
3235a2d2237SArnaud Pouliquen 			res = TEE_ERROR_BAD_PARAMETERS;
3245a2d2237SArnaud Pouliquen 			goto err;
3255a2d2237SArnaud Pouliquen 		}
3265a2d2237SArnaud Pouliquen 
3275a2d2237SArnaud Pouliquen 		DMSG("register region %#"PRIxPA" size %#zx",
3285a2d2237SArnaud Pouliquen 		     regions[i].addr, regions[i].size);
3295a2d2237SArnaud Pouliquen 	}
3305a2d2237SArnaud Pouliquen 
3315a2d2237SArnaud Pouliquen 	rproc->n_regions = n_regions;
3325a2d2237SArnaud Pouliquen 	rproc->regions = regions;
3335a2d2237SArnaud Pouliquen 
3345a2d2237SArnaud Pouliquen 	return TEE_SUCCESS;
3355a2d2237SArnaud Pouliquen 
3365a2d2237SArnaud Pouliquen err:
3375a2d2237SArnaud Pouliquen 	free(regions);
3385a2d2237SArnaud Pouliquen 
3395a2d2237SArnaud Pouliquen 	return res;
3405a2d2237SArnaud Pouliquen }
3415a2d2237SArnaud Pouliquen 
stm32_rproc_clean_up_memories(uint32_t rproc_id)342b8f75963SArnaud Pouliquen TEE_Result stm32_rproc_clean_up_memories(uint32_t rproc_id)
343b8f75963SArnaud Pouliquen {
344b8f75963SArnaud Pouliquen 	struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id);
345b8f75963SArnaud Pouliquen 	struct stm32_rproc_mem *mems = NULL;
346b8f75963SArnaud Pouliquen 	TEE_Result res = TEE_ERROR_GENERIC;
347b8f75963SArnaud Pouliquen 	unsigned int i = 0;
348b8f75963SArnaud Pouliquen 	void *va = NULL;
349b8f75963SArnaud Pouliquen 	size_t size = 0;
350b8f75963SArnaud Pouliquen 	paddr_t pa = 0;
351b8f75963SArnaud Pouliquen 
352b8f75963SArnaud Pouliquen 	if (!rproc)
353b8f75963SArnaud Pouliquen 		return TEE_ERROR_BAD_PARAMETERS;
354b8f75963SArnaud Pouliquen 
355b8f75963SArnaud Pouliquen 	mems = rproc->regions;
356b8f75963SArnaud Pouliquen 	for (i = 0; i < rproc->n_regions; i++) {
357b8f75963SArnaud Pouliquen 		pa = mems[i].addr;
358b8f75963SArnaud Pouliquen 		size = mems[i].size;
359b8f75963SArnaud Pouliquen 		res = stm32_rproc_map(rproc_id, pa, size, &va);
360b8f75963SArnaud Pouliquen 		if (res)
361b8f75963SArnaud Pouliquen 			break;
362b8f75963SArnaud Pouliquen 		memset(va, 0, size);
363b8f75963SArnaud Pouliquen 		res = stm32_rproc_unmap(rproc_id, va, size);
364b8f75963SArnaud Pouliquen 		if (res)
365b8f75963SArnaud Pouliquen 			break;
366b8f75963SArnaud Pouliquen 	}
367b8f75963SArnaud Pouliquen 
368b8f75963SArnaud Pouliquen 	return res;
369b8f75963SArnaud Pouliquen }
370b8f75963SArnaud Pouliquen 
stm32_rproc_cleanup(struct stm32_rproc_instance * rproc)3715a2d2237SArnaud Pouliquen static void stm32_rproc_cleanup(struct stm32_rproc_instance *rproc)
3725a2d2237SArnaud Pouliquen {
3735a2d2237SArnaud Pouliquen 	free(rproc->regions);
3745a2d2237SArnaud Pouliquen 	free(rproc);
3755a2d2237SArnaud Pouliquen }
3765a2d2237SArnaud Pouliquen 
stm32_rproc_probe(const void * fdt,int node,const void * comp_data)3775a2d2237SArnaud Pouliquen static TEE_Result stm32_rproc_probe(const void *fdt, int node,
3785a2d2237SArnaud Pouliquen 				    const void *comp_data)
3795a2d2237SArnaud Pouliquen {
3805a2d2237SArnaud Pouliquen 	struct stm32_rproc_instance *rproc = NULL;
3815a2d2237SArnaud Pouliquen 	TEE_Result res = TEE_ERROR_GENERIC;
3825a2d2237SArnaud Pouliquen 
3835a2d2237SArnaud Pouliquen 	rproc = calloc(1, sizeof(*rproc));
3845a2d2237SArnaud Pouliquen 	if (!rproc)
3855a2d2237SArnaud Pouliquen 		return TEE_ERROR_OUT_OF_MEMORY;
3865a2d2237SArnaud Pouliquen 
3875a2d2237SArnaud Pouliquen 	rproc->cdata = comp_data;
3885a2d2237SArnaud Pouliquen 
3895a2d2237SArnaud Pouliquen 	res = stm32_rproc_parse_mems(rproc, fdt, node);
3905a2d2237SArnaud Pouliquen 	if (res)
3915a2d2237SArnaud Pouliquen 		goto err;
3925a2d2237SArnaud Pouliquen 
3935a2d2237SArnaud Pouliquen 	res = rstctrl_dt_get_by_name(fdt, node, "mcu_rst", &rproc->mcu_rst);
3945a2d2237SArnaud Pouliquen 	if (res)
3955a2d2237SArnaud Pouliquen 		goto err;
3965a2d2237SArnaud Pouliquen 
3975a2d2237SArnaud Pouliquen 	res = rstctrl_dt_get_by_name(fdt, node, "hold_boot", &rproc->hold_boot);
3985a2d2237SArnaud Pouliquen 	if (res)
3995a2d2237SArnaud Pouliquen 		goto err;
4005a2d2237SArnaud Pouliquen 
4015a2d2237SArnaud Pouliquen 	/* Ensure that the MCU is HOLD */
4025a2d2237SArnaud Pouliquen 	if (rproc->mcu_rst) {
4035a2d2237SArnaud Pouliquen 		res = rproc_stop(rproc);
4045a2d2237SArnaud Pouliquen 		if (res)
4055a2d2237SArnaud Pouliquen 			goto err;
4065a2d2237SArnaud Pouliquen 	}
4075a2d2237SArnaud Pouliquen 
4080cc468d1SEtienne Carriere 	if (!stm32_rcc_is_secure()) {
4090cc468d1SEtienne Carriere 		IMSG("WARNING: insecure rproc isolation, RCC is not secure");
4100cc468d1SEtienne Carriere 		if (!IS_ENABLED(CFG_INSECURE))
4110cc468d1SEtienne Carriere 			panic();
4120cc468d1SEtienne Carriere 	} else {
4130cc468d1SEtienne Carriere 		stm32_rcc_set_mckprot(true);
4140cc468d1SEtienne Carriere 	}
4150cc468d1SEtienne Carriere 
4165a2d2237SArnaud Pouliquen 	/*
4175a2d2237SArnaud Pouliquen 	 * The memory management should be enhance with firewall
4185a2d2237SArnaud Pouliquen 	 * mechanism to map the memory in secure area for the firmware
4195a2d2237SArnaud Pouliquen 	 * loading and then to give exclusive access right to the
4205a2d2237SArnaud Pouliquen 	 * coprocessor (except for the shared memory).
4215a2d2237SArnaud Pouliquen 	 */
4225a2d2237SArnaud Pouliquen 	IMSG("Warning: the remoteproc memories are not protected by firewall");
4235a2d2237SArnaud Pouliquen 
4245a2d2237SArnaud Pouliquen 	SLIST_INSERT_HEAD(&rproc_list, rproc, link);
4255a2d2237SArnaud Pouliquen 
4265a2d2237SArnaud Pouliquen 	return TEE_SUCCESS;
4275a2d2237SArnaud Pouliquen 
4285a2d2237SArnaud Pouliquen err:
4295a2d2237SArnaud Pouliquen 	stm32_rproc_cleanup(rproc);
4305a2d2237SArnaud Pouliquen 	return res;
4315a2d2237SArnaud Pouliquen }
4325a2d2237SArnaud Pouliquen 
4335a2d2237SArnaud Pouliquen static const struct stm32_rproc_compat_data stm32_rproc_m4_compat = {
4345a2d2237SArnaud Pouliquen 	.rproc_id = STM32_M4_RPROC_ID,
435a0304431SEtienne Carriere 	.ns_loading = false,
4365a2d2237SArnaud Pouliquen };
4375a2d2237SArnaud Pouliquen 
4385a2d2237SArnaud Pouliquen static const struct dt_device_match stm32_rproc_match_table[] = {
4395a2d2237SArnaud Pouliquen 	{
4405a2d2237SArnaud Pouliquen 		.compatible = "st,stm32mp1-m4-tee",
4415a2d2237SArnaud Pouliquen 		.compat_data = &stm32_rproc_m4_compat,
4425a2d2237SArnaud Pouliquen 	},
4435a2d2237SArnaud Pouliquen 	{ }
4445a2d2237SArnaud Pouliquen };
4455a2d2237SArnaud Pouliquen 
4465a2d2237SArnaud Pouliquen DEFINE_DT_DRIVER(stm32_rproc_dt_driver) = {
4475a2d2237SArnaud Pouliquen 	.name = "stm32-rproc",
4485a2d2237SArnaud Pouliquen 	.match_table = stm32_rproc_match_table,
4495a2d2237SArnaud Pouliquen 	.probe = &stm32_rproc_probe,
4505a2d2237SArnaud Pouliquen };
451