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