14353bb20SYann Gautier/* 24353bb20SYann Gautier * Copyright (c) 2018, 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> 7*6d264afcSYann Gautier#include <assert_macros.S> 8*6d264afcSYann Gautier#define USE_FINISH_CONSOLE_REG_2 9*6d264afcSYann Gautier#include <console_macros.S> 10*6d264afcSYann Gautier#include <stm32_console.h> 118244d226SYann Gautier#include <stm32_uart_regs.h> 124353bb20SYann Gautier 13278c34dfSYann Gautier#define USART_TIMEOUT 0x1000 14278c34dfSYann Gautier 15*6d264afcSYann Gautier /* 16*6d264afcSYann Gautier * "core" functions are low-level implementations that don't require 17*6d264afcSYann Gautier * writeable memory and are thus safe to call in BL1 crash context. 18*6d264afcSYann Gautier */ 19*6d264afcSYann Gautier .globl console_stm32_core_init 20*6d264afcSYann Gautier .globl console_stm32_core_putc 21*6d264afcSYann Gautier .globl console_stm32_core_getc 22*6d264afcSYann Gautier .globl console_stm32_core_flush 23*6d264afcSYann Gautier 24*6d264afcSYann Gautier .globl console_stm32_putc 25*6d264afcSYann Gautier .globl console_stm32_flush 26*6d264afcSYann Gautier 27*6d264afcSYann Gautier 284353bb20SYann Gautier 294353bb20SYann Gautier /* ----------------------------------------------------------------- 304353bb20SYann Gautier * int console_core_init(uintptr_t base_addr, 314353bb20SYann Gautier * unsigned int uart_clk, 324353bb20SYann Gautier * unsigned int baud_rate) 334353bb20SYann Gautier * 344353bb20SYann Gautier * Function to initialize the console without a C Runtime to print 354353bb20SYann Gautier * debug information. This function will be accessed by console_init 364353bb20SYann Gautier * and crash reporting. 374353bb20SYann Gautier * 384353bb20SYann Gautier * In: r0 - console base address 394353bb20SYann Gautier * r1 - Uart clock in Hz 404353bb20SYann Gautier * r2 - Baud rate 414353bb20SYann Gautier * Out: return 1 on success else 0 on error 424353bb20SYann Gautier * Clobber list : r1, r2, r3 434353bb20SYann Gautier * ----------------------------------------------------------------- 444353bb20SYann Gautier */ 45*6d264afcSYann Gautierfunc console_stm32_core_init 46278c34dfSYann Gautier /* Check the input base address */ 47278c34dfSYann Gautier cmp r0, #0 48278c34dfSYann Gautier beq core_init_fail 49278c34dfSYann Gautier#if defined(IMAGE_BL2) 50278c34dfSYann Gautier /* Check baud rate and uart clock for sanity */ 51278c34dfSYann Gautier cmp r1, #0 52278c34dfSYann Gautier beq core_init_fail 53278c34dfSYann Gautier cmp r2, #0 54278c34dfSYann Gautier beq core_init_fail 55278c34dfSYann Gautier /* Disable UART */ 56278c34dfSYann Gautier ldr r3, [r0, #USART_CR1] 57278c34dfSYann Gautier bic r3, r3, #USART_CR1_UE 58278c34dfSYann Gautier str r3, [r0, #USART_CR1] 59278c34dfSYann Gautier /* Configure UART */ 60278c34dfSYann Gautier orr r3, r3, #(USART_CR1_TE | USART_CR1_FIFOEN) 61278c34dfSYann Gautier str r3, [r0, #USART_CR1] 62278c34dfSYann Gautier ldr r3, [r0, #USART_CR2] 63278c34dfSYann Gautier bic r3, r3, #USART_CR2_STOP 64278c34dfSYann Gautier str r3, [r0, #USART_CR2] 65278c34dfSYann Gautier /* Divisor = (Uart clock + (baudrate / 2)) / baudrate */ 66278c34dfSYann Gautier lsl r3, r2, #1 67278c34dfSYann Gautier add r3, r1, r3 68278c34dfSYann Gautier udiv r3, r3, r2 69278c34dfSYann Gautier str r3, [r0, #USART_BRR] 70278c34dfSYann Gautier /* Enable UART */ 71278c34dfSYann Gautier ldr r3, [r0, #USART_CR1] 72278c34dfSYann Gautier orr r3, r3, #USART_CR1_UE 73278c34dfSYann Gautier str r3, [r0, #USART_CR1] 74278c34dfSYann Gautier /* Check TEACK bit */ 75278c34dfSYann Gautier mov r2, #USART_TIMEOUT 76278c34dfSYann Gautierteack_loop: 77278c34dfSYann Gautier subs r2, r2, #1 78278c34dfSYann Gautier beq core_init_fail 79278c34dfSYann Gautier ldr r3, [r0, #USART_ISR] 80278c34dfSYann Gautier tst r3, #USART_ISR_TEACK 81278c34dfSYann Gautier beq teack_loop 82278c34dfSYann Gautier#endif /* IMAGE_BL2 */ 83278c34dfSYann Gautier mov r0, #1 84278c34dfSYann Gautier bx lr 85278c34dfSYann Gautiercore_init_fail: 86278c34dfSYann Gautier mov r0, #0 874353bb20SYann Gautier bx lr 88*6d264afcSYann Gautierendfunc console_stm32_core_init 89*6d264afcSYann Gautier 90*6d264afcSYann Gautier#if MULTI_CONSOLE_API 91*6d264afcSYann Gautier .globl console_stm32_register 92*6d264afcSYann Gautier 93*6d264afcSYann Gautier /* ------------------------------------------------------- 94*6d264afcSYann Gautier * int console_stm32_register(uintptr_t baseaddr, 95*6d264afcSYann Gautier * uint32_t clock, uint32_t baud, 96*6d264afcSYann Gautier * struct console_stm32 *console); 97*6d264afcSYann Gautier * Function to initialize and register a new STM32 98*6d264afcSYann Gautier * console. Storage passed in for the console struct 99*6d264afcSYann Gautier * *must* be persistent (i.e. not from the stack). 100*6d264afcSYann Gautier * In: r0 - UART register base address 101*6d264afcSYann Gautier * r1 - UART clock in Hz 102*6d264afcSYann Gautier * r2 - Baud rate 103*6d264afcSYann Gautier * r3 - pointer to empty console_stm32 struct 104*6d264afcSYann Gautier * Out: return 1 on success, 0 on error 105*6d264afcSYann Gautier * Clobber list : r0, r1, r2 106*6d264afcSYann Gautier * ------------------------------------------------------- 107*6d264afcSYann Gautier */ 108*6d264afcSYann Gautierfunc console_stm32_register 109*6d264afcSYann Gautier push {r4, lr} 110*6d264afcSYann Gautier mov r4, r3 111*6d264afcSYann Gautier cmp r4, #0 112*6d264afcSYann Gautier beq register_fail 113*6d264afcSYann Gautier str r0, [r4, #CONSOLE_T_STM32_BASE] 114*6d264afcSYann Gautier 115*6d264afcSYann Gautier bl console_stm32_core_init 116*6d264afcSYann Gautier cmp r0, #0 117*6d264afcSYann Gautier beq register_fail 118*6d264afcSYann Gautier 119*6d264afcSYann Gautier mov r0, r4 120*6d264afcSYann Gautier pop {r4, lr} 121*6d264afcSYann Gautier finish_console_register stm32 putc=1, getc=0, flush=1 122*6d264afcSYann Gautier 123*6d264afcSYann Gautierregister_fail: 124*6d264afcSYann Gautier pop {r4, pc} 125*6d264afcSYann Gautierendfunc console_stm32_register 126*6d264afcSYann Gautier#else 127*6d264afcSYann Gautier .globl console_core_init 128*6d264afcSYann Gautier .globl console_core_putc 129*6d264afcSYann Gautier .globl console_core_getc 130*6d264afcSYann Gautier .globl console_core_flush 131*6d264afcSYann Gautier .equ console_core_init, console_stm32_core_init 132*6d264afcSYann Gautier .equ console_core_putc, console_stm32_core_putc 133*6d264afcSYann Gautier .equ console_core_getc, console_stm32_core_getc 134*6d264afcSYann Gautier .equ console_core_flush, console_stm32_core_flush 135*6d264afcSYann Gautier#endif 1364353bb20SYann Gautier 1374353bb20SYann Gautier /* --------------------------------------------------------------- 1384353bb20SYann Gautier * int console_core_putc(int c, uintptr_t base_addr) 1394353bb20SYann Gautier * 1404353bb20SYann Gautier * Function to output a character over the console. It returns the 1414353bb20SYann Gautier * character printed on success or -1 on error. 1424353bb20SYann Gautier * 1434353bb20SYann Gautier * In : r0 - character to be printed 1444353bb20SYann Gautier * r1 - console base address 1454353bb20SYann Gautier * Out : return -1 on error else return character. 1464353bb20SYann Gautier * Clobber list : r2 1474353bb20SYann Gautier * --------------------------------------------------------------- 1484353bb20SYann Gautier */ 149*6d264afcSYann Gautierfunc console_stm32_core_putc 150278c34dfSYann Gautier /* Check the input parameter */ 151278c34dfSYann Gautier cmp r1, #0 152278c34dfSYann Gautier beq putc_error 153278c34dfSYann Gautier /* Prepend '\r' to '\n' */ 154278c34dfSYann Gautier cmp r0, #0xA 155278c34dfSYann Gautier bne 2f 156278c34dfSYann Gautier1: 157278c34dfSYann Gautier /* Check Transmit Data Register Empty */ 158278c34dfSYann Gautiertxe_loop_1: 159278c34dfSYann Gautier ldr r2, [r1, #USART_ISR] 160278c34dfSYann Gautier tst r2, #USART_ISR_TXE 161278c34dfSYann Gautier beq txe_loop_1 162278c34dfSYann Gautier mov r2, #0xD 163278c34dfSYann Gautier str r2, [r1, #USART_TDR] 164278c34dfSYann Gautier /* Check transmit complete flag */ 165278c34dfSYann Gautiertc_loop_1: 166278c34dfSYann Gautier ldr r2, [r1, #USART_ISR] 167278c34dfSYann Gautier tst r2, #USART_ISR_TC 168278c34dfSYann Gautier beq tc_loop_1 169278c34dfSYann Gautier2: 170278c34dfSYann Gautier /* Check Transmit Data Register Empty */ 171278c34dfSYann Gautiertxe_loop_2: 172278c34dfSYann Gautier ldr r2, [r1, #USART_ISR] 173278c34dfSYann Gautier tst r2, #USART_ISR_TXE 174278c34dfSYann Gautier beq txe_loop_2 175278c34dfSYann Gautier str r0, [r1, #USART_TDR] 176278c34dfSYann Gautier /* Check transmit complete flag */ 177278c34dfSYann Gautiertc_loop_2: 178278c34dfSYann Gautier ldr r2, [r1, #USART_ISR] 179278c34dfSYann Gautier tst r2, #USART_ISR_TC 180278c34dfSYann Gautier beq tc_loop_2 181278c34dfSYann Gautier bx lr 182278c34dfSYann Gautierputc_error: 183278c34dfSYann Gautier mov r0, #-1 1844353bb20SYann Gautier bx lr 185*6d264afcSYann Gautierendfunc console_stm32_core_putc 186*6d264afcSYann Gautier 187*6d264afcSYann Gautier /* ------------------------------------------------------------ 188*6d264afcSYann Gautier * int console_stm32_putc(int c, struct console_stm32 *console) 189*6d264afcSYann Gautier * Function to output a character over the console. It 190*6d264afcSYann Gautier * returns the character printed on success or -1 on error. 191*6d264afcSYann Gautier * In: r0 - character to be printed 192*6d264afcSYann Gautier * r1 - pointer to console_t structure 193*6d264afcSYann Gautier * Out : return -1 on error else return character. 194*6d264afcSYann Gautier * Clobber list: r2 195*6d264afcSYann Gautier * ------------------------------------------------------------ 196*6d264afcSYann Gautier */ 197*6d264afcSYann Gautierfunc console_stm32_putc 198*6d264afcSYann Gautier#if ENABLE_ASSERTIONS 199*6d264afcSYann Gautier cmp r1, #0 200*6d264afcSYann Gautier ASM_ASSERT(ne) 201*6d264afcSYann Gautier#endif /* ENABLE_ASSERTIONS */ 202*6d264afcSYann Gautier ldr r1, [r1, #CONSOLE_T_STM32_BASE] 203*6d264afcSYann Gautier b console_stm32_core_putc 204*6d264afcSYann Gautierendfunc console_stm32_putc 2054353bb20SYann Gautier 2064353bb20SYann Gautier /* ----------------------------------------------------------- 2074353bb20SYann Gautier * int console_core_getc(uintptr_t base_addr) 2084353bb20SYann Gautier * 2094353bb20SYann Gautier * Function to get a character from the console. 2104353bb20SYann Gautier * It returns the character grabbed on success or -1 on error. 2114353bb20SYann Gautier * 2124353bb20SYann Gautier * In : r0 - console base address 2134353bb20SYann Gautier * Out : return -1. 2144353bb20SYann Gautier * Clobber list : r0, r1 2154353bb20SYann Gautier * ----------------------------------------------------------- 2164353bb20SYann Gautier */ 217*6d264afcSYann Gautierfunc console_stm32_core_getc 2184353bb20SYann Gautier /* Not supported */ 2194353bb20SYann Gautier mov r0, #-1 2204353bb20SYann Gautier bx lr 221*6d264afcSYann Gautierendfunc console_stm32_core_getc 2224353bb20SYann Gautier 2234353bb20SYann Gautier /* --------------------------------------------------------------- 2244353bb20SYann Gautier * int console_core_flush(uintptr_t base_addr) 2254353bb20SYann Gautier * 2264353bb20SYann Gautier * Function to force a write of all buffered data that hasn't been 2274353bb20SYann Gautier * output. 2284353bb20SYann Gautier * 2294353bb20SYann Gautier * In : r0 - console base address 2304353bb20SYann Gautier * Out : return -1 on error else return 0. 2314353bb20SYann Gautier * Clobber list : r0, r1 2324353bb20SYann Gautier * --------------------------------------------------------------- 2334353bb20SYann Gautier */ 234*6d264afcSYann Gautierfunc console_stm32_core_flush 235278c34dfSYann Gautier cmp r0, #0 236278c34dfSYann Gautier beq flush_error 237278c34dfSYann Gautier /* Check Transmit Data Register Empty */ 238278c34dfSYann Gautiertxe_loop_3: 239278c34dfSYann Gautier ldr r1, [r0, #USART_ISR] 240278c34dfSYann Gautier tst r1, #USART_ISR_TXE 241278c34dfSYann Gautier beq txe_loop_3 242278c34dfSYann Gautier mov r0, #0 243278c34dfSYann Gautier bx lr 244278c34dfSYann Gautierflush_error: 245278c34dfSYann Gautier mov r0, #-1 2464353bb20SYann Gautier bx lr 247*6d264afcSYann Gautierendfunc console_stm32_core_flush 248*6d264afcSYann Gautier 249*6d264afcSYann Gautier /* ------------------------------------------------------ 250*6d264afcSYann Gautier * int console_stm32_flush(struct console_stm32 *console) 251*6d264afcSYann Gautier * Function to force a write of all buffered 252*6d264afcSYann Gautier * data that hasn't been output. 253*6d264afcSYann Gautier * In : r0 - pointer to console_t structure 254*6d264afcSYann Gautier * Out : return -1 on error else return 0. 255*6d264afcSYann Gautier * Clobber list: r0, r1 256*6d264afcSYann Gautier * ------------------------------------------------------ 257*6d264afcSYann Gautier */ 258*6d264afcSYann Gautierfunc console_stm32_flush 259*6d264afcSYann Gautier#if ENABLE_ASSERTIONS 260*6d264afcSYann Gautier cmp r0, #0 261*6d264afcSYann Gautier ASM_ASSERT(ne) 262*6d264afcSYann Gautier#endif /* ENABLE_ASSERTIONS */ 263*6d264afcSYann Gautier ldr r0, [r0, #CONSOLE_T_STM32_BASE] 264*6d264afcSYann Gautier b console_stm32_core_flush 265*6d264afcSYann Gautierendfunc console_stm32_flush 266