]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - android-sdk/kernel-video.git/blobdiff - drivers/tty/serial/omap-serial.c
Merge branch 'platform-base-3.8.y' of git://git.ti.com/~rrnayak/ti-linux-kernel/platf...
[android-sdk/kernel-video.git] / drivers / tty / serial / omap-serial.c
index 004e4027141eb20d3365af6201a5e41f5fcf2d25..352fcef5e8dda71fd7bc984302824f369f5dc370 100644 (file)
@@ -59,6 +59,7 @@
 
 /* SCR register bitmasks */
 #define OMAP_UART_SCR_RX_TRIG_GRANU1_MASK              (1 << 7)
+#define OMAP_UART_SCR_TX_TRIG_GRANU1_MASK              (1 << 6)
 #define OMAP_UART_SCR_TX_EMPTY                 (1 << 3)
 
 /* FCR register bitmasks */
@@ -212,25 +213,43 @@ static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool enable)
        pdata->enable_wakeup(up->dev, enable);
 }
 
+/*
+ * serial_omap_baud_is_mode16 - check if baud rate is MODE16X
+ * @port: uart port info
+ * @baud: baudrate for which mode needs to be determined
+ *
+ * Returns true if baud rate is MODE16X and false if MODE13X
+ * Original table in OMAP TRM named "UART Mode Baud Rates, Divisor Values,
+ * and Error Rates" determines modes not for all common baud rates.
+ * E.g. for 1000000 baud rate mode must be 16x, but according to that
+ * table it's determined as 13x.
+ */
+static bool
+serial_omap_baud_is_mode16(struct uart_port *port, unsigned int baud)
+{
+       unsigned int n13 = port->uartclk / (13 * baud);
+       unsigned int n16 = port->uartclk / (16 * baud);
+       int baudAbsDiff13 = baud - (port->uartclk / (13 * n13));
+       int baudAbsDiff16 = baud - (port->uartclk / (16 * n16));
+       if(baudAbsDiff13 < 0)
+               baudAbsDiff13 = -baudAbsDiff13;
+       if(baudAbsDiff16 < 0)
+               baudAbsDiff16 = -baudAbsDiff16;
+
+       return (baudAbsDiff13 > baudAbsDiff16);
+}
+
 /*
  * serial_omap_get_divisor - calculate divisor value
  * @port: uart port info
  * @baud: baudrate for which divisor needs to be calculated.
- *
- * We have written our own function to get the divisor so as to support
- * 13x mode. 3Mbps Baudrate as an different divisor.
- * Reference OMAP TRM Chapter 17:
- * Table 17-1. UART Mode Baud Rates, Divisor Values, and Error Rates
- * referring to oversampling - divisor value
- * baudrate 460,800 to 3,686,400 all have divisor 13
- * except 3,000,000 which has divisor value 16
  */
 static unsigned int
 serial_omap_get_divisor(struct uart_port *port, unsigned int baud)
 {
        unsigned int divisor;
 
-       if (baud > OMAP_MODE13X_SPEED && baud != 3000000)
+       if (!serial_omap_baud_is_mode16(port, baud))
                divisor = 13;
        else
                divisor = 16;
@@ -281,9 +300,6 @@ static void transmit_chars(struct uart_omap_port *up, unsigned int lsr)
        struct circ_buf *xmit = &up->port.state->xmit;
        int count;
 
-       if (!(lsr & UART_LSR_THRE))
-               return;
-
        if (up->port.x_char) {
                serial_out(up, UART_TX, up->port.x_char);
                up->port.icount.tx++;
@@ -754,6 +770,8 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
                cval |= UART_LCR_PARITY;
        if (!(termios->c_cflag & PARODD))
                cval |= UART_LCR_EPAR;
+       if (termios->c_cflag & CMSPAR)
+               cval |= UART_LCR_SPAR;
 
        /*
         * Ask the core to calculate the divisor for us.
@@ -823,7 +841,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
        serial_out(up, UART_IER, up->ier);
        serial_out(up, UART_LCR, cval);         /* reset DLAB */
        up->lcr = cval;
-       up->scr = OMAP_UART_SCR_TX_EMPTY;
+       up->scr = 0;
 
        /* FIFOs and DMA Settings */
 
@@ -848,6 +866,15 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
        /* FIFO ENABLE, DMA MODE */
 
        up->scr |= OMAP_UART_SCR_RX_TRIG_GRANU1_MASK;
+       /*
+        * NOTE: Setting OMAP_UART_SCR_RX_TRIG_GRANU1_MASK
+        * sets Enables the granularity of 1 for TRIGGER RX
+        * level. Along with setting RX FIFO trigger level
+        * to 1 (as noted below, 16 characters) and TLR[3:0]
+        * to zero this will result RX FIFO threshold level
+        * to 1 character, instead of 16 as noted in comment
+        * below.
+        */
 
        /* Set receive FIFO threshold to 16 characters and
         * transmit FIFO threshold to 16 spaces
@@ -893,7 +920,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
        serial_out(up, UART_EFR, up->efr);
        serial_out(up, UART_LCR, cval);
 
-       if (baud > 230400 && baud != 3000000)
+       if (!serial_omap_baud_is_mode16(port, baud))
                up->mdr1 = UART_OMAP_MDR1_13X_MODE;
        else
                up->mdr1 = UART_OMAP_MDR1_16X_MODE;