aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial
diff options
context:
space:
mode:
authorErwan Le Ray <erwan.leray@st.com>2019-06-18 12:02:23 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-06-21 11:17:36 +0200
commit5d9176edacc29cadb9a0b52c8aaba67ce5ff4ed4 (patch)
treee46c06578e457eba410545d103a76a20bcc5c9c1 /drivers/tty/serial
parentserial: stm32: add support of timeout interrupt for RX (diff)
downloadlinux-dev-5d9176edacc29cadb9a0b52c8aaba67ce5ff4ed4.tar.xz
linux-dev-5d9176edacc29cadb9a0b52c8aaba67ce5ff4ed4.zip
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/serial')
-rw-r--r--drivers/tty/serial/stm32-usart.c27
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)