[DRIVER MODEL] Convert platform drivers to use struct platform_driver
[safe/jmp/linux-2.6] / drivers / serial / 8250.c
index 7e8fc7c..3742753 100644 (file)
 #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 <asm/io.h>
 #include <asm/irq.h>
@@ -251,9 +252,53 @@ static const struct serial8250_config uart_config[] = {
        },
 };
 
+#ifdef 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];
+}
+
+#else
+
+/* sane hardware needs no mapping */
+#define map_8250_in_reg(up, offset) (offset)
+#define map_8250_out_reg(up, offset) (offset)
+
+#endif
+
 static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset)
 {
-       offset <<= up->port.regshift;
+       offset = map_8250_in_reg(up, offset) << up->port.regshift;
 
        switch (up->port.iotype) {
        case UPIO_HUB6:
@@ -266,6 +311,11 @@ static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset)
        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
+
        default:
                return inb(up->port.iobase + offset);
        }
@@ -274,7 +324,7 @@ static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset)
 static _INLINE_ void
 serial_out(struct uart_8250_port *up, int offset, int value)
 {
-       offset <<= up->port.regshift;
+       offset = map_8250_out_reg(up, offset) << up->port.regshift;
 
        switch (up->port.iotype) {
        case UPIO_HUB6:
@@ -290,6 +340,12 @@ serial_out(struct uart_8250_port *up, int offset, int value)
                writel(value, up->port.membase + offset);
                break;
 
+#ifdef CONFIG_SERIAL_8250_AU1X00
+       case UPIO_AU:
+               __raw_writel(value, up->port.membase + offset);
+               break;
+#endif
+
        default:
                outb(value, up->port.iobase + offset);
        }
@@ -864,7 +920,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
        /*
         * We're pretty sure there's a port here.  Lets find out what
         * type of port it is.  The IIR top two bits allows us to find
-        * out if its 8250 or 16450, 16550, 16550A or later.  This
+        * out if it's 8250 or 16450, 16550, 16550A or later.  This
         * determines what we test for next.
         *
         * We also initialise the EFR (if any) to zero for later.  The
@@ -910,6 +966,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) {
@@ -1001,7 +1064,7 @@ static inline void __stop_tx(struct uart_8250_port *p)
        }
 }
 
-static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void serial8250_stop_tx(struct uart_port *port)
 {
        struct uart_8250_port *up = (struct uart_8250_port *)port;
 
@@ -1018,7 +1081,7 @@ static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop)
 
 static void transmit_chars(struct uart_8250_port *up);
 
-static void serial8250_start_tx(struct uart_port *port, unsigned int tty_start)
+static void serial8250_start_tx(struct uart_port *port)
 {
        struct uart_8250_port *up = (struct uart_8250_port *)port;
 
@@ -1057,6 +1120,10 @@ 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);
 }
@@ -1158,7 +1225,11 @@ static _INLINE_ void transmit_chars(struct uart_8250_port *up)
                up->port.x_char = 0;
                return;
        }
-       if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
+       if (uart_tx_stopped(&up->port)) {
+               serial8250_stop_tx(&up->port);
+               return;
+       }
+       if (uart_circ_empty(xmit)) {
                __stop_tx(up);
                return;
        }
@@ -1770,7 +1841,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;
@@ -2137,6 +2209,8 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
        unsigned int ier;
        int i;
 
+       touch_nmi_watchdog();
+
        /*
         *      First save the UER then disable the interrupts
         */
@@ -2307,9 +2381,9 @@ 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;
 
@@ -2325,12 +2399,12 @@ static int __devinit serial8250_probe(struct device *dev)
                port.flags      = p->flags;
                port.mapbase    = p->mapbase;
                port.hub6       = p->hub6;
-               port.dev        = dev;
+               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 "
+                       dev_err(&dev->dev, "unable to register port at index %d "
                                "(IO%lx MEM%lx IRQ%d): %d\n", i,
                                p->iobase, p->mapbase, p->irq, ret);
                }
@@ -2341,60 +2415,55 @@ 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++) {
                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)
+               if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
                        uart_resume_port(&serial8250_reg, &up->port);
        }
 
        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",
+       },
 };
 
 /*
@@ -2532,7 +2601,7 @@ static int __init serial8250_init(void)
                goto out;
 
        serial8250_isa_devs = platform_device_register_simple("serial8250",
-                                                             -1, NULL, 0);
+                                        PLAT8250_DEV_LEGACY, NULL, 0);
        if (IS_ERR(serial8250_isa_devs)) {
                ret = PTR_ERR(serial8250_isa_devs);
                goto unreg;
@@ -2540,7 +2609,7 @@ static int __init serial8250_init(void)
 
        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;
 
@@ -2562,7 +2631,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);
@@ -2586,82 +2655,3 @@ module_param_array(probe_rsa, ulong, &probe_rsa_count, 0444);
 MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");
 #endif
 MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR);
-
-/**
- *     register_serial - configure a 16x50 serial port at runtime
- *     @req: request structure
- *
- *     Configure the serial port specified by the request. If the
- *     port exists and is in use an error is returned. If the port
- *     is not currently in the table it is added.
- *
- *     The port is then probed and if necessary the IRQ is autodetected
- *     If this fails an error is returned.
- *
- *     On success the port is ready to use and the line number is returned.
- *
- *     Note: this function is deprecated - use serial8250_register_port
- *     instead.
- */
-int register_serial(struct serial_struct *req)
-{
-       struct uart_port port;
-
-       port.iobase   = req->port;
-       port.membase  = req->iomem_base;
-       port.irq      = req->irq;
-       port.uartclk  = req->baud_base * 16;
-       port.fifosize = req->xmit_fifo_size;
-       port.regshift = req->iomem_reg_shift;
-       port.iotype   = req->io_type;
-       port.flags    = req->flags | UPF_BOOT_AUTOCONF;
-       port.mapbase  = req->iomap_base;
-       port.dev      = NULL;
-
-       if (share_irqs)
-               port.flags |= UPF_SHARE_IRQ;
-
-       if (HIGH_BITS_OFFSET)
-               port.iobase |= (long) req->port_high << HIGH_BITS_OFFSET;
-
-       /*
-        * If a clock rate wasn't specified by the low level driver, then
-        * default to the standard clock rate.  This should be 115200 (*16)
-        * and should not depend on the architecture's BASE_BAUD definition.
-        * However, since this API will be deprecated, it's probably a
-        * better idea to convert the drivers to use the new API
-        * (serial8250_register_port and serial8250_unregister_port).
-        */
-       if (port.uartclk == 0) {
-               printk(KERN_WARNING
-                      "Serial: registering port at [%08x,%08lx,%p] irq %d with zero baud_base\n",
-                      port.iobase, port.mapbase, port.membase, port.irq);
-               printk(KERN_WARNING "Serial: see %s:%d for more information\n",
-                      __FILE__, __LINE__);
-               dump_stack();
-
-               /*
-                * Fix it up for now, but this is only a temporary measure.
-                */
-               port.uartclk = BASE_BAUD * 16;
-       }
-
-       return serial8250_register_port(&port);
-}
-EXPORT_SYMBOL(register_serial);
-
-/**
- *     unregister_serial - remove a 16x50 serial port at runtime
- *     @line: serial line number
- *
- *     Remove one serial port.  This may not be called from interrupt
- *     context.  We hand the port back to our local PM control.
- *
- *     Note: this function is deprecated - use serial8250_unregister_port
- *     instead.
- */
-void unregister_serial(int line)
-{
-       serial8250_unregister_port(line);
-}
-EXPORT_SYMBOL(unregister_serial);