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