From: Jakub Kicinski <[email protected]>

Hardware is capable of inverting RTS signal when working
in RS-485 mode.  Expose this functionality to user space.
Relay on a matching combination of standard flags
(SER_RS485_RTS_ON_SEND and SER_RS485_RTS_AFTER_SEND) to
detect when user space is requesting inverted RTS mode.

Signed-off-by: Jakub Kicinski <[email protected]>
---
 drivers/tty/serial/sc16is7xx.c | 32 +++++++++++++++++++++++---------
 1 file changed, 23 insertions(+), 9 deletions(-)

diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c
index e6b396e584f3..24902d589b07 100644
--- a/drivers/tty/serial/sc16is7xx.c
+++ b/drivers/tty/serial/sc16is7xx.c
@@ -829,16 +829,30 @@ static void sc16is7xx_set_termios(struct uart_port *port,
 }
 
 static int sc16is7xx_config_rs485(struct uart_port *port,
-                                  struct serial_rs485 *rs485)
+                                 struct serial_rs485 *rs485)
 {
-       if (port->rs485.flags & SER_RS485_ENABLED)
-               sc16is7xx_port_update(port, SC16IS7XX_EFCR_REG,
-                                     SC16IS7XX_EFCR_AUTO_RS485_BIT,
-                                     SC16IS7XX_EFCR_AUTO_RS485_BIT);
-       else
-               sc16is7xx_port_update(port, SC16IS7XX_EFCR_REG,
-                                     SC16IS7XX_EFCR_AUTO_RS485_BIT,
-                                     0);
+       const u32 mask = SC16IS7XX_EFCR_AUTO_RS485_BIT |
+                        SC16IS7XX_EFCR_RTS_INVERT_BIT;
+       u32 efcr = 0;
+
+       if (rs485->flags & SER_RS485_ENABLED) {
+               bool rts_during_rx, rts_during_tx;
+
+               rts_during_rx = rs485->flags & SER_RS485_RTS_AFTER_SEND;
+               rts_during_tx = rs485->flags & SER_RS485_RTS_ON_SEND;
+
+               efcr |= SC16IS7XX_EFCR_AUTO_RS485_BIT;
+
+               if (!rts_during_rx && rts_during_tx)
+                       /* default */;
+               else if (rts_during_rx && !rts_during_tx)
+                       efcr |= SC16IS7XX_EFCR_RTS_INVERT_BIT;
+               else
+                       return -EINVAL;
+       }
+
+       sc16is7xx_port_update(port, SC16IS7XX_EFCR_REG, mask, efcr);
+
        port->rs485 = *rs485;
 
        return 0;
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to