Skip to content

Commit

Permalink
serial: omap: Fix RTS handling
Browse files Browse the repository at this point in the history
The OMAP UART ignores MCR[1] (ie., RTS) when in autoRTS mode. This
makes it impossible for either the serial core or userspace to
manually flow control the sender.

Disable autoRTS mode when RTS is lowered and restore the previous
mode when RTS is raised.

Signed-off-by: Peter Hurley <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
  • Loading branch information
peterhurley authored and gregkh committed Feb 2, 2015
1 parent 9719acc commit 348f9bb
Showing 1 changed file with 14 additions and 8 deletions.
22 changes: 14 additions & 8 deletions drivers/tty/serial/omap-serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,7 @@ static unsigned int serial_omap_get_mctrl(struct uart_port *port)
static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
struct uart_omap_port *up = to_uart_omap_port(port);
unsigned char mcr = 0, old_mcr;
unsigned char mcr = 0, old_mcr, lcr;

dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->port.line);
if (mctrl & TIOCM_RTS)
Expand All @@ -701,6 +701,17 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
UART_MCR_DTR | UART_MCR_RTS);
up->mcr = old_mcr | mcr;
serial_out(up, UART_MCR, up->mcr);

/* Turn off autoRTS if RTS is lowered; restore autoRTS if RTS raised */
lcr = serial_in(up, UART_LCR);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
if ((mctrl & TIOCM_RTS) && (port->status & UPSTAT_AUTORTS))
up->efr |= UART_EFR_RTS;
else
up->efr &= UART_EFR_RTS;
serial_out(up, UART_EFR, up->efr);
serial_out(up, UART_LCR, lcr);

pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
}
Expand Down Expand Up @@ -756,8 +767,6 @@ static int serial_omap_startup(struct uart_port *port)
* (they will be reenabled in set_termios())
*/
serial_omap_clear_fifos(up);
/* For Hardware flow control */
serial_out(up, UART_MCR, UART_MCR_RTS);

/*
* Clear the interrupt registers.
Expand Down Expand Up @@ -1056,12 +1065,9 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
up->port.status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS | UPSTAT_AUTOXOFF);

if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW) {
/* Enable AUTORTS and AUTOCTS */
/* Enable AUTOCTS (autoRTS is enabled when RTS is raised) */
up->port.status |= UPSTAT_AUTOCTS | UPSTAT_AUTORTS;
up->efr |= UART_EFR_CTS | UART_EFR_RTS;

/* Ensure MCR RTS is asserted */
up->mcr |= UART_MCR_RTS;
up->efr |= UART_EFR_CTS;
} else {
/* Disable AUTORTS and AUTOCTS */
up->efr &= ~(UART_EFR_CTS | UART_EFR_RTS);
Expand Down

0 comments on commit 348f9bb

Please sign in to comment.