summaryrefslogtreecommitdiffstats
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
parentd075719e62ae7bc7fed3ff5be365c8c384483f15 (diff)
downloadlinux-d0a6a7bcc3fa0e97efce1d9a5c4cca6f3474c6bb.tar.gz
linux-d0a6a7bcc3fa0e97efce1d9a5c4cca6f3474c6bb.tar.bz2
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>
-rw-r--r--drivers/tty/serial/stm32-usart.c21
-rw-r--r--drivers/tty/serial/stm32-usart.h7
2 files changed, 25 insertions, 3 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];
}
diff --git a/drivers/tty/serial/stm32-usart.h b/drivers/tty/serial/stm32-usart.h
index a5984463e113..a175c1094dc8 100644
--- a/drivers/tty/serial/stm32-usart.h
+++ b/drivers/tty/serial/stm32-usart.h
@@ -210,7 +210,8 @@ struct stm32_usart_info stm32h7_info = {
#define USART_CR3_WUFIE BIT(22) /* H7 */
#define USART_CR3_TXFTIE BIT(23) /* H7 */
#define USART_CR3_TCBGTIE BIT(24) /* H7 */
-#define USART_CR3_RXFTCFG GENMASK(27, 25) /* H7 */
+#define USART_CR3_RXFTCFG_MASK GENMASK(27, 25) /* H7 */
+#define USART_CR3_RXFTCFG_SHIFT 25 /* H7 */
#define USART_CR3_RXFTIE BIT(28) /* H7 */
#define USART_CR3_TXFTCFG_MASK GENMASK(31, 29) /* H7 */
#define USART_CR3_TXFTCFG_SHIFT 29 /* H7 */
@@ -218,6 +219,9 @@ struct stm32_usart_info stm32h7_info = {
/* TX FIFO threashold set to half of its depth */
#define USART_CR3_TXFTCFG_HALF 0x2
+/* RX FIFO threashold set to half of its depth */
+#define USART_CR3_RXFTCFG_HALF 0x2
+
/* USART_GTPR */
#define USART_GTPR_PSC_MASK GENMASK(7, 0)
#define USART_GTPR_GT_MASK GENMASK(15, 8)
@@ -263,6 +267,7 @@ struct stm32_port {
dma_addr_t tx_dma_buf; /* dma tx buffer bus address */
unsigned char *tx_buf; /* dma tx buffer cpu address */
u32 cr1_irq; /* USART_CR1_RXNEIE or RTOIE */
+ u32 cr3_irq; /* USART_CR3_RXFTIE */
int last_res;
bool tx_dma_busy; /* dma tx busy */
bool hw_flow_control;