serial: stm32: Add RS485 RTS GPIO control again
authorMarek Vasut <marex@denx.de>
Mon, 31 Aug 2020 17:10:45 +0000 (19:10 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 4 Sep 2020 15:16:40 +0000 (17:16 +0200)
While the STM32 does support RS485 drive-enable control within the
UART IP itself, some systems have the drive-enable line connected
to a pin which cannot be pinmuxed as RTS. Add support for toggling
the RTS GPIO line using the modem control GPIOs to provide at least
some sort of emulation.

Fixes: 7df5081cbf5e ("serial: stm32: Add RS485 RTS GPIO control")
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Alexandre Torgue <alexandre.torgue@st.com>
Cc: Andy Shevchenko <andy.shevchenko@gmail.com>
Cc: Manivannan Sadhasivam <mani@kernel.org>
Cc: Fabrice Gasnier <fabrice.gasnier@st.com>
Cc: linux-stm32@st-md-mailman.stormreply.com
Link: https://lore.kernel.org/r/20200831171045.205691-1-marex@denx.de
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/stm32-usart.c

index ba503dd..ee6c776 100644 (file)
@@ -129,13 +129,9 @@ static int stm32_config_rs485(struct uart_port *port,
                if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
                        cr3 &= ~USART_CR3_DEP;
                        rs485conf->flags &= ~SER_RS485_RTS_AFTER_SEND;
-                       mctrl_gpio_set(stm32_port->gpios,
-                                       stm32_port->port.mctrl & ~TIOCM_RTS);
                } else {
                        cr3 |= USART_CR3_DEP;
                        rs485conf->flags |= SER_RS485_RTS_AFTER_SEND;
-                       mctrl_gpio_set(stm32_port->gpios,
-                                       stm32_port->port.mctrl | TIOCM_RTS);
                }
 
                writel_relaxed(cr3, port->membase + ofs->cr3);
@@ -541,17 +537,42 @@ static void stm32_disable_ms(struct uart_port *port)
 /* Transmit stop */
 static void stm32_stop_tx(struct uart_port *port)
 {
+       struct stm32_port *stm32_port = to_stm32_port(port);
+       struct serial_rs485 *rs485conf = &port->rs485;
+
        stm32_tx_interrupt_disable(port);
+
+       if (rs485conf->flags & SER_RS485_ENABLED) {
+               if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
+                       mctrl_gpio_set(stm32_port->gpios,
+                                       stm32_port->port.mctrl & ~TIOCM_RTS);
+               } else {
+                       mctrl_gpio_set(stm32_port->gpios,
+                                       stm32_port->port.mctrl | TIOCM_RTS);
+               }
+       }
 }
 
 /* There are probably characters waiting to be transmitted. */
 static void stm32_start_tx(struct uart_port *port)
 {
+       struct stm32_port *stm32_port = to_stm32_port(port);
+       struct serial_rs485 *rs485conf = &port->rs485;
        struct circ_buf *xmit = &port->state->xmit;
 
        if (uart_circ_empty(xmit))
                return;
 
+       if (rs485conf->flags & SER_RS485_ENABLED) {
+               if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
+                       mctrl_gpio_set(stm32_port->gpios,
+                                       stm32_port->port.mctrl | TIOCM_RTS);
+               } else {
+                       mctrl_gpio_set(stm32_port->gpios,
+                                       stm32_port->port.mctrl & ~TIOCM_RTS);
+               }
+       }
+
        stm32_transmit_chars(port);
 }
 
@@ -851,13 +872,9 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios,
                if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
                        cr3 &= ~USART_CR3_DEP;
                        rs485conf->flags &= ~SER_RS485_RTS_AFTER_SEND;
-                       mctrl_gpio_set(stm32_port->gpios,
-                                       stm32_port->port.mctrl & ~TIOCM_RTS);
                } else {
                        cr3 |= USART_CR3_DEP;
                        rs485conf->flags |= SER_RS485_RTS_AFTER_SEND;
-                       mctrl_gpio_set(stm32_port->gpios,
-                                       stm32_port->port.mctrl | TIOCM_RTS);
                }
 
        } else {