xref: /arm-trusted-firmware/drivers/st/uart/stm32_uart.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
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