serial: imx: Fix the RTS GPIO polarity in RS485 mode
authorFabio Estevam <fabio.estevam@nxp.com>
Mon, 30 Jan 2017 11:12:11 +0000 (09:12 -0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 31 Jan 2017 09:54:58 +0000 (10:54 +0100)
On a board that needs to drive RTS GPIO high in order to enable the
transmission of a RS485 transceiver the following description is
passed in the devide tree:

&uart4 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_uart4>;
        rts-gpios = <&gpio6 2 GPIO_ACTIVE_HIGH>;
        status = "okay";
};

and userspace configures the uart port as follows:

/* enable RS485 mode: */
rs485conf.flags |= SER_RS485_ENABLED;

/* set logical level for RTS pin equal to 1 when sending: */
rs485conf.flags |= SER_RS485_RTS_ON_SEND;

/* set logical level for RTS pin equal to 0 after sending: */
rs485conf.flags &= ~(SER_RS485_RTS_AFTER_SEND);

However the RTS GPIO polarity observed in the oscilloscope is inverted.

When the SER_RS485_RTS_ON_SEND flag is set the imx_port_rts_active()
function should be called and following the same logic when
SER_RS485_RTS_AFTER_SEND flag is cleared the imx_port_rts_inactive()
should be called.

Do such logic change so that RS485 communication in half duplex can
work successfully when the RTS GPIO pin is passed via device tree.

Signed-off-by: Fabio Estevam <fabio.estevam@nxp.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/imx.c

index 33fcc84e756b2d89a47d9f0bcaf976db9580ff03..29dd57c51706c1725474eea6e6cb7884d15da2cf 100644 (file)
@@ -377,9 +377,9 @@ static void imx_stop_tx(struct uart_port *port)
            readl(port->membase + USR2) & USR2_TXDC) {
                temp = readl(port->membase + UCR2);
                if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
-                       imx_port_rts_inactive(sport, &temp);
-               else
                        imx_port_rts_active(sport, &temp);
+               else
+                       imx_port_rts_inactive(sport, &temp);
                temp |= UCR2_RXEN;
                writel(temp, port->membase + UCR2);
 
@@ -585,9 +585,9 @@ static void imx_start_tx(struct uart_port *port)
        if (port->rs485.flags & SER_RS485_ENABLED) {
                temp = readl(port->membase + UCR2);
                if (port->rs485.flags & SER_RS485_RTS_ON_SEND)
-                       imx_port_rts_inactive(sport, &temp);
-               else
                        imx_port_rts_active(sport, &temp);
+               else
+                       imx_port_rts_inactive(sport, &temp);
                if (!(port->rs485.flags & SER_RS485_RX_DURING_TX))
                        temp &= ~UCR2_RXEN;
                writel(temp, port->membase + UCR2);
@@ -1477,9 +1477,9 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
                                 */
                                if (port->rs485.flags &
                                    SER_RS485_RTS_AFTER_SEND)
-                                       imx_port_rts_inactive(sport, &ucr2);
-                               else
                                        imx_port_rts_active(sport, &ucr2);
+                               else
+                                       imx_port_rts_inactive(sport, &ucr2);
                        } else {
                                imx_port_rts_auto(sport, &ucr2);
                        }
@@ -1489,9 +1489,9 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
        } else if (port->rs485.flags & SER_RS485_ENABLED) {
                /* disable transmitter */
                if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
-                       imx_port_rts_inactive(sport, &ucr2);
-               else
                        imx_port_rts_active(sport, &ucr2);
+               else
+                       imx_port_rts_inactive(sport, &ucr2);
        }
 
 
@@ -1733,9 +1733,9 @@ static int imx_rs485_config(struct uart_port *port,
                /* disable transmitter */
                temp = readl(sport->port.membase + UCR2);
                if (rs485conf->flags & SER_RS485_RTS_AFTER_SEND)
-                       imx_port_rts_inactive(sport, &temp);
-               else
                        imx_port_rts_active(sport, &temp);
+               else
+                       imx_port_rts_inactive(sport, &temp);
                writel(temp, sport->port.membase + UCR2);
        }