xref: /optee_os/core/arch/arm/plat-stm32mp1/main.c (revision e29eb9dd31504e836ce3d261ad58e494311a5a29)
1a30d4efbSEtienne Carriere // SPDX-License-Identifier: BSD-2-Clause
2a30d4efbSEtienne Carriere /*
3c501c3e1SLionel Debieve  * Copyright (c) 2017-2025, STMicroelectronics
4a30d4efbSEtienne Carriere  * Copyright (c) 2016-2018, Linaro Limited
5a30d4efbSEtienne Carriere  */
6a30d4efbSEtienne Carriere 
7a30d4efbSEtienne Carriere #include <boot_api.h>
8ee4d1590SEtienne Carriere #include <config.h>
9a30d4efbSEtienne Carriere #include <console.h>
10132151fbSEtienne Carriere #include <drivers/firewall_device.h>
11a30d4efbSEtienne Carriere #include <drivers/gic.h>
12*e29eb9ddSGatien Chevallier #include <drivers/rstctrl.h>
136d6aeba1SEtienne Carriere #include <drivers/pinctrl.h>
14db3e6bf9SEtienne Carriere #include <drivers/stm32_bsec.h>
152a5482f7SEtienne Carriere #include <drivers/stm32_gpio.h>
16e9f46c74SJens Wiklander #include <drivers/stm32_uart.h>
1737010ab7SGatien Chevallier #include <drivers/stm32mp_dt_bindings.h>
18db3e6bf9SEtienne Carriere #ifdef CFG_STM32MP15
19db3e6bf9SEtienne Carriere #include <drivers/stm32mp1_rcc.h>
20db3e6bf9SEtienne Carriere #endif
21986fccc8SEtienne Carriere #include <io.h>
2265401337SJens Wiklander #include <kernel/boot.h>
23651d7537SJens Wiklander #include <kernel/dt.h>
24132151fbSEtienne Carriere #include <kernel/dt_driver.h>
25a30d4efbSEtienne Carriere #include <kernel/misc.h>
26a30d4efbSEtienne Carriere #include <kernel/panic.h>
2700707cccSEtienne Carriere #include <kernel/spinlock.h>
28885b1c02SEtienne Carriere #include <kernel/tee_misc.h>
29f2e5b5e0SGatien Chevallier #include <libfdt.h>
30a30d4efbSEtienne Carriere #include <mm/core_memprot.h>
31a30d4efbSEtienne Carriere #include <platform_config.h>
32a30d4efbSEtienne Carriere #include <sm/psci.h>
33eb07694aSEtienne Carriere #include <stm32_util.h>
34986fccc8SEtienne Carriere #include <string.h>
35a78ef925SEtienne Carriere #include <trace.h>
36a30d4efbSEtienne Carriere 
37acab9a17SEtienne Carriere register_phys_mem_pgdir(MEM_AREA_IO_NSEC, APB1_BASE, APB1_SIZE);
38acab9a17SEtienne Carriere register_phys_mem_pgdir(MEM_AREA_IO_NSEC, APB2_BASE, APB2_SIZE);
39acab9a17SEtienne Carriere register_phys_mem_pgdir(MEM_AREA_IO_NSEC, APB3_BASE, APB3_SIZE);
40acab9a17SEtienne Carriere register_phys_mem_pgdir(MEM_AREA_IO_NSEC, APB4_BASE, APB4_SIZE);
41acab9a17SEtienne Carriere register_phys_mem_pgdir(MEM_AREA_IO_NSEC, APB5_BASE, APB5_SIZE);
42acab9a17SEtienne Carriere register_phys_mem_pgdir(MEM_AREA_IO_NSEC, AHB4_BASE, AHB4_SIZE);
43acab9a17SEtienne Carriere register_phys_mem_pgdir(MEM_AREA_IO_NSEC, AHB5_BASE, AHB5_SIZE);
44a30d4efbSEtienne Carriere 
45a3009556SMichael Scott register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB1_BASE, APB1_SIZE);
469650ed7cSEtienne Carriere register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB3_BASE, APB3_SIZE);
479650ed7cSEtienne Carriere register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB4_BASE, APB4_SIZE);
48acab9a17SEtienne Carriere register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB5_BASE, APB5_SIZE);
49dedaf8caSGatien Chevallier #ifdef CFG_STM32MP13
50dedaf8caSGatien Chevallier register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB6_BASE, APB6_SIZE);
51dedaf8caSGatien Chevallier #endif
52acab9a17SEtienne Carriere register_phys_mem_pgdir(MEM_AREA_IO_SEC, AHB4_BASE, AHB4_SIZE);
53acab9a17SEtienne Carriere register_phys_mem_pgdir(MEM_AREA_IO_SEC, AHB5_BASE, AHB5_SIZE);
54a5e82dc7SJerome Forissier register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_BASE, GIC_SIZE);
55a30d4efbSEtienne Carriere 
568db78a81SEtienne Carriere register_ddr(DDR_BASE, CFG_DRAM_SIZE);
572b7b5d91SEtienne Carriere 
58a78ef925SEtienne Carriere #define _ID2STR(id)		(#id)
59a78ef925SEtienne Carriere #define ID2STR(id)		_ID2STR(id)
60a78ef925SEtienne Carriere 
platform_banner(void)61a78ef925SEtienne Carriere static TEE_Result platform_banner(void)
62a78ef925SEtienne Carriere {
63a78ef925SEtienne Carriere 	IMSG("Platform stm32mp1: flavor %s - DT %s",
64a78ef925SEtienne Carriere 		ID2STR(PLATFORM_FLAVOR),
65a78ef925SEtienne Carriere 		ID2STR(CFG_EMBED_DTB_SOURCE_FILE));
66a78ef925SEtienne Carriere 
67a78ef925SEtienne Carriere 	return TEE_SUCCESS;
68a78ef925SEtienne Carriere }
69a78ef925SEtienne Carriere service_init(platform_banner);
70a78ef925SEtienne Carriere 
71ce2d526aSEtienne Carriere /*
72ce2d526aSEtienne Carriere  * Console
73ce2d526aSEtienne Carriere  *
74ce2d526aSEtienne Carriere  * CFG_STM32_EARLY_CONSOLE_UART specifies the ID of the UART used for
75ce2d526aSEtienne Carriere  * trace console. Value 0 disables the early console.
767d887fc5SEtienne Carriere  *
777d887fc5SEtienne Carriere  * We cannot use the generic serial_console support since probing
787d887fc5SEtienne Carriere  * the console requires the platform clock driver to be already
797d887fc5SEtienne Carriere  * up and ready which is done only once service_init are completed.
80ce2d526aSEtienne Carriere  */
81ce2d526aSEtienne Carriere static struct stm32_uart_pdata console_data;
82ce2d526aSEtienne Carriere 
plat_console_init(void)8355ab8f06SAlvin Chang void plat_console_init(void)
84a30d4efbSEtienne Carriere {
85ce2d526aSEtienne Carriere 	/* Early console initialization before MMU setup */
86ce2d526aSEtienne Carriere 	struct uart {
879b39d0faSEtienne Carriere 		paddr_t pa;
88ce2d526aSEtienne Carriere 	} uarts[] = {
89ce2d526aSEtienne Carriere 		[0] = { .pa = 0 },
907a1f6540SEtienne Carriere 		[1] = { .pa = USART1_BASE },
917a1f6540SEtienne Carriere 		[2] = { .pa = USART2_BASE },
927a1f6540SEtienne Carriere 		[3] = { .pa = USART3_BASE },
937a1f6540SEtienne Carriere 		[4] = { .pa = UART4_BASE },
947a1f6540SEtienne Carriere 		[5] = { .pa = UART5_BASE },
957a1f6540SEtienne Carriere 		[6] = { .pa = USART6_BASE },
967a1f6540SEtienne Carriere 		[7] = { .pa = UART7_BASE },
977a1f6540SEtienne Carriere 		[8] = { .pa = UART8_BASE },
98ce2d526aSEtienne Carriere 	};
99ce2d526aSEtienne Carriere 
100ce2d526aSEtienne Carriere 	COMPILE_TIME_ASSERT(ARRAY_SIZE(uarts) > CFG_STM32_EARLY_CONSOLE_UART);
101ce2d526aSEtienne Carriere 
102ce2d526aSEtienne Carriere 	if (!uarts[CFG_STM32_EARLY_CONSOLE_UART].pa)
103ce2d526aSEtienne Carriere 		return;
104ce2d526aSEtienne Carriere 
1057d887fc5SEtienne Carriere 	/* No clock yet bound to the UART console */
1065e369f14SEtienne Carriere 	console_data.clock = NULL;
1077d887fc5SEtienne Carriere 
108ce2d526aSEtienne Carriere 	stm32_uart_init(&console_data, uarts[CFG_STM32_EARLY_CONSOLE_UART].pa);
109ce2d526aSEtienne Carriere 
110a30d4efbSEtienne Carriere 	register_serial_console(&console_data.chip);
111ce2d526aSEtienne Carriere 
112ce2d526aSEtienne Carriere 	IMSG("Early console on UART#%u", CFG_STM32_EARLY_CONSOLE_UART);
113a30d4efbSEtienne Carriere }
114a30d4efbSEtienne Carriere 
init_console_from_dt(void)1157d887fc5SEtienne Carriere static TEE_Result init_console_from_dt(void)
1167d887fc5SEtienne Carriere {
11710e1dc35SEtienne Carriere 	struct stm32_uart_pdata *pd = NULL;
11810e1dc35SEtienne Carriere 	void *fdt = NULL;
11910e1dc35SEtienne Carriere 	int node = 0;
120286c31d4SEtienne Carriere 	TEE_Result res = TEE_ERROR_GENERIC;
1217d887fc5SEtienne Carriere 
122286c31d4SEtienne Carriere 	fdt = get_embedded_dt();
123286c31d4SEtienne Carriere 	res = get_console_node_from_dt(fdt, &node, NULL, NULL);
124286c31d4SEtienne Carriere 	if (res == TEE_ERROR_ITEM_NOT_FOUND) {
125286c31d4SEtienne Carriere 		fdt = get_external_dt();
126286c31d4SEtienne Carriere 		res = get_console_node_from_dt(fdt, &node, NULL, NULL);
127286c31d4SEtienne Carriere 		if (res == TEE_ERROR_ITEM_NOT_FOUND)
1287d887fc5SEtienne Carriere 			return TEE_SUCCESS;
129286c31d4SEtienne Carriere 		if (res != TEE_SUCCESS)
130286c31d4SEtienne Carriere 			return res;
131286c31d4SEtienne Carriere 	}
1327d887fc5SEtienne Carriere 
1337d887fc5SEtienne Carriere 	pd = stm32_uart_init_from_dt_node(fdt, node);
1347d887fc5SEtienne Carriere 	if (!pd) {
1357d887fc5SEtienne Carriere 		IMSG("DTB disables console");
1367d887fc5SEtienne Carriere 		register_serial_console(NULL);
1377d887fc5SEtienne Carriere 		return TEE_SUCCESS;
1387d887fc5SEtienne Carriere 	}
1397d887fc5SEtienne Carriere 
1407d887fc5SEtienne Carriere 	/* Replace early console with the new one */
1417d887fc5SEtienne Carriere 	console_flush();
1427d887fc5SEtienne Carriere 	console_data = *pd;
1437d887fc5SEtienne Carriere 	register_serial_console(&console_data.chip);
1447a1f6540SEtienne Carriere 	IMSG("DTB enables console");
145a54b2f16SJose Quaresma 	free(pd);
1467d887fc5SEtienne Carriere 
1477d887fc5SEtienne Carriere 	return TEE_SUCCESS;
1487d887fc5SEtienne Carriere }
1497d887fc5SEtienne Carriere 
1507d887fc5SEtienne Carriere /* Probe console from DT once clock inits (service init level) are completed */
1517d887fc5SEtienne Carriere service_init_late(init_console_from_dt);
1527d887fc5SEtienne Carriere 
stm32_dbgmcu_base(void)153d8aa45ccSPascal Paillet static uintptr_t stm32_dbgmcu_base(void)
154d8aa45ccSPascal Paillet {
155d8aa45ccSPascal Paillet 	static void *va;
156d8aa45ccSPascal Paillet 
157d8aa45ccSPascal Paillet 	if (!cpu_mmu_enabled())
158d8aa45ccSPascal Paillet 		return DBGMCU_BASE;
159d8aa45ccSPascal Paillet 
160d8aa45ccSPascal Paillet 	if (!va)
161d8aa45ccSPascal Paillet 		va = phys_to_virt(DBGMCU_BASE, MEM_AREA_IO_SEC, 1);
162d8aa45ccSPascal Paillet 
163d8aa45ccSPascal Paillet 	return (uintptr_t)va;
164d8aa45ccSPascal Paillet }
165d8aa45ccSPascal Paillet 
166d8aa45ccSPascal Paillet /* SoC device ID util, returns default ID if can't access DBGMCU */
stm32mp1_dbgmcu_get_chip_dev_id(uint32_t * chip_dev_id)167d8aa45ccSPascal Paillet TEE_Result stm32mp1_dbgmcu_get_chip_dev_id(uint32_t *chip_dev_id)
168d8aa45ccSPascal Paillet {
169d8aa45ccSPascal Paillet 	uint32_t id = STM32MP1_CHIP_ID;
170d8aa45ccSPascal Paillet 
171d8aa45ccSPascal Paillet 	assert(chip_dev_id);
172d8aa45ccSPascal Paillet 
173d8aa45ccSPascal Paillet 	if (stm32_bsec_read_debug_conf() & BSEC_DBGSWGEN)
174d8aa45ccSPascal Paillet 		id = io_read32(stm32_dbgmcu_base() + DBGMCU_IDC) &
175d8aa45ccSPascal Paillet 		     DBGMCU_IDC_DEV_ID_MASK;
176d8aa45ccSPascal Paillet 
177d8aa45ccSPascal Paillet 	*chip_dev_id = id;
178d8aa45ccSPascal Paillet 
179d8aa45ccSPascal Paillet 	return TEE_SUCCESS;
180d8aa45ccSPascal Paillet }
181d8aa45ccSPascal Paillet 
182eb07694aSEtienne Carriere /*
183eb07694aSEtienne Carriere  * GIC init, used also for primary/secondary boot core wake completion
184eb07694aSEtienne Carriere  */
boot_primary_init_intc(void)185df913c6dSAlvin Chang void boot_primary_init_intc(void)
186a30d4efbSEtienne Carriere {
18767e55c51SEtienne Carriere 	gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET);
18800707cccSEtienne Carriere 
18900707cccSEtienne Carriere 	stm32mp_register_online_cpu();
190a30d4efbSEtienne Carriere }
191a30d4efbSEtienne Carriere 
boot_secondary_init_intc(void)1928aae4669SAlvin Chang void boot_secondary_init_intc(void)
193a30d4efbSEtienne Carriere {
194f388e2b7SJens Wiklander 	gic_init_per_cpu();
19500707cccSEtienne Carriere 
19600707cccSEtienne Carriere 	stm32mp_register_online_cpu();
197a30d4efbSEtienne Carriere }
198eb07694aSEtienne Carriere 
199885b1c02SEtienne Carriere #ifdef CFG_STM32MP15
200885b1c02SEtienne Carriere /*
201885b1c02SEtienne Carriere  * This concerns OP-TEE pager for STM32MP1 to use secure internal
202885b1c02SEtienne Carriere  * RAMs to execute. TZSRAM refers the TZSRAM_BASE/TZSRAM_SIZE
203885b1c02SEtienne Carriere  * used in boot.c to locate secure unpaged memory.
204885b1c02SEtienne Carriere  *
205885b1c02SEtienne Carriere  * STM32MP15 variants embed 640kB of contiguous securable SRAMs
206885b1c02SEtienne Carriere  *
207885b1c02SEtienne Carriere  *  +--------------+ <-- SYSRAM_BASE
208885b1c02SEtienne Carriere  *  |              |     lower part can be assigned to secure world
209885b1c02SEtienne Carriere  *  | SYSRAM 256kB |     4kB granule boundary
210885b1c02SEtienne Carriere  *  |              |     upper part can be assigned to secure world
211885b1c02SEtienne Carriere  *  +--------------+ <-- SRAM1_BASE (= SYSRAM_BASE + SYSRAM_SIZE)
212885b1c02SEtienne Carriere     |              |     full range assigned to non-secure world or
213885b1c02SEtienne Carriere  *  | SRAM1  128kB |     to secure world, or to- Cortex-M4 exclusive access
214885b1c02SEtienne Carriere  *  +--------------+ <-- SRAM2_BASE (= SRAM1_BASE + SRAM1_SIZE)
215885b1c02SEtienne Carriere     |              |     full range assigned to non-secure world or
216885b1c02SEtienne Carriere  *  | SRAM2  128kB |     to secure world, or to- Cortex-M4 exclusive access
217885b1c02SEtienne Carriere  *  +--------------+ <-- SRAM3_BASE (= SRAM2_BASE + SRAM2_SIZE)
218885b1c02SEtienne Carriere     |              |     full range assigned to non-secure world or
219885b1c02SEtienne Carriere  *  | SRAM3   64kB |     to secure world, or to- Cortex-M4 exclusive access
220885b1c02SEtienne Carriere  *  +--------------+ <-- SRAM4_BASE (= SRAM3_BASE + SRAM3_SIZE)
221885b1c02SEtienne Carriere     |              |     full range assigned to non-secure world or
222885b1c02SEtienne Carriere  *  | SRAM4   64kB |     to secure world, or to- Cortex-M4 exclusive access
223885b1c02SEtienne Carriere  *  +--------------+ <-- SRAM4_BASE + SRAM4_SIZE
224885b1c02SEtienne Carriere  *
225885b1c02SEtienne Carriere  * If SRAMx memories are not used for the companion Cortex-M4
226885b1c02SEtienne Carriere  * processor, OP-TEE can use this memory.
227885b1c02SEtienne Carriere  *
228885b1c02SEtienne Carriere  * SYSRAM configuration for secure/non-secure boundaries requires the
229885b1c02SEtienne Carriere  * secure SYSRAM memory to start at the SYSRAM physical base address and grow
230885b1c02SEtienne Carriere  * from there while the non-secure SYSRAM range lies at SYSRAM end addresses
231885b1c02SEtienne Carriere  * with a 4KB page granule.
232885b1c02SEtienne Carriere  *
233885b1c02SEtienne Carriere  * SRAM1, SRAM2, SRAM3 and SRAM4 are independently assigned to secure world,
234885b1c02SEtienne Carriere  * to non-secure world or possibly to Cortex-M4 exclusive access. Each
235885b1c02SEtienne Carriere  * assignment covers the full related SRAMx memory range.
236885b1c02SEtienne Carriere  *
237885b1c02SEtienne Carriere  * Using non-secure SYSRAM or one of the SRAMx for SCMI message communication
238885b1c02SEtienne Carriere  * can be done using CFG_STM32MP1_SCMI_SHM_BASE/CFG_STM32MP1_SCMI_SHM_SIZE.
239885b1c02SEtienne Carriere  * This imposes related memory area is assigned to non-secure world.
240885b1c02SEtienne Carriere 
241885b1c02SEtienne Carriere  * Using secure internal memories (SYSRAM and/or some SRAMx) with STM32MP15
242885b1c02SEtienne Carriere  * shall meet this constraints known the TZSRAM physical memory range shall
243885b1c02SEtienne Carriere  * be contiguous.
244885b1c02SEtienne Carriere  */
245885b1c02SEtienne Carriere 
246885b1c02SEtienne Carriere #define SYSRAM_END			(SYSRAM_BASE + SYSRAM_SIZE)
247885b1c02SEtienne Carriere #define SYSRAM_SEC_END			(SYSRAM_BASE + SYSRAM_SEC_SIZE)
248885b1c02SEtienne Carriere #define SRAMS_END			(SRAM4_BASE + SRAM4_SIZE)
249885b1c02SEtienne Carriere #define SRAMS_START			SRAM1_BASE
250885b1c02SEtienne Carriere #define TZSRAM_END			(CFG_TZSRAM_START + CFG_TZSRAM_SIZE)
251885b1c02SEtienne Carriere 
252885b1c02SEtienne Carriere #define TZSRAM_FITS_IN_SYSRAM_SEC	((CFG_TZSRAM_START >= SYSRAM_BASE) && \
253885b1c02SEtienne Carriere 					 (TZSRAM_END <= SYSRAM_SEC_END))
254885b1c02SEtienne Carriere 
255885b1c02SEtienne Carriere #define TZSRAM_FITS_IN_SYSRAM_AND_SRAMS	((CFG_TZSRAM_START >= SYSRAM_BASE) && \
256885b1c02SEtienne Carriere 					 (CFG_TZSRAM_START < SYSRAM_END) && \
257885b1c02SEtienne Carriere 					 (TZSRAM_END > SYSRAM_END) && \
258885b1c02SEtienne Carriere 					 (TZSRAM_END <= SRAMS_END) && \
259885b1c02SEtienne Carriere 					 (SYSRAM_SIZE == SYSRAM_SEC_SIZE))
260885b1c02SEtienne Carriere 
261885b1c02SEtienne Carriere #define TZSRAM_FITS_IN_SRAMS	((CFG_TZSRAM_START >= SRAMS_START) && \
262885b1c02SEtienne Carriere 				 (CFG_TZSRAM_START < SRAMS_END) && \
263885b1c02SEtienne Carriere 				 (TZSRAM_END <= SRAMS_END))
264885b1c02SEtienne Carriere 
265885b1c02SEtienne Carriere #define TZSRAM_IS_IN_DRAM	(CFG_TZSRAM_START >= CFG_DRAM_BASE)
266885b1c02SEtienne Carriere 
267885b1c02SEtienne Carriere #ifdef CFG_WITH_PAGER
268885b1c02SEtienne Carriere /*
269885b1c02SEtienne Carriere  * At build time, we enforce that, when pager is used,
270885b1c02SEtienne Carriere  * either TZSRAM fully fits inside SYSRAM secure address range,
271885b1c02SEtienne Carriere  * or TZSRAM fully fits inside the full SYSRAM and spread inside SRAMx orderly,
272885b1c02SEtienne Carriere  * or TZSRAM fully fits some inside SRAMs address range,
273885b1c02SEtienne Carriere  * or TZSRAM is in DDR for debug and test purpose.
274885b1c02SEtienne Carriere  */
275885b1c02SEtienne Carriere static_assert(TZSRAM_FITS_IN_SYSRAM_SEC || TZSRAM_FITS_IN_SYSRAM_AND_SRAMS ||
276885b1c02SEtienne Carriere 	      TZSRAM_FITS_IN_SRAMS || TZSRAM_IS_IN_DRAM);
277132151fbSEtienne Carriere #endif /* CFG_WITH_PAGER */
278132151fbSEtienne Carriere #endif /* CFG_STM32MP15 */
279132151fbSEtienne Carriere 
secure_pager_ram(struct dt_driver_provider * fw_provider,unsigned int decprot_id,paddr_t base,size_t secure_size)280132151fbSEtienne Carriere static TEE_Result secure_pager_ram(struct dt_driver_provider *fw_provider,
281132151fbSEtienne Carriere 				   unsigned int decprot_id,
282132151fbSEtienne Carriere 				   paddr_t base, size_t secure_size)
283132151fbSEtienne Carriere {
284132151fbSEtienne Carriere 	/* Lock firewall configuration for secure internal RAMs used by pager */
285132151fbSEtienne Carriere 	uint32_t query_arg = DECPROT(decprot_id, DECPROT_S_RW, DECPROT_LOCK);
286132151fbSEtienne Carriere 	struct firewall_query fw_query = {
287132151fbSEtienne Carriere 		.ctrl = dt_driver_provider_priv_data(fw_provider),
288132151fbSEtienne Carriere 		.args = &query_arg,
289132151fbSEtienne Carriere 		.arg_count = 1,
290132151fbSEtienne Carriere 	};
291132151fbSEtienne Carriere 	TEE_Result res = TEE_ERROR_GENERIC;
292132151fbSEtienne Carriere 	bool is_pager_ram = false;
293132151fbSEtienne Carriere 
294132151fbSEtienne Carriere #if defined(CFG_WITH_PAGER)
295132151fbSEtienne Carriere 	is_pager_ram = core_is_buffer_intersect(CFG_TZSRAM_START,
296132151fbSEtienne Carriere 						CFG_TZSRAM_SIZE,
297132151fbSEtienne Carriere 						base, secure_size);
298885b1c02SEtienne Carriere #endif
299132151fbSEtienne Carriere 	if (!is_pager_ram)
300885b1c02SEtienne Carriere 		return TEE_SUCCESS;
301132151fbSEtienne Carriere 
302132151fbSEtienne Carriere 	res = firewall_set_memory_configuration(&fw_query, base, secure_size);
303132151fbSEtienne Carriere 	if (res)
304132151fbSEtienne Carriere 		EMSG("Failed to configure secure SRAM %#"PRIxPA"..%#"PRIxPA,
305132151fbSEtienne Carriere 		     base, base + secure_size);
306132151fbSEtienne Carriere 
307132151fbSEtienne Carriere 	return res;
308885b1c02SEtienne Carriere }
309885b1c02SEtienne Carriere 
non_secure_scmi_ram(struct dt_driver_provider * fw_provider,unsigned int decprot_id,paddr_t base,size_t size)310132151fbSEtienne Carriere static TEE_Result non_secure_scmi_ram(struct dt_driver_provider *fw_provider,
311132151fbSEtienne Carriere 				      unsigned int decprot_id,
312132151fbSEtienne Carriere 				      paddr_t base, size_t size)
3131095cc2eSEtienne Carriere {
314132151fbSEtienne Carriere 	/* Do not lock firewall configuration for non-secure internal RAMs */
315132151fbSEtienne Carriere 	uint32_t query_arg = DECPROT(decprot_id, DECPROT_NS_RW, DECPROT_UNLOCK);
316132151fbSEtienne Carriere 	struct firewall_query fw_query = {
317132151fbSEtienne Carriere 		.ctrl = dt_driver_provider_priv_data(fw_provider),
318132151fbSEtienne Carriere 		.args = &query_arg,
319132151fbSEtienne Carriere 		.arg_count = 1,
320132151fbSEtienne Carriere 	};
321132151fbSEtienne Carriere 	TEE_Result res = TEE_ERROR_GENERIC;
322132151fbSEtienne Carriere 
323132151fbSEtienne Carriere 	if (!core_is_buffer_intersect(CFG_STM32MP1_SCMI_SHM_BASE,
324132151fbSEtienne Carriere 				      CFG_STM32MP1_SCMI_SHM_SIZE,
325132151fbSEtienne Carriere 				      base, size))
326132151fbSEtienne Carriere 		return TEE_SUCCESS;
327132151fbSEtienne Carriere 
328132151fbSEtienne Carriere 	res = firewall_set_memory_configuration(&fw_query, base, size);
329132151fbSEtienne Carriere 	if (res)
330132151fbSEtienne Carriere 		EMSG("Failed to configure non-secure SRAM %#"PRIxPA"..%#"PRIxPA,
331132151fbSEtienne Carriere 		     base, base + size);
332132151fbSEtienne Carriere 
333132151fbSEtienne Carriere 	return res;
334132151fbSEtienne Carriere }
335132151fbSEtienne Carriere 
336132151fbSEtienne Carriere /* At run time we enforce that SRAM1 to SRAM4 are properly assigned if used */
configure_srams(struct dt_driver_provider * fw_provider)337132151fbSEtienne Carriere static void configure_srams(struct dt_driver_provider *fw_provider)
338132151fbSEtienne Carriere {
339132151fbSEtienne Carriere 	bool error = false;
340132151fbSEtienne Carriere 
341132151fbSEtienne Carriere 	if (IS_ENABLED(CFG_WITH_PAGER)) {
342132151fbSEtienne Carriere 		if (secure_pager_ram(fw_provider, STM32MP1_ETZPC_SRAM1_ID,
343132151fbSEtienne Carriere 				     SRAM1_BASE, SRAM1_SIZE))
344132151fbSEtienne Carriere 			error = true;
345132151fbSEtienne Carriere 
346132151fbSEtienne Carriere 		if (secure_pager_ram(fw_provider, STM32MP1_ETZPC_SRAM2_ID,
347132151fbSEtienne Carriere 				     SRAM2_BASE, SRAM2_SIZE))
348132151fbSEtienne Carriere 			error = true;
349132151fbSEtienne Carriere 
350132151fbSEtienne Carriere 		if (secure_pager_ram(fw_provider, STM32MP1_ETZPC_SRAM3_ID,
351132151fbSEtienne Carriere 				     SRAM3_BASE, SRAM3_SIZE))
352132151fbSEtienne Carriere 			error = true;
353132151fbSEtienne Carriere 
354132151fbSEtienne Carriere #if defined(CFG_STM32MP15)
355132151fbSEtienne Carriere 		if (secure_pager_ram(fw_provider, STM32MP1_ETZPC_SRAM4_ID,
356132151fbSEtienne Carriere 				     SRAM4_BASE, SRAM4_SIZE))
357132151fbSEtienne Carriere 			error = true;
358132151fbSEtienne Carriere #endif
359132151fbSEtienne Carriere 	}
360132151fbSEtienne Carriere 	if (CFG_STM32MP1_SCMI_SHM_BASE) {
361132151fbSEtienne Carriere 		if (non_secure_scmi_ram(fw_provider, STM32MP1_ETZPC_SRAM1_ID,
362132151fbSEtienne Carriere 					SRAM1_BASE, SRAM1_SIZE))
363132151fbSEtienne Carriere 			error = true;
364132151fbSEtienne Carriere 
365132151fbSEtienne Carriere 		if (non_secure_scmi_ram(fw_provider, STM32MP1_ETZPC_SRAM2_ID,
366132151fbSEtienne Carriere 					SRAM2_BASE, SRAM2_SIZE))
367132151fbSEtienne Carriere 			error = true;
368132151fbSEtienne Carriere 
369132151fbSEtienne Carriere 		if (non_secure_scmi_ram(fw_provider, STM32MP1_ETZPC_SRAM3_ID,
370132151fbSEtienne Carriere 					SRAM3_BASE, SRAM3_SIZE))
371132151fbSEtienne Carriere 			error = true;
372132151fbSEtienne Carriere 
373132151fbSEtienne Carriere #if defined(CFG_STM32MP15)
374132151fbSEtienne Carriere 		if (non_secure_scmi_ram(fw_provider, STM32MP1_ETZPC_SRAM4_ID,
375132151fbSEtienne Carriere 					SRAM4_BASE, SRAM4_SIZE))
376132151fbSEtienne Carriere 			error = true;
377132151fbSEtienne Carriere #endif
378132151fbSEtienne Carriere 	}
379132151fbSEtienne Carriere 
380132151fbSEtienne Carriere 	if (error)
381132151fbSEtienne Carriere 		panic();
382132151fbSEtienne Carriere }
383132151fbSEtienne Carriere 
configure_sysram(struct dt_driver_provider * fw_provider)384132151fbSEtienne Carriere static void configure_sysram(struct dt_driver_provider *fw_provider)
385132151fbSEtienne Carriere {
386132151fbSEtienne Carriere 	uint32_t query_arg = DECPROT(ETZPC_TZMA1_ID, DECPROT_S_RW,
387132151fbSEtienne Carriere 				     DECPROT_UNLOCK);
388132151fbSEtienne Carriere 	struct firewall_query firewall = {
389132151fbSEtienne Carriere 		.ctrl = dt_driver_provider_priv_data(fw_provider),
390132151fbSEtienne Carriere 		.args = &query_arg,
391132151fbSEtienne Carriere 		.arg_count = 1,
392132151fbSEtienne Carriere 	};
393132151fbSEtienne Carriere 	TEE_Result res = TEE_ERROR_GENERIC;
394132151fbSEtienne Carriere 
395132151fbSEtienne Carriere 	res = firewall_set_memory_configuration(&firewall, SYSRAM_BASE,
396132151fbSEtienne Carriere 						SYSRAM_SEC_SIZE);
397132151fbSEtienne Carriere 	if (res)
398132151fbSEtienne Carriere 		panic("Unable to secure SYSRAM");
3991095cc2eSEtienne Carriere 
400986fccc8SEtienne Carriere 	if (SYSRAM_SIZE > SYSRAM_SEC_SIZE) {
401986fccc8SEtienne Carriere 		size_t nsec_size = SYSRAM_SIZE - SYSRAM_SEC_SIZE;
402986fccc8SEtienne Carriere 		paddr_t nsec_start = SYSRAM_BASE + SYSRAM_SEC_SIZE;
403986fccc8SEtienne Carriere 		uint8_t *va = phys_to_virt(nsec_start, MEM_AREA_IO_NSEC,
404986fccc8SEtienne Carriere 					   nsec_size);
405986fccc8SEtienne Carriere 
406986fccc8SEtienne Carriere 		IMSG("Non-secure SYSRAM [%p %p]", va, va + nsec_size - 1);
407986fccc8SEtienne Carriere 
408986fccc8SEtienne Carriere 		/* Clear content from the non-secure part */
409986fccc8SEtienne Carriere 		memset(va, 0, nsec_size);
410986fccc8SEtienne Carriere 	}
4111095cc2eSEtienne Carriere }
4126b054087SEtienne Carriere 
init_late_stm32mp1_drivers(void)4136b054087SEtienne Carriere static TEE_Result init_late_stm32mp1_drivers(void)
4146b054087SEtienne Carriere {
415db3e6bf9SEtienne Carriere 	uint32_t __maybe_unused state = 0;
4166b054087SEtienne Carriere 
417132151fbSEtienne Carriere 	/* Configure SYSRAM and SRAMx secure hardening */
418132151fbSEtienne Carriere 	if (IS_ENABLED(CFG_STM32_ETZPC)) {
419132151fbSEtienne Carriere 		struct dt_driver_provider *prov = NULL;
420132151fbSEtienne Carriere 		int node = 0;
421132151fbSEtienne Carriere 
422132151fbSEtienne Carriere 		node = fdt_node_offset_by_compatible(get_embedded_dt(), -1,
423132151fbSEtienne Carriere 						     "st,stm32-etzpc");
424132151fbSEtienne Carriere 		if (node < 0)
425132151fbSEtienne Carriere 			panic("Could not get ETZPC node");
426132151fbSEtienne Carriere 
427132151fbSEtienne Carriere 		prov = dt_driver_get_provider_by_node(node, DT_DRIVER_FIREWALL);
428132151fbSEtienne Carriere 		assert(prov);
429132151fbSEtienne Carriere 
430132151fbSEtienne Carriere 		configure_sysram(prov);
431132151fbSEtienne Carriere 		configure_srams(prov);
432132151fbSEtienne Carriere 	}
433132151fbSEtienne Carriere 
434db3e6bf9SEtienne Carriere #ifdef CFG_STM32MP15
435db3e6bf9SEtienne Carriere 	/* Device in Secure Closed state require RCC secure hardening */
436db3e6bf9SEtienne Carriere 	if (stm32_bsec_get_state(&state))
437db3e6bf9SEtienne Carriere 		panic();
438db3e6bf9SEtienne Carriere 	if (state == BSEC_STATE_SEC_CLOSED && !stm32_rcc_is_secure())
439db3e6bf9SEtienne Carriere 		panic("Closed device mandates secure RCC");
440db3e6bf9SEtienne Carriere #endif
441db3e6bf9SEtienne Carriere 
4426b054087SEtienne Carriere 	return TEE_SUCCESS;
4436b054087SEtienne Carriere }
4446b054087SEtienne Carriere 
4456b054087SEtienne Carriere driver_init_late(init_late_stm32mp1_drivers);
4466b054087SEtienne Carriere 
stm32_rcc_base(void)447569d17b0SEtienne Carriere vaddr_t stm32_rcc_base(void)
448569d17b0SEtienne Carriere {
449569d17b0SEtienne Carriere 	static struct io_pa_va base = { .pa = RCC_BASE };
450569d17b0SEtienne Carriere 
451569d17b0SEtienne Carriere 	return io_pa_or_va_secure(&base, 1);
452569d17b0SEtienne Carriere }
453569d17b0SEtienne Carriere 
get_gicd_base(void)4549b39d0faSEtienne Carriere vaddr_t get_gicd_base(void)
455eb07694aSEtienne Carriere {
4569b39d0faSEtienne Carriere 	struct io_pa_va base = { .pa = GIC_BASE + GICD_OFFSET };
457eb07694aSEtienne Carriere 
458c2e4eb43SAnton Rybakov 	return io_pa_or_va_secure(&base, 1);
459eb07694aSEtienne Carriere }
46000707cccSEtienne Carriere 
stm32mp_get_bsec_static_cfg(struct stm32_bsec_static_cfg * cfg)461e043ba4bSEtienne Carriere void stm32mp_get_bsec_static_cfg(struct stm32_bsec_static_cfg *cfg)
462e043ba4bSEtienne Carriere {
463e043ba4bSEtienne Carriere 	cfg->base = BSEC_BASE;
464e043ba4bSEtienne Carriere 	cfg->upper_start = STM32MP1_UPPER_OTP_START;
465e043ba4bSEtienne Carriere 	cfg->max_id = STM32MP1_OTP_MAX_ID;
466e043ba4bSEtienne Carriere }
467e043ba4bSEtienne Carriere 
stm32mp_with_pmic(void)468944c2c63SEtienne Carriere bool __weak stm32mp_with_pmic(void)
469944c2c63SEtienne Carriere {
470944c2c63SEtienne Carriere 	return false;
471944c2c63SEtienne Carriere }
472944c2c63SEtienne Carriere 
may_spin_lock(unsigned int * lock)47300707cccSEtienne Carriere uint32_t may_spin_lock(unsigned int *lock)
47400707cccSEtienne Carriere {
47500707cccSEtienne Carriere 	if (!lock || !cpu_mmu_enabled())
47600707cccSEtienne Carriere 		return 0;
47700707cccSEtienne Carriere 
47800707cccSEtienne Carriere 	return cpu_spin_lock_xsave(lock);
47900707cccSEtienne Carriere }
48000707cccSEtienne Carriere 
may_spin_unlock(unsigned int * lock,uint32_t exceptions)48100707cccSEtienne Carriere void may_spin_unlock(unsigned int *lock, uint32_t exceptions)
48200707cccSEtienne Carriere {
48300707cccSEtienne Carriere 	if (!lock || !cpu_mmu_enabled())
48400707cccSEtienne Carriere 		return;
48500707cccSEtienne Carriere 
48600707cccSEtienne Carriere 	cpu_spin_unlock_xrestore(lock, exceptions);
48700707cccSEtienne Carriere }
488b9c19263SEtienne Carriere 
stm32_tamp_base(void)4899b39d0faSEtienne Carriere static vaddr_t stm32_tamp_base(void)
490b9c19263SEtienne Carriere {
491b9c19263SEtienne Carriere 	static struct io_pa_va base = { .pa = TAMP_BASE };
492b9c19263SEtienne Carriere 
493c2e4eb43SAnton Rybakov 	return io_pa_or_va_secure(&base, 1);
494b9c19263SEtienne Carriere }
495b9c19263SEtienne Carriere 
bkpreg_base(void)4969b39d0faSEtienne Carriere static vaddr_t bkpreg_base(void)
497b9c19263SEtienne Carriere {
498b9c19263SEtienne Carriere 	return stm32_tamp_base() + TAMP_BKP_REGISTER_OFF;
499b9c19263SEtienne Carriere }
500b9c19263SEtienne Carriere 
stm32mp_bkpreg(unsigned int idx)5019b39d0faSEtienne Carriere vaddr_t stm32mp_bkpreg(unsigned int idx)
502b9c19263SEtienne Carriere {
503b9c19263SEtienne Carriere 	return bkpreg_base() + (idx * sizeof(uint32_t));
504b9c19263SEtienne Carriere }
505fff9beb4SEtienne Carriere 
bank_is_valid(unsigned int bank)506a9f86b17SGatien Chevallier static bool __maybe_unused bank_is_valid(unsigned int bank)
507a9f86b17SGatien Chevallier {
508a9f86b17SGatien Chevallier 	if (IS_ENABLED(CFG_STM32MP15))
509a9f86b17SGatien Chevallier 		return bank == GPIO_BANK_Z || bank <= GPIO_BANK_K;
510a9f86b17SGatien Chevallier 
511a9f86b17SGatien Chevallier 	if (IS_ENABLED(CFG_STM32MP13))
512a9f86b17SGatien Chevallier 		return bank <= GPIO_BANK_I;
513a9f86b17SGatien Chevallier 
514a9f86b17SGatien Chevallier 	panic();
515a9f86b17SGatien Chevallier }
516a9f86b17SGatien Chevallier 
5178f29a74fSGatien Chevallier #ifdef CFG_STM32_DEBUG_ACCESS
init_debug(void)5188f29a74fSGatien Chevallier static TEE_Result init_debug(void)
5198f29a74fSGatien Chevallier {
5208f29a74fSGatien Chevallier 	TEE_Result res = TEE_SUCCESS;
5218f29a74fSGatien Chevallier 	uint32_t conf = stm32_bsec_read_debug_conf();
5228f29a74fSGatien Chevallier 	struct clk *dbg_clk = stm32mp_rcc_clock_id_to_clk(CK_DBG);
5238f29a74fSGatien Chevallier 	uint32_t state = 0;
5248f29a74fSGatien Chevallier 
5258f29a74fSGatien Chevallier 	res = stm32_bsec_get_state(&state);
5268f29a74fSGatien Chevallier 	if (res)
5278f29a74fSGatien Chevallier 		return res;
5288f29a74fSGatien Chevallier 
5298f29a74fSGatien Chevallier 	if (state != BSEC_STATE_SEC_CLOSED && conf) {
5309ea709a7SEtienne Carriere 		if (IS_ENABLED(CFG_INSECURE))
5318f29a74fSGatien Chevallier 			IMSG("WARNING: All debug accesses are allowed");
5328f29a74fSGatien Chevallier 
5338f29a74fSGatien Chevallier 		res = stm32_bsec_write_debug_conf(conf | BSEC_DEBUG_ALL);
5348f29a74fSGatien Chevallier 		if (res)
5358f29a74fSGatien Chevallier 			return res;
5368f29a74fSGatien Chevallier 
5378f29a74fSGatien Chevallier 		/*
5388f29a74fSGatien Chevallier 		 * Enable DBG clock as used to access coprocessor
5398f29a74fSGatien Chevallier 		 * debug registers
5408f29a74fSGatien Chevallier 		 */
5418f29a74fSGatien Chevallier 		clk_enable(dbg_clk);
5428f29a74fSGatien Chevallier 	}
5438f29a74fSGatien Chevallier 
5448f29a74fSGatien Chevallier 	return TEE_SUCCESS;
5458f29a74fSGatien Chevallier }
5468f29a74fSGatien Chevallier early_init_late(init_debug);
5478f29a74fSGatien Chevallier #endif /* CFG_STM32_DEBUG_ACCESS */
5486d6aeba1SEtienne Carriere 
5496d6aeba1SEtienne Carriere /* Some generic resources need to be unpaged */
5506d6aeba1SEtienne Carriere DECLARE_KEEP_PAGER(pinctrl_apply_state);
551f2e5b5e0SGatien Chevallier 
stm32mp_allow_probe_shared_device(const void * fdt,int node)552f2e5b5e0SGatien Chevallier bool stm32mp_allow_probe_shared_device(const void *fdt, int node)
553f2e5b5e0SGatien Chevallier {
554f2e5b5e0SGatien Chevallier 	static int uart_console_node = -1;
555f2e5b5e0SGatien Chevallier 	const char *compat = NULL;
556f2e5b5e0SGatien Chevallier 	static bool once;
557f2e5b5e0SGatien Chevallier 
558f2e5b5e0SGatien Chevallier 	if (IS_ENABLED(CFG_STM32_ALLOW_UNSAFE_PROBE))
559f2e5b5e0SGatien Chevallier 		return true;
560f2e5b5e0SGatien Chevallier 
561f2e5b5e0SGatien Chevallier 	if (!once) {
562f2e5b5e0SGatien Chevallier 		get_console_node_from_dt((void *)fdt, &uart_console_node,
563f2e5b5e0SGatien Chevallier 					 NULL, NULL);
564f2e5b5e0SGatien Chevallier 		once = true;
565f2e5b5e0SGatien Chevallier 	}
566f2e5b5e0SGatien Chevallier 
567f2e5b5e0SGatien Chevallier 	compat = fdt_stringlist_get(fdt, node, "compatible", 0, NULL);
568f2e5b5e0SGatien Chevallier 
569f2e5b5e0SGatien Chevallier 	/*
570f2e5b5e0SGatien Chevallier 	 * Allow OP-TEE console and MP15 I2C and RNG to be shared
571f2e5b5e0SGatien Chevallier 	 * with non-secure world.
572f2e5b5e0SGatien Chevallier 	 */
573f2e5b5e0SGatien Chevallier 	if (node == uart_console_node ||
574f2e5b5e0SGatien Chevallier 	    !strcmp(compat, "st,stm32mp15-i2c-non-secure") ||
575f2e5b5e0SGatien Chevallier 	    (!strcmp(compat, "st,stm32-rng") &&
576f2e5b5e0SGatien Chevallier 	     IS_ENABLED(CFG_WITH_SOFTWARE_PRNG)))
577f2e5b5e0SGatien Chevallier 		return true;
578f2e5b5e0SGatien Chevallier 
579f2e5b5e0SGatien Chevallier 	return false;
580f2e5b5e0SGatien Chevallier }
5812714147bSEtienne Carriere 
5822714147bSEtienne Carriere #if defined(CFG_STM32MP15) && defined(CFG_WITH_PAGER)
stm32mp1_pa_or_sram_alias_pa(paddr_t pa)5832714147bSEtienne Carriere paddr_t stm32mp1_pa_or_sram_alias_pa(paddr_t pa)
5842714147bSEtienne Carriere {
5852714147bSEtienne Carriere 	/*
5862714147bSEtienne Carriere 	 * OP-TEE uses the alias physical addresses of SRAM1/2/3/4,
5872714147bSEtienne Carriere 	 * not the standard physical addresses. This choice was initially
5882714147bSEtienne Carriere 	 * driven by pager that needs physically contiguous memories
5892714147bSEtienne Carriere 	 * for internal secure memories.
5902714147bSEtienne Carriere 	 */
5912714147bSEtienne Carriere 	if (core_is_buffer_inside(pa, 1, SRAM1_ALT_BASE, SRAM1_SIZE))
5922714147bSEtienne Carriere 		pa += SRAM1_BASE - SRAM1_ALT_BASE;
5932714147bSEtienne Carriere 	else if (core_is_buffer_inside(pa, 1, SRAM2_ALT_BASE, SRAM2_SIZE))
5942714147bSEtienne Carriere 		pa += SRAM2_BASE - SRAM2_ALT_BASE;
5952714147bSEtienne Carriere 	else if (core_is_buffer_inside(pa, 1, SRAM3_ALT_BASE, SRAM3_SIZE))
5962714147bSEtienne Carriere 		pa += SRAM3_BASE - SRAM3_ALT_BASE;
5972714147bSEtienne Carriere 	else if (core_is_buffer_inside(pa, 1, SRAM4_ALT_BASE, SRAM4_SIZE))
5982714147bSEtienne Carriere 		pa += SRAM4_BASE - SRAM4_ALT_BASE;
5992714147bSEtienne Carriere 
6002714147bSEtienne Carriere 	return pa;
6012714147bSEtienne Carriere }
602a0cac862SEtienne Carriere 
stm32mp1_ram_intersect_pager_ram(paddr_t base,size_t size)603a0cac862SEtienne Carriere bool stm32mp1_ram_intersect_pager_ram(paddr_t base, size_t size)
604a0cac862SEtienne Carriere {
605a0cac862SEtienne Carriere 	base = stm32mp1_pa_or_sram_alias_pa(base);
606a0cac862SEtienne Carriere 
607a0cac862SEtienne Carriere 	return core_is_buffer_intersect(base, size, CFG_TZSRAM_START,
608a0cac862SEtienne Carriere 					CFG_TZSRAM_SIZE);
609a0cac862SEtienne Carriere }
6102714147bSEtienne Carriere #endif
61161491a0cSPascal Paillet 
get_chip_dev_id(uint32_t * dev_id)61261491a0cSPascal Paillet static TEE_Result get_chip_dev_id(uint32_t *dev_id)
61361491a0cSPascal Paillet {
614d8aa45ccSPascal Paillet #ifdef CFG_STM32MP13
61561491a0cSPascal Paillet 	*dev_id = stm32mp_syscfg_get_chip_dev_id();
61661491a0cSPascal Paillet 	return TEE_SUCCESS;
617d8aa45ccSPascal Paillet #else /* assume CFG_STM32MP15 */
618d8aa45ccSPascal Paillet 	return stm32mp1_dbgmcu_get_chip_dev_id(dev_id);
619d8aa45ccSPascal Paillet #endif
62061491a0cSPascal Paillet }
62161491a0cSPascal Paillet 
get_part_number(uint32_t * part_nb)62261491a0cSPascal Paillet static TEE_Result get_part_number(uint32_t *part_nb)
62361491a0cSPascal Paillet {
62461491a0cSPascal Paillet 	static uint32_t part_number;
62561491a0cSPascal Paillet 	uint32_t dev_id = 0;
62661491a0cSPascal Paillet 	uint32_t otp = 0;
62761491a0cSPascal Paillet 	size_t bit_len = 0;
62861491a0cSPascal Paillet 	TEE_Result res = TEE_ERROR_GENERIC;
62961491a0cSPascal Paillet 
63061491a0cSPascal Paillet 	assert(part_nb);
63161491a0cSPascal Paillet 
63261491a0cSPascal Paillet 	if (part_number) {
63361491a0cSPascal Paillet 		*part_nb = part_number;
63461491a0cSPascal Paillet 		return TEE_SUCCESS;
63561491a0cSPascal Paillet 	}
63661491a0cSPascal Paillet 
63761491a0cSPascal Paillet 	res = get_chip_dev_id(&dev_id);
63861491a0cSPascal Paillet 	if (res)
63961491a0cSPascal Paillet 		return res;
64061491a0cSPascal Paillet 
64161491a0cSPascal Paillet 	res = stm32_bsec_find_otp_in_nvmem_layout("part_number_otp",
64261491a0cSPascal Paillet 						  &otp, NULL, &bit_len);
64361491a0cSPascal Paillet 	if (res)
64461491a0cSPascal Paillet 		return res;
64561491a0cSPascal Paillet 
64661491a0cSPascal Paillet 	res = stm32_bsec_read_otp(&part_number, otp);
64761491a0cSPascal Paillet 	if (res)
64861491a0cSPascal Paillet 		return res;
64961491a0cSPascal Paillet 
65061491a0cSPascal Paillet 	assert(bit_len < 16);
65161491a0cSPascal Paillet 	part_number = (part_number & GENMASK_32(bit_len, 0)) |
65261491a0cSPascal Paillet 		      SHIFT_U32(dev_id, 16);
65361491a0cSPascal Paillet 
65461491a0cSPascal Paillet 	*part_nb = part_number;
65561491a0cSPascal Paillet 
65661491a0cSPascal Paillet 	return TEE_SUCCESS;
65761491a0cSPascal Paillet }
65861491a0cSPascal Paillet 
stm32mp_supports_cpu_opp(uint32_t opp_id)65961491a0cSPascal Paillet bool stm32mp_supports_cpu_opp(uint32_t opp_id)
66061491a0cSPascal Paillet {
66161491a0cSPascal Paillet 	uint32_t part_number = 0;
66261491a0cSPascal Paillet 	uint32_t id = 0;
66361491a0cSPascal Paillet 
66461491a0cSPascal Paillet 	if (get_part_number(&part_number)) {
66561491a0cSPascal Paillet 		DMSG("Cannot get part number");
66661491a0cSPascal Paillet 		panic();
66761491a0cSPascal Paillet 	}
66861491a0cSPascal Paillet 
66961491a0cSPascal Paillet 	switch (part_number) {
67061491a0cSPascal Paillet 	case STM32MP135F_PART_NB:
67161491a0cSPascal Paillet 	case STM32MP135D_PART_NB:
67261491a0cSPascal Paillet 	case STM32MP133F_PART_NB:
67361491a0cSPascal Paillet 	case STM32MP133D_PART_NB:
67461491a0cSPascal Paillet 	case STM32MP131F_PART_NB:
67561491a0cSPascal Paillet 	case STM32MP131D_PART_NB:
67661491a0cSPascal Paillet 	case STM32MP157F_PART_NB:
67761491a0cSPascal Paillet 	case STM32MP157D_PART_NB:
67861491a0cSPascal Paillet 	case STM32MP153F_PART_NB:
67961491a0cSPascal Paillet 	case STM32MP153D_PART_NB:
68061491a0cSPascal Paillet 	case STM32MP151F_PART_NB:
68161491a0cSPascal Paillet 	case STM32MP151D_PART_NB:
68261491a0cSPascal Paillet 		id = BIT(1);
68361491a0cSPascal Paillet 		break;
68461491a0cSPascal Paillet 	default:
68561491a0cSPascal Paillet 		id = BIT(0);
68661491a0cSPascal Paillet 		break;
68761491a0cSPascal Paillet 	}
68861491a0cSPascal Paillet 
68961491a0cSPascal Paillet 	return opp_id & id;
69061491a0cSPascal Paillet }
69161491a0cSPascal Paillet 
stm32mp_supports_hw_cryp(void)69261491a0cSPascal Paillet bool stm32mp_supports_hw_cryp(void)
69361491a0cSPascal Paillet {
69461491a0cSPascal Paillet 	uint32_t part_number = 0;
69561491a0cSPascal Paillet 
69661491a0cSPascal Paillet 	if (!IS_ENABLED(CFG_STM32_CRYP))
69761491a0cSPascal Paillet 		return false;
69861491a0cSPascal Paillet 
69961491a0cSPascal Paillet 	if (get_part_number(&part_number)) {
70061491a0cSPascal Paillet 		DMSG("Cannot get part number");
70161491a0cSPascal Paillet 		panic();
70261491a0cSPascal Paillet 	}
70361491a0cSPascal Paillet 
70461491a0cSPascal Paillet 	switch (part_number) {
70561491a0cSPascal Paillet 	case STM32MP135F_PART_NB:
70661491a0cSPascal Paillet 	case STM32MP135C_PART_NB:
70761491a0cSPascal Paillet 	case STM32MP133F_PART_NB:
70861491a0cSPascal Paillet 	case STM32MP133C_PART_NB:
70961491a0cSPascal Paillet 	case STM32MP131F_PART_NB:
71061491a0cSPascal Paillet 	case STM32MP131C_PART_NB:
71161491a0cSPascal Paillet 		return true;
71261491a0cSPascal Paillet 	case STM32MP157F_PART_NB:
71361491a0cSPascal Paillet 	case STM32MP157C_PART_NB:
71461491a0cSPascal Paillet 	case STM32MP153F_PART_NB:
71561491a0cSPascal Paillet 	case STM32MP153C_PART_NB:
71661491a0cSPascal Paillet 	case STM32MP151F_PART_NB:
71761491a0cSPascal Paillet 	case STM32MP151C_PART_NB:
71861491a0cSPascal Paillet 		return true;
71961491a0cSPascal Paillet 	default:
72061491a0cSPascal Paillet 		return false;
72161491a0cSPascal Paillet 	}
72261491a0cSPascal Paillet }
72361491a0cSPascal Paillet 
stm32mp_supports_second_core(void)72461491a0cSPascal Paillet bool stm32mp_supports_second_core(void)
72561491a0cSPascal Paillet {
72661491a0cSPascal Paillet 	uint32_t part_number = 0;
72761491a0cSPascal Paillet 
72861491a0cSPascal Paillet 	if (CFG_TEE_CORE_NB_CORE == 1)
72961491a0cSPascal Paillet 		return false;
73061491a0cSPascal Paillet 
73161491a0cSPascal Paillet 	if (get_part_number(&part_number)) {
73261491a0cSPascal Paillet 		DMSG("Cannot get part number");
73361491a0cSPascal Paillet 		panic();
73461491a0cSPascal Paillet 	}
73561491a0cSPascal Paillet 
73661491a0cSPascal Paillet 	switch (part_number) {
73761491a0cSPascal Paillet 	case STM32MP151F_PART_NB:
73861491a0cSPascal Paillet 	case STM32MP151D_PART_NB:
73961491a0cSPascal Paillet 	case STM32MP151C_PART_NB:
74061491a0cSPascal Paillet 	case STM32MP151A_PART_NB:
74161491a0cSPascal Paillet 		return false;
74261491a0cSPascal Paillet 	default:
74361491a0cSPascal Paillet 		return true;
74461491a0cSPascal Paillet 	}
74561491a0cSPascal Paillet }
746*e29eb9ddSGatien Chevallier 
do_reset(const char * str __maybe_unused)747*e29eb9ddSGatien Chevallier void __noreturn do_reset(const char *str __maybe_unused)
748*e29eb9ddSGatien Chevallier {
749*e29eb9ddSGatien Chevallier 	struct rstctrl *rstctrl = NULL;
750*e29eb9ddSGatien Chevallier 
751*e29eb9ddSGatien Chevallier 	if (CFG_TEE_CORE_NB_CORE > 1) {
752*e29eb9ddSGatien Chevallier 		/* Halt execution of other CPUs */
753*e29eb9ddSGatien Chevallier 		interrupt_raise_sgi(interrupt_get_main_chip(),
754*e29eb9ddSGatien Chevallier 				    CFG_HALT_CORES_SGI,
755*e29eb9ddSGatien Chevallier 				    ITR_CPU_MASK_TO_OTHER_CPUS);
756*e29eb9ddSGatien Chevallier 		mdelay(1);
757*e29eb9ddSGatien Chevallier 	}
758*e29eb9ddSGatien Chevallier 
759*e29eb9ddSGatien Chevallier 	IMSG("Forced system reset %s", str);
760*e29eb9ddSGatien Chevallier 	console_flush();
761*e29eb9ddSGatien Chevallier 
762*e29eb9ddSGatien Chevallier 	/* Request system reset to RCC driver */
763*e29eb9ddSGatien Chevallier 	rstctrl = stm32mp_rcc_reset_id_to_rstctrl(MPSYST_R);
764*e29eb9ddSGatien Chevallier 	rstctrl_assert(rstctrl);
765*e29eb9ddSGatien Chevallier 	udelay(100);
766*e29eb9ddSGatien Chevallier 
767*e29eb9ddSGatien Chevallier 	/* Cannot occur */
768*e29eb9ddSGatien Chevallier 	panic();
769*e29eb9ddSGatien Chevallier }
770