serial: add PNP ID GVC0303 for Archtek 3334BRV ISA modem
[safe/jmp/linux-2.6] / drivers / serial / 8250.c
index 4d75cdf..77f7a7f 100644 (file)
@@ -19,7 +19,6 @@
  *  mapbase is the physical address of the IO port.
  *  membase is an 'ioremapped' cookie.
  */
-#include <linux/config.h>
 
 #if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
 #include <linux/init.h>
 #include <linux/console.h>
 #include <linux/sysrq.h>
-#include <linux/mca.h>
 #include <linux/delay.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/serial_reg.h>
 #include <linux/serial_core.h>
 #include <linux/serial.h>
 #include <linux/serial_8250.h>
+#include <linux/nmi.h>
+#include <linux/mutex.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
 
 /*
  * Configuration:
- *   share_irqs - whether we pass SA_SHIRQ to request_irq().  This option
+ *   share_irqs - whether we pass IRQF_SHARED to request_irq().  This option
  *                is unsafe when used on edge-triggered interrupts.
  */
 static unsigned int share_irqs = SERIAL8250_SHARE_IRQS;
 
+static unsigned int nr_uarts = CONFIG_SERIAL_8250_RUNTIME_UARTS;
+
 /*
  * Debugging.
  */
@@ -101,7 +103,7 @@ static unsigned int share_irqs = SERIAL8250_SHARE_IRQS;
 #define SERIAL_PORT_DFNS
 #endif
 
-static struct old_serial_port old_serial_port[] = {
+static const struct old_serial_port old_serial_port[] = {
        SERIAL_PORT_DFNS /* defined in asm/serial.h */
 };
 
@@ -127,7 +129,16 @@ struct uart_8250_port {
        unsigned char           mcr;
        unsigned char           mcr_mask;       /* mask of user bits */
        unsigned char           mcr_force;      /* mask of forced bits */
-       unsigned char           lsr_break_flag;
+
+       /*
+        * Some bits in registers are cleared on a read, so they must
+        * be saved whenever the register is read but the bits will not
+        * be immediately processed.
+        */
+#define LSR_SAVE_FLAGS UART_LSR_BRK_ERROR_BITS
+       unsigned char           lsr_saved_flags;
+#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
+       unsigned char           msr_saved_flags;
 
        /*
         * We provide a per-port pm hook.
@@ -249,11 +260,101 @@ static const struct serial8250_config uart_config[] = {
                .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
                .flags          = UART_CAP_FIFO | UART_CAP_UUE,
        },
+       [PORT_RM9000] = {
+               .name           = "RM9000",
+               .fifo_size      = 16,
+               .tx_loadsz      = 16,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .flags          = UART_CAP_FIFO,
+       },
 };
 
-static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset)
+#if defined (CONFIG_SERIAL_8250_AU1X00)
+
+/* Au1x00 UART hardware has a weird register layout */
+static const u8 au_io_in_map[] = {
+       [UART_RX]  = 0,
+       [UART_IER] = 2,
+       [UART_IIR] = 3,
+       [UART_LCR] = 5,
+       [UART_MCR] = 6,
+       [UART_LSR] = 7,
+       [UART_MSR] = 8,
+};
+
+static const u8 au_io_out_map[] = {
+       [UART_TX]  = 1,
+       [UART_IER] = 2,
+       [UART_FCR] = 4,
+       [UART_LCR] = 5,
+       [UART_MCR] = 6,
+};
+
+/* sane hardware needs no mapping */
+static inline int map_8250_in_reg(struct uart_8250_port *up, int offset)
+{
+       if (up->port.iotype != UPIO_AU)
+               return offset;
+       return au_io_in_map[offset];
+}
+
+static inline int map_8250_out_reg(struct uart_8250_port *up, int offset)
+{
+       if (up->port.iotype != UPIO_AU)
+               return offset;
+       return au_io_out_map[offset];
+}
+
+#elif defined(CONFIG_SERIAL_8250_RM9K)
+
+static const u8
+       regmap_in[8] = {
+               [UART_RX]       = 0x00,
+               [UART_IER]      = 0x0c,
+               [UART_IIR]      = 0x14,
+               [UART_LCR]      = 0x1c,
+               [UART_MCR]      = 0x20,
+               [UART_LSR]      = 0x24,
+               [UART_MSR]      = 0x28,
+               [UART_SCR]      = 0x2c
+       },
+       regmap_out[8] = {
+               [UART_TX]       = 0x04,
+               [UART_IER]      = 0x0c,
+               [UART_FCR]      = 0x18,
+               [UART_LCR]      = 0x1c,
+               [UART_MCR]      = 0x20,
+               [UART_LSR]      = 0x24,
+               [UART_MSR]      = 0x28,
+               [UART_SCR]      = 0x2c
+       };
+
+static inline int map_8250_in_reg(struct uart_8250_port *up, int offset)
+{
+       if (up->port.iotype != UPIO_RM9000)
+               return offset;
+       return regmap_in[offset];
+}
+
+static inline int map_8250_out_reg(struct uart_8250_port *up, int offset)
+{
+       if (up->port.iotype != UPIO_RM9000)
+               return offset;
+       return regmap_out[offset];
+}
+
+#else
+
+/* sane hardware needs no mapping */
+#define map_8250_in_reg(up, offset) (offset)
+#define map_8250_out_reg(up, offset) (offset)
+
+#endif
+
+static unsigned int serial_in(struct uart_8250_port *up, int offset)
 {
-       offset <<= up->port.regshift;
+       unsigned int tmp;
+       offset = map_8250_in_reg(up, offset) << up->port.regshift;
 
        switch (up->port.iotype) {
        case UPIO_HUB6:
@@ -261,20 +362,36 @@ static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset)
                return inb(up->port.iobase + 1);
 
        case UPIO_MEM:
+       case UPIO_DWAPB:
                return readb(up->port.membase + offset);
 
+       case UPIO_RM9000:
        case UPIO_MEM32:
                return readl(up->port.membase + offset);
 
+#ifdef CONFIG_SERIAL_8250_AU1X00
+       case UPIO_AU:
+               return __raw_readl(up->port.membase + offset);
+#endif
+
+       case UPIO_TSI:
+               if (offset == UART_IIR) {
+                       tmp = readl(up->port.membase + (UART_IIR & ~3));
+                       return (tmp >> 16) & 0xff; /* UART_IIR % 4 == 2 */
+               } else
+                       return readb(up->port.membase + offset);
+
        default:
                return inb(up->port.iobase + offset);
        }
 }
 
-static _INLINE_ void
+static void
 serial_out(struct uart_8250_port *up, int offset, int value)
 {
-       offset <<= up->port.regshift;
+       /* Save the offset before it's remapped */
+       int save_offset = offset;
+       offset = map_8250_out_reg(up, offset) << up->port.regshift;
 
        switch (up->port.iotype) {
        case UPIO_HUB6:
@@ -286,15 +403,56 @@ serial_out(struct uart_8250_port *up, int offset, int value)
                writeb(value, up->port.membase + offset);
                break;
 
+       case UPIO_RM9000:
        case UPIO_MEM32:
                writel(value, up->port.membase + offset);
                break;
 
+#ifdef CONFIG_SERIAL_8250_AU1X00
+       case UPIO_AU:
+               __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;
+
+       case UPIO_DWAPB:
+               /* Save the LCR value so it can be re-written when a
+                * Busy Detect interrupt occurs. */
+               if (save_offset == UART_LCR)
+                       up->lcr = value;
+               writeb(value, up->port.membase + offset);
+               /* Read the IER to ensure any interrupt is cleared before
+                * returning from ISR. */
+               if (save_offset == UART_TX || save_offset == UART_IER)
+                       value = serial_in(up, UART_IER);
+               break;
+
        default:
                outb(value, up->port.iobase + offset);
        }
 }
 
+static void
+serial_out_sync(struct uart_8250_port *up, int offset, int value)
+{
+       switch (up->port.iotype) {
+       case UPIO_MEM:
+       case UPIO_MEM32:
+#ifdef CONFIG_SERIAL_8250_AU1X00
+       case UPIO_AU:
+#endif
+       case UPIO_DWAPB:
+               serial_out(up, offset, value);
+               serial_in(up, UART_LCR);        /* safe, no side-effects */
+               break;
+       default:
+               serial_out(up, offset, value);
+       }
+}
+
 /*
  * We used to support using pause I/O for certain machines.  We
  * haven't supported this for a while, but just in case it's badly
@@ -304,6 +462,58 @@ serial_out(struct uart_8250_port *up, int offset, int value)
 #define serial_inp(up, offset)         serial_in(up, offset)
 #define serial_outp(up, offset, value) serial_out(up, offset, value)
 
+/* Uart divisor latch read */
+static inline int _serial_dl_read(struct uart_8250_port *up)
+{
+       return serial_inp(up, UART_DLL) | serial_inp(up, UART_DLM) << 8;
+}
+
+/* Uart divisor latch write */
+static inline void _serial_dl_write(struct uart_8250_port *up, int value)
+{
+       serial_outp(up, UART_DLL, value & 0xff);
+       serial_outp(up, UART_DLM, value >> 8 & 0xff);
+}
+
+#if defined(CONFIG_SERIAL_8250_AU1X00)
+/* Au1x00 haven't got a standard divisor latch */
+static int serial_dl_read(struct uart_8250_port *up)
+{
+       if (up->port.iotype == UPIO_AU)
+               return __raw_readl(up->port.membase + 0x28);
+       else
+               return _serial_dl_read(up);
+}
+
+static void serial_dl_write(struct uart_8250_port *up, int value)
+{
+       if (up->port.iotype == UPIO_AU)
+               __raw_writel(value, up->port.membase + 0x28);
+       else
+               _serial_dl_write(up, value);
+}
+#elif defined(CONFIG_SERIAL_8250_RM9K)
+static int serial_dl_read(struct uart_8250_port *up)
+{
+       return  (up->port.iotype == UPIO_RM9000) ?
+               (((__raw_readl(up->port.membase + 0x10) << 8) |
+               (__raw_readl(up->port.membase + 0x08) & 0xff)) & 0xffff) :
+               _serial_dl_read(up);
+}
+
+static void serial_dl_write(struct uart_8250_port *up, int value)
+{
+       if (up->port.iotype == UPIO_RM9000) {
+               __raw_writel(value, up->port.membase + 0x08);
+               __raw_writel(value >> 8, up->port.membase + 0x10);
+       } else {
+               _serial_dl_write(up, value);
+       }
+}
+#else
+#define serial_dl_read(up) _serial_dl_read(up)
+#define serial_dl_write(up, value) _serial_dl_write(up, value)
+#endif
 
 /*
  * For the 16C950
@@ -436,7 +646,8 @@ static void disable_rsa(struct uart_8250_port *up)
  */
 static int size_fifo(struct uart_8250_port *up)
 {
-       unsigned char old_fcr, old_mcr, old_dll, old_dlm, old_lcr;
+       unsigned char old_fcr, old_mcr, old_lcr;
+       unsigned short old_dl;
        int count;
 
        old_lcr = serial_inp(up, UART_LCR);
@@ -447,10 +658,8 @@ static int size_fifo(struct uart_8250_port *up)
                    UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
        serial_outp(up, UART_MCR, UART_MCR_LOOP);
        serial_outp(up, UART_LCR, UART_LCR_DLAB);
-       old_dll = serial_inp(up, UART_DLL);
-       old_dlm = serial_inp(up, UART_DLM);
-       serial_outp(up, UART_DLL, 0x01);
-       serial_outp(up, UART_DLM, 0x00);
+       old_dl = serial_dl_read(up);
+       serial_dl_write(up, 0x0001);
        serial_outp(up, UART_LCR, 0x03);
        for (count = 0; count < 256; count++)
                serial_outp(up, UART_TX, count);
@@ -461,8 +670,7 @@ static int size_fifo(struct uart_8250_port *up)
        serial_outp(up, UART_FCR, old_fcr);
        serial_outp(up, UART_MCR, old_mcr);
        serial_outp(up, UART_LCR, UART_LCR_DLAB);
-       serial_outp(up, UART_DLL, old_dll);
-       serial_outp(up, UART_DLM, old_dlm);
+       serial_dl_write(up, old_dl);
        serial_outp(up, UART_LCR, old_lcr);
 
        return count;
@@ -503,7 +711,7 @@ static unsigned int autoconfig_read_divisor_id(struct uart_8250_port *p)
  * its clones.  (We treat the broken original StarTech 16650 V1 as a
  * 16550, and why not?  Startech doesn't seem to even acknowledge its
  * existence.)
- * 
+ *
  * What evil have men's minds wrought...
  */
 static void autoconfig_has_efr(struct uart_8250_port *up)
@@ -556,7 +764,7 @@ static void autoconfig_has_efr(struct uart_8250_port *up)
                        up->bugs |= UART_BUG_QUOT;
                return;
        }
-       
+
        /*
         * We check for a XR16C850 by setting DLL and DLM to 0, and then
         * reading back DLL and DLM.  The chip type depends on the DLM
@@ -692,17 +900,15 @@ static void autoconfig_16550a(struct uart_8250_port *up)
 
                        serial_outp(up, UART_LCR, 0xE0);
 
-                       quot = serial_inp(up, UART_DLM) << 8;
-                       quot += serial_inp(up, UART_DLL);
+                       quot = serial_dl_read(up);
                        quot <<= 3;
 
-                       status1 = serial_in(up, 0x04); /* EXCR1 */
+                       status1 = serial_in(up, 0x04); /* EXCR2 */
                        status1 &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
                        status1 |= 0x10;  /* 1.625 divisor for baud_base --> 921600 */
                        serial_outp(up, 0x04, status1);
-                       
-                       serial_outp(up, UART_DLL, quot & 0xff);
-                       serial_outp(up, UART_DLM, quot >> 8);
+
+                       serial_dl_write(up, quot);
 
                        serial_outp(up, UART_LCR, 0);
 
@@ -797,7 +1003,6 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
         * be frobbing the chips IRQ enable register to see if it exists.
         */
        spin_lock_irqsave(&up->port.lock, flags);
-//     save_flags(flags); cli();
 
        up->capabilities = 0;
        up->bugs = 0;
@@ -806,7 +1011,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
                /*
                 * Do a simple existence test first; if we fail this,
                 * there's no point trying anything else.
-                * 
+                *
                 * 0x80 is used as a nonsense port to prevent against
                 * false positives due to ISA bus float.  The
                 * assumption is that 0x80 is a non-existent port;
@@ -821,12 +1026,16 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
 #ifdef __i386__
                outb(0xff, 0x080);
 #endif
-               scratch2 = serial_inp(up, UART_IER);
+               /*
+                * Mask out IER[7:4] bits for test as some UARTs (e.g. TL
+                * 16C754B) allow only to modify them if an EFR bit is set.
+                */
+               scratch2 = serial_inp(up, UART_IER) & 0x0f;
                serial_outp(up, UART_IER, 0x0F);
 #ifdef __i386__
                outb(0, 0x080);
 #endif
-               scratch3 = serial_inp(up, UART_IER);
+               scratch3 = serial_inp(up, UART_IER) & 0x0f;
                serial_outp(up, UART_IER, scratch);
                if (scratch2 != 0 || scratch3 != 0x0F) {
                        /*
@@ -841,7 +1050,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
        save_mcr = serial_in(up, UART_MCR);
        save_lcr = serial_in(up, UART_LCR);
 
-       /* 
+       /*
         * Check to see if a UART is really there.  Certain broken
         * internal modems based on the Rockwell chipset fail this
         * test, because they apparently don't implement the loopback
@@ -910,6 +1119,13 @@ 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) {
@@ -935,12 +1151,14 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
 #endif
        serial_outp(up, UART_MCR, save_mcr);
        serial8250_clear_fifos(up);
-       (void)serial_in(up, UART_RX);
-       serial_outp(up, UART_IER, 0);
+       serial_in(up, UART_RX);
+       if (up->capabilities & UART_CAP_UUE)
+               serial_outp(up, UART_IER, UART_IER_UUE);
+       else
+               serial_outp(up, UART_IER, 0);
 
- out:  
+ out:
        spin_unlock_irqrestore(&up->port.lock, flags);
-//     restore_flags(flags);
        DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name);
 }
 
@@ -964,11 +1182,11 @@ static void autoconfig_irq(struct uart_8250_port *up)
        save_mcr = serial_inp(up, UART_MCR);
        save_ier = serial_inp(up, UART_IER);
        serial_outp(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
-       
+
        irqs = probe_irq_on();
        serial_outp(up, UART_MCR, 0);
-       udelay (10);
-       if (up->port.flags & UPF_FOURPORT)  {
+       udelay(10);
+       if (up->port.flags & UPF_FOURPORT) {
                serial_outp(up, UART_MCR,
                            UART_MCR_DTR | UART_MCR_RTS);
        } else {
@@ -981,7 +1199,7 @@ static void autoconfig_irq(struct uart_8250_port *up)
        (void)serial_inp(up, UART_IIR);
        (void)serial_inp(up, UART_MSR);
        serial_outp(up, UART_TX, 0xFF);
-       udelay (20);
+       udelay(20);
        irq = probe_irq_off(irqs);
 
        serial_outp(up, UART_MCR, save_mcr);
@@ -1029,8 +1247,12 @@ static void serial8250_start_tx(struct uart_port *port)
                if (up->bugs & UART_BUG_TXEN) {
                        unsigned char lsr, iir;
                        lsr = serial_in(up, UART_LSR);
-                       iir = serial_in(up, UART_IIR);
-                       if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT)
+                       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))
                                transmit_chars(up);
                }
        }
@@ -1057,12 +1279,16 @@ static void serial8250_enable_ms(struct uart_port *port)
 {
        struct uart_8250_port *up = (struct uart_8250_port *)port;
 
+       /* no MSR capabilities */
+       if (up->bugs & UART_BUG_NOMSR)
+               return;
+
        up->ier |= UART_IER_MSI;
        serial_out(up, UART_IER, up->ier);
 }
 
-static _INLINE_ void
-receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
+static void
+receive_chars(struct uart_8250_port *up, unsigned int *status)
 {
        struct tty_struct *tty = up->port.info->tty;
        unsigned char ch, lsr = *status;
@@ -1070,35 +1296,14 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
        char flag;
 
        do {
-               /* The following is not allowed by the tty layer and
-                  unsafe. It should be fixed ASAP */
-               if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
-                       if (tty->low_latency) {
-                               spin_unlock(&up->port.lock);
-                               tty_flip_buffer_push(tty);
-                               spin_lock(&up->port.lock);
-                       }
-                       /*
-                        * If this failed then we will throw away the
-                        * bytes but must do so to clear interrupts
-                        */
-               }
                ch = serial_inp(up, UART_RX);
                flag = TTY_NORMAL;
                up->port.icount.rx++;
 
-#ifdef CONFIG_SERIAL_8250_CONSOLE
-               /*
-                * Recover the break flag from console xmit
-                */
-               if (up->port.line == up->port.cons->index) {
-                       lsr |= up->lsr_break_flag;
-                       up->lsr_break_flag = 0;
-               }
-#endif
+               lsr |= up->lsr_saved_flags;
+               up->lsr_saved_flags = 0;
 
-               if (unlikely(lsr & (UART_LSR_BI | UART_LSR_PE |
-                                   UART_LSR_FE | UART_LSR_OE))) {
+               if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) {
                        /*
                         * For statistics only
                         */
@@ -1133,12 +1338,12 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
                        else if (lsr & UART_LSR_FE)
                                flag = TTY_FRAME;
                }
-               if (uart_handle_sysrq_char(&up->port, ch, regs))
+               if (uart_handle_sysrq_char(&up->port, ch))
                        goto ignore_char;
 
                uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag);
 
-       ignore_char:
+ignore_char:
                lsr = serial_inp(up, UART_LSR);
        } while ((lsr & UART_LSR_DR) && (max_count-- > 0));
        spin_unlock(&up->port.lock);
@@ -1147,7 +1352,7 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
        *status = lsr;
 }
 
-static _INLINE_ void transmit_chars(struct uart_8250_port *up)
+static void transmit_chars(struct uart_8250_port *up)
 {
        struct circ_buf *xmit = &up->port.info->xmit;
        int count;
@@ -1185,42 +1390,51 @@ static _INLINE_ void transmit_chars(struct uart_8250_port *up)
                __stop_tx(up);
 }
 
-static _INLINE_ void check_modem_status(struct uart_8250_port *up)
+static unsigned int check_modem_status(struct uart_8250_port *up)
 {
-       int status;
+       unsigned int status = serial_in(up, UART_MSR);
 
-       status = serial_in(up, UART_MSR);
-
-       if ((status & UART_MSR_ANY_DELTA) == 0)
-               return;
+       status |= up->msr_saved_flags;
+       up->msr_saved_flags = 0;
+       if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI &&
+           up->port.info != NULL) {
+               if (status & UART_MSR_TERI)
+                       up->port.icount.rng++;
+               if (status & UART_MSR_DDSR)
+                       up->port.icount.dsr++;
+               if (status & UART_MSR_DDCD)
+                       uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
+               if (status & UART_MSR_DCTS)
+                       uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
 
-       if (status & UART_MSR_TERI)
-               up->port.icount.rng++;
-       if (status & UART_MSR_DDSR)
-               up->port.icount.dsr++;
-       if (status & UART_MSR_DDCD)
-               uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
-       if (status & UART_MSR_DCTS)
-               uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
+               wake_up_interruptible(&up->port.info->delta_msr_wait);
+       }
 
-       wake_up_interruptible(&up->port.info->delta_msr_wait);
+       return status;
 }
 
 /*
  * This handles the interrupt from one port.
  */
 static inline void
-serial8250_handle_port(struct uart_8250_port *up, struct pt_regs *regs)
+serial8250_handle_port(struct uart_8250_port *up)
 {
-       unsigned int status = serial_inp(up, UART_LSR);
+       unsigned int status;
+       unsigned long flags;
+
+       spin_lock_irqsave(&up->port.lock, flags);
+
+       status = serial_inp(up, UART_LSR);
 
        DEBUG_INTR("status = %x...", status);
 
        if (status & UART_LSR_DR)
-               receive_chars(up, &status, regs);
+               receive_chars(up, &status);
        check_modem_status(up);
        if (status & UART_LSR_THRE)
                transmit_chars(up);
+
+       spin_unlock_irqrestore(&up->port.lock, flags);
 }
 
 /*
@@ -1237,7 +1451,7 @@ serial8250_handle_port(struct uart_8250_port *up, struct pt_regs *regs)
  * This means we need to loop through all ports. checking that they
  * don't have an interrupt pending.
  */
-static irqreturn_t serial8250_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
 {
        struct irq_info *i = dev_id;
        struct list_head *l, *end = NULL;
@@ -1256,9 +1470,20 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id, struct pt_regs *r
 
                iir = serial_in(up, UART_IIR);
                if (!(iir & UART_IIR_NO_INT)) {
-                       spin_lock(&up->port.lock);
-                       serial8250_handle_port(up, regs);
-                       spin_unlock(&up->port.lock);
+                       serial8250_handle_port(up);
+
+                       handled = 1;
+
+                       end = NULL;
+               } else if (up->port.iotype == UPIO_DWAPB &&
+                         (iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
+                       /* The DesignWare APB UART has an Busy Detect (0x07)
+                        * interrupt meaning an LCR write attempt occured while the
+                        * UART was busy. The interrupt must be cleared by reading
+                        * the UART status register (USR) and the LCR re-written. */
+                       unsigned int status;
+                       status = *(volatile u32 *)up->port.private_data;
+                       serial_out(up, UART_LCR, up->lcr);
 
                        handled = 1;
 
@@ -1309,7 +1534,7 @@ static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up)
 static int serial_link_irq_chain(struct uart_8250_port *up)
 {
        struct irq_info *i = irq_lists + up->port.irq;
-       int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? SA_SHIRQ : 0;
+       int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;
 
        spin_lock_irq(&i->lock);
 
@@ -1344,6 +1569,12 @@ static void serial_unlink_irq_chain(struct uart_8250_port *up)
        serial_do_unlink(i, up);
 }
 
+/* Base timer interval for polling */
+static inline int poll_timeout(int timeout)
+{
+       return timeout > 6 ? (timeout / 2 - 2) : 1;
+}
+
 /*
  * This function is used to handle ports that do not have an
  * interrupt.  This doesn't work very well for 16450's, but gives
@@ -1353,41 +1584,80 @@ static void serial_unlink_irq_chain(struct uart_8250_port *up)
 static void serial8250_timeout(unsigned long data)
 {
        struct uart_8250_port *up = (struct uart_8250_port *)data;
-       unsigned int timeout;
        unsigned int iir;
 
        iir = serial_in(up, UART_IIR);
-       if (!(iir & UART_IIR_NO_INT)) {
-               spin_lock(&up->port.lock);
-               serial8250_handle_port(up, NULL);
-               spin_unlock(&up->port.lock);
+       if (!(iir & UART_IIR_NO_INT))
+               serial8250_handle_port(up);
+       mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout));
+}
+
+static void serial8250_backup_timeout(unsigned long data)
+{
+       struct uart_8250_port *up = (struct uart_8250_port *)data;
+       unsigned int iir, ier = 0, lsr;
+       unsigned long flags;
+
+       /*
+        * Must disable interrupts or else we risk racing with the interrupt
+        * based handler.
+        */
+       if (is_real_interrupt(up->port.irq)) {
+               ier = serial_in(up, UART_IER);
+               serial_out(up, UART_IER, 0);
        }
 
-       timeout = up->port.timeout;
-       timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
-       mod_timer(&up->timer, jiffies + timeout);
+       iir = serial_in(up, UART_IIR);
+
+       /*
+        * This should be a safe test for anyone who doesn't trust the
+        * IIR bits on their UART, but it's specifically designed for
+        * the "Diva" UART used on the management processor on many HP
+        * ia64 and parisc boxes.
+        */
+       spin_lock_irqsave(&up->port.lock, flags);
+       lsr = serial_in(up, UART_LSR);
+       up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
+       spin_unlock_irqrestore(&up->port.lock, flags);
+       if ((iir & UART_IIR_NO_INT) && (up->ier & UART_IER_THRI) &&
+           (!uart_circ_empty(&up->port.info->xmit) || up->port.x_char) &&
+           (lsr & UART_LSR_THRE)) {
+               iir &= ~(UART_IIR_ID | UART_IIR_NO_INT);
+               iir |= UART_IIR_THRI;
+       }
+
+       if (!(iir & UART_IIR_NO_INT))
+               serial8250_handle_port(up);
+
+       if (is_real_interrupt(up->port.irq))
+               serial_out(up, UART_IER, ier);
+
+       /* Standard timer interval plus 0.2s to keep the port running */
+       mod_timer(&up->timer,
+               jiffies + poll_timeout(up->port.timeout) + HZ / 5);
 }
 
 static unsigned int serial8250_tx_empty(struct uart_port *port)
 {
        struct uart_8250_port *up = (struct uart_8250_port *)port;
        unsigned long flags;
-       unsigned int ret;
+       unsigned int lsr;
 
        spin_lock_irqsave(&up->port.lock, flags);
-       ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
+       lsr = serial_in(up, UART_LSR);
+       up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
        spin_unlock_irqrestore(&up->port.lock, flags);
 
-       return ret;
+       return lsr & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
 }
 
 static unsigned int serial8250_get_mctrl(struct uart_port *port)
 {
        struct uart_8250_port *up = (struct uart_8250_port *)port;
-       unsigned char status;
+       unsigned int status;
        unsigned int ret;
 
-       status = serial_in(up, UART_MSR);
+       status = check_modem_status(up);
 
        ret = 0;
        if (status & UART_MSR_DCD)
@@ -1436,6 +1706,40 @@ 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
+ */
+static inline void wait_for_xmitr(struct uart_8250_port *up, int bits)
+{
+       unsigned int status, tmout = 10000;
+
+       /* Wait up to 10ms for the character(s) to be sent. */
+       do {
+               status = serial_in(up, UART_LSR);
+
+               up->lsr_saved_flags |= status & LSR_SAVE_FLAGS;
+
+               if (--tmout == 0)
+                       break;
+               udelay(1);
+       } while ((status & bits) != bits);
+
+       /* Wait up to 1s for flow control if necessary */
+       if (up->port.flags & UPF_CONS_FLOW) {
+               unsigned int tmout;
+               for (tmout = 1000000; tmout; tmout--) {
+                       unsigned int msr = serial_in(up, UART_MSR);
+                       up->msr_saved_flags |= msr & MSR_SAVE_FLAGS;
+                       if (msr & UART_MSR_CTS)
+                               break;
+                       udelay(1);
+                       touch_nmi_watchdog();
+               }
+       }
+}
+
 static int serial8250_startup(struct uart_port *port)
 {
        struct uart_8250_port *up = (struct uart_8250_port *)port;
@@ -1469,7 +1773,7 @@ static int serial8250_startup(struct uart_port *port)
 
        /*
         * Clear the FIFO buffers and disable them.
-        * (they will be reeanbled in set_termios())
+        * (they will be reenabled in set_termios())
         */
        serial8250_clear_fifos(up);
 
@@ -1509,18 +1813,50 @@ static int serial8250_startup(struct uart_port *port)
                serial_outp(up, UART_LCR, 0);
        }
 
+       if (is_real_interrupt(up->port.irq)) {
+               /*
+                * Test for UARTs that do not reassert THRE when the
+                * transmitter is idle and the interrupt has already
+                * been cleared.  Real 16550s should always reassert
+                * this interrupt whenever the transmitter is idle and
+                * the interrupt is enabled.  Delays are necessary to
+                * allow register changes to become visible.
+                */
+               spin_lock_irqsave(&up->port.lock, flags);
+
+               wait_for_xmitr(up, UART_LSR_THRE);
+               serial_out_sync(up, UART_IER, UART_IER_THRI);
+               udelay(1); /* allow THRE to set */
+               serial_in(up, UART_IIR);
+               serial_out(up, UART_IER, 0);
+               serial_out_sync(up, UART_IER, UART_IER_THRI);
+               udelay(1); /* allow a working UART time to re-assert THRE */
+               iir = serial_in(up, UART_IIR);
+               serial_out(up, UART_IER, 0);
+
+               spin_unlock_irqrestore(&up->port.lock, flags);
+
+               /*
+                * If the interrupt is not reasserted, setup a timer to
+                * kick the UART on a regular basis.
+                */
+               if (iir & UART_IIR_NO_INT) {
+                       pr_debug("ttyS%d - using backup timer\n", port->line);
+                       up->timer.function = serial8250_backup_timeout;
+                       up->timer.data = (unsigned long)up;
+                       mod_timer(&up->timer, jiffies +
+                               poll_timeout(up->port.timeout) + HZ / 5);
+               }
+       }
+
        /*
         * If the "interrupt" for this port doesn't correspond with any
         * hardware interrupt, we use a timer-based system.  The original
         * driver used to do this with IRQ0.
         */
        if (!is_real_interrupt(up->port.irq)) {
-               unsigned int timeout = up->port.timeout;
-
-               timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
-
                up->timer.data = (unsigned long)up;
-               mod_timer(&up->timer, jiffies + timeout);
+               mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout));
        } else {
                retval = serial_link_irq_chain(up);
                if (retval)
@@ -1567,6 +1903,18 @@ static int serial8250_startup(struct uart_port *port)
        spin_unlock_irqrestore(&up->port.lock, flags);
 
        /*
+        * Clear the interrupt registers again for luck, and clear the
+        * saved flags to avoid getting false values from polling
+        * routines or the previous session.
+        */
+       serial_inp(up, UART_LSR);
+       serial_inp(up, UART_RX);
+       serial_inp(up, UART_IIR);
+       serial_inp(up, UART_MSR);
+       up->lsr_saved_flags = 0;
+       up->msr_saved_flags = 0;
+
+       /*
         * Finally, enable interrupts.  Note: Modem status interrupts
         * are set via set_termios(), which will be occurring imminently
         * anyway, so we don't enable them here.
@@ -1584,14 +1932,6 @@ static int serial8250_startup(struct uart_port *port)
                (void) inb_p(icp);
        }
 
-       /*
-        * And clear the interrupt registers again for luck.
-        */
-       (void) serial_inp(up, UART_LSR);
-       (void) serial_inp(up, UART_RX);
-       (void) serial_inp(up, UART_IIR);
-       (void) serial_inp(up, UART_MSR);
-
        return 0;
 }
 
@@ -1636,9 +1976,9 @@ static void serial8250_shutdown(struct uart_port *port)
         */
        (void) serial_in(up, UART_RX);
 
-       if (!is_real_interrupt(up->port.irq))
-               del_timer_sync(&up->timer);
-       else
+       del_timer_sync(&up->timer);
+       up->timer.function = serial8250_timeout;
+       if (is_real_interrupt(up->port.irq))
                serial_unlink_irq_chain(up);
 }
 
@@ -1663,8 +2003,8 @@ static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int
 }
 
 static void
-serial8250_set_termios(struct uart_port *port, struct termios *termios,
-                      struct termios *old)
+serial8250_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;
@@ -1701,14 +2041,14 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios,
        /*
         * Ask the core to calculate the divisor for us.
         */
-       baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); 
+       baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
        quot = serial8250_get_divisor(port, baud);
 
        /*
         * Oxford Semi 952 rev B workaround
         */
        if (up->bugs & UART_BUG_QUOT && (quot & 0xff) == 0)
-               quot ++;
+               quot++;
 
        if (up->capabilities & UART_CAP_FIFO && up->port.fifosize > 1) {
                if (baud < 2400)
@@ -1774,7 +2114,8 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios,
         * CTS flow control flag and modem status interrupts
         */
        up->ier &= ~UART_IER_MSI;
-       if (UART_ENABLE_MS(&up->port, termios->c_cflag))
+       if (!(up->bugs & UART_BUG_NOMSR) &&
+                       UART_ENABLE_MS(&up->port, termios->c_cflag))
                up->ier |= UART_IER_MSI;
        if (up->capabilities & UART_CAP_UUE)
                up->ier |= UART_IER_UUE | UART_IER_RTOIE;
@@ -1795,6 +2136,17 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios,
                serial_outp(up, UART_EFR, efr);
        }
 
+#ifdef CONFIG_ARCH_OMAP15XX
+       /* Workaround to enable 115200 baud on OMAP1510 internal ports */
+       if (cpu_is_omap1510() && is_omap_port((unsigned int)up->port.membase)) {
+               if (baud == 115200) {
+                       quot = 1;
+                       serial_out(up, UART_OMAP_OSC_12M_SEL, 1);
+               } else
+                       serial_out(up, UART_OMAP_OSC_12M_SEL, 0);
+       }
+#endif
+
        if (up->capabilities & UART_NATSEMI) {
                /* Switch to bank 2 not bank 1, to avoid resetting EXCR2 */
                serial_outp(up, UART_LCR, 0xe0);
@@ -1802,8 +2154,7 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios,
                serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
        }
 
-       serial_outp(up, UART_DLL, quot & 0xff);         /* LS of divisor */
-       serial_outp(up, UART_DLM, quot >> 8);           /* MS of divisor */
+       serial_dl_write(up, quot);
 
        /*
         * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
@@ -1823,6 +2174,7 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios,
        }
        serial8250_set_mctrl(&up->port, up->port.mctrl);
        spin_unlock_irqrestore(&up->port.lock, flags);
+       tty_termios_encode_baud_rate(termios, baud, baud);
 }
 
 static void
@@ -1846,7 +2198,13 @@ static int serial8250_request_std_resource(struct uart_8250_port *up)
        int ret = 0;
 
        switch (up->port.iotype) {
+       case UPIO_AU:
+               size = 0x100000;
+               /* fall thru */
+       case UPIO_TSI:
+       case UPIO_MEM32:
        case UPIO_MEM:
+       case UPIO_DWAPB:
                if (!up->port.mapbase)
                        break;
 
@@ -1878,7 +2236,13 @@ static void serial8250_release_std_resource(struct uart_8250_port *up)
        unsigned int size = 8 << up->port.regshift;
 
        switch (up->port.iotype) {
+       case UPIO_AU:
+               size = 0x100000;
+               /* fall thru */
+       case UPIO_TSI:
+       case UPIO_MEM32:
        case UPIO_MEM:
+       case UPIO_DWAPB:
                if (!up->port.mapbase)
                        break;
 
@@ -1901,17 +2265,15 @@ static int serial8250_request_rsa_resource(struct uart_8250_port *up)
 {
        unsigned long start = UART_RSA_BASE << up->port.regshift;
        unsigned int size = 8 << up->port.regshift;
-       int ret = 0;
+       int ret = -EINVAL;
 
        switch (up->port.iotype) {
-       case UPIO_MEM:
-               ret = -EINVAL;
-               break;
-
        case UPIO_HUB6:
        case UPIO_PORT:
                start += up->port.iobase;
-               if (!request_region(start, size, "serial-rsa"))
+               if (request_region(start, size, "serial-rsa"))
+                       ret = 0;
+               else
                        ret = -EBUSY;
                break;
        }
@@ -1925,9 +2287,6 @@ static void serial8250_release_rsa_resource(struct uart_8250_port *up)
        unsigned int size = 8 << up->port.regshift;
 
        switch (up->port.iotype) {
-       case UPIO_MEM:
-               break;
-
        case UPIO_HUB6:
        case UPIO_PORT:
                release_region(up->port.iobase + offset, size);
@@ -1966,12 +2325,6 @@ static void serial8250_config_port(struct uart_port *port, int flags)
        int ret;
 
        /*
-        * Don't probe for MCA ports on non-MCA machines.
-        */
-       if (up->port.flags & UPF_BOOT_ONLYMCA && !MCA_bus)
-               return;
-
-       /*
         * Find the region that we can probe for.  This in turn
         * tells us whether we can probe for the type of port.
         */
@@ -2047,7 +2400,7 @@ static void __init serial8250_isa_init_ports(void)
                return;
        first = 0;
 
-       for (i = 0; i < UART_NR; i++) {
+       for (i = 0; i < nr_uarts; i++) {
                struct uart_8250_port *up = &serial8250_ports[i];
 
                up->port.line = i;
@@ -2066,7 +2419,7 @@ static void __init serial8250_isa_init_ports(void)
        }
 
        for (i = 0, up = serial8250_ports;
-            i < ARRAY_SIZE(old_serial_port) && i < UART_NR;
+            i < ARRAY_SIZE(old_serial_port) && i < nr_uarts;
             i++, up++) {
                up->port.iobase   = old_serial_port[i].port;
                up->port.irq      = irq_canonicalize(old_serial_port[i].irq);
@@ -2088,7 +2441,7 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev)
 
        serial8250_isa_init_ports();
 
-       for (i = 0; i < UART_NR; i++) {
+       for (i = 0; i < nr_uarts; i++) {
                struct uart_8250_port *up = &serial8250_ports[i];
 
                up->port.dev = dev;
@@ -2098,34 +2451,12 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev)
 
 #ifdef CONFIG_SERIAL_8250_CONSOLE
 
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/*
- *     Wait for transmitter & holding register to empty
- */
-static inline void wait_for_xmitr(struct uart_8250_port *up)
+static void serial8250_console_putchar(struct uart_port *port, int ch)
 {
-       unsigned int status, tmout = 10000;
-
-       /* Wait up to 10ms for the character(s) to be sent. */
-       do {
-               status = serial_in(up, UART_LSR);
-
-               if (status & UART_LSR_BI)
-                       up->lsr_break_flag = UART_LSR_BI;
-
-               if (--tmout == 0)
-                       break;
-               udelay(1);
-       } while ((status & BOTH_EMPTY) != BOTH_EMPTY);
+       struct uart_8250_port *up = (struct uart_8250_port *)port;
 
-       /* Wait up to 1s for flow control if necessary */
-       if (up->port.flags & UPF_CONS_FLOW) {
-               tmout = 1000000;
-               while (--tmout &&
-                      ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
-                       udelay(1);
-       }
+       wait_for_xmitr(up, UART_LSR_THRE);
+       serial_out(up, UART_TX, ch);
 }
 
 /*
@@ -2138,11 +2469,23 @@ static void
 serial8250_console_write(struct console *co, const char *s, unsigned int count)
 {
        struct uart_8250_port *up = &serial8250_ports[co->index];
+       unsigned long flags;
        unsigned int ier;
-       int i;
+       int locked = 1;
+
+       touch_nmi_watchdog();
+
+       local_irq_save(flags);
+       if (up->port.sysrq) {
+               /* serial8250_handle_port() already took the lock */
+               locked = 0;
+       } else if (oops_in_progress) {
+               locked = spin_trylock(&up->port.lock);
+       } else
+               spin_lock(&up->port.lock);
 
        /*
-        *      First save the UER then disable the interrupts
+        *      First save the IER then disable the interrupts
         */
        ier = serial_in(up, UART_IER);
 
@@ -2151,32 +2494,31 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
        else
                serial_out(up, UART_IER, 0);
 
-       /*
-        *      Now, do each character
-        */
-       for (i = 0; i < count; i++, s++) {
-               wait_for_xmitr(up);
-
-               /*
-                *      Send the character out.
-                *      If a LF, also do CR...
-                */
-               serial_out(up, UART_TX, *s);
-               if (*s == 10) {
-                       wait_for_xmitr(up);
-                       serial_out(up, UART_TX, 13);
-               }
-       }
+       uart_console_write(&up->port, s, count, serial8250_console_putchar);
 
        /*
         *      Finally, wait for transmitter to become empty
         *      and restore the IER
         */
-       wait_for_xmitr(up);
+       wait_for_xmitr(up, BOTH_EMPTY);
        serial_out(up, UART_IER, ier);
+
+       /*
+        *      The receive handling will happen properly because the
+        *      receive ready bit will still be set; it is not cleared
+        *      on read.  However, modem control will not, we must
+        *      call it if we have saved something in the saved flags
+        *      while processing with interrupts off.
+        */
+       if (up->msr_saved_flags)
+               check_modem_status(up);
+
+       if (locked)
+               spin_unlock(&up->port.lock);
+       local_irq_restore(flags);
 }
 
-static int serial8250_console_setup(struct console *co, char *options)
+static int __init serial8250_console_setup(struct console *co, char *options)
 {
        struct uart_port *port;
        int baud = 9600;
@@ -2189,7 +2531,7 @@ static int serial8250_console_setup(struct console *co, char *options)
         * if so, search for the first available port that does have
         * console support.
         */
-       if (co->index >= UART_NR)
+       if (co->index >= nr_uarts)
                co->index = 0;
        port = &serial8250_ports[co->index].port;
        if (!port->iobase && !port->membase)
@@ -2201,12 +2543,18 @@ static int serial8250_console_setup(struct console *co, char *options)
        return uart_set_options(port, co, baud, parity, bits, flow);
 }
 
+static int serial8250_console_early_setup(void)
+{
+       return serial8250_find_port_for_earlycon();
+}
+
 static struct uart_driver serial8250_reg;
 static struct console serial8250_console = {
        .name           = "ttyS",
        .write          = serial8250_console_write,
        .device         = uart_console_device,
        .setup          = serial8250_console_setup,
+       .early_setup    = serial8250_console_early_setup,
        .flags          = CON_PRINTBUFFER,
        .index          = -1,
        .data           = &serial8250_reg,
@@ -2220,41 +2568,19 @@ static int __init serial8250_console_init(void)
 }
 console_initcall(serial8250_console_init);
 
-static int __init find_port(struct uart_port *p)
+int serial8250_find_port(struct uart_port *p)
 {
        int line;
        struct uart_port *port;
 
-       for (line = 0; line < UART_NR; line++) {
+       for (line = 0; line < nr_uarts; line++) {
                port = &serial8250_ports[line].port;
-               if (p->iotype == port->iotype &&
-                   p->iobase == port->iobase &&
-                   p->membase == port->membase)
+               if (uart_match_port(p, port))
                        return line;
        }
        return -ENODEV;
 }
 
-int __init serial8250_start_console(struct uart_port *port, char *options)
-{
-       int line;
-
-       line = find_port(port);
-       if (line < 0)
-               return -ENODEV;
-
-       add_preferred_console("ttyS", line, options);
-       printk("Adding console on ttyS%d at %s 0x%lx (options '%s')\n",
-               line, port->iotype == UPIO_MEM ? "MMIO" : "I/O port",
-               port->iotype == UPIO_MEM ? (unsigned long) port->mapbase :
-                   (unsigned long) port->iobase, options);
-       if (!(serial8250_console.flags & CON_ENABLED)) {
-               serial8250_console.flags &= ~CON_PRINTBUFFER;
-               register_console(&serial8250_console);
-       }
-       return line;
-}
-
 #define SERIAL8250_CONSOLE     &serial8250_console
 #else
 #define SERIAL8250_CONSOLE     NULL
@@ -2263,7 +2589,6 @@ int __init serial8250_start_console(struct uart_port *port, char *options)
 static struct uart_driver serial8250_reg = {
        .owner                  = THIS_MODULE,
        .driver_name            = "serial",
-       .devfs_name             = "tts/",
        .dev_name               = "ttyS",
        .major                  = TTY_MAJOR,
        .minor                  = 64,
@@ -2271,6 +2596,12 @@ static struct uart_driver serial8250_reg = {
        .cons                   = SERIAL8250_CONSOLE,
 };
 
+/*
+ * early_serial_setup - early registration for 8250 ports
+ *
+ * Setup an 8250 port structure prior to console initialisation.  Use
+ * after console initialisation will cause undefined behaviour.
+ */
 int __init early_serial_setup(struct uart_port *port)
 {
        if (port->line >= ARRAY_SIZE(serial8250_ports))
@@ -2285,7 +2616,6 @@ int __init early_serial_setup(struct uart_port *port)
 /**
  *     serial8250_suspend_port - suspend one serial port
  *     @line:  serial line number
- *      @level: the level of port suspension, as per uart_suspend_port
  *
  *     Suspend one serial port.
  */
@@ -2297,13 +2627,27 @@ void serial8250_suspend_port(int line)
 /**
  *     serial8250_resume_port - resume one serial port
  *     @line:  serial line number
- *      @level: the level of port resumption, as per uart_resume_port
  *
  *     Resume one serial port.
  */
 void serial8250_resume_port(int line)
 {
-       uart_resume_port(&serial8250_reg, &serial8250_ports[line].port);
+       struct uart_8250_port *up = &serial8250_ports[line];
+
+       if (up->capabilities & UART_NATSEMI) {
+               unsigned char tmp;
+
+               /* Ensure it's still in high speed mode */
+               serial_outp(up, UART_LCR, 0xE0);
+
+               tmp = serial_in(up, 0x04); /* EXCR2 */
+               tmp &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
+               tmp |= 0x10;  /* 1.625 divisor for baud_base --> 921600 */
+               serial_outp(up, 0x04, tmp);
+
+               serial_outp(up, UART_LCR, 0);
+       }
+       uart_resume_port(&serial8250_reg, &up->port);
 }
 
 /*
@@ -2311,32 +2655,34 @@ void serial8250_resume_port(int line)
  * list is terminated with a zero flags entry, which means we expect
  * all entries to have at least UPF_BOOT_AUTOCONF set.
  */
-static int __devinit serial8250_probe(struct device *dev)
+static int __devinit serial8250_probe(struct platform_device *dev)
 {
-       struct plat_serial8250_port *p = dev->platform_data;
+       struct plat_serial8250_port *p = dev->dev.platform_data;
        struct uart_port port;
        int ret, i;
 
        memset(&port, 0, sizeof(struct uart_port));
 
        for (i = 0; p && p->flags != 0; p++, i++) {
-               port.iobase     = p->iobase;
-               port.membase    = p->membase;
-               port.irq        = p->irq;
-               port.uartclk    = p->uartclk;
-               port.regshift   = p->regshift;
-               port.iotype     = p->iotype;
-               port.flags      = p->flags;
-               port.mapbase    = p->mapbase;
-               port.hub6       = p->hub6;
-               port.dev        = dev;
+               port.iobase             = p->iobase;
+               port.membase            = p->membase;
+               port.irq                = p->irq;
+               port.uartclk            = p->uartclk;
+               port.regshift           = p->regshift;
+               port.iotype             = p->iotype;
+               port.flags              = p->flags;
+               port.mapbase            = p->mapbase;
+               port.hub6               = p->hub6;
+               port.private_data       = p->private_data;
+               port.dev                = &dev->dev;
                if (share_irqs)
                        port.flags |= UPF_SHARE_IRQ;
                ret = serial8250_register_port(&port);
                if (ret < 0) {
-                       dev_err(dev, "unable to register port at index %d "
-                               "(IO%lx MEM%lx IRQ%d): %d\n", i,
-                               p->iobase, p->mapbase, p->irq, ret);
+                       dev_err(&dev->dev, "unable to register port at index %d "
+                               "(IO%lx MEM%llx IRQ%d): %d\n", i,
+                               p->iobase, (unsigned long long)p->mapbase,
+                               p->irq, ret);
                }
        }
        return 0;
@@ -2345,60 +2691,56 @@ static int __devinit serial8250_probe(struct device *dev)
 /*
  * Remove serial ports registered against a platform device.
  */
-static int __devexit serial8250_remove(struct device *dev)
+static int __devexit serial8250_remove(struct platform_device *dev)
 {
        int i;
 
-       for (i = 0; i < UART_NR; i++) {
+       for (i = 0; i < nr_uarts; i++) {
                struct uart_8250_port *up = &serial8250_ports[i];
 
-               if (up->port.dev == dev)
+               if (up->port.dev == &dev->dev)
                        serial8250_unregister_port(i);
        }
        return 0;
 }
 
-static int serial8250_suspend(struct device *dev, pm_message_t state, u32 level)
+static int serial8250_suspend(struct platform_device *dev, pm_message_t state)
 {
        int i;
 
-       if (level != SUSPEND_DISABLE)
-               return 0;
-
        for (i = 0; i < UART_NR; i++) {
                struct uart_8250_port *up = &serial8250_ports[i];
 
-               if (up->port.type != PORT_UNKNOWN && up->port.dev == dev)
+               if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
                        uart_suspend_port(&serial8250_reg, &up->port);
        }
 
        return 0;
 }
 
-static int serial8250_resume(struct device *dev, u32 level)
+static int serial8250_resume(struct platform_device *dev)
 {
        int i;
 
-       if (level != RESUME_ENABLE)
-               return 0;
-
        for (i = 0; i < UART_NR; i++) {
                struct uart_8250_port *up = &serial8250_ports[i];
 
-               if (up->port.type != PORT_UNKNOWN && up->port.dev == dev)
-                       uart_resume_port(&serial8250_reg, &up->port);
+               if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
+                       serial8250_resume_port(i);
        }
 
        return 0;
 }
 
-static struct device_driver serial8250_isa_driver = {
-       .name           = "serial8250",
-       .bus            = &platform_bus_type,
+static struct platform_driver serial8250_isa_driver = {
        .probe          = serial8250_probe,
        .remove         = __devexit_p(serial8250_remove),
        .suspend        = serial8250_suspend,
        .resume         = serial8250_resume,
+       .driver         = {
+               .name   = "serial8250",
+               .owner  = THIS_MODULE,
+       },
 };
 
 /*
@@ -2412,7 +2754,7 @@ static struct platform_device *serial8250_isa_devs;
  * 16x50 serial ports to be configured at run-time, to support PCMCIA
  * modems and PCI multiport cards.
  */
-static DECLARE_MUTEX(serial_sem);
+static DEFINE_MUTEX(serial_mutex);
 
 static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *port)
 {
@@ -2421,7 +2763,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *
        /*
         * First, find a port entry which matches.
         */
-       for (i = 0; i < UART_NR; i++)
+       for (i = 0; i < nr_uarts; i++)
                if (uart_match_port(&serial8250_ports[i].port, port))
                        return &serial8250_ports[i];
 
@@ -2430,7 +2772,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *
         * free entry.  We look for one which hasn't been previously
         * used (indicated by zero iobase).
         */
-       for (i = 0; i < UART_NR; i++)
+       for (i = 0; i < nr_uarts; i++)
                if (serial8250_ports[i].port.type == PORT_UNKNOWN &&
                    serial8250_ports[i].port.iobase == 0)
                        return &serial8250_ports[i];
@@ -2439,7 +2781,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *
         * That also failed.  Last resort is to find any entry which
         * doesn't have a real port associated with it.
         */
-       for (i = 0; i < UART_NR; i++)
+       for (i = 0; i < nr_uarts; i++)
                if (serial8250_ports[i].port.type == PORT_UNKNOWN)
                        return &serial8250_ports[i];
 
@@ -2467,21 +2809,22 @@ int serial8250_register_port(struct uart_port *port)
        if (port->uartclk == 0)
                return -EINVAL;
 
-       down(&serial_sem);
+       mutex_lock(&serial_mutex);
 
        uart = serial8250_find_match_or_unused(port);
        if (uart) {
                uart_remove_one_port(&serial8250_reg, &uart->port);
 
-               uart->port.iobase   = port->iobase;
-               uart->port.membase  = port->membase;
-               uart->port.irq      = port->irq;
-               uart->port.uartclk  = port->uartclk;
-               uart->port.fifosize = port->fifosize;
-               uart->port.regshift = port->regshift;
-               uart->port.iotype   = port->iotype;
-               uart->port.flags    = port->flags | UPF_BOOT_AUTOCONF;
-               uart->port.mapbase  = port->mapbase;
+               uart->port.iobase       = port->iobase;
+               uart->port.membase      = port->membase;
+               uart->port.irq          = port->irq;
+               uart->port.uartclk      = port->uartclk;
+               uart->port.fifosize     = port->fifosize;
+               uart->port.regshift     = port->regshift;
+               uart->port.iotype       = port->iotype;
+               uart->port.flags        = port->flags | UPF_BOOT_AUTOCONF;
+               uart->port.mapbase      = port->mapbase;
+               uart->port.private_data = port->private_data;
                if (port->dev)
                        uart->port.dev = port->dev;
 
@@ -2489,7 +2832,7 @@ int serial8250_register_port(struct uart_port *port)
                if (ret == 0)
                        ret = uart->port.line;
        }
-       up(&serial_sem);
+       mutex_unlock(&serial_mutex);
 
        return ret;
 }
@@ -2506,7 +2849,7 @@ void serial8250_unregister_port(int line)
 {
        struct uart_8250_port *uart = &serial8250_ports[line];
 
-       down(&serial_sem);
+       mutex_lock(&serial_mutex);
        uart_remove_one_port(&serial8250_reg, &uart->port);
        if (serial8250_isa_devs) {
                uart->port.flags &= ~UPF_BOOT_AUTOCONF;
@@ -2516,7 +2859,7 @@ void serial8250_unregister_port(int line)
        } else {
                uart->port.dev = NULL;
        }
-       up(&serial_sem);
+       mutex_unlock(&serial_mutex);
 }
 EXPORT_SYMBOL(serial8250_unregister_port);
 
@@ -2524,8 +2867,11 @@ static int __init serial8250_init(void)
 {
        int ret, i;
 
+       if (nr_uarts > UART_NR)
+               nr_uarts = UART_NR;
+
        printk(KERN_INFO "Serial: 8250/16550 driver $Revision: 1.90 $ "
-               "%d ports, IRQ sharing %sabled\n", (int) UART_NR,
+               "%d ports, IRQ sharing %sabled\n", nr_uarts,
                share_irqs ? "en" : "dis");
 
        for (i = 0; i < NR_IRQS; i++)
@@ -2535,21 +2881,27 @@ static int __init serial8250_init(void)
        if (ret)
                goto out;
 
-       serial8250_isa_devs = platform_device_register_simple("serial8250",
-                                        PLAT8250_DEV_LEGACY, NULL, 0);
-       if (IS_ERR(serial8250_isa_devs)) {
-               ret = PTR_ERR(serial8250_isa_devs);
-               goto unreg;
+       serial8250_isa_devs = platform_device_alloc("serial8250",
+                                                   PLAT8250_DEV_LEGACY);
+       if (!serial8250_isa_devs) {
+               ret = -ENOMEM;
+               goto unreg_uart_drv;
        }
 
+       ret = platform_device_add(serial8250_isa_devs);
+       if (ret)
+               goto put_dev;
+
        serial8250_register_ports(&serial8250_reg, &serial8250_isa_devs->dev);
 
-       ret = driver_register(&serial8250_isa_driver);
+       ret = platform_driver_register(&serial8250_isa_driver);
        if (ret == 0)
                goto out;
 
-       platform_device_unregister(serial8250_isa_devs);
- unreg:
+       platform_device_del(serial8250_isa_devs);
+ put_dev:
+       platform_device_put(serial8250_isa_devs);
+ unreg_uart_drv:
        uart_unregister_driver(&serial8250_reg);
  out:
        return ret;
@@ -2566,7 +2918,7 @@ static void __exit serial8250_exit(void)
         */
        serial8250_isa_devs = NULL;
 
-       driver_unregister(&serial8250_isa_driver);
+       platform_driver_unregister(&serial8250_isa_driver);
        platform_device_unregister(isa_dev);
 
        uart_unregister_driver(&serial8250_reg);
@@ -2585,6 +2937,9 @@ module_param(share_irqs, uint, 0644);
 MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices"
        " (unsafe)");
 
+module_param(nr_uarts, uint, 0644);
+MODULE_PARM_DESC(nr_uarts, "Maximum number of UARTs supported. (1-" __MODULE_STRING(CONFIG_SERIAL_8250_NR_UARTS) ")");
+
 #ifdef CONFIG_SERIAL_8250_RSA
 module_param_array(probe_rsa, ulong, &probe_rsa_count, 0444);
 MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");