feat(stm32mp2): add console configuration

Use UART driver and fill helpers for crash console.
Add early console setup in bl2_el3_early_platform_setup().

Signed-off-by: Yann Gautier <yann.gautier@st.com>
Change-Id: Ifb39554214dec05dafe4e306f8754e1454cdab61
diff --git a/plat/st/stm32mp2/aarch64/stm32mp2_helper.S b/plat/st/stm32mp2/aarch64/stm32mp2_helper.S
index 4848275..66333ad 100644
--- a/plat/st/stm32mp2/aarch64/stm32mp2_helper.S
+++ b/plat/st/stm32mp2/aarch64/stm32mp2_helper.S
@@ -5,15 +5,19 @@
  */
 
 #include <asm_macros.S>
+#include <drivers/st/stm32_gpio.h>
 
 #include <platform_def.h>
 
+#define GPIO_TX_SHIFT		(DEBUG_UART_TX_GPIO_PORT << 1)
+
 	.globl	platform_mem_init
 	.globl	plat_secondary_cold_boot_setup
 	.globl	plat_is_my_cpu_primary
 	.globl	plat_crash_console_init
 	.globl	plat_crash_console_flush
 	.globl	plat_crash_console_putc
+	.globl	plat_report_exception
 
 func platform_mem_init
 	/* Nothing to do, don't need to init SYSRAM */
@@ -53,11 +57,138 @@
 	 * ---------------------------------------------
 	 */
 func plat_crash_console_init
+	/* Reset UART peripheral */
+	mov_imm	x1, (RCC_BASE + DEBUG_UART_RST_REG)
+	ldr	x2, =DEBUG_UART_RST_BIT
+	ldr	x0, [x1]
+	orr	x0, x0, x2
+	str	x0, [x1]
+1:
+	ldr	x0, [x1]
+	ands	x2, x0, x2
+	beq	1b
+	bic	x2, x2, #DEBUG_UART_RST_BIT
+	str	x2, [x1]
+2:
+	ldr	x0, [x1]
+	ands	x2, x0, x2
+	bne	2b
+	/* Enable GPIOs for UART TX */
+	mov_imm	x1, (RCC_BASE + DEBUG_UART_TX_GPIO_BANK_CLK_REG)
+	ldr	w2, [x1]
+	/* Configure GPIO */
+	orr	w2, w2, #DEBUG_UART_TX_GPIO_BANK_CLK_EN
+	str	w2, [x1]
+	mov_imm	x1, DEBUG_UART_TX_GPIO_BANK_ADDRESS
+	/* Set GPIO mode alternate */
+	ldr	w2, [x1, #GPIO_MODE_OFFSET]
+	bic	w2, w2, #(GPIO_MODE_MASK << GPIO_TX_SHIFT)
+	orr	w2, w2, #(GPIO_MODE_ALTERNATE << GPIO_TX_SHIFT)
+	str	w2, [x1, #GPIO_MODE_OFFSET]
+	/* Set GPIO speed low */
+	ldr	w2, [x1, #GPIO_SPEED_OFFSET]
+	bic	w2, w2, #(GPIO_SPEED_MASK << GPIO_TX_SHIFT)
+	str	w2, [x1, #GPIO_SPEED_OFFSET]
+	/* Set no-pull */
+	ldr	w2, [x1, #GPIO_PUPD_OFFSET]
+	bic	w2, w2, #(GPIO_PULL_MASK << GPIO_TX_SHIFT)
+	str	w2, [x1, #GPIO_PUPD_OFFSET]
+	/* Set alternate */
+#if DEBUG_UART_TX_GPIO_PORT >= GPIO_ALT_LOWER_LIMIT
+	ldr	w2, [x1, #GPIO_AFRH_OFFSET]
+	bic	w2, w2, #(GPIO_ALTERNATE_MASK << \
+				((DEBUG_UART_TX_GPIO_PORT - GPIO_ALT_LOWER_LIMIT) << 2))
+	orr	w2, w2, #(DEBUG_UART_TX_GPIO_ALTERNATE << \
+				((DEBUG_UART_TX_GPIO_PORT - GPIO_ALT_LOWER_LIMIT) << 2))
+	str	w2, [x1, #GPIO_AFRH_OFFSET]
+#else
+	ldr	w2, [x1, #GPIO_AFRL_OFFSET]
+	bic	w2, w2, #(GPIO_ALTERNATE_MASK << (DEBUG_UART_TX_GPIO_PORT << 2))
+	orr	w2, w2, #(DEBUG_UART_TX_GPIO_ALTERNATE << (DEBUG_UART_TX_GPIO_PORT << 2))
+	str	w2, [x1, #GPIO_AFRL_OFFSET]
+#endif
+	/* Clear UART clock flexgen divisors, keep enable bit */
+	mov_imm	x1, (RCC_BASE + DEBUG_UART_PREDIV_CFGR)
+	mov	x2, #0
+	str	w2, [x1]
+	mov_imm	x1, (RCC_BASE + DEBUG_UART_FINDIV_CFGR)
+	mov	x2, #0x40
+	str	w2, [x1]
+	/* Enable UART clock, with its source */
+	mov_imm	x1, (RCC_BASE + DEBUG_UART_TX_CLKSRC_REG)
+	mov_imm	w2, (DEBUG_UART_TX_CLKSRC | RCC_XBARxCFGR_XBARxEN)
+	str	w2, [x1]
+	mov_imm	x1, (RCC_BASE + DEBUG_UART_TX_EN_REG)
+	ldr	w2, [x1]
+	orr	w2, w2, #DEBUG_UART_TX_EN
+	str	w2, [x1]
+
+	mov_imm	x0, STM32MP_DEBUG_USART_BASE
+	mov_imm	x1, STM32MP_DEBUG_USART_CLK_FRQ
+	mov_imm	x2, STM32MP_UART_BAUDRATE
+	b	console_stm32_core_init
 endfunc plat_crash_console_init
 
 func plat_crash_console_flush
+	mov_imm	x0, STM32MP_DEBUG_USART_BASE
+	b	console_stm32_core_flush
 endfunc plat_crash_console_flush
 
 func plat_crash_console_putc
+	mov_imm	x1, STM32MP_DEBUG_USART_BASE
+	cmp	x0, #'\n'
+	b.ne	1f
+	mov	x15, x30
+	mov	x0, #'\r'
+	bl	console_stm32_core_putc
+	mov	x30, x15
+	mov	x0, #'\n'
+1:
+	b	console_stm32_core_putc
 endfunc plat_crash_console_putc
 
+#ifdef IMAGE_BL2
+	/* ---------------------------------------------
+	 * void plat_report_exception(unsigned int type)
+	 * Function to report an unhandled exception
+	 * with platform-specific means.
+	 * ---------------------------------------------
+	 */
+func plat_report_exception
+	mov	x8, x30
+
+	adr	x4, plat_err_str
+	bl	asm_print_str
+
+	adr	x4, esr_el3_str
+	bl	asm_print_str
+
+	mrs	x4, esr_el3
+	bl	asm_print_hex
+
+	adr	x4, elr_el3_str
+	bl	asm_print_str
+
+	mrs	x4, elr_el3
+	bl	asm_print_hex
+
+	adr	x4, far_el3_str
+	bl	asm_print_str
+
+	mrs	x4, far_el3
+	bl	asm_print_hex
+
+	mov	x30, x8
+	ret
+endfunc plat_report_exception
+
+.section .rodata.rev_err_str, "aS"
+plat_err_str:
+	.asciz "\nPlatform exception reporting:"
+esr_el3_str:
+	.asciz "\nESR_EL3: "
+elr_el3_str:
+	.asciz "\nELR_EL3: "
+far_el3_str:
+	.asciz "\nFAR_EL3: "
+#endif /* IMAGE_BL2 */
diff --git a/plat/st/stm32mp2/bl2_plat_setup.c b/plat/st/stm32mp2/bl2_plat_setup.c
index e497c96..0805756 100644
--- a/plat/st/stm32mp2/bl2_plat_setup.c
+++ b/plat/st/stm32mp2/bl2_plat_setup.c
@@ -7,11 +7,14 @@
 #include <cdefs.h>
 #include <stdint.h>
 
+#include <stm32mp_common.h>
+
 void bl2_el3_early_platform_setup(u_register_t arg0 __unused,
 				  u_register_t arg1 __unused,
 				  u_register_t arg2 __unused,
 				  u_register_t arg3 __unused)
 {
+	stm32mp_setup_early_console();
 }
 
 void bl2_platform_setup(void)
diff --git a/plat/st/stm32mp2/platform.mk b/plat/st/stm32mp2/platform.mk
index f66612b..ba6ab4b 100644
--- a/plat/st/stm32mp2/platform.mk
+++ b/plat/st/stm32mp2/platform.mk
@@ -34,7 +34,7 @@
 PLAT_INCLUDES			+=	-Iplat/st/stm32mp2/include/
 
 PLAT_BL_COMMON_SOURCES		+=	lib/cpus/${ARCH}/cortex_a35.S
-
+PLAT_BL_COMMON_SOURCES		+=	drivers/st/uart/${ARCH}/stm32_console.S
 PLAT_BL_COMMON_SOURCES		+=	plat/st/stm32mp2/${ARCH}/stm32mp2_helper.S
 
 BL2_SOURCES			+=	plat/st/stm32mp2/plat_bl2_mem_params_desc.c
diff --git a/plat/st/stm32mp2/stm32mp2_def.h b/plat/st/stm32mp2/stm32mp2_def.h
index 99ccbb3..f8148b7 100644
--- a/plat/st/stm32mp2/stm32mp2_def.h
+++ b/plat/st/stm32mp2/stm32mp2_def.h
@@ -11,6 +11,7 @@
 #ifndef __ASSEMBLER__
 #include <drivers/st/bsec.h>
 #endif
+#include <drivers/st/stm32mp25_rcc.h>
 #include <dt-bindings/clock/stm32mp25-clks.h>
 #include <dt-bindings/clock/stm32mp25-clksrc.h>
 #include <dt-bindings/reset/stm32mp25-resets.h>
@@ -73,6 +74,58 @@
 #define PWR_BASE				U(0x44210000)
 
 /*******************************************************************************
+ * STM32MP2 GPIO
+ ******************************************************************************/
+#define GPIOA_BASE				U(0x44240000)
+#define GPIOB_BASE				U(0x44250000)
+#define GPIOC_BASE				U(0x44260000)
+#define GPIOD_BASE				U(0x44270000)
+#define GPIOE_BASE				U(0x44280000)
+#define GPIOF_BASE				U(0x44290000)
+#define GPIOG_BASE				U(0x442A0000)
+#define GPIOH_BASE				U(0x442B0000)
+#define GPIOI_BASE				U(0x442C0000)
+#define GPIOJ_BASE				U(0x442D0000)
+#define GPIOK_BASE				U(0x442E0000)
+#define GPIOZ_BASE				U(0x46200000)
+#define GPIO_BANK_OFFSET			U(0x10000)
+
+#define STM32MP_GPIOS_PIN_MAX_COUNT		16
+#define STM32MP_GPIOZ_PIN_MAX_COUNT		8
+
+/*******************************************************************************
+ * STM32MP2 UART
+ ******************************************************************************/
+#define USART1_BASE				U(0x40330000)
+#define USART2_BASE				U(0x400E0000)
+#define USART3_BASE				U(0x400F0000)
+#define UART4_BASE				U(0x40100000)
+#define UART5_BASE				U(0x40110000)
+#define USART6_BASE				U(0x40220000)
+#define UART7_BASE				U(0x40370000)
+#define UART8_BASE				U(0x40380000)
+#define UART9_BASE				U(0x402C0000)
+#define STM32MP_NB_OF_UART			U(9)
+
+/* For UART crash console */
+#define STM32MP_DEBUG_USART_CLK_FRQ		64000000
+/* USART2 on HSI@64MHz, TX on GPIOA4 Alternate 6 */
+#define STM32MP_DEBUG_USART_BASE		USART2_BASE
+#define DEBUG_UART_TX_GPIO_BANK_ADDRESS		GPIOA_BASE
+#define DEBUG_UART_TX_GPIO_BANK_CLK_REG		RCC_GPIOACFGR
+#define DEBUG_UART_TX_GPIO_BANK_CLK_EN		RCC_GPIOxCFGR_GPIOxEN
+#define DEBUG_UART_TX_GPIO_PORT			4
+#define DEBUG_UART_TX_GPIO_ALTERNATE		6
+#define DEBUG_UART_TX_CLKSRC_REG		RCC_XBAR8CFGR
+#define DEBUG_UART_TX_CLKSRC			XBAR_SRC_HSI
+#define DEBUG_UART_TX_EN_REG			RCC_USART2CFGR
+#define DEBUG_UART_TX_EN			RCC_UARTxCFGR_UARTxEN
+#define DEBUG_UART_RST_REG			RCC_USART2CFGR
+#define DEBUG_UART_RST_BIT			RCC_UARTxCFGR_UARTxRST
+#define DEBUG_UART_PREDIV_CFGR			RCC_PREDIV8CFGR
+#define DEBUG_UART_FINDIV_CFGR			RCC_FINDIV8CFGR
+
+/*******************************************************************************
  * STM32MP2 SDMMC
  ******************************************************************************/
 #define STM32MP_SDMMC1_BASE			U(0x48220000)