From 1a613626d2895f4f6b95a3b0a6413e52e00b5f95 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 30 Jan 2017 09:12:11 -0200 Subject: [PATCH] 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: Fabio Estevam Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 33fcc84e756b..29dd57c51706 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -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); } -- 2.20.1