summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZang Roy-r61911 <tie-fei.zang@freescale.com>2006-06-30 02:29:58 -0700
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-07-09 21:11:09 +0100
commit3be91ec7388bae3cf1bfb4febcee5ab6c65f409f (patch)
treecb2fa80f81321e0d1dda6e88ca95ade081064624
parentc65b15cfd6b8b74c6f2b3635bf47ee661d351ef3 (diff)
[SERIAL] 8250: add tsi108 serial support
The following patch gets rid of CONFIG_TSI108_BRIDGE. I add UPIO_TSI to handle IIR and IER register in serial_in and serial_out. (1) the reason to rewrite serial_in: TSI108 rev Z1 version ERRATA. Reading the UART's Interrupt Identification Register (IIR) clears the Transmit Holding Register Empty (THRE) and Transmit buffer Empty (TEMP) interrupts even if they are not enabled in the Interrupt Enable Register (IER). This leads to loss of the interrupts. Interrupts are not cleared when reading UART registers as 32-bit word. (2) the reason to rewrite serial_out: Check for UART_IER_UUE bit in the autoconfig routine. This section of autoconfig is excluded for Tsi108/109 because bits 7 and 6 are reserved for internal use. They are R/W bits. In addition to incorrect identification, changing these bits (from 00) will make Tsi108/109 UART non-functional. Signed-off-by: Roy Zang <tie-fei.zang@freescale.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--drivers/serial/8250.c12
-rw-r--r--drivers/serial/serial_core.c1
-rw-r--r--include/linux/serial_core.h1
3 files changed, 14 insertions, 0 deletions
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 0995430e4cf1..5443fcd38355 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -299,6 +299,7 @@ static inline int map_8250_out_reg(struct uart_8250_port *up, int offset)
static unsigned int serial_in(struct uart_8250_port *up, int offset)
{
+ unsigned int tmp;
offset = map_8250_in_reg(up, offset) << up->port.regshift;
switch (up->port.iotype) {
@@ -317,6 +318,13 @@ static unsigned int serial_in(struct uart_8250_port *up, int offset)
return __raw_readl(up->port.membase + offset);
#endif
+ case UPIO_TSI:
+ if (offset == UART_IIR) {
+ tmp = readl((u32 *)(up->port.membase + UART_RX));
+ return (cpu_to_le32(tmp) >> 8) & 0xff;
+ } else
+ return readb(up->port.membase + offset);
+
default:
return inb(up->port.iobase + offset);
}
@@ -346,6 +354,10 @@ serial_out(struct uart_8250_port *up, int offset, int value)
__raw_writel(value, up->port.membase + offset);
break;
#endif
+ case UPIO_TSI:
+ if (!((offset == UART_IER) && (value & UART_IER_UUE)))
+ writeb(value, up->port.membase + offset);
+ break;
default:
outb(value, up->port.iobase + offset);
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index d5f636fbf29a..80ef7d482756 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -2036,6 +2036,7 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port)
case UPIO_MEM:
case UPIO_MEM32:
case UPIO_AU:
+ case UPIO_TSI:
snprintf(address, sizeof(address),
"MMIO 0x%lx", port->mapbase);
break;
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 058cba70818a..86501a3de2ac 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -227,6 +227,7 @@ struct uart_port {
#define UPIO_MEM (2)
#define UPIO_MEM32 (3)
#define UPIO_AU (4) /* Au1x00 type IO */
+#define UPIO_TSI (5) /* Tsi108/109 type IO */
unsigned int read_status_mask; /* driver specific */
unsigned int ignore_status_mask; /* driver specific */