* rx errors in dma mode has to be handled ASAP to avoid overrun as the DMA request
* line has been masked by HW and rx data are stacking in FIFO.
*/
- if (((sr & USART_SR_RXNE) && !stm32_usart_rx_dma_enabled(port)) ||
- ((sr & USART_SR_ERR_MASK) && stm32_usart_rx_dma_enabled(port)))
- stm32_usart_receive_chars(port, false);
+ if (!stm32_port->throttled) {
+ if (((sr & USART_SR_RXNE) && !stm32_usart_rx_dma_enabled(port)) ||
+ ((sr & USART_SR_ERR_MASK) && stm32_usart_rx_dma_enabled(port))) {
+ stm32_usart_receive_chars(port, false);
+ }
+ }
if ((sr & USART_SR_TXE) && !(stm32_port->tx_ch)) {
spin_lock(&port->lock);
static irqreturn_t stm32_usart_threaded_interrupt(int irq, void *ptr)
{
struct uart_port *port = ptr;
+ struct stm32_port *stm32_port = to_stm32_port(port);
/* Receiver timeout irq for DMA RX */
- stm32_usart_receive_chars(port, false);
+ if (!stm32_port->throttled)
+ stm32_usart_receive_chars(port, false);
return IRQ_HANDLED;
}
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
+
+ /*
+ * Disable DMA request line if enabled, so the RX data gets queued into the FIFO.
+ * Hardware flow control is triggered when RX FIFO is full.
+ */
+ if (stm32_usart_rx_dma_enabled(port))
+ stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR);
+
stm32_usart_clr_bits(port, ofs->cr1, stm32_port->cr1_irq);
if (stm32_port->cr3_irq)
stm32_usart_clr_bits(port, ofs->cr3, stm32_port->cr3_irq);
+ stm32_port->throttled = true;
spin_unlock_irqrestore(&port->lock, flags);
}
if (stm32_port->cr3_irq)
stm32_usart_set_bits(port, ofs->cr3, stm32_port->cr3_irq);
+ /*
+ * Switch back to DMA mode (re-enable DMA request line).
+ * Hardware flow control is stopped when FIFO is not full any more.
+ */
+ if (stm32_port->rx_ch)
+ stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAR);
+
+ stm32_port->throttled = false;
spin_unlock_irqrestore(&port->lock, flags);
}
if (ofs->rqr != UNDEF_REG)
writel_relaxed(USART_RQR_RXFRQ, port->membase + ofs->rqr);
+ /*
+ * DMA request line not re-enabled at resume when port is throttled.
+ * It will be re-enabled by unthrottle ops.
+ */
+ if (!stm32_port->throttled)
+ stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAR);
+
/* RX enabling */
val = stm32_port->cr1_irq | USART_CR1_RE | BIT(cfg->uart_enable_bit);
stm32_usart_set_bits(port, ofs->cr1, val);