xref: /optee_os/core/arch/arm/plat-stm32mp2/main.c (revision 072babca3f30f0e79f70ba77f7cb3581f58cc502)
1bd1fffe5SGatien Chevallier // SPDX-License-Identifier: BSD-2-Clause
2bd1fffe5SGatien Chevallier /*
3bd1fffe5SGatien Chevallier  * Copyright (c) 2023, STMicroelectronics
4bd1fffe5SGatien Chevallier  */
5bd1fffe5SGatien Chevallier 
6bd1fffe5SGatien Chevallier #include <config.h>
7bd1fffe5SGatien Chevallier #include <console.h>
8bd1fffe5SGatien Chevallier #include <drivers/gic.h>
9*072babcaSGatien Chevallier #include <drivers/rstctrl.h>
101c32a0eaSGatien Chevallier #include <drivers/stm32_rif.h>
11321b5b24SGatien Chevallier #include <drivers/stm32_serc.h>
12bd1fffe5SGatien Chevallier #include <drivers/stm32_uart.h>
13*072babcaSGatien Chevallier #include <drivers/stm32mp_dt_bindings.h>
14bd1fffe5SGatien Chevallier #include <initcall.h>
15321b5b24SGatien Chevallier #include <kernel/abort.h>
16bd1fffe5SGatien Chevallier #include <kernel/boot.h>
17bd1fffe5SGatien Chevallier #include <kernel/dt.h>
18bd1fffe5SGatien Chevallier #include <kernel/interrupt.h>
19bd1fffe5SGatien Chevallier #include <kernel/misc.h>
20bd1fffe5SGatien Chevallier #include <kernel/spinlock.h>
21bd1fffe5SGatien Chevallier #include <mm/core_memprot.h>
22bd1fffe5SGatien Chevallier #include <platform_config.h>
23bd1fffe5SGatien Chevallier #include <stm32_util.h>
24bd1fffe5SGatien Chevallier #include <trace.h>
25bd1fffe5SGatien Chevallier 
26bd1fffe5SGatien Chevallier register_phys_mem_pgdir(MEM_AREA_IO_NSEC, APB1_BASE, APB1_SIZE);
27bd1fffe5SGatien Chevallier 
28bd1fffe5SGatien Chevallier register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB1_BASE, APB1_SIZE);
29bd1fffe5SGatien Chevallier register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB2_BASE, APB2_SIZE);
30bd1fffe5SGatien Chevallier register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB3_BASE, APB3_SIZE);
31bd1fffe5SGatien Chevallier register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB4_BASE, APB4_SIZE);
32bd1fffe5SGatien Chevallier register_phys_mem_pgdir(MEM_AREA_IO_SEC, AHB2_BASE, AHB2_SIZE);
33bd1fffe5SGatien Chevallier register_phys_mem_pgdir(MEM_AREA_IO_SEC, AHB3_BASE, AHB3_SIZE);
34bd1fffe5SGatien Chevallier register_phys_mem_pgdir(MEM_AREA_IO_SEC, AHB4_BASE, AHB4_SIZE);
35bd1fffe5SGatien Chevallier register_phys_mem_pgdir(MEM_AREA_IO_SEC, AHB5_BASE, AHB5_SIZE);
36bd1fffe5SGatien Chevallier register_phys_mem_pgdir(MEM_AREA_IO_SEC, SAPB_BASE, SAPB_SIZE);
37bd1fffe5SGatien Chevallier register_phys_mem_pgdir(MEM_AREA_IO_SEC, SAHB_BASE, SAHB_SIZE);
38bd1fffe5SGatien Chevallier 
39bd1fffe5SGatien Chevallier register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_BASE, GIC_SIZE);
40bd1fffe5SGatien Chevallier 
41bd1fffe5SGatien Chevallier #define _ID2STR(id)		(#id)
42bd1fffe5SGatien Chevallier #define ID2STR(id)		_ID2STR(id)
43bd1fffe5SGatien Chevallier 
platform_banner(void)44bd1fffe5SGatien Chevallier static TEE_Result platform_banner(void)
45bd1fffe5SGatien Chevallier {
46bd1fffe5SGatien Chevallier 	IMSG("Platform stm32mp2: flavor %s - DT %s", ID2STR(PLATFORM_FLAVOR),
47bd1fffe5SGatien Chevallier 	     ID2STR(CFG_EMBED_DTB_SOURCE_FILE));
48bd1fffe5SGatien Chevallier 
49bd1fffe5SGatien Chevallier 	return TEE_SUCCESS;
50bd1fffe5SGatien Chevallier }
51bd1fffe5SGatien Chevallier 
52bd1fffe5SGatien Chevallier service_init(platform_banner);
53bd1fffe5SGatien Chevallier 
54bd1fffe5SGatien Chevallier /*
55bd1fffe5SGatien Chevallier  * Console
56bd1fffe5SGatien Chevallier  *
57bd1fffe5SGatien Chevallier  * CFG_STM32_EARLY_CONSOLE_UART specifies the ID of the UART used for
58bd1fffe5SGatien Chevallier  * trace console. Value 0 disables the early console.
59bd1fffe5SGatien Chevallier  *
60bd1fffe5SGatien Chevallier  * We cannot use the generic serial_console support since probing
61bd1fffe5SGatien Chevallier  * the console requires the platform clock driver to be already
62bd1fffe5SGatien Chevallier  * up and ready which is done only once service_init are completed.
63bd1fffe5SGatien Chevallier  */
64bd1fffe5SGatien Chevallier static struct stm32_uart_pdata console_data;
65bd1fffe5SGatien Chevallier 
plat_console_init(void)6655ab8f06SAlvin Chang void plat_console_init(void)
67bd1fffe5SGatien Chevallier {
68e7f93998SEtienne Carriere #ifdef CFG_STM32_UART
69bd1fffe5SGatien Chevallier 	/* Early console initialization before MMU setup */
70bd1fffe5SGatien Chevallier 	struct uart {
71bd1fffe5SGatien Chevallier 		paddr_t pa;
72bd1fffe5SGatien Chevallier 	} uarts[] = {
73bd1fffe5SGatien Chevallier 		[0] = { .pa = 0 },
747a1f6540SEtienne Carriere 		[1] = { .pa = USART1_BASE },
757a1f6540SEtienne Carriere 		[2] = { .pa = USART2_BASE },
767a1f6540SEtienne Carriere 		[3] = { .pa = USART3_BASE },
777a1f6540SEtienne Carriere 		[4] = { .pa = UART4_BASE },
787a1f6540SEtienne Carriere 		[5] = { .pa = UART5_BASE },
797a1f6540SEtienne Carriere 		[6] = { .pa = USART6_BASE },
807a1f6540SEtienne Carriere 		[7] = { .pa = UART7_BASE },
817a1f6540SEtienne Carriere 		[8] = { .pa = UART8_BASE },
827a1f6540SEtienne Carriere 		[9] = { .pa = UART9_BASE },
83bd1fffe5SGatien Chevallier 	};
84bd1fffe5SGatien Chevallier 
85bd1fffe5SGatien Chevallier 	static_assert(ARRAY_SIZE(uarts) > CFG_STM32_EARLY_CONSOLE_UART);
86bd1fffe5SGatien Chevallier 
87bd1fffe5SGatien Chevallier 	if (!uarts[CFG_STM32_EARLY_CONSOLE_UART].pa)
88bd1fffe5SGatien Chevallier 		return;
89bd1fffe5SGatien Chevallier 
90bd1fffe5SGatien Chevallier 	/* No clock yet bound to the UART console */
91bd1fffe5SGatien Chevallier 	console_data.clock = NULL;
92bd1fffe5SGatien Chevallier 	stm32_uart_init(&console_data, uarts[CFG_STM32_EARLY_CONSOLE_UART].pa);
93bd1fffe5SGatien Chevallier 	register_serial_console(&console_data.chip);
94bd1fffe5SGatien Chevallier 
95bd1fffe5SGatien Chevallier 	IMSG("Early console on UART#%u", CFG_STM32_EARLY_CONSOLE_UART);
96bd1fffe5SGatien Chevallier #endif
97bd1fffe5SGatien Chevallier }
98bd1fffe5SGatien Chevallier 
99bd1fffe5SGatien Chevallier #ifdef CFG_STM32_UART
init_console_from_dt(void)100bd1fffe5SGatien Chevallier static TEE_Result init_console_from_dt(void)
101bd1fffe5SGatien Chevallier {
102bd1fffe5SGatien Chevallier 	struct stm32_uart_pdata *pd = NULL;
103bd1fffe5SGatien Chevallier 	void *fdt = NULL;
104bd1fffe5SGatien Chevallier 	int node = 0;
105bd1fffe5SGatien Chevallier 	TEE_Result res = TEE_ERROR_GENERIC;
106bd1fffe5SGatien Chevallier 
107bd1fffe5SGatien Chevallier 	fdt = get_embedded_dt();
108bd1fffe5SGatien Chevallier 	res = get_console_node_from_dt(fdt, &node, NULL, NULL);
109bd1fffe5SGatien Chevallier 	if (res == TEE_ERROR_ITEM_NOT_FOUND) {
110bd1fffe5SGatien Chevallier 		fdt = get_external_dt();
111bd1fffe5SGatien Chevallier 		res = get_console_node_from_dt(fdt, &node, NULL, NULL);
112bd1fffe5SGatien Chevallier 		if (res == TEE_ERROR_ITEM_NOT_FOUND)
113bd1fffe5SGatien Chevallier 			return TEE_SUCCESS;
114bd1fffe5SGatien Chevallier 		if (res != TEE_SUCCESS)
115bd1fffe5SGatien Chevallier 			return res;
116bd1fffe5SGatien Chevallier 	}
117bd1fffe5SGatien Chevallier 
118bd1fffe5SGatien Chevallier 	pd = stm32_uart_init_from_dt_node(fdt, node);
119bd1fffe5SGatien Chevallier 	if (!pd) {
120bd1fffe5SGatien Chevallier 		IMSG("DTB disables console");
121bd1fffe5SGatien Chevallier 		register_serial_console(NULL);
122bd1fffe5SGatien Chevallier 		return TEE_SUCCESS;
123bd1fffe5SGatien Chevallier 	}
124bd1fffe5SGatien Chevallier 
125bd1fffe5SGatien Chevallier 	/* Replace early console with the new one */
126bd1fffe5SGatien Chevallier 	console_flush();
127bd1fffe5SGatien Chevallier 	console_data = *pd;
128bd1fffe5SGatien Chevallier 	register_serial_console(&console_data.chip);
1297a1f6540SEtienne Carriere 	IMSG("DTB enables console");
130bd1fffe5SGatien Chevallier 	free(pd);
131bd1fffe5SGatien Chevallier 
132bd1fffe5SGatien Chevallier 	return TEE_SUCCESS;
133bd1fffe5SGatien Chevallier }
134bd1fffe5SGatien Chevallier 
135bd1fffe5SGatien Chevallier /* Probe console from DT once clock inits (service init level) are completed */
136bd1fffe5SGatien Chevallier service_init_late(init_console_from_dt);
137bd1fffe5SGatien Chevallier #endif /*STM32_UART*/
138bd1fffe5SGatien Chevallier 
stm32_rcc_base(void)13911ece294SGabriel Fernandez vaddr_t stm32_rcc_base(void)
14011ece294SGabriel Fernandez {
14111ece294SGabriel Fernandez 	static struct io_pa_va base = { .pa = RCC_BASE };
14211ece294SGabriel Fernandez 
14311ece294SGabriel Fernandez 	return io_pa_or_va_secure(&base, 1);
14411ece294SGabriel Fernandez }
14511ece294SGabriel Fernandez 
boot_primary_init_intc(void)146bd1fffe5SGatien Chevallier void boot_primary_init_intc(void)
147bd1fffe5SGatien Chevallier {
148bd1fffe5SGatien Chevallier 	gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET);
149bd1fffe5SGatien Chevallier }
150bd1fffe5SGatien Chevallier 
boot_secondary_init_intc(void)151bd1fffe5SGatien Chevallier void boot_secondary_init_intc(void)
152bd1fffe5SGatien Chevallier {
1537c173858SJens Wiklander 	gic_init_per_cpu();
154bd1fffe5SGatien Chevallier }
1551c32a0eaSGatien Chevallier 
1561c32a0eaSGatien Chevallier #ifdef CFG_STM32_RIF
stm32_rif_access_violation_action(void)1571c32a0eaSGatien Chevallier void stm32_rif_access_violation_action(void)
1581c32a0eaSGatien Chevallier {
1591c32a0eaSGatien Chevallier }
1601c32a0eaSGatien Chevallier #endif /* CFG_STM32_RIF */
161a6a331e5SGatien Chevallier 
stm32mp_allow_probe_shared_device(const void * fdt,int node)162a6a331e5SGatien Chevallier bool stm32mp_allow_probe_shared_device(const void *fdt, int node)
163a6a331e5SGatien Chevallier {
164a6a331e5SGatien Chevallier 	static int uart_console_node = -1;
165a6a331e5SGatien Chevallier 	static bool once;
166a6a331e5SGatien Chevallier 
167a6a331e5SGatien Chevallier 	if (!once) {
168a6a331e5SGatien Chevallier 		get_console_node_from_dt((void *)fdt, &uart_console_node,
169a6a331e5SGatien Chevallier 					 NULL, NULL);
170a6a331e5SGatien Chevallier 		once = true;
171a6a331e5SGatien Chevallier 	}
172a6a331e5SGatien Chevallier 
173a6a331e5SGatien Chevallier 	/* Allow OP-TEE console to be shared with non-secure world */
174a6a331e5SGatien Chevallier 	if (node == uart_console_node)
175a6a331e5SGatien Chevallier 		return true;
176a6a331e5SGatien Chevallier 
177a6a331e5SGatien Chevallier 	return false;
178a6a331e5SGatien Chevallier }
179321b5b24SGatien Chevallier 
plat_external_abort_handler(struct abort_info * ai __unused)180321b5b24SGatien Chevallier void plat_external_abort_handler(struct abort_info *ai __unused)
181321b5b24SGatien Chevallier {
182321b5b24SGatien Chevallier 	/* External abort may be due to SERC events */
183321b5b24SGatien Chevallier 	stm32_serc_handle_ilac();
184321b5b24SGatien Chevallier }
185*072babcaSGatien Chevallier 
do_reset(const char * str __maybe_unused)186*072babcaSGatien Chevallier void __noreturn do_reset(const char *str __maybe_unused)
187*072babcaSGatien Chevallier {
188*072babcaSGatien Chevallier 	struct rstctrl *rstctrl = NULL;
189*072babcaSGatien Chevallier 
190*072babcaSGatien Chevallier 	if (CFG_TEE_CORE_NB_CORE > 1) {
191*072babcaSGatien Chevallier 		/* Halt execution of other CPUs */
192*072babcaSGatien Chevallier 		interrupt_raise_sgi(interrupt_get_main_chip(),
193*072babcaSGatien Chevallier 				    CFG_HALT_CORES_SGI,
194*072babcaSGatien Chevallier 				    ITR_CPU_MASK_TO_OTHER_CPUS);
195*072babcaSGatien Chevallier 		mdelay(1);
196*072babcaSGatien Chevallier 	}
197*072babcaSGatien Chevallier 
198*072babcaSGatien Chevallier 	IMSG("Forced system reset: %s", str);
199*072babcaSGatien Chevallier 	console_flush();
200*072babcaSGatien Chevallier 
201*072babcaSGatien Chevallier 	/* Request system reset to RCC driver */
202*072babcaSGatien Chevallier 	rstctrl = stm32mp_rcc_reset_id_to_rstctrl(SYS_R);
203*072babcaSGatien Chevallier 	rstctrl_assert(rstctrl);
204*072babcaSGatien Chevallier 	udelay(100);
205*072babcaSGatien Chevallier 
206*072babcaSGatien Chevallier 	/* Cannot occur */
207*072babcaSGatien Chevallier 	panic();
208*072babcaSGatien Chevallier }
209