mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Tapio Reijonen <tapio.reijonen@vaisala.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	 Jiri Slaby <jirislaby@kernel.org>
Cc: linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org,
	 Hugo Villeneuve <hvilleneuve@dimonoff.com>,
	 Tapio Reijonen <tapio.reijonen@kolumbus.fi>,
	 Tapio Reijonen <tapio.reijonen@vaisala.com>
Subject: [PATCH v5 5/8] serial: max310x: support active-low RTS on the hardware path
Date: Tue, 29 Sep 2026 09:37:59 +0000	[thread overview]
Message-ID: <20260929-max310x-rs485-sw-delay-v5-5-ae46afa583f2@vaisala.com> (raw)
In-Reply-To: <20260929-max310x-rs485-sw-delay-v5-0-ae46afa583f2@vaisala.com>

The chip's auto-RTS engine asserts the RTS_ pin high while data is
shifting out, so a transceiver with an active-low driver-enable could
not use the hardware RS485 path at all: SER_RS485_RTS_AFTER_SEND is
not in the supported flags and the core normalizes it away with
"invalid RTS setting, using RTS_ON_SEND instead".

The output stage is invertible: program IRDA.RTSINVERT when the
requested polarity is active-low and advertise SER_RS485_RTS_AFTER_SEND
in rs485_supported. A break already drives break_state onto the RTS
bit unadjusted, which remains correct because RTSINVERT inverts the
output stage itself, not the register value.

Signed-off-by: Tapio Reijonen <tapio.reijonen@vaisala.com>
---
 drivers/tty/serial/max310x.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
index cd3b1913aaadba94805f4728b5eba18e970e34c8..e07fb87f21f102cfa3fdae5275cb7810be1c3dbd 100644
--- a/drivers/tty/serial/max310x.c
+++ b/drivers/tty/serial/max310x.c
@@ -164,6 +164,7 @@
 /* IRDA register bits */
 #define MAX310X_IRDA_IRDAEN_BIT		(1 << 0) /* IRDA mode enable */
 #define MAX310X_IRDA_SIR_BIT		(1 << 1) /* SIR mode enable */
+#define MAX310X_IRDA_RTSINVERT_BIT	(1 << 2) /* Invert RTS output */
 
 /* HDPIXDELAY accessor macros */
 #define MAX310X_HDPIXDELAY_SETUP(val)	(((val) & 0x0f) << 4)
@@ -951,7 +952,7 @@ static void max310x_set_rts_ctl_params(struct max310x_one *one)
 	const unsigned int max_bit_dly = 15;
 	struct uart_port *port = &one->port;
 	unsigned int setup = 0, hold = 0;
-	u8 mode1 = 0;
+	u8 mode1 = 0, irda = 0;
 
 	if (port->rs485.flags & SER_RS485_ENABLED) {
 		/* Convert milliseconds to bit-times, rounding up. */
@@ -963,6 +964,12 @@ static void max310x_set_rts_ctl_params(struct max310x_one *one)
 		hold  = min(hold,  max_bit_dly);
 
 		mode1 = MAX310X_MODE1_TRNSCVCTRL_BIT;
+		/*
+		 * The auto-RTS engine asserts RTS high on send; for an
+		 * active-low RTS let IRDA.RTSINVERT invert the output stage.
+		 */
+		if (!(port->rs485.flags & SER_RS485_RTS_ON_SEND))
+			irda = MAX310X_IRDA_RTSINVERT_BIT;
 	}
 
 	max310x_port_write(port, MAX310X_HDPIXDELAY_REG,
@@ -980,6 +987,8 @@ static void max310x_set_rts_ctl_params(struct max310x_one *one)
 
 	max310x_port_update(port, MAX310X_MODE1_REG,
 			    MAX310X_MODE1_TRNSCVCTRL_BIT, mode1);
+	max310x_port_update(port, MAX310X_IRDA_REG,
+			    MAX310X_IRDA_RTSINVERT_BIT, irda);
 }
 
 static void max310x_break_ctl(struct uart_port *port, int break_state)
@@ -999,7 +1008,9 @@ static void max310x_break_ctl(struct uart_port *port, int break_state)
 	 * The chip's auto-RTS asserts the transceiver only while FIFO data is
 	 * shifting out, and a break is not FIFO data. Disable auto-RTS for the
 	 * break duration and drive RTS manually so the break reaches the wire;
-	 * restore auto-RTS when the break ends.
+	 * restore auto-RTS when the break ends. For an active-low RTS,
+	 * IRDA.RTSINVERT already inverts the RTS_ output stage, so break_state
+	 * is driven as it is.
 	 */
 	if (break_state) {
 		max310x_port_update(port, MAX310X_MODE1_REG,
@@ -1407,7 +1418,8 @@ static int max310x_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
 #endif
 
 static const struct serial_rs485 max310x_rs485_supported = {
-	.flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND | SER_RS485_RX_DURING_TX,
+	.flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND |
+		 SER_RS485_RTS_AFTER_SEND | SER_RS485_RX_DURING_TX,
 	.delay_rts_before_send = 1,
 	.delay_rts_after_send = 1,
 };

-- 
2.47.3


  parent reply	other threads:[~2026-09-29  9:38 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-29  9:37 [PATCH v5 0/8] serial: max310x: RS485 delay and RTS fixes, software-timed delays Tapio Reijonen
2026-09-29  9:37 ` [PATCH v5 1/8] serial: max310x: don't clobber the TX break bit in set_termios Tapio Reijonen
2026-09-29 13:40   ` Hugo Villeneuve
2026-10-02  7:25     ` Tapio Reijonen
2026-10-02 15:03       ` Hugo Villeneuve
2026-10-04 10:45         ` Tapio Reijonen
2026-09-29  9:37 ` [PATCH v5 2/8] serial: max310x: assert the transceiver during a break Tapio Reijonen
2026-09-29  9:37 ` [PATCH v5 3/8] serial: max310x: convert RS485 delays from milliseconds to bit-times Tapio Reijonen
2026-09-29 13:54   ` Hugo Villeneuve
2026-10-01 19:11   ` Hugo Villeneuve
2026-10-02  7:27     ` Tapio Reijonen
2026-09-29  9:37 ` [PATCH v5 4/8] serial: max310x: wait for TX to drain before powering down in shutdown Tapio Reijonen
2026-10-01 20:00   ` Hugo Villeneuve
2026-10-02  7:28     ` Tapio Reijonen
2026-10-02 15:01       ` Hugo Villeneuve
2026-10-04 10:56         ` Tapio Reijonen
2026-09-29  9:37 ` Tapio Reijonen [this message]
2026-09-29  9:38 ` [PATCH v5 6/8] serial: max310x: schedule tx_work directly from the IRQ handler Tapio Reijonen
2026-09-29  9:38 ` [PATCH v5 7/8] serial: max310x: drive RTS in software when hardware delays are too short Tapio Reijonen
2026-09-29  9:38 ` [PATCH v5 8/8] serial: max310x: don't transmit while an RS485 reconfigure is pending Tapio Reijonen
2026-10-01  8:35 ` [PATCH v5 0/8] serial: max310x: RS485 delay and RTS fixes, software-timed delays Greg Kroah-Hartman
2026-10-01  9:10   ` Tapio Reijonen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260929-max310x-rs485-sw-delay-v5-5-ae46afa583f2@vaisala.com \
    --to=tapio.reijonen@vaisala.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=hvilleneuve@dimonoff.com \
    --cc=jirislaby@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-serial@vger.kernel.org \
    --cc=tapio.reijonen@kolumbus.fi \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®