firewire: fw-sbp2: simplify some macros
[safe/jmp/linux-2.6] / drivers / serial / imx.c
index 01a8726..16ba9ac 100644 (file)
@@ -25,7 +25,6 @@
  * [29-Mar-2005] Mike Lee
  * Added hardware handshake
  */
-#include <linux/config.h>
 
 #if defined(CONFIG_SERIAL_IMX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
@@ -36,7 +35,7 @@
 #include <linux/init.h>
 #include <linux/console.h>
 #include <linux/sysrq.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/serial_core.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/hardware.h>
+#include <asm/arch/imx-uart.h>
+
+/* Register definitions */
+#define URXD0 0x0  /* Receiver Register */
+#define URTX0 0x40 /* Transmitter Register */
+#define UCR1  0x80 /* Control Register 1 */
+#define UCR2  0x84 /* Control Register 2 */
+#define UCR3  0x88 /* Control Register 3 */
+#define UCR4  0x8c /* Control Register 4 */
+#define UFCR  0x90 /* FIFO Control Register */
+#define USR1  0x94 /* Status Register 1 */
+#define USR2  0x98 /* Status Register 2 */
+#define UESC  0x9c /* Escape Character Register */
+#define UTIM  0xa0 /* Escape Timer Register */
+#define UBIR  0xa4 /* BRM Incremental Register */
+#define UBMR  0xa8 /* BRM Modulator Register */
+#define UBRC  0xac /* Baud Rate Count Register */
+#define BIPR1 0xb0 /* Incremental Preset Register 1 */
+#define BIPR2 0xb4 /* Incremental Preset Register 2 */
+#define BIPR3 0xb8 /* Incremental Preset Register 3 */
+#define BIPR4 0xbc /* Incremental Preset Register 4 */
+#define BMPR1 0xc0 /* BRM Modulator Register 1 */
+#define BMPR2 0xc4 /* BRM Modulator Register 2 */
+#define BMPR3 0xc8 /* BRM Modulator Register 3 */
+#define BMPR4 0xcc /* BRM Modulator Register 4 */
+#define UTS   0xd0 /* UART Test Register */
+
+/* UART Control Register Bit Fields.*/
+#define  URXD_CHARRDY    (1<<15)
+#define  URXD_ERR        (1<<14)
+#define  URXD_OVRRUN     (1<<13)
+#define  URXD_FRMERR     (1<<12)
+#define  URXD_BRK        (1<<11)
+#define  URXD_PRERR      (1<<10)
+#define  UCR1_ADEN       (1<<15) /* Auto dectect interrupt */
+#define  UCR1_ADBR       (1<<14) /* Auto detect baud rate */
+#define  UCR1_TRDYEN     (1<<13) /* Transmitter ready interrupt enable */
+#define  UCR1_IDEN       (1<<12) /* Idle condition interrupt */
+#define  UCR1_RRDYEN     (1<<9)         /* Recv ready interrupt enable */
+#define  UCR1_RDMAEN     (1<<8)         /* Recv ready DMA enable */
+#define  UCR1_IREN       (1<<7)         /* Infrared interface enable */
+#define  UCR1_TXMPTYEN   (1<<6)         /* Transimitter empty interrupt enable */
+#define  UCR1_RTSDEN     (1<<5)         /* RTS delta interrupt enable */
+#define  UCR1_SNDBRK     (1<<4)         /* Send break */
+#define  UCR1_TDMAEN     (1<<3)         /* Transmitter ready DMA enable */
+#define  UCR1_UARTCLKEN  (1<<2)         /* UART clock enabled */
+#define  UCR1_DOZE       (1<<1)         /* Doze */
+#define  UCR1_UARTEN     (1<<0)         /* UART enabled */
+#define  UCR2_ESCI              (1<<15) /* Escape seq interrupt enable */
+#define  UCR2_IRTS      (1<<14) /* Ignore RTS pin */
+#define  UCR2_CTSC      (1<<13) /* CTS pin control */
+#define  UCR2_CTS        (1<<12) /* Clear to send */
+#define  UCR2_ESCEN      (1<<11) /* Escape enable */
+#define  UCR2_PREN       (1<<8)  /* Parity enable */
+#define  UCR2_PROE       (1<<7)  /* Parity odd/even */
+#define  UCR2_STPB       (1<<6)         /* Stop */
+#define  UCR2_WS         (1<<5)         /* Word size */
+#define  UCR2_RTSEN      (1<<4)         /* Request to send interrupt enable */
+#define  UCR2_TXEN       (1<<2)         /* Transmitter enabled */
+#define  UCR2_RXEN       (1<<1)         /* Receiver enabled */
+#define  UCR2_SRST      (1<<0)  /* SW reset */
+#define  UCR3_DTREN     (1<<13) /* DTR interrupt enable */
+#define  UCR3_PARERREN   (1<<12) /* Parity enable */
+#define  UCR3_FRAERREN   (1<<11) /* Frame error interrupt enable */
+#define  UCR3_DSR        (1<<10) /* Data set ready */
+#define  UCR3_DCD        (1<<9)  /* Data carrier detect */
+#define  UCR3_RI         (1<<8)  /* Ring indicator */
+#define  UCR3_TIMEOUTEN  (1<<7)  /* Timeout interrupt enable */
+#define  UCR3_RXDSEN    (1<<6)  /* Receive status interrupt enable */
+#define  UCR3_AIRINTEN   (1<<5)  /* Async IR wake interrupt enable */
+#define  UCR3_AWAKEN    (1<<4)  /* Async wake interrupt enable */
+#define  UCR3_REF25     (1<<3)  /* Ref freq 25 MHz */
+#define  UCR3_REF30     (1<<2)  /* Ref Freq 30 MHz */
+#define  UCR3_INVT      (1<<1)  /* Inverted Infrared transmission */
+#define  UCR3_BPEN      (1<<0)  /* Preset registers enable */
+#define  UCR4_CTSTL_32   (32<<10) /* CTS trigger level (32 chars) */
+#define  UCR4_INVR      (1<<9)  /* Inverted infrared reception */
+#define  UCR4_ENIRI     (1<<8)  /* Serial infrared interrupt enable */
+#define  UCR4_WKEN      (1<<7)  /* Wake interrupt enable */
+#define  UCR4_REF16     (1<<6)  /* Ref freq 16 MHz */
+#define  UCR4_IRSC      (1<<5)  /* IR special case */
+#define  UCR4_TCEN      (1<<3)  /* Transmit complete interrupt enable */
+#define  UCR4_BKEN      (1<<2)  /* Break condition interrupt enable */
+#define  UCR4_OREN      (1<<1)  /* Receiver overrun interrupt enable */
+#define  UCR4_DREN      (1<<0)  /* Recv data ready interrupt enable */
+#define  UFCR_RXTL_SHF   0       /* Receiver trigger level shift */
+#define  UFCR_RFDIV      (7<<7)  /* Reference freq divider mask */
+#define  UFCR_TXTL_SHF   10      /* Transmitter trigger level shift */
+#define  USR1_PARITYERR  (1<<15) /* Parity error interrupt flag */
+#define  USR1_RTSS      (1<<14) /* RTS pin status */
+#define  USR1_TRDY      (1<<13) /* Transmitter ready interrupt/dma flag */
+#define  USR1_RTSD      (1<<12) /* RTS delta */
+#define  USR1_ESCF      (1<<11) /* Escape seq interrupt flag */
+#define  USR1_FRAMERR    (1<<10) /* Frame error interrupt flag */
+#define  USR1_RRDY       (1<<9)         /* Receiver ready interrupt/dma flag */
+#define  USR1_TIMEOUT    (1<<7)         /* Receive timeout interrupt status */
+#define  USR1_RXDS      (1<<6)  /* Receiver idle interrupt flag */
+#define  USR1_AIRINT    (1<<5)  /* Async IR wake interrupt flag */
+#define  USR1_AWAKE     (1<<4)  /* Aysnc wake interrupt flag */
+#define  USR2_ADET      (1<<15) /* Auto baud rate detect complete */
+#define  USR2_TXFE      (1<<14) /* Transmit buffer FIFO empty */
+#define  USR2_DTRF      (1<<13) /* DTR edge interrupt flag */
+#define  USR2_IDLE      (1<<12) /* Idle condition */
+#define  USR2_IRINT     (1<<8)  /* Serial infrared interrupt flag */
+#define  USR2_WAKE      (1<<7)  /* Wake */
+#define  USR2_RTSF      (1<<4)  /* RTS edge interrupt flag */
+#define  USR2_TXDC      (1<<3)  /* Transmitter complete */
+#define  USR2_BRCD      (1<<2)  /* Break condition */
+#define  USR2_ORE        (1<<1)         /* Overrun error */
+#define  USR2_RDR        (1<<0)         /* Recv data ready */
+#define  UTS_FRCPERR    (1<<13) /* Force parity error */
+#define  UTS_LOOP        (1<<12) /* Loop tx and rx */
+#define  UTS_TXEMPTY    (1<<6)  /* TxFIFO empty */
+#define  UTS_RXEMPTY    (1<<5)  /* RxFIFO empty */
+#define  UTS_TXFULL     (1<<4)  /* TxFIFO full */
+#define  UTS_RXFULL     (1<<3)  /* RxFIFO full */
+#define  UTS_SOFTRST    (1<<0)  /* Software reset */
 
 /* We've been assigned a range on the "Low-density serial ports" major */
 #define SERIAL_IMX_MAJOR       204
@@ -73,7 +189,8 @@ struct imx_port {
        struct uart_port        port;
        struct timer_list       timer;
        unsigned int            old_status;
-       int txirq,rxirq;
+       int                     txirq,rxirq,rtsirq;
+       int                     have_rtscts:1;
 };
 
 /*
@@ -124,10 +241,13 @@ static void imx_timeout(unsigned long data)
 /*
  * interrupts disabled on entry
  */
-static void imx_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void imx_stop_tx(struct uart_port *port)
 {
        struct imx_port *sport = (struct imx_port *)port;
-       UCR1((u32)sport->port.membase) &= ~UCR1_TXMPTYEN;
+       unsigned long temp;
+
+       temp = readl(sport->port.membase + UCR1);
+       writel(temp & ~UCR1_TXMPTYEN, sport->port.membase + UCR1);
 }
 
 /*
@@ -136,7 +256,10 @@ static void imx_stop_tx(struct uart_port *port, unsigned int tty_stop)
 static void imx_stop_rx(struct uart_port *port)
 {
        struct imx_port *sport = (struct imx_port *)port;
-       UCR2((u32)sport->port.membase) &= ~UCR2_RXEN;
+       unsigned long temp;
+
+       temp = readl(sport->port.membase + UCR2);
+       writel(temp &~ UCR2_RXEN, sport->port.membase + UCR2);
 }
 
 /*
@@ -153,37 +276,55 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
 {
        struct circ_buf *xmit = &sport->port.info->xmit;
 
-       do {
+       while (!(readl(sport->port.membase + UTS) & UTS_TXFULL)) {
                /* send xmit->buf[xmit->tail]
                 * out the port here */
-               URTX0((u32)sport->port.membase) = xmit->buf[xmit->tail];
+               writel(xmit->buf[xmit->tail], sport->port.membase + URTX0);
                xmit->tail = (xmit->tail + 1) &
                         (UART_XMIT_SIZE - 1);
                sport->port.icount.tx++;
                if (uart_circ_empty(xmit))
                        break;
-       } while (!(UTS((u32)sport->port.membase) & UTS_TXFULL));
+       }
 
        if (uart_circ_empty(xmit))
-               imx_stop_tx(&sport->port, 0);
+               imx_stop_tx(&sport->port);
 }
 
 /*
  * interrupts disabled on entry
  */
-static void imx_start_tx(struct uart_port *port, unsigned int tty_start)
+static void imx_start_tx(struct uart_port *port)
 {
        struct imx_port *sport = (struct imx_port *)port;
+       unsigned long temp;
 
-       UCR1((u32)sport->port.membase) |= UCR1_TXMPTYEN;
+       temp = readl(sport->port.membase + UCR1);
+       writel(temp | UCR1_TXMPTYEN, sport->port.membase + UCR1);
 
-       if(UTS((u32)sport->port.membase) & UTS_TXEMPTY)
+       if (readl(sport->port.membase + UTS) & UTS_TXEMPTY)
                imx_transmit_buffer(sport);
 }
 
-static irqreturn_t imx_txint(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t imx_rtsint(int irq, void *dev_id)
+{
+       struct imx_port *sport = dev_id;
+       unsigned int val = readl(sport->port.membase + USR1) & USR1_RTSS;
+       unsigned long flags;
+
+       spin_lock_irqsave(&sport->port.lock, flags);
+
+       writel(USR1_RTSD, sport->port.membase + USR1);
+       uart_handle_cts_change(&sport->port, !!val);
+       wake_up_interruptible(&sport->port.info->delta_msr_wait);
+
+       spin_unlock_irqrestore(&sport->port.lock, flags);
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t imx_txint(int irq, void *dev_id)
 {
-       struct imx_port *sport = (struct imx_port *)dev_id;
+       struct imx_port *sport = dev_id;
        struct circ_buf *xmit = &sport->port.info->xmit;
        unsigned long flags;
 
@@ -191,12 +332,12 @@ static irqreturn_t imx_txint(int irq, void *dev_id, struct pt_regs *regs)
        if (sport->port.x_char)
        {
                /* Send next char */
-               URTX0((u32)sport->port.membase) = sport->port.x_char;
+               writel(sport->port.x_char, sport->port.membase + URTX0);
                goto out;
        }
 
        if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
-               imx_stop_tx(&sport->port, 0);
+               imx_stop_tx(&sport->port);
                goto out;
        }
 
@@ -210,28 +351,29 @@ out:
        return IRQ_HANDLED;
 }
 
-static irqreturn_t imx_rxint(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t imx_rxint(int irq, void *dev_id)
 {
        struct imx_port *sport = dev_id;
        unsigned int rx,flg,ignored = 0;
        struct tty_struct *tty = sport->port.info->tty;
-       unsigned long flags;
+       unsigned long flags, temp;
 
-       rx = URXD0((u32)sport->port.membase);
+       rx = readl(sport->port.membase + URXD0);
        spin_lock_irqsave(&sport->port.lock,flags);
 
        do {
                flg = TTY_NORMAL;
                sport->port.icount.rx++;
 
-               if( USR2((u32)sport->port.membase) & USR2_BRCD ) {
-                       USR2((u32)sport->port.membase) |= USR2_BRCD;
+               temp = readl(sport->port.membase + USR2);
+               if( temp & USR2_BRCD ) {
+                       writel(temp | USR2_BRCD, sport->port.membase + USR2);
                        if(uart_handle_break(&sport->port))
                                goto ignore_char;
                }
 
                if (uart_handle_sysrq_char
-                           (&sport->port, (unsigned char)rx, regs))
+                           (&sport->port, (unsigned char)rx))
                        goto ignore_char;
 
                if( rx & (URXD_PRERR | URXD_OVRRUN | URXD_FRMERR) )
@@ -240,11 +382,8 @@ static irqreturn_t imx_rxint(int irq, void *dev_id, struct pt_regs *regs)
        error_return:
                tty_insert_flip_char(tty, rx, flg);
 
-               if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-                       goto out;
-
        ignore_char:
-               rx = URXD0((u32)sport->port.membase);
+               rx = readl(sport->port.membase + URXD0);
        } while(rx & URXD_CHARRDY);
 
 out:
@@ -288,16 +427,37 @@ static unsigned int imx_tx_empty(struct uart_port *port)
 {
        struct imx_port *sport = (struct imx_port *)port;
 
-       return USR2((u32)sport->port.membase) & USR2_TXDC ?  TIOCSER_TEMT : 0;
+       return (readl(sport->port.membase + USR2) & USR2_TXDC) ?  TIOCSER_TEMT : 0;
 }
 
+/*
+ * We have a modem side uart, so the meanings of RTS and CTS are inverted.
+ */
 static unsigned int imx_get_mctrl(struct uart_port *port)
 {
-       return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
+        struct imx_port *sport = (struct imx_port *)port;
+        unsigned int tmp = TIOCM_DSR | TIOCM_CAR;
+
+        if (readl(sport->port.membase + USR1) & USR1_RTSS)
+                tmp |= TIOCM_CTS;
+
+        if (readl(sport->port.membase + UCR2) & UCR2_CTS)
+                tmp |= TIOCM_RTS;
+
+        return tmp;
 }
 
 static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
+        struct imx_port *sport = (struct imx_port *)port;
+       unsigned long temp;
+
+       temp = readl(sport->port.membase + UCR2) & ~UCR2_CTS;
+
+        if (mctrl & TIOCM_RTS)
+               temp |= UCR2_CTS;
+
+       writel(temp, sport->port.membase + UCR2);
 }
 
 /*
@@ -306,14 +466,16 @@ static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl)
 static void imx_break_ctl(struct uart_port *port, int break_state)
 {
        struct imx_port *sport = (struct imx_port *)port;
-       unsigned long flags;
+       unsigned long flags, temp;
 
        spin_lock_irqsave(&sport->port.lock, flags);
 
+       temp = readl(sport->port.membase + UCR1) & ~UCR1_SNDBRK;
+
        if ( break_state != 0 )
-               UCR1((u32)sport->port.membase) |= UCR1_SNDBRK;
-       else
-               UCR1((u32)sport->port.membase) &= ~UCR1_SNDBRK;
+               temp |= UCR1_SNDBRK;
+
+       writel(temp, sport->port.membase + UCR1);
 
        spin_unlock_irqrestore(&sport->port.lock, flags);
 }
@@ -329,7 +491,7 @@ static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode)
        /* set receiver / transmitter trigger level.
         * RFDIV is set such way to satisfy requested uartclk value
         */
-       val = TXTL<<10 | RXTL;
+       val = TXTL << 10 | RXTL;
        ufcr_rfdiv = (imx_get_perclk1() + sport->port.uartclk / 2) / sport->port.uartclk;
 
        if(!ufcr_rfdiv)
@@ -342,7 +504,7 @@ static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode)
 
        val |= UFCR_RFDIV & (ufcr_rfdiv << 7);
 
-       UFCR((u32)sport->port.membase) = val;
+       writel(val, sport->port.membase + UFCR);
 
        return 0;
 }
@@ -351,34 +513,46 @@ static int imx_startup(struct uart_port *port)
 {
        struct imx_port *sport = (struct imx_port *)port;
        int retval;
-       unsigned long flags;
+       unsigned long flags, temp;
 
        imx_setup_ufcr(sport, 0);
 
        /* disable the DREN bit (Data Ready interrupt enable) before
         * requesting IRQs
         */
-       UCR4((u32)sport->port.membase) &= ~UCR4_DREN;
+       temp = readl(sport->port.membase + UCR4);
+       writel(temp & ~UCR4_DREN, sport->port.membase + UCR4);
 
        /*
         * Allocate the IRQ
         */
        retval = request_irq(sport->rxirq, imx_rxint, 0,
                             DRIVER_NAME, sport);
-       if (retval) goto error_out2;
+       if (retval) goto error_out1;
 
        retval = request_irq(sport->txirq, imx_txint, 0,
-                            "imx-uart", sport);
-       if (retval) goto error_out1;
+                            DRIVER_NAME, sport);
+       if (retval) goto error_out2;
+
+       retval = request_irq(sport->rtsirq, imx_rtsint,
+                            (sport->rtsirq < IMX_IRQS) ? 0 :
+                              IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+                            DRIVER_NAME, sport);
+       if (retval) goto error_out3;
 
        /*
         * Finally, clear and enable interrupts
         */
+       writel(USR1_RTSD, sport->port.membase + USR1);
 
-       UCR1((u32)sport->port.membase) |=
-                        (UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_UARTEN);
+       temp = readl(sport->port.membase + UCR1);
+       temp |= (UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);
+       writel(temp, sport->port.membase + UCR1);
+
+       temp = readl(sport->port.membase + UCR2);
+       temp |= (UCR2_RXEN | UCR2_TXEN);
+       writel(temp, sport->port.membase + UCR2);
 
-       UCR2((u32)sport->port.membase) |= (UCR2_RXEN | UCR2_TXEN);
        /*
         * Enable modem status interrupts
         */
@@ -388,16 +562,18 @@ static int imx_startup(struct uart_port *port)
 
        return 0;
 
-error_out1:
-       free_irq(sport->rxirq, sport);
-error_out2:
+error_out3:
        free_irq(sport->txirq, sport);
+error_out2:
+       free_irq(sport->rxirq, sport);
+error_out1:
        return retval;
 }
 
 static void imx_shutdown(struct uart_port *port)
 {
        struct imx_port *sport = (struct imx_port *)port;
+       unsigned long temp;
 
        /*
         * Stop our timer.
@@ -407,6 +583,7 @@ static void imx_shutdown(struct uart_port *port)
        /*
         * Free the interrupts
         */
+       free_irq(sport->rtsirq, sport);
        free_irq(sport->txirq, sport);
        free_irq(sport->rxirq, sport);
 
@@ -414,13 +591,14 @@ static void imx_shutdown(struct uart_port *port)
         * Disable all interrupts, port and break condition.
         */
 
-       UCR1((u32)sport->port.membase) &=
-                        ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_UARTEN);
+       temp = readl(sport->port.membase + UCR1);
+       temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);
+       writel(temp, sport->port.membase + UCR1);
 }
 
 static void
-imx_set_termios(struct uart_port *port, struct termios *termios,
-                  struct termios *old)
+imx_set_termios(struct uart_port *port, struct ktermios *termios,
+                  struct ktermios *old)
 {
        struct imx_port *sport = (struct imx_port *)port;
        unsigned long flags;
@@ -452,15 +630,19 @@ imx_set_termios(struct uart_port *port, struct termios *termios,
                ucr2 = UCR2_SRST | UCR2_IRTS;
 
        if (termios->c_cflag & CRTSCTS) {
-               ucr2 &= ~UCR2_IRTS;
-               ucr2 |= UCR2_CTSC;
+               if( sport->have_rtscts ) {
+                       ucr2 &= ~UCR2_IRTS;
+                       ucr2 |= UCR2_CTSC;
+               } else {
+                       termios->c_cflag &= ~CRTSCTS;
+               }
        }
 
        if (termios->c_cflag & CSTOPB)
                ucr2 |= UCR2_STPB;
        if (termios->c_cflag & PARENB) {
                ucr2 |= UCR2_PREN;
-               if (!(termios->c_cflag & PARODD))
+               if (termios->c_cflag & PARODD)
                        ucr2 |= UCR2_PROE;
        }
 
@@ -504,18 +686,18 @@ imx_set_termios(struct uart_port *port, struct termios *termios,
        /*
         * disable interrupts and drain transmitter
         */
-       old_ucr1 = UCR1((u32)sport->port.membase);
-       UCR1((u32)sport->port.membase) &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN);
+       old_ucr1 = readl(sport->port.membase + UCR1);
+       writel(old_ucr1 & ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN),
+                       sport->port.membase + UCR1);
 
-       while ( !(USR2((u32)sport->port.membase) & USR2_TXDC))
+       while ( !(readl(sport->port.membase + USR2) & USR2_TXDC))
                barrier();
 
        /* then, disable everything */
-       old_txrxen = UCR2((u32)sport->port.membase) & ( UCR2_TXEN | UCR2_RXEN );
-       UCR2((u32)sport->port.membase) &= ~( UCR2_TXEN | UCR2_RXEN);
-
-       /* set the parity, stop bits and data size */
-       UCR2((u32)sport->port.membase) = ucr2;
+       old_txrxen = readl(sport->port.membase + UCR2);
+       writel(old_txrxen & ~( UCR2_TXEN | UCR2_RXEN),
+                       sport->port.membase + UCR2);
+       old_txrxen &= (UCR2_TXEN | UCR2_RXEN);
 
        /* set the baud rate. We assume uartclk = 16 MHz
         *
@@ -523,11 +705,13 @@ imx_set_termios(struct uart_port *port, struct termios *termios,
         * --------- = --------
         *  uartclk    UBMR - 1
         */
-       UBIR((u32)sport->port.membase) = (baud / 100) - 1;
-       UBMR((u32)sport->port.membase) = 10000 - 1;
+       writel((baud / 100) - 1, sport->port.membase + UBIR);
+       writel(10000 - 1, sport->port.membase + UBMR);
+
+       writel(old_ucr1, sport->port.membase + UCR1);
 
-       UCR1((u32)sport->port.membase) = old_ucr1;
-       UCR2((u32)sport->port.membase) |= old_txrxen;
+       /* set the parity, stop bits and data size */
+       writel(ucr2 | old_txrxen, sport->port.membase + UCR2);
 
        if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
                imx_enable_ms(&sport->port);
@@ -626,30 +810,32 @@ static struct imx_port imx_ports[] = {
        {
        .txirq  = UART1_MINT_TX,
        .rxirq  = UART1_MINT_RX,
+       .rtsirq = UART1_MINT_RTS,
        .port   = {
                .type           = PORT_IMX,
-               .iotype         = SERIAL_IO_MEM,
+               .iotype         = UPIO_MEM,
                .membase        = (void *)IMX_UART1_BASE,
                .mapbase        = IMX_UART1_BASE, /* FIXME */
                .irq            = UART1_MINT_RX,
                .uartclk        = 16000000,
-               .fifosize       = 8,
-               .flags          = ASYNC_BOOT_AUTOCONF,
+               .fifosize       = 32,
+               .flags          = UPF_BOOT_AUTOCONF,
                .ops            = &imx_pops,
                .line           = 0,
        },
        }, {
        .txirq  = UART2_MINT_TX,
        .rxirq  = UART2_MINT_RX,
+       .rtsirq = UART2_MINT_RTS,
        .port   = {
                .type           = PORT_IMX,
-               .iotype         = SERIAL_IO_MEM,
+               .iotype         = UPIO_MEM,
                .membase        = (void *)IMX_UART2_BASE,
                .mapbase        = IMX_UART2_BASE, /* FIXME */
                .irq            = UART2_MINT_RX,
                .uartclk        = 16000000,
-               .fifosize       = 8,
-               .flags          = ASYNC_BOOT_AUTOCONF,
+               .fifosize       = 32,
+               .flags          = UPF_BOOT_AUTOCONF,
                .ops            = &imx_pops,
                .line           = 1,
        },
@@ -678,31 +864,19 @@ static void __init imx_init_ports(void)
                imx_ports[i].timer.function = imx_timeout;
                imx_ports[i].timer.data     = (unsigned long)&imx_ports[i];
        }
+}
 
-       imx_gpio_mode(PC9_PF_UART1_CTS);
-       imx_gpio_mode(PC10_PF_UART1_RTS);
-       imx_gpio_mode(PC11_PF_UART1_TXD);
-       imx_gpio_mode(PC12_PF_UART1_RXD);
-       imx_gpio_mode(PB28_PF_UART2_CTS);
-       imx_gpio_mode(PB29_PF_UART2_RTS);
-
-       imx_gpio_mode(PB30_PF_UART2_TXD);
-       imx_gpio_mode(PB31_PF_UART2_RXD);
-
-#if 0 /* We don't need these, on the mx1 the _modem_ side of the uart
-       * is implemented.
-       */
-       imx_gpio_mode(PD7_AF_UART2_DTR);
-       imx_gpio_mode(PD8_AF_UART2_DCD);
-       imx_gpio_mode(PD9_AF_UART2_RI);
-       imx_gpio_mode(PD10_AF_UART2_DSR);
-#endif
+#ifdef CONFIG_SERIAL_IMX_CONSOLE
+static void imx_console_putchar(struct uart_port *port, int ch)
+{
+       struct imx_port *sport = (struct imx_port *)port;
 
+       while (readl(sport->port.membase + UTS) & UTS_TXFULL)
+               barrier();
 
+       writel(ch, sport->port.membase + URTX0);
 }
 
-#ifdef CONFIG_SERIAL_IMX_CONSOLE
-
 /*
  * Interrupts are disabled on entering
  */
@@ -710,44 +884,30 @@ static void
 imx_console_write(struct console *co, const char *s, unsigned int count)
 {
        struct imx_port *sport = &imx_ports[co->index];
-       unsigned int old_ucr1, old_ucr2, i;
+       unsigned int old_ucr1, old_ucr2;
 
        /*
         *      First, save UCR1/2 and then disable interrupts
         */
-       old_ucr1 = UCR1((u32)sport->port.membase);
-       old_ucr2 = UCR2((u32)sport->port.membase);
+       old_ucr1 = readl(sport->port.membase + UCR1);
+       old_ucr2 = readl(sport->port.membase + UCR2);
 
-       UCR1((u32)sport->port.membase) =
-                          (old_ucr1 | UCR1_UARTCLKEN | UCR1_UARTEN)
-                          & ~(UCR1_TXMPTYEN | UCR1_RRDYEN);
-       UCR2((u32)sport->port.membase) = old_ucr2 | UCR2_TXEN;
+       writel((old_ucr1 | UCR1_UARTCLKEN | UCR1_UARTEN) &
+               ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN),
+               sport->port.membase + UCR1);
 
-       /*
-        *      Now, do each character
-        */
-       for (i = 0; i < count; i++) {
+       writel(old_ucr2 | UCR2_TXEN, sport->port.membase + UCR2);
 
-               while ((UTS((u32)sport->port.membase) & UTS_TXFULL))
-                       barrier();
-
-               URTX0((u32)sport->port.membase) = s[i];
-
-               if (s[i] == '\n') {
-                       while ((UTS((u32)sport->port.membase) & UTS_TXFULL))
-                               barrier();
-                       URTX0((u32)sport->port.membase) = '\r';
-               }
-       }
+       uart_console_write(&sport->port, s, count, imx_console_putchar);
 
        /*
         *      Finally, wait for transmitter to become empty
         *      and restore UCR1/2
         */
-       while (!(USR2((u32)sport->port.membase) & USR2_TXDC));
+       while (!(readl(sport->port.membase + USR2) & USR2_TXDC));
 
-       UCR1((u32)sport->port.membase) = old_ucr1;
-       UCR2((u32)sport->port.membase) = old_ucr2;
+       writel(old_ucr1, sport->port.membase + UCR1);
+       writel(old_ucr2, sport->port.membase + UCR2);
 }
 
 /*
@@ -759,13 +919,13 @@ imx_console_get_options(struct imx_port *sport, int *baud,
                           int *parity, int *bits)
 {
 
-       if ( UCR1((u32)sport->port.membase) | UCR1_UARTEN ) {
+       if ( readl(sport->port.membase + UCR1) | UCR1_UARTEN ) {
                /* ok, the port was enabled */
                unsigned int ucr2, ubir,ubmr, uartclk;
                unsigned int baud_raw;
                unsigned int ucfr_rfdiv;
 
-               ucr2 = UCR2((u32)sport->port.membase);
+               ucr2 = readl(sport->port.membase + UCR2);
 
                *parity = 'n';
                if (ucr2 & UCR2_PREN) {
@@ -780,11 +940,10 @@ imx_console_get_options(struct imx_port *sport, int *baud,
                else
                        *bits = 7;
 
-               ubir = UBIR((u32)sport->port.membase) & 0xffff;
-               ubmr = UBMR((u32)sport->port.membase) & 0xffff;
+               ubir = readl(sport->port.membase + UBIR) & 0xffff;
+               ubmr = readl(sport->port.membase + UBMR) & 0xffff;
 
-
-               ucfr_rfdiv = (UFCR((u32)sport->port.membase) & UFCR_RFDIV) >> 7;
+               ucfr_rfdiv = (readl(sport->port.membase + UFCR) & UFCR_RFDIV) >> 7;
                if (ucfr_rfdiv == 6)
                        ucfr_rfdiv = 7;
                else
@@ -842,7 +1001,7 @@ imx_console_setup(struct console *co, char *options)
        return uart_set_options(&sport->port, co, baud, parity, bits, flow);
 }
 
-extern struct uart_driver imx_reg;
+static struct uart_driver imx_reg;
 static struct console imx_console = {
        .name           = "ttySMX",
        .write          = imx_console_write,
@@ -870,48 +1029,52 @@ static struct uart_driver imx_reg = {
        .owner          = THIS_MODULE,
        .driver_name    = DRIVER_NAME,
        .dev_name       = "ttySMX",
-       .devfs_name     = "ttsmx/",
        .major          = SERIAL_IMX_MAJOR,
        .minor          = MINOR_START,
        .nr             = ARRAY_SIZE(imx_ports),
        .cons           = IMX_CONSOLE,
 };
 
-static int serial_imx_suspend(struct device *_dev, pm_message_t state, u32 level)
+static int serial_imx_suspend(struct platform_device *dev, pm_message_t state)
 {
-        struct imx_port *sport = dev_get_drvdata(_dev);
+        struct imx_port *sport = platform_get_drvdata(dev);
 
-        if (sport && level == SUSPEND_DISABLE)
+        if (sport)
                 uart_suspend_port(&imx_reg, &sport->port);
 
         return 0;
 }
 
-static int serial_imx_resume(struct device *_dev, u32 level)
+static int serial_imx_resume(struct platform_device *dev)
 {
-        struct imx_port *sport = dev_get_drvdata(_dev);
+        struct imx_port *sport = platform_get_drvdata(dev);
 
-        if (sport && level == RESUME_ENABLE)
+        if (sport)
                 uart_resume_port(&imx_reg, &sport->port);
 
         return 0;
 }
 
-static int serial_imx_probe(struct device *_dev)
+static int serial_imx_probe(struct platform_device *dev)
 {
-       struct platform_device *dev = to_platform_device(_dev);
+       struct imxuart_platform_data *pdata;
+
+       imx_ports[dev->id].port.dev = &dev->dev;
+
+       pdata = (struct imxuart_platform_data *)dev->dev.platform_data;
+       if(pdata && (pdata->flags & IMXUART_HAVE_RTSCTS))
+               imx_ports[dev->id].have_rtscts = 1;
 
-       imx_ports[dev->id].port.dev = _dev;
        uart_add_one_port(&imx_reg, &imx_ports[dev->id].port);
-       dev_set_drvdata(_dev, &imx_ports[dev->id]);
+       platform_set_drvdata(dev, &imx_ports[dev->id]);
        return 0;
 }
 
-static int serial_imx_remove(struct device *_dev)
+static int serial_imx_remove(struct platform_device *dev)
 {
-       struct imx_port *sport = dev_get_drvdata(_dev);
+       struct imx_port *sport = platform_get_drvdata(dev);
 
-       dev_set_drvdata(_dev, NULL);
+       platform_set_drvdata(dev, NULL);
 
        if (sport)
                uart_remove_one_port(&imx_reg, &sport->port);
@@ -919,14 +1082,16 @@ static int serial_imx_remove(struct device *_dev)
        return 0;
 }
 
-static struct device_driver serial_imx_driver = {
-        .name           = "imx-uart",
-        .bus            = &platform_bus_type,
+static struct platform_driver serial_imx_driver = {
         .probe          = serial_imx_probe,
         .remove         = serial_imx_remove,
 
        .suspend        = serial_imx_suspend,
        .resume         = serial_imx_resume,
+       .driver         = {
+               .name   = "imx-uart",
+               .owner  = THIS_MODULE,
+       },
 };
 
 static int __init imx_serial_init(void)
@@ -941,7 +1106,7 @@ static int __init imx_serial_init(void)
        if (ret)
                return ret;
 
-       ret = driver_register(&serial_imx_driver);
+       ret = platform_driver_register(&serial_imx_driver);
        if (ret != 0)
                uart_unregister_driver(&imx_reg);
 
@@ -950,6 +1115,7 @@ static int __init imx_serial_init(void)
 
 static void __exit imx_serial_exit(void)
 {
+       platform_driver_unregister(&serial_imx_driver);
        uart_unregister_driver(&imx_reg);
 }
 
@@ -959,3 +1125,4 @@ module_exit(imx_serial_exit);
 MODULE_AUTHOR("Sascha Hauer");
 MODULE_DESCRIPTION("IMX generic serial port driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:imx-uart");