From cc419fa0d38c425e4ea7bffeed931b07b0a3e461 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 2 May 2012 21:46:51 +0900 Subject: [PATCH] serial8250: Add dl_read()/dl_write() callbacks Convert serial_dl_read() and serial_dl_write() from macro to 8250 specific callbacks. This change makes it easier to support 8250 hardware with non-standard DLL and DLM register configurations such as Alchemy, RM9K and upcoming Emma Mobile UART hardware. Signed-off-by: Magnus Damm Acked-by: Arnd Bergmann Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250.c | 117 ++++++++++++++++++--------------- drivers/tty/serial/8250/8250.h | 14 ++++ 2 files changed, 78 insertions(+), 53 deletions(-) diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c index c9ac4eabe35..590ee85150b 100644 --- a/drivers/tty/serial/8250/8250.c +++ b/drivers/tty/serial/8250/8250.c @@ -284,6 +284,66 @@ static const struct serial8250_config uart_config[] = { }, }; +/* Uart divisor latch read */ +static int default_dl_read(struct uart_8250_port *up) +{ + return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8; +} + +/* Uart divisor latch write */ +static void default_dl_write(struct uart_8250_port *up, int value) +{ + serial_out(up, UART_DLL, value & 0xff); + serial_out(up, UART_DLM, value >> 8 & 0xff); +} + +#if defined(CONFIG_MIPS_ALCHEMY) +/* 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 default_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 + default_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) : + default_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 { + default_dl_write(up, value); + } +} +#else +static int _serial_dl_read(struct uart_8250_port *up) +{ + return default_dl_read(up); +} + +static void _serial_dl_write(struct uart_8250_port *up, int value) +{ + default_dl_write(up, value); +} +#endif + #if defined(CONFIG_MIPS_ALCHEMY) /* Au1x00 UART hardware has a weird register layout */ @@ -434,6 +494,10 @@ static void set_io_from_upio(struct uart_port *p) { struct uart_8250_port *up = container_of(p, struct uart_8250_port, port); + + up->dl_read = _serial_dl_read; + up->dl_write = _serial_dl_write; + switch (p->iotype) { case UPIO_HUB6: p->serial_in = hub6_serial_in; @@ -481,59 +545,6 @@ serial_port_out_sync(struct uart_port *p, int offset, int value) } } -/* Uart divisor latch read */ -static inline int _serial_dl_read(struct uart_8250_port *up) -{ - return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8; -} - -/* Uart divisor latch write */ -static inline void _serial_dl_write(struct uart_8250_port *up, int value) -{ - serial_out(up, UART_DLL, value & 0xff); - serial_out(up, UART_DLM, value >> 8 & 0xff); -} - -#if defined(CONFIG_MIPS_ALCHEMY) -/* 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); -} -#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) -#endif - /* * For the 16C950 */ diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index c9d0ebe952f..f9719d167c8 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -37,6 +37,10 @@ struct uart_8250_port { unsigned char lsr_saved_flags; #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA unsigned char msr_saved_flags; + + /* 8250 specific callbacks */ + int (*dl_read)(struct uart_8250_port *); + void (*dl_write)(struct uart_8250_port *, int); }; struct old_serial_port { @@ -98,6 +102,16 @@ static inline void serial_out(struct uart_8250_port *up, int offset, int value) void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p); +static inline int serial_dl_read(struct uart_8250_port *up) +{ + return up->dl_read(up); +} + +static inline void serial_dl_write(struct uart_8250_port *up, int value) +{ + up->dl_write(up, value); +} + #if defined(__alpha__) && !defined(CONFIG_PCI) /* * Digital did something really horribly wrong with the OUT1 and OUT2 -- 2.20.1