]> err.no Git - linux-2.6/blobdiff - drivers/serial/imx.c
[SERIAL] Spelling fix in 8250.c
[linux-2.6] / drivers / serial / imx.c
index c682c6308cde1067d27ff6201341305e87f4ce6e..4c985e6b3784b0b611413c74deba61a98c086997 100644 (file)
@@ -124,7 +124,7 @@ 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;
@@ -165,13 +165,13 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
        } 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;
 
@@ -196,7 +196,7 @@ static irqreturn_t imx_txint(int irq, void *dev_id, struct pt_regs *regs)
        }
 
        if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
-               imx_stop_tx(&sport->port, 0);
+               imx_stop_tx(&sport->port);
                goto out;
        }
 
@@ -291,13 +291,31 @@ static unsigned int imx_tx_empty(struct uart_port *port)
        return USR2((u32)sport->port.membase) & 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 (USR1((u32)sport->port.membase) & USR1_RTSS)
+                tmp |= TIOCM_CTS;
+
+        if (UCR2((u32)sport->port.membase) & 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;
+
+        if (mctrl & TIOCM_RTS)
+                UCR2((u32)sport->port.membase) |= UCR2_CTS;
+        else
+                UCR2((u32)sport->port.membase) &= ~UCR2_CTS;
 }
 
 /*
@@ -321,18 +339,39 @@ static void imx_break_ctl(struct uart_port *port, int break_state)
 #define TXTL 2 /* reset default */
 #define RXTL 1 /* reset default */
 
+static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode)
+{
+       unsigned int val;
+       unsigned int ufcr_rfdiv;
+
+       /* set receiver / transmitter trigger level.
+        * RFDIV is set such way to satisfy requested uartclk value
+        */
+       val = TXTL<<10 | RXTL;
+       ufcr_rfdiv = (imx_get_perclk1() + sport->port.uartclk / 2) / sport->port.uartclk;
+
+       if(!ufcr_rfdiv)
+               ufcr_rfdiv = 1;
+
+       if(ufcr_rfdiv >= 7)
+               ufcr_rfdiv = 6;
+       else
+               ufcr_rfdiv = 6 - ufcr_rfdiv;
+
+       val |= UFCR_RFDIV & (ufcr_rfdiv << 7);
+
+       UFCR((u32)sport->port.membase) = val;
+
+       return 0;
+}
+
 static int imx_startup(struct uart_port *port)
 {
        struct imx_port *sport = (struct imx_port *)port;
        int retval;
-       unsigned int val;
        unsigned long flags;
 
-       /* set receiver / transmitter trigger level. We assume
-        * that RFDIV has been set by the arch setup or by the bootloader.
-        */
-       val = (UFCR((u32)sport->port.membase) & UFCR_RFDIV)  | TXTL<<10 | RXTL;
-       UFCR((u32)sport->port.membase) = val;
+       imx_setup_ufcr(sport, 0);
 
        /* disable the DREN bit (Data Ready interrupt enable) before
         * requesting IRQs
@@ -737,9 +776,12 @@ static void __init
 imx_console_get_options(struct imx_port *sport, int *baud,
                           int *parity, int *bits)
 {
+
        if ( UCR1((u32)sport->port.membase) | 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);
 
@@ -758,9 +800,35 @@ imx_console_get_options(struct imx_port *sport, int *baud,
 
                ubir = UBIR((u32)sport->port.membase) & 0xffff;
                ubmr = UBMR((u32)sport->port.membase) & 0xffff;
-               uartclk = sport->port.uartclk;
 
-               *baud = ((uartclk/16) * (ubir + 1)) / (ubmr + 1);
+
+               ucfr_rfdiv = (UFCR((u32)sport->port.membase) & UFCR_RFDIV) >> 7;
+               if (ucfr_rfdiv == 6)
+                       ucfr_rfdiv = 7;
+               else
+                       ucfr_rfdiv = 6 - ucfr_rfdiv;
+
+               uartclk = imx_get_perclk1();
+               uartclk /= ucfr_rfdiv;
+
+               {       /*
+                        * The next code provides exact computation of
+                        *   baud_raw = round(((uartclk/16) * (ubir + 1)) / (ubmr + 1))
+                        * without need of float support or long long division,
+                        * which would be required to prevent 32bit arithmetic overflow
+                        */
+                       unsigned int mul = ubir + 1;
+                       unsigned int div = 16 * (ubmr + 1);
+                       unsigned int rem = uartclk % div;
+
+                       baud_raw = (uartclk / div) * mul;
+                       baud_raw += (rem * mul + div / 2) / div;
+                       *baud = (baud_raw + 50) / 100 * 100;
+               }
+
+               if(*baud != baud_raw)
+                       printk(KERN_INFO "Serial: Console IMX rounded baud rate from %d to %d\n",
+                               baud_raw, *baud);
        }
 }
 
@@ -787,6 +855,8 @@ imx_console_setup(struct console *co, char *options)
        else
                imx_console_get_options(sport, &baud, &parity, &bits);
 
+       imx_setup_ufcr(sport, 0);
+
        return uart_set_options(&sport->port, co, baud, parity, bits, flow);
 }