serial: core: Consider rs485 settings to drive RTS
Previously the rs485 settings weren't considered when setting the RTS line, so e.g. closing and reopening a port made serial_core to drive the line as if rs485 was disabled. This patch fixes those issues. Signed-off-by: Rafael Gago Castano <rgc@hms.se> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
d77dc47fce
commit
a6845e1e1b
@ -165,6 +165,27 @@ uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear)
|
|||||||
#define uart_set_mctrl(port, set) uart_update_mctrl(port, set, 0)
|
#define uart_set_mctrl(port, set) uart_update_mctrl(port, set, 0)
|
||||||
#define uart_clear_mctrl(port, clear) uart_update_mctrl(port, 0, clear)
|
#define uart_clear_mctrl(port, clear) uart_update_mctrl(port, 0, clear)
|
||||||
|
|
||||||
|
static void uart_port_dtr_rts(struct uart_port *uport, int raise)
|
||||||
|
{
|
||||||
|
int rs485_on = uport->rs485_config &&
|
||||||
|
(uport->rs485.flags & SER_RS485_ENABLED);
|
||||||
|
int RTS_after_send = !!(uport->rs485.flags & SER_RS485_RTS_AFTER_SEND);
|
||||||
|
|
||||||
|
if (raise) {
|
||||||
|
if (rs485_on && !RTS_after_send) {
|
||||||
|
uart_set_mctrl(uport, TIOCM_DTR);
|
||||||
|
uart_clear_mctrl(uport, TIOCM_RTS);
|
||||||
|
} else {
|
||||||
|
uart_set_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unsigned int clear = TIOCM_DTR;
|
||||||
|
|
||||||
|
clear |= (!rs485_on || !RTS_after_send) ? TIOCM_RTS : 0;
|
||||||
|
uart_clear_mctrl(uport, clear);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Startup the port. This will be called once per open. All calls
|
* Startup the port. This will be called once per open. All calls
|
||||||
* will be serialised by the per-port mutex.
|
* will be serialised by the per-port mutex.
|
||||||
@ -214,7 +235,7 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state,
|
|||||||
* port is open and ready to respond.
|
* port is open and ready to respond.
|
||||||
*/
|
*/
|
||||||
if (init_hw && C_BAUD(tty))
|
if (init_hw && C_BAUD(tty))
|
||||||
uart_set_mctrl(uport, TIOCM_RTS | TIOCM_DTR);
|
uart_port_dtr_rts(uport, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -272,7 +293,7 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
|
|||||||
uport->cons->cflag = tty->termios.c_cflag;
|
uport->cons->cflag = tty->termios.c_cflag;
|
||||||
|
|
||||||
if (!tty || C_HUPCL(tty))
|
if (!tty || C_HUPCL(tty))
|
||||||
uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
|
uart_port_dtr_rts(uport, 0);
|
||||||
|
|
||||||
uart_port_shutdown(port);
|
uart_port_shutdown(port);
|
||||||
}
|
}
|
||||||
@ -1658,7 +1679,7 @@ static int uart_carrier_raised(struct tty_port *port)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void uart_dtr_rts(struct tty_port *port, int onoff)
|
static void uart_dtr_rts(struct tty_port *port, int raise)
|
||||||
{
|
{
|
||||||
struct uart_state *state = container_of(port, struct uart_state, port);
|
struct uart_state *state = container_of(port, struct uart_state, port);
|
||||||
struct uart_port *uport;
|
struct uart_port *uport;
|
||||||
@ -1666,12 +1687,7 @@ static void uart_dtr_rts(struct tty_port *port, int onoff)
|
|||||||
uport = uart_port_ref(state);
|
uport = uart_port_ref(state);
|
||||||
if (!uport)
|
if (!uport)
|
||||||
return;
|
return;
|
||||||
|
uart_port_dtr_rts(uport, raise);
|
||||||
if (onoff)
|
|
||||||
uart_set_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
|
|
||||||
else
|
|
||||||
uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
|
|
||||||
|
|
||||||
uart_port_deref(uport);
|
uart_port_deref(uport);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user