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.c43
1 files changed, 31 insertions, 12 deletions
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 57d6b29c039c..9915e4d1418c 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -232,24 +232,42 @@ static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool enable)
232} 232}
233 233
234/* 234/*
235 * serial_omap_baud_is_mode16 - check if baud rate is MODE16X
236 * @port: uart port info
237 * @baud: baudrate for which mode needs to be determined
238 *
239 * Returns true if baud rate is MODE16X and false if MODE13X
240 * Original table in OMAP TRM named "UART Mode Baud Rates, Divisor Values,
241 * and Error Rates" determines modes not for all common baud rates.
242 * E.g. for 1000000 baud rate mode must be 16x, but according to that
243 * table it's determined as 13x.
244 */
245static bool
246serial_omap_baud_is_mode16(struct uart_port *port, unsigned int baud)
247{
248 unsigned int n13 = port->uartclk / (13 * baud);
249 unsigned int n16 = port->uartclk / (16 * baud);
250 int baudAbsDiff13 = baud - (port->uartclk / (13 * n13));
251 int baudAbsDiff16 = baud - (port->uartclk / (16 * n16));
252 if(baudAbsDiff13 < 0)
253 baudAbsDiff13 = -baudAbsDiff13;
254 if(baudAbsDiff16 < 0)
255 baudAbsDiff16 = -baudAbsDiff16;
256
257 return (baudAbsDiff13 > baudAbsDiff16);
258}
259
260/*
235 * serial_omap_get_divisor - calculate divisor value 261 * serial_omap_get_divisor - calculate divisor value
236 * @port: uart port info 262 * @port: uart port info
237 * @baud: baudrate for which divisor needs to be calculated. 263 * @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 */ 264 */
247static unsigned int 265static unsigned int
248serial_omap_get_divisor(struct uart_port *port, unsigned int baud) 266serial_omap_get_divisor(struct uart_port *port, unsigned int baud)
249{ 267{
250 unsigned int divisor; 268 unsigned int divisor;
251 269
252 if (baud > OMAP_MODE13X_SPEED && baud != 3000000) 270 if (!serial_omap_baud_is_mode16(port, baud))
253 divisor = 13; 271 divisor = 13;
254 else 272 else
255 divisor = 16; 273 divisor = 16;
@@ -483,7 +501,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) 501static irqreturn_t serial_omap_irq(int irq, void *dev_id)
484{ 502{
485 struct uart_omap_port *up = dev_id; 503 struct uart_omap_port *up = dev_id;
486 struct tty_struct *tty = up->port.state->port.tty;
487 unsigned int iir, lsr; 504 unsigned int iir, lsr;
488 unsigned int type; 505 unsigned int type;
489 irqreturn_t ret = IRQ_NONE; 506 irqreturn_t ret = IRQ_NONE;
@@ -530,7 +547,7 @@ static irqreturn_t serial_omap_irq(int irq, void *dev_id)
530 547
531 spin_unlock(&up->port.lock); 548 spin_unlock(&up->port.lock);
532 549
533 tty_flip_buffer_push(tty); 550 tty_flip_buffer_push(&up->port.state->port);
534 551
535 pm_runtime_mark_last_busy(up->dev); 552 pm_runtime_mark_last_busy(up->dev);
536 pm_runtime_put_autosuspend(up->dev); 553 pm_runtime_put_autosuspend(up->dev);
@@ -776,6 +793,8 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
776 cval |= UART_LCR_PARITY; 793 cval |= UART_LCR_PARITY;
777 if (!(termios->c_cflag & PARODD)) 794 if (!(termios->c_cflag & PARODD))
778 cval |= UART_LCR_EPAR; 795 cval |= UART_LCR_EPAR;
796 if (termios->c_cflag & CMSPAR)
797 cval |= UART_LCR_SPAR;
779 798
780 /* 799 /*
781 * Ask the core to calculate the divisor for us. 800 * Ask the core to calculate the divisor for us.
@@ -915,7 +934,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
915 serial_out(up, UART_EFR, up->efr); 934 serial_out(up, UART_EFR, up->efr);
916 serial_out(up, UART_LCR, cval); 935 serial_out(up, UART_LCR, cval);
917 936
918 if (baud > 230400 && baud != 3000000) 937 if (!serial_omap_baud_is_mode16(port, baud))
919 up->mdr1 = UART_OMAP_MDR1_13X_MODE; 938 up->mdr1 = UART_OMAP_MDR1_13X_MODE;
920 else 939 else
921 up->mdr1 = UART_OMAP_MDR1_16X_MODE; 940 up->mdr1 = UART_OMAP_MDR1_16X_MODE;