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 ret 174endfunc console_stm32_core_putc 175 176 /* -------------------------------------------------------- 177 * int console_stm32_putc(int c, console_t *console) 178 * Function to output a character over the console. It 179 * returns the character printed on success or -1 on error. 180 * In : w0 - character to be printed 181 * x1 - pointer to console_t structure 182 * Out : return -1 on error else return character. 183 * Clobber list : x2 184 * -------------------------------------------------------- 185 */ 186func console_stm32_putc 187#if ENABLE_ASSERTIONS 188 cmp x1, #0 189 ASM_ASSERT(ne) 190#endif /* ENABLE_ASSERTIONS */ 191 ldr x1, [x1, #CONSOLE_T_BASE] 192 b console_stm32_core_putc 193endfunc console_stm32_putc 194 195 /* --------------------------------------------- 196 * int console_stm32_core_getc(uintptr_t base_addr) 197 * Function to get a character from the console. 198 * It returns the character grabbed on success 199 * or -1 if no character is available. 200 * In : x0 - console base address 201 * Out: w0 - character if available, else -1 202 * Clobber list : x0, x1 203 * --------------------------------------------- 204 */ 205func console_stm32_core_getc 206 /* Not supported */ 207 mov w0, #-1 208 ret 209endfunc console_stm32_core_getc 210 211 /* --------------------------------------------- 212 * void console_stm32_core_flush(uintptr_t base_addr) 213 * Function to force a write of all buffered 214 * data that hasn't been output. 215 * In : x0 - console base address 216 * Out : void. 217 * Clobber list : x0, x1 218 * --------------------------------------------- 219 */ 220func console_stm32_core_flush 221#if ENABLE_ASSERTIONS 222 cmp x0, #0 223 ASM_ASSERT(ne) 224#endif /* ENABLE_ASSERTIONS */ 225 /* Check Transmission Complete flag */ 226tc_loop: 227 ldr w1, [x0, #USART_ISR] 228 tst w1, #USART_ISR_TC 229 beq tc_loop 230 ret 231endfunc console_stm32_core_flush 232 233 /* --------------------------------------------- 234 * void console_stm32_flush(console_t *console) 235 * Function to force a write of all buffered 236 * data that hasn't been output. 237 * In : x0 - pointer to console_t structure 238 * Out : void 239 * Clobber list : x0, x1 240 * --------------------------------------------- 241 */ 242func console_stm32_flush 243#if ENABLE_ASSERTIONS 244 cmp x0, #0 245 ASM_ASSERT(ne) 246#endif /* ENABLE_ASSERTIONS */ 247 ldr x0, [x0, #CONSOLE_T_BASE] 248 b console_stm32_core_flush 249endfunc console_stm32_flush 250