mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-15 09:46:46 +07:00
serial: omap: Fix RTS handling
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 <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
9719acce37
commit
348f9bb31c
@ -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)
|
static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||||
{
|
{
|
||||||
struct uart_omap_port *up = to_uart_omap_port(port);
|
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);
|
dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->port.line);
|
||||||
if (mctrl & TIOCM_RTS)
|
if (mctrl & TIOCM_RTS)
|
||||||
@ -701,6 +701,17 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
|||||||
UART_MCR_DTR | UART_MCR_RTS);
|
UART_MCR_DTR | UART_MCR_RTS);
|
||||||
up->mcr = old_mcr | mcr;
|
up->mcr = old_mcr | mcr;
|
||||||
serial_out(up, UART_MCR, up->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_mark_last_busy(up->dev);
|
||||||
pm_runtime_put_autosuspend(up->dev);
|
pm_runtime_put_autosuspend(up->dev);
|
||||||
}
|
}
|
||||||
@ -756,8 +767,6 @@ static int serial_omap_startup(struct uart_port *port)
|
|||||||
* (they will be reenabled in set_termios())
|
* (they will be reenabled in set_termios())
|
||||||
*/
|
*/
|
||||||
serial_omap_clear_fifos(up);
|
serial_omap_clear_fifos(up);
|
||||||
/* For Hardware flow control */
|
|
||||||
serial_out(up, UART_MCR, UART_MCR_RTS);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clear the interrupt registers.
|
* Clear the interrupt registers.
|
||||||
@ -1056,12 +1065,9 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
|
|||||||
up->port.status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS | UPSTAT_AUTOXOFF);
|
up->port.status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS | UPSTAT_AUTOXOFF);
|
||||||
|
|
||||||
if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW) {
|
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->port.status |= UPSTAT_AUTOCTS | UPSTAT_AUTORTS;
|
||||||
up->efr |= UART_EFR_CTS | UART_EFR_RTS;
|
up->efr |= UART_EFR_CTS;
|
||||||
|
|
||||||
/* Ensure MCR RTS is asserted */
|
|
||||||
up->mcr |= UART_MCR_RTS;
|
|
||||||
} else {
|
} else {
|
||||||
/* Disable AUTORTS and AUTOCTS */
|
/* Disable AUTORTS and AUTOCTS */
|
||||||
up->efr &= ~(UART_EFR_CTS | UART_EFR_RTS);
|
up->efr &= ~(UART_EFR_CTS | UART_EFR_RTS);
|
||||||
|
Loading…
Reference in New Issue
Block a user