diff options
-rw-r--r-- | drivers/tty/serial/omap-serial.c | 50 |
1 files changed, 38 insertions, 12 deletions
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index b69393f2817d..e42eb1e5a21a 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c | |||
@@ -298,21 +298,22 @@ static void serial_omap_enable_ms(struct uart_port *port) | |||
298 | static void serial_omap_stop_tx(struct uart_port *port) | 298 | static void serial_omap_stop_tx(struct uart_port *port) |
299 | { | 299 | { |
300 | struct uart_omap_port *up = to_uart_omap_port(port); | 300 | struct uart_omap_port *up = to_uart_omap_port(port); |
301 | struct circ_buf *xmit = &up->port.state->xmit; | ||
302 | int res; | 301 | int res; |
303 | 302 | ||
304 | pm_runtime_get_sync(up->dev); | 303 | pm_runtime_get_sync(up->dev); |
305 | 304 | ||
306 | /* handle rs485 */ | 305 | /* Handle RS-485 */ |
307 | if (up->rs485.flags & SER_RS485_ENABLED) { | 306 | if (up->rs485.flags & SER_RS485_ENABLED) { |
308 | /* do nothing if current tx not yet completed */ | 307 | if (up->scr & OMAP_UART_SCR_TX_EMPTY) { |
309 | res = serial_in(up, UART_LSR) & UART_LSR_TEMT; | 308 | /* THR interrupt is fired when both TX FIFO and TX |
310 | if (!res) | 309 | * shift register are empty. This means there's nothing |
311 | return; | 310 | * left to transmit now, so make sure the THR interrupt |
312 | 311 | * is fired when TX FIFO is below the trigger level, | |
313 | /* if there's no more data to send, turn off rts */ | 312 | * disable THR interrupts and toggle the RS-485 GPIO |
314 | if (uart_circ_empty(xmit)) { | 313 | * data direction pin if needed. |
315 | /* if rts not already disabled */ | 314 | */ |
315 | up->scr &= ~OMAP_UART_SCR_TX_EMPTY; | ||
316 | serial_out(up, UART_OMAP_SCR, up->scr); | ||
316 | res = (up->rs485.flags & SER_RS485_RTS_AFTER_SEND) ? 1 : 0; | 317 | res = (up->rs485.flags & SER_RS485_RTS_AFTER_SEND) ? 1 : 0; |
317 | if (gpio_get_value(up->rts_gpio) != res) { | 318 | if (gpio_get_value(up->rts_gpio) != res) { |
318 | if (up->rs485.delay_rts_after_send > 0) { | 319 | if (up->rs485.delay_rts_after_send > 0) { |
@@ -320,6 +321,18 @@ static void serial_omap_stop_tx(struct uart_port *port) | |||
320 | } | 321 | } |
321 | gpio_set_value(up->rts_gpio, res); | 322 | gpio_set_value(up->rts_gpio, res); |
322 | } | 323 | } |
324 | } else { | ||
325 | /* We're asked to stop, but there's still stuff in the | ||
326 | * UART FIFO, so make sure the THR interrupt is fired | ||
327 | * when both TX FIFO and TX shift register are empty. | ||
328 | * The next THR interrupt (if no transmission is started | ||
329 | * in the meantime) will indicate the end of a | ||
330 | * transmission. Therefore we _don't_ disable THR | ||
331 | * interrupts in this situation. | ||
332 | */ | ||
333 | up->scr |= OMAP_UART_SCR_TX_EMPTY; | ||
334 | serial_out(up, UART_OMAP_SCR, up->scr); | ||
335 | return; | ||
323 | } | 336 | } |
324 | } | 337 | } |
325 | 338 | ||
@@ -399,8 +412,12 @@ static void serial_omap_start_tx(struct uart_port *port) | |||
399 | 412 | ||
400 | pm_runtime_get_sync(up->dev); | 413 | pm_runtime_get_sync(up->dev); |
401 | 414 | ||
402 | /* handle rs485 */ | 415 | /* Handle RS-485 */ |
403 | if (up->rs485.flags & SER_RS485_ENABLED) { | 416 | if (up->rs485.flags & SER_RS485_ENABLED) { |
417 | /* Fire THR interrupts when FIFO is below trigger level */ | ||
418 | up->scr &= ~OMAP_UART_SCR_TX_EMPTY; | ||
419 | serial_out(up, UART_OMAP_SCR, up->scr); | ||
420 | |||
404 | /* if rts not already enabled */ | 421 | /* if rts not already enabled */ |
405 | res = (up->rs485.flags & SER_RS485_RTS_ON_SEND) ? 1 : 0; | 422 | res = (up->rs485.flags & SER_RS485_RTS_ON_SEND) ? 1 : 0; |
406 | if (gpio_get_value(up->rts_gpio) != res) { | 423 | if (gpio_get_value(up->rts_gpio) != res) { |
@@ -969,7 +986,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, | |||
969 | */ | 986 | */ |
970 | 987 | ||
971 | /* Set receive FIFO threshold to 16 characters and | 988 | /* Set receive FIFO threshold to 16 characters and |
972 | * transmit FIFO threshold to 16 spaces | 989 | * transmit FIFO threshold to 32 spaces |
973 | */ | 990 | */ |
974 | up->fcr &= ~OMAP_UART_FCR_RX_FIFO_TRIG_MASK; | 991 | up->fcr &= ~OMAP_UART_FCR_RX_FIFO_TRIG_MASK; |
975 | up->fcr &= ~OMAP_UART_FCR_TX_FIFO_TRIG_MASK; | 992 | up->fcr &= ~OMAP_UART_FCR_TX_FIFO_TRIG_MASK; |
@@ -1375,6 +1392,15 @@ serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf) | |||
1375 | up->ier = mode; | 1392 | up->ier = mode; |
1376 | serial_out(up, UART_IER, up->ier); | 1393 | serial_out(up, UART_IER, up->ier); |
1377 | 1394 | ||
1395 | /* If RS-485 is disabled, make sure the THR interrupt is fired when | ||
1396 | * TX FIFO is below the trigger level. | ||
1397 | */ | ||
1398 | if (!(up->rs485.flags & SER_RS485_ENABLED) && | ||
1399 | (up->scr & OMAP_UART_SCR_TX_EMPTY)) { | ||
1400 | up->scr &= ~OMAP_UART_SCR_TX_EMPTY; | ||
1401 | serial_out(up, UART_OMAP_SCR, up->scr); | ||
1402 | } | ||
1403 | |||
1378 | spin_unlock_irqrestore(&up->port.lock, flags); | 1404 | spin_unlock_irqrestore(&up->port.lock, flags); |
1379 | pm_runtime_mark_last_busy(up->dev); | 1405 | pm_runtime_mark_last_busy(up->dev); |
1380 | pm_runtime_put_autosuspend(up->dev); | 1406 | pm_runtime_put_autosuspend(up->dev); |