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 /* Check transmit complete flag */ 175ebf851edSYann Gautiertc_loop: 176278c34dfSYann Gautier ldr r2, [r1, #USART_ISR] 177278c34dfSYann Gautier tst r2, #USART_ISR_TC 178ebf851edSYann Gautier beq tc_loop 179278c34dfSYann Gautier bx lr 180278c34dfSYann Gautierputc_error: 181278c34dfSYann Gautier mov r0, #-1 1824353bb20SYann Gautier bx lr 1836d264afcSYann Gautierendfunc console_stm32_core_putc 1846d264afcSYann Gautier 1856d264afcSYann Gautier /* ------------------------------------------------------------ 186c10db6deSAndre Przywara * int console_stm32_putc(int c, console_t *console) 1876d264afcSYann Gautier * Function to output a character over the console. It 1886d264afcSYann Gautier * returns the character printed on success or -1 on error. 1896d264afcSYann Gautier * In: r0 - character to be printed 1906d264afcSYann Gautier * r1 - pointer to console_t structure 1916d264afcSYann Gautier * Out : return -1 on error else return character. 1926d264afcSYann Gautier * Clobber list: r2 1936d264afcSYann Gautier * ------------------------------------------------------------ 1946d264afcSYann Gautier */ 1956d264afcSYann Gautierfunc console_stm32_putc 1966d264afcSYann Gautier#if ENABLE_ASSERTIONS 1976d264afcSYann Gautier cmp r1, #0 1986d264afcSYann Gautier ASM_ASSERT(ne) 1996d264afcSYann Gautier#endif /* ENABLE_ASSERTIONS */ 200c10db6deSAndre Przywara ldr r1, [r1, #CONSOLE_T_BASE] 2016d264afcSYann Gautier b console_stm32_core_putc 2026d264afcSYann Gautierendfunc console_stm32_putc 2034353bb20SYann Gautier 2044353bb20SYann Gautier /* ----------------------------------------------------------- 2054353bb20SYann Gautier * int console_core_getc(uintptr_t base_addr) 2064353bb20SYann Gautier * 2074353bb20SYann Gautier * Function to get a character from the console. 2084353bb20SYann Gautier * It returns the character grabbed on success or -1 on error. 2094353bb20SYann Gautier * 2104353bb20SYann Gautier * In : r0 - console base address 2114353bb20SYann Gautier * Out : return -1. 2124353bb20SYann Gautier * Clobber list : r0, r1 2134353bb20SYann Gautier * ----------------------------------------------------------- 2144353bb20SYann Gautier */ 2156d264afcSYann Gautierfunc console_stm32_core_getc 2164353bb20SYann Gautier /* Not supported */ 2174353bb20SYann Gautier mov r0, #-1 2184353bb20SYann Gautier bx lr 2196d264afcSYann Gautierendfunc console_stm32_core_getc 2204353bb20SYann Gautier 2214353bb20SYann Gautier /* --------------------------------------------------------------- 222831b0e98SJimmy Brisson * void console_core_flush(uintptr_t base_addr) 2234353bb20SYann Gautier * 2244353bb20SYann Gautier * Function to force a write of all buffered data that hasn't been 2254353bb20SYann Gautier * output. 2264353bb20SYann Gautier * 2274353bb20SYann Gautier * In : r0 - console base address 228831b0e98SJimmy Brisson * Out : void. 2294353bb20SYann Gautier * Clobber list : r0, r1 2304353bb20SYann Gautier * --------------------------------------------------------------- 2314353bb20SYann Gautier */ 2326d264afcSYann Gautierfunc console_stm32_core_flush 233831b0e98SJimmy Brisson#if ENABLE_ASSERTIONS 234278c34dfSYann Gautier cmp r0, #0 235831b0e98SJimmy Brisson ASM_ASSERT(ne) 236831b0e98SJimmy Brisson#endif /* ENABLE_ASSERTIONS */ 237b156d7b1SYann Gautier /* Skip flush if UART is not enabled */ 238b156d7b1SYann Gautier ldr r1, [r0, #USART_CR1] 239*a5273808SYann Gautier tst r1, #USART_CR1_UE 240b156d7b1SYann Gautier beq 1f 241278c34dfSYann Gautier /* Check Transmit Data Register Empty */ 242278c34dfSYann Gautiertxe_loop_3: 243278c34dfSYann Gautier ldr r1, [r0, #USART_ISR] 244278c34dfSYann Gautier tst r1, #USART_ISR_TXE 245278c34dfSYann Gautier beq txe_loop_3 246b156d7b1SYann Gautier1: 2474353bb20SYann Gautier bx lr 2486d264afcSYann Gautierendfunc console_stm32_core_flush 2496d264afcSYann Gautier 2506d264afcSYann Gautier /* ------------------------------------------------------ 251831b0e98SJimmy Brisson * void console_stm32_flush(console_t *console) 2526d264afcSYann Gautier * Function to force a write of all buffered 2536d264afcSYann Gautier * data that hasn't been output. 2546d264afcSYann Gautier * In : r0 - pointer to console_t structure 255831b0e98SJimmy Brisson * Out : void. 2566d264afcSYann Gautier * Clobber list: r0, r1 2576d264afcSYann Gautier * ------------------------------------------------------ 2586d264afcSYann Gautier */ 2596d264afcSYann Gautierfunc console_stm32_flush 2606d264afcSYann Gautier#if ENABLE_ASSERTIONS 2616d264afcSYann Gautier cmp r0, #0 2626d264afcSYann Gautier ASM_ASSERT(ne) 2636d264afcSYann Gautier#endif /* ENABLE_ASSERTIONS */ 264c10db6deSAndre Przywara ldr r0, [r0, #CONSOLE_T_BASE] 2656d264afcSYann Gautier b console_stm32_core_flush 2666d264afcSYann Gautierendfunc console_stm32_flush 267