struct timer_list timer; /* "no irq" timer */
struct list_head list; /* ports on this IRQ */
unsigned int capabilities; /* port capabilities */
+ unsigned int tx_loadsz; /* transmit fifo load size */
unsigned short rev;
unsigned char acr;
unsigned char ier;
/*
* 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] = {
- { "unknown", 1, 0 },
- { "8250", 1, 0 },
- { "16450", 1, 0 },
- { "16550", 1, 0 },
- { "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO },
- { "Cirrus", 1, 0 },
- { "ST16650", 1, UART_CLEAR_FIFO | UART_STARTECH },
- { "ST16650V2", 32, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
- { "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO },
- { "Startech", 1, 0 },
- { "16C950/954", 128, UART_CLEAR_FIFO | UART_USE_FIFO },
- { "ST16654", 64, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
- { "XR16850", 128, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
- { "RSA", 2048, UART_CLEAR_FIFO | UART_USE_FIFO },
- { "NS16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO | UART_NATSEMI },
- { "XScale", 32, UART_CLEAR_FIFO | UART_USE_FIFO },
+static const struct serial8250_config uart_config[PORT_MAX_8250+1] = {
+ { "unknown", 1, 1, 0 },
+ { "8250", 1, 1, 0 },
+ { "16450", 1, 1, 0 },
+ { "16550", 1, 1, 0 },
+ { "16550A", 16, 16, UART_CAP_FIFO },
+ { "Cirrus", 1, 1, 0 },
+ { "ST16650", 1, 1, UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_EFR },
+ { "ST16650V2", 32, 16, UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_EFR },
+ { "TI16750", 64, 64, UART_CAP_FIFO | UART_CAP_SLEEP },
+ { "Startech", 1, 1, 0 },
+ { "16C950/954", 128, 128, UART_CAP_FIFO },
+ { "ST16654", 64, 32, UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_EFR },
+ { "XR16850", 128, 128, UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_EFR },
+ { "RSA", 2048, 2048, UART_CAP_FIFO },
+ { "NS16550A", 16, 16, UART_CAP_FIFO | UART_NATSEMI },
+ { "XScale", 32, 32, UART_CAP_FIFO },
};
static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset)
case UPIO_MEM:
return readb(up->port.membase + offset);
+ case UPIO_MEM32:
+ return readl(up->port.membase + offset);
+
default:
return inb(up->port.iobase + offset);
}
writeb(value, up->port.membase + offset);
break;
+ case UPIO_MEM32:
+ writel(value, up->port.membase + offset);
+ break;
+
default:
outb(value, up->port.iobase + offset);
}
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
/*
* Attempts to turn on the RSA FIFO. Returns zero on failure.
#endif
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->tx_loadsz = uart_config[up->port.type].tx_loadsz;
if (up->port.type == PORT_UNKNOWN)
goto out;
serial_outp(up, UART_RSA_FRR, 0);
#endif
serial_outp(up, UART_MCR, save_mcr);
- serial_outp(up, UART_FCR, (UART_FCR_ENABLE_FIFO |
- UART_FCR_CLEAR_RCVR |
- UART_FCR_CLEAR_XMIT));
- serial_outp(up, UART_FCR, 0);
+ serial8250_clear_fifos(up);
(void)serial_in(up, UART_RX);
serial_outp(up, UART_IER, 0);
return;
}
- count = up->port.fifosize;
+ count = up->tx_loadsz;
do {
serial_out(up, UART_TX, xmit->buf[xmit->tail]);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
* Clear the FIFO buffers and disable them.
* (they will be reeanbled in set_termios())
*/
- if (up->capabilities & UART_CLEAR_FIFO) {
- 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);
- }
+ serial8250_clear_fifos(up);
/*
* Clear the interrupt registers.
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
* hardware interrupt, we use a timer-based system. The original
* Disable break condition and FIFOs
*/
serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC);
- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
- UART_FCR_CLEAR_RCVR |
- UART_FCR_CLEAR_XMIT);
- serial_outp(up, UART_FCR, 0);
+ serial8250_clear_fifos(up);
#ifdef CONFIG_SERIAL_8250_RSA
/*
up->rev == 0x5201)
quot ++;
- if (up->capabilities & UART_USE_FIFO) {
+ if (up->capabilities & UART_CAP_FIFO && up->port.fifosize > 1) {
if (baud < 2400)
fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
#ifdef CONFIG_SERIAL_8250_RSA
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_EFR,
termios->c_cflag & CRTSCTS ? UART_EFR_CTS :0);
serial8250_pm(struct uart_port *port, unsigned int state,
unsigned int oldstate)
{
- struct uart_8250_port *up = (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);
- }
+ struct uart_8250_port *p = (struct uart_8250_port *)port;
- if (up->pm)
- 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);
- }
+ serial8250_set_sleep(p, state != 0);
- if (up->port.type == PORT_16750) {
- /* Wake up UART */
- serial_outp(up, UART_IER, 0);
- }
-
- if (up->pm)
- up->pm(port, state, oldstate);
- }
+ if (p->pm)
+ p->pm(port, state, oldstate);
}
/*