1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu #include <errno.h> 9*91f16700Schasinglulu #include <string.h> 10*91f16700Schasinglulu 11*91f16700Schasinglulu #include <common/bl_common.h> 12*91f16700Schasinglulu #include <drivers/clk.h> 13*91f16700Schasinglulu #include <drivers/delay_timer.h> 14*91f16700Schasinglulu #include <drivers/st/stm32_gpio.h> 15*91f16700Schasinglulu #include <drivers/st/stm32_uart.h> 16*91f16700Schasinglulu #include <drivers/st/stm32_uart_regs.h> 17*91f16700Schasinglulu #include <drivers/st/stm32mp_clkfunc.h> 18*91f16700Schasinglulu #include <lib/mmio.h> 19*91f16700Schasinglulu 20*91f16700Schasinglulu #include <platform_def.h> 21*91f16700Schasinglulu 22*91f16700Schasinglulu /* UART time-out value */ 23*91f16700Schasinglulu #define STM32_UART_TIMEOUT_US 20000U 24*91f16700Schasinglulu 25*91f16700Schasinglulu /* Mask to clear ALL the configuration registers */ 26*91f16700Schasinglulu 27*91f16700Schasinglulu #define STM32_UART_CR1_FIELDS \ 28*91f16700Schasinglulu (USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | \ 29*91f16700Schasinglulu USART_CR1_RE | USART_CR1_OVER8 | USART_CR1_FIFOEN) 30*91f16700Schasinglulu 31*91f16700Schasinglulu #define STM32_UART_CR2_FIELDS \ 32*91f16700Schasinglulu (USART_CR2_SLVEN | USART_CR2_DIS_NSS | USART_CR2_ADDM7 | \ 33*91f16700Schasinglulu USART_CR2_LBDL | USART_CR2_LBDIE | USART_CR2_LBCL | \ 34*91f16700Schasinglulu USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_CLKEN | \ 35*91f16700Schasinglulu USART_CR2_STOP | USART_CR2_LINEN | USART_CR2_SWAP | \ 36*91f16700Schasinglulu USART_CR2_RXINV | USART_CR2_TXINV | USART_CR2_DATAINV | \ 37*91f16700Schasinglulu USART_CR2_MSBFIRST | USART_CR2_ABREN | USART_CR2_ABRMODE | \ 38*91f16700Schasinglulu USART_CR2_RTOEN | USART_CR2_ADD) 39*91f16700Schasinglulu 40*91f16700Schasinglulu #define STM32_UART_CR3_FIELDS \ 41*91f16700Schasinglulu (USART_CR3_EIE | USART_CR3_IREN | USART_CR3_IRLP | \ 42*91f16700Schasinglulu USART_CR3_HDSEL | USART_CR3_NACK | USART_CR3_SCEN | \ 43*91f16700Schasinglulu USART_CR3_DMAR | USART_CR3_DMAT | USART_CR3_RTSE | \ 44*91f16700Schasinglulu USART_CR3_CTSE | USART_CR3_CTSIE | USART_CR3_ONEBIT | \ 45*91f16700Schasinglulu USART_CR3_OVRDIS | USART_CR3_DDRE | USART_CR3_DEM | \ 46*91f16700Schasinglulu USART_CR3_DEP | USART_CR3_SCARCNT | USART_CR3_WUS | \ 47*91f16700Schasinglulu USART_CR3_WUFIE | USART_CR3_TXFTIE | USART_CR3_TCBGTIE | \ 48*91f16700Schasinglulu USART_CR3_RXFTCFG | USART_CR3_RXFTIE | USART_CR3_TXFTCFG) 49*91f16700Schasinglulu 50*91f16700Schasinglulu #define STM32_UART_ISR_ERRORS \ 51*91f16700Schasinglulu (USART_ISR_ORE | USART_ISR_NE | USART_ISR_FE | USART_ISR_PE) 52*91f16700Schasinglulu 53*91f16700Schasinglulu static const uint16_t presc_table[STM32_UART_PRESCALER_NB] = { 54*91f16700Schasinglulu 1U, 2U, 4U, 6U, 8U, 10U, 12U, 16U, 32U, 64U, 128U, 256U 55*91f16700Schasinglulu }; 56*91f16700Schasinglulu 57*91f16700Schasinglulu /* @brief BRR division operation to set BRR register in 8-bit oversampling 58*91f16700Schasinglulu * mode. 59*91f16700Schasinglulu * @param clockfreq: UART clock. 60*91f16700Schasinglulu * @param baud_rate: Baud rate set by the user. 61*91f16700Schasinglulu * @param prescaler: UART prescaler value. 62*91f16700Schasinglulu * @retval Division result. 63*91f16700Schasinglulu */ 64*91f16700Schasinglulu static uint32_t uart_div_sampling8(unsigned long clockfreq, 65*91f16700Schasinglulu uint32_t baud_rate, 66*91f16700Schasinglulu uint32_t prescaler) 67*91f16700Schasinglulu { 68*91f16700Schasinglulu uint32_t scaled_freq = clockfreq / presc_table[prescaler]; 69*91f16700Schasinglulu 70*91f16700Schasinglulu return ((scaled_freq * 2) + (baud_rate / 2)) / baud_rate; 71*91f16700Schasinglulu 72*91f16700Schasinglulu } 73*91f16700Schasinglulu 74*91f16700Schasinglulu /* @brief BRR division operation to set BRR register in 16-bit oversampling 75*91f16700Schasinglulu * mode. 76*91f16700Schasinglulu * @param clockfreq: UART clock. 77*91f16700Schasinglulu * @param baud_rate: Baud rate set by the user. 78*91f16700Schasinglulu * @param prescaler: UART prescaler value. 79*91f16700Schasinglulu * @retval Division result. 80*91f16700Schasinglulu */ 81*91f16700Schasinglulu static uint32_t uart_div_sampling16(unsigned long clockfreq, 82*91f16700Schasinglulu uint32_t baud_rate, 83*91f16700Schasinglulu uint32_t prescaler) 84*91f16700Schasinglulu { 85*91f16700Schasinglulu uint32_t scaled_freq = clockfreq / presc_table[prescaler]; 86*91f16700Schasinglulu 87*91f16700Schasinglulu return (scaled_freq + (baud_rate / 2)) / baud_rate; 88*91f16700Schasinglulu 89*91f16700Schasinglulu } 90*91f16700Schasinglulu 91*91f16700Schasinglulu /* 92*91f16700Schasinglulu * @brief Return the UART clock frequency. 93*91f16700Schasinglulu * @param huart: UART handle. 94*91f16700Schasinglulu * @retval Frequency value in Hz. 95*91f16700Schasinglulu */ 96*91f16700Schasinglulu static unsigned long uart_get_clock_freq(struct stm32_uart_handle_s *huart) 97*91f16700Schasinglulu { 98*91f16700Schasinglulu return fdt_get_uart_clock_freq((uintptr_t)huart->base); 99*91f16700Schasinglulu } 100*91f16700Schasinglulu 101*91f16700Schasinglulu /* 102*91f16700Schasinglulu * @brief Configure the UART peripheral. 103*91f16700Schasinglulu * @param huart: UART handle. 104*91f16700Schasinglulu * @retval UART status. 105*91f16700Schasinglulu */ 106*91f16700Schasinglulu static int uart_set_config(struct stm32_uart_handle_s *huart, 107*91f16700Schasinglulu const struct stm32_uart_init_s *init) 108*91f16700Schasinglulu { 109*91f16700Schasinglulu uint32_t tmpreg; 110*91f16700Schasinglulu unsigned long clockfreq; 111*91f16700Schasinglulu unsigned long int_div; 112*91f16700Schasinglulu uint32_t brrtemp; 113*91f16700Schasinglulu uint32_t over_sampling; 114*91f16700Schasinglulu 115*91f16700Schasinglulu /*---------------------- USART BRR configuration --------------------*/ 116*91f16700Schasinglulu clockfreq = uart_get_clock_freq(huart); 117*91f16700Schasinglulu if (clockfreq == 0UL) { 118*91f16700Schasinglulu return -ENODEV; 119*91f16700Schasinglulu } 120*91f16700Schasinglulu 121*91f16700Schasinglulu int_div = clockfreq / init->baud_rate; 122*91f16700Schasinglulu if (int_div < 16U) { 123*91f16700Schasinglulu uint32_t usartdiv = uart_div_sampling8(clockfreq, 124*91f16700Schasinglulu init->baud_rate, 125*91f16700Schasinglulu init->prescaler); 126*91f16700Schasinglulu 127*91f16700Schasinglulu brrtemp = (usartdiv & USART_BRR_DIV_MANTISSA) | 128*91f16700Schasinglulu ((usartdiv & USART_BRR_DIV_FRACTION) >> 1); 129*91f16700Schasinglulu over_sampling = USART_CR1_OVER8; 130*91f16700Schasinglulu } else { 131*91f16700Schasinglulu brrtemp = uart_div_sampling16(clockfreq, 132*91f16700Schasinglulu init->baud_rate, 133*91f16700Schasinglulu init->prescaler) & 134*91f16700Schasinglulu (USART_BRR_DIV_FRACTION | USART_BRR_DIV_MANTISSA); 135*91f16700Schasinglulu over_sampling = 0x0U; 136*91f16700Schasinglulu } 137*91f16700Schasinglulu mmio_write_32(huart->base + USART_BRR, brrtemp); 138*91f16700Schasinglulu 139*91f16700Schasinglulu /* 140*91f16700Schasinglulu * ---------------------- USART CR1 Configuration -------------------- 141*91f16700Schasinglulu * Clear M, PCE, PS, TE, RE and OVER8 bits and configure 142*91f16700Schasinglulu * the UART word length, parity, mode and oversampling: 143*91f16700Schasinglulu * - set the M bits according to init->word_length value, 144*91f16700Schasinglulu * - set PCE and PS bits according to init->parity value, 145*91f16700Schasinglulu * - set TE and RE bits according to init->mode value, 146*91f16700Schasinglulu * - set OVER8 bit according baudrate and clock. 147*91f16700Schasinglulu */ 148*91f16700Schasinglulu tmpreg = init->word_length | 149*91f16700Schasinglulu init->parity | 150*91f16700Schasinglulu init->mode | 151*91f16700Schasinglulu over_sampling | 152*91f16700Schasinglulu init->fifo_mode; 153*91f16700Schasinglulu mmio_clrsetbits_32(huart->base + USART_CR1, STM32_UART_CR1_FIELDS, tmpreg); 154*91f16700Schasinglulu 155*91f16700Schasinglulu /* 156*91f16700Schasinglulu * --------------------- USART CR2 Configuration --------------------- 157*91f16700Schasinglulu * Configure the UART Stop Bits: Set STOP[13:12] bits according 158*91f16700Schasinglulu * to init->stop_bits value. 159*91f16700Schasinglulu */ 160*91f16700Schasinglulu mmio_clrsetbits_32(huart->base + USART_CR2, STM32_UART_CR2_FIELDS, 161*91f16700Schasinglulu init->stop_bits); 162*91f16700Schasinglulu 163*91f16700Schasinglulu /* 164*91f16700Schasinglulu * --------------------- USART CR3 Configuration --------------------- 165*91f16700Schasinglulu * Configure: 166*91f16700Schasinglulu * - UART HardWare Flow Control: set CTSE and RTSE bits according 167*91f16700Schasinglulu * to init->hw_flow_control value, 168*91f16700Schasinglulu * - one-bit sampling method versus three samples' majority rule 169*91f16700Schasinglulu * according to init->one_bit_sampling (not applicable to 170*91f16700Schasinglulu * LPUART), 171*91f16700Schasinglulu * - set TXFTCFG bit according to init->tx_fifo_threshold value, 172*91f16700Schasinglulu * - set RXFTCFG bit according to init->rx_fifo_threshold value. 173*91f16700Schasinglulu */ 174*91f16700Schasinglulu tmpreg = init->hw_flow_control | init->one_bit_sampling; 175*91f16700Schasinglulu 176*91f16700Schasinglulu if (init->fifo_mode == USART_CR1_FIFOEN) { 177*91f16700Schasinglulu tmpreg |= init->tx_fifo_threshold | 178*91f16700Schasinglulu init->rx_fifo_threshold; 179*91f16700Schasinglulu } 180*91f16700Schasinglulu 181*91f16700Schasinglulu mmio_clrsetbits_32(huart->base + USART_CR3, STM32_UART_CR3_FIELDS, tmpreg); 182*91f16700Schasinglulu 183*91f16700Schasinglulu /* 184*91f16700Schasinglulu * --------------------- USART PRESC Configuration ------------------- 185*91f16700Schasinglulu * Configure UART Clock Prescaler : set PRESCALER according to 186*91f16700Schasinglulu * init->prescaler value. 187*91f16700Schasinglulu */ 188*91f16700Schasinglulu assert(init->prescaler < STM32_UART_PRESCALER_NB); 189*91f16700Schasinglulu mmio_clrsetbits_32(huart->base + USART_PRESC, USART_PRESC_PRESCALER, 190*91f16700Schasinglulu init->prescaler); 191*91f16700Schasinglulu 192*91f16700Schasinglulu return 0; 193*91f16700Schasinglulu } 194*91f16700Schasinglulu 195*91f16700Schasinglulu /* 196*91f16700Schasinglulu * @brief Handle UART communication timeout. 197*91f16700Schasinglulu * @param huart: UART handle. 198*91f16700Schasinglulu * @param flag: Specifies the UART flag to check. 199*91f16700Schasinglulu * @retval UART status. 200*91f16700Schasinglulu */ 201*91f16700Schasinglulu static int stm32_uart_wait_flag(struct stm32_uart_handle_s *huart, uint32_t flag) 202*91f16700Schasinglulu { 203*91f16700Schasinglulu uint64_t timeout_ref = timeout_init_us(STM32_UART_TIMEOUT_US); 204*91f16700Schasinglulu 205*91f16700Schasinglulu while ((mmio_read_32(huart->base + USART_ISR) & flag) == 0U) { 206*91f16700Schasinglulu if (timeout_elapsed(timeout_ref)) { 207*91f16700Schasinglulu return -ETIMEDOUT; 208*91f16700Schasinglulu } 209*91f16700Schasinglulu } 210*91f16700Schasinglulu 211*91f16700Schasinglulu return 0; 212*91f16700Schasinglulu } 213*91f16700Schasinglulu 214*91f16700Schasinglulu /* 215*91f16700Schasinglulu * @brief Check the UART idle State. 216*91f16700Schasinglulu * @param huart: UART handle. 217*91f16700Schasinglulu * @retval UART status. 218*91f16700Schasinglulu */ 219*91f16700Schasinglulu static int stm32_uart_check_idle(struct stm32_uart_handle_s *huart) 220*91f16700Schasinglulu { 221*91f16700Schasinglulu int ret; 222*91f16700Schasinglulu 223*91f16700Schasinglulu /* Check if the transmitter is enabled */ 224*91f16700Schasinglulu if ((mmio_read_32(huart->base + USART_CR1) & USART_CR1_TE) == USART_CR1_TE) { 225*91f16700Schasinglulu ret = stm32_uart_wait_flag(huart, USART_ISR_TEACK); 226*91f16700Schasinglulu if (ret != 0) { 227*91f16700Schasinglulu return ret; 228*91f16700Schasinglulu } 229*91f16700Schasinglulu } 230*91f16700Schasinglulu 231*91f16700Schasinglulu /* Check if the receiver is enabled */ 232*91f16700Schasinglulu if ((mmio_read_32(huart->base + USART_CR1) & USART_CR1_RE) == USART_CR1_RE) { 233*91f16700Schasinglulu ret = stm32_uart_wait_flag(huart, USART_ISR_REACK); 234*91f16700Schasinglulu if (ret != 0) { 235*91f16700Schasinglulu return ret; 236*91f16700Schasinglulu } 237*91f16700Schasinglulu } 238*91f16700Schasinglulu 239*91f16700Schasinglulu return 0; 240*91f16700Schasinglulu } 241*91f16700Schasinglulu 242*91f16700Schasinglulu /* 243*91f16700Schasinglulu * @brief Compute RDR register mask depending on word length. 244*91f16700Schasinglulu * @param huart: UART handle. 245*91f16700Schasinglulu * @retval Mask value. 246*91f16700Schasinglulu */ 247*91f16700Schasinglulu static unsigned int stm32_uart_rdr_mask(const struct stm32_uart_init_s *init) 248*91f16700Schasinglulu { 249*91f16700Schasinglulu unsigned int mask = 0U; 250*91f16700Schasinglulu 251*91f16700Schasinglulu switch (init->word_length) { 252*91f16700Schasinglulu case STM32_UART_WORDLENGTH_9B: 253*91f16700Schasinglulu mask = GENMASK(8, 0); 254*91f16700Schasinglulu break; 255*91f16700Schasinglulu case STM32_UART_WORDLENGTH_8B: 256*91f16700Schasinglulu mask = GENMASK(7, 0); 257*91f16700Schasinglulu break; 258*91f16700Schasinglulu case STM32_UART_WORDLENGTH_7B: 259*91f16700Schasinglulu mask = GENMASK(6, 0); 260*91f16700Schasinglulu break; 261*91f16700Schasinglulu default: 262*91f16700Schasinglulu break; /* not reached */ 263*91f16700Schasinglulu } 264*91f16700Schasinglulu 265*91f16700Schasinglulu if (init->parity != STM32_UART_PARITY_NONE) { 266*91f16700Schasinglulu mask >>= 1; 267*91f16700Schasinglulu } 268*91f16700Schasinglulu 269*91f16700Schasinglulu return mask; 270*91f16700Schasinglulu } 271*91f16700Schasinglulu 272*91f16700Schasinglulu /* 273*91f16700Schasinglulu * @brief Check interrupt and status errors. 274*91f16700Schasinglulu * @retval True if error detected, false otherwise. 275*91f16700Schasinglulu */ 276*91f16700Schasinglulu static bool stm32_uart_error_detected(struct stm32_uart_handle_s *huart) 277*91f16700Schasinglulu { 278*91f16700Schasinglulu return (mmio_read_32(huart->base + USART_ISR) & STM32_UART_ISR_ERRORS) != 0U; 279*91f16700Schasinglulu } 280*91f16700Schasinglulu 281*91f16700Schasinglulu /* 282*91f16700Schasinglulu * @brief Clear status errors. 283*91f16700Schasinglulu */ 284*91f16700Schasinglulu static void stm32_uart_error_clear(struct stm32_uart_handle_s *huart) 285*91f16700Schasinglulu { 286*91f16700Schasinglulu mmio_write_32(huart->base + USART_ICR, STM32_UART_ISR_ERRORS); 287*91f16700Schasinglulu } 288*91f16700Schasinglulu 289*91f16700Schasinglulu /* 290*91f16700Schasinglulu * @brief Stop the UART. 291*91f16700Schasinglulu * @param base: UART base address. 292*91f16700Schasinglulu */ 293*91f16700Schasinglulu void stm32_uart_stop(uintptr_t base) 294*91f16700Schasinglulu { 295*91f16700Schasinglulu mmio_clrbits_32(base + USART_CR1, USART_CR1_UE); 296*91f16700Schasinglulu } 297*91f16700Schasinglulu 298*91f16700Schasinglulu /* 299*91f16700Schasinglulu * @brief Initialize UART. 300*91f16700Schasinglulu * @param huart: UART handle. 301*91f16700Schasinglulu * @param base_addr: base address of UART. 302*91f16700Schasinglulu * @param init: UART initialization parameter. 303*91f16700Schasinglulu * @retval UART status. 304*91f16700Schasinglulu */ 305*91f16700Schasinglulu int stm32_uart_init(struct stm32_uart_handle_s *huart, 306*91f16700Schasinglulu uintptr_t base_addr, 307*91f16700Schasinglulu const struct stm32_uart_init_s *init) 308*91f16700Schasinglulu { 309*91f16700Schasinglulu int ret; 310*91f16700Schasinglulu int uart_node; 311*91f16700Schasinglulu int clk; 312*91f16700Schasinglulu void *fdt = NULL; 313*91f16700Schasinglulu 314*91f16700Schasinglulu if (huart == NULL || init == NULL || base_addr == 0U) { 315*91f16700Schasinglulu return -EINVAL; 316*91f16700Schasinglulu } 317*91f16700Schasinglulu 318*91f16700Schasinglulu huart->base = base_addr; 319*91f16700Schasinglulu 320*91f16700Schasinglulu /* Search UART instance in DT */ 321*91f16700Schasinglulu if (fdt_get_address(&fdt) == 0) { 322*91f16700Schasinglulu return -FDT_ERR_NOTFOUND; 323*91f16700Schasinglulu } 324*91f16700Schasinglulu 325*91f16700Schasinglulu if (fdt == NULL) { 326*91f16700Schasinglulu return -FDT_ERR_NOTFOUND; 327*91f16700Schasinglulu } 328*91f16700Schasinglulu 329*91f16700Schasinglulu uart_node = dt_match_instance_by_compatible(DT_UART_COMPAT, base_addr); 330*91f16700Schasinglulu if (uart_node == -FDT_ERR_NOTFOUND) { 331*91f16700Schasinglulu return -FDT_ERR_NOTFOUND; 332*91f16700Schasinglulu } 333*91f16700Schasinglulu 334*91f16700Schasinglulu /* Pinctrl initialization */ 335*91f16700Schasinglulu if (dt_set_pinctrl_config(uart_node) != 0) { 336*91f16700Schasinglulu return -FDT_ERR_BADVALUE; 337*91f16700Schasinglulu } 338*91f16700Schasinglulu 339*91f16700Schasinglulu /* Clock initialization */ 340*91f16700Schasinglulu clk = fdt_get_clock_id(uart_node); 341*91f16700Schasinglulu if (clk < 0) { 342*91f16700Schasinglulu return -FDT_ERR_NOTFOUND; 343*91f16700Schasinglulu } 344*91f16700Schasinglulu clk_enable(clk); 345*91f16700Schasinglulu 346*91f16700Schasinglulu /* Disable the peripheral */ 347*91f16700Schasinglulu stm32_uart_stop(huart->base); 348*91f16700Schasinglulu 349*91f16700Schasinglulu /* Computation of UART mask to apply to RDR register */ 350*91f16700Schasinglulu huart->rdr_mask = stm32_uart_rdr_mask(init); 351*91f16700Schasinglulu 352*91f16700Schasinglulu /* Init the peripheral */ 353*91f16700Schasinglulu ret = uart_set_config(huart, init); 354*91f16700Schasinglulu if (ret != 0) { 355*91f16700Schasinglulu return ret; 356*91f16700Schasinglulu } 357*91f16700Schasinglulu 358*91f16700Schasinglulu /* Enable the peripheral */ 359*91f16700Schasinglulu mmio_setbits_32(huart->base + USART_CR1, USART_CR1_UE); 360*91f16700Schasinglulu 361*91f16700Schasinglulu /* TEACK and/or REACK to check */ 362*91f16700Schasinglulu return stm32_uart_check_idle(huart); 363*91f16700Schasinglulu } 364*91f16700Schasinglulu 365*91f16700Schasinglulu /* 366*91f16700Schasinglulu * @brief Transmit one data in no blocking mode. 367*91f16700Schasinglulu * @param huart: UART handle. 368*91f16700Schasinglulu * @param c: data to sent. 369*91f16700Schasinglulu * @retval UART status. 370*91f16700Schasinglulu */ 371*91f16700Schasinglulu int stm32_uart_putc(struct stm32_uart_handle_s *huart, int c) 372*91f16700Schasinglulu { 373*91f16700Schasinglulu int ret; 374*91f16700Schasinglulu 375*91f16700Schasinglulu if (huart == NULL) { 376*91f16700Schasinglulu return -EINVAL; 377*91f16700Schasinglulu } 378*91f16700Schasinglulu 379*91f16700Schasinglulu ret = stm32_uart_wait_flag(huart, USART_ISR_TXE); 380*91f16700Schasinglulu if (ret != 0) { 381*91f16700Schasinglulu return ret; 382*91f16700Schasinglulu } 383*91f16700Schasinglulu 384*91f16700Schasinglulu mmio_write_32(huart->base + USART_TDR, c); 385*91f16700Schasinglulu if (stm32_uart_error_detected(huart)) { 386*91f16700Schasinglulu stm32_uart_error_clear(huart); 387*91f16700Schasinglulu return -EFAULT; 388*91f16700Schasinglulu } 389*91f16700Schasinglulu 390*91f16700Schasinglulu return 0; 391*91f16700Schasinglulu } 392*91f16700Schasinglulu 393*91f16700Schasinglulu /* 394*91f16700Schasinglulu * @brief Flush TX Transmit fifo 395*91f16700Schasinglulu * @param huart: UART handle. 396*91f16700Schasinglulu * @retval UART status. 397*91f16700Schasinglulu */ 398*91f16700Schasinglulu int stm32_uart_flush(struct stm32_uart_handle_s *huart) 399*91f16700Schasinglulu { 400*91f16700Schasinglulu int ret; 401*91f16700Schasinglulu 402*91f16700Schasinglulu if (huart == NULL) { 403*91f16700Schasinglulu return -EINVAL; 404*91f16700Schasinglulu } 405*91f16700Schasinglulu 406*91f16700Schasinglulu ret = stm32_uart_wait_flag(huart, USART_ISR_TXE); 407*91f16700Schasinglulu if (ret != 0) { 408*91f16700Schasinglulu return ret; 409*91f16700Schasinglulu } 410*91f16700Schasinglulu 411*91f16700Schasinglulu return stm32_uart_wait_flag(huart, USART_ISR_TC); 412*91f16700Schasinglulu } 413*91f16700Schasinglulu 414*91f16700Schasinglulu /* 415*91f16700Schasinglulu * @brief Receive a data in no blocking mode. 416*91f16700Schasinglulu * @retval value if >0 or UART status. 417*91f16700Schasinglulu */ 418*91f16700Schasinglulu int stm32_uart_getc(struct stm32_uart_handle_s *huart) 419*91f16700Schasinglulu { 420*91f16700Schasinglulu uint32_t data; 421*91f16700Schasinglulu 422*91f16700Schasinglulu if (huart == NULL) { 423*91f16700Schasinglulu return -EINVAL; 424*91f16700Schasinglulu } 425*91f16700Schasinglulu 426*91f16700Schasinglulu /* Check if data is available */ 427*91f16700Schasinglulu if ((mmio_read_32(huart->base + USART_ISR) & USART_ISR_RXNE) == 0U) { 428*91f16700Schasinglulu return -EAGAIN; 429*91f16700Schasinglulu } 430*91f16700Schasinglulu 431*91f16700Schasinglulu data = mmio_read_32(huart->base + USART_RDR) & huart->rdr_mask; 432*91f16700Schasinglulu 433*91f16700Schasinglulu if (stm32_uart_error_detected(huart)) { 434*91f16700Schasinglulu stm32_uart_error_clear(huart); 435*91f16700Schasinglulu return -EFAULT; 436*91f16700Schasinglulu } 437*91f16700Schasinglulu 438*91f16700Schasinglulu return (int)data; 439*91f16700Schasinglulu } 440