All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>
To: linux-serial@vger.kernel.org, Jiri Slaby <jirislaby@kernel.org>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-kernel@vger.kernel.org, "Lukas Wunner" <lukas@wunner.de>,
	"Johan Hovold" <johan@kernel.org>,
	"Andy Shevchenko" <andriy.shevchenko@linux.intel.com>,
	"Heikki Krogerus" <heikki.krogerus@linux.intel.com>,
	"Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>,
	"Eric Tremblay" <etremblay@distech-controls.com>,
	"Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>
Subject: [RFC PATCH 3/7] serial: 8250_dwlib: Implement SW half duplex support
Date: Wed,  2 Mar 2022 11:56:02 +0200	[thread overview]
Message-ID: <20220302095606.14818-4-ilpo.jarvinen@linux.intel.com> (raw)
In-Reply-To: <20220302095606.14818-1-ilpo.jarvinen@linux.intel.com>

This patch enables support for SW half-duplex mode. Synopsys
DesignWare UART has a build-in support for the RS485 protocol
from IP version 4.0 onward with dedicated RE/DE_EN registers.
This patch enables RS485 either using dedicated registers or
em485 as fallback.

In order to select preference for SW half-duplex mode (em485 +
RE/DE_EN) over HW managed one, as both are supported under
some configurations, SER_RS485_SW_RX_OR_TX flag is added to
serial_rs485.

This patch depends on UART_CAP_NOTEMT which is not provided
by this series but another one:
  https://lore.kernel.org/all/20210204161158.643-1-etremblay@distech-controls.com/

Cc: Eric Tremblay <etremblay@distech-controls.com>
Cc: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 drivers/tty/serial/8250/8250_dwlib.c | 60 +++++++++++++++++++++++++---
 include/uapi/linux/serial.h          |  2 +
 2 files changed, 56 insertions(+), 6 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_dwlib.c b/drivers/tty/serial/8250/8250_dwlib.c
index d26792999984..51b0f55ee9d0 100644
--- a/drivers/tty/serial/8250/8250_dwlib.c
+++ b/drivers/tty/serial/8250/8250_dwlib.c
@@ -101,8 +101,26 @@ void dw8250_do_set_termios(struct uart_port *p, struct ktermios *termios, struct
 }
 EXPORT_SYMBOL_GPL(dw8250_do_set_termios);
 
+static void dw8250_rs485_start_tx(struct uart_8250_port *up)
+{
+	struct uart_port *p = &(up->port);
+
+	dw8250_writel_ext(p, DW_UART_RE_EN, 0);
+	dw8250_writel_ext(p, DW_UART_DE_EN, 1);
+}
+
+static void dw8250_rs485_stop_tx(struct uart_8250_port *up)
+{
+	struct uart_port *p = &(up->port);
+
+	dw8250_writel_ext(p, DW_UART_DE_EN, 0);
+	dw8250_writel_ext(p, DW_UART_RE_EN, 1);
+}
+
 static int dw8250_rs485_config(struct uart_port *p, struct serial_rs485 *rs485)
 {
+	struct uart_8250_port *up = up_to_u8250p(p);
+	u32 re_en, de_en;
 	u32 tcr;
 
 	tcr = dw8250_readl_ext(p, DW_UART_TCR);
@@ -110,16 +128,29 @@ static int dw8250_rs485_config(struct uart_port *p, struct serial_rs485 *rs485)
 
 	if (rs485->flags & SER_RS485_ENABLED) {
 		/* Clearing unsupported flags. */
-		rs485->flags &= SER_RS485_ENABLED | SER_RS485_RX_DURING_TX;
+		rs485->flags &= SER_RS485_ENABLED | SER_RS485_RX_DURING_TX | SER_RS485_SW_RX_OR_TX;
 		tcr |= DW_UART_TCR_RS485_EN;
 
 		if (rs485->flags & SER_RS485_RX_DURING_TX) {
 			tcr |= DW_UART_TCR_XFER_MODE_DE_DURING_RE;
+			re_en = 1;
+			de_en = 1;
+			rs485->flags &= ~SER_RS485_SW_RX_OR_TX;
+		} else if (rs485->flags & SER_RS485_SW_RX_OR_TX) {
+			tcr |= DW_UART_TCR_XFER_MODE_SW_DE_OR_RE;
+			re_en = 1;
+			de_en = 0;
+			if (up->em485 && !up->em485->tx_stopped) {
+				re_en = 0;
+				de_en = 1;
+			}
 		} else {
 			tcr |= DW_UART_TCR_XFER_MODE_DE_OR_RE;
+			re_en = 1;
+			de_en = 1;
 		}
-		dw8250_writel_ext(p, DW_UART_DE_EN, 1);
-		dw8250_writel_ext(p, DW_UART_RE_EN, 1);
+		dw8250_writel_ext(p, DW_UART_DE_EN, de_en);
+		dw8250_writel_ext(p, DW_UART_RE_EN, re_en);
 	} else {
 		rs485->flags = 0;
 
@@ -147,7 +178,16 @@ static int dw8250_rs485_config(struct uart_port *p, struct serial_rs485 *rs485)
 	rs485->delay_rts_before_send = 0;
 	rs485->delay_rts_after_send = 0;
 
-	p->rs485 = *rs485;
+	if (rs485->flags & SER_RS485_SW_RX_OR_TX) {
+		int ret;
+
+		ret = serial8250_em485_config(p, rs485);
+		if (ret)
+			return ret;
+	} else {
+		serial8250_em485_destroy(up_to_u8250p(p));
+		p->rs485 = *rs485;
+	}
 
 	return 0;
 }
@@ -159,8 +199,16 @@ void dw8250_setup_port(struct uart_port *p)
 	u32 reg;
 
 	d->hw_rs485_support = device_property_read_bool(p->dev, "snps,rs485-interface-en");
-	if (d->hw_rs485_support)
+	if (d->hw_rs485_support) {
 		p->rs485_config = dw8250_rs485_config;
+		up->rs485_start_tx = dw8250_rs485_start_tx;
+		up->rs485_stop_tx = dw8250_rs485_stop_tx;
+	} else {
+		p->rs485_config = serial8250_em485_config;
+		up->rs485_start_tx = serial8250_em485_start_tx;
+		up->rs485_stop_tx = serial8250_em485_stop_tx;
+	}
+	up->capabilities |= UART_CAP_NOTEMT;
 
 	/*
 	 * If the Component Version Register returns zero, we know that
@@ -192,7 +240,7 @@ void dw8250_setup_port(struct uart_port *p)
 		p->type = PORT_16550A;
 		p->flags |= UPF_FIXED_TYPE;
 		p->fifosize = DW_UART_CPR_FIFO_SIZE(reg);
-		up->capabilities = UART_CAP_FIFO;
+		up->capabilities = UART_CAP_FIFO | UART_CAP_NOTEMT;
 	}
 
 	if (reg & DW_UART_CPR_AFCE_MODE)
diff --git a/include/uapi/linux/serial.h b/include/uapi/linux/serial.h
index fa6b16e5fdd8..f868685b35a0 100644
--- a/include/uapi/linux/serial.h
+++ b/include/uapi/linux/serial.h
@@ -126,6 +126,8 @@ struct serial_rs485 {
 #define SER_RS485_TERMINATE_BUS		(1 << 5)	/* Enable bus
 							   termination
 							   (if supported) */
+#define SER_RS485_SW_RX_OR_TX		(1 << 6)	/* Prefer SW half-duplex
+							   mode over HW one */
 	__u32	delay_rts_before_send;	/* Delay before send (milliseconds) */
 	__u32	delay_rts_after_send;	/* Delay after send (milliseconds) */
 	__u32	padding[5];		/* Memory is cheap, new structs
-- 
2.30.2


  parent reply	other threads:[~2022-03-02  9:57 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-03-02  9:55 [PATCH 0/7] Add RS485 support to DW UART Ilpo Järvinen
2022-03-02  9:56 ` [PATCH 1/7] serial: 8250_dwlib: RS485 HW half duplex support Ilpo Järvinen
2022-03-06 18:48   ` Lukas Wunner
2022-03-06 22:07     ` Andy Shevchenko
2022-03-07  9:19       ` Ilpo Järvinen
2022-03-07 19:18         ` Lukas Wunner
2022-03-07 19:39           ` Andy Shevchenko
2022-03-08 12:16             ` Ilpo Järvinen
2022-03-08 12:22               ` Lukas Wunner
2022-03-08 12:59                 ` Ilpo Järvinen
2022-03-08 14:50                   ` Lukas Wunner
2022-03-08 14:53                     ` Andy Shevchenko
2022-03-08 20:30                       ` Lukas Wunner
2022-03-09  9:51                         ` Ilpo Järvinen
2022-03-07 10:54     ` Ilpo Järvinen
2022-03-09  8:52       ` Lukas Wunner
2022-03-09 12:19       ` Ilpo Järvinen
2022-03-09 12:59         ` Lukas Wunner
2022-03-02  9:56 ` [PATCH 2/7] serial: 8250_dwlib: RS485 HW full " Ilpo Järvinen
2022-03-06 18:51   ` Lukas Wunner
2022-03-07  9:22     ` Ilpo Järvinen
2022-03-02  9:56 ` Ilpo Järvinen [this message]
2022-03-06 19:21   ` [RFC PATCH 3/7] serial: 8250_dwlib: Implement SW half " Lukas Wunner
2022-03-06 22:13     ` Andy Shevchenko
2022-03-02  9:56 ` [PATCH 4/7] dt_bindings: snps-dw-apb-uart: Add RS485 Ilpo Järvinen
2022-03-02 17:47   ` Rob Herring
2022-03-02  9:56 ` [RFC PATCH 5/7] serial: termbits: ADDRB to indicate 9th bit addressing mode Ilpo Järvinen
2022-03-02  9:56   ` Ilpo Järvinen
2022-03-02  9:56   ` Ilpo Järvinen
2022-03-02  9:56 ` [RFC PATCH 6/7] serial: General support for multipoint addresses Ilpo Järvinen
2022-03-02  9:56   ` Ilpo Järvinen
2022-03-02  9:56   ` Ilpo Järvinen
2022-03-06 19:40   ` Lukas Wunner
2022-03-06 19:40     ` Lukas Wunner
2022-03-06 19:40     ` Lukas Wunner
2022-03-07  9:48     ` Ilpo Järvinen
2022-03-07  9:48       ` Ilpo Järvinen
2022-03-07  9:48       ` Ilpo Järvinen
2022-03-09 19:05       ` Lukas Wunner
2022-03-09 19:05         ` Lukas Wunner
2022-03-09 19:05         ` Lukas Wunner
2022-03-10 12:29         ` Ilpo Järvinen
2022-03-10 12:29           ` Ilpo Järvinen
2022-03-10 12:29           ` Ilpo Järvinen
2022-03-10 14:09         ` Andy Shevchenko
2022-03-10 14:09           ` Andy Shevchenko
2022-03-10 14:09           ` Andy Shevchenko
2022-03-02  9:56 ` [RFC PATCH 7/7] serial: 8250_dwlib: Support for 9th bit multipoint addressing Ilpo Järvinen

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=20220302095606.14818-4-ilpo.jarvinen@linux.intel.com \
    --to=ilpo.jarvinen@linux.intel.com \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=etremblay@distech-controls.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=heikki.krogerus@linux.intel.com \
    --cc=jirislaby@kernel.org \
    --cc=johan@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-serial@vger.kernel.org \
    --cc=lukas@wunner.de \
    --cc=u.kleine-koenig@pengutronix.de \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.