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