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

Commit bd71c182 authored by Thomas Koeller's avatar Thomas Koeller Committed by Linus Torvalds
Browse files

RM9000 serial driver



Add support for the integrated serial ports of the MIPS RM9122 processor
and its relatives.

The patch also does some whitespace cleanup.

[akpm@linux-foundation.org: cleanups]
Signed-off-by: default avatarThomas Koeller <thomas.koeller@baslerweb.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Russell King <rmk@arm.linux.org.uk>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent beab697a
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -1042,6 +1042,9 @@ config SOC_AU1X00
	select SYS_SUPPORTS_APM_EMULATION
	select SYS_SUPPORTS_KGDB

config SERIAL_RM9000
	bool

config PNX8550
	bool
	select SOC_PNX8550
+80 −12
Original line number Diff line number Diff line
@@ -251,9 +251,16 @@ static const struct serial8250_config uart_config[] = {
		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
		.flags		= UART_CAP_FIFO | UART_CAP_UUE,
	},
	[PORT_RM9000] = {
		.name		= "RM9000",
		.fifo_size	= 16,
		.tx_loadsz	= 16,
		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
		.flags		= UART_CAP_FIFO,
	},
};

#ifdef CONFIG_SERIAL_8250_AU1X00
#if defined (CONFIG_SERIAL_8250_AU1X00)

/* Au1x00 UART hardware has a weird register layout */
static const u8 au_io_in_map[] = {
@@ -289,6 +296,44 @@ static inline int map_8250_out_reg(struct uart_8250_port *up, int offset)
	return au_io_out_map[offset];
}

#elif defined (CONFIG_SERIAL_8250_RM9K)

static const u8
	regmap_in[8] = {
		[UART_RX]	= 0x00,
		[UART_IER]	= 0x0c,
		[UART_IIR]	= 0x14,
		[UART_LCR]	= 0x1c,
		[UART_MCR]	= 0x20,
		[UART_LSR]	= 0x24,
		[UART_MSR]	= 0x28,
		[UART_SCR]	= 0x2c
	},
	regmap_out[8] = {
		[UART_TX] 	= 0x04,
		[UART_IER]	= 0x0c,
		[UART_FCR]	= 0x18,
		[UART_LCR]	= 0x1c,
		[UART_MCR]	= 0x20,
		[UART_LSR]	= 0x24,
		[UART_MSR]	= 0x28,
		[UART_SCR]	= 0x2c
	};

static inline int map_8250_in_reg(struct uart_8250_port *up, int offset)
{
	if (up->port.iotype != UPIO_RM9000)
		return offset;
	return regmap_in[offset];
}

static inline int map_8250_out_reg(struct uart_8250_port *up, int offset)
{
	if (up->port.iotype != UPIO_RM9000)
		return offset;
	return regmap_out[offset];
}

#else

/* sane hardware needs no mapping */
@@ -311,6 +356,7 @@ static unsigned int serial_in(struct uart_8250_port *up, int offset)
	case UPIO_DWAPB:
		return readb(up->port.membase + offset);

	case UPIO_RM9000:
	case UPIO_MEM32:
		return readl(up->port.membase + offset);

@@ -348,6 +394,7 @@ serial_out(struct uart_8250_port *up, int offset, int value)
		writeb(value, up->port.membase + offset);
		break;

	case UPIO_RM9000:
	case UPIO_MEM32:
		writel(value, up->port.membase + offset);
		break;
@@ -419,7 +466,7 @@ static inline void _serial_dl_write(struct uart_8250_port *up, int value)
	serial_outp(up, UART_DLM, value >> 8 & 0xff);
}

#ifdef CONFIG_SERIAL_8250_AU1X00
#if defined (CONFIG_SERIAL_8250_AU1X00)
/* Au1x00 haven't got a standard divisor latch */
static int serial_dl_read(struct uart_8250_port *up)
{
@@ -436,6 +483,24 @@ static void serial_dl_write(struct uart_8250_port *up, int value)
	else
		_serial_dl_write(up, value);
}
#elif defined (CONFIG_SERIAL_8250_RM9K)
static int serial_dl_read(struct uart_8250_port *up)
{
	return	(up->port.iotype == UPIO_RM9000) ?
		(((__raw_readl(up->port.membase + 0x10) << 8) |
		(__raw_readl(up->port.membase + 0x08) & 0xff)) & 0xffff) :
		_serial_dl_read(up);
}

static void serial_dl_write(struct uart_8250_port *up, int value)
{
	if (up->port.iotype == UPIO_RM9000) {
		__raw_writel(value, up->port.membase + 0x08);
		__raw_writel(value >> 8, up->port.membase + 0x10);
	} 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)
@@ -1175,8 +1240,11 @@ static void serial8250_start_tx(struct uart_port *port)
		if (up->bugs & UART_BUG_TXEN) {
			unsigned char lsr, iir;
			lsr = serial_in(up, UART_LSR);
			iir = serial_in(up, UART_IIR);
			if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT)
			iir = serial_in(up, UART_IIR) & 0x0f;
			if ((up->port.type == PORT_RM9000) ?
				(lsr & UART_LSR_THRE &&
				(iir == UART_IIR_NO_INT || iir == UART_IIR_THRI)) :
				(lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT))
				transmit_chars(up);
		}
	}
+9 −0
Original line number Diff line number Diff line
@@ -254,6 +254,15 @@ config SERIAL_8250_AU1X00
	  to this option.  The driver can handle 1 or 2 serial ports.
	  If unsure, say N.

config SERIAL_8250_RM9K
	bool "Support for MIPS RM9xxx integrated serial port"
	depends on SERIAL_8250 != n && SERIAL_RM9000
	select SERIAL_8250_SHARE_IRQ
	help
	  Selecting this option will add support for the integrated serial
	  port hardware found on MIPS RM9122 and similar processors.
	  If unsure, say N.

comment "Non-8250 serial port support"

config SERIAL_AMBA_PL010
+3 −1
Original line number Diff line number Diff line
@@ -39,7 +39,8 @@
#define PORT_RSA	13
#define PORT_NS16550A	14
#define PORT_XSCALE	15
#define PORT_MAX_8250	15	/* max port ID */
#define PORT_RM9000	16	/* PMC-Sierra RM9xxx internal UART */
#define PORT_MAX_8250	16	/* max port ID */

/*
 * ARM specific type numbers.  These are not currently guaranteed
@@ -231,6 +232,7 @@ struct uart_port {
#define UPIO_AU			(4)			/* Au1x00 type IO */
#define UPIO_TSI		(5)			/* Tsi108/109 type IO */
#define UPIO_DWAPB		(6)			/* DesignWare APB UART */
#define UPIO_RM9000		(7)			/* RM9000 type IO */

	unsigned int		read_status_mask;	/* driver specific */
	unsigned int		ignore_status_mask;	/* driver specific */