Commit 1a613626 authored by Fabio Estevam's avatar Fabio Estevam Committed by Greg Kroah-Hartman

serial: imx: Fix the RTS GPIO polarity in RS485 mode

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: default avatarFabio Estevam <fabio.estevam@nxp.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent aa42db44
...@@ -377,9 +377,9 @@ static void imx_stop_tx(struct uart_port *port) ...@@ -377,9 +377,9 @@ static void imx_stop_tx(struct uart_port *port)
readl(port->membase + USR2) & USR2_TXDC) { readl(port->membase + USR2) & USR2_TXDC) {
temp = readl(port->membase + UCR2); temp = readl(port->membase + UCR2);
if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND) if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
imx_port_rts_inactive(sport, &temp);
else
imx_port_rts_active(sport, &temp); imx_port_rts_active(sport, &temp);
else
imx_port_rts_inactive(sport, &temp);
temp |= UCR2_RXEN; temp |= UCR2_RXEN;
writel(temp, port->membase + UCR2); writel(temp, port->membase + UCR2);
...@@ -585,9 +585,9 @@ static void imx_start_tx(struct uart_port *port) ...@@ -585,9 +585,9 @@ static void imx_start_tx(struct uart_port *port)
if (port->rs485.flags & SER_RS485_ENABLED) { if (port->rs485.flags & SER_RS485_ENABLED) {
temp = readl(port->membase + UCR2); temp = readl(port->membase + UCR2);
if (port->rs485.flags & SER_RS485_RTS_ON_SEND) if (port->rs485.flags & SER_RS485_RTS_ON_SEND)
imx_port_rts_inactive(sport, &temp);
else
imx_port_rts_active(sport, &temp); imx_port_rts_active(sport, &temp);
else
imx_port_rts_inactive(sport, &temp);
if (!(port->rs485.flags & SER_RS485_RX_DURING_TX)) if (!(port->rs485.flags & SER_RS485_RX_DURING_TX))
temp &= ~UCR2_RXEN; temp &= ~UCR2_RXEN;
writel(temp, port->membase + UCR2); writel(temp, port->membase + UCR2);
...@@ -1477,9 +1477,9 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, ...@@ -1477,9 +1477,9 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
*/ */
if (port->rs485.flags & if (port->rs485.flags &
SER_RS485_RTS_AFTER_SEND) SER_RS485_RTS_AFTER_SEND)
imx_port_rts_inactive(sport, &ucr2);
else
imx_port_rts_active(sport, &ucr2); imx_port_rts_active(sport, &ucr2);
else
imx_port_rts_inactive(sport, &ucr2);
} else { } else {
imx_port_rts_auto(sport, &ucr2); imx_port_rts_auto(sport, &ucr2);
} }
...@@ -1489,9 +1489,9 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, ...@@ -1489,9 +1489,9 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
} else if (port->rs485.flags & SER_RS485_ENABLED) { } else if (port->rs485.flags & SER_RS485_ENABLED) {
/* disable transmitter */ /* disable transmitter */
if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND) if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
imx_port_rts_inactive(sport, &ucr2);
else
imx_port_rts_active(sport, &ucr2); 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, ...@@ -1733,9 +1733,9 @@ static int imx_rs485_config(struct uart_port *port,
/* disable transmitter */ /* disable transmitter */
temp = readl(sport->port.membase + UCR2); temp = readl(sport->port.membase + UCR2);
if (rs485conf->flags & SER_RS485_RTS_AFTER_SEND) if (rs485conf->flags & SER_RS485_RTS_AFTER_SEND)
imx_port_rts_inactive(sport, &temp);
else
imx_port_rts_active(sport, &temp); imx_port_rts_active(sport, &temp);
else
imx_port_rts_inactive(sport, &temp);
writel(temp, sport->port.membase + UCR2); writel(temp, sport->port.membase + UCR2);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment