Commit 5d9176ed authored by Erwan Le Ray's avatar Erwan Le Ray Committed by Greg Kroah-Hartman
Browse files

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: default avatarErwan Le Ray <erwan.leray@st.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 4cc0ed62
Loading
Loading
Loading
Loading
+13 −14
Original line number Diff line number Diff line
@@ -300,29 +300,28 @@ 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++;
	}

	/* 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)
{
	struct stm32_port *stm32port = to_stm32_port(port);