[PATCH 07/15] serial: 8250_mxpcie: speed up RX using memory-mapped FIFO window
From: Crescent Hsieh
Date: Mon May 04 2026 - 04:56:29 EST
The MUEx50 UART provides a memory-mapped RX FIFO data window along with
an RX FIFO byte counter.
When no break or error conditions are present, read received data in
bulk via the MMIO FIFO window and push it to the tty layer in one
operation. Fall back to the generic 8250 RX path for break and error
handling.
Signed-off-by: Crescent Hsieh <crescentcy.hsieh@xxxxxxxx>
---
drivers/tty/serial/8250/8250_mxpcie.c | 32 +++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/drivers/tty/serial/8250/8250_mxpcie.c b/drivers/tty/serial/8250/8250_mxpcie.c
index 9860f2ac2572..f13fcb090df7 100644
--- a/drivers/tty/serial/8250/8250_mxpcie.c
+++ b/drivers/tty/serial/8250/8250_mxpcie.c
@@ -17,6 +17,7 @@
#include <linux/serial_8250.h>
#include <linux/serial_core.h>
#include <linux/serial_reg.h>
+#include <linux/tty_flip.h>
#include <linux/8250_pci.h>
#include "8250.h"
@@ -48,6 +49,7 @@
/* UART */
#define MOXA_PUART_BASE_BAUD 921600
#define MOXA_PUART_OFFSET 0x200
+#define MOXA_PUART_FIFO_SIZE 128
/* Special Function Register (SFR) */
#define MOXA_PUART_SFR 0x07
@@ -83,6 +85,9 @@
#define MOXA_PUART_RTL 0x11 /* Rx Interrupt Trigger Level */
#define MOXA_PUART_FCL 0x12 /* Flow Control Low Trigger Level */
#define MOXA_PUART_FCH 0x13 /* Flow Control High Trigger Level */
+#define MOXA_PUART_RX_FIFO_CNT 0x15 /* Rx FIFO Data Counter */
+
+#define MOXA_PUART_RX_FIFO_MEM 0x100 /* Memory Space to Rx FIFO Data Register */
#define MOXA_GPIO_DIRECTION 0x09
#define MOXA_GPIO_OUTPUT 0x0A
@@ -265,6 +270,29 @@ static void mxpcie8250_unthrottle(struct uart_port *port)
uart_port_unlock_irqrestore(port, flags);
}
+static void mxpcie8250_do_rx_chars(struct uart_8250_port *up)
+{
+ struct uart_port *port = &up->port;
+ struct tty_port *tport = &port->state->port;
+ u8 buf[MOXA_PUART_FIFO_SIZE];
+ int recv_room, gdl, i;
+
+ recv_room = tty_buffer_request_room(tport, port->fifosize);
+ if (!recv_room)
+ return;
+
+ gdl = serial_in(up, MOXA_PUART_RX_FIFO_CNT);
+ if (gdl > recv_room)
+ gdl = recv_room;
+
+ for (i = 0; i < gdl; ++i)
+ buf[i] = serial_in(up, MOXA_PUART_RX_FIFO_MEM + i);
+
+ port->icount.rx += gdl;
+ tty_insert_flip_string(tport, buf, gdl);
+ tty_flip_buffer_push(tport);
+}
+
static u16 mxpcie8250_rx_chars(struct uart_8250_port *up, u16 lsr)
{
struct uart_port *port = &up->port;
@@ -282,6 +310,10 @@ static u16 mxpcie8250_rx_chars(struct uart_8250_port *up, u16 lsr)
return lsr;
do_rx:
+ if (!(lsr & UART_LSR_BRK_ERROR_BITS)) {
+ mxpcie8250_do_rx_chars(up);
+ return lsr;
+ }
return serial8250_rx_chars(up, lsr);
}
--
2.43.0