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