U6715 16550A serial driver support
[sfrench/cifs-2.6.git] / drivers / serial / 8250.c
index 355148dc085ebed8fd3a7ec0aee221706395d8bb..24110f6f61e0efae9beddc0d509ba28968e73224 100644 (file)
@@ -300,6 +300,13 @@ static const struct serial8250_config uart_config[] = {
                .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00,
                .flags          = UART_CAP_FIFO | UART_CAP_AFE,
        },
+       [PORT_U6_16550A] = {
+               .name           = "U6_16550A",
+               .fifo_size      = 64,
+               .tx_loadsz      = 64,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .flags          = UART_CAP_FIFO | UART_CAP_AFE,
+       },
 };
 
 #if defined(CONFIG_MIPS_ALCHEMY)
@@ -1070,6 +1077,15 @@ static void autoconfig_16550a(struct uart_8250_port *up)
                DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 ");
        }
        serial_outp(up, UART_IER, iersave);
+
+       /*
+        * We distinguish between 16550A and U6 16550A by counting
+        * how many bytes are in the FIFO.
+        */
+       if (up->port.type == PORT_16550A && size_fifo(up) == 64) {
+               up->port.type = PORT_U6_16550A;
+               up->capabilities |= UART_CAP_AFE;
+       }
 }
 
 /*
@@ -2224,9 +2240,9 @@ static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int
        return quot;
 }
 
-static void
-serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
-                      struct ktermios *old)
+void
+serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
+                         struct ktermios *old)
 {
        struct uart_8250_port *up = (struct uart_8250_port *)port;
        unsigned char cval, fcr = 0;
@@ -2402,6 +2418,17 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
        if (tty_termios_baud_rate(termios))
                tty_termios_encode_baud_rate(termios, baud, baud);
 }
+EXPORT_SYMBOL(serial8250_do_set_termios);
+
+static void
+serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
+                      struct ktermios *old)
+{
+       if (port->set_termios)
+               port->set_termios(port, termios, old);
+       else
+               serial8250_do_set_termios(port, termios, old);
+}
 
 static void
 serial8250_set_ldisc(struct uart_port *port, int new)
@@ -2982,6 +3009,7 @@ static int __devinit serial8250_probe(struct platform_device *dev)
                port.type               = p->type;
                port.serial_in          = p->serial_in;
                port.serial_out         = p->serial_out;
+               port.set_termios        = p->set_termios;
                port.dev                = &dev->dev;
                port.irqflags           |= irqflag;
                ret = serial8250_register_port(&port);
@@ -3145,6 +3173,9 @@ int serial8250_register_port(struct uart_port *port)
                        uart->port.serial_in = port->serial_in;
                if (port->serial_out)
                        uart->port.serial_out = port->serial_out;
+               /*  Possibly override set_termios call */
+               if (port->set_termios)
+                       uart->port.set_termios = port->set_termios;
 
                ret = uart_add_one_port(&serial8250_reg, &uart->port);
                if (ret == 0)