Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b32b19b8 authored by Jon Anders Haugum's avatar Jon Anders Haugum Committed by Russell King
Browse files

[SERIAL] 8250: set divisor register correctly for AMD Alchemy SoC uart



Alchemy SoC uart have got a non-standard divisor register that needs some
special handling.

This patch adds divisor read/write functions with test and special
handling for Alchemy internal uart.

Signed-off-by: default avatarJon Anders Haugum <jonah@omegav.ntnu.no>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 85835f44
Loading
Loading
Loading
Loading
+42 −13
Original line number Diff line number Diff line
@@ -362,6 +362,40 @@ serial_out(struct uart_8250_port *up, int offset, int value)
#define serial_inp(up, offset)		serial_in(up, offset)
#define serial_outp(up, offset, value)	serial_out(up, offset, value)

/* Uart divisor latch read */
static inline int _serial_dl_read(struct uart_8250_port *up)
{
	return serial_inp(up, UART_DLL) | serial_inp(up, UART_DLM) << 8;
}

/* Uart divisor latch write */
static inline void _serial_dl_write(struct uart_8250_port *up, int value)
{
	serial_outp(up, UART_DLL, value & 0xff);
	serial_outp(up, UART_DLM, value >> 8 & 0xff);
}

#ifdef CONFIG_SERIAL_8250_AU1X00
/* Au1x00 haven't got a standard divisor latch */
static int serial_dl_read(struct uart_8250_port *up)
{
	if (up->port.iotype == UPIO_AU)
		return __raw_readl(up->port.membase + 0x28);
	else
		return _serial_dl_read(up);
}

static void serial_dl_write(struct uart_8250_port *up, int value)
{
	if (up->port.iotype == UPIO_AU)
		__raw_writel(value, up->port.membase + 0x28);
	else
		_serial_dl_write(up, value);
}
#else
#define serial_dl_read(up) _serial_dl_read(up)
#define serial_dl_write(up, value) _serial_dl_write(up, value)
#endif

/*
 * For the 16C950
@@ -494,7 +528,8 @@ static void disable_rsa(struct uart_8250_port *up)
 */
static int size_fifo(struct uart_8250_port *up)
{
	unsigned char old_fcr, old_mcr, old_dll, old_dlm, old_lcr;
	unsigned char old_fcr, old_mcr, old_lcr;
	unsigned short old_dl;
	int count;

	old_lcr = serial_inp(up, UART_LCR);
@@ -505,10 +540,8 @@ static int size_fifo(struct uart_8250_port *up)
		    UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
	serial_outp(up, UART_MCR, UART_MCR_LOOP);
	serial_outp(up, UART_LCR, UART_LCR_DLAB);
	old_dll = serial_inp(up, UART_DLL);
	old_dlm = serial_inp(up, UART_DLM);
	serial_outp(up, UART_DLL, 0x01);
	serial_outp(up, UART_DLM, 0x00);
	old_dl = serial_dl_read(up);
	serial_dl_write(up, 0x0001);
	serial_outp(up, UART_LCR, 0x03);
	for (count = 0; count < 256; count++)
		serial_outp(up, UART_TX, count);
@@ -519,8 +552,7 @@ static int size_fifo(struct uart_8250_port *up)
	serial_outp(up, UART_FCR, old_fcr);
	serial_outp(up, UART_MCR, old_mcr);
	serial_outp(up, UART_LCR, UART_LCR_DLAB);
	serial_outp(up, UART_DLL, old_dll);
	serial_outp(up, UART_DLM, old_dlm);
	serial_dl_write(up, old_dl);
	serial_outp(up, UART_LCR, old_lcr);

	return count;
@@ -750,8 +782,7 @@ static void autoconfig_16550a(struct uart_8250_port *up)

			serial_outp(up, UART_LCR, 0xE0);

			quot = serial_inp(up, UART_DLM) << 8;
			quot += serial_inp(up, UART_DLL);
			quot = serial_dl_read(up);
			quot <<= 3;

			status1 = serial_in(up, 0x04); /* EXCR1 */
@@ -759,8 +790,7 @@ static void autoconfig_16550a(struct uart_8250_port *up)
			status1 |= 0x10;  /* 1.625 divisor for baud_base --> 921600 */
			serial_outp(up, 0x04, status1);
			
			serial_outp(up, UART_DLL, quot & 0xff);
			serial_outp(up, UART_DLM, quot >> 8);
			serial_dl_write(up, quot);

			serial_outp(up, UART_LCR, 0);

@@ -1862,8 +1892,7 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios,
		serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
	}

	serial_outp(up, UART_DLL, quot & 0xff);		/* LS of divisor */
	serial_outp(up, UART_DLM, quot >> 8);		/* MS of divisor */
	serial_dl_write(up, quot);

	/*
	 * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR