[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251130104222.63077-4-crescentcy.hsieh@moxa.com>
Date: Sun, 30 Nov 2025 18:41:54 +0800
From: Crescent Hsieh <crescentcy.hsieh@...a.com>
To: gregkh@...uxfoundation.org,
jirislaby@...nel.org,
ilpo.jarvinen@...ux.intel.com,
andy.shevchenko@...il.com
Cc: linux-kernel@...r.kernel.org,
linux-serial@...r.kernel.org,
crescentcy.hsieh@...a.com
Subject: [PATCH v1 03/31] serial: 8250_mxupci: enable enhanced mode and custom FIFO trigger levels
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@...a.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
Powered by blists - more mailing lists