From 552114b8cbbd956ad8466261b5f11b059eba82ca Mon Sep 17 00:00:00 2001
From: Minda Chen <minda.chen@starfivetech.com>
Date: Sun, 25 Jun 2023 09:40:29 +0800
Subject: [PATCH 066/116] uart: 8250: Add dw auto flow ctrl support

Add designeware 8250 auto flow ctrl support. Enable
it by add auto-flow-control in dts.

Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
---
 drivers/tty/serial/8250/8250_core.c |  2 ++
 drivers/tty/serial/8250/8250_dw.c   |  3 +++
 drivers/tty/serial/8250/8250_port.c | 14 +++++++++++++-
 include/linux/serial_8250.h         |  1 +
 include/uapi/linux/serial_core.h    |  2 ++
 5 files changed, 21 insertions(+), 1 deletion(-)

--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -1129,6 +1129,8 @@ int serial8250_register_8250_port(const
 			uart->dl_read = up->dl_read;
 		if (up->dl_write)
 			uart->dl_write = up->dl_write;
+		if (up->probe)
+			uart->probe = up->probe;
 
 		if (uart->port.type != PORT_8250_CIR) {
 			if (serial8250_isa_config != NULL)
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -612,6 +612,9 @@ static int dw8250_probe(struct platform_
 		data->msr_mask_off |= UART_MSR_TERI;
 	}
 
+	if (device_property_read_bool(dev, "auto-flow-control"))
+		up->probe |= UART_PROBE_AFE;
+
 	/* If there is separate baudclk, get the rate from it. */
 	data->clk = devm_clk_get_optional(dev, "baudclk");
 	if (data->clk == NULL)
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -330,6 +330,14 @@ static const struct serial8250_config ua
 		.rxtrig_bytes	= {1, 8, 16, 30},
 		.flags		= UART_CAP_FIFO | UART_CAP_AFE,
 	},
+	[PORT_16550A_AFE] = {
+		.name		= "16550A_AFE",
+		.fifo_size	= 16,
+		.tx_loadsz	= 16,
+		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+		.rxtrig_bytes	= {1, 4, 8, 14},
+		.flags		= UART_CAP_FIFO | UART_CAP_AFE,
+	},
 };
 
 /* Uart divisor latch read */
@@ -1143,6 +1151,11 @@ static void autoconfig_16550a(struct uar
 		up->port.type = PORT_U6_16550A;
 		up->capabilities |= UART_CAP_AFE;
 	}
+
+	if ((up->port.type == PORT_16550A) && (up->probe & UART_PROBE_AFE)) {
+		up->port.type = PORT_16550A_AFE;
+		up->capabilities |= UART_CAP_AFE;
+	}
 }
 
 /*
@@ -2813,7 +2826,6 @@ serial8250_do_set_termios(struct uart_po
 		if (termios->c_cflag & CRTSCTS)
 			up->mcr |= UART_MCR_AFE;
 	}
-
 	/*
 	 * Update the per-port timeout.
 	 */
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -141,6 +141,7 @@ struct uart_8250_port {
 	unsigned char		probe;
 	struct mctrl_gpios	*gpios;
 #define UART_PROBE_RSA	(1 << 0)
+#define UART_PROBE_AFE  (1 << 1)
 
 	/*
 	 * Some bits in registers are cleared on a read, so they must
--- a/include/uapi/linux/serial_core.h
+++ b/include/uapi/linux/serial_core.h
@@ -245,4 +245,6 @@
 /* Sunplus UART */
 #define PORT_SUNPLUS	123
 
+#define PORT_16550A_AFE	124
+
 #endif /* _UAPILINUX_SERIAL_CORE_H */
