14353bb20SYann Gautier/* 2af7775abSYann 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 */ 70af7775abSYann Gautier lsr r3, r2, #1 71278c34dfSYann Gautier add r3, r1, r3 72278c34dfSYann Gautier udiv r3, r3, r2 73*1f60d1bdSYann Gautier cmp r3, #16 74*1f60d1bdSYann Gautier bhi 2f 75*1f60d1bdSYann Gautier /* Oversampling 8 */ 76*1f60d1bdSYann Gautier /* Divisor = (2 * Uart clock + (baudrate / 2)) / baudrate */ 77*1f60d1bdSYann Gautier lsr r3, r2, #1 78*1f60d1bdSYann Gautier add r3, r3, r1, lsl #1 79*1f60d1bdSYann Gautier udiv r3, r3, r2 80*1f60d1bdSYann Gautier and r1, r3, #USART_BRR_DIV_FRACTION 81*1f60d1bdSYann Gautier lsr r1, r1, #1 82*1f60d1bdSYann Gautier bic r3, r3, #USART_BRR_DIV_FRACTION 83*1f60d1bdSYann Gautier orr r3, r3, r1 84*1f60d1bdSYann Gautier ldr r1, [r0, #USART_CR1] 85*1f60d1bdSYann Gautier orr r1, r1, #USART_CR1_OVER8 86*1f60d1bdSYann Gautier str r1, [r0, #USART_CR1] 87*1f60d1bdSYann Gautier2: 88278c34dfSYann Gautier str r3, [r0, #USART_BRR] 89278c34dfSYann Gautier /* Enable UART */ 90278c34dfSYann Gautier ldr r3, [r0, #USART_CR1] 91278c34dfSYann Gautier orr r3, r3, #USART_CR1_UE 92278c34dfSYann Gautier str r3, [r0, #USART_CR1] 93278c34dfSYann Gautier /* Check TEACK bit */ 94278c34dfSYann Gautier mov r2, #USART_TIMEOUT 95278c34dfSYann Gautierteack_loop: 96278c34dfSYann Gautier subs r2, r2, #1 97278c34dfSYann Gautier beq core_init_fail 98278c34dfSYann Gautier ldr r3, [r0, #USART_ISR] 99278c34dfSYann Gautier tst r3, #USART_ISR_TEACK 100278c34dfSYann Gautier beq teack_loop 10149c7f0ceSYann Gautier1: 102278c34dfSYann Gautier mov r0, #1 103278c34dfSYann Gautier bx lr 104278c34dfSYann Gautiercore_init_fail: 105278c34dfSYann Gautier mov r0, #0 1064353bb20SYann Gautier bx lr 1076d264afcSYann Gautierendfunc console_stm32_core_init 1086d264afcSYann Gautier 1096d264afcSYann Gautier .globl console_stm32_register 1106d264afcSYann Gautier 1116d264afcSYann Gautier /* ------------------------------------------------------- 1126d264afcSYann Gautier * int console_stm32_register(uintptr_t baseaddr, 1136d264afcSYann Gautier * uint32_t clock, uint32_t baud, 114c10db6deSAndre Przywara * console_t *console); 1156d264afcSYann Gautier * Function to initialize and register a new STM32 1166d264afcSYann Gautier * console. Storage passed in for the console struct 1176d264afcSYann Gautier * *must* be persistent (i.e. not from the stack). 1186d264afcSYann Gautier * In: r0 - UART register base address 1196d264afcSYann Gautier * r1 - UART clock in Hz 1206d264afcSYann Gautier * r2 - Baud rate 121c10db6deSAndre Przywara * r3 - pointer to empty console_t struct 1226d264afcSYann Gautier * Out: return 1 on success, 0 on error 1236d264afcSYann Gautier * Clobber list : r0, r1, r2 1246d264afcSYann Gautier * ------------------------------------------------------- 1256d264afcSYann Gautier */ 1266d264afcSYann Gautierfunc console_stm32_register 1276d264afcSYann Gautier push {r4, lr} 1286d264afcSYann Gautier mov r4, r3 1296d264afcSYann Gautier cmp r4, #0 1306d264afcSYann Gautier beq register_fail 131c10db6deSAndre Przywara str r0, [r4, #CONSOLE_T_BASE] 1326d264afcSYann Gautier 1336d264afcSYann Gautier bl console_stm32_core_init 1346d264afcSYann Gautier cmp r0, #0 1356d264afcSYann Gautier beq register_fail 1366d264afcSYann Gautier 1376d264afcSYann Gautier mov r0, r4 1386d264afcSYann Gautier pop {r4, lr} 1396d264afcSYann Gautier finish_console_register stm32 putc=1, getc=0, flush=1 1406d264afcSYann Gautier 1416d264afcSYann Gautierregister_fail: 1426d264afcSYann Gautier pop {r4, pc} 1436d264afcSYann Gautierendfunc console_stm32_register 1444353bb20SYann Gautier 1454353bb20SYann Gautier /* --------------------------------------------------------------- 1464353bb20SYann Gautier * int console_core_putc(int c, uintptr_t base_addr) 1474353bb20SYann Gautier * 1484353bb20SYann Gautier * Function to output a character over the console. It returns the 1494353bb20SYann Gautier * character printed on success or -1 on error. 1504353bb20SYann Gautier * 1514353bb20SYann Gautier * In : r0 - character to be printed 1524353bb20SYann Gautier * r1 - console base address 1534353bb20SYann Gautier * Out : return -1 on error else return character. 1544353bb20SYann Gautier * Clobber list : r2 1554353bb20SYann Gautier * --------------------------------------------------------------- 1564353bb20SYann Gautier */ 1576d264afcSYann Gautierfunc console_stm32_core_putc 158278c34dfSYann Gautier /* Check the input parameter */ 159278c34dfSYann Gautier cmp r1, #0 160278c34dfSYann Gautier beq putc_error 161ebf851edSYann Gautier 162278c34dfSYann Gautier /* Check Transmit Data Register Empty */ 163ebf851edSYann Gautiertxe_loop: 164278c34dfSYann Gautier ldr r2, [r1, #USART_ISR] 165278c34dfSYann Gautier tst r2, #USART_ISR_TXE 166ebf851edSYann Gautier beq txe_loop 167278c34dfSYann Gautier str r0, [r1, #USART_TDR] 168278c34dfSYann Gautier /* Check transmit complete flag */ 169ebf851edSYann Gautiertc_loop: 170278c34dfSYann Gautier ldr r2, [r1, #USART_ISR] 171278c34dfSYann Gautier tst r2, #USART_ISR_TC 172ebf851edSYann Gautier beq tc_loop 173278c34dfSYann Gautier bx lr 174278c34dfSYann Gautierputc_error: 175278c34dfSYann Gautier mov r0, #-1 1764353bb20SYann Gautier bx lr 1776d264afcSYann Gautierendfunc console_stm32_core_putc 1786d264afcSYann Gautier 1796d264afcSYann Gautier /* ------------------------------------------------------------ 180c10db6deSAndre Przywara * int console_stm32_putc(int c, console_t *console) 1816d264afcSYann Gautier * Function to output a character over the console. It 1826d264afcSYann Gautier * returns the character printed on success or -1 on error. 1836d264afcSYann Gautier * In: r0 - character to be printed 1846d264afcSYann Gautier * r1 - pointer to console_t structure 1856d264afcSYann Gautier * Out : return -1 on error else return character. 1866d264afcSYann Gautier * Clobber list: r2 1876d264afcSYann Gautier * ------------------------------------------------------------ 1886d264afcSYann Gautier */ 1896d264afcSYann Gautierfunc console_stm32_putc 1906d264afcSYann Gautier#if ENABLE_ASSERTIONS 1916d264afcSYann Gautier cmp r1, #0 1926d264afcSYann Gautier ASM_ASSERT(ne) 1936d264afcSYann Gautier#endif /* ENABLE_ASSERTIONS */ 194c10db6deSAndre Przywara ldr r1, [r1, #CONSOLE_T_BASE] 1956d264afcSYann Gautier b console_stm32_core_putc 1966d264afcSYann Gautierendfunc console_stm32_putc 1974353bb20SYann Gautier 1984353bb20SYann Gautier /* ----------------------------------------------------------- 1994353bb20SYann Gautier * int console_core_getc(uintptr_t base_addr) 2004353bb20SYann Gautier * 2014353bb20SYann Gautier * Function to get a character from the console. 2024353bb20SYann Gautier * It returns the character grabbed on success or -1 on error. 2034353bb20SYann Gautier * 2044353bb20SYann Gautier * In : r0 - console base address 2054353bb20SYann Gautier * Out : return -1. 2064353bb20SYann Gautier * Clobber list : r0, r1 2074353bb20SYann Gautier * ----------------------------------------------------------- 2084353bb20SYann Gautier */ 2096d264afcSYann Gautierfunc console_stm32_core_getc 2104353bb20SYann Gautier /* Not supported */ 2114353bb20SYann Gautier mov r0, #-1 2124353bb20SYann Gautier bx lr 2136d264afcSYann Gautierendfunc console_stm32_core_getc 2144353bb20SYann Gautier 2154353bb20SYann Gautier /* --------------------------------------------------------------- 216831b0e98SJimmy Brisson * void console_core_flush(uintptr_t base_addr) 2174353bb20SYann Gautier * 2184353bb20SYann Gautier * Function to force a write of all buffered data that hasn't been 2194353bb20SYann Gautier * output. 2204353bb20SYann Gautier * 2214353bb20SYann Gautier * In : r0 - console base address 222831b0e98SJimmy Brisson * Out : void. 2234353bb20SYann Gautier * Clobber list : r0, r1 2244353bb20SYann Gautier * --------------------------------------------------------------- 2254353bb20SYann Gautier */ 2266d264afcSYann Gautierfunc console_stm32_core_flush 227831b0e98SJimmy Brisson#if ENABLE_ASSERTIONS 228278c34dfSYann Gautier cmp r0, #0 229831b0e98SJimmy Brisson ASM_ASSERT(ne) 230831b0e98SJimmy Brisson#endif /* ENABLE_ASSERTIONS */ 231278c34dfSYann Gautier /* Check Transmit Data Register Empty */ 232278c34dfSYann Gautiertxe_loop_3: 233278c34dfSYann Gautier ldr r1, [r0, #USART_ISR] 234278c34dfSYann Gautier tst r1, #USART_ISR_TXE 235278c34dfSYann Gautier beq txe_loop_3 2364353bb20SYann Gautier bx lr 2376d264afcSYann Gautierendfunc console_stm32_core_flush 2386d264afcSYann Gautier 2396d264afcSYann Gautier /* ------------------------------------------------------ 240831b0e98SJimmy Brisson * void console_stm32_flush(console_t *console) 2416d264afcSYann Gautier * Function to force a write of all buffered 2426d264afcSYann Gautier * data that hasn't been output. 2436d264afcSYann Gautier * In : r0 - pointer to console_t structure 244831b0e98SJimmy Brisson * Out : void. 2456d264afcSYann Gautier * Clobber list: r0, r1 2466d264afcSYann Gautier * ------------------------------------------------------ 2476d264afcSYann Gautier */ 2486d264afcSYann Gautierfunc console_stm32_flush 2496d264afcSYann Gautier#if ENABLE_ASSERTIONS 2506d264afcSYann Gautier cmp r0, #0 2516d264afcSYann Gautier ASM_ASSERT(ne) 2526d264afcSYann Gautier#endif /* ENABLE_ASSERTIONS */ 253c10db6deSAndre Przywara ldr r0, [r0, #CONSOLE_T_BASE] 2546d264afcSYann Gautier b console_stm32_core_flush 2556d264afcSYann Gautierendfunc console_stm32_flush 256