Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
[pandora-kernel.git] / drivers / tty / serial / 8250.c
index 610b8e6..eeadf1b 100644 (file)
@@ -309,6 +309,13 @@ static const struct serial8250_config uart_config[] = {
                                  UART_FCR_T_TRIG_01,
                .flags          = UART_CAP_FIFO | UART_CAP_RTOIE,
        },
+       [PORT_XR17D15X] = {
+               .name           = "XR17D15X",
+               .fifo_size      = 64,
+               .tx_loadsz      = 64,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .flags          = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR,
+       },
 };
 
 #if defined(CONFIG_MIPS_ALCHEMY)
@@ -443,42 +450,6 @@ static void au_serial_out(struct uart_port *p, int offset, int value)
        __raw_writel(value, p->membase + offset);
 }
 
-/* Save the LCR value so it can be re-written when a Busy Detect IRQ occurs. */
-static inline void dwapb_save_out_value(struct uart_port *p, int offset,
-                                       int value)
-{
-       struct uart_8250_port *up =
-               container_of(p, struct uart_8250_port, port);
-
-       if (offset == UART_LCR)
-               up->lcr = value;
-}
-
-/* Read the IER to ensure any interrupt is cleared before returning from ISR. */
-static inline void dwapb_check_clear_ier(struct uart_port *p, int offset)
-{
-       if (offset == UART_TX || offset == UART_IER)
-               p->serial_in(p, UART_IER);
-}
-
-static void dwapb_serial_out(struct uart_port *p, int offset, int value)
-{
-       int save_offset = offset;
-       offset = map_8250_out_reg(p, offset) << p->regshift;
-       dwapb_save_out_value(p, save_offset, value);
-       writeb(value, p->membase + offset);
-       dwapb_check_clear_ier(p, save_offset);
-}
-
-static void dwapb32_serial_out(struct uart_port *p, int offset, int value)
-{
-       int save_offset = offset;
-       offset = map_8250_out_reg(p, offset) << p->regshift;
-       dwapb_save_out_value(p, save_offset, value);
-       writel(value, p->membase + offset);
-       dwapb_check_clear_ier(p, save_offset);
-}
-
 static unsigned int io_serial_in(struct uart_port *p, int offset)
 {
        offset = map_8250_in_reg(p, offset) << p->regshift;
@@ -491,6 +462,8 @@ static void io_serial_out(struct uart_port *p, int offset, int value)
        outb(value, p->iobase + offset);
 }
 
+static int serial8250_default_handle_irq(struct uart_port *port);
+
 static void set_io_from_upio(struct uart_port *p)
 {
        struct uart_8250_port *up =
@@ -517,16 +490,6 @@ static void set_io_from_upio(struct uart_port *p)
                p->serial_out = au_serial_out;
                break;
 
-       case UPIO_DWAPB:
-               p->serial_in = mem_serial_in;
-               p->serial_out = dwapb_serial_out;
-               break;
-
-       case UPIO_DWAPB32:
-               p->serial_in = mem32_serial_in;
-               p->serial_out = dwapb32_serial_out;
-               break;
-
        default:
                p->serial_in = io_serial_in;
                p->serial_out = io_serial_out;
@@ -534,6 +497,7 @@ static void set_io_from_upio(struct uart_port *p)
        }
        /* Remember loaded iotype */
        up->cur_iotype = p->iotype;
+       p->handle_irq = serial8250_default_handle_irq;
 }
 
 static void
@@ -544,8 +508,6 @@ serial_out_sync(struct uart_8250_port *up, int offset, int value)
        case UPIO_MEM:
        case UPIO_MEM32:
        case UPIO_AU:
-       case UPIO_DWAPB:
-       case UPIO_DWAPB32:
                p->serial_out(p, offset, value);
                p->serial_in(p, UART_LCR);      /* safe, no side-effects */
                break;
@@ -1096,6 +1058,14 @@ static void autoconfig_16550a(struct uart_8250_port *up)
        }
        serial_outp(up, UART_IER, iersave);
 
+       /*
+        * Exar uarts have EFR in a weird location
+        */
+       if (up->port.flags & UPF_EXAR_EFR) {
+               up->port.type = PORT_XR17D15X;
+               up->capabilities |= UART_CAP_AFE | UART_CAP_EFR;
+       }
+
        /*
         * We distinguish between 16550A and U6 16550A by counting
         * how many bytes are in the FIFO.
@@ -1598,6 +1568,29 @@ static void serial8250_handle_port(struct uart_8250_port *up)
        spin_unlock_irqrestore(&up->port.lock, flags);
 }
 
+int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
+{
+       struct uart_8250_port *up =
+               container_of(port, struct uart_8250_port, port);
+
+       if (!(iir & UART_IIR_NO_INT)) {
+               serial8250_handle_port(up);
+               return 1;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(serial8250_handle_irq);
+
+static int serial8250_default_handle_irq(struct uart_port *port)
+{
+       struct uart_8250_port *up =
+               container_of(port, struct uart_8250_port, port);
+       unsigned int iir = serial_in(up, UART_IIR);
+
+       return serial8250_handle_irq(port, iir);
+}
+
 /*
  * This is the serial driver's interrupt routine.
  *
@@ -1625,30 +1618,13 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
        l = i->head;
        do {
                struct uart_8250_port *up;
-               unsigned int iir;
+               struct uart_port *port;
 
                up = list_entry(l, struct uart_8250_port, list);
+               port = &up->port;
 
-               iir = serial_in(up, UART_IIR);
-               if (!(iir & UART_IIR_NO_INT)) {
-                       serial8250_handle_port(up);
-
+               if (port->handle_irq(port)) {
                        handled = 1;
-
-                       end = NULL;
-               } else if ((up->port.iotype == UPIO_DWAPB ||
-                           up->port.iotype == UPIO_DWAPB32) &&
-                         (iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
-                       /* The DesignWare APB UART has an Busy Detect (0x07)
-                        * interrupt meaning an LCR write attempt occurred 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;
-
                        end = NULL;
                } else if (end == NULL)
                        end = l;
@@ -2058,8 +2034,8 @@ static int serial8250_startup(struct uart_port *port)
         */
        if (!(up->port.flags & UPF_BUGGY_UART) &&
            (serial_inp(up, UART_LSR) == 0xff)) {
-               printk(KERN_INFO "ttyS%d: LSR safety check engaged!\n",
-                      serial_index(&up->port));
+               printk_ratelimited(KERN_INFO "ttyS%d: LSR safety check engaged!\n",
+                                  serial_index(&up->port));
                return -ENODEV;
        }
 
@@ -2435,7 +2411,10 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
                        efr |= UART_EFR_CTS;
 
                serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
-               serial_outp(up, UART_EFR, efr);
+               if (up->port.flags & UPF_EXAR_EFR)
+                       serial_outp(up, UART_XR_EFR, efr);
+               else
+                       serial_outp(up, UART_EFR, efr);
        }
 
 #ifdef CONFIG_ARCH_OMAP
@@ -2547,8 +2526,6 @@ static int serial8250_request_std_resource(struct uart_8250_port *up)
        case UPIO_TSI:
        case UPIO_MEM32:
        case UPIO_MEM:
-       case UPIO_DWAPB:
-       case UPIO_DWAPB32:
                if (!up->port.mapbase)
                        break;
 
@@ -2585,8 +2562,6 @@ static void serial8250_release_std_resource(struct uart_8250_port *up)
        case UPIO_TSI:
        case UPIO_MEM32:
        case UPIO_MEM:
-       case UPIO_DWAPB:
-       case UPIO_DWAPB32:
                if (!up->port.mapbase)
                        break;
 
@@ -3027,6 +3002,10 @@ int __init early_serial_setup(struct uart_port *port)
                p->serial_in = port->serial_in;
        if (port->serial_out)
                p->serial_out = port->serial_out;
+       if (port->handle_irq)
+               p->handle_irq = port->handle_irq;
+       else
+               p->handle_irq = serial8250_default_handle_irq;
 
        return 0;
 }
@@ -3095,6 +3074,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.handle_irq         = p->handle_irq;
                port.set_termios        = p->set_termios;
                port.pm                 = p->pm;
                port.dev                = &dev->dev;
@@ -3260,6 +3240,8 @@ 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;
+               if (port->handle_irq)
+                       uart->port.handle_irq = port->handle_irq;
                /*  Possibly override set_termios call */
                if (port->set_termios)
                        uart->port.set_termios = port->set_termios;