aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty
diff options
context:
space:
mode:
authorPhilippe Proulx <philippe.proulx@savoirfairelinux.com>2013-10-23 18:49:58 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-10-29 19:34:11 -0400
commit018e7448f2b2beba4a58f4c7fe99a5b32542be4c (patch)
tree0f0304d2b98ba78cdad56dde29dbb972eda76c30 /drivers/tty
parent68357c7d3f0a5930b48dcbe6d10e5324fdbd8c7a (diff)
serial: omap: improve RS-485 performance
If RS-485 is enabled, make the OMAP UART fire THR interrupts when both TX FIFO and TX shift register are empty instead of polling the equivalent status bit. This removes the burst of interrupt requests seen at every end of transmission. Also: the comment said that the TX FIFO trigger level was set at 16 characters when it's 32 in reality. Signed-off-by: Philippe Proulx <philippe.proulx@savoirfairelinux.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty')
-rw-r--r--drivers/tty/serial/omap-serial.c50
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)
298static void serial_omap_stop_tx(struct uart_port *port) 298static 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);