diff options
Diffstat (limited to 'drivers/tty/serial/omap-serial.c')
-rw-r--r-- | drivers/tty/serial/omap-serial.c | 43 |
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 | */ | ||
245 | static bool | ||
246 | serial_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 | */ |
247 | static unsigned int | 265 | static unsigned int |
248 | serial_omap_get_divisor(struct uart_port *port, unsigned int baud) | 266 | serial_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) | |||
483 | static irqreturn_t serial_omap_irq(int irq, void *dev_id) | 501 | static 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; |