diff options
author | Erwan Le Ray <erwan.leray@st.com> | 2019-06-18 12:02:23 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-06-21 11:17:36 +0200 |
commit | 5d9176edacc29cadb9a0b52c8aaba67ce5ff4ed4 (patch) | |
tree | e46c06578e457eba410545d103a76a20bcc5c9c1 /drivers/tty | |
parent | 4cc0ed626f2ba36cd008d4b380613f0360133891 (diff) |
serial: stm32: update PIO transmission
Improves PIO transmission:
- Replaces the FIFO filling per character by a filling per blocks of
characters, which provides better performances
- Replaces the active waiting loop by TX empty interrupt dynamic handling.
TXE interrupt is now enabled when data has to be sent (ie when
uart_circ is not empty), and inhibited when there is no more data to
send (ie when uart_circ is empty).
Signed-off-by: Erwan Le Ray <erwan.leray@st.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty')
-rw-r--r-- | drivers/tty/serial/stm32-usart.c | 27 |
1 files changed, 13 insertions, 14 deletions
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index 2e75b586e5bf..2085f10aabfa 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -300,27 +300,26 @@ static void stm32_transmit_chars_pio(struct uart_port *port) struct stm32_port *stm32_port = to_stm32_port(port); struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; struct circ_buf *xmit = &port->state->xmit; - unsigned int isr; - int ret; if (stm32_port->tx_dma_busy) { stm32_clr_bits(port, ofs->cr3, USART_CR3_DMAT); stm32_port->tx_dma_busy = false; } - ret = readl_relaxed_poll_timeout_atomic(port->membase + ofs->isr, - isr, - (isr & USART_SR_TXE), - 10, 100000); - - if (ret) - dev_err(port->dev, "tx empty not set\n"); - - stm32_set_bits(port, ofs->cr1, USART_CR1_TXEIE); + while (!uart_circ_empty(xmit)) { + /* Check that TDR is empty before filling FIFO */ + if (!(readl_relaxed(port->membase + ofs->isr) & USART_SR_TXE)) + break; + writel_relaxed(xmit->buf[xmit->tail], port->membase + ofs->tdr); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + port->icount.tx++; + } - writel_relaxed(xmit->buf[xmit->tail], port->membase + ofs->tdr); - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - port->icount.tx++; + /* rely on TXE irq (mask or unmask) for sending remaining data */ + if (uart_circ_empty(xmit)) + stm32_clr_bits(port, ofs->cr1, USART_CR1_TXEIE); + else + stm32_set_bits(port, ofs->cr1, USART_CR1_TXEIE); } static void stm32_transmit_chars_dma(struct uart_port *port) |