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
platform_banner(void)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
plat_console_init(void)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
init_console_from_dt(void)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
stm32_rcc_base(void)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
boot_primary_init_intc(void)146 void boot_primary_init_intc(void)
147 {
148 gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET);
149 }
150
boot_secondary_init_intc(void)151 void boot_secondary_init_intc(void)
152 {
153 gic_init_per_cpu();
154 }
155
156 #ifdef CFG_STM32_RIF
stm32_rif_access_violation_action(void)157 void stm32_rif_access_violation_action(void)
158 {
159 }
160 #endif /* CFG_STM32_RIF */
161
stm32mp_allow_probe_shared_device(const void * fdt,int node)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
plat_external_abort_handler(struct abort_info * ai __unused)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
do_reset(const char * str __maybe_unused)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