[PATCH 5/5] serial-uartlite: Moved endianness detection to startup.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Factored out endianness detection to ulite_detect_endianness() and moved it
from ulite_request_port() to ulite_startup(). Always flush and detect presence.

Signed-off-by: Maarten Brock <m.brock@xxxxxxxxxxxxx>
---
 drivers/tty/serial/uartlite.c | 48 ++++++++++++++++++++++++++++++++++---------
 1 file changed, 38 insertions(+), 10 deletions(-)

diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c
index 4aeacfa..b4f0c14 100644
--- a/drivers/tty/serial/uartlite.c
+++ b/drivers/tty/serial/uartlite.c
@@ -257,10 +257,48 @@ static void ulite_break_ctl(struct uart_port *port, int ctl)
 	/* N/A */
 }
 
+static int ulite_detect_endianness(struct uart_port *port)
+{
+	int ret;
+
+	if (port->private_data == (void*)&uartlite_be) 	{
+		return 0;
+	}
+	if (port->private_data == (void*)&uartlite_le) 	{
+		return 0;
+	}
+
+	// Try to flush using little-endian interface first
+	port->private_data = (void*)&uartlite_le;
+	uart_out32(ULITE_CONTROL_RST_TX, ULITE_CONTROL, port);
+	ret = uart_in32(ULITE_STATUS, port);
+
+	// Endianness detection
+	if ((ret & ULITE_STATUS_TXEMPTY) != ULITE_STATUS_TXEMPTY) {
+		// Retry flush with big-endian interface
+		port->private_data = (void*)&uartlite_be;
+		uart_out32(ULITE_CONTROL_RST_TX, ULITE_CONTROL, port);
+		ret = uart_in32(ULITE_STATUS, port);
+
+		// Presence detection
+		if ((ret & ULITE_STATUS_TXEMPTY) != ULITE_STATUS_TXEMPTY) {
+			port->private_data = NULL;
+			pr_err("[/dev/ttyUL%d] ENDIAN check failed\n", port->line);
+			return -ENODEV;
+		}
+	}
+
+	return 0;
+}
+
 static int ulite_startup(struct uart_port *port)
 {
 	int ret;
 
+	ret = ulite_detect_endianness(port);
+	if (ret)
+		return ret;
+
 	ret = request_irq(port->irq, ulite_isr, IRQF_SHARED | IRQF_TRIGGER_RISING,
 			  "uartlite", port);
 	if (ret)
@@ -327,8 +365,6 @@ static void ulite_release_port(struct uart_port *port)
 
 static int ulite_request_port(struct uart_port *port)
 {
-	int ret;
-
 	pr_debug("ulite console: port=%p; port->mapbase=%llx\n",
 		 port, (unsigned long long) port->mapbase);
 
@@ -344,14 +380,6 @@ static int ulite_request_port(struct uart_port *port)
 		return -EBUSY;
 	}
 
-	port->private_data = &uartlite_be;
-	ret = uart_in32(ULITE_CONTROL, port);
-	uart_out32(ULITE_CONTROL_RST_TX, ULITE_CONTROL, port);
-	ret = uart_in32(ULITE_STATUS, port);
-	/* Endianess detection */
-	if ((ret & ULITE_STATUS_TXEMPTY) != ULITE_STATUS_TXEMPTY)
-		port->private_data = &uartlite_le;
-
 	return 0;
 }
 
-- 
1.8.3.1

--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux