Skip to content

Commit d1ec8a2

Browse files
Erwan Le Raygregkh
authored andcommitted
serial: stm32: update throttle and unthrottle ops for dma mode
Disable DMA request line (if enabled) to switch in PIO mode in throttle ops, so the RX data gets queues into the FIFO. The hardware flow control is triggered when the RX FIFO is full. Switch back to DMA mode (re-enable DMA request line) in unthrottle ops. Hardware flow control is stopped when FIFO is not full anymore. Signed-off-by: Valentin Caron <valentin.caron@foss.st.com> Signed-off-by: Erwan Le Ray <erwan.leray@foss.st.com> Link: https://lore.kernel.org/r/20211020150332.10214-4-erwan.leray@foss.st.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 33bb2f6 commit d1ec8a2

File tree

2 files changed

+34
-4
lines changed

2 files changed

+34
-4
lines changed

drivers/tty/serial/stm32-usart.c

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -577,9 +577,12 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
577577
* rx errors in dma mode has to be handled ASAP to avoid overrun as the DMA request
578578
* line has been masked by HW and rx data are stacking in FIFO.
579579
*/
580-
if (((sr & USART_SR_RXNE) && !stm32_usart_rx_dma_enabled(port)) ||
581-
((sr & USART_SR_ERR_MASK) && stm32_usart_rx_dma_enabled(port)))
582-
stm32_usart_receive_chars(port, false);
580+
if (!stm32_port->throttled) {
581+
if (((sr & USART_SR_RXNE) && !stm32_usart_rx_dma_enabled(port)) ||
582+
((sr & USART_SR_ERR_MASK) && stm32_usart_rx_dma_enabled(port))) {
583+
stm32_usart_receive_chars(port, false);
584+
}
585+
}
583586

584587
if ((sr & USART_SR_TXE) && !(stm32_port->tx_ch)) {
585588
spin_lock(&port->lock);
@@ -596,9 +599,11 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
596599
static irqreturn_t stm32_usart_threaded_interrupt(int irq, void *ptr)
597600
{
598601
struct uart_port *port = ptr;
602+
struct stm32_port *stm32_port = to_stm32_port(port);
599603

600604
/* Receiver timeout irq for DMA RX */
601-
stm32_usart_receive_chars(port, false);
605+
if (!stm32_port->throttled)
606+
stm32_usart_receive_chars(port, false);
602607

603608
return IRQ_HANDLED;
604609
}
@@ -711,10 +716,19 @@ static void stm32_usart_throttle(struct uart_port *port)
711716
unsigned long flags;
712717

713718
spin_lock_irqsave(&port->lock, flags);
719+
720+
/*
721+
* Disable DMA request line if enabled, so the RX data gets queued into the FIFO.
722+
* Hardware flow control is triggered when RX FIFO is full.
723+
*/
724+
if (stm32_usart_rx_dma_enabled(port))
725+
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR);
726+
714727
stm32_usart_clr_bits(port, ofs->cr1, stm32_port->cr1_irq);
715728
if (stm32_port->cr3_irq)
716729
stm32_usart_clr_bits(port, ofs->cr3, stm32_port->cr3_irq);
717730

731+
stm32_port->throttled = true;
718732
spin_unlock_irqrestore(&port->lock, flags);
719733
}
720734

@@ -730,6 +744,14 @@ static void stm32_usart_unthrottle(struct uart_port *port)
730744
if (stm32_port->cr3_irq)
731745
stm32_usart_set_bits(port, ofs->cr3, stm32_port->cr3_irq);
732746

747+
/*
748+
* Switch back to DMA mode (re-enable DMA request line).
749+
* Hardware flow control is stopped when FIFO is not full any more.
750+
*/
751+
if (stm32_port->rx_ch)
752+
stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAR);
753+
754+
stm32_port->throttled = false;
733755
spin_unlock_irqrestore(&port->lock, flags);
734756
}
735757

@@ -775,6 +797,13 @@ static int stm32_usart_startup(struct uart_port *port)
775797
if (ofs->rqr != UNDEF_REG)
776798
writel_relaxed(USART_RQR_RXFRQ, port->membase + ofs->rqr);
777799

800+
/*
801+
* DMA request line not re-enabled at resume when port is throttled.
802+
* It will be re-enabled by unthrottle ops.
803+
*/
804+
if (!stm32_port->throttled)
805+
stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAR);
806+
778807
/* RX enabling */
779808
val = stm32_port->cr1_irq | USART_CR1_RE | BIT(cfg->uart_enable_bit);
780809
stm32_usart_set_bits(port, ofs->cr1, val);

drivers/tty/serial/stm32-usart.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ struct stm32_port {
265265
u32 cr3_irq; /* USART_CR3_RXFTIE */
266266
int last_res;
267267
bool tx_dma_busy; /* dma tx busy */
268+
bool throttled; /* port throttled */
268269
bool hw_flow_control;
269270
bool swap; /* swap RX & TX pins */
270271
bool fifoen;

0 commit comments

Comments
 (0)