Commit ee9e2c8a authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://bk.arm.linux.org.uk/linux-2.6-serial

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents 07b03017 1e6d9d3c
...@@ -130,6 +130,7 @@ struct uart_8250_port { ...@@ -130,6 +130,7 @@ struct uart_8250_port {
struct timer_list timer; /* "no irq" timer */ struct timer_list timer; /* "no irq" timer */
struct list_head list; /* ports on this IRQ */ struct list_head list; /* ports on this IRQ */
unsigned int capabilities; /* port capabilities */ unsigned int capabilities; /* port capabilities */
unsigned int tx_loadsz; /* transmit fifo load size */
unsigned short rev; unsigned short rev;
unsigned char acr; unsigned char acr;
unsigned char ier; unsigned char ier;
...@@ -156,23 +157,23 @@ static struct irq_info irq_lists[NR_IRQS]; ...@@ -156,23 +157,23 @@ static struct irq_info irq_lists[NR_IRQS];
/* /*
* Here we define the default xmit fifo size used for each type of UART. * Here we define the default xmit fifo size used for each type of UART.
*/ */
static const struct serial_uart_config uart_config[PORT_MAX_8250+1] = { static const struct serial8250_config uart_config[PORT_MAX_8250+1] = {
{ "unknown", 1, 0 }, { "unknown", 1, 1, 0 },
{ "8250", 1, 0 }, { "8250", 1, 1, 0 },
{ "16450", 1, 0 }, { "16450", 1, 1, 0 },
{ "16550", 1, 0 }, { "16550", 1, 1, 0 },
{ "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO }, { "16550A", 16, 16, UART_CAP_FIFO },
{ "Cirrus", 1, 0 }, { "Cirrus", 1, 1, 0 },
{ "ST16650", 1, UART_CLEAR_FIFO | UART_STARTECH }, { "ST16650", 1, 1, UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_EFR },
{ "ST16650V2", 32, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH }, { "ST16650V2", 32, 16, UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_EFR },
{ "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO }, { "TI16750", 64, 64, UART_CAP_FIFO | UART_CAP_SLEEP },
{ "Startech", 1, 0 }, { "Startech", 1, 1, 0 },
{ "16C950/954", 128, UART_CLEAR_FIFO | UART_USE_FIFO }, { "16C950/954", 128, 128, UART_CAP_FIFO },
{ "ST16654", 64, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH }, { "ST16654", 64, 32, UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_EFR },
{ "XR16850", 128, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH }, { "XR16850", 128, 128, UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_EFR },
{ "RSA", 2048, UART_CLEAR_FIFO | UART_USE_FIFO }, { "RSA", 2048, 2048, UART_CAP_FIFO },
{ "NS16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO | UART_NATSEMI }, { "NS16550A", 16, 16, UART_CAP_FIFO | UART_NATSEMI },
{ "XScale", 32, UART_CLEAR_FIFO | UART_USE_FIFO }, { "XScale", 32, 32, UART_CAP_FIFO },
}; };
static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset) static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset)
...@@ -243,6 +244,41 @@ static unsigned int serial_icr_read(struct uart_8250_port *up, int offset) ...@@ -243,6 +244,41 @@ static unsigned int serial_icr_read(struct uart_8250_port *up, int offset)
return value; return value;
} }
/*
* FIFO support.
*/
static inline void serial8250_clear_fifos(struct uart_8250_port *p)
{
if (p->capabilities & UART_CAP_FIFO) {
serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO);
serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO |
UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
serial_outp(p, UART_FCR, 0);
}
}
/*
* IER sleep support. UARTs which have EFRs need the "extended
* capability" bit enabled. Note that on XR16C850s, we need to
* reset LCR to write to IER.
*/
static inline void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
{
if (p->capabilities & UART_CAP_SLEEP) {
if (p->capabilities & UART_CAP_EFR) {
serial_outp(p, UART_LCR, 0xBF);
serial_outp(p, UART_EFR, UART_EFR_ECB);
serial_outp(p, UART_LCR, 0);
}
serial_outp(p, UART_IER, sleep ? UART_IERX_SLEEP : 0);
if (p->capabilities & UART_CAP_EFR) {
serial_outp(p, UART_LCR, 0xBF);
serial_outp(p, UART_EFR, 0);
serial_outp(p, UART_LCR, 0);
}
}
}
#ifdef CONFIG_SERIAL_8250_RSA #ifdef CONFIG_SERIAL_8250_RSA
/* /*
* Attempts to turn on the RSA FIFO. Returns zero on failure. * Attempts to turn on the RSA FIFO. Returns zero on failure.
...@@ -697,8 +733,9 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) ...@@ -697,8 +733,9 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
#endif #endif
serial_outp(up, UART_LCR, save_lcr); serial_outp(up, UART_LCR, save_lcr);
up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size; up->port.fifosize = uart_config[up->port.type].fifo_size;
up->capabilities = uart_config[up->port.type].flags; up->capabilities = uart_config[up->port.type].flags;
up->tx_loadsz = uart_config[up->port.type].tx_loadsz;
if (up->port.type == PORT_UNKNOWN) if (up->port.type == PORT_UNKNOWN)
goto out; goto out;
...@@ -711,10 +748,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) ...@@ -711,10 +748,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
serial_outp(up, UART_RSA_FRR, 0); serial_outp(up, UART_RSA_FRR, 0);
#endif #endif
serial_outp(up, UART_MCR, save_mcr); serial_outp(up, UART_MCR, save_mcr);
serial_outp(up, UART_FCR, (UART_FCR_ENABLE_FIFO | serial8250_clear_fifos(up);
UART_FCR_CLEAR_RCVR |
UART_FCR_CLEAR_XMIT));
serial_outp(up, UART_FCR, 0);
(void)serial_in(up, UART_RX); (void)serial_in(up, UART_RX);
serial_outp(up, UART_IER, 0); serial_outp(up, UART_IER, 0);
...@@ -923,7 +957,7 @@ static _INLINE_ void transmit_chars(struct uart_8250_port *up) ...@@ -923,7 +957,7 @@ static _INLINE_ void transmit_chars(struct uart_8250_port *up)
return; return;
} }
count = up->port.fifosize; count = up->tx_loadsz;
do { do {
serial_out(up, UART_TX, xmit->buf[xmit->tail]); serial_out(up, UART_TX, xmit->buf[xmit->tail]);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
...@@ -1227,12 +1261,7 @@ static int serial8250_startup(struct uart_port *port) ...@@ -1227,12 +1261,7 @@ static int serial8250_startup(struct uart_port *port)
* Clear the FIFO buffers and disable them. * Clear the FIFO buffers and disable them.
* (they will be reeanbled in set_termios()) * (they will be reeanbled in set_termios())
*/ */
if (up->capabilities & UART_CLEAR_FIFO) { serial8250_clear_fifos(up);
serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
serial_outp(up, UART_FCR, 0);
}
/* /*
* Clear the interrupt registers. * Clear the interrupt registers.
...@@ -1253,6 +1282,23 @@ static int serial8250_startup(struct uart_port *port) ...@@ -1253,6 +1282,23 @@ static int serial8250_startup(struct uart_port *port)
return -ENODEV; return -ENODEV;
} }
/*
* For a XR16C850, we need to set the trigger levels
*/
if (up->port.type == PORT_16850) {
unsigned char fctr;
serial_outp(up, UART_LCR, 0xbf);
fctr = serial_inp(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX);
serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_RX);
serial_outp(up, UART_TRG, UART_TRG_96);
serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_TX);
serial_outp(up, UART_TRG, UART_TRG_96);
serial_outp(up, UART_LCR, 0);
}
/* /*
* If the "interrupt" for this port doesn't correspond with any * If the "interrupt" for this port doesn't correspond with any
* hardware interrupt, we use a timer-based system. The original * hardware interrupt, we use a timer-based system. The original
...@@ -1345,10 +1391,7 @@ static void serial8250_shutdown(struct uart_port *port) ...@@ -1345,10 +1391,7 @@ static void serial8250_shutdown(struct uart_port *port)
* Disable break condition and FIFOs * Disable break condition and FIFOs
*/ */
serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC); serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC);
serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | serial8250_clear_fifos(up);
UART_FCR_CLEAR_RCVR |
UART_FCR_CLEAR_XMIT);
serial_outp(up, UART_FCR, 0);
#ifdef CONFIG_SERIAL_8250_RSA #ifdef CONFIG_SERIAL_8250_RSA
/* /*
...@@ -1440,7 +1483,7 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios, ...@@ -1440,7 +1483,7 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios,
up->rev == 0x5201) up->rev == 0x5201)
quot ++; quot ++;
if (up->capabilities & UART_USE_FIFO) { if (up->capabilities & UART_CAP_FIFO && up->port.fifosize > 1) {
if (baud < 2400) if (baud < 2400)
fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1; fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
#ifdef CONFIG_SERIAL_8250_RSA #ifdef CONFIG_SERIAL_8250_RSA
...@@ -1514,7 +1557,7 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios, ...@@ -1514,7 +1557,7 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios,
serial_out(up, UART_IER, up->ier); serial_out(up, UART_IER, up->ier);
if (up->capabilities & UART_STARTECH) { if (up->capabilities & UART_CAP_EFR) {
serial_outp(up, UART_LCR, 0xBF); serial_outp(up, UART_LCR, 0xBF);
serial_outp(up, UART_EFR, serial_outp(up, UART_EFR,
termios->c_cflag & CRTSCTS ? UART_EFR_CTS :0); termios->c_cflag & CRTSCTS ? UART_EFR_CTS :0);
...@@ -1554,71 +1597,12 @@ static void ...@@ -1554,71 +1597,12 @@ static void
serial8250_pm(struct uart_port *port, unsigned int state, serial8250_pm(struct uart_port *port, unsigned int state,
unsigned int oldstate) unsigned int oldstate)
{ {
struct uart_8250_port *up = (struct uart_8250_port *)port; struct uart_8250_port *p = (struct uart_8250_port *)port;
if (state) {
/* sleep */
if (up->capabilities & UART_STARTECH) {
/* Arrange to enter sleep mode */
serial_outp(up, UART_LCR, 0xBF);
serial_outp(up, UART_EFR, UART_EFR_ECB);
serial_outp(up, UART_LCR, 0);
serial_outp(up, UART_IER, UART_IERX_SLEEP);
serial_outp(up, UART_LCR, 0xBF);
serial_outp(up, UART_EFR, 0);
serial_outp(up, UART_LCR, 0);
}
if (up->port.type == PORT_16750) {
/* Arrange to enter sleep mode */
serial_outp(up, UART_IER, UART_IERX_SLEEP);
}
if (up->pm) serial8250_set_sleep(p, state != 0);
up->pm(port, state, oldstate);
} else {
/* wake */
if (up->capabilities & UART_STARTECH) {
/* Wake up UART */
serial_outp(up, UART_LCR, 0xBF);
serial_outp(up, UART_EFR, UART_EFR_ECB);
/*
* Turn off LCR == 0xBF so we actually set the IER
* register on the XR16C850
*/
serial_outp(up, UART_LCR, 0);
serial_outp(up, UART_IER, 0);
/*
* Now reset LCR so we can turn off the ECB bit
*/
serial_outp(up, UART_LCR, 0xBF);
serial_outp(up, UART_EFR, 0);
/*
* For a XR16C850, we need to set the trigger levels
*/
if (up->port.type == PORT_16850) {
unsigned char fctr;
fctr = serial_inp(up, UART_FCTR) &
~(UART_FCTR_RX | UART_FCTR_TX);
serial_outp(up, UART_FCTR, fctr |
UART_FCTR_TRGD |
UART_FCTR_RX);
serial_outp(up, UART_TRG, UART_TRG_96);
serial_outp(up, UART_FCTR, fctr |
UART_FCTR_TRGD |
UART_FCTR_TX);
serial_outp(up, UART_TRG, UART_TRG_96);
}
serial_outp(up, UART_LCR, 0);
}
if (up->port.type == PORT_16750) { if (p->pm)
/* Wake up UART */ p->pm(port, state, oldstate);
serial_outp(up, UART_IER, 0);
}
if (up->pm)
up->pm(port, state, oldstate);
}
} }
/* /*
......
...@@ -33,6 +33,20 @@ struct old_serial_port { ...@@ -33,6 +33,20 @@ struct old_serial_port {
unsigned short iomem_reg_shift; unsigned short iomem_reg_shift;
}; };
/*
* This replaces serial_uart_config in include/linux/serial.h
*/
struct serial8250_config {
const char *name;
unsigned int fifo_size;
unsigned int tx_loadsz;
unsigned int flags;
};
#define UART_CAP_FIFO (1 << 8) /* UART has FIFO */
#define UART_CAP_EFR (1 << 9) /* UART has EFR */
#define UART_CAP_SLEEP (1 << 10) /* UART has IER sleep */
#undef SERIAL_DEBUG_PCI #undef SERIAL_DEBUG_PCI
#if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486)) #if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment