Add support for enabling enhanced mode and configuring custom FIFO
trigger levels on Moxa PCIe serial boards.
Enhanced mode is activated via EFR[4] and SFR[5], which is required to
access special function registers used for advanced features. Once
enhanced mode is enabled, custom TX/RX FIFO trigger levels and flow
control thresholds are configured through specific registers.
Signed-off-by: Crescent Hsieh <crescentcy.hsieh@moxa.com>
---
drivers/tty/serial/8250/8250_mxpcie.c | 47 +++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/drivers/tty/serial/8250/8250_mxpcie.c b/drivers/tty/serial/8250/8250_mxpcie.c
index f38684d11a90..39a178dc0519 100644
--- a/drivers/tty/serial/8250/8250_mxpcie.c
+++ b/drivers/tty/serial/8250/8250_mxpcie.c
@@ -36,6 +36,19 @@
#define MOXA_PUART_BASE_BAUD 921600
#define MOXA_PUART_OFFSET 0x200
+/* Special Function Register (SFR) */
+#define MOXA_PUART_SFR 0x07
+#define MOXA_PUART_SFR_950 BIT(5)
+
+/* Enhanced Function Register (EFR) */
+#define MOXA_PUART_EFR 0x0A
+#define MOXA_PUART_EFR_ENHANCED BIT(4)
+
+#define MOXA_PUART_TTL 0x10 /* Tx Interrupt Trigger Level */
+#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_GPIO_DIRECTION 0x09
#define MOXA_GPIO_OUTPUT 0x0A
@@ -124,6 +137,37 @@ static int mxpcie8250_set_interface(struct mxpcie8250 *priv,
return 0;
}
+static int mxpcie8250_startup(struct uart_port *port)
+{
+ struct uart_8250_port *up = up_to_u8250p(port);
+ int i, ret;
+
+ ret = serial8250_do_startup(port);
+
+ for (i = 0; i < 5; ++i)
+ serial_out(up, UART_FCR, UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+
+ serial_out(up, MOXA_PUART_EFR, MOXA_PUART_EFR_ENHANCED);
+ serial_out(up, MOXA_PUART_SFR, MOXA_PUART_SFR_950);
+
+ serial_out(up, MOXA_PUART_TTL, 0);
+ serial_out(up, MOXA_PUART_RTL, 96);
+ serial_out(up, MOXA_PUART_FCL, 16);
+ serial_out(up, MOXA_PUART_FCH, 110);
+
+ return ret;
+}
+
+static void mxpcie8250_shutdown(struct uart_port *port)
+{
+ struct uart_8250_port *up = up_to_u8250p(port);
+
+ serial_out(up, MOXA_PUART_EFR, 0);
+ serial_out(up, MOXA_PUART_SFR, 0);
+
+ serial8250_do_shutdown(port);
+}
+
static int mxpcie8250_init(struct pci_dev *pdev)
{
resource_size_t iobar_addr = pci_resource_start(pdev, 2);
@@ -210,6 +254,9 @@ static int mxpcie8250_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_MUEX50;
+ up.port.startup = mxpcie8250_startup;
+ up.port.shutdown = mxpcie8250_shutdown;
+
for (i = 0; i < num_ports; i++) {
if (mxpcie8250_setup(pdev, priv, &up, i))
break;
--
2.45.2