Commit e33253f3 authored by Michael Walle's avatar Michael Walle Committed by Greg Kroah-Hartman
Browse files

tty: serial: fsl_lpuart: add LS1028A earlycon support



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: default avatarMichael Walle <michael@walle.cc>
Link: https://lore.kernel.org/r/20200306214433.23215-5-michael@walle.cc


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent c2f448cf
Loading
Loading
Loading
Loading
+43 −8
Original line number Diff line number Diff line
@@ -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);