diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index c57d6dde7fe3..86400092a901 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -300,6 +300,7 @@ struct max310x_one { struct work_struct md_work; struct work_struct rs_work; struct regmap *regmap; + unsigned int char_time_us; unsigned int baud; bool tx_break; /* break_ctl() owns the transceiver */ @@ -1010,6 +1011,7 @@ static void max310x_set_termios(struct uart_port *port, struct ktermios *termios, const struct ktermios *old) { + unsigned int frame_bits = tty_get_frame_size(termios->c_cflag); unsigned int lcr = 0, flow = 0; int baud; @@ -1122,10 +1124,13 @@ static void max310x_set_termios(struct uart_port *port, uart_update_timeout(port, termios->c_cflag, baud); /* - * Cache the new baud rate and reprogram the RS485 RTS delays, whose - * millisecond-to-bit-time conversion depends on it. + * Cache the new baud rate and the time it takes to clock out one + * character before reprogramming the RS485 RTS delays: the + * millisecond-to-bit-time conversion divides by the baud rate. */ to_max310x_port(port)->baud = baud; + to_max310x_port(port)->char_time_us = + DIV_ROUND_UP(USEC_PER_SEC * frame_bits, baud); max310x_set_rts_ctl_params(to_max310x_port(port)); } @@ -1182,9 +1187,10 @@ static int max310x_startup(struct uart_port *port) one->tx_break = false; max310x_port_update(port, MAX310X_LCR_REG, MAX310X_LCR_TXBREAK_BIT, 0); - /* Configure MODE1 register */ + /* Configure MODE1: re-enable the transmitter shutdown() stopped */ max310x_port_update(port, MAX310X_MODE1_REG, - MAX310X_MODE1_TRNSCVCTRL_BIT, 0); + MAX310X_MODE1_TRNSCVCTRL_BIT | + MAX310X_MODE1_TXDIS_BIT, 0); /* Configure MODE2 register & Reset FIFOs*/ val = MAX310X_MODE2_RXEMPTINV_BIT | MAX310X_MODE2_FIFORST_BIT; @@ -1221,9 +1227,39 @@ static int max310x_startup(struct uart_port *port) static void max310x_shutdown(struct uart_port *port) { + struct max310x_one *one = to_max310x_port(port); + /* Disable all interrupts */ max310x_port_write(port, MAX310X_IRQEN_REG, 0); + /* + * Stop the transmitter: the character in flight completes, data + * still queued is abandoned (the next startup() resets the FIFOs). + */ + max310x_port_update(port, MAX310X_MODE1_REG, + MAX310X_MODE1_TXDIS_BIT, MAX310X_MODE1_TXDIS_BIT); + + /* + * Let the character in flight finish (the chip has no + * transmitter-idle status), then empty the FIFO: auto-RTS releases + * only once the transmitter is empty, and the power-off below + * would freeze an asserted pin until the next open. + */ + fsleep(one->char_time_us); + max310x_port_update(port, MAX310X_MODE2_REG, + MAX310X_MODE2_FIFORST_BIT, + MAX310X_MODE2_FIFORST_BIT); + max310x_port_update(port, MAX310X_MODE2_REG, + MAX310X_MODE2_FIFORST_BIT, 0); + if (port->rs485.flags & SER_RS485_ENABLED && one->baud) { + unsigned int hold = DIV_ROUND_UP(one->baud * + port->rs485.delay_rts_after_send, + MSEC_PER_SEC); + + fsleep(max(DIV_ROUND_UP((hold + 1) * USEC_PER_SEC, + one->baud), 100U)); + } + max310x_power(port, 0); }