diff options
Diffstat (limited to 'drivers/tty/serial/uartlite.c')
-rw-r--r-- | drivers/tty/serial/uartlite.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c index b1c6bd3d483f..ee2e8efdea4a 100644 --- a/drivers/tty/serial/uartlite.c +++ b/drivers/tty/serial/uartlite.c @@ -194,7 +194,9 @@ static irqreturn_t ulite_isr(int irq, void *dev_id) { struct uart_port *port = dev_id; int busy, n = 0; + unsigned long flags; + spin_lock_irqsave(&port->lock, flags); do { int stat = uart_in32(ULITE_STATUS, port); busy = ulite_receive(port, stat); @@ -202,6 +204,8 @@ static irqreturn_t ulite_isr(int irq, void *dev_id) n++; } while (busy); + spin_unlock_irqrestore(&port->lock, flags); + /* work done? */ if (n > 1) { tty_flip_buffer_push(&port->state->port); @@ -519,6 +523,47 @@ static int __init ulite_console_init(void) console_initcall(ulite_console_init); +static void early_uartlite_putc(struct uart_port *port, int c) +{ + /* + * Limit how many times we'll spin waiting for TX FIFO status. + * This will prevent lockups if the base address is incorrectly + * set, or any other issue on the UARTLITE. + * This limit is pretty arbitrary, unless we are at about 10 baud + * we'll never timeout on a working UART. + */ + + unsigned retries = 1000000; + /* read status bit - 0x8 offset */ + while (--retries && (readl(port->membase + 8) & (1 << 3))) + ; + + /* Only attempt the iowrite if we didn't timeout */ + /* write to TX_FIFO - 0x4 offset */ + if (retries) + writel(c & 0xff, port->membase + 4); +} + +static void early_uartlite_write(struct console *console, + const char *s, unsigned n) +{ + struct earlycon_device *device = console->data; + uart_console_write(&device->port, s, n, early_uartlite_putc); +} + +static int __init early_uartlite_setup(struct earlycon_device *device, + const char *options) +{ + if (!device->port.membase) + return -ENODEV; + + device->con->write = early_uartlite_write; + return 0; +} +EARLYCON_DECLARE(uartlite, early_uartlite_setup); +OF_EARLYCON_DECLARE(uartlite_b, "xlnx,opb-uartlite-1.00.b", early_uartlite_setup); +OF_EARLYCON_DECLARE(uartlite_a, "xlnx,xps-uartlite-1.00.a", early_uartlite_setup); + #endif /* CONFIG_SERIAL_UARTLITE_CONSOLE */ static struct uart_driver ulite_uart_driver = { |