watchdog: s3c2410_wdt - Add extra option to include watchdog for Samsung SoCs
[safe/jmp/linux-2.6] / drivers / serial / 8250.c
index 737b4c9..891e1dd 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/serial_8250.h>
 #include <linux/nmi.h>
 #include <linux/mutex.h>
+#include <linux/slab.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -83,6 +84,9 @@ static unsigned int skip_txen_test; /* force skip of txen test at init time */
 
 #define PASS_LIMIT     256
 
+#define BOTH_EMPTY     (UART_LSR_TEMT | UART_LSR_THRE)
+
+
 /*
  * We default to IRQ0 for the "no irq" hack.   Some
  * machine types want others as well - they're free
@@ -1214,12 +1218,6 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
        }
 #endif
 
-#ifdef CONFIG_SERIAL_8250_AU1X00
-       /* if access method is AU, it is a 16550 with a quirk */
-       if (up->port.type == PORT_16550A && up->port.iotype == UPIO_AU)
-               up->bugs |= UART_BUG_NOMSR;
-#endif
-
        serial_outp(up, UART_LCR, save_lcr);
 
        if (up->capabilities != uart_config[up->port.type].flags) {
@@ -1339,14 +1337,12 @@ static void serial8250_start_tx(struct uart_port *port)
                serial_out(up, UART_IER, up->ier);
 
                if (up->bugs & UART_BUG_TXEN) {
-                       unsigned char lsr, iir;
+                       unsigned char lsr;
                        lsr = serial_in(up, UART_LSR);
                        up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
-                       iir = serial_in(up, UART_IIR) & 0x0f;
                        if ((up->port.type == PORT_RM9000) ?
-                               (lsr & UART_LSR_THRE &&
-                               (iir == UART_IIR_NO_INT || iir == UART_IIR_THRI)) :
-                               (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT))
+                               (lsr & UART_LSR_THRE) :
+                               (lsr & UART_LSR_TEMT))
                                transmit_chars(up);
                }
        }
@@ -1794,7 +1790,7 @@ static unsigned int serial8250_tx_empty(struct uart_port *port)
        up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
        spin_unlock_irqrestore(&up->port.lock, flags);
 
-       return lsr & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
+       return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0;
 }
 
 static unsigned int serial8250_get_mctrl(struct uart_port *port)
@@ -1852,8 +1848,6 @@ static void serial8250_break_ctl(struct uart_port *port, int break_state)
        spin_unlock_irqrestore(&up->port.lock, flags);
 }
 
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
 /*
  *     Wait for transmitter & holding register to empty
  */
@@ -1897,8 +1891,8 @@ static int serial8250_get_poll_char(struct uart_port *port)
        struct uart_8250_port *up = (struct uart_8250_port *)port;
        unsigned char lsr = serial_inp(up, UART_LSR);
 
-       while (!(lsr & UART_LSR_DR))
-               lsr = serial_inp(up, UART_LSR);
+       if (!(lsr & UART_LSR_DR))
+               return NO_POLL_CHAR;
 
        return serial_inp(up, UART_RX);
 }
@@ -2415,6 +2409,21 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
 }
 
 static void
+serial8250_set_ldisc(struct uart_port *port)
+{
+       int line = port->line;
+
+       if (line >= port->state->port.tty->driver->num)
+               return;
+
+       if (port->state->port.tty->ldisc->ops->num == N_PPS) {
+               port->flags |= UPF_HARDPPS_CD;
+               serial8250_enable_ms(port);
+       } else
+               port->flags &= ~UPF_HARDPPS_CD;
+}
+
+static void
 serial8250_pm(struct uart_port *port, unsigned int state,
              unsigned int oldstate)
 {
@@ -2429,7 +2438,7 @@ serial8250_pm(struct uart_port *port, unsigned int state,
 static unsigned int serial8250_port_size(struct uart_8250_port *pt)
 {
        if (pt->port.iotype == UPIO_AU)
-               return 0x100000;
+               return 0x1000;
 #ifdef CONFIG_ARCH_OMAP
        if (is_omap_port(pt))
                return 0x16 << pt->port.regshift;
@@ -2586,6 +2595,13 @@ static void serial8250_config_port(struct uart_port *port, int flags)
 
        if (flags & UART_CONFIG_TYPE)
                autoconfig(up, probeflags);
+
+#ifdef CONFIG_SERIAL_8250_AU1X00
+       /* if access method is AU, it is a 16550 with a quirk */
+       if (up->port.type == PORT_16550A && up->port.iotype == UPIO_AU)
+               up->bugs |= UART_BUG_NOMSR;
+#endif
+
        if (up->port.type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)
                autoconfig_irq(up);
 
@@ -2628,6 +2644,7 @@ static struct uart_ops serial8250_pops = {
        .startup        = serial8250_startup,
        .shutdown       = serial8250_shutdown,
        .set_termios    = serial8250_set_termios,
+       .set_ldisc      = serial8250_set_ldisc,
        .pm             = serial8250_pm,
        .type           = serial8250_type,
        .release_port   = serial8250_release_port,
@@ -2646,7 +2663,7 @@ static void __init serial8250_isa_init_ports(void)
 {
        struct uart_8250_port *up;
        static int first = 1;
-       int i;
+       int i, irqflag = 0;
 
        if (!first)
                return;
@@ -2670,6 +2687,9 @@ static void __init serial8250_isa_init_ports(void)
                up->port.ops = &serial8250_pops;
        }
 
+       if (share_irqs)
+               irqflag = IRQF_SHARED;
+
        for (i = 0, up = serial8250_ports;
             i < ARRAY_SIZE(old_serial_port) && i < nr_uarts;
             i++, up++) {
@@ -2683,11 +2703,19 @@ static void __init serial8250_isa_init_ports(void)
                up->port.iotype   = old_serial_port[i].io_type;
                up->port.regshift = old_serial_port[i].iomem_reg_shift;
                set_io_from_upio(&up->port);
-               if (share_irqs)
-                       up->port.irqflags |= IRQF_SHARED;
+               up->port.irqflags |= irqflag;
        }
 }
 
+static void
+serial8250_init_fixed_type_port(struct uart_8250_port *up, unsigned int type)
+{
+       up->port.type = type;
+       up->port.fifosize = uart_config[type].fifo_size;
+       up->capabilities = uart_config[type].flags;
+       up->tx_loadsz = uart_config[type].tx_loadsz;
+}
+
 static void __init
 serial8250_register_ports(struct uart_driver *drv, struct device *dev)
 {
@@ -2704,6 +2732,10 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev)
                struct uart_8250_port *up = &serial8250_ports[i];
 
                up->port.dev = dev;
+
+               if (up->port.flags & UPF_FIXED_TYPE)
+                       serial8250_init_fixed_type_port(up, up->port.type);
+
                uart_add_one_port(drv, &up->port);
        }
 }
@@ -2940,10 +2972,13 @@ static int __devinit serial8250_probe(struct platform_device *dev)
 {
        struct plat_serial8250_port *p = dev->dev.platform_data;
        struct uart_port port;
-       int ret, i;
+       int ret, i, irqflag = 0;
 
        memset(&port, 0, sizeof(struct uart_port));
 
+       if (share_irqs)
+               irqflag = IRQF_SHARED;
+
        for (i = 0; p && p->flags != 0; p++, i++) {
                port.iobase             = p->iobase;
                port.membase            = p->membase;
@@ -2960,8 +2995,7 @@ static int __devinit serial8250_probe(struct platform_device *dev)
                port.serial_in          = p->serial_in;
                port.serial_out         = p->serial_out;
                port.dev                = &dev->dev;
-               if (share_irqs)
-                       port.irqflags |= IRQF_SHARED;
+               port.irqflags           |= irqflag;
                ret = serial8250_register_port(&port);
                if (ret < 0) {
                        dev_err(&dev->dev, "unable to register port at index %d "
@@ -3114,12 +3148,8 @@ int serial8250_register_port(struct uart_port *port)
                if (port->dev)
                        uart->port.dev = port->dev;
 
-               if (port->flags & UPF_FIXED_TYPE) {
-                       uart->port.type = port->type;
-                       uart->port.fifosize = uart_config[port->type].fifo_size;
-                       uart->capabilities = uart_config[port->type].flags;
-                       uart->tx_loadsz = uart_config[port->type].tx_loadsz;
-               }
+               if (port->flags & UPF_FIXED_TYPE)
+                       serial8250_init_fixed_type_port(uart, port->type);
 
                set_io_from_upio(&uart->port);
                /* Possibly override default I/O functions.  */