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#if STM32MP_RECONFIGURE_CONSOLE 50 /* UART clock rate is set to 0 in BL32, skip init in that case */ 51 cmp r1, #0 52 beq 1f 53#else /* STM32MP_RECONFIGURE_CONSOLE */ 54 /* Skip UART initialization if it is already enabled */ 55 ldr r3, [r0, #USART_CR1] 56 ands r3, r3, #USART_CR1_UE 57 bne 1f 58#endif /* STM32MP_RECONFIGURE_CONSOLE */ 59#endif /* IMAGE_BL2 */ 60 /* Check baud rate and uart clock for sanity */ 61 cmp r1, #0 62 beq core_init_fail 63 cmp r2, #0 64 beq core_init_fail 65 /* Disable UART */ 66 ldr r3, [r0, #USART_CR1] 67 bic r3, r3, #USART_CR1_UE 68 str r3, [r0, #USART_CR1] 69 /* Configure UART */ 70 orr r3, r3, #(USART_CR1_TE | USART_CR1_FIFOEN) 71 str r3, [r0, #USART_CR1] 72 ldr r3, [r0, #USART_CR2] 73 bic r3, r3, #USART_CR2_STOP 74 str r3, [r0, #USART_CR2] 75 /* Divisor = (Uart clock + (baudrate / 2)) / baudrate */ 76 lsr r3, r2, #1 77 add r3, r1, r3 78 udiv r3, r3, r2 79 cmp r3, #16 80 bhi 2f 81 /* Oversampling 8 */ 82 /* Divisor = (2 * Uart clock + (baudrate / 2)) / baudrate */ 83 lsr r3, r2, #1 84 add r3, r3, r1, lsl #1 85 udiv r3, r3, r2 86 and r1, r3, #USART_BRR_DIV_FRACTION 87 lsr r1, r1, #1 88 bic r3, r3, #USART_BRR_DIV_FRACTION 89 orr r3, r3, r1 90 ldr r1, [r0, #USART_CR1] 91 orr r1, r1, #USART_CR1_OVER8 92 str r1, [r0, #USART_CR1] 932: 94 str r3, [r0, #USART_BRR] 95 /* Enable UART */ 96 ldr r3, [r0, #USART_CR1] 97 orr r3, r3, #USART_CR1_UE 98 str r3, [r0, #USART_CR1] 99 /* Check TEACK bit */ 100 mov r2, #USART_TIMEOUT 101teack_loop: 102 subs r2, r2, #1 103 beq core_init_fail 104 ldr r3, [r0, #USART_ISR] 105 tst r3, #USART_ISR_TEACK 106 beq teack_loop 1071: 108 mov r0, #1 109 bx lr 110core_init_fail: 111 mov r0, #0 112 bx lr 113endfunc console_stm32_core_init 114 115 .globl console_stm32_register 116 117 /* ------------------------------------------------------- 118 * int console_stm32_register(uintptr_t baseaddr, 119 * uint32_t clock, uint32_t baud, 120 * console_t *console); 121 * Function to initialize and register a new STM32 122 * console. Storage passed in for the console struct 123 * *must* be persistent (i.e. not from the stack). 124 * In: r0 - UART register base address 125 * r1 - UART clock in Hz 126 * r2 - Baud rate 127 * r3 - pointer to empty console_t struct 128 * Out: return 1 on success, 0 on error 129 * Clobber list : r0, r1, r2 130 * ------------------------------------------------------- 131 */ 132func console_stm32_register 133 push {r4, lr} 134 mov r4, r3 135 cmp r4, #0 136 beq register_fail 137 str r0, [r4, #CONSOLE_T_BASE] 138 139 bl console_stm32_core_init 140 cmp r0, #0 141 beq register_fail 142 143 mov r0, r4 144 pop {r4, lr} 145 finish_console_register stm32 putc=1, getc=0, flush=1 146 147register_fail: 148 pop {r4, pc} 149endfunc console_stm32_register 150 151 /* --------------------------------------------------------------- 152 * int console_core_putc(int c, uintptr_t base_addr) 153 * 154 * Function to output a character over the console. It returns the 155 * character printed on success or -1 on error. 156 * 157 * In : r0 - character to be printed 158 * r1 - console base address 159 * Out : return -1 on error else return character. 160 * Clobber list : r2 161 * --------------------------------------------------------------- 162 */ 163func console_stm32_core_putc 164 /* Check the input parameter */ 165 cmp r1, #0 166 beq putc_error 167 168 /* Check Transmit Data Register Empty */ 169txe_loop: 170 ldr r2, [r1, #USART_ISR] 171 tst r2, #USART_ISR_TXE 172 beq txe_loop 173 str r0, [r1, #USART_TDR] 174 /* Check transmit complete flag */ 175tc_loop: 176 ldr r2, [r1, #USART_ISR] 177 tst r2, #USART_ISR_TC 178 beq tc_loop 179 bx lr 180putc_error: 181 mov r0, #-1 182 bx lr 183endfunc console_stm32_core_putc 184 185 /* ------------------------------------------------------------ 186 * int console_stm32_putc(int c, console_t *console) 187 * Function to output a character over the console. It 188 * returns the character printed on success or -1 on error. 189 * In: r0 - character to be printed 190 * r1 - pointer to console_t structure 191 * Out : return -1 on error else return character. 192 * Clobber list: r2 193 * ------------------------------------------------------------ 194 */ 195func console_stm32_putc 196#if ENABLE_ASSERTIONS 197 cmp r1, #0 198 ASM_ASSERT(ne) 199#endif /* ENABLE_ASSERTIONS */ 200 ldr r1, [r1, #CONSOLE_T_BASE] 201 b console_stm32_core_putc 202endfunc console_stm32_putc 203 204 /* ----------------------------------------------------------- 205 * int console_core_getc(uintptr_t base_addr) 206 * 207 * Function to get a character from the console. 208 * It returns the character grabbed on success or -1 on error. 209 * 210 * In : r0 - console base address 211 * Out : return -1. 212 * Clobber list : r0, r1 213 * ----------------------------------------------------------- 214 */ 215func console_stm32_core_getc 216 /* Not supported */ 217 mov r0, #-1 218 bx lr 219endfunc console_stm32_core_getc 220 221 /* --------------------------------------------------------------- 222 * void console_core_flush(uintptr_t base_addr) 223 * 224 * Function to force a write of all buffered data that hasn't been 225 * output. 226 * 227 * In : r0 - console base address 228 * Out : void. 229 * Clobber list : r0, r1 230 * --------------------------------------------------------------- 231 */ 232func console_stm32_core_flush 233#if ENABLE_ASSERTIONS 234 cmp r0, #0 235 ASM_ASSERT(ne) 236#endif /* ENABLE_ASSERTIONS */ 237 /* Check Transmit Data Register Empty */ 238txe_loop_3: 239 ldr r1, [r0, #USART_ISR] 240 tst r1, #USART_ISR_TXE 241 beq txe_loop_3 242 bx lr 243endfunc console_stm32_core_flush 244 245 /* ------------------------------------------------------ 246 * void console_stm32_flush(console_t *console) 247 * Function to force a write of all buffered 248 * data that hasn't been output. 249 * In : r0 - pointer to console_t structure 250 * Out : void. 251 * Clobber list: r0, r1 252 * ------------------------------------------------------ 253 */ 254func console_stm32_flush 255#if ENABLE_ASSERTIONS 256 cmp r0, #0 257 ASM_ASSERT(ne) 258#endif /* ENABLE_ASSERTIONS */ 259 ldr r0, [r0, #CONSOLE_T_BASE] 260 b console_stm32_core_flush 261endfunc console_stm32_flush 262