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