aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/omap-serial.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/omap-serial.c')
-rw-r--r--drivers/tty/serial/omap-serial.c51
1 files changed, 33 insertions, 18 deletions
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 57d6b29c039c..4dc41408ecb7 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -59,6 +59,7 @@
59 59
60/* SCR register bitmasks */ 60/* SCR register bitmasks */
61#define OMAP_UART_SCR_RX_TRIG_GRANU1_MASK (1 << 7) 61#define OMAP_UART_SCR_RX_TRIG_GRANU1_MASK (1 << 7)
62#define OMAP_UART_SCR_TX_TRIG_GRANU1_MASK (1 << 6)
62#define OMAP_UART_SCR_TX_EMPTY (1 << 3) 63#define OMAP_UART_SCR_TX_EMPTY (1 << 3)
63 64
64/* FCR register bitmasks */ 65/* FCR register bitmasks */
@@ -232,24 +233,42 @@ static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool enable)
232} 233}
233 234
234/* 235/*
236 * serial_omap_baud_is_mode16 - check if baud rate is MODE16X
237 * @port: uart port info
238 * @baud: baudrate for which mode needs to be determined
239 *
240 * Returns true if baud rate is MODE16X and false if MODE13X
241 * Original table in OMAP TRM named "UART Mode Baud Rates, Divisor Values,
242 * and Error Rates" determines modes not for all common baud rates.
243 * E.g. for 1000000 baud rate mode must be 16x, but according to that
244 * table it's determined as 13x.
245 */
246static bool
247serial_omap_baud_is_mode16(struct uart_port *port, unsigned int baud)
248{
249 unsigned int n13 = port->uartclk / (13 * baud);
250 unsigned int n16 = port->uartclk / (16 * baud);
251 int baudAbsDiff13 = baud - (port->uartclk / (13 * n13));
252 int baudAbsDiff16 = baud - (port->uartclk / (16 * n16));
253 if(baudAbsDiff13 < 0)
254 baudAbsDiff13 = -baudAbsDiff13;
255 if(baudAbsDiff16 < 0)
256 baudAbsDiff16 = -baudAbsDiff16;
257
258 return (baudAbsDiff13 > baudAbsDiff16);
259}
260
261/*
235 * serial_omap_get_divisor - calculate divisor value 262 * serial_omap_get_divisor - calculate divisor value
236 * @port: uart port info 263 * @port: uart port info
237 * @baud: baudrate for which divisor needs to be calculated. 264 * @baud: baudrate for which divisor needs to be calculated.
238 *
239 * We have written our own function to get the divisor so as to support
240 * 13x mode. 3Mbps Baudrate as an different divisor.
241 * Reference OMAP TRM Chapter 17:
242 * Table 17-1. UART Mode Baud Rates, Divisor Values, and Error Rates
243 * referring to oversampling - divisor value
244 * baudrate 460,800 to 3,686,400 all have divisor 13
245 * except 3,000,000 which has divisor value 16
246 */ 265 */
247static unsigned int 266static unsigned int
248serial_omap_get_divisor(struct uart_port *port, unsigned int baud) 267serial_omap_get_divisor(struct uart_port *port, unsigned int baud)
249{ 268{
250 unsigned int divisor; 269 unsigned int divisor;
251 270
252 if (baud > OMAP_MODE13X_SPEED && baud != 3000000) 271 if (!serial_omap_baud_is_mode16(port, baud))
253 divisor = 13; 272 divisor = 13;
254 else 273 else
255 divisor = 16; 274 divisor = 16;
@@ -302,9 +321,6 @@ static void transmit_chars(struct uart_omap_port *up, unsigned int lsr)
302 struct circ_buf *xmit = &up->port.state->xmit; 321 struct circ_buf *xmit = &up->port.state->xmit;
303 int count; 322 int count;
304 323
305 if (!(lsr & UART_LSR_THRE))
306 return;
307
308 if (up->port.x_char) { 324 if (up->port.x_char) {
309 serial_out(up, UART_TX, up->port.x_char); 325 serial_out(up, UART_TX, up->port.x_char);
310 up->port.icount.tx++; 326 up->port.icount.tx++;
@@ -483,7 +499,6 @@ static void serial_omap_rdi(struct uart_omap_port *up, unsigned int lsr)
483static irqreturn_t serial_omap_irq(int irq, void *dev_id) 499static irqreturn_t serial_omap_irq(int irq, void *dev_id)
484{ 500{
485 struct uart_omap_port *up = dev_id; 501 struct uart_omap_port *up = dev_id;
486 struct tty_struct *tty = up->port.state->port.tty;
487 unsigned int iir, lsr; 502 unsigned int iir, lsr;
488 unsigned int type; 503 unsigned int type;
489 irqreturn_t ret = IRQ_NONE; 504 irqreturn_t ret = IRQ_NONE;
@@ -530,7 +545,7 @@ static irqreturn_t serial_omap_irq(int irq, void *dev_id)
530 545
531 spin_unlock(&up->port.lock); 546 spin_unlock(&up->port.lock);
532 547
533 tty_flip_buffer_push(tty); 548 tty_flip_buffer_push(&up->port.state->port);
534 549
535 pm_runtime_mark_last_busy(up->dev); 550 pm_runtime_mark_last_busy(up->dev);
536 pm_runtime_put_autosuspend(up->dev); 551 pm_runtime_put_autosuspend(up->dev);
@@ -776,6 +791,8 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
776 cval |= UART_LCR_PARITY; 791 cval |= UART_LCR_PARITY;
777 if (!(termios->c_cflag & PARODD)) 792 if (!(termios->c_cflag & PARODD))
778 cval |= UART_LCR_EPAR; 793 cval |= UART_LCR_EPAR;
794 if (termios->c_cflag & CMSPAR)
795 cval |= UART_LCR_SPAR;
779 796
780 /* 797 /*
781 * Ask the core to calculate the divisor for us. 798 * Ask the core to calculate the divisor for us.
@@ -845,7 +862,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
845 serial_out(up, UART_IER, up->ier); 862 serial_out(up, UART_IER, up->ier);
846 serial_out(up, UART_LCR, cval); /* reset DLAB */ 863 serial_out(up, UART_LCR, cval); /* reset DLAB */
847 up->lcr = cval; 864 up->lcr = cval;
848 up->scr = OMAP_UART_SCR_TX_EMPTY; 865 up->scr = 0;
849 866
850 /* FIFOs and DMA Settings */ 867 /* FIFOs and DMA Settings */
851 868
@@ -869,8 +886,6 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
869 serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR); 886 serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
870 /* FIFO ENABLE, DMA MODE */ 887 /* FIFO ENABLE, DMA MODE */
871 888
872 up->scr |= OMAP_UART_SCR_RX_TRIG_GRANU1_MASK;
873
874 /* Set receive FIFO threshold to 16 characters and 889 /* Set receive FIFO threshold to 16 characters and
875 * transmit FIFO threshold to 16 spaces 890 * transmit FIFO threshold to 16 spaces
876 */ 891 */
@@ -915,7 +930,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
915 serial_out(up, UART_EFR, up->efr); 930 serial_out(up, UART_EFR, up->efr);
916 serial_out(up, UART_LCR, cval); 931 serial_out(up, UART_LCR, cval);
917 932
918 if (baud > 230400 && baud != 3000000) 933 if (!serial_omap_baud_is_mode16(port, baud))
919 up->mdr1 = UART_OMAP_MDR1_13X_MODE; 934 up->mdr1 = UART_OMAP_MDR1_13X_MODE;
920 else 935 else
921 up->mdr1 = UART_OMAP_MDR1_16X_MODE; 936 up->mdr1 = UART_OMAP_MDR1_16X_MODE;