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