[PATCH v1 03/31] serial: 8250_mxupci: enable enhanced mode and custom FIFO trigger levels

Crescent Hsieh posted 31 patches 1 day, 11 hours ago
[PATCH v1 03/31] serial: 8250_mxupci: enable enhanced mode and custom FIFO trigger levels
Posted by Crescent Hsieh 1 day, 11 hours ago
Add support for enabling enhanced mode and configuring custom FIFO trigger
levels on Moxa UPCI serial boards.

Enhanced mode is activated via EFR, which also provides access to three
configuration pages selected through EFR[7:6].
These pages allow fine-tuning of advanced UART feature such as Rx/Tx
interrupt trigger levels and flow control thresholds.

Signed-off-by: Crescent Hsieh <crescentcy.hsieh@moxa.com>
---
 drivers/tty/serial/8250/8250_mxupci.c | 65 +++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/drivers/tty/serial/8250/8250_mxupci.c b/drivers/tty/serial/8250/8250_mxupci.c
index d7a4b838ec1f..c4fa52de8962 100644
--- a/drivers/tty/serial/8250/8250_mxupci.c
+++ b/drivers/tty/serial/8250/8250_mxupci.c
@@ -43,6 +43,25 @@
 #define MOXA_UART_BASE_BAUD	921600
 #define MOXA_UART_OFFSET	8
 
+/* Enhanced Function Register (EFR) */
+/*
+ * EFR[7:6] - Enhanced Register Page Select:
+ *	00b (0x00) = Software flow control characters
+ *	01b (0x40) = FIFO trigger level
+ *	10b (0x80) = Clock, ID, reset
+ *	11b (0xC0) = Alias of Page 2 (same behavior as 10b)
+ */
+#define	MOXA_UART_EFR_PAGE_0		0x00	/* Software flow control characters */
+#define	MOXA_UART_EFR_PAGE_1		0x40	/* FIFO trigger level */
+#define	MOXA_UART_EFR_PAGE_2		0x80	/* Clock, ID, reset */
+#define MOXA_UART_EFR_PAGE_MASK		GENMASK(7, 6)
+
+/* Enhanced Registers Page 1 */
+#define MOXA_UART_RBRTL	0x04	/* Flow Control Low Trigger Level */
+#define MOXA_UART_RBRTH	0x05	/* Flow Control High Trigger Level */
+#define MOXA_UART_RBRTI	0x06	/* Rx Interrupt Trigger Level */
+#define MOXA_UART_THRTL	0x07	/* Tx Interrupt Trigger Level */
+
 struct mxupci8250 {
 	struct pci_dev *pdev;
 	unsigned int num_ports;
@@ -59,6 +78,49 @@ static unsigned short mxupci8250_get_nports(unsigned short device)
 	return FIELD_GET(0x00F0, device);
 }
 
+static int mxupci8250_startup(struct uart_port *port)
+{
+	struct uart_8250_port *up = up_to_u8250p(port);
+	int ret;
+	u8 efr;
+
+	ret = serial8250_do_startup(port);
+
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+
+	efr = serial_in(up, UART_EFR);
+	efr |= UART_EFR_ECB;
+	serial_out(up, UART_EFR, efr);
+
+	efr &= ~MOXA_UART_EFR_PAGE_MASK;
+	efr |= MOXA_UART_EFR_PAGE_1;
+	serial_out(up, UART_EFR, efr);
+
+	serial_out(up, MOXA_UART_THRTL, 0);
+	serial_out(up, MOXA_UART_RBRTI, 96);
+	serial_out(up, MOXA_UART_RBRTL, 32);
+	serial_out(up, MOXA_UART_RBRTH, 96);
+
+	serial_out(up, UART_LCR, up->lcr);
+
+	return ret;
+}
+
+static void mxupci8250_shutdown(struct uart_port *port)
+{
+	struct uart_8250_port *up = up_to_u8250p(port);
+	u8 efr;
+
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+
+	efr = serial_in(up, UART_EFR);
+	serial_out(up, UART_EFR, efr & ~UART_EFR_ECB);
+
+	serial_out(up, UART_LCR, up->lcr);
+
+	serial8250_do_shutdown(port);
+}
+
 static int mxupci8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	struct uart_8250_port up;
@@ -90,6 +152,9 @@ static int mxupci8250_probe(struct pci_dev *pdev, const struct pci_device_id *id
 	up.port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
 	up.port.type = PORT_MU860;
 
+	up.port.startup = mxupci8250_startup;
+	up.port.shutdown = mxupci8250_shutdown;
+
 	for (i = 0; i < num_ports; i++) {
 		if (serial8250_pci_setup_port(pdev, &up, FL_GET_BASE(FL_BASE2), i * MOXA_UART_OFFSET, 0))
 			break;
-- 
2.45.2
Re: [PATCH v1 03/31] serial: 8250_mxupci: enable enhanced mode and custom FIFO trigger levels
Posted by Andy Shevchenko 1 day, 4 hours ago
On Sun, Nov 30, 2025 at 12:43 PM Crescent Hsieh
<crescentcy.hsieh@moxa.com> wrote:
>
> Add support for enabling enhanced mode and configuring custom FIFO trigger
> levels on Moxa UPCI serial boards.
>
> Enhanced mode is activated via EFR, which also provides access to three
> configuration pages selected through EFR[7:6].
> These pages allow fine-tuning of advanced UART feature such as Rx/Tx

features

> interrupt trigger levels and flow control thresholds.

...

> +static int mxupci8250_startup(struct uart_port *port)
> +{
> +       struct uart_8250_port *up = up_to_u8250p(port);
> +       int ret;
> +       u8 efr;
> +
> +       ret = serial8250_do_startup(port);

This needs a very good comment on why it is okay to continue even in
error cases.

> +       serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
> +
> +       efr = serial_in(up, UART_EFR);
> +       efr |= UART_EFR_ECB;
> +       serial_out(up, UART_EFR, efr);
> +
> +       efr &= ~MOXA_UART_EFR_PAGE_MASK;
> +       efr |= MOXA_UART_EFR_PAGE_1;
> +       serial_out(up, UART_EFR, efr);
> +
> +       serial_out(up, MOXA_UART_THRTL, 0);
> +       serial_out(up, MOXA_UART_RBRTI, 96);
> +       serial_out(up, MOXA_UART_RBRTL, 32);
> +       serial_out(up, MOXA_UART_RBRTH, 96);
> +
> +       serial_out(up, UART_LCR, up->lcr);
> +
> +       return ret;
> +}

-- 
With Best Regards,
Andy Shevchenko