USB: s3c-hsotg: Ensure FIFOs are fully flushed after layout
[safe/jmp/linux-2.6] / drivers / serial / imx.c
index 285b414..eacb588 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/rational.h>
+#include <linux/slab.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
 #define UBIR  0xa4 /* BRM Incremental Register */
 #define UBMR  0xa8 /* BRM Modulator Register */
 #define UBRC  0xac /* Baud Rate Count Register */
-#if defined CONFIG_ARCH_MX3 || defined CONFIG_ARCH_MX2
-#define ONEMS 0xb0 /* One Millisecond register */
-#define UTS   0xb4 /* UART Test Register */
-#endif
-#ifdef CONFIG_ARCH_MX1
-#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 */
-#endif
+#define MX2_ONEMS 0xb0 /* One Millisecond register */
+#define UTS (cpu_is_mx1() ? 0xd0 : 0xb4) /* UART Test Register */
 
 /* UART Control Register Bit Fields.*/
 #define  URXD_CHARRDY    (1<<15)
 #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 */
-#ifdef CONFIG_ARCH_MX1
-#define  UCR1_UARTCLKEN  (1<<2)         /* UART clock enabled */
-#endif
-#if defined CONFIG_ARCH_MX3 || defined CONFIG_ARCH_MX2
-#define  UCR1_UARTCLKEN  (0)    /* not present on mx2/mx3 */
-#endif
+#define  MX1_UCR1_UARTCLKEN  (1<<2)     /* UART clock enabled, mx1 only */
 #define  UCR1_DOZE       (1<<1)         /* Doze */
 #define  UCR1_UARTEN     (1<<0)         /* UART enabled */
 #define  UCR2_ESCI              (1<<15) /* Escape seq 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 */
-#ifdef CONFIG_ARCH_MX1
-#define  UCR3_REF25     (1<<3)  /* Ref freq 25 MHz, only on mx1 */
-#define  UCR3_REF30     (1<<2)  /* Ref Freq 30 MHz, only on mx1 */
-#endif
-#if defined CONFIG_ARCH_MX2 || defined CONFIG_ARCH_MX3
-#define  UCR3_RXDMUXSEL         (1<<2)  /* RXD Muxed Input Select, on mx2/mx3 */
-#endif
+#define  MX1_UCR3_REF25         (1<<3)  /* Ref freq 25 MHz, only on mx1 */
+#define  MX1_UCR3_REF30         (1<<2)  /* Ref Freq 30 MHz, only on mx1 */
+#define  MX2_UCR3_RXDMUXSEL     (1<<2)  /* RXD Muxed Input Select, on mx2/mx3 */
 #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_CTSTL_SHF  10      /* CTS trigger level shift */
+#define  UCR4_CTSTL_MASK 0x3F    /* CTS trigger is 6 bits wide */
 #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  UTS_SOFTRST    (1<<0)  /* Software reset */
 
 /* We've been assigned a range on the "Low-density serial ports" major */
-#ifdef CONFIG_ARCH_MXC
 #define SERIAL_IMX_MAJOR        207
 #define MINOR_START            16
 #define DEV_NAME               "ttymxc"
 #define MAX_INTERNAL_IRQ       MXC_INTERNAL_IRQS
-#endif
 
 /*
  * This determines how often we check the modem status signals
@@ -248,7 +226,7 @@ static void imx_mctrl_check(struct imx_port *sport)
        if (changed & TIOCM_CTS)
                uart_handle_cts_change(&sport->port, status & TIOCM_CTS);
 
-       wake_up_interruptible(&sport->port.info->delta_msr_wait);
+       wake_up_interruptible(&sport->port.state->port.delta_msr_wait);
 }
 
 /*
@@ -260,7 +238,7 @@ static void imx_timeout(unsigned long data)
        struct imx_port *sport = (struct imx_port *)data;
        unsigned long flags;
 
-       if (sport->port.info) {
+       if (sport->port.state) {
                spin_lock_irqsave(&sport->port.lock, flags);
                imx_mctrl_check(sport);
                spin_unlock_irqrestore(&sport->port.lock, flags);
@@ -347,7 +325,7 @@ static void imx_enable_ms(struct uart_port *port)
 
 static inline void imx_transmit_buffer(struct imx_port *sport)
 {
-       struct circ_buf *xmit = &sport->port.info->xmit;
+       struct circ_buf *xmit = &sport->port.state->xmit;
 
        while (!(readl(sport->port.membase + UTS) & UTS_TXFULL)) {
                /* send xmit->buf[xmit->tail]
@@ -412,7 +390,7 @@ static irqreturn_t imx_rtsint(int irq, void *dev_id)
 
        writel(USR1_RTSD, sport->port.membase + USR1);
        uart_handle_cts_change(&sport->port, !!val);
-       wake_up_interruptible(&sport->port.info->delta_msr_wait);
+       wake_up_interruptible(&sport->port.state->port.delta_msr_wait);
 
        spin_unlock_irqrestore(&sport->port.lock, flags);
        return IRQ_HANDLED;
@@ -421,7 +399,7 @@ static irqreturn_t imx_rtsint(int irq, void *dev_id)
 static irqreturn_t imx_txint(int irq, void *dev_id)
 {
        struct imx_port *sport = dev_id;
-       struct circ_buf *xmit = &sport->port.info->xmit;
+       struct circ_buf *xmit = &sport->port.state->xmit;
        unsigned long flags;
 
        spin_lock_irqsave(&sport->port.lock,flags);
@@ -451,7 +429,7 @@ 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->port.tty;
+       struct tty_struct *tty = sport->port.state->port.tty;
        unsigned long flags, temp;
 
        spin_lock_irqsave(&sport->port.lock,flags);
@@ -464,7 +442,7 @@ static irqreturn_t imx_rxint(int irq, void *dev_id)
 
                temp = readl(sport->port.membase + USR2);
                if (temp & USR2_BRCD) {
-                       writel(temp | USR2_BRCD, sport->port.membase + USR2);
+                       writel(USR2_BRCD, sport->port.membase + USR2);
                        if (uart_handle_break(&sport->port))
                                continue;
                }
@@ -614,6 +592,9 @@ static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode)
        return 0;
 }
 
+/* half the RX buffer size */
+#define CTSTL 16
+
 static int imx_startup(struct uart_port *port)
 {
        struct imx_port *sport = (struct imx_port *)port;
@@ -630,6 +611,10 @@ static int imx_startup(struct uart_port *port)
        if (USE_IRDA(sport))
                temp |= UCR4_IRSC;
 
+       /* set the trigger level for CTS */
+       temp &= ~(UCR4_CTSTL_MASK<<  UCR4_CTSTL_SHF);
+       temp |= CTSTL<<  UCR4_CTSTL_SHF;
+
        writel(temp & ~UCR4_DREN, sport->port.membase + UCR4);
 
        if (USE_IRDA(sport)) {
@@ -706,11 +691,11 @@ static int imx_startup(struct uart_port *port)
                }
        }
 
-#if defined CONFIG_ARCH_MX2 || defined CONFIG_ARCH_MX3
-       temp = readl(sport->port.membase + UCR3);
-       temp |= UCR3_RXDMUXSEL;
-       writel(temp, sport->port.membase + UCR3);
-#endif
+       if (!cpu_is_mx1()) {
+               temp = readl(sport->port.membase + UCR3);
+               temp |= MX2_UCR3_RXDMUXSEL;
+               writel(temp, sport->port.membase + UCR3);
+       }
 
        if (USE_IRDA(sport)) {
                temp = readl(sport->port.membase + UCR4);
@@ -924,11 +909,13 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
        rational_best_approximation(16 * div * baud, sport->port.uartclk,
                1 << 16, 1 << 16, &num, &denom);
 
-       tdiv64 = sport->port.uartclk;
-       tdiv64 *= num;
-       do_div(tdiv64, denom * 16 * div);
-       tty_encode_baud_rate(sport->port.info->port.tty,
-               (speed_t)tdiv64, (speed_t)tdiv64);
+       if (port->state && port->state->port.tty) {
+               tdiv64 = sport->port.uartclk;
+               tdiv64 *= num;
+               do_div(tdiv64, denom * 16 * div);
+               tty_encode_baud_rate(sport->port.state->port.tty,
+                               (speed_t)tdiv64, (speed_t)tdiv64);
+       }
 
        num -= 1;
        denom -= 1;
@@ -940,9 +927,9 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
        writel(num, sport->port.membase + UBIR);
        writel(denom, sport->port.membase + UBMR);
 
-#ifdef ONEMS
-       writel(sport->port.uartclk / div / 1000, sport->port.membase + ONEMS);
-#endif
+       if (!cpu_is_mx1())
+               writel(sport->port.uartclk / div / 1000,
+                               sport->port.membase + MX2_ONEMS);
 
        writel(old_ucr1, sport->port.membase + UCR1);
 
@@ -1072,17 +1059,20 @@ 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;
+       unsigned int old_ucr1, old_ucr2, ucr1;
 
        /*
         *      First, save UCR1/2 and then disable interrupts
         */
-       old_ucr1 = readl(sport->port.membase + UCR1);
+       ucr1 = old_ucr1 = readl(sport->port.membase + UCR1);
        old_ucr2 = readl(sport->port.membase + UCR2);
 
-       writel((old_ucr1 | UCR1_UARTCLKEN | UCR1_UARTEN) &
-               ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN),
-               sport->port.membase + UCR1);
+       if (cpu_is_mx1())
+               ucr1 |= MX1_UCR1_UARTCLKEN;
+       ucr1 |= UCR1_UARTEN;
+       ucr1 &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN);
+
+       writel(ucr1, sport->port.membase + UCR1);
 
        writel(old_ucr2 | UCR2_TXEN, sport->port.membase + UCR2);
 
@@ -1107,7 +1097,7 @@ imx_console_get_options(struct imx_port *sport, int *baud,
                           int *parity, int *bits)
 {
 
-       if ( readl(sport->port.membase + UCR1) | 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;
@@ -1298,7 +1288,7 @@ static int serial_imx_probe(struct platform_device *pdev)
                sport->use_irda = 1;
 #endif
 
-       if (pdata->init) {
+       if (pdata && pdata->init) {
                ret = pdata->init(pdev);
                if (ret)
                        goto clkput;
@@ -1311,7 +1301,7 @@ static int serial_imx_probe(struct platform_device *pdev)
 
        return 0;
 deinit:
-       if (pdata->exit)
+       if (pdata && pdata->exit)
                pdata->exit(pdev);
 clkput:
        clk_put(sport->clk);
@@ -1340,7 +1330,7 @@ static int serial_imx_remove(struct platform_device *pdev)
 
        clk_disable(sport->clk);
 
-       if (pdata->exit)
+       if (pdata && pdata->exit)
                pdata->exit(pdev);
 
        iounmap(sport->port.membase);