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