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