tty: serial: fsl_lpuart: add LS1028A earlycon support
authorMichael Walle <michael@walle.cc>
Fri, 6 Mar 2020 21:44:33 +0000 (22:44 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 12 Mar 2020 09:02:00 +0000 (10:02 +0100)
Add a early_console_setup() for the LS1028A SoC with 32bit, little
endian access. If the bootloader does a fixup of the clock-frequency
node the baudrate divisor register will automatically be set.

Signed-off-by: Michael Walle <michael@walle.cc>
Link: https://lore.kernel.org/r/20200306214433.23215-5-michael@walle.cc
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/fsl_lpuart.c

index 1d4f75716e32451152ec876b06aab910c234a5c0..9c6a018b139041d2c2d67f606f172b8f266e9745 100644 (file)
@@ -1878,11 +1878,12 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
        spin_unlock_irqrestore(&sport->port.lock, flags);
 }
 
-static void
-lpuart32_serial_setbrg(struct lpuart_port *sport, unsigned int baudrate)
+static void __lpuart32_serial_setbrg(struct uart_port *port,
+                                    unsigned int baudrate, bool use_rx_dma,
+                                    bool use_tx_dma)
 {
        u32 sbr, osr, baud_diff, tmp_osr, tmp_sbr, tmp_diff, tmp;
-       u32 clk = sport->port.uartclk;
+       u32 clk = port->uartclk;
 
        /*
         * The idea is to use the best OSR (over-sampling rate) possible.
@@ -1928,10 +1929,10 @@ lpuart32_serial_setbrg(struct lpuart_port *sport, unsigned int baudrate)
 
        /* handle buadrate outside acceptable rate */
        if (baud_diff > ((baudrate / 100) * 3))
-               dev_warn(sport->port.dev,
+               dev_warn(port->dev,
                         "unacceptable baud rate difference of more than 3%%\n");
 
-       tmp = lpuart32_read(&sport->port, UARTBAUD);
+       tmp = lpuart32_read(port, UARTBAUD);
 
        if ((osr > 3) && (osr < 8))
                tmp |= UARTBAUD_BOTHEDGE;
@@ -1942,14 +1943,23 @@ lpuart32_serial_setbrg(struct lpuart_port *sport, unsigned int baudrate)
        tmp &= ~UARTBAUD_SBR_MASK;
        tmp |= sbr & UARTBAUD_SBR_MASK;
 
-       if (!sport->lpuart_dma_rx_use)
+       if (!use_rx_dma)
                tmp &= ~UARTBAUD_RDMAE;
-       if (!sport->lpuart_dma_tx_use)
+       if (!use_tx_dma)
                tmp &= ~UARTBAUD_TDMAE;
 
-       lpuart32_write(&sport->port, tmp, UARTBAUD);
+       lpuart32_write(port, tmp, UARTBAUD);
+}
+
+static void lpuart32_serial_setbrg(struct lpuart_port *sport,
+                                  unsigned int baudrate)
+{
+       __lpuart32_serial_setbrg(&sport->port, baudrate,
+                                sport->lpuart_dma_rx_use,
+                                sport->lpuart_dma_tx_use);
 }
 
+
 static void
 lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
                   struct ktermios *old)
@@ -2443,6 +2453,30 @@ static int __init lpuart32_early_console_setup(struct earlycon_device *device,
        return 0;
 }
 
+static int __init ls1028a_early_console_setup(struct earlycon_device *device,
+                                             const char *opt)
+{
+       u32 cr;
+
+       if (!device->port.membase)
+               return -ENODEV;
+
+       device->port.iotype = UPIO_MEM32;
+       device->con->write = lpuart32_early_write;
+
+       /* set the baudrate */
+       if (device->port.uartclk && device->baud)
+               __lpuart32_serial_setbrg(&device->port, device->baud,
+                                        false, false);
+
+       /* enable transmitter */
+       cr = lpuart32_read(&device->port, UARTCTRL);
+       cr |= UARTCTRL_TE;
+       lpuart32_write(&device->port, cr, UARTCTRL);
+
+       return 0;
+}
+
 static int __init lpuart32_imx_early_console_setup(struct earlycon_device *device,
                                                   const char *opt)
 {
@@ -2457,6 +2491,7 @@ static int __init lpuart32_imx_early_console_setup(struct earlycon_device *devic
 }
 OF_EARLYCON_DECLARE(lpuart, "fsl,vf610-lpuart", lpuart_early_console_setup);
 OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1021a-lpuart", lpuart32_early_console_setup);
+OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1028a-lpuart", ls1028a_early_console_setup);
 OF_EARLYCON_DECLARE(lpuart32, "fsl,imx7ulp-lpuart", lpuart32_imx_early_console_setup);
 EARLYCON_DECLARE(lpuart, lpuart_early_console_setup);
 EARLYCON_DECLARE(lpuart32, lpuart32_early_console_setup);