1/* 2 * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6#include <asm_macros.S> 7#include <assert_macros.S> 8#include <console_macros.S> 9#include <drivers/st/stm32_console.h> 10#include <drivers/st/stm32_uart_regs.h> 11 12#define USART_TIMEOUT 0x1000 13 14 /* 15 * "core" functions are low-level implementations that don't require 16 * writeable memory and are thus safe to call in BL1 crash context. 17 */ 18 .globl console_stm32_core_init 19 .globl console_stm32_core_putc 20 .globl console_stm32_core_getc 21 .globl console_stm32_core_flush 22 23 .globl console_stm32_putc 24 .globl console_stm32_flush 25 26 27 28 /* ----------------------------------------------------------------- 29 * int console_core_init(uintptr_t base_addr, 30 * unsigned int uart_clk, 31 * unsigned int baud_rate) 32 * 33 * Function to initialize the console without a C Runtime to print 34 * debug information. This function will be accessed by console_init 35 * and crash reporting. 36 * 37 * In: r0 - console base address 38 * r1 - Uart clock in Hz 39 * r2 - Baud rate 40 * Out: return 1 on success else 0 on error 41 * Clobber list : r1, r2, r3 42 * ----------------------------------------------------------------- 43 */ 44func console_stm32_core_init 45 /* Check the input base address */ 46 cmp r0, #0 47 beq core_init_fail 48#if !defined(IMAGE_BL2) 49 /* Skip UART initialization if it is already enabled */ 50 ldr r3, [r0, #USART_CR1] 51 ands r3, r3, #USART_CR1_UE 52 bne 1f 53#endif /* IMAGE_BL2 */ 54 /* Check baud rate and uart clock for sanity */ 55 cmp r1, #0 56 beq core_init_fail 57 cmp r2, #0 58 beq core_init_fail 59 /* Disable UART */ 60 ldr r3, [r0, #USART_CR1] 61 bic r3, r3, #USART_CR1_UE 62 str r3, [r0, #USART_CR1] 63 /* Configure UART */ 64 orr r3, r3, #(USART_CR1_TE | USART_CR1_FIFOEN) 65 str r3, [r0, #USART_CR1] 66 ldr r3, [r0, #USART_CR2] 67 bic r3, r3, #USART_CR2_STOP 68 str r3, [r0, #USART_CR2] 69 /* Divisor = (Uart clock + (baudrate / 2)) / baudrate */ 70 lsr r3, r2, #1 71 add r3, r1, r3 72 udiv r3, r3, r2 73 cmp r3, #16 74 bhi 2f 75 /* Oversampling 8 */ 76 /* Divisor = (2 * Uart clock + (baudrate / 2)) / baudrate */ 77 lsr r3, r2, #1 78 add r3, r3, r1, lsl #1 79 udiv r3, r3, r2 80 and r1, r3, #USART_BRR_DIV_FRACTION 81 lsr r1, r1, #1 82 bic r3, r3, #USART_BRR_DIV_FRACTION 83 orr r3, r3, r1 84 ldr r1, [r0, #USART_CR1] 85 orr r1, r1, #USART_CR1_OVER8 86 str r1, [r0, #USART_CR1] 872: 88 str r3, [r0, #USART_BRR] 89 /* Enable UART */ 90 ldr r3, [r0, #USART_CR1] 91 orr r3, r3, #USART_CR1_UE 92 str r3, [r0, #USART_CR1] 93 /* Check TEACK bit */ 94 mov r2, #USART_TIMEOUT 95teack_loop: 96 subs r2, r2, #1 97 beq core_init_fail 98 ldr r3, [r0, #USART_ISR] 99 tst r3, #USART_ISR_TEACK 100 beq teack_loop 1011: 102 mov r0, #1 103 bx lr 104core_init_fail: 105 mov r0, #0 106 bx lr 107endfunc console_stm32_core_init 108 109 .globl console_stm32_register 110 111 /* ------------------------------------------------------- 112 * int console_stm32_register(uintptr_t baseaddr, 113 * uint32_t clock, uint32_t baud, 114 * console_t *console); 115 * Function to initialize and register a new STM32 116 * console. Storage passed in for the console struct 117 * *must* be persistent (i.e. not from the stack). 118 * In: r0 - UART register base address 119 * r1 - UART clock in Hz 120 * r2 - Baud rate 121 * r3 - pointer to empty console_t struct 122 * Out: return 1 on success, 0 on error 123 * Clobber list : r0, r1, r2 124 * ------------------------------------------------------- 125 */ 126func console_stm32_register 127 push {r4, lr} 128 mov r4, r3 129 cmp r4, #0 130 beq register_fail 131 str r0, [r4, #CONSOLE_T_BASE] 132 133 bl console_stm32_core_init 134 cmp r0, #0 135 beq register_fail 136 137 mov r0, r4 138 pop {r4, lr} 139 finish_console_register stm32 putc=1, getc=0, flush=1 140 141register_fail: 142 pop {r4, pc} 143endfunc console_stm32_register 144 145 /* --------------------------------------------------------------- 146 * int console_core_putc(int c, uintptr_t base_addr) 147 * 148 * Function to output a character over the console. It returns the 149 * character printed on success or -1 on error. 150 * 151 * In : r0 - character to be printed 152 * r1 - console base address 153 * Out : return -1 on error else return character. 154 * Clobber list : r2 155 * --------------------------------------------------------------- 156 */ 157func console_stm32_core_putc 158 /* Check the input parameter */ 159 cmp r1, #0 160 beq putc_error 161 162 /* Check Transmit Data Register Empty */ 163txe_loop: 164 ldr r2, [r1, #USART_ISR] 165 tst r2, #USART_ISR_TXE 166 beq txe_loop 167 str r0, [r1, #USART_TDR] 168 /* Check transmit complete flag */ 169tc_loop: 170 ldr r2, [r1, #USART_ISR] 171 tst r2, #USART_ISR_TC 172 beq tc_loop 173 bx lr 174putc_error: 175 mov r0, #-1 176 bx lr 177endfunc console_stm32_core_putc 178 179 /* ------------------------------------------------------------ 180 * int console_stm32_putc(int c, console_t *console) 181 * Function to output a character over the console. It 182 * returns the character printed on success or -1 on error. 183 * In: r0 - character to be printed 184 * r1 - pointer to console_t structure 185 * Out : return -1 on error else return character. 186 * Clobber list: r2 187 * ------------------------------------------------------------ 188 */ 189func console_stm32_putc 190#if ENABLE_ASSERTIONS 191 cmp r1, #0 192 ASM_ASSERT(ne) 193#endif /* ENABLE_ASSERTIONS */ 194 ldr r1, [r1, #CONSOLE_T_BASE] 195 b console_stm32_core_putc 196endfunc console_stm32_putc 197 198 /* ----------------------------------------------------------- 199 * int console_core_getc(uintptr_t base_addr) 200 * 201 * Function to get a character from the console. 202 * It returns the character grabbed on success or -1 on error. 203 * 204 * In : r0 - console base address 205 * Out : return -1. 206 * Clobber list : r0, r1 207 * ----------------------------------------------------------- 208 */ 209func console_stm32_core_getc 210 /* Not supported */ 211 mov r0, #-1 212 bx lr 213endfunc console_stm32_core_getc 214 215 /* --------------------------------------------------------------- 216 * void console_core_flush(uintptr_t base_addr) 217 * 218 * Function to force a write of all buffered data that hasn't been 219 * output. 220 * 221 * In : r0 - console base address 222 * Out : void. 223 * Clobber list : r0, r1 224 * --------------------------------------------------------------- 225 */ 226func console_stm32_core_flush 227#if ENABLE_ASSERTIONS 228 cmp r0, #0 229 ASM_ASSERT(ne) 230#endif /* ENABLE_ASSERTIONS */ 231 /* Check Transmit Data Register Empty */ 232txe_loop_3: 233 ldr r1, [r0, #USART_ISR] 234 tst r1, #USART_ISR_TXE 235 beq txe_loop_3 236 bx lr 237endfunc console_stm32_core_flush 238 239 /* ------------------------------------------------------ 240 * void console_stm32_flush(console_t *console) 241 * Function to force a write of all buffered 242 * data that hasn't been output. 243 * In : r0 - pointer to console_t structure 244 * Out : void. 245 * Clobber list: r0, r1 246 * ------------------------------------------------------ 247 */ 248func console_stm32_flush 249#if ENABLE_ASSERTIONS 250 cmp r0, #0 251 ASM_ASSERT(ne) 252#endif /* ENABLE_ASSERTIONS */ 253 ldr r0, [r0, #CONSOLE_T_BASE] 254 b console_stm32_core_flush 255endfunc console_stm32_flush 256