14353bb20SYann Gautier/* 2*af7775abSYann Gautier * Copyright (c) 2018-2022, 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) 4949c7f0ceSYann Gautier /* Skip UART initialization if it is already enabled */ 5049c7f0ceSYann Gautier ldr r3, [r0, #USART_CR1] 5149c7f0ceSYann Gautier ands r3, r3, #USART_CR1_UE 5249c7f0ceSYann Gautier bne 1f 5349c7f0ceSYann Gautier#endif /* IMAGE_BL2 */ 54278c34dfSYann Gautier /* Check baud rate and uart clock for sanity */ 55278c34dfSYann Gautier cmp r1, #0 56278c34dfSYann Gautier beq core_init_fail 57278c34dfSYann Gautier cmp r2, #0 58278c34dfSYann Gautier beq core_init_fail 59278c34dfSYann Gautier /* Disable UART */ 60278c34dfSYann Gautier ldr r3, [r0, #USART_CR1] 61278c34dfSYann Gautier bic r3, r3, #USART_CR1_UE 62278c34dfSYann Gautier str r3, [r0, #USART_CR1] 63278c34dfSYann Gautier /* Configure UART */ 64278c34dfSYann Gautier orr r3, r3, #(USART_CR1_TE | USART_CR1_FIFOEN) 65278c34dfSYann Gautier str r3, [r0, #USART_CR1] 66278c34dfSYann Gautier ldr r3, [r0, #USART_CR2] 67278c34dfSYann Gautier bic r3, r3, #USART_CR2_STOP 68278c34dfSYann Gautier str r3, [r0, #USART_CR2] 69278c34dfSYann Gautier /* Divisor = (Uart clock + (baudrate / 2)) / baudrate */ 70*af7775abSYann Gautier lsr r3, r2, #1 71278c34dfSYann Gautier add r3, r1, r3 72278c34dfSYann Gautier udiv r3, r3, r2 73278c34dfSYann Gautier str r3, [r0, #USART_BRR] 74278c34dfSYann Gautier /* Enable UART */ 75278c34dfSYann Gautier ldr r3, [r0, #USART_CR1] 76278c34dfSYann Gautier orr r3, r3, #USART_CR1_UE 77278c34dfSYann Gautier str r3, [r0, #USART_CR1] 78278c34dfSYann Gautier /* Check TEACK bit */ 79278c34dfSYann Gautier mov r2, #USART_TIMEOUT 80278c34dfSYann Gautierteack_loop: 81278c34dfSYann Gautier subs r2, r2, #1 82278c34dfSYann Gautier beq core_init_fail 83278c34dfSYann Gautier ldr r3, [r0, #USART_ISR] 84278c34dfSYann Gautier tst r3, #USART_ISR_TEACK 85278c34dfSYann Gautier beq teack_loop 8649c7f0ceSYann Gautier1: 87278c34dfSYann Gautier mov r0, #1 88278c34dfSYann Gautier bx lr 89278c34dfSYann Gautiercore_init_fail: 90278c34dfSYann Gautier mov r0, #0 914353bb20SYann Gautier bx lr 926d264afcSYann Gautierendfunc console_stm32_core_init 936d264afcSYann Gautier 946d264afcSYann Gautier .globl console_stm32_register 956d264afcSYann Gautier 966d264afcSYann Gautier /* ------------------------------------------------------- 976d264afcSYann Gautier * int console_stm32_register(uintptr_t baseaddr, 986d264afcSYann Gautier * uint32_t clock, uint32_t baud, 99c10db6deSAndre Przywara * console_t *console); 1006d264afcSYann Gautier * Function to initialize and register a new STM32 1016d264afcSYann Gautier * console. Storage passed in for the console struct 1026d264afcSYann Gautier * *must* be persistent (i.e. not from the stack). 1036d264afcSYann Gautier * In: r0 - UART register base address 1046d264afcSYann Gautier * r1 - UART clock in Hz 1056d264afcSYann Gautier * r2 - Baud rate 106c10db6deSAndre Przywara * r3 - pointer to empty console_t struct 1076d264afcSYann Gautier * Out: return 1 on success, 0 on error 1086d264afcSYann Gautier * Clobber list : r0, r1, r2 1096d264afcSYann Gautier * ------------------------------------------------------- 1106d264afcSYann Gautier */ 1116d264afcSYann Gautierfunc console_stm32_register 1126d264afcSYann Gautier push {r4, lr} 1136d264afcSYann Gautier mov r4, r3 1146d264afcSYann Gautier cmp r4, #0 1156d264afcSYann Gautier beq register_fail 116c10db6deSAndre Przywara str r0, [r4, #CONSOLE_T_BASE] 1176d264afcSYann Gautier 1186d264afcSYann Gautier bl console_stm32_core_init 1196d264afcSYann Gautier cmp r0, #0 1206d264afcSYann Gautier beq register_fail 1216d264afcSYann Gautier 1226d264afcSYann Gautier mov r0, r4 1236d264afcSYann Gautier pop {r4, lr} 1246d264afcSYann Gautier finish_console_register stm32 putc=1, getc=0, flush=1 1256d264afcSYann Gautier 1266d264afcSYann Gautierregister_fail: 1276d264afcSYann Gautier pop {r4, pc} 1286d264afcSYann Gautierendfunc console_stm32_register 1294353bb20SYann Gautier 1304353bb20SYann Gautier /* --------------------------------------------------------------- 1314353bb20SYann Gautier * int console_core_putc(int c, uintptr_t base_addr) 1324353bb20SYann Gautier * 1334353bb20SYann Gautier * Function to output a character over the console. It returns the 1344353bb20SYann Gautier * character printed on success or -1 on error. 1354353bb20SYann Gautier * 1364353bb20SYann Gautier * In : r0 - character to be printed 1374353bb20SYann Gautier * r1 - console base address 1384353bb20SYann Gautier * Out : return -1 on error else return character. 1394353bb20SYann Gautier * Clobber list : r2 1404353bb20SYann Gautier * --------------------------------------------------------------- 1414353bb20SYann Gautier */ 1426d264afcSYann Gautierfunc console_stm32_core_putc 143278c34dfSYann Gautier /* Check the input parameter */ 144278c34dfSYann Gautier cmp r1, #0 145278c34dfSYann Gautier beq putc_error 146ebf851edSYann Gautier 147278c34dfSYann Gautier /* Check Transmit Data Register Empty */ 148ebf851edSYann Gautiertxe_loop: 149278c34dfSYann Gautier ldr r2, [r1, #USART_ISR] 150278c34dfSYann Gautier tst r2, #USART_ISR_TXE 151ebf851edSYann Gautier beq txe_loop 152278c34dfSYann Gautier str r0, [r1, #USART_TDR] 153278c34dfSYann Gautier /* Check transmit complete flag */ 154ebf851edSYann Gautiertc_loop: 155278c34dfSYann Gautier ldr r2, [r1, #USART_ISR] 156278c34dfSYann Gautier tst r2, #USART_ISR_TC 157ebf851edSYann Gautier beq tc_loop 158278c34dfSYann Gautier bx lr 159278c34dfSYann Gautierputc_error: 160278c34dfSYann Gautier mov r0, #-1 1614353bb20SYann Gautier bx lr 1626d264afcSYann Gautierendfunc console_stm32_core_putc 1636d264afcSYann Gautier 1646d264afcSYann Gautier /* ------------------------------------------------------------ 165c10db6deSAndre Przywara * int console_stm32_putc(int c, console_t *console) 1666d264afcSYann Gautier * Function to output a character over the console. It 1676d264afcSYann Gautier * returns the character printed on success or -1 on error. 1686d264afcSYann Gautier * In: r0 - character to be printed 1696d264afcSYann Gautier * r1 - pointer to console_t structure 1706d264afcSYann Gautier * Out : return -1 on error else return character. 1716d264afcSYann Gautier * Clobber list: r2 1726d264afcSYann Gautier * ------------------------------------------------------------ 1736d264afcSYann Gautier */ 1746d264afcSYann Gautierfunc console_stm32_putc 1756d264afcSYann Gautier#if ENABLE_ASSERTIONS 1766d264afcSYann Gautier cmp r1, #0 1776d264afcSYann Gautier ASM_ASSERT(ne) 1786d264afcSYann Gautier#endif /* ENABLE_ASSERTIONS */ 179c10db6deSAndre Przywara ldr r1, [r1, #CONSOLE_T_BASE] 1806d264afcSYann Gautier b console_stm32_core_putc 1816d264afcSYann Gautierendfunc console_stm32_putc 1824353bb20SYann Gautier 1834353bb20SYann Gautier /* ----------------------------------------------------------- 1844353bb20SYann Gautier * int console_core_getc(uintptr_t base_addr) 1854353bb20SYann Gautier * 1864353bb20SYann Gautier * Function to get a character from the console. 1874353bb20SYann Gautier * It returns the character grabbed on success or -1 on error. 1884353bb20SYann Gautier * 1894353bb20SYann Gautier * In : r0 - console base address 1904353bb20SYann Gautier * Out : return -1. 1914353bb20SYann Gautier * Clobber list : r0, r1 1924353bb20SYann Gautier * ----------------------------------------------------------- 1934353bb20SYann Gautier */ 1946d264afcSYann Gautierfunc console_stm32_core_getc 1954353bb20SYann Gautier /* Not supported */ 1964353bb20SYann Gautier mov r0, #-1 1974353bb20SYann Gautier bx lr 1986d264afcSYann Gautierendfunc console_stm32_core_getc 1994353bb20SYann Gautier 2004353bb20SYann Gautier /* --------------------------------------------------------------- 201831b0e98SJimmy Brisson * void console_core_flush(uintptr_t base_addr) 2024353bb20SYann Gautier * 2034353bb20SYann Gautier * Function to force a write of all buffered data that hasn't been 2044353bb20SYann Gautier * output. 2054353bb20SYann Gautier * 2064353bb20SYann Gautier * In : r0 - console base address 207831b0e98SJimmy Brisson * Out : void. 2084353bb20SYann Gautier * Clobber list : r0, r1 2094353bb20SYann Gautier * --------------------------------------------------------------- 2104353bb20SYann Gautier */ 2116d264afcSYann Gautierfunc console_stm32_core_flush 212831b0e98SJimmy Brisson#if ENABLE_ASSERTIONS 213278c34dfSYann Gautier cmp r0, #0 214831b0e98SJimmy Brisson ASM_ASSERT(ne) 215831b0e98SJimmy Brisson#endif /* ENABLE_ASSERTIONS */ 216278c34dfSYann Gautier /* Check Transmit Data Register Empty */ 217278c34dfSYann Gautiertxe_loop_3: 218278c34dfSYann Gautier ldr r1, [r0, #USART_ISR] 219278c34dfSYann Gautier tst r1, #USART_ISR_TXE 220278c34dfSYann Gautier beq txe_loop_3 2214353bb20SYann Gautier bx lr 2226d264afcSYann Gautierendfunc console_stm32_core_flush 2236d264afcSYann Gautier 2246d264afcSYann Gautier /* ------------------------------------------------------ 225831b0e98SJimmy Brisson * void console_stm32_flush(console_t *console) 2266d264afcSYann Gautier * Function to force a write of all buffered 2276d264afcSYann Gautier * data that hasn't been output. 2286d264afcSYann Gautier * In : r0 - pointer to console_t structure 229831b0e98SJimmy Brisson * Out : void. 2306d264afcSYann Gautier * Clobber list: r0, r1 2316d264afcSYann Gautier * ------------------------------------------------------ 2326d264afcSYann Gautier */ 2336d264afcSYann Gautierfunc console_stm32_flush 2346d264afcSYann Gautier#if ENABLE_ASSERTIONS 2356d264afcSYann Gautier cmp r0, #0 2366d264afcSYann Gautier ASM_ASSERT(ne) 2376d264afcSYann Gautier#endif /* ENABLE_ASSERTIONS */ 238c10db6deSAndre Przywara ldr r0, [r0, #CONSOLE_T_BASE] 2396d264afcSYann Gautier b console_stm32_core_flush 2406d264afcSYann Gautierendfunc console_stm32_flush 241