aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/tty/serial/stm32-usart.c
diff options
context:
space:
mode:
authorErwan Le Ray <erwan.leray@st.com>2019-06-18 12:02:25 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-06-21 11:17:36 +0200
commitd0a6a7bcc3fa0e97efce1d9a5c4cca6f3474c6bb (patch)
tree2488b1dd7497894f58efb3b7a51b6ff07f520d17 /drivers/tty/serial/stm32-usart.c
parentserial: stm32: add support of TX FIFO threshold (diff)
downloadwireguard-linux-d0a6a7bcc3fa0e97efce1d9a5c4cca6f3474c6bb.tar.xz
wireguard-linux-d0a6a7bcc3fa0e97efce1d9a5c4cca6f3474c6bb.zip
serial: stm32: add support of RX FIFO threshold
Adds the support of RX FIFO threshold in order to improve the RX FIFO management. This is done by enabling fifo threshold interrupt, instead of relying on rx empty/fifo not full irq. That basically generates one irq/char currently. With this patch: - RXCFG is set to half fifo size (e.g. 16/2 = 8 data for a 16 data depth FIFO) - irq rate may be reduced by up to 1/RXCFG, e.g. 1 over 8 with current RXCFG setting. - Receiver timeout is used to gather chars when FIFO threshold isn't reached. 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/stm32-usart.c')
-rw-r--r--drivers/tty/serial/stm32-usart.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index 959f33bb0eb6..fd9fb33ce4fe 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -547,6 +547,9 @@ static void stm32_throttle(struct uart_port *port)
spin_lock_irqsave(&port->lock, flags);
stm32_clr_bits(port, ofs->cr1, stm32_port->cr1_irq);
+ if (stm32_port->cr3_irq)
+ stm32_clr_bits(port, ofs->cr3, stm32_port->cr3_irq);
+
spin_unlock_irqrestore(&port->lock, flags);
}
@@ -559,6 +562,9 @@ static void stm32_unthrottle(struct uart_port *port)
spin_lock_irqsave(&port->lock, flags);
stm32_set_bits(port, ofs->cr1, stm32_port->cr1_irq);
+ if (stm32_port->cr3_irq)
+ stm32_set_bits(port, ofs->cr3, stm32_port->cr3_irq);
+
spin_unlock_irqrestore(&port->lock, flags);
}
@@ -569,6 +575,9 @@ static void stm32_stop_rx(struct uart_port *port)
struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
stm32_clr_bits(port, ofs->cr1, stm32_port->cr1_irq);
+ if (stm32_port->cr3_irq)
+ stm32_clr_bits(port, ofs->cr3, stm32_port->cr3_irq);
+
}
/* Handle breaks - ignored by us */
@@ -597,8 +606,9 @@ static int stm32_startup(struct uart_port *port)
if (stm32_port->fifoen) {
val = readl_relaxed(port->membase + ofs->cr3);
- val &= ~USART_CR3_TXFTCFG_MASK;
+ val &= ~(USART_CR3_TXFTCFG_MASK | USART_CR3_RXFTCFG_MASK);
val |= USART_CR3_TXFTCFG_HALF << USART_CR3_TXFTCFG_SHIFT;
+ val |= USART_CR3_RXFTCFG_HALF << USART_CR3_RXFTCFG_SHIFT;
writel_relaxed(val, port->membase + ofs->cr3);
}
@@ -690,7 +700,7 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios,
cr1 |= USART_CR1_FIFOEN;
cr2 = 0;
cr3 = readl_relaxed(port->membase + ofs->cr3);
- cr3 &= USART_CR3_TXFTIE | USART_CR3_RXFTCFG | USART_CR3_RXFTIE
+ cr3 &= USART_CR3_TXFTIE | USART_CR3_RXFTCFG_MASK | USART_CR3_RXFTIE
| USART_CR3_TXFTCFG_MASK;
if (cflag & CSTOPB)
@@ -730,8 +740,14 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios,
stm32_port->cr1_irq = USART_CR1_RTOIE;
writel_relaxed(bits, port->membase + ofs->rtor);
cr2 |= USART_CR2_RTOEN;
+ /* Not using dma, enable fifo threshold irq */
+ if (!stm32_port->rx_ch)
+ stm32_port->cr3_irq = USART_CR3_RXFTIE;
}
+ cr1 |= stm32_port->cr1_irq;
+ cr3 |= stm32_port->cr3_irq;
+
if (cflag & PARODD)
cr1 |= USART_CR1_PS;
@@ -973,6 +989,7 @@ static struct stm32_port *stm32_of_get_stm32_port(struct platform_device *pdev)
"st,hw-flow-ctrl");
stm32_ports[id].port.line = id;
stm32_ports[id].cr1_irq = USART_CR1_RXNEIE;
+ stm32_ports[id].cr3_irq = 0;
stm32_ports[id].last_res = RX_BUF_L;
return &stm32_ports[id];
}