Skip to content

Commit 2dd8a74

Browse files
l1kgregkh
authored andcommitted
serial: core: Initialize rs485 RTS polarity already on probe
RTS polarity of rs485-enabled ports is currently initialized on uart open via: tty_port_open() tty_port_block_til_ready() tty_port_raise_dtr_rts() # if (C_BAUD(tty)) uart_dtr_rts() uart_port_dtr_rts() There's at least three problems here: First, if no baud rate is set, RTS polarity is not initialized. That's the right thing to do for rs232, but not for rs485, which requires that RTS is deasserted unconditionally. Second, if the DeviceTree property "linux,rs485-enabled-at-boot-time" is present, RTS should be deasserted as early as possible, i.e. on probe. Otherwise it may remain asserted until first open. Third, even though RTS is deasserted on open and close, it may subsequently be asserted by uart_throttle(), uart_unthrottle() or uart_set_termios() because those functions aren't rs485-aware. (Only uart_tiocmset() is.) To address these issues, move RTS initialization from uart_port_dtr_rts() to uart_configure_port(). Prevent subsequent modification of RTS polarity by moving the existing rs485 check from uart_tiocmget() to uart_update_mctrl(). That way, RTS is initialized on probe and then remains unmodified unless the uart transmits data. If rs485 is enabled at runtime (instead of at boot) through a TIOCSRS485 ioctl(), RTS is initialized by the uart driver's ->rs485_config() callback and then likewise remains unmodified. The PL011 driver initializes RTS on uart open and prevents subsequent modification in its ->set_mctrl() callback. That code is obsoleted by the present commit, so drop it. Cc: Jan Kiszka <[email protected]> Cc: Su Bao Cheng <[email protected]> Signed-off-by: Lukas Wunner <[email protected]> Link: https://lore.kernel.org/r/2d2acaf3a69e89b7bf687c912022b11fd29dfa1e.1642909284.git.lukas@wunner.de Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 62f676f commit 2dd8a74

File tree

2 files changed

+13
-36
lines changed

2 files changed

+13
-36
lines changed

drivers/tty/serial/amba-pl011.c

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1582,13 +1582,6 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl)
15821582
container_of(port, struct uart_amba_port, port);
15831583
unsigned int cr;
15841584

1585-
if (port->rs485.flags & SER_RS485_ENABLED) {
1586-
if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
1587-
mctrl &= ~TIOCM_RTS;
1588-
else
1589-
mctrl |= TIOCM_RTS;
1590-
}
1591-
15921585
cr = pl011_read(uap, REG_CR);
15931586

15941587
#define TIOCMBIT(tiocmbit, uartbit) \
@@ -1812,14 +1805,8 @@ static int pl011_startup(struct uart_port *port)
18121805
cr &= UART011_CR_RTS | UART011_CR_DTR;
18131806
cr |= UART01x_CR_UARTEN | UART011_CR_RXE;
18141807

1815-
if (port->rs485.flags & SER_RS485_ENABLED) {
1816-
if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
1817-
cr &= ~UART011_CR_RTS;
1818-
else
1819-
cr |= UART011_CR_RTS;
1820-
} else {
1808+
if (!(port->rs485.flags & SER_RS485_ENABLED))
18211809
cr |= UART011_CR_TXE;
1822-
}
18231810

18241811
pl011_write(cr, uap, REG_CR);
18251812

drivers/tty/serial/serial_core.c

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,11 @@ uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear)
144144
unsigned long flags;
145145
unsigned int old;
146146

147+
if (port->rs485.flags & SER_RS485_ENABLED) {
148+
set &= ~TIOCM_RTS;
149+
clear &= ~TIOCM_RTS;
150+
}
151+
147152
spin_lock_irqsave(&port->lock, flags);
148153
old = port->mctrl;
149154
port->mctrl = (old & ~clear) | set;
@@ -157,23 +162,10 @@ uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear)
157162

158163
static void uart_port_dtr_rts(struct uart_port *uport, int raise)
159164
{
160-
int rs485_on = uport->rs485_config &&
161-
(uport->rs485.flags & SER_RS485_ENABLED);
162-
int RTS_after_send = !!(uport->rs485.flags & SER_RS485_RTS_AFTER_SEND);
163-
164-
if (raise) {
165-
if (rs485_on && RTS_after_send) {
166-
uart_set_mctrl(uport, TIOCM_DTR);
167-
uart_clear_mctrl(uport, TIOCM_RTS);
168-
} else {
169-
uart_set_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
170-
}
171-
} else {
172-
unsigned int clear = TIOCM_DTR;
173-
174-
clear |= (!rs485_on || RTS_after_send) ? TIOCM_RTS : 0;
175-
uart_clear_mctrl(uport, clear);
176-
}
165+
if (raise)
166+
uart_set_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
167+
else
168+
uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
177169
}
178170

179171
/*
@@ -1075,11 +1067,6 @@ uart_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear)
10751067
goto out;
10761068

10771069
if (!tty_io_error(tty)) {
1078-
if (uport->rs485.flags & SER_RS485_ENABLED) {
1079-
set &= ~TIOCM_RTS;
1080-
clear &= ~TIOCM_RTS;
1081-
}
1082-
10831070
uart_update_mctrl(uport, set, clear);
10841071
ret = 0;
10851072
}
@@ -2390,6 +2377,9 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
23902377
*/
23912378
spin_lock_irqsave(&port->lock, flags);
23922379
port->mctrl &= TIOCM_DTR;
2380+
if (port->rs485.flags & SER_RS485_ENABLED &&
2381+
!(port->rs485.flags & SER_RS485_RTS_AFTER_SEND))
2382+
port->mctrl |= TIOCM_RTS;
23932383
port->ops->set_mctrl(port, port->mctrl);
23942384
spin_unlock_irqrestore(&port->lock, flags);
23952385

0 commit comments

Comments
 (0)