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, ®ions[i].addr,
3036a0116edSEtienne Carriere ®ions[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(®ions[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