14353bb20SYann Gautier/* 2b156d7b1SYann Gautier * Copyright (c) 2018-2023, Arm Limited and Contributors. All rights reserved. 34353bb20SYann Gautier * 44353bb20SYann Gautier * SPDX-License-Identifier: BSD-3-Clause 54353bb20SYann Gautier */ 64353bb20SYann Gautier#include <asm_macros.S> 76d264afcSYann Gautier#include <assert_macros.S> 86d264afcSYann Gautier#include <console_macros.S> 909d40e0eSAntonio Nino Diaz#include <drivers/st/stm32_console.h> 1009d40e0eSAntonio Nino Diaz#include <drivers/st/stm32_uart_regs.h> 114353bb20SYann Gautier 12278c34dfSYann Gautier#define USART_TIMEOUT 0x1000 13278c34dfSYann Gautier 146d264afcSYann Gautier /* 156d264afcSYann Gautier * "core" functions are low-level implementations that don't require 166d264afcSYann Gautier * writeable memory and are thus safe to call in BL1 crash context. 176d264afcSYann Gautier */ 186d264afcSYann Gautier .globl console_stm32_core_init 196d264afcSYann Gautier .globl console_stm32_core_putc 206d264afcSYann Gautier .globl console_stm32_core_getc 216d264afcSYann Gautier .globl console_stm32_core_flush 226d264afcSYann Gautier 236d264afcSYann Gautier .globl console_stm32_putc 246d264afcSYann Gautier .globl console_stm32_flush 256d264afcSYann Gautier 266d264afcSYann Gautier 274353bb20SYann Gautier 284353bb20SYann Gautier /* ----------------------------------------------------------------- 294353bb20SYann Gautier * int console_core_init(uintptr_t base_addr, 304353bb20SYann Gautier * unsigned int uart_clk, 314353bb20SYann Gautier * unsigned int baud_rate) 324353bb20SYann Gautier * 334353bb20SYann Gautier * Function to initialize the console without a C Runtime to print 344353bb20SYann Gautier * debug information. This function will be accessed by console_init 354353bb20SYann Gautier * and crash reporting. 364353bb20SYann Gautier * 374353bb20SYann Gautier * In: r0 - console base address 384353bb20SYann Gautier * r1 - Uart clock in Hz 394353bb20SYann Gautier * r2 - Baud rate 404353bb20SYann Gautier * Out: return 1 on success else 0 on error 414353bb20SYann Gautier * Clobber list : r1, r2, r3 424353bb20SYann Gautier * ----------------------------------------------------------------- 434353bb20SYann Gautier */ 446d264afcSYann Gautierfunc console_stm32_core_init 45278c34dfSYann Gautier /* Check the input base address */ 46278c34dfSYann Gautier cmp r0, #0 47278c34dfSYann Gautier beq core_init_fail 4849c7f0ceSYann Gautier#if !defined(IMAGE_BL2) 49ea69dcdcSYann Gautier#if STM32MP_RECONFIGURE_CONSOLE 50ea69dcdcSYann Gautier /* UART clock rate is set to 0 in BL32, skip init in that case */ 51ea69dcdcSYann Gautier cmp r1, #0 52ea69dcdcSYann Gautier beq 1f 53ea69dcdcSYann Gautier#else /* STM32MP_RECONFIGURE_CONSOLE */ 5449c7f0ceSYann Gautier /* Skip UART initialization if it is already enabled */ 5549c7f0ceSYann Gautier ldr r3, [r0, #USART_CR1] 5649c7f0ceSYann Gautier ands r3, r3, #USART_CR1_UE 5749c7f0ceSYann Gautier bne 1f 58ea69dcdcSYann Gautier#endif /* STM32MP_RECONFIGURE_CONSOLE */ 5949c7f0ceSYann Gautier#endif /* IMAGE_BL2 */ 60278c34dfSYann Gautier /* Check baud rate and uart clock for sanity */ 61278c34dfSYann Gautier cmp r1, #0 62278c34dfSYann Gautier beq core_init_fail 63278c34dfSYann Gautier cmp r2, #0 64278c34dfSYann Gautier beq core_init_fail 65278c34dfSYann Gautier /* Disable UART */ 66278c34dfSYann Gautier ldr r3, [r0, #USART_CR1] 67278c34dfSYann Gautier bic r3, r3, #USART_CR1_UE 68278c34dfSYann Gautier str r3, [r0, #USART_CR1] 69278c34dfSYann Gautier /* Configure UART */ 70278c34dfSYann Gautier orr r3, r3, #(USART_CR1_TE | USART_CR1_FIFOEN) 71278c34dfSYann Gautier str r3, [r0, #USART_CR1] 72278c34dfSYann Gautier ldr r3, [r0, #USART_CR2] 73278c34dfSYann Gautier bic r3, r3, #USART_CR2_STOP 74278c34dfSYann Gautier str r3, [r0, #USART_CR2] 75278c34dfSYann Gautier /* Divisor = (Uart clock + (baudrate / 2)) / baudrate */ 76af7775abSYann Gautier lsr r3, r2, #1 77278c34dfSYann Gautier add r3, r1, r3 78278c34dfSYann Gautier udiv r3, r3, r2 791f60d1bdSYann Gautier cmp r3, #16 801f60d1bdSYann Gautier bhi 2f 811f60d1bdSYann Gautier /* Oversampling 8 */ 821f60d1bdSYann Gautier /* Divisor = (2 * Uart clock + (baudrate / 2)) / baudrate */ 831f60d1bdSYann Gautier lsr r3, r2, #1 841f60d1bdSYann Gautier add r3, r3, r1, lsl #1 851f60d1bdSYann Gautier udiv r3, r3, r2 861f60d1bdSYann Gautier and r1, r3, #USART_BRR_DIV_FRACTION 871f60d1bdSYann Gautier lsr r1, r1, #1 881f60d1bdSYann Gautier bic r3, r3, #USART_BRR_DIV_FRACTION 891f60d1bdSYann Gautier orr r3, r3, r1 901f60d1bdSYann Gautier ldr r1, [r0, #USART_CR1] 911f60d1bdSYann Gautier orr r1, r1, #USART_CR1_OVER8 921f60d1bdSYann Gautier str r1, [r0, #USART_CR1] 931f60d1bdSYann Gautier2: 94278c34dfSYann Gautier str r3, [r0, #USART_BRR] 95278c34dfSYann Gautier /* Enable UART */ 96278c34dfSYann Gautier ldr r3, [r0, #USART_CR1] 97278c34dfSYann Gautier orr r3, r3, #USART_CR1_UE 98278c34dfSYann Gautier str r3, [r0, #USART_CR1] 99278c34dfSYann Gautier /* Check TEACK bit */ 100278c34dfSYann Gautier mov r2, #USART_TIMEOUT 101278c34dfSYann Gautierteack_loop: 102278c34dfSYann Gautier subs r2, r2, #1 103278c34dfSYann Gautier beq core_init_fail 104278c34dfSYann Gautier ldr r3, [r0, #USART_ISR] 105278c34dfSYann Gautier tst r3, #USART_ISR_TEACK 106278c34dfSYann Gautier beq teack_loop 10749c7f0ceSYann Gautier1: 108278c34dfSYann Gautier mov r0, #1 109278c34dfSYann Gautier bx lr 110278c34dfSYann Gautiercore_init_fail: 111278c34dfSYann Gautier mov r0, #0 1124353bb20SYann Gautier bx lr 1136d264afcSYann Gautierendfunc console_stm32_core_init 1146d264afcSYann Gautier 1156d264afcSYann Gautier .globl console_stm32_register 1166d264afcSYann Gautier 1176d264afcSYann Gautier /* ------------------------------------------------------- 1186d264afcSYann Gautier * int console_stm32_register(uintptr_t baseaddr, 1196d264afcSYann Gautier * uint32_t clock, uint32_t baud, 120c10db6deSAndre Przywara * console_t *console); 1216d264afcSYann Gautier * Function to initialize and register a new STM32 1226d264afcSYann Gautier * console. Storage passed in for the console struct 1236d264afcSYann Gautier * *must* be persistent (i.e. not from the stack). 1246d264afcSYann Gautier * In: r0 - UART register base address 1256d264afcSYann Gautier * r1 - UART clock in Hz 1266d264afcSYann Gautier * r2 - Baud rate 127c10db6deSAndre Przywara * r3 - pointer to empty console_t struct 1286d264afcSYann Gautier * Out: return 1 on success, 0 on error 1296d264afcSYann Gautier * Clobber list : r0, r1, r2 1306d264afcSYann Gautier * ------------------------------------------------------- 1316d264afcSYann Gautier */ 1326d264afcSYann Gautierfunc console_stm32_register 1336d264afcSYann Gautier push {r4, lr} 1346d264afcSYann Gautier mov r4, r3 1356d264afcSYann Gautier cmp r4, #0 1366d264afcSYann Gautier beq register_fail 137c10db6deSAndre Przywara str r0, [r4, #CONSOLE_T_BASE] 1386d264afcSYann Gautier 1396d264afcSYann Gautier bl console_stm32_core_init 1406d264afcSYann Gautier cmp r0, #0 1416d264afcSYann Gautier beq register_fail 1426d264afcSYann Gautier 1436d264afcSYann Gautier mov r0, r4 1446d264afcSYann Gautier pop {r4, lr} 1456d264afcSYann Gautier finish_console_register stm32 putc=1, getc=0, flush=1 1466d264afcSYann Gautier 1476d264afcSYann Gautierregister_fail: 1486d264afcSYann Gautier pop {r4, pc} 1496d264afcSYann Gautierendfunc console_stm32_register 1504353bb20SYann Gautier 1514353bb20SYann Gautier /* --------------------------------------------------------------- 1524353bb20SYann Gautier * int console_core_putc(int c, uintptr_t base_addr) 1534353bb20SYann Gautier * 1544353bb20SYann Gautier * Function to output a character over the console. It returns the 1554353bb20SYann Gautier * character printed on success or -1 on error. 1564353bb20SYann Gautier * 1574353bb20SYann Gautier * In : r0 - character to be printed 1584353bb20SYann Gautier * r1 - console base address 1594353bb20SYann Gautier * Out : return -1 on error else return character. 1604353bb20SYann Gautier * Clobber list : r2 1614353bb20SYann Gautier * --------------------------------------------------------------- 1624353bb20SYann Gautier */ 1636d264afcSYann Gautierfunc console_stm32_core_putc 164278c34dfSYann Gautier /* Check the input parameter */ 165278c34dfSYann Gautier cmp r1, #0 166278c34dfSYann Gautier beq putc_error 167ebf851edSYann Gautier 168278c34dfSYann Gautier /* Check Transmit Data Register Empty */ 169ebf851edSYann Gautiertxe_loop: 170278c34dfSYann Gautier ldr r2, [r1, #USART_ISR] 171278c34dfSYann Gautier tst r2, #USART_ISR_TXE 172ebf851edSYann Gautier beq txe_loop 173278c34dfSYann Gautier str r0, [r1, #USART_TDR] 174278c34dfSYann Gautier bx lr 175278c34dfSYann Gautierputc_error: 176278c34dfSYann Gautier mov r0, #-1 1774353bb20SYann Gautier bx lr 1786d264afcSYann Gautierendfunc console_stm32_core_putc 1796d264afcSYann Gautier 1806d264afcSYann Gautier /* ------------------------------------------------------------ 181c10db6deSAndre Przywara * int console_stm32_putc(int c, console_t *console) 1826d264afcSYann Gautier * Function to output a character over the console. It 1836d264afcSYann Gautier * returns the character printed on success or -1 on error. 1846d264afcSYann Gautier * In: r0 - character to be printed 1856d264afcSYann Gautier * r1 - pointer to console_t structure 1866d264afcSYann Gautier * Out : return -1 on error else return character. 1876d264afcSYann Gautier * Clobber list: r2 1886d264afcSYann Gautier * ------------------------------------------------------------ 1896d264afcSYann Gautier */ 1906d264afcSYann Gautierfunc console_stm32_putc 1916d264afcSYann Gautier#if ENABLE_ASSERTIONS 1926d264afcSYann Gautier cmp r1, #0 1936d264afcSYann Gautier ASM_ASSERT(ne) 1946d264afcSYann Gautier#endif /* ENABLE_ASSERTIONS */ 195c10db6deSAndre Przywara ldr r1, [r1, #CONSOLE_T_BASE] 1966d264afcSYann Gautier b console_stm32_core_putc 1976d264afcSYann Gautierendfunc console_stm32_putc 1984353bb20SYann Gautier 1994353bb20SYann Gautier /* ----------------------------------------------------------- 2004353bb20SYann Gautier * int console_core_getc(uintptr_t base_addr) 2014353bb20SYann Gautier * 2024353bb20SYann Gautier * Function to get a character from the console. 2034353bb20SYann Gautier * It returns the character grabbed on success or -1 on error. 2044353bb20SYann Gautier * 2054353bb20SYann Gautier * In : r0 - console base address 2064353bb20SYann Gautier * Out : return -1. 2074353bb20SYann Gautier * Clobber list : r0, r1 2084353bb20SYann Gautier * ----------------------------------------------------------- 2094353bb20SYann Gautier */ 2106d264afcSYann Gautierfunc console_stm32_core_getc 2114353bb20SYann Gautier /* Not supported */ 2124353bb20SYann Gautier mov r0, #-1 2134353bb20SYann Gautier bx lr 2146d264afcSYann Gautierendfunc console_stm32_core_getc 2154353bb20SYann Gautier 2164353bb20SYann Gautier /* --------------------------------------------------------------- 217831b0e98SJimmy Brisson * void console_core_flush(uintptr_t base_addr) 2184353bb20SYann Gautier * 2194353bb20SYann Gautier * Function to force a write of all buffered data that hasn't been 2204353bb20SYann Gautier * output. 2214353bb20SYann Gautier * 2224353bb20SYann Gautier * In : r0 - console base address 223831b0e98SJimmy Brisson * Out : void. 2244353bb20SYann Gautier * Clobber list : r0, r1 2254353bb20SYann Gautier * --------------------------------------------------------------- 2264353bb20SYann Gautier */ 2276d264afcSYann Gautierfunc console_stm32_core_flush 228831b0e98SJimmy Brisson#if ENABLE_ASSERTIONS 229278c34dfSYann Gautier cmp r0, #0 230831b0e98SJimmy Brisson ASM_ASSERT(ne) 231831b0e98SJimmy Brisson#endif /* ENABLE_ASSERTIONS */ 232b156d7b1SYann Gautier /* Skip flush if UART is not enabled */ 233b156d7b1SYann Gautier ldr r1, [r0, #USART_CR1] 234a5273808SYann Gautier tst r1, #USART_CR1_UE 235b156d7b1SYann Gautier beq 1f 236*35988c64SClément Le Goffic /* Check Transmission Complete flag */ 237*35988c64SClément Le Goffictc_loop: 238278c34dfSYann Gautier ldr r1, [r0, #USART_ISR] 239*35988c64SClément Le Goffic tst r1, #USART_ISR_TC 240*35988c64SClément Le Goffic beq tc_loop 241b156d7b1SYann Gautier1: 2424353bb20SYann Gautier bx lr 2436d264afcSYann Gautierendfunc console_stm32_core_flush 2446d264afcSYann Gautier 2456d264afcSYann Gautier /* ------------------------------------------------------ 246831b0e98SJimmy Brisson * void console_stm32_flush(console_t *console) 2476d264afcSYann Gautier * Function to force a write of all buffered 2486d264afcSYann Gautier * data that hasn't been output. 2496d264afcSYann Gautier * In : r0 - pointer to console_t structure 250831b0e98SJimmy Brisson * Out : void. 2516d264afcSYann Gautier * Clobber list: r0, r1 2526d264afcSYann Gautier * ------------------------------------------------------ 2536d264afcSYann Gautier */ 2546d264afcSYann Gautierfunc console_stm32_flush 2556d264afcSYann Gautier#if ENABLE_ASSERTIONS 2566d264afcSYann Gautier cmp r0, #0 2576d264afcSYann Gautier ASM_ASSERT(ne) 2586d264afcSYann Gautier#endif /* ENABLE_ASSERTIONS */ 259c10db6deSAndre Przywara ldr r0, [r0, #CONSOLE_T_BASE] 2606d264afcSYann Gautier b console_stm32_core_flush 2616d264afcSYann Gautierendfunc console_stm32_flush 262