All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/7] Add RS485 support to DW UART
@ 2022-03-02  9:55 Ilpo Järvinen
  2022-03-02  9:56 ` [PATCH 1/7] serial: 8250_dwlib: RS485 HW half duplex support Ilpo Järvinen
                   ` (6 more replies)
  0 siblings, 7 replies; 48+ messages in thread
From: Ilpo Järvinen @ 2022-03-02  9:55 UTC (permalink / raw)
  To: linux-serial, Jiri Slaby, Greg Kroah-Hartman
  Cc: linux-kernel, Lukas Wunner, Johan Hovold, Andy Shevchenko,
	Heikki Krogerus, Ilpo Järvinen

This patchset adds RS-485 support to the DW UART driver. The patchset
has two main parts. The first part adds HW support for RS-485 itself
in various modes of operation and the second part focuses on enabling
9th bit addressing mode that can be used on a multipoint RS-485
communications line.

SW half-duplex patch (3/7) depends on UART_CAP_NOTEMT for which there
is existing work from others:
  https://marc.info/?l=linux-kernel&m=161245538311420&w=2
That patchset is not yet applied (and requires revision from its
author).

To configure multipoint addressing, ADDRB flag is added to termios
and two new IOCTLs are added into serial core. On the driver side,
I looked into using mux subsystem but its model didn't seem to match
well enough to how RS-485 multipoint can be operated.

I'm aware of the RS485 changes Lino Sanfilippo recently posted
which will make one assignment in the patchset redundant. I'll make
the adjustment if those get applied.

Ilpo Järvinen (7):
  serial: 8250_dwlib: RS485 HW half duplex support
  serial: 8250_dwlib: RS485 HW full duplex support
  serial: 8250_dwlib: Implement SW half duplex support
  dt_bindings: snps-dw-apb-uart: Add RS485
  serial: termbits: ADDRB to indicate 9th bit addressing mode
  serial: General support for multipoint addresses
  serial: 8250_dwlib: Support for 9th bit multipoint addressing

 .../bindings/serial/snps-dw-apb-uart.yaml     |  17 ++
 .../driver-api/serial/serial-rs485.rst        |  23 +-
 arch/alpha/include/uapi/asm/ioctls.h          |   3 +
 arch/alpha/include/uapi/asm/termbits.h        |   1 +
 arch/mips/include/uapi/asm/ioctls.h           |   3 +
 arch/mips/include/uapi/asm/termbits.h         |   1 +
 arch/parisc/include/uapi/asm/ioctls.h         |   3 +
 arch/parisc/include/uapi/asm/termbits.h       |   1 +
 arch/powerpc/include/uapi/asm/ioctls.h        |   3 +
 arch/powerpc/include/uapi/asm/termbits.h      |   1 +
 arch/sh/include/uapi/asm/ioctls.h             |   3 +
 arch/sparc/include/uapi/asm/ioctls.h          |   3 +
 arch/sparc/include/uapi/asm/termbits.h        |   1 +
 arch/xtensa/include/uapi/asm/ioctls.h         |   3 +
 drivers/tty/amiserial.c                       |   6 +-
 drivers/tty/moxa.c                            |   1 +
 drivers/tty/mxser.c                           |   1 +
 drivers/tty/serial/8250/8250_core.c           |   2 +
 drivers/tty/serial/8250/8250_dwlib.c          | 246 +++++++++++++++++-
 drivers/tty/serial/8250/8250_dwlib.h          |   6 +
 drivers/tty/serial/serial_core.c              |  62 +++++
 drivers/tty/tty_ioctl.c                       |   2 +
 drivers/usb/serial/usb-serial.c               |   5 +-
 include/linux/serial_core.h                   |   6 +
 include/uapi/asm-generic/ioctls.h             |   3 +
 include/uapi/asm-generic/termbits.h           |   1 +
 include/uapi/linux/serial.h                   |  10 +
 27 files changed, 410 insertions(+), 7 deletions(-)

-- 
2.30.2


^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH 1/7] serial: 8250_dwlib: RS485 HW half duplex support
  2022-03-02  9:55 [PATCH 0/7] Add RS485 support to DW UART Ilpo Järvinen
@ 2022-03-02  9:56 ` Ilpo Järvinen
  2022-03-06 18:48   ` Lukas Wunner
  2022-03-02  9:56 ` [PATCH 2/7] serial: 8250_dwlib: RS485 HW full " Ilpo Järvinen
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 48+ messages in thread
From: Ilpo Järvinen @ 2022-03-02  9:56 UTC (permalink / raw)
  To: linux-serial, Jiri Slaby, Greg Kroah-Hartman
  Cc: linux-kernel, Lukas Wunner, Johan Hovold, Andy Shevchenko,
	Heikki Krogerus, Ilpo Järvinen, Raymond Tan

The Synopsys DesignWare UART has a build-in support for the
RS485 protocol from IP version 4.0 onward. This commit
enables basic hardware-controlled half duplex mode support
for it.

HW will take care of managing DE and RE, the driver just gives
it permission to use either by setting both to 1.

Co-developed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Co-developed-by: Raymond Tan <raymond.tan@intel.com>
Signed-off-by: Raymond Tan <raymond.tan@intel.com>
Co-developed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 drivers/tty/serial/8250/8250_dwlib.c | 67 +++++++++++++++++++++++++++-
 drivers/tty/serial/8250/8250_dwlib.h |  3 ++
 2 files changed, 68 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_dwlib.c b/drivers/tty/serial/8250/8250_dwlib.c
index 622d3b0d89e7..a4f09a95049b 100644
--- a/drivers/tty/serial/8250/8250_dwlib.c
+++ b/drivers/tty/serial/8250/8250_dwlib.c
@@ -2,19 +2,33 @@
 /* Synopsys DesignWare 8250 library. */
 
 #include <linux/bitops.h>
+#include <linux/bitfield.h>
 #include <linux/device.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
+#include <linux/property.h>
 #include <linux/serial_8250.h>
 #include <linux/serial_core.h>
 
 #include "8250_dwlib.h"
 
 /* Offsets for the DesignWare specific registers */
+#define DW_UART_TCR	0xac /* Transceiver Control Register (RS485) */
+#define DW_UART_DE_EN	0xb0 /* Driver Output Enable Register */
+#define DW_UART_RE_EN	0xb4 /* Receiver Output Enable Register */
 #define DW_UART_DLF	0xc0 /* Divisor Latch Fraction Register */
 #define DW_UART_CPR	0xf4 /* Component Parameter Register */
 #define DW_UART_UCV	0xf8 /* UART Component Version */
 
+/* Transceiver Control Register bits */
+#define DW_UART_TCR_RS485_EN		BIT(0)
+#define DW_UART_TCR_RE_POL		BIT(1)
+#define DW_UART_TCR_DE_POL		BIT(2)
+#define DW_UART_TCR_XFER_MODE		GENMASK(4, 3)
+#define DW_UART_TCR_XFER_MODE_DE_DURING_RE	FIELD_PREP(DW_UART_TCR_XFER_MODE, 0)
+#define DW_UART_TCR_XFER_MODE_SW_DE_OR_RE	FIELD_PREP(DW_UART_TCR_XFER_MODE, 1)
+#define DW_UART_TCR_XFER_MODE_DE_OR_RE		FIELD_PREP(DW_UART_TCR_XFER_MODE, 2)
+
 /* Component Parameter Register bits */
 #define DW_UART_CPR_ABP_DATA_WIDTH	(3 << 0)
 #define DW_UART_CPR_AFCE_MODE		(1 << 4)
@@ -87,11 +101,62 @@ void dw8250_do_set_termios(struct uart_port *p, struct ktermios *termios, struct
 }
 EXPORT_SYMBOL_GPL(dw8250_do_set_termios);
 
+static int dw8250_rs485_config(struct uart_port *p, struct serial_rs485 *rs485)
+{
+	u32 tcr;
+
+	tcr = dw8250_readl_ext(p, DW_UART_TCR);
+	tcr &= ~DW_UART_TCR_XFER_MODE;
+
+	if (rs485->flags & SER_RS485_ENABLED) {
+		/* Clearing unsupported flags. */
+		rs485->flags &= SER_RS485_ENABLED;
+
+		tcr |= DW_UART_TCR_RS485_EN | DW_UART_TCR_XFER_MODE_DE_OR_RE;
+		dw8250_writel_ext(p, DW_UART_DE_EN, 1);
+		dw8250_writel_ext(p, DW_UART_RE_EN, 1);
+	} else {
+		rs485->flags = 0;
+
+		tcr &= ~DW_UART_TCR_RS485_EN;
+		dw8250_writel_ext(p, DW_UART_DE_EN, 0);
+		dw8250_writel_ext(p, DW_UART_RE_EN, 0);
+	}
+
+	/* Resetting the default DE_POL & RE_POL */
+	tcr &= ~(DW_UART_TCR_DE_POL | DW_UART_TCR_RE_POL);
+
+	if (device_property_read_bool(p->dev, "snps,de-active-high"))
+		tcr |= DW_UART_TCR_DE_POL;
+	if (device_property_read_bool(p->dev, "snps,re-active-high"))
+		tcr |= DW_UART_TCR_RE_POL;
+
+	dw8250_writel_ext(p, DW_UART_TCR, tcr);
+
+	/*
+	 * XXX: Though we could interpret the "RTS" timings as Driver Enable
+	 * (DE) assertion/de-assertion timings, initially not supporting that.
+	 * Ideally we should have timing values for the Driver instead of the
+	 * RTS signal.
+	 */
+	rs485->delay_rts_before_send = 0;
+	rs485->delay_rts_after_send = 0;
+
+	p->rs485 = *rs485;
+
+	return 0;
+}
+
 void dw8250_setup_port(struct uart_port *p)
 {
+	struct dw8250_port_data *d = p->private_data;
 	struct uart_8250_port *up = up_to_u8250p(p);
 	u32 reg;
 
+	d->hw_rs485_support = device_property_read_bool(p->dev, "snps,rs485-interface-en");
+	if (d->hw_rs485_support)
+		p->rs485_config = dw8250_rs485_config;
+
 	/*
 	 * If the Component Version Register returns zero, we know that
 	 * ADDITIONAL_FEATURES are not enabled. No need to go any further.
@@ -108,8 +173,6 @@ void dw8250_setup_port(struct uart_port *p)
 	dw8250_writel_ext(p, DW_UART_DLF, 0);
 
 	if (reg) {
-		struct dw8250_port_data *d = p->private_data;
-
 		d->dlf_size = fls(reg);
 		p->get_divisor = dw8250_get_divisor;
 		p->set_divisor = dw8250_set_divisor;
diff --git a/drivers/tty/serial/8250/8250_dwlib.h b/drivers/tty/serial/8250/8250_dwlib.h
index 83d528e5cc21..a8fa020ca544 100644
--- a/drivers/tty/serial/8250/8250_dwlib.h
+++ b/drivers/tty/serial/8250/8250_dwlib.h
@@ -14,6 +14,9 @@ struct dw8250_port_data {
 
 	/* Hardware configuration */
 	u8			dlf_size;
+
+	/* RS485 variables */
+	bool			hw_rs485_support;
 };
 
 void dw8250_do_set_termios(struct uart_port *p, struct ktermios *termios, struct ktermios *old);
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 2/7] serial: 8250_dwlib: RS485 HW full duplex support
  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-02  9:56 ` Ilpo Järvinen
  2022-03-06 18:51   ` Lukas Wunner
  2022-03-02  9:56 ` [RFC PATCH 3/7] serial: 8250_dwlib: Implement SW half " Ilpo Järvinen
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 48+ messages in thread
From: Ilpo Järvinen @ 2022-03-02  9:56 UTC (permalink / raw)
  To: linux-serial, Jiri Slaby, Greg Kroah-Hartman
  Cc: linux-kernel, Lukas Wunner, Johan Hovold, Andy Shevchenko,
	Heikki Krogerus, Ilpo Järvinen, Raymond Tan

The Synopsys DesignWare UART has a build-in support for the
RS485 protocol from IP version 4.0 onward. This patch enables
the support of HW Full Duplex mode support for it.

To ask for full duplex mode, userspace sets SER_RS485_RX_DURING_TX
flag and HW will take care of the rest.

Co-developed-by: Raymond Tan <raymond.tan@intel.com>
Signed-off-by: Raymond Tan <raymond.tan@intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 drivers/tty/serial/8250/8250_dwlib.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_dwlib.c b/drivers/tty/serial/8250/8250_dwlib.c
index a4f09a95049b..d26792999984 100644
--- a/drivers/tty/serial/8250/8250_dwlib.c
+++ b/drivers/tty/serial/8250/8250_dwlib.c
@@ -110,9 +110,14 @@ 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;
-
-		tcr |= DW_UART_TCR_RS485_EN | DW_UART_TCR_XFER_MODE_DE_OR_RE;
+		rs485->flags &= SER_RS485_ENABLED | SER_RS485_RX_DURING_TX;
+		tcr |= DW_UART_TCR_RS485_EN;
+
+		if (rs485->flags & SER_RS485_RX_DURING_TX) {
+			tcr |= DW_UART_TCR_XFER_MODE_DE_DURING_RE;
+		} else {
+			tcr |= DW_UART_TCR_XFER_MODE_DE_OR_RE;
+		}
 		dw8250_writel_ext(p, DW_UART_DE_EN, 1);
 		dw8250_writel_ext(p, DW_UART_RE_EN, 1);
 	} else {
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 3/7] serial: 8250_dwlib: Implement SW half duplex support
  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-02  9:56 ` [PATCH 2/7] serial: 8250_dwlib: RS485 HW full " Ilpo Järvinen
@ 2022-03-02  9:56 ` Ilpo Järvinen
  2022-03-06 19:21   ` Lukas Wunner
  2022-03-02  9:56 ` [PATCH 4/7] dt_bindings: snps-dw-apb-uart: Add RS485 Ilpo Järvinen
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 48+ messages in thread
From: Ilpo Järvinen @ 2022-03-02  9:56 UTC (permalink / raw)
  To: linux-serial, Jiri Slaby, Greg Kroah-Hartman
  Cc: linux-kernel, Lukas Wunner, Johan Hovold, Andy Shevchenko,
	Heikki Krogerus, Ilpo Järvinen, Eric Tremblay,
	Uwe Kleine-König

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


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 4/7] dt_bindings: snps-dw-apb-uart: Add RS485
  2022-03-02  9:55 [PATCH 0/7] Add RS485 support to DW UART Ilpo Järvinen
                   ` (2 preceding siblings ...)
  2022-03-02  9:56 ` [RFC PATCH 3/7] serial: 8250_dwlib: Implement SW half " Ilpo Järvinen
@ 2022-03-02  9:56 ` Ilpo Järvinen
  2022-03-02 17:47   ` Rob Herring
  2022-03-02  9:56   ` Ilpo Järvinen
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 48+ messages in thread
From: Ilpo Järvinen @ 2022-03-02  9:56 UTC (permalink / raw)
  To: linux-serial, Jiri Slaby, Greg Kroah-Hartman
  Cc: linux-kernel, Lukas Wunner, Johan Hovold, Andy Shevchenko,
	Heikki Krogerus, Ilpo Järvinen, Rob Herring, devicetree

Add RS485 enable & line polarity properties.

Cc: Rob Herring <robh+dt@kernel.org>
Cc: devicetree@vger.kernel.org
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 .../bindings/serial/snps-dw-apb-uart.yaml       | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
index 12137fe80acf..8d440afabb1f 100644
--- a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
+++ b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
@@ -103,6 +103,23 @@ properties:
       register. Define this if your serial port does not use this pin.
     type: boolean
 
+  snps,rs485-interface-en:
+    description: Use true RS-485 DE and RE signals (in contrast to RS-485
+      emulation using RTS). Requires IP version 4 or above.
+    type: boolean
+
+  snps,de-active-high:
+    description: Defines the polarity of driver enable (DE_EN) signal.
+      Meaningful only with snps,rs485-interface-en. True indicates active
+      high.
+    type: boolean
+
+  snps,re-active-high:
+    description: Defines the polarity of receiver enable (RE_EN) signal.
+      Meaningful only with snps,rs485-interface-en. True indicates active
+      high.
+    type: boolean
+
 required:
   - compatible
   - reg
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 5/7] serial: termbits: ADDRB to indicate 9th bit addressing mode
  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-02  9:56   ` Ilpo Järvinen
  2022-03-02  9:56 ` [RFC PATCH 3/7] serial: 8250_dwlib: Implement SW half " Ilpo Järvinen
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 48+ messages in thread
From: Ilpo Järvinen @ 2022-03-02  9:56 UTC (permalink / raw)
  To: linux-serial, Jiri Slaby, Greg Kroah-Hartman
  Cc: linux-kernel, Lukas Wunner, Johan Hovold, Andy Shevchenko,
	Heikki Krogerus, Ilpo Järvinen, linux-api,
	Richard Henderson, Ivan Kokshaysky, Matt Turner, linux-alpha,
	Thomas Bogendoerfer, linux-mips, James E.J. Bottomley,
	Helge Deller, linux-parisc, Michael Ellerman,
	Benjamin Herrenschmidt, Paul Mackerras, linuxppc-dev,
	David S. Miller, sparclinux, Arnd Bergmann, linux-arch,
	linux-usb

Add ADDRB to termbits to indicate 9th bit addressing mode.
This change is necessary for supporting devices with RS485
multipoint addressing [*]. A later patch in the patch series
adds support for Synopsys Designware UART capable for 9th bit
addressing mode. In this mode, 9th bit is used to indicate an
address (byte) within the communication line. The 9th bit
addressing mode is selected using ADDRB introduced by an earlier
patch.

[*] Technically, RS485 is just an electronic spec and does not
itself specify the 9th bit addressing mode but 9th bit seems
at least "semi-standard" way to do addressing with RS485.

Cc: linux-api@vger.kernel.org
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Matt Turner <mattst88@gmail.com>
Cc: linux-alpha@vger.kernel.org
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: linux-mips@vger.kernel.org
Cc: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
Cc: Helge Deller <deller@gmx.de>
Cc: linux-parisc@vger.kernel.org
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: "David S. Miller" <davem@davemloft.net>
Cc: sparclinux@vger.kernel.org
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: linux-arch@vger.kernel.org
Cc: linux-usb@vger.kernel.org
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 arch/alpha/include/uapi/asm/termbits.h   | 1 +
 arch/mips/include/uapi/asm/termbits.h    | 1 +
 arch/parisc/include/uapi/asm/termbits.h  | 1 +
 arch/powerpc/include/uapi/asm/termbits.h | 1 +
 arch/sparc/include/uapi/asm/termbits.h   | 1 +
 drivers/tty/amiserial.c                  | 6 +++++-
 drivers/tty/moxa.c                       | 1 +
 drivers/tty/mxser.c                      | 1 +
 drivers/tty/serial/serial_core.c         | 2 ++
 drivers/tty/tty_ioctl.c                  | 2 ++
 drivers/usb/serial/usb-serial.c          | 5 +++--
 include/uapi/asm-generic/termbits.h      | 1 +
 12 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/arch/alpha/include/uapi/asm/termbits.h b/arch/alpha/include/uapi/asm/termbits.h
index 4575ba34a0ea..285169c794ec 100644
--- a/arch/alpha/include/uapi/asm/termbits.h
+++ b/arch/alpha/include/uapi/asm/termbits.h
@@ -180,6 +180,7 @@ struct ktermios {
 #define HUPCL	00040000
 
 #define CLOCAL	00100000
+#define ADDRB	010000000		/* address bit */
 #define CMSPAR	  010000000000		/* mark or space (stick) parity */
 #define CRTSCTS	  020000000000		/* flow control */
 
diff --git a/arch/mips/include/uapi/asm/termbits.h b/arch/mips/include/uapi/asm/termbits.h
index dfeffba729b7..e7ea31cfec78 100644
--- a/arch/mips/include/uapi/asm/termbits.h
+++ b/arch/mips/include/uapi/asm/termbits.h
@@ -181,6 +181,7 @@ struct ktermios {
 #define	 B3000000 0010015
 #define	 B3500000 0010016
 #define	 B4000000 0010017
+#define ADDRB	  0020000	/* address bit */
 #define CIBAUD	  002003600000	/* input baud rate */
 #define CMSPAR	  010000000000	/* mark or space (stick) parity */
 #define CRTSCTS	  020000000000	/* flow control */
diff --git a/arch/parisc/include/uapi/asm/termbits.h b/arch/parisc/include/uapi/asm/termbits.h
index 40e920f8d683..629be061f5d5 100644
--- a/arch/parisc/include/uapi/asm/termbits.h
+++ b/arch/parisc/include/uapi/asm/termbits.h
@@ -158,6 +158,7 @@ struct ktermios {
 #define  B3000000 0010015
 #define  B3500000 0010016
 #define  B4000000 0010017
+#define ADDRB	  0020000		/* address bit */
 #define CIBAUD    002003600000		/* input baud rate */
 #define CMSPAR    010000000000          /* mark or space (stick) parity */
 #define CRTSCTS   020000000000          /* flow control */
diff --git a/arch/powerpc/include/uapi/asm/termbits.h b/arch/powerpc/include/uapi/asm/termbits.h
index ed18bc61f63d..1b778ac562a4 100644
--- a/arch/powerpc/include/uapi/asm/termbits.h
+++ b/arch/powerpc/include/uapi/asm/termbits.h
@@ -171,6 +171,7 @@ struct ktermios {
 #define HUPCL	00040000
 
 #define CLOCAL	00100000
+#define ADDRB	00200000		/* address bit */
 #define CMSPAR	  010000000000		/* mark or space (stick) parity */
 #define CRTSCTS	  020000000000		/* flow control */
 
diff --git a/arch/sparc/include/uapi/asm/termbits.h b/arch/sparc/include/uapi/asm/termbits.h
index ce5ad5d0f105..4ad60c4acf65 100644
--- a/arch/sparc/include/uapi/asm/termbits.h
+++ b/arch/sparc/include/uapi/asm/termbits.h
@@ -200,6 +200,7 @@ struct ktermios {
 #define B3000000  0x00001011
 #define B3500000  0x00001012
 #define B4000000  0x00001013  */
+#define ADDRB	  0x00002000  /* address bit */
 #define CIBAUD	  0x100f0000  /* input baud rate (not used) */
 #define CMSPAR	  0x40000000  /* mark or space (stick) parity */
 #define CRTSCTS	  0x80000000  /* flow control */
diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c
index 533d02b38e02..3ca97007bd6e 100644
--- a/drivers/tty/amiserial.c
+++ b/drivers/tty/amiserial.c
@@ -1175,7 +1175,11 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
 	struct serial_state *info = tty->driver_data;
 	unsigned long flags;
-	unsigned int cflag = tty->termios.c_cflag;
+	unsigned int cflag;
+
+	tty->termios.c_cflag &= ~ADDRB;
+
+	cflag = tty->termios.c_cflag;
 
 	change_speed(tty, info, old_termios);
 
diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c
index f3c72ab1476c..07cd88152d58 100644
--- a/drivers/tty/moxa.c
+++ b/drivers/tty/moxa.c
@@ -2050,6 +2050,7 @@ static int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio,
 
 	ofsAddr = port->tableAddr;
 
+	termio->c_cflag &= ~ADDRB;
 	mode = termio->c_cflag & CSIZE;
 	if (mode == CS5)
 		mode = MX_CS5;
diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c
index 836c9eca2946..220676363a07 100644
--- a/drivers/tty/mxser.c
+++ b/drivers/tty/mxser.c
@@ -577,6 +577,7 @@ static void mxser_change_speed(struct tty_struct *tty, struct ktermios *old_term
 	struct mxser_port *info = tty->driver_data;
 	unsigned cflag, cval;
 
+	tty->termios.c_cflag &= ~ADDRB;
 	cflag = tty->termios.c_cflag;
 
 	if (mxser_set_baud(tty, tty_get_baud_rate(tty))) {
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 846192a7b4bf..8ab88293c917 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -1489,6 +1489,8 @@ static void uart_set_termios(struct tty_struct *tty,
 		goto out;
 	}
 
+	tty->termios.c_cflag &= ~ADDRB;
+
 	uart_change_speed(tty, state, old_termios);
 	/* reload cflag from termios; port driver may have overridden flags */
 	cflag = tty->termios.c_cflag;
diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c
index 63181925ec1a..934037d78868 100644
--- a/drivers/tty/tty_ioctl.c
+++ b/drivers/tty/tty_ioctl.c
@@ -319,6 +319,8 @@ unsigned char tty_get_frame_size(unsigned int cflag)
 		bits++;
 	if (cflag & PARENB)
 		bits++;
+	if (cflag & ADDRB)
+		bits++;
 
 	return bits;
 }
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 24101bd7fcad..44b73aea80bb 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -525,9 +525,10 @@ static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)
 
 	dev_dbg(&port->dev, "%s\n", __func__);
 
-	if (port->serial->type->set_termios)
+	if (port->serial->type->set_termios) {
+		tty->termios.c_cflag &= ~ADDRB;
 		port->serial->type->set_termios(tty, port, old);
-	else
+	} else
 		tty_termios_copy_hw(&tty->termios, old);
 }
 
diff --git a/include/uapi/asm-generic/termbits.h b/include/uapi/asm-generic/termbits.h
index 2fbaf9ae89dd..5f5228329d45 100644
--- a/include/uapi/asm-generic/termbits.h
+++ b/include/uapi/asm-generic/termbits.h
@@ -157,6 +157,7 @@ struct ktermios {
 #define  B3000000 0010015
 #define  B3500000 0010016
 #define  B4000000 0010017
+#define ADDRB     0020000	/* address bit */
 #define CIBAUD	  002003600000	/* input baud rate */
 #define CMSPAR	  010000000000	/* mark or space (stick) parity */
 #define CRTSCTS	  020000000000	/* flow control */
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 5/7] serial: termbits: ADDRB to indicate 9th bit addressing mode
@ 2022-03-02  9:56   ` Ilpo Järvinen
  0 siblings, 0 replies; 48+ messages in thread
From: Ilpo Järvinen @ 2022-03-02  9:56 UTC (permalink / raw)
  To: linux-serial, Jiri Slaby, Greg Kroah-Hartman
  Cc: Heikki Krogerus, linux-kernel, James E.J. Bottomley,
	Paul Mackerras, sparclinux, linux-arch, Helge Deller,
	Ilpo Järvinen, Matt Turner, Arnd Bergmann, Johan Hovold,
	Ivan Kokshaysky, Andy Shevchenko, Richard Henderson,
	Thomas Bogendoerfer, linux-parisc, linux-api, linux-usb,
	linux-mips, Lukas Wunner, linux-alpha, linuxppc-dev,
	David S. Miller

Add ADDRB to termbits to indicate 9th bit addressing mode.
This change is necessary for supporting devices with RS485
multipoint addressing [*]. A later patch in the patch series
adds support for Synopsys Designware UART capable for 9th bit
addressing mode. In this mode, 9th bit is used to indicate an
address (byte) within the communication line. The 9th bit
addressing mode is selected using ADDRB introduced by an earlier
patch.

[*] Technically, RS485 is just an electronic spec and does not
itself specify the 9th bit addressing mode but 9th bit seems
at least "semi-standard" way to do addressing with RS485.

Cc: linux-api@vger.kernel.org
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Matt Turner <mattst88@gmail.com>
Cc: linux-alpha@vger.kernel.org
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: linux-mips@vger.kernel.org
Cc: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
Cc: Helge Deller <deller@gmx.de>
Cc: linux-parisc@vger.kernel.org
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: "David S. Miller" <davem@davemloft.net>
Cc: sparclinux@vger.kernel.org
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: linux-arch@vger.kernel.org
Cc: linux-usb@vger.kernel.org
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 arch/alpha/include/uapi/asm/termbits.h   | 1 +
 arch/mips/include/uapi/asm/termbits.h    | 1 +
 arch/parisc/include/uapi/asm/termbits.h  | 1 +
 arch/powerpc/include/uapi/asm/termbits.h | 1 +
 arch/sparc/include/uapi/asm/termbits.h   | 1 +
 drivers/tty/amiserial.c                  | 6 +++++-
 drivers/tty/moxa.c                       | 1 +
 drivers/tty/mxser.c                      | 1 +
 drivers/tty/serial/serial_core.c         | 2 ++
 drivers/tty/tty_ioctl.c                  | 2 ++
 drivers/usb/serial/usb-serial.c          | 5 +++--
 include/uapi/asm-generic/termbits.h      | 1 +
 12 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/arch/alpha/include/uapi/asm/termbits.h b/arch/alpha/include/uapi/asm/termbits.h
index 4575ba34a0ea..285169c794ec 100644
--- a/arch/alpha/include/uapi/asm/termbits.h
+++ b/arch/alpha/include/uapi/asm/termbits.h
@@ -180,6 +180,7 @@ struct ktermios {
 #define HUPCL	00040000
 
 #define CLOCAL	00100000
+#define ADDRB	010000000		/* address bit */
 #define CMSPAR	  010000000000		/* mark or space (stick) parity */
 #define CRTSCTS	  020000000000		/* flow control */
 
diff --git a/arch/mips/include/uapi/asm/termbits.h b/arch/mips/include/uapi/asm/termbits.h
index dfeffba729b7..e7ea31cfec78 100644
--- a/arch/mips/include/uapi/asm/termbits.h
+++ b/arch/mips/include/uapi/asm/termbits.h
@@ -181,6 +181,7 @@ struct ktermios {
 #define	 B3000000 0010015
 #define	 B3500000 0010016
 #define	 B4000000 0010017
+#define ADDRB	  0020000	/* address bit */
 #define CIBAUD	  002003600000	/* input baud rate */
 #define CMSPAR	  010000000000	/* mark or space (stick) parity */
 #define CRTSCTS	  020000000000	/* flow control */
diff --git a/arch/parisc/include/uapi/asm/termbits.h b/arch/parisc/include/uapi/asm/termbits.h
index 40e920f8d683..629be061f5d5 100644
--- a/arch/parisc/include/uapi/asm/termbits.h
+++ b/arch/parisc/include/uapi/asm/termbits.h
@@ -158,6 +158,7 @@ struct ktermios {
 #define  B3000000 0010015
 #define  B3500000 0010016
 #define  B4000000 0010017
+#define ADDRB	  0020000		/* address bit */
 #define CIBAUD    002003600000		/* input baud rate */
 #define CMSPAR    010000000000          /* mark or space (stick) parity */
 #define CRTSCTS   020000000000          /* flow control */
diff --git a/arch/powerpc/include/uapi/asm/termbits.h b/arch/powerpc/include/uapi/asm/termbits.h
index ed18bc61f63d..1b778ac562a4 100644
--- a/arch/powerpc/include/uapi/asm/termbits.h
+++ b/arch/powerpc/include/uapi/asm/termbits.h
@@ -171,6 +171,7 @@ struct ktermios {
 #define HUPCL	00040000
 
 #define CLOCAL	00100000
+#define ADDRB	00200000		/* address bit */
 #define CMSPAR	  010000000000		/* mark or space (stick) parity */
 #define CRTSCTS	  020000000000		/* flow control */
 
diff --git a/arch/sparc/include/uapi/asm/termbits.h b/arch/sparc/include/uapi/asm/termbits.h
index ce5ad5d0f105..4ad60c4acf65 100644
--- a/arch/sparc/include/uapi/asm/termbits.h
+++ b/arch/sparc/include/uapi/asm/termbits.h
@@ -200,6 +200,7 @@ struct ktermios {
 #define B3000000  0x00001011
 #define B3500000  0x00001012
 #define B4000000  0x00001013  */
+#define ADDRB	  0x00002000  /* address bit */
 #define CIBAUD	  0x100f0000  /* input baud rate (not used) */
 #define CMSPAR	  0x40000000  /* mark or space (stick) parity */
 #define CRTSCTS	  0x80000000  /* flow control */
diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c
index 533d02b38e02..3ca97007bd6e 100644
--- a/drivers/tty/amiserial.c
+++ b/drivers/tty/amiserial.c
@@ -1175,7 +1175,11 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
 	struct serial_state *info = tty->driver_data;
 	unsigned long flags;
-	unsigned int cflag = tty->termios.c_cflag;
+	unsigned int cflag;
+
+	tty->termios.c_cflag &= ~ADDRB;
+
+	cflag = tty->termios.c_cflag;
 
 	change_speed(tty, info, old_termios);
 
diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c
index f3c72ab1476c..07cd88152d58 100644
--- a/drivers/tty/moxa.c
+++ b/drivers/tty/moxa.c
@@ -2050,6 +2050,7 @@ static int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio,
 
 	ofsAddr = port->tableAddr;
 
+	termio->c_cflag &= ~ADDRB;
 	mode = termio->c_cflag & CSIZE;
 	if (mode == CS5)
 		mode = MX_CS5;
diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c
index 836c9eca2946..220676363a07 100644
--- a/drivers/tty/mxser.c
+++ b/drivers/tty/mxser.c
@@ -577,6 +577,7 @@ static void mxser_change_speed(struct tty_struct *tty, struct ktermios *old_term
 	struct mxser_port *info = tty->driver_data;
 	unsigned cflag, cval;
 
+	tty->termios.c_cflag &= ~ADDRB;
 	cflag = tty->termios.c_cflag;
 
 	if (mxser_set_baud(tty, tty_get_baud_rate(tty))) {
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 846192a7b4bf..8ab88293c917 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -1489,6 +1489,8 @@ static void uart_set_termios(struct tty_struct *tty,
 		goto out;
 	}
 
+	tty->termios.c_cflag &= ~ADDRB;
+
 	uart_change_speed(tty, state, old_termios);
 	/* reload cflag from termios; port driver may have overridden flags */
 	cflag = tty->termios.c_cflag;
diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c
index 63181925ec1a..934037d78868 100644
--- a/drivers/tty/tty_ioctl.c
+++ b/drivers/tty/tty_ioctl.c
@@ -319,6 +319,8 @@ unsigned char tty_get_frame_size(unsigned int cflag)
 		bits++;
 	if (cflag & PARENB)
 		bits++;
+	if (cflag & ADDRB)
+		bits++;
 
 	return bits;
 }
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 24101bd7fcad..44b73aea80bb 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -525,9 +525,10 @@ static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)
 
 	dev_dbg(&port->dev, "%s\n", __func__);
 
-	if (port->serial->type->set_termios)
+	if (port->serial->type->set_termios) {
+		tty->termios.c_cflag &= ~ADDRB;
 		port->serial->type->set_termios(tty, port, old);
-	else
+	} else
 		tty_termios_copy_hw(&tty->termios, old);
 }
 
diff --git a/include/uapi/asm-generic/termbits.h b/include/uapi/asm-generic/termbits.h
index 2fbaf9ae89dd..5f5228329d45 100644
--- a/include/uapi/asm-generic/termbits.h
+++ b/include/uapi/asm-generic/termbits.h
@@ -157,6 +157,7 @@ struct ktermios {
 #define  B3000000 0010015
 #define  B3500000 0010016
 #define  B4000000 0010017
+#define ADDRB     0020000	/* address bit */
 #define CIBAUD	  002003600000	/* input baud rate */
 #define CMSPAR	  010000000000	/* mark or space (stick) parity */
 #define CRTSCTS	  020000000000	/* flow control */
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 5/7] serial: termbits: ADDRB to indicate 9th bit addressing mode
@ 2022-03-02  9:56   ` Ilpo Järvinen
  0 siblings, 0 replies; 48+ messages in thread
From: Ilpo Järvinen @ 2022-03-02  9:56 UTC (permalink / raw)
  To: linux-serial, Jiri Slaby, Greg Kroah-Hartman
  Cc: linux-kernel, Lukas Wunner, Johan Hovold, Andy Shevchenko,
	Heikki Krogerus, Ilpo Järvinen, linux-api,
	Richard Henderson, Ivan Kokshaysky, Matt Turner, linux-alpha,
	Thomas Bogendoerfer, linux-mips, James E.J. Bottomley,
	Helge Deller, linux-parisc, Michael Ellerman,
	Benjamin Herrenschmidt, Paul Mackerras, linuxppc-dev

Add ADDRB to termbits to indicate 9th bit addressing mode.
This change is necessary for supporting devices with RS485
multipoint addressing [*]. A later patch in the patch series
adds support for Synopsys Designware UART capable for 9th bit
addressing mode. In this mode, 9th bit is used to indicate an
address (byte) within the communication line. The 9th bit
addressing mode is selected using ADDRB introduced by an earlier
patch.

[*] Technically, RS485 is just an electronic spec and does not
itself specify the 9th bit addressing mode but 9th bit seems
at least "semi-standard" way to do addressing with RS485.

Cc: linux-api@vger.kernel.org
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Matt Turner <mattst88@gmail.com>
Cc: linux-alpha@vger.kernel.org
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: linux-mips@vger.kernel.org
Cc: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
Cc: Helge Deller <deller@gmx.de>
Cc: linux-parisc@vger.kernel.org
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: "David S. Miller" <davem@davemloft.net>
Cc: sparclinux@vger.kernel.org
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: linux-arch@vger.kernel.org
Cc: linux-usb@vger.kernel.org
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 arch/alpha/include/uapi/asm/termbits.h   | 1 +
 arch/mips/include/uapi/asm/termbits.h    | 1 +
 arch/parisc/include/uapi/asm/termbits.h  | 1 +
 arch/powerpc/include/uapi/asm/termbits.h | 1 +
 arch/sparc/include/uapi/asm/termbits.h   | 1 +
 drivers/tty/amiserial.c                  | 6 +++++-
 drivers/tty/moxa.c                       | 1 +
 drivers/tty/mxser.c                      | 1 +
 drivers/tty/serial/serial_core.c         | 2 ++
 drivers/tty/tty_ioctl.c                  | 2 ++
 drivers/usb/serial/usb-serial.c          | 5 +++--
 include/uapi/asm-generic/termbits.h      | 1 +
 12 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/arch/alpha/include/uapi/asm/termbits.h b/arch/alpha/include/uapi/asm/termbits.h
index 4575ba34a0ea..285169c794ec 100644
--- a/arch/alpha/include/uapi/asm/termbits.h
+++ b/arch/alpha/include/uapi/asm/termbits.h
@@ -180,6 +180,7 @@ struct ktermios {
 #define HUPCL	00040000
 
 #define CLOCAL	00100000
+#define ADDRB	010000000		/* address bit */
 #define CMSPAR	  010000000000		/* mark or space (stick) parity */
 #define CRTSCTS	  020000000000		/* flow control */
 
diff --git a/arch/mips/include/uapi/asm/termbits.h b/arch/mips/include/uapi/asm/termbits.h
index dfeffba729b7..e7ea31cfec78 100644
--- a/arch/mips/include/uapi/asm/termbits.h
+++ b/arch/mips/include/uapi/asm/termbits.h
@@ -181,6 +181,7 @@ struct ktermios {
 #define	 B3000000 0010015
 #define	 B3500000 0010016
 #define	 B4000000 0010017
+#define ADDRB	  0020000	/* address bit */
 #define CIBAUD	  002003600000	/* input baud rate */
 #define CMSPAR	  010000000000	/* mark or space (stick) parity */
 #define CRTSCTS	  020000000000	/* flow control */
diff --git a/arch/parisc/include/uapi/asm/termbits.h b/arch/parisc/include/uapi/asm/termbits.h
index 40e920f8d683..629be061f5d5 100644
--- a/arch/parisc/include/uapi/asm/termbits.h
+++ b/arch/parisc/include/uapi/asm/termbits.h
@@ -158,6 +158,7 @@ struct ktermios {
 #define  B3000000 0010015
 #define  B3500000 0010016
 #define  B4000000 0010017
+#define ADDRB	  0020000		/* address bit */
 #define CIBAUD    002003600000		/* input baud rate */
 #define CMSPAR    010000000000          /* mark or space (stick) parity */
 #define CRTSCTS   020000000000          /* flow control */
diff --git a/arch/powerpc/include/uapi/asm/termbits.h b/arch/powerpc/include/uapi/asm/termbits.h
index ed18bc61f63d..1b778ac562a4 100644
--- a/arch/powerpc/include/uapi/asm/termbits.h
+++ b/arch/powerpc/include/uapi/asm/termbits.h
@@ -171,6 +171,7 @@ struct ktermios {
 #define HUPCL	00040000
 
 #define CLOCAL	00100000
+#define ADDRB	00200000		/* address bit */
 #define CMSPAR	  010000000000		/* mark or space (stick) parity */
 #define CRTSCTS	  020000000000		/* flow control */
 
diff --git a/arch/sparc/include/uapi/asm/termbits.h b/arch/sparc/include/uapi/asm/termbits.h
index ce5ad5d0f105..4ad60c4acf65 100644
--- a/arch/sparc/include/uapi/asm/termbits.h
+++ b/arch/sparc/include/uapi/asm/termbits.h
@@ -200,6 +200,7 @@ struct ktermios {
 #define B3000000  0x00001011
 #define B3500000  0x00001012
 #define B4000000  0x00001013  */
+#define ADDRB	  0x00002000  /* address bit */
 #define CIBAUD	  0x100f0000  /* input baud rate (not used) */
 #define CMSPAR	  0x40000000  /* mark or space (stick) parity */
 #define CRTSCTS	  0x80000000  /* flow control */
diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c
index 533d02b38e02..3ca97007bd6e 100644
--- a/drivers/tty/amiserial.c
+++ b/drivers/tty/amiserial.c
@@ -1175,7 +1175,11 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
 	struct serial_state *info = tty->driver_data;
 	unsigned long flags;
-	unsigned int cflag = tty->termios.c_cflag;
+	unsigned int cflag;
+
+	tty->termios.c_cflag &= ~ADDRB;
+
+	cflag = tty->termios.c_cflag;
 
 	change_speed(tty, info, old_termios);
 
diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c
index f3c72ab1476c..07cd88152d58 100644
--- a/drivers/tty/moxa.c
+++ b/drivers/tty/moxa.c
@@ -2050,6 +2050,7 @@ static int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio,
 
 	ofsAddr = port->tableAddr;
 
+	termio->c_cflag &= ~ADDRB;
 	mode = termio->c_cflag & CSIZE;
 	if (mode == CS5)
 		mode = MX_CS5;
diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c
index 836c9eca2946..220676363a07 100644
--- a/drivers/tty/mxser.c
+++ b/drivers/tty/mxser.c
@@ -577,6 +577,7 @@ static void mxser_change_speed(struct tty_struct *tty, struct ktermios *old_term
 	struct mxser_port *info = tty->driver_data;
 	unsigned cflag, cval;
 
+	tty->termios.c_cflag &= ~ADDRB;
 	cflag = tty->termios.c_cflag;
 
 	if (mxser_set_baud(tty, tty_get_baud_rate(tty))) {
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 846192a7b4bf..8ab88293c917 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -1489,6 +1489,8 @@ static void uart_set_termios(struct tty_struct *tty,
 		goto out;
 	}
 
+	tty->termios.c_cflag &= ~ADDRB;
+
 	uart_change_speed(tty, state, old_termios);
 	/* reload cflag from termios; port driver may have overridden flags */
 	cflag = tty->termios.c_cflag;
diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c
index 63181925ec1a..934037d78868 100644
--- a/drivers/tty/tty_ioctl.c
+++ b/drivers/tty/tty_ioctl.c
@@ -319,6 +319,8 @@ unsigned char tty_get_frame_size(unsigned int cflag)
 		bits++;
 	if (cflag & PARENB)
 		bits++;
+	if (cflag & ADDRB)
+		bits++;
 
 	return bits;
 }
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 24101bd7fcad..44b73aea80bb 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -525,9 +525,10 @@ static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)
 
 	dev_dbg(&port->dev, "%s\n", __func__);
 
-	if (port->serial->type->set_termios)
+	if (port->serial->type->set_termios) {
+		tty->termios.c_cflag &= ~ADDRB;
 		port->serial->type->set_termios(tty, port, old);
-	else
+	} else
 		tty_termios_copy_hw(&tty->termios, old);
 }
 
diff --git a/include/uapi/asm-generic/termbits.h b/include/uapi/asm-generic/termbits.h
index 2fbaf9ae89dd..5f5228329d45 100644
--- a/include/uapi/asm-generic/termbits.h
+++ b/include/uapi/asm-generic/termbits.h
@@ -157,6 +157,7 @@ struct ktermios {
 #define  B3000000 0010015
 #define  B3500000 0010016
 #define  B4000000 0010017
+#define ADDRB     0020000	/* address bit */
 #define CIBAUD	  002003600000	/* input baud rate */
 #define CMSPAR	  010000000000	/* mark or space (stick) parity */
 #define CRTSCTS	  020000000000	/* flow control */
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 6/7] serial: General support for multipoint addresses
  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-02  9:56   ` Ilpo Järvinen
  2022-03-02  9:56 ` [RFC PATCH 3/7] serial: 8250_dwlib: Implement SW half " Ilpo Järvinen
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 48+ messages in thread
From: Ilpo Järvinen @ 2022-03-02  9:56 UTC (permalink / raw)
  To: linux-serial, Jiri Slaby, Greg Kroah-Hartman
  Cc: linux-kernel, Lukas Wunner, Johan Hovold, Andy Shevchenko,
	Heikki Krogerus, Ilpo Järvinen, linux-api,
	Richard Henderson, Ivan Kokshaysky, Matt Turner, linux-alpha,
	Thomas Bogendoerfer, linux-mips, James E.J. Bottomley,
	Helge Deller, linux-parisc, Michael Ellerman,
	Benjamin Herrenschmidt, Paul Mackerras, linuxppc-dev,
	Yoshinori Sato, Rich Felker, linux-sh, David S. Miller,
	sparclinux, Chris Zankel, Max Filippov, linux-xtensa,
	Arnd Bergmann, linux-arch, linux-doc

This patch adds generic support for serial multipoint
addressing. Two new ioctls are added. TIOCSADDR is used to
indicate the destination/receive address. TIOCGADDR returns
the current address in use. The driver should implement
set_addr and get_addr to support addressing mode.

Adjust ADDRB clearing to happen only if driver does not provide
set_addr (=the driver doesn't support address mode).

This change is necessary for supporting devices with RS485
multipoint addressing [*]. A following patch in the patch series
adds support for Synopsys Designware UART capable for 9th bit
addressing mode. In this mode, 9th bit is used to indicate an
address (byte) within the communication line. The 9th bit
addressing mode is selected using ADDRB introduced by the
previous patch.

Transmit addresses / receiver filter are specified by setting
the flags SER_ADDR_DEST and/or SER_ADDR_RECV. When the user
supplies the transmit address, in the 9bit addressing mode it is
sent out immediately with the 9th bit set to 1. After that, the
subsequent normal data bytes are sent with 9th bit as 0 and they
are intended to the device with the given address. It is up to
receiver to enforce the filter using SER_ADDR_RECV. When userspace
has supplied the receive address, the driver is expected to handle
the matching of the address and only data with that address is
forwarded to the user. Both SER_ADDR_DEST and SER_ADDR_RECV can
be given at the same time in a single call if the addresses are
the same.

The user can clear the receive filter with SER_ADDR_RECV_CLEAR.

[*] Technically, RS485 is just an electronic spec and does not
itself specify the 9th bit addressing mode but 9th bit seems
at least "semi-standard" way to do addressing with RS485.

Cc: linux-api@vger.kernel.org
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Matt Turner <mattst88@gmail.com>
Cc: linux-alpha@vger.kernel.org
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: linux-mips@vger.kernel.org
Cc: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
Cc: Helge Deller <deller@gmx.de>
Cc: linux-parisc@vger.kernel.org
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
Cc: Rich Felker <dalias@libc.org>
Cc: linux-sh@vger.kernel.org
Cc: "David S. Miller" <davem@davemloft.net>
Cc: sparclinux@vger.kernel.org
Cc: Chris Zankel <chris@zankel.net>
Cc: Max Filippov <jcmvbkbc@gmail.com>
Cc: linux-xtensa@linux-xtensa.org
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: linux-arch@vger.kernel.org
Cc: linux-doc@vger.kernel.org
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 .../driver-api/serial/serial-rs485.rst        | 23 ++++++-
 arch/alpha/include/uapi/asm/ioctls.h          |  3 +
 arch/mips/include/uapi/asm/ioctls.h           |  3 +
 arch/parisc/include/uapi/asm/ioctls.h         |  3 +
 arch/powerpc/include/uapi/asm/ioctls.h        |  3 +
 arch/sh/include/uapi/asm/ioctls.h             |  3 +
 arch/sparc/include/uapi/asm/ioctls.h          |  3 +
 arch/xtensa/include/uapi/asm/ioctls.h         |  3 +
 drivers/tty/serial/8250/8250_core.c           |  2 +
 drivers/tty/serial/serial_core.c              | 62 ++++++++++++++++++-
 include/linux/serial_core.h                   |  6 ++
 include/uapi/asm-generic/ioctls.h             |  3 +
 include/uapi/linux/serial.h                   |  8 +++
 13 files changed, 123 insertions(+), 2 deletions(-)

diff --git a/Documentation/driver-api/serial/serial-rs485.rst b/Documentation/driver-api/serial/serial-rs485.rst
index 6bc824f948f9..2f45f007fa5b 100644
--- a/Documentation/driver-api/serial/serial-rs485.rst
+++ b/Documentation/driver-api/serial/serial-rs485.rst
@@ -95,7 +95,28 @@ RS485 Serial Communications
 		/* Error handling. See errno. */
 	}
 
-5. References
+5. Multipoint Addressing
+========================
+
+   The Linux kernel provides serial_addr structure to handle addressing within
+   multipoint serial communications line such as RS485. 9th bit addressiong mode
+   is enabled by adding ADDRB flag in termios c_cflag.
+
+   Serial core calls device specific set/get_addr in response to TIOCSADDR and
+   TIOCGADDR ioctls with a pointer to serial_addr. Destination and receive
+   address can be specified using serial_addr flags field. Receive address may
+   also be cleared using flags. Once an address is set, the communication
+   can occur only with the particular device and other peers are filtered out.
+   It is left up to the receiver side to enforce the filtering.
+
+   Address flags:
+	- SER_ADDR_RECV: Receive (filter) address.
+	- SER_ADDR_RECV_CLEAR: Clear receive filter (only for TIOCSADDR).
+	- SER_ADDR_DEST: Destination address.
+
+   Note: not all devices supporting RS485 support multipoint addressing.
+
+6. References
 =============
 
  [1]	include/uapi/linux/serial.h
diff --git a/arch/alpha/include/uapi/asm/ioctls.h b/arch/alpha/include/uapi/asm/ioctls.h
index 971311605288..500cab3e1d6b 100644
--- a/arch/alpha/include/uapi/asm/ioctls.h
+++ b/arch/alpha/include/uapi/asm/ioctls.h
@@ -125,4 +125,7 @@
 #define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
 #define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
 
+#define TIOCSADDR	_IOWR('T', 0x63, struct serial_addr)
+#define TIOCGADDR	_IOWR('T', 0x64, struct serial_addr)
+
 #endif /* _ASM_ALPHA_IOCTLS_H */
diff --git a/arch/mips/include/uapi/asm/ioctls.h b/arch/mips/include/uapi/asm/ioctls.h
index 16aa8a766aec..3859dc46857e 100644
--- a/arch/mips/include/uapi/asm/ioctls.h
+++ b/arch/mips/include/uapi/asm/ioctls.h
@@ -96,6 +96,9 @@
 #define TIOCGISO7816	_IOR('T', 0x42, struct serial_iso7816)
 #define TIOCSISO7816	_IOWR('T', 0x43, struct serial_iso7816)
 
+#define TIOCSADDR	_IOWR('T', 0x63, struct serial_addr)
+#define TIOCGADDR	_IOWR('T', 0x64, struct serial_addr)
+
 /* I hope the range from 0x5480 on is free ... */
 #define TIOCSCTTY	0x5480		/* become controlling tty */
 #define TIOCGSOFTCAR	0x5481
diff --git a/arch/parisc/include/uapi/asm/ioctls.h b/arch/parisc/include/uapi/asm/ioctls.h
index 82d1148c6379..62337743db64 100644
--- a/arch/parisc/include/uapi/asm/ioctls.h
+++ b/arch/parisc/include/uapi/asm/ioctls.h
@@ -86,6 +86,9 @@
 #define TIOCSTOP	0x5462
 #define TIOCSLTC	0x5462
 
+#define TIOCSADDR	_IOWR('T', 0x63, struct serial_addr)
+#define TIOCGADDR	_IOWR('T', 0x64, struct serial_addr)
+
 /* Used for packet mode */
 #define TIOCPKT_DATA		 0
 #define TIOCPKT_FLUSHREAD	 1
diff --git a/arch/powerpc/include/uapi/asm/ioctls.h b/arch/powerpc/include/uapi/asm/ioctls.h
index 2c145da3b774..84fd69ac366a 100644
--- a/arch/powerpc/include/uapi/asm/ioctls.h
+++ b/arch/powerpc/include/uapi/asm/ioctls.h
@@ -120,4 +120,7 @@
 #define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
 #define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
 
+#define TIOCSADDR	_IOWR('T', 0x63, struct serial_addr)
+#define TIOCGADDR	_IOWR('T', 0x64, struct serial_addr)
+
 #endif	/* _ASM_POWERPC_IOCTLS_H */
diff --git a/arch/sh/include/uapi/asm/ioctls.h b/arch/sh/include/uapi/asm/ioctls.h
index 11866d4f60e1..f82966b7dba2 100644
--- a/arch/sh/include/uapi/asm/ioctls.h
+++ b/arch/sh/include/uapi/asm/ioctls.h
@@ -113,4 +113,7 @@
 #define TIOCMIWAIT	_IO('T', 92) /* 0x545C */	/* wait for a change on serial input line(s) */
 #define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
 
+#define TIOCSADDR	_IOWR('T', 0x63, struct serial_addr)
+#define TIOCGADDR	_IOWR('T', 0x64, struct serial_addr)
+
 #endif /* __ASM_SH_IOCTLS_H */
diff --git a/arch/sparc/include/uapi/asm/ioctls.h b/arch/sparc/include/uapi/asm/ioctls.h
index 7fd2f5873c9e..e44624c67c79 100644
--- a/arch/sparc/include/uapi/asm/ioctls.h
+++ b/arch/sparc/include/uapi/asm/ioctls.h
@@ -125,6 +125,9 @@
 #define TIOCMIWAIT	0x545C /* Wait for change on serial input line(s) */
 #define TIOCGICOUNT	0x545D /* Read serial port inline interrupt counts */
 
+#define TIOCSADDR	_IOWR('T', 0x63, struct serial_addr)
+#define TIOCGADDR	_IOWR('T', 0x64, struct serial_addr)
+
 /* Kernel definitions */
 
 /* Used for packet mode */
diff --git a/arch/xtensa/include/uapi/asm/ioctls.h b/arch/xtensa/include/uapi/asm/ioctls.h
index 6d4a87296c95..759ca9377f2a 100644
--- a/arch/xtensa/include/uapi/asm/ioctls.h
+++ b/arch/xtensa/include/uapi/asm/ioctls.h
@@ -127,4 +127,7 @@
 #define TIOCMIWAIT	_IO('T', 92) /* wait for a change on serial input line(s) */
 #define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
 
+#define TIOCSADDR	_IOWR('T', 0x63, struct serial_addr)
+#define TIOCGADDR	_IOWR('T', 0x64, struct serial_addr)
+
 #endif /* _XTENSA_IOCTLS_H */
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 01d30f6ed8fb..f67bc3b76f65 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -1008,6 +1008,8 @@ int serial8250_register_8250_port(const struct uart_8250_port *up)
 		uart->port.rs485	= up->port.rs485;
 		uart->rs485_start_tx	= up->rs485_start_tx;
 		uart->rs485_stop_tx	= up->rs485_stop_tx;
+		uart->port.set_addr	= up->port.set_addr;
+		uart->port.get_addr	= up->port.get_addr;
 		uart->dma		= up->dma;
 
 		/* Take tx_loadsz from fifosize if it wasn't set separately */
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 8ab88293c917..8235f696d073 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -1346,6 +1346,56 @@ static int uart_set_iso7816_config(struct uart_port *port,
 	return 0;
 }
 
+static int uart_set_addr(struct uart_port *port,
+			 struct serial_addr __user *serial_addr_user)
+{
+	struct serial_addr addr;
+	unsigned long flags;
+	int ret;
+
+	if (copy_from_user(&addr, serial_addr_user, sizeof(*serial_addr_user)))
+		return -EFAULT;
+
+	spin_lock_irqsave(&port->lock, flags);
+	if (port->set_addr)
+		ret = port->set_addr(port, &addr);
+	else
+		ret = -EINVAL;
+	spin_unlock_irqrestore(&port->lock, flags);
+	if (ret)
+		return ret;
+
+	if (copy_to_user(serial_addr_user, &addr, sizeof(addr)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int uart_get_addr(struct uart_port *port,
+			 struct serial_addr __user *serial_addr_user)
+{
+	struct serial_addr addr;
+	unsigned long flags;
+	int ret;
+
+	if (copy_from_user(&addr, serial_addr_user, sizeof(*serial_addr_user)))
+		return -EFAULT;
+
+	spin_lock_irqsave(&port->lock, flags);
+	if (port->get_addr)
+		ret = port->get_addr(port, &addr);
+	else
+		ret = -EINVAL;
+	spin_unlock_irqrestore(&port->lock, flags);
+	if (ret)
+		return ret;
+
+	if (copy_to_user(serial_addr_user, &addr, sizeof(addr)))
+		return -EFAULT;
+
+	return 0;
+}
+
 /*
  * Called via sys_ioctl.  We can use spin_lock_irq() here.
  */
@@ -1423,6 +1473,15 @@ uart_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
 	case TIOCGISO7816:
 		ret = uart_get_iso7816_config(state->uart_port, uarg);
 		break;
+
+	case TIOCSADDR:
+		ret = uart_set_addr(uport, uarg);
+		break;
+
+	case TIOCGADDR:
+		ret = uart_get_addr(uport, uarg);
+		break;
+
 	default:
 		if (uport->ops->ioctl)
 			ret = uport->ops->ioctl(uport, cmd, arg);
@@ -1489,7 +1548,8 @@ static void uart_set_termios(struct tty_struct *tty,
 		goto out;
 	}
 
-	tty->termios.c_cflag &= ~ADDRB;
+	if (!uport->set_addr)
+		tty->termios.c_cflag &= ~ADDRB;
 
 	uart_change_speed(tty, state, old_termios);
 	/* reload cflag from termios; port driver may have overridden flags */
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 31f7fe527395..ebe1d0ec11d8 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -135,6 +135,12 @@ struct uart_port {
 						struct serial_rs485 *rs485);
 	int			(*iso7816_config)(struct uart_port *,
 						  struct serial_iso7816 *iso7816);
+
+	int			(*set_addr)(struct uart_port *p,
+					    struct serial_addr *addr);
+	int			(*get_addr)(struct uart_port *p,
+					    struct serial_addr *addr);
+
 	unsigned int		irq;			/* irq number */
 	unsigned long		irqflags;		/* irq flags  */
 	unsigned int		uartclk;		/* base uart clock */
diff --git a/include/uapi/asm-generic/ioctls.h b/include/uapi/asm-generic/ioctls.h
index cdc9f4ca8c27..689743366091 100644
--- a/include/uapi/asm-generic/ioctls.h
+++ b/include/uapi/asm-generic/ioctls.h
@@ -106,6 +106,9 @@
 # define FIOQSIZE	0x5460
 #endif
 
+#define TIOCSADDR	_IOWR('T', 0x63, struct serial_addr)
+#define TIOCGADDR	_IOWR('T', 0x64, struct serial_addr)
+
 /* Used for packet mode */
 #define TIOCPKT_DATA		 0
 #define TIOCPKT_FLUSHREAD	 1
diff --git a/include/uapi/linux/serial.h b/include/uapi/linux/serial.h
index f868685b35a0..7b198fd5d390 100644
--- a/include/uapi/linux/serial.h
+++ b/include/uapi/linux/serial.h
@@ -151,4 +151,12 @@ struct serial_iso7816 {
 	__u32	reserved[5];
 };
 
+struct serial_addr {
+	__u32	flags;
+#define SER_ADDR_RECV			(1 << 0)
+#define SER_ADDR_RECV_CLEAR		(1 << 1)
+#define SER_ADDR_DEST			(1 << 2)
+	__u32	addr;
+};
+
 #endif /* _UAPI_LINUX_SERIAL_H */
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 6/7] serial: General support for multipoint addresses
@ 2022-03-02  9:56   ` Ilpo Järvinen
  0 siblings, 0 replies; 48+ messages in thread
From: Ilpo Järvinen @ 2022-03-02  9:56 UTC (permalink / raw)
  To: linux-serial, Jiri Slaby, Greg Kroah-Hartman
  Cc: Heikki Krogerus, linux-sh, linux-kernel, James E.J. Bottomley,
	Max Filippov, Rich Felker, Paul Mackerras, sparclinux,
	linux-arch, Yoshinori Sato, Helge Deller, linux-doc,
	Ilpo Järvinen, Matt Turner, linux-xtensa, Arnd Bergmann,
	Johan Hovold, Ivan Kokshaysky, Andy Shevchenko,
	Richard Henderson, Chris Zankel, Thomas Bogendoerfer,
	linux-parisc, linux-api, linux-mips, Lukas Wunner, linux-alpha,
	linuxppc-dev, David S. Miller

This patch adds generic support for serial multipoint
addressing. Two new ioctls are added. TIOCSADDR is used to
indicate the destination/receive address. TIOCGADDR returns
the current address in use. The driver should implement
set_addr and get_addr to support addressing mode.

Adjust ADDRB clearing to happen only if driver does not provide
set_addr (=the driver doesn't support address mode).

This change is necessary for supporting devices with RS485
multipoint addressing [*]. A following patch in the patch series
adds support for Synopsys Designware UART capable for 9th bit
addressing mode. In this mode, 9th bit is used to indicate an
address (byte) within the communication line. The 9th bit
addressing mode is selected using ADDRB introduced by the
previous patch.

Transmit addresses / receiver filter are specified by setting
the flags SER_ADDR_DEST and/or SER_ADDR_RECV. When the user
supplies the transmit address, in the 9bit addressing mode it is
sent out immediately with the 9th bit set to 1. After that, the
subsequent normal data bytes are sent with 9th bit as 0 and they
are intended to the device with the given address. It is up to
receiver to enforce the filter using SER_ADDR_RECV. When userspace
has supplied the receive address, the driver is expected to handle
the matching of the address and only data with that address is
forwarded to the user. Both SER_ADDR_DEST and SER_ADDR_RECV can
be given at the same time in a single call if the addresses are
the same.

The user can clear the receive filter with SER_ADDR_RECV_CLEAR.

[*] Technically, RS485 is just an electronic spec and does not
itself specify the 9th bit addressing mode but 9th bit seems
at least "semi-standard" way to do addressing with RS485.

Cc: linux-api@vger.kernel.org
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Matt Turner <mattst88@gmail.com>
Cc: linux-alpha@vger.kernel.org
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: linux-mips@vger.kernel.org
Cc: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
Cc: Helge Deller <deller@gmx.de>
Cc: linux-parisc@vger.kernel.org
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
Cc: Rich Felker <dalias@libc.org>
Cc: linux-sh@vger.kernel.org
Cc: "David S. Miller" <davem@davemloft.net>
Cc: sparclinux@vger.kernel.org
Cc: Chris Zankel <chris@zankel.net>
Cc: Max Filippov <jcmvbkbc@gmail.com>
Cc: linux-xtensa@linux-xtensa.org
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: linux-arch@vger.kernel.org
Cc: linux-doc@vger.kernel.org
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 .../driver-api/serial/serial-rs485.rst        | 23 ++++++-
 arch/alpha/include/uapi/asm/ioctls.h          |  3 +
 arch/mips/include/uapi/asm/ioctls.h           |  3 +
 arch/parisc/include/uapi/asm/ioctls.h         |  3 +
 arch/powerpc/include/uapi/asm/ioctls.h        |  3 +
 arch/sh/include/uapi/asm/ioctls.h             |  3 +
 arch/sparc/include/uapi/asm/ioctls.h          |  3 +
 arch/xtensa/include/uapi/asm/ioctls.h         |  3 +
 drivers/tty/serial/8250/8250_core.c           |  2 +
 drivers/tty/serial/serial_core.c              | 62 ++++++++++++++++++-
 include/linux/serial_core.h                   |  6 ++
 include/uapi/asm-generic/ioctls.h             |  3 +
 include/uapi/linux/serial.h                   |  8 +++
 13 files changed, 123 insertions(+), 2 deletions(-)

diff --git a/Documentation/driver-api/serial/serial-rs485.rst b/Documentation/driver-api/serial/serial-rs485.rst
index 6bc824f948f9..2f45f007fa5b 100644
--- a/Documentation/driver-api/serial/serial-rs485.rst
+++ b/Documentation/driver-api/serial/serial-rs485.rst
@@ -95,7 +95,28 @@ RS485 Serial Communications
 		/* Error handling. See errno. */
 	}
 
-5. References
+5. Multipoint Addressing
+========================
+
+   The Linux kernel provides serial_addr structure to handle addressing within
+   multipoint serial communications line such as RS485. 9th bit addressiong mode
+   is enabled by adding ADDRB flag in termios c_cflag.
+
+   Serial core calls device specific set/get_addr in response to TIOCSADDR and
+   TIOCGADDR ioctls with a pointer to serial_addr. Destination and receive
+   address can be specified using serial_addr flags field. Receive address may
+   also be cleared using flags. Once an address is set, the communication
+   can occur only with the particular device and other peers are filtered out.
+   It is left up to the receiver side to enforce the filtering.
+
+   Address flags:
+	- SER_ADDR_RECV: Receive (filter) address.
+	- SER_ADDR_RECV_CLEAR: Clear receive filter (only for TIOCSADDR).
+	- SER_ADDR_DEST: Destination address.
+
+   Note: not all devices supporting RS485 support multipoint addressing.
+
+6. References
 =============
 
  [1]	include/uapi/linux/serial.h
diff --git a/arch/alpha/include/uapi/asm/ioctls.h b/arch/alpha/include/uapi/asm/ioctls.h
index 971311605288..500cab3e1d6b 100644
--- a/arch/alpha/include/uapi/asm/ioctls.h
+++ b/arch/alpha/include/uapi/asm/ioctls.h
@@ -125,4 +125,7 @@
 #define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
 #define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
 
+#define TIOCSADDR	_IOWR('T', 0x63, struct serial_addr)
+#define TIOCGADDR	_IOWR('T', 0x64, struct serial_addr)
+
 #endif /* _ASM_ALPHA_IOCTLS_H */
diff --git a/arch/mips/include/uapi/asm/ioctls.h b/arch/mips/include/uapi/asm/ioctls.h
index 16aa8a766aec..3859dc46857e 100644
--- a/arch/mips/include/uapi/asm/ioctls.h
+++ b/arch/mips/include/uapi/asm/ioctls.h
@@ -96,6 +96,9 @@
 #define TIOCGISO7816	_IOR('T', 0x42, struct serial_iso7816)
 #define TIOCSISO7816	_IOWR('T', 0x43, struct serial_iso7816)
 
+#define TIOCSADDR	_IOWR('T', 0x63, struct serial_addr)
+#define TIOCGADDR	_IOWR('T', 0x64, struct serial_addr)
+
 /* I hope the range from 0x5480 on is free ... */
 #define TIOCSCTTY	0x5480		/* become controlling tty */
 #define TIOCGSOFTCAR	0x5481
diff --git a/arch/parisc/include/uapi/asm/ioctls.h b/arch/parisc/include/uapi/asm/ioctls.h
index 82d1148c6379..62337743db64 100644
--- a/arch/parisc/include/uapi/asm/ioctls.h
+++ b/arch/parisc/include/uapi/asm/ioctls.h
@@ -86,6 +86,9 @@
 #define TIOCSTOP	0x5462
 #define TIOCSLTC	0x5462
 
+#define TIOCSADDR	_IOWR('T', 0x63, struct serial_addr)
+#define TIOCGADDR	_IOWR('T', 0x64, struct serial_addr)
+
 /* Used for packet mode */
 #define TIOCPKT_DATA		 0
 #define TIOCPKT_FLUSHREAD	 1
diff --git a/arch/powerpc/include/uapi/asm/ioctls.h b/arch/powerpc/include/uapi/asm/ioctls.h
index 2c145da3b774..84fd69ac366a 100644
--- a/arch/powerpc/include/uapi/asm/ioctls.h
+++ b/arch/powerpc/include/uapi/asm/ioctls.h
@@ -120,4 +120,7 @@
 #define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
 #define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
 
+#define TIOCSADDR	_IOWR('T', 0x63, struct serial_addr)
+#define TIOCGADDR	_IOWR('T', 0x64, struct serial_addr)
+
 #endif	/* _ASM_POWERPC_IOCTLS_H */
diff --git a/arch/sh/include/uapi/asm/ioctls.h b/arch/sh/include/uapi/asm/ioctls.h
index 11866d4f60e1..f82966b7dba2 100644
--- a/arch/sh/include/uapi/asm/ioctls.h
+++ b/arch/sh/include/uapi/asm/ioctls.h
@@ -113,4 +113,7 @@
 #define TIOCMIWAIT	_IO('T', 92) /* 0x545C */	/* wait for a change on serial input line(s) */
 #define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
 
+#define TIOCSADDR	_IOWR('T', 0x63, struct serial_addr)
+#define TIOCGADDR	_IOWR('T', 0x64, struct serial_addr)
+
 #endif /* __ASM_SH_IOCTLS_H */
diff --git a/arch/sparc/include/uapi/asm/ioctls.h b/arch/sparc/include/uapi/asm/ioctls.h
index 7fd2f5873c9e..e44624c67c79 100644
--- a/arch/sparc/include/uapi/asm/ioctls.h
+++ b/arch/sparc/include/uapi/asm/ioctls.h
@@ -125,6 +125,9 @@
 #define TIOCMIWAIT	0x545C /* Wait for change on serial input line(s) */
 #define TIOCGICOUNT	0x545D /* Read serial port inline interrupt counts */
 
+#define TIOCSADDR	_IOWR('T', 0x63, struct serial_addr)
+#define TIOCGADDR	_IOWR('T', 0x64, struct serial_addr)
+
 /* Kernel definitions */
 
 /* Used for packet mode */
diff --git a/arch/xtensa/include/uapi/asm/ioctls.h b/arch/xtensa/include/uapi/asm/ioctls.h
index 6d4a87296c95..759ca9377f2a 100644
--- a/arch/xtensa/include/uapi/asm/ioctls.h
+++ b/arch/xtensa/include/uapi/asm/ioctls.h
@@ -127,4 +127,7 @@
 #define TIOCMIWAIT	_IO('T', 92) /* wait for a change on serial input line(s) */
 #define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
 
+#define TIOCSADDR	_IOWR('T', 0x63, struct serial_addr)
+#define TIOCGADDR	_IOWR('T', 0x64, struct serial_addr)
+
 #endif /* _XTENSA_IOCTLS_H */
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 01d30f6ed8fb..f67bc3b76f65 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -1008,6 +1008,8 @@ int serial8250_register_8250_port(const struct uart_8250_port *up)
 		uart->port.rs485	= up->port.rs485;
 		uart->rs485_start_tx	= up->rs485_start_tx;
 		uart->rs485_stop_tx	= up->rs485_stop_tx;
+		uart->port.set_addr	= up->port.set_addr;
+		uart->port.get_addr	= up->port.get_addr;
 		uart->dma		= up->dma;
 
 		/* Take tx_loadsz from fifosize if it wasn't set separately */
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 8ab88293c917..8235f696d073 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -1346,6 +1346,56 @@ static int uart_set_iso7816_config(struct uart_port *port,
 	return 0;
 }
 
+static int uart_set_addr(struct uart_port *port,
+			 struct serial_addr __user *serial_addr_user)
+{
+	struct serial_addr addr;
+	unsigned long flags;
+	int ret;
+
+	if (copy_from_user(&addr, serial_addr_user, sizeof(*serial_addr_user)))
+		return -EFAULT;
+
+	spin_lock_irqsave(&port->lock, flags);
+	if (port->set_addr)
+		ret = port->set_addr(port, &addr);
+	else
+		ret = -EINVAL;
+	spin_unlock_irqrestore(&port->lock, flags);
+	if (ret)
+		return ret;
+
+	if (copy_to_user(serial_addr_user, &addr, sizeof(addr)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int uart_get_addr(struct uart_port *port,
+			 struct serial_addr __user *serial_addr_user)
+{
+	struct serial_addr addr;
+	unsigned long flags;
+	int ret;
+
+	if (copy_from_user(&addr, serial_addr_user, sizeof(*serial_addr_user)))
+		return -EFAULT;
+
+	spin_lock_irqsave(&port->lock, flags);
+	if (port->get_addr)
+		ret = port->get_addr(port, &addr);
+	else
+		ret = -EINVAL;
+	spin_unlock_irqrestore(&port->lock, flags);
+	if (ret)
+		return ret;
+
+	if (copy_to_user(serial_addr_user, &addr, sizeof(addr)))
+		return -EFAULT;
+
+	return 0;
+}
+
 /*
  * Called via sys_ioctl.  We can use spin_lock_irq() here.
  */
@@ -1423,6 +1473,15 @@ uart_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
 	case TIOCGISO7816:
 		ret = uart_get_iso7816_config(state->uart_port, uarg);
 		break;
+
+	case TIOCSADDR:
+		ret = uart_set_addr(uport, uarg);
+		break;
+
+	case TIOCGADDR:
+		ret = uart_get_addr(uport, uarg);
+		break;
+
 	default:
 		if (uport->ops->ioctl)
 			ret = uport->ops->ioctl(uport, cmd, arg);
@@ -1489,7 +1548,8 @@ static void uart_set_termios(struct tty_struct *tty,
 		goto out;
 	}
 
-	tty->termios.c_cflag &= ~ADDRB;
+	if (!uport->set_addr)
+		tty->termios.c_cflag &= ~ADDRB;
 
 	uart_change_speed(tty, state, old_termios);
 	/* reload cflag from termios; port driver may have overridden flags */
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 31f7fe527395..ebe1d0ec11d8 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -135,6 +135,12 @@ struct uart_port {
 						struct serial_rs485 *rs485);
 	int			(*iso7816_config)(struct uart_port *,
 						  struct serial_iso7816 *iso7816);
+
+	int			(*set_addr)(struct uart_port *p,
+					    struct serial_addr *addr);
+	int			(*get_addr)(struct uart_port *p,
+					    struct serial_addr *addr);
+
 	unsigned int		irq;			/* irq number */
 	unsigned long		irqflags;		/* irq flags  */
 	unsigned int		uartclk;		/* base uart clock */
diff --git a/include/uapi/asm-generic/ioctls.h b/include/uapi/asm-generic/ioctls.h
index cdc9f4ca8c27..689743366091 100644
--- a/include/uapi/asm-generic/ioctls.h
+++ b/include/uapi/asm-generic/ioctls.h
@@ -106,6 +106,9 @@
 # define FIOQSIZE	0x5460
 #endif
 
+#define TIOCSADDR	_IOWR('T', 0x63, struct serial_addr)
+#define TIOCGADDR	_IOWR('T', 0x64, struct serial_addr)
+
 /* Used for packet mode */
 #define TIOCPKT_DATA		 0
 #define TIOCPKT_FLUSHREAD	 1
diff --git a/include/uapi/linux/serial.h b/include/uapi/linux/serial.h
index f868685b35a0..7b198fd5d390 100644
--- a/include/uapi/linux/serial.h
+++ b/include/uapi/linux/serial.h
@@ -151,4 +151,12 @@ struct serial_iso7816 {
 	__u32	reserved[5];
 };
 
+struct serial_addr {
+	__u32	flags;
+#define SER_ADDR_RECV			(1 << 0)
+#define SER_ADDR_RECV_CLEAR		(1 << 1)
+#define SER_ADDR_DEST			(1 << 2)
+	__u32	addr;
+};
+
 #endif /* _UAPI_LINUX_SERIAL_H */
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 6/7] serial: General support for multipoint addresses
@ 2022-03-02  9:56   ` Ilpo Järvinen
  0 siblings, 0 replies; 48+ messages in thread
From: Ilpo Järvinen @ 2022-03-02  9:56 UTC (permalink / raw)
  To: linux-serial-u79uwXL29TY76Z2rM5mHXA, Jiri Slaby, Greg Kroah-Hartman
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA, Lukas Wunner, Johan Hovold,
	Andy Shevchenko, Heikki Krogerus, Ilpo Järvinen,
	linux-api-u79uwXL29TY76Z2rM5mHXA, Richard Henderson,
	Ivan Kokshaysky, Matt Turner, linux-alpha-u79uwXL29TY76Z2rM5mHXA,
	Thomas Bogendoerfer, linux-mips-u79uwXL29TY76Z2rM5mHXA,
	James E.J. Bottomley, Helge Deller,
	linux-parisc-u79uwXL29TY76Z2rM5mHXA, Michael Ellerman,
	Benjamin Herrenschmidt, Paul Mackerras, linuxppc-dev

This patch adds generic support for serial multipoint
addressing. Two new ioctls are added. TIOCSADDR is used to
indicate the destination/receive address. TIOCGADDR returns
the current address in use. The driver should implement
set_addr and get_addr to support addressing mode.

Adjust ADDRB clearing to happen only if driver does not provide
set_addr (=the driver doesn't support address mode).

This change is necessary for supporting devices with RS485
multipoint addressing [*]. A following patch in the patch series
adds support for Synopsys Designware UART capable for 9th bit
addressing mode. In this mode, 9th bit is used to indicate an
address (byte) within the communication line. The 9th bit
addressing mode is selected using ADDRB introduced by the
previous patch.

Transmit addresses / receiver filter are specified by setting
the flags SER_ADDR_DEST and/or SER_ADDR_RECV. When the user
supplies the transmit address, in the 9bit addressing mode it is
sent out immediately with the 9th bit set to 1. After that, the
subsequent normal data bytes are sent with 9th bit as 0 and they
are intended to the device with the given address. It is up to
receiver to enforce the filter using SER_ADDR_RECV. When userspace
has supplied the receive address, the driver is expected to handle
the matching of the address and only data with that address is
forwarded to the user. Both SER_ADDR_DEST and SER_ADDR_RECV can
be given at the same time in a single call if the addresses are
the same.

The user can clear the receive filter with SER_ADDR_RECV_CLEAR.

[*] Technically, RS485 is just an electronic spec and does not
itself specify the 9th bit addressing mode but 9th bit seems
at least "semi-standard" way to do addressing with RS485.

Cc: linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: Richard Henderson <rth-hL46jP5Bxq7R7s880joybQ@public.gmane.org>
Cc: Ivan Kokshaysky <ink-biIs/Y0ymYJMZLIVYojuPNP0rXTJTi09@public.gmane.org>
Cc: Matt Turner <mattst88-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Cc: linux-alpha-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: Thomas Bogendoerfer <tsbogend-I1c7kopa9pxLokYuJOExCg@public.gmane.org>
Cc: linux-mips-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: "James E.J. Bottomley" <James.Bottomley-d9PhHud1JfjCXq6kfMZ53/egYHeGw8Jk@public.gmane.org>
Cc: Helge Deller <deller-Mmb7MZpHnFY@public.gmane.org>
Cc: linux-parisc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: Michael Ellerman <mpe-Gsx/Oe8HsFggBc27wqDAHg@public.gmane.org>
Cc: Benjamin Herrenschmidt <benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>
Cc: Paul Mackerras <paulus-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
Cc: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
Cc: Yoshinori Sato <ysato-Rn4VEauK+AKRv+LV9MX5uooqe+aC9MnS@public.gmane.org>
Cc: Rich Felker <dalias-8zAoT0mYgF4@public.gmane.org>
Cc: linux-sh-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: "David S. Miller" <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
Cc: sparclinux-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: Chris Zankel <chris-YvXeqwSYzG2sTnJN9+BGXg@public.gmane.org>
Cc: Max Filippov <jcmvbkbc-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Cc: linux-xtensa-PjhNF2WwrV/0Sa2dR60CXw@public.gmane.org
Cc: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
Cc: linux-arch-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: linux-doc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
---
 .../driver-api/serial/serial-rs485.rst        | 23 ++++++-
 arch/alpha/include/uapi/asm/ioctls.h          |  3 +
 arch/mips/include/uapi/asm/ioctls.h           |  3 +
 arch/parisc/include/uapi/asm/ioctls.h         |  3 +
 arch/powerpc/include/uapi/asm/ioctls.h        |  3 +
 arch/sh/include/uapi/asm/ioctls.h             |  3 +
 arch/sparc/include/uapi/asm/ioctls.h          |  3 +
 arch/xtensa/include/uapi/asm/ioctls.h         |  3 +
 drivers/tty/serial/8250/8250_core.c           |  2 +
 drivers/tty/serial/serial_core.c              | 62 ++++++++++++++++++-
 include/linux/serial_core.h                   |  6 ++
 include/uapi/asm-generic/ioctls.h             |  3 +
 include/uapi/linux/serial.h                   |  8 +++
 13 files changed, 123 insertions(+), 2 deletions(-)

diff --git a/Documentation/driver-api/serial/serial-rs485.rst b/Documentation/driver-api/serial/serial-rs485.rst
index 6bc824f948f9..2f45f007fa5b 100644
--- a/Documentation/driver-api/serial/serial-rs485.rst
+++ b/Documentation/driver-api/serial/serial-rs485.rst
@@ -95,7 +95,28 @@ RS485 Serial Communications
 		/* Error handling. See errno. */
 	}
 
-5. References
+5. Multipoint Addressing
+========================
+
+   The Linux kernel provides serial_addr structure to handle addressing within
+   multipoint serial communications line such as RS485. 9th bit addressiong mode
+   is enabled by adding ADDRB flag in termios c_cflag.
+
+   Serial core calls device specific set/get_addr in response to TIOCSADDR and
+   TIOCGADDR ioctls with a pointer to serial_addr. Destination and receive
+   address can be specified using serial_addr flags field. Receive address may
+   also be cleared using flags. Once an address is set, the communication
+   can occur only with the particular device and other peers are filtered out.
+   It is left up to the receiver side to enforce the filtering.
+
+   Address flags:
+	- SER_ADDR_RECV: Receive (filter) address.
+	- SER_ADDR_RECV_CLEAR: Clear receive filter (only for TIOCSADDR).
+	- SER_ADDR_DEST: Destination address.
+
+   Note: not all devices supporting RS485 support multipoint addressing.
+
+6. References
 =============
 
  [1]	include/uapi/linux/serial.h
diff --git a/arch/alpha/include/uapi/asm/ioctls.h b/arch/alpha/include/uapi/asm/ioctls.h
index 971311605288..500cab3e1d6b 100644
--- a/arch/alpha/include/uapi/asm/ioctls.h
+++ b/arch/alpha/include/uapi/asm/ioctls.h
@@ -125,4 +125,7 @@
 #define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
 #define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
 
+#define TIOCSADDR	_IOWR('T', 0x63, struct serial_addr)
+#define TIOCGADDR	_IOWR('T', 0x64, struct serial_addr)
+
 #endif /* _ASM_ALPHA_IOCTLS_H */
diff --git a/arch/mips/include/uapi/asm/ioctls.h b/arch/mips/include/uapi/asm/ioctls.h
index 16aa8a766aec..3859dc46857e 100644
--- a/arch/mips/include/uapi/asm/ioctls.h
+++ b/arch/mips/include/uapi/asm/ioctls.h
@@ -96,6 +96,9 @@
 #define TIOCGISO7816	_IOR('T', 0x42, struct serial_iso7816)
 #define TIOCSISO7816	_IOWR('T', 0x43, struct serial_iso7816)
 
+#define TIOCSADDR	_IOWR('T', 0x63, struct serial_addr)
+#define TIOCGADDR	_IOWR('T', 0x64, struct serial_addr)
+
 /* I hope the range from 0x5480 on is free ... */
 #define TIOCSCTTY	0x5480		/* become controlling tty */
 #define TIOCGSOFTCAR	0x5481
diff --git a/arch/parisc/include/uapi/asm/ioctls.h b/arch/parisc/include/uapi/asm/ioctls.h
index 82d1148c6379..62337743db64 100644
--- a/arch/parisc/include/uapi/asm/ioctls.h
+++ b/arch/parisc/include/uapi/asm/ioctls.h
@@ -86,6 +86,9 @@
 #define TIOCSTOP	0x5462
 #define TIOCSLTC	0x5462
 
+#define TIOCSADDR	_IOWR('T', 0x63, struct serial_addr)
+#define TIOCGADDR	_IOWR('T', 0x64, struct serial_addr)
+
 /* Used for packet mode */
 #define TIOCPKT_DATA		 0
 #define TIOCPKT_FLUSHREAD	 1
diff --git a/arch/powerpc/include/uapi/asm/ioctls.h b/arch/powerpc/include/uapi/asm/ioctls.h
index 2c145da3b774..84fd69ac366a 100644
--- a/arch/powerpc/include/uapi/asm/ioctls.h
+++ b/arch/powerpc/include/uapi/asm/ioctls.h
@@ -120,4 +120,7 @@
 #define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
 #define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
 
+#define TIOCSADDR	_IOWR('T', 0x63, struct serial_addr)
+#define TIOCGADDR	_IOWR('T', 0x64, struct serial_addr)
+
 #endif	/* _ASM_POWERPC_IOCTLS_H */
diff --git a/arch/sh/include/uapi/asm/ioctls.h b/arch/sh/include/uapi/asm/ioctls.h
index 11866d4f60e1..f82966b7dba2 100644
--- a/arch/sh/include/uapi/asm/ioctls.h
+++ b/arch/sh/include/uapi/asm/ioctls.h
@@ -113,4 +113,7 @@
 #define TIOCMIWAIT	_IO('T', 92) /* 0x545C */	/* wait for a change on serial input line(s) */
 #define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
 
+#define TIOCSADDR	_IOWR('T', 0x63, struct serial_addr)
+#define TIOCGADDR	_IOWR('T', 0x64, struct serial_addr)
+
 #endif /* __ASM_SH_IOCTLS_H */
diff --git a/arch/sparc/include/uapi/asm/ioctls.h b/arch/sparc/include/uapi/asm/ioctls.h
index 7fd2f5873c9e..e44624c67c79 100644
--- a/arch/sparc/include/uapi/asm/ioctls.h
+++ b/arch/sparc/include/uapi/asm/ioctls.h
@@ -125,6 +125,9 @@
 #define TIOCMIWAIT	0x545C /* Wait for change on serial input line(s) */
 #define TIOCGICOUNT	0x545D /* Read serial port inline interrupt counts */
 
+#define TIOCSADDR	_IOWR('T', 0x63, struct serial_addr)
+#define TIOCGADDR	_IOWR('T', 0x64, struct serial_addr)
+
 /* Kernel definitions */
 
 /* Used for packet mode */
diff --git a/arch/xtensa/include/uapi/asm/ioctls.h b/arch/xtensa/include/uapi/asm/ioctls.h
index 6d4a87296c95..759ca9377f2a 100644
--- a/arch/xtensa/include/uapi/asm/ioctls.h
+++ b/arch/xtensa/include/uapi/asm/ioctls.h
@@ -127,4 +127,7 @@
 #define TIOCMIWAIT	_IO('T', 92) /* wait for a change on serial input line(s) */
 #define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
 
+#define TIOCSADDR	_IOWR('T', 0x63, struct serial_addr)
+#define TIOCGADDR	_IOWR('T', 0x64, struct serial_addr)
+
 #endif /* _XTENSA_IOCTLS_H */
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 01d30f6ed8fb..f67bc3b76f65 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -1008,6 +1008,8 @@ int serial8250_register_8250_port(const struct uart_8250_port *up)
 		uart->port.rs485	= up->port.rs485;
 		uart->rs485_start_tx	= up->rs485_start_tx;
 		uart->rs485_stop_tx	= up->rs485_stop_tx;
+		uart->port.set_addr	= up->port.set_addr;
+		uart->port.get_addr	= up->port.get_addr;
 		uart->dma		= up->dma;
 
 		/* Take tx_loadsz from fifosize if it wasn't set separately */
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 8ab88293c917..8235f696d073 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -1346,6 +1346,56 @@ static int uart_set_iso7816_config(struct uart_port *port,
 	return 0;
 }
 
+static int uart_set_addr(struct uart_port *port,
+			 struct serial_addr __user *serial_addr_user)
+{
+	struct serial_addr addr;
+	unsigned long flags;
+	int ret;
+
+	if (copy_from_user(&addr, serial_addr_user, sizeof(*serial_addr_user)))
+		return -EFAULT;
+
+	spin_lock_irqsave(&port->lock, flags);
+	if (port->set_addr)
+		ret = port->set_addr(port, &addr);
+	else
+		ret = -EINVAL;
+	spin_unlock_irqrestore(&port->lock, flags);
+	if (ret)
+		return ret;
+
+	if (copy_to_user(serial_addr_user, &addr, sizeof(addr)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int uart_get_addr(struct uart_port *port,
+			 struct serial_addr __user *serial_addr_user)
+{
+	struct serial_addr addr;
+	unsigned long flags;
+	int ret;
+
+	if (copy_from_user(&addr, serial_addr_user, sizeof(*serial_addr_user)))
+		return -EFAULT;
+
+	spin_lock_irqsave(&port->lock, flags);
+	if (port->get_addr)
+		ret = port->get_addr(port, &addr);
+	else
+		ret = -EINVAL;
+	spin_unlock_irqrestore(&port->lock, flags);
+	if (ret)
+		return ret;
+
+	if (copy_to_user(serial_addr_user, &addr, sizeof(addr)))
+		return -EFAULT;
+
+	return 0;
+}
+
 /*
  * Called via sys_ioctl.  We can use spin_lock_irq() here.
  */
@@ -1423,6 +1473,15 @@ uart_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
 	case TIOCGISO7816:
 		ret = uart_get_iso7816_config(state->uart_port, uarg);
 		break;
+
+	case TIOCSADDR:
+		ret = uart_set_addr(uport, uarg);
+		break;
+
+	case TIOCGADDR:
+		ret = uart_get_addr(uport, uarg);
+		break;
+
 	default:
 		if (uport->ops->ioctl)
 			ret = uport->ops->ioctl(uport, cmd, arg);
@@ -1489,7 +1548,8 @@ static void uart_set_termios(struct tty_struct *tty,
 		goto out;
 	}
 
-	tty->termios.c_cflag &= ~ADDRB;
+	if (!uport->set_addr)
+		tty->termios.c_cflag &= ~ADDRB;
 
 	uart_change_speed(tty, state, old_termios);
 	/* reload cflag from termios; port driver may have overridden flags */
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 31f7fe527395..ebe1d0ec11d8 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -135,6 +135,12 @@ struct uart_port {
 						struct serial_rs485 *rs485);
 	int			(*iso7816_config)(struct uart_port *,
 						  struct serial_iso7816 *iso7816);
+
+	int			(*set_addr)(struct uart_port *p,
+					    struct serial_addr *addr);
+	int			(*get_addr)(struct uart_port *p,
+					    struct serial_addr *addr);
+
 	unsigned int		irq;			/* irq number */
 	unsigned long		irqflags;		/* irq flags  */
 	unsigned int		uartclk;		/* base uart clock */
diff --git a/include/uapi/asm-generic/ioctls.h b/include/uapi/asm-generic/ioctls.h
index cdc9f4ca8c27..689743366091 100644
--- a/include/uapi/asm-generic/ioctls.h
+++ b/include/uapi/asm-generic/ioctls.h
@@ -106,6 +106,9 @@
 # define FIOQSIZE	0x5460
 #endif
 
+#define TIOCSADDR	_IOWR('T', 0x63, struct serial_addr)
+#define TIOCGADDR	_IOWR('T', 0x64, struct serial_addr)
+
 /* Used for packet mode */
 #define TIOCPKT_DATA		 0
 #define TIOCPKT_FLUSHREAD	 1
diff --git a/include/uapi/linux/serial.h b/include/uapi/linux/serial.h
index f868685b35a0..7b198fd5d390 100644
--- a/include/uapi/linux/serial.h
+++ b/include/uapi/linux/serial.h
@@ -151,4 +151,12 @@ struct serial_iso7816 {
 	__u32	reserved[5];
 };
 
+struct serial_addr {
+	__u32	flags;
+#define SER_ADDR_RECV			(1 << 0)
+#define SER_ADDR_RECV_CLEAR		(1 << 1)
+#define SER_ADDR_DEST			(1 << 2)
+	__u32	addr;
+};
+
 #endif /* _UAPI_LINUX_SERIAL_H */
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 7/7] serial: 8250_dwlib: Support for 9th bit multipoint addressing
  2022-03-02  9:55 [PATCH 0/7] Add RS485 support to DW UART Ilpo Järvinen
                   ` (5 preceding siblings ...)
  2022-03-02  9:56   ` Ilpo Järvinen
@ 2022-03-02  9:56 ` Ilpo Järvinen
  6 siblings, 0 replies; 48+ messages in thread
From: Ilpo Järvinen @ 2022-03-02  9:56 UTC (permalink / raw)
  To: linux-serial, Jiri Slaby, Greg Kroah-Hartman
  Cc: linux-kernel, Lukas Wunner, Johan Hovold, Andy Shevchenko,
	Heikki Krogerus, Ilpo Järvinen, Raymond Tan,
	Lakshmi Sowjanya

This change adds 9th bit multipoint addressing mode for DW UART using
the new ioctls introduced in the previous change. 9th bit addressing
can be used only when HW RS485 is available.

Updating RAR (receive address register) is bit tricky because
busy indication is not be available when DW UART is strictly
16550 compatible, which is the case with the hardware I was
testing with. RAR should not be updated while receive is in
progress which is now achieved by deasserting RE and waiting
for one frame (in case rx would be in progress, the driver
seems to have no way of knowing it w/o busy indication).

Co-developed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Co-developed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Co-developed-by: Raymond Tan <raymond.tan@intel.com>
Signed-off-by: Raymond Tan <raymond.tan@intel.com>
Co-developed-by: Lakshmi Sowjanya <lakshmi.sowjanya.d@intel.com>
Signed-off-by: Lakshmi Sowjanya <lakshmi.sowjanya.d@intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 drivers/tty/serial/8250/8250_dwlib.c | 124 +++++++++++++++++++++++++++
 drivers/tty/serial/8250/8250_dwlib.h |   3 +
 2 files changed, 127 insertions(+)

diff --git a/drivers/tty/serial/8250/8250_dwlib.c b/drivers/tty/serial/8250/8250_dwlib.c
index 51b0f55ee9d0..57bf6ca0309b 100644
--- a/drivers/tty/serial/8250/8250_dwlib.c
+++ b/drivers/tty/serial/8250/8250_dwlib.c
@@ -3,9 +3,11 @@
 
 #include <linux/bitops.h>
 #include <linux/bitfield.h>
+#include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
+#include <linux/math.h>
 #include <linux/property.h>
 #include <linux/serial_8250.h>
 #include <linux/serial_core.h>
@@ -17,6 +19,9 @@
 #define DW_UART_DE_EN	0xb0 /* Driver Output Enable Register */
 #define DW_UART_RE_EN	0xb4 /* Receiver Output Enable Register */
 #define DW_UART_DLF	0xc0 /* Divisor Latch Fraction Register */
+#define DW_UART_RAR	0xc4 /* Receive Address Register */
+#define DW_UART_TAR	0xc8 /* Transmit Address Register */
+#define DW_UART_LCR_EXT	0xcc /* Line Extended Control Register */
 #define DW_UART_CPR	0xf4 /* Component Parameter Register */
 #define DW_UART_UCV	0xf8 /* UART Component Version */
 
@@ -29,6 +34,12 @@
 #define DW_UART_TCR_XFER_MODE_SW_DE_OR_RE	FIELD_PREP(DW_UART_TCR_XFER_MODE, 1)
 #define DW_UART_TCR_XFER_MODE_DE_OR_RE		FIELD_PREP(DW_UART_TCR_XFER_MODE, 2)
 
+/* Line Extended Control Register bits */
+#define DW_UART_LCR_EXT_DLS_E		BIT(0)
+#define DW_UART_LCR_EXT_ADDR_MATCH	BIT(1)
+#define DW_UART_LCR_EXT_SEND_ADDR	BIT(2)
+#define DW_UART_LCR_EXT_TRANSMIT_MODE	BIT(3)
+
 /* Component Parameter Register bits */
 #define DW_UART_CPR_ABP_DATA_WIDTH	(3 << 0)
 #define DW_UART_CPR_AFCE_MODE		(1 << 4)
@@ -91,16 +102,126 @@ static void dw8250_set_divisor(struct uart_port *p, unsigned int baud,
 	serial8250_do_set_divisor(p, baud, quot, quot_frac);
 }
 
+/* Wait until re is de-asserted for sure. Without BUSY indication available,
+ * only available course of action is to wait until current frame is received.
+ */
+static void dw8250_wait_re_deassert(struct uart_port *p)
+{
+	struct dw8250_port_data *d = p->private_data;
+
+	if (d->rar_timeout_us)
+		udelay(d->rar_timeout_us);
+}
+
+static void dw8250_update_rar(struct uart_port *p, u32 addr)
+{
+	u32 re_en = dw8250_readl_ext(p, DW_UART_RE_EN);
+
+	/* RAR shouldn't be changed while receiving. Thus, de-assert RE_EN
+	 * if asserted and wait.
+	 */
+	if (re_en)
+		dw8250_writel_ext(p, DW_UART_RE_EN, 0);
+	dw8250_wait_re_deassert(p);
+	dw8250_writel_ext(p, DW_UART_RAR, addr);
+	if (re_en)
+		dw8250_writel_ext(p, DW_UART_RE_EN, re_en);
+}
+
+static void dw8250_addrmode_setup(struct uart_port *p, bool enable_addrmode)
+{
+	struct dw8250_port_data *d = p->private_data;
+
+	if (enable_addrmode) {
+		/* Clear RAR & TAR of any previous values */
+		dw8250_writel_ext(p, DW_UART_RAR, 0);
+		dw8250_writel_ext(p, DW_UART_TAR, 0);
+		dw8250_writel_ext(p, DW_UART_LCR_EXT, DW_UART_LCR_EXT_DLS_E);
+	} else {
+		dw8250_writel_ext(p, DW_UART_LCR_EXT, 0);
+	}
+
+	d->addrmode = enable_addrmode;
+}
+
 void dw8250_do_set_termios(struct uart_port *p, struct ktermios *termios, struct ktermios *old)
 {
+	struct dw8250_port_data *d = p->private_data;
+
 	p->status &= ~UPSTAT_AUTOCTS;
 	if (termios->c_cflag & CRTSCTS)
 		p->status |= UPSTAT_AUTOCTS;
 
+	if (!(p->rs485.flags & SER_RS485_ENABLED) || !d->hw_rs485_support)
+		termios->c_cflag &= ~ADDRB;
+
+	if (!old || (termios->c_cflag ^ old->c_cflag) & ADDRB)
+		dw8250_addrmode_setup(p, termios->c_cflag & ADDRB);
+
 	serial8250_do_set_termios(p, termios, old);
+
+	d->rar_timeout_us = termios->c_ispeed ?
+			    DIV_ROUND_UP(tty_get_frame_size(termios->c_cflag) * USEC_PER_SEC,
+					 termios->c_ispeed) : 0;
 }
 EXPORT_SYMBOL_GPL(dw8250_do_set_termios);
 
+static int dw8250_rs485_set_addr(struct uart_port *p, struct serial_addr *addr)
+{
+	struct dw8250_port_data *d = p->private_data;
+	u32 lcr;
+
+	if (!(p->rs485.flags & SER_RS485_ENABLED) || !d->addrmode)
+		return -EINVAL;
+
+	addr->flags &= SER_ADDR_RECV | SER_ADDR_RECV_CLEAR | SER_ADDR_DEST;
+	if (!addr->flags)
+		return -EINVAL;
+
+	lcr = dw8250_readl_ext(p, DW_UART_LCR_EXT);
+	if (addr->flags & SER_ADDR_RECV) {
+		dw8250_update_rar(p, addr->addr & 0xff);
+		lcr |= DW_UART_LCR_EXT_ADDR_MATCH;
+		addr->flags &= ~SER_ADDR_RECV_CLEAR;
+	} else if (addr->flags & SER_ADDR_RECV_CLEAR) {
+		lcr &= DW_UART_LCR_EXT_ADDR_MATCH;
+	}
+	if (addr->flags & SER_ADDR_DEST) {
+		dw8250_writel_ext(p, DW_UART_TAR, addr->addr & 0xff);
+		lcr |= DW_UART_LCR_EXT_SEND_ADDR;
+	}
+	dw8250_writel_ext(p, DW_UART_LCR_EXT, lcr);
+
+	return 0;
+}
+
+static int dw8250_rs485_get_addr(struct uart_port *p, struct serial_addr *addr)
+{
+	struct dw8250_port_data *d = p->private_data;
+
+	if (!(p->rs485.flags & SER_RS485_ENABLED) || !d->addrmode)
+		return -EINVAL;
+
+	if (addr->flags == SER_ADDR_DEST) {
+		addr->addr = dw8250_readl_ext(p, DW_UART_TAR) & 0xff;
+		return 0;
+	}
+	if (addr->flags == SER_ADDR_RECV) {
+		u32 lcr = dw8250_readl_ext(p, DW_UART_LCR_EXT);
+
+		if (!(lcr & DW_UART_LCR_EXT_ADDR_MATCH)) {
+			addr->flags = SER_ADDR_RECV_CLEAR;
+			addr->addr = 0;
+		} else {
+			addr->addr = dw8250_readl_ext(p, DW_UART_RAR) & 0xff;
+		}
+
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
 static void dw8250_rs485_start_tx(struct uart_8250_port *up)
 {
 	struct uart_port *p = &(up->port);
@@ -157,6 +278,7 @@ static int dw8250_rs485_config(struct uart_port *p, struct serial_rs485 *rs485)
 		tcr &= ~DW_UART_TCR_RS485_EN;
 		dw8250_writel_ext(p, DW_UART_DE_EN, 0);
 		dw8250_writel_ext(p, DW_UART_RE_EN, 0);
+		dw8250_addrmode_setup(p, false);
 	}
 
 	/* Resetting the default DE_POL & RE_POL */
@@ -203,6 +325,8 @@ void dw8250_setup_port(struct uart_port *p)
 		p->rs485_config = dw8250_rs485_config;
 		up->rs485_start_tx = dw8250_rs485_start_tx;
 		up->rs485_stop_tx = dw8250_rs485_stop_tx;
+		p->set_addr = dw8250_rs485_set_addr;
+		p->get_addr = dw8250_rs485_get_addr;
 	} else {
 		p->rs485_config = serial8250_em485_config;
 		up->rs485_start_tx = serial8250_em485_start_tx;
diff --git a/drivers/tty/serial/8250/8250_dwlib.h b/drivers/tty/serial/8250/8250_dwlib.h
index a8fa020ca544..bfb1d8af7f0c 100644
--- a/drivers/tty/serial/8250/8250_dwlib.h
+++ b/drivers/tty/serial/8250/8250_dwlib.h
@@ -17,6 +17,9 @@ struct dw8250_port_data {
 
 	/* RS485 variables */
 	bool			hw_rs485_support;
+	/* 9-bit framing (9th bit is address indicator) */
+	bool			addrmode;
+	unsigned int		rar_timeout_us;
 };
 
 void dw8250_do_set_termios(struct uart_port *p, struct ktermios *termios, struct ktermios *old);
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* Re: [PATCH 4/7] dt_bindings: snps-dw-apb-uart: Add RS485
  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
  0 siblings, 0 replies; 48+ messages in thread
From: Rob Herring @ 2022-03-02 17:47 UTC (permalink / raw)
  To: Ilpo Järvinen
  Cc: linux-serial, Jiri Slaby, Greg Kroah-Hartman, linux-kernel,
	Lukas Wunner, Johan Hovold, Andy Shevchenko, Heikki Krogerus,
	devicetree

On Wed, Mar 02, 2022 at 11:56:03AM +0200, Ilpo Järvinen wrote:
> Add RS485 enable & line polarity properties.
> 
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: devicetree@vger.kernel.org
> Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
> ---
>  .../bindings/serial/snps-dw-apb-uart.yaml       | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
> index 12137fe80acf..8d440afabb1f 100644
> --- a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
> +++ b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
> @@ -103,6 +103,23 @@ properties:
>        register. Define this if your serial port does not use this pin.
>      type: boolean
>  
> +  snps,rs485-interface-en:
> +    description: Use true RS-485 DE and RE signals (in contrast to RS-485
> +      emulation using RTS). Requires IP version 4 or above.
> +    type: boolean
> +

> +  snps,de-active-high:
> +    description: Defines the polarity of driver enable (DE_EN) signal.
> +      Meaningful only with snps,rs485-interface-en. True indicates active
> +      high.
> +    type: boolean
> +
> +  snps,re-active-high:
> +    description: Defines the polarity of receiver enable (RE_EN) signal.
> +      Meaningful only with snps,rs485-interface-en. True indicates active
> +      high.
> +    type: boolean

Seems plausible that other rs485 implementations could have varying 
polarities too. IOW, should be common properties.

> +
>  required:
>    - compatible
>    - reg
> -- 
> 2.30.2
> 

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 1/7] serial: 8250_dwlib: RS485 HW half duplex support
  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 10:54     ` Ilpo Järvinen
  0 siblings, 2 replies; 48+ messages in thread
From: Lukas Wunner @ 2022-03-06 18:48 UTC (permalink / raw)
  To: Ilpo Järvinen
  Cc: linux-serial, Jiri Slaby, Greg Kroah-Hartman, linux-kernel,
	Johan Hovold, Andy Shevchenko, Heikki Krogerus, Raymond Tan,
	Heiko Stuebner

On Wed, Mar 02, 2022 at 11:56:00AM +0200, Ilpo Järvinen wrote:
> +static int dw8250_rs485_config(struct uart_port *p, struct serial_rs485 *rs485)
> +{
> +	u32 tcr;
> +
> +	tcr = dw8250_readl_ext(p, DW_UART_TCR);
> +	tcr &= ~DW_UART_TCR_XFER_MODE;
> +
> +	if (rs485->flags & SER_RS485_ENABLED) {
> +		/* Clearing unsupported flags. */

Nit:  Usually we use imperative mood, i.e. "/* clear unsupported flags */".


> +		rs485->flags &= SER_RS485_ENABLED;
> +
> +		tcr |= DW_UART_TCR_RS485_EN | DW_UART_TCR_XFER_MODE_DE_OR_RE;
> +		dw8250_writel_ext(p, DW_UART_DE_EN, 1);
> +		dw8250_writel_ext(p, DW_UART_RE_EN, 1);
> +	} else {
> +		rs485->flags = 0;
> +
> +		tcr &= ~DW_UART_TCR_RS485_EN;
> +		dw8250_writel_ext(p, DW_UART_DE_EN, 0);
> +		dw8250_writel_ext(p, DW_UART_RE_EN, 0);

Do the DW_UART_DE_EN and DW_UART_RE_EN registers have any effect at all
if DW_UART_TCR_RS485_EN is disabled in the TCR register?

If they don't, there's no need to clear them here.  It would be sufficient
to set them once (e.g. on probe).


> +	/* Resetting the default DE_POL & RE_POL */
> +	tcr &= ~(DW_UART_TCR_DE_POL | DW_UART_TCR_RE_POL);

Nit:  Imperative mood, i.e. "/* reset to default polarity */"


> +	if (device_property_read_bool(p->dev, "snps,de-active-high"))
> +		tcr |= DW_UART_TCR_DE_POL;

That device property is a duplication of the existing "rs485-rts-active-low"
property.  Please use the existing one unless there are devices already
in the field which use the new property (in which case that should be
provided as justification in the commit message).

Does the DesignWare UART use dedicated DE and RE pins instead of
the RTS pin?  That would be quite unusual.


> +	if (device_property_read_bool(p->dev, "snps,re-active-high"))
> +		tcr |= DW_UART_TCR_RE_POL;

Heiko Stübner (+cc) posted patches in 2020 to support a separate RE pin
in addition to a DE pin (which is usually simply the RTS pin):

https://lore.kernel.org/linux-serial/20200517215610.2131618-4-heiko@sntech.de/

He called the devicetree property for the pin "rs485-rx-enable",
so perhaps "rs485-rx-active-low" would be a better name here.


> +	/*
> +	 * XXX: Though we could interpret the "RTS" timings as Driver Enable
> +	 * (DE) assertion/de-assertion timings, initially not supporting that.
> +	 * Ideally we should have timing values for the Driver instead of the
> +	 * RTS signal.
> +	 */
> +	rs485->delay_rts_before_send = 0;
> +	rs485->delay_rts_after_send = 0;

I don't quite understand this code comment.


>  void dw8250_setup_port(struct uart_port *p)
>  {
> +	struct dw8250_port_data *d = p->private_data;
>  	struct uart_8250_port *up = up_to_u8250p(p);
>  	u32 reg;
>  
> +	d->hw_rs485_support = device_property_read_bool(p->dev, "snps,rs485-interface-en");
> +	if (d->hw_rs485_support)
> +		p->rs485_config = dw8250_rs485_config;
> +

You wrote in the commit message that rs485 support is present from
version 4.0 onward.  Can't we just check the IP version and enable
rs485 support for >= 4.0?  That would seem more appropriate instead
of introducing yet another new property.

Note that dw8250_setup_port() already reads the version from the
DW_UART_UCV register.

Thanks,

Lukas

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 2/7] serial: 8250_dwlib: RS485 HW full duplex support
  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
  0 siblings, 1 reply; 48+ messages in thread
From: Lukas Wunner @ 2022-03-06 18:51 UTC (permalink / raw)
  To: Ilpo Järvinen
  Cc: linux-serial, Jiri Slaby, Greg Kroah-Hartman, linux-kernel,
	Johan Hovold, Andy Shevchenko, Heikki Krogerus, Raymond Tan

On Wed, Mar 02, 2022 at 11:56:01AM +0200, Ilpo Järvinen wrote:
> @@ -110,9 +110,14 @@ 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;
> -
> -		tcr |= DW_UART_TCR_RS485_EN | DW_UART_TCR_XFER_MODE_DE_OR_RE;
> +		rs485->flags &= SER_RS485_ENABLED | SER_RS485_RX_DURING_TX;
> +		tcr |= DW_UART_TCR_RS485_EN;
> +
> +		if (rs485->flags & SER_RS485_RX_DURING_TX) {
> +			tcr |= DW_UART_TCR_XFER_MODE_DE_DURING_RE;
> +		} else {
> +			tcr |= DW_UART_TCR_XFER_MODE_DE_OR_RE;
> +		}

This patch deletes lines introduced by the preceding patch.
I'd just squash the two together, I don't see much value in
introducing full duplex support in a separate patch.

Thanks,

Lukas

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH 3/7] serial: 8250_dwlib: Implement SW half duplex support
  2022-03-02  9:56 ` [RFC PATCH 3/7] serial: 8250_dwlib: Implement SW half " Ilpo Järvinen
@ 2022-03-06 19:21   ` Lukas Wunner
  2022-03-06 22:13     ` Andy Shevchenko
  0 siblings, 1 reply; 48+ messages in thread
From: Lukas Wunner @ 2022-03-06 19:21 UTC (permalink / raw)
  To: Ilpo Järvinen
  Cc: linux-serial, Jiri Slaby, Greg Kroah-Hartman, linux-kernel,
	Johan Hovold, Andy Shevchenko, Heikki Krogerus, Eric Tremblay,
	Uwe Kleine-König, heiko, giulio.benetti

On Wed, Mar 02, 2022 at 11:56:02AM +0200, Ilpo Järvinen wrote:
> 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/

I don't see any benefit in using software emulated RTS assertion
if hardware support is present.  It just consumes more CPU time
and is slower to deassert RTS, thereby increasing bus turn-around time.

So if hardware support is present, I think you always want to
use that and you need to fallback to software emulation only
if hardware support is missing (i.e. on IP versions < 4).

The registers you're using here, DW_UART_RE_EN and DW_UART_DE_EN
don't seem to be present on older IP versions.  I'm looking at
the databook for version 3.04a and those registers aren't mentioned:

https://linux-sunxi.org/images/d/d2/Dw_apb_uart_db.pdf

So the software emulation you've implemented here won't help with
older IP and the newer IP doesn't need it because it supports
RTS assertion in hardware.  Is that correct?  If so, I'd suggest
not supporting DW_UART_TCR_XFER_MODE_SW_DE_OR_RE at all.

A number of people have attempted to add rs485 software emulation
to 8250_dw.c but noone ever pursued it into mainline.  The last
attempt was by Heiko Stübner, who used patches by Giulio Benetti (+cc):

https://lore.kernel.org/linux-serial/20200517215610.2131618-1-heiko@sntech.de/

FWIW, newer TI Sitara SoCs have also added hardware support for
rs485 and in this (not yet upstreamed) patch, I likewise chose
to use software emulation only if hardware support is not available:

https://github.com/l1k/linux/commit/82c989617a05

Thanks,

Lukas

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH 6/7] serial: General support for multipoint addresses
  2022-03-02  9:56   ` Ilpo Järvinen
  (?)
@ 2022-03-06 19:40     ` Lukas Wunner
  -1 siblings, 0 replies; 48+ messages in thread
From: Lukas Wunner @ 2022-03-06 19:40 UTC (permalink / raw)
  To: Ilpo Järvinen
  Cc: linux-serial, Jiri Slaby, Greg Kroah-Hartman, linux-kernel,
	Johan Hovold, Andy Shevchenko, Heikki Krogerus, linux-api,
	Richard Henderson, Ivan Kokshaysky, Matt Turner, linux-alpha,
	Thomas Bogendoerfer, linux-mips, James E.J. Bottomley,
	Helge Deller, linux-parisc, Michael Ellerman,
	Benjamin Herrenschmidt, Paul Mackerras, linuxppc-dev,
	Yoshinori Sato, Rich Felker, linux-sh, David S. Miller,
	sparclinux, Chris Zankel, Max Filippov, linux-xtensa,
	Arnd Bergmann, linux-arch, linux-doc

On Wed, Mar 02, 2022 at 11:56:05AM +0200, Ilpo Järvinen wrote:
> This patch adds generic support for serial multipoint
> addressing. Two new ioctls are added. TIOCSADDR is used to

Nit:  "This patch adds..." is superfluous.  Just write "Add ..."
in imperative mood.


> This change is necessary for supporting devices with RS485
> multipoint addressing [*].

If this is only used with RS485, why can't we just store the
addresses in struct serial_rs485 and use the existing TIOCSRS485
and TIOCGRS485 ioctls?  There's 20 bytes of padding left in
struct serial_rs485 which you could use.  No need to add more
user-space ABI.


> [*] Technically, RS485 is just an electronic spec and does not
> itself specify the 9th bit addressing mode but 9th bit seems
> at least "semi-standard" way to do addressing with RS485.

Is 9th bit addressing actually used by an Intel customer or was
it implemented just for feature completeness?  I think this mode
isn't used often (I've never seen a use case myself), primarily
because it requires disabling parity.

Thanks,

Lukas

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH 6/7] serial: General support for multipoint addresses
@ 2022-03-06 19:40     ` Lukas Wunner
  0 siblings, 0 replies; 48+ messages in thread
From: Lukas Wunner @ 2022-03-06 19:40 UTC (permalink / raw)
  To: Ilpo Järvinen
  Cc: Heikki Krogerus, linux-sh, linux-kernel, James E.J. Bottomley,
	Max Filippov, Rich Felker, Paul Mackerras, sparclinux, linux-api,
	Jiri Slaby, linux-arch, Yoshinori Sato, Helge Deller, linux-doc,
	linux-serial, Matt Turner, linux-xtensa, Arnd Bergmann,
	Johan Hovold, Ivan Kokshaysky, Andy Shevchenko,
	Richard Henderson, Chris Zankel, Thomas Bogendoerfer,
	linux-parisc, Greg Kroah-Hartman, linux-mips, linux-alpha,
	linuxppc-dev, David S. Miller

On Wed, Mar 02, 2022 at 11:56:05AM +0200, Ilpo Järvinen wrote:
> This patch adds generic support for serial multipoint
> addressing. Two new ioctls are added. TIOCSADDR is used to

Nit:  "This patch adds..." is superfluous.  Just write "Add ..."
in imperative mood.


> This change is necessary for supporting devices with RS485
> multipoint addressing [*].

If this is only used with RS485, why can't we just store the
addresses in struct serial_rs485 and use the existing TIOCSRS485
and TIOCGRS485 ioctls?  There's 20 bytes of padding left in
struct serial_rs485 which you could use.  No need to add more
user-space ABI.


> [*] Technically, RS485 is just an electronic spec and does not
> itself specify the 9th bit addressing mode but 9th bit seems
> at least "semi-standard" way to do addressing with RS485.

Is 9th bit addressing actually used by an Intel customer or was
it implemented just for feature completeness?  I think this mode
isn't used often (I've never seen a use case myself), primarily
because it requires disabling parity.

Thanks,

Lukas

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH 6/7] serial: General support for multipoint addresses
@ 2022-03-06 19:40     ` Lukas Wunner
  0 siblings, 0 replies; 48+ messages in thread
From: Lukas Wunner @ 2022-03-06 19:40 UTC (permalink / raw)
  To: Ilpo Järvinen
  Cc: linux-serial, Jiri Slaby, Greg Kroah-Hartman, linux-kernel,
	Johan Hovold, Andy Shevchenko, Heikki Krogerus, linux-api,
	Richard Henderson, Ivan Kokshaysky, Matt Turner, linux-alpha,
	Thomas Bogendoerfer, linux-mips, James E.J. Bottomley,
	Helge Deller, linux-parisc, Michael Ellerman,
	Benjamin Herrenschmidt, Paul Mackerras

On Wed, Mar 02, 2022 at 11:56:05AM +0200, Ilpo Järvinen wrote:
> This patch adds generic support for serial multipoint
> addressing. Two new ioctls are added. TIOCSADDR is used to

Nit:  "This patch adds..." is superfluous.  Just write "Add ..."
in imperative mood.


> This change is necessary for supporting devices with RS485
> multipoint addressing [*].

If this is only used with RS485, why can't we just store the
addresses in struct serial_rs485 and use the existing TIOCSRS485
and TIOCGRS485 ioctls?  There's 20 bytes of padding left in
struct serial_rs485 which you could use.  No need to add more
user-space ABI.


> [*] Technically, RS485 is just an electronic spec and does not
> itself specify the 9th bit addressing mode but 9th bit seems
> at least "semi-standard" way to do addressing with RS485.

Is 9th bit addressing actually used by an Intel customer or was
it implemented just for feature completeness?  I think this mode
isn't used often (I've never seen a use case myself), primarily
because it requires disabling parity.

Thanks,

Lukas

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 1/7] serial: 8250_dwlib: RS485 HW half duplex support
  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 10:54     ` Ilpo Järvinen
  1 sibling, 1 reply; 48+ messages in thread
From: Andy Shevchenko @ 2022-03-06 22:07 UTC (permalink / raw)
  To: Lukas Wunner
  Cc: Ilpo Järvinen, open list:SERIAL DRIVERS, Jiri Slaby,
	Greg Kroah-Hartman, Linux Kernel Mailing List, Johan Hovold,
	Andy Shevchenko, Heikki Krogerus, Raymond Tan, Heiko Stuebner

On Mon, Mar 7, 2022 at 12:00 AM Lukas Wunner <lukas@wunner.de> wrote:
> On Wed, Mar 02, 2022 at 11:56:00AM +0200, Ilpo Järvinen wrote:

...

> Does the DesignWare UART use dedicated DE and RE pins instead of
> the RTS pin?  That would be quite unusual.

They are muxed with other UART pins on SoC level, but I don't remember
by heart which ones. According to the Synopsys datasheet they are
separate signals. It might be that I'm missing something, since the
last time I looked was last year.

...

> > +     d->hw_rs485_support = device_property_read_bool(p->dev, "snps,rs485-interface-en");
> > +     if (d->hw_rs485_support)
> > +             p->rs485_config = dw8250_rs485_config;
> > +
>
> You wrote in the commit message that rs485 support is present from
> version 4.0 onward.  Can't we just check the IP version and enable
> rs485 support for >= 4.0?  That would seem more appropriate instead
> of introducing yet another new property.

AFAIU this is dependent on the IP syntheses. I.o.w. version 4.0+ is a
prerequisite, but doesn't automatically mean that there is a support.
Unfortunately there is no way to tell this clearly in the IP
configuration register.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH 3/7] serial: 8250_dwlib: Implement SW half duplex support
  2022-03-06 19:21   ` Lukas Wunner
@ 2022-03-06 22:13     ` Andy Shevchenko
  0 siblings, 0 replies; 48+ messages in thread
From: Andy Shevchenko @ 2022-03-06 22:13 UTC (permalink / raw)
  To: Lukas Wunner
  Cc: Ilpo Järvinen, open list:SERIAL DRIVERS, Jiri Slaby,
	Greg Kroah-Hartman, Linux Kernel Mailing List, Johan Hovold,
	Andy Shevchenko, Heikki Krogerus, Eric Tremblay,
	Uwe Kleine-König, Heiko Stübner, Giulio Benetti

On Mon, Mar 7, 2022 at 12:01 AM Lukas Wunner <lukas@wunner.de> wrote:
> On Wed, Mar 02, 2022 at 11:56:02AM +0200, Ilpo Järvinen wrote:
> > 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/
>
> I don't see any benefit in using software emulated RTS assertion
> if hardware support is present.  It just consumes more CPU time
> and is slower to deassert RTS, thereby increasing bus turn-around time.
>
> So if hardware support is present, I think you always want to
> use that and you need to fallback to software emulation only
> if hardware support is missing (i.e. on IP versions < 4).

No, this is not a good idea because presence of the HW support does
not guarantee we will have pins on PCB level and/or properly muxed by
firmware, or be able to be properly muxed by software (OS). Or am I
missing something here and you have an idea how to enable RS485 in
that case?

> The registers you're using here, DW_UART_RE_EN and DW_UART_DE_EN
> don't seem to be present on older IP versions.  I'm looking at
> the databook for version 3.04a and those registers aren't mentioned:
>
> https://linux-sunxi.org/images/d/d2/Dw_apb_uart_db.pdf
>
> So the software emulation you've implemented here won't help with
> older IP and the newer IP doesn't need it because it supports
> RTS assertion in hardware.  Is that correct?  If so, I'd suggest
> not supporting DW_UART_TCR_XFER_MODE_SW_DE_OR_RE at all.
>
> A number of people have attempted to add rs485 software emulation
> to 8250_dw.c but noone ever pursued it into mainline.  The last
> attempt was by Heiko Stübner, who used patches by Giulio Benetti (+cc):
>
> https://lore.kernel.org/linux-serial/20200517215610.2131618-1-heiko@sntech.de/
>
> FWIW, newer TI Sitara SoCs have also added hardware support for
> rs485 and in this (not yet upstreamed) patch, I likewise chose
> to use software emulation only if hardware support is not available:
>
> https://github.com/l1k/linux/commit/82c989617a05



-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 1/7] serial: 8250_dwlib: RS485 HW half duplex support
  2022-03-06 22:07     ` Andy Shevchenko
@ 2022-03-07  9:19       ` Ilpo Järvinen
  2022-03-07 19:18         ` Lukas Wunner
  0 siblings, 1 reply; 48+ messages in thread
From: Ilpo Järvinen @ 2022-03-07  9:19 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Lukas Wunner, open list:SERIAL DRIVERS, Jiri Slaby,
	Greg Kroah-Hartman, Linux Kernel Mailing List, Johan Hovold,
	Andy Shevchenko, Heikki Krogerus, Raymond Tan, Heiko Stuebner

[-- Attachment #1: Type: text/plain, Size: 1805 bytes --]

On Mon, 7 Mar 2022, Andy Shevchenko wrote:

> On Mon, Mar 7, 2022 at 12:00 AM Lukas Wunner <lukas@wunner.de> wrote:
> > On Wed, Mar 02, 2022 at 11:56:00AM +0200, Ilpo Järvinen wrote:
> 
> ...
> 
> > Does the DesignWare UART use dedicated DE and RE pins instead of
> > the RTS pin?  That would be quite unusual.
> 
> They are muxed with other UART pins on SoC level, but I don't remember
> by heart which ones. According to the Synopsys datasheet they are
> separate signals. It might be that I'm missing something, since the
> last time I looked was last year.

Unusual or not, there is a pin for both DE and RE. DE is muxed with RTS.

> > > +     d->hw_rs485_support = device_property_read_bool(p->dev, "snps,rs485-interface-en");
> > > +     if (d->hw_rs485_support)
> > > +             p->rs485_config = dw8250_rs485_config;
> > > +
> >
> > You wrote in the commit message that rs485 support is present from
> > version 4.0 onward.  Can't we just check the IP version and enable
> > rs485 support for >= 4.0?  That would seem more appropriate instead
> > of introducing yet another new property.
> 
> AFAIU this is dependent on the IP syntheses. I.o.w. version 4.0+ is a
> prerequisite, but doesn't automatically mean that there is a support.
> Unfortunately there is no way to tell this clearly in the IP
> configuration register.

And the IP synthesis only part of the picture, in general case, it'd
also matter that there's something connected to that RE (i.e.,
an RS485 transceiver).

On the board I'm testing with, I can also turn RS485 on/off from BIOS
which makes the pins (mainly RE) behave differently.

I initially had additional version check here while developing this
patch series but it seemed to not provide any added value due those
other factors that need to be considered.


-- 
 i.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 2/7] serial: 8250_dwlib: RS485 HW full duplex support
  2022-03-06 18:51   ` Lukas Wunner
@ 2022-03-07  9:22     ` Ilpo Järvinen
  0 siblings, 0 replies; 48+ messages in thread
From: Ilpo Järvinen @ 2022-03-07  9:22 UTC (permalink / raw)
  To: Lukas Wunner
  Cc: linux-serial, Jiri Slaby, Greg Kroah-Hartman, LKML, Johan Hovold,
	Andy Shevchenko, Heikki Krogerus, Raymond Tan

[-- Attachment #1: Type: text/plain, Size: 921 bytes --]

On Sun, 6 Mar 2022, Lukas Wunner wrote:

> On Wed, Mar 02, 2022 at 11:56:01AM +0200, Ilpo Järvinen wrote:
> > @@ -110,9 +110,14 @@ 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;
> > -
> > -		tcr |= DW_UART_TCR_RS485_EN | DW_UART_TCR_XFER_MODE_DE_OR_RE;
> > +		rs485->flags &= SER_RS485_ENABLED | SER_RS485_RX_DURING_TX;
> > +		tcr |= DW_UART_TCR_RS485_EN;
> > +
> > +		if (rs485->flags & SER_RS485_RX_DURING_TX) {
> > +			tcr |= DW_UART_TCR_XFER_MODE_DE_DURING_RE;
> > +		} else {
> > +			tcr |= DW_UART_TCR_XFER_MODE_DE_OR_RE;
> > +		}
> 
> This patch deletes lines introduced by the preceding patch.
> I'd just squash the two together, I don't see much value in
> introducing full duplex support in a separate patch.

Sure, I can merge them.

-- 
 i.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH 6/7] serial: General support for multipoint addresses
  2022-03-06 19:40     ` Lukas Wunner
  (?)
@ 2022-03-07  9:48       ` Ilpo Järvinen
  -1 siblings, 0 replies; 48+ messages in thread
From: Ilpo Järvinen @ 2022-03-07  9:48 UTC (permalink / raw)
  To: Lukas Wunner
  Cc: Heikki Krogerus, linux-sh, LKML, James E.J. Bottomley,
	Max Filippov, Rich Felker, Paul Mackerras, sparclinux, linux-api,
	Jiri Slaby, linux-arch, Yoshinori Sato, Helge Deller, linux-doc,
	linux-serial, Matt Turner, linux-xtensa, Arnd Bergmann,
	Johan Hovold, Ivan Kokshaysky, Andy Shevchenko,
	Richard Henderson, Chris Zankel, Thomas Bogendoerfer,
	linux-parisc, Greg Kroah-Hartman, linux-mips, linux-alpha,
	linuxppc-dev, David S. Miller

[-- Attachment #1: Type: text/plain, Size: 1350 bytes --]

On Sun, 6 Mar 2022, Lukas Wunner wrote:

> On Wed, Mar 02, 2022 at 11:56:05AM +0200, Ilpo Järvinen wrote:
> 
> > This change is necessary for supporting devices with RS485
> > multipoint addressing [*].
> 
> If this is only used with RS485, why can't we just store the
> addresses in struct serial_rs485 and use the existing TIOCSRS485
> and TIOCGRS485 ioctls?  There's 20 bytes of padding left in
> struct serial_rs485 which you could use.  No need to add more
> user-space ABI.

It could if it is agreed that serial multipoint addressing is just
a thing in RS-485 and nowhere else? In that case, there is no point
in adding more generic support for it.

> > [*] Technically, RS485 is just an electronic spec and does not
> > itself specify the 9th bit addressing mode but 9th bit seems
> > at least "semi-standard" way to do addressing with RS485.
> 
> Is 9th bit addressing actually used by an Intel customer or was
> it implemented just for feature completeness? I think this mode
> isn't used often (I've never seen a use case myself), primarily
> because it requires disabling parity.

On what basis? ...The datasheet I'm looking at has a timing diagram 
with both D8 (9th bit) and parity so I think your information must be
incorrect. I don't have direct contacts with customers but I'm told
it's important for other org's customers.


-- 
 i.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH 6/7] serial: General support for multipoint addresses
@ 2022-03-07  9:48       ` Ilpo Järvinen
  0 siblings, 0 replies; 48+ messages in thread
From: Ilpo Järvinen @ 2022-03-07  9:48 UTC (permalink / raw)
  To: Lukas Wunner
  Cc: linux-serial, Jiri Slaby, Greg Kroah-Hartman, LKML, Johan Hovold,
	Andy Shevchenko, Heikki Krogerus, linux-api, Richard Henderson,
	Ivan Kokshaysky, Matt Turner, linux-alpha, Thomas Bogendoerfer,
	linux-mips, James E.J. Bottomley, Helge Deller, linux-parisc,
	Michael Ellerman, Benjamin Herrenschmidt, Paul Mackerras,
	linuxppc-dev, Yoshinori Sato, Rich Felker, linux-sh,
	David S. Miller, sparclinux, Chris Zankel, Max Filippov,
	linux-xtensa, Arnd Bergmann, linux-arch, linux-doc

[-- Attachment #1: Type: text/plain, Size: 1350 bytes --]

On Sun, 6 Mar 2022, Lukas Wunner wrote:

> On Wed, Mar 02, 2022 at 11:56:05AM +0200, Ilpo Järvinen wrote:
> 
> > This change is necessary for supporting devices with RS485
> > multipoint addressing [*].
> 
> If this is only used with RS485, why can't we just store the
> addresses in struct serial_rs485 and use the existing TIOCSRS485
> and TIOCGRS485 ioctls?  There's 20 bytes of padding left in
> struct serial_rs485 which you could use.  No need to add more
> user-space ABI.

It could if it is agreed that serial multipoint addressing is just
a thing in RS-485 and nowhere else? In that case, there is no point
in adding more generic support for it.

> > [*] Technically, RS485 is just an electronic spec and does not
> > itself specify the 9th bit addressing mode but 9th bit seems
> > at least "semi-standard" way to do addressing with RS485.
> 
> Is 9th bit addressing actually used by an Intel customer or was
> it implemented just for feature completeness? I think this mode
> isn't used often (I've never seen a use case myself), primarily
> because it requires disabling parity.

On what basis? ...The datasheet I'm looking at has a timing diagram 
with both D8 (9th bit) and parity so I think your information must be
incorrect. I don't have direct contacts with customers but I'm told
it's important for other org's customers.


-- 
 i.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH 6/7] serial: General support for multipoint addresses
@ 2022-03-07  9:48       ` Ilpo Järvinen
  0 siblings, 0 replies; 48+ messages in thread
From: Ilpo Järvinen @ 2022-03-07  9:48 UTC (permalink / raw)
  To: Lukas Wunner
  Cc: Heikki Krogerus, linux-sh, LKML, James E.J. Bottomley,
	Max Filippov, Rich Felker, Paul Mackerras, sparclinux, linux-api,
	Jiri Slaby, linux-arch, Yoshinori Sato, Helge Deller, linux-doc,
	linux-serial, Matt Turner, linux-xtensa, Arnd Bergmann,
	Johan Hovold, Ivan Kokshaysky, Andy Shevchenko,
	Richard Henderson, Chris Zankel, Thomas Bogendoerfer

[-- Attachment #1: Type: text/plain, Size: 1383 bytes --]

On Sun, 6 Mar 2022, Lukas Wunner wrote:

> On Wed, Mar 02, 2022 at 11:56:05AM +0200, Ilpo Järvinen wrote:
> 
> > This change is necessary for supporting devices with RS485
> > multipoint addressing [*].
> 
> If this is only used with RS485, why can't we just store the
> addresses in struct serial_rs485 and use the existing TIOCSRS485
> and TIOCGRS485 ioctls?  There's 20 bytes of padding left in
> struct serial_rs485 which you could use.  No need to add more
> user-space ABI.

It could if it is agreed that serial multipoint addressing is just
a thing in RS-485 and nowhere else? In that case, there is no point
in adding more generic support for it.

> > [*] Technically, RS485 is just an electronic spec and does not
> > itself specify the 9th bit addressing mode but 9th bit seems
> > at least "semi-standard" way to do addressing with RS485.
> 
> Is 9th bit addressing actually used by an Intel customer or was
> it implemented just for feature completeness? I think this mode
> isn't used often (I've never seen a use case myself), primarily
> because it requires disabling parity.

On what basis? ...The datasheet I'm looking at has a timing diagram 
with both D8 (9th bit) and parity so I think your information must be
incorrect. I don't have direct contacts with customers but I'm told
it's important for other org's customers.


-- 
 i.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 1/7] serial: 8250_dwlib: RS485 HW half duplex support
  2022-03-06 18:48   ` Lukas Wunner
  2022-03-06 22:07     ` Andy Shevchenko
@ 2022-03-07 10:54     ` Ilpo Järvinen
  2022-03-09  8:52       ` Lukas Wunner
  2022-03-09 12:19       ` Ilpo Järvinen
  1 sibling, 2 replies; 48+ messages in thread
From: Ilpo Järvinen @ 2022-03-07 10:54 UTC (permalink / raw)
  To: Lukas Wunner
  Cc: linux-serial, Jiri Slaby, Greg Kroah-Hartman, LKML, Johan Hovold,
	Andy Shevchenko, Heikki Krogerus, Raymond Tan, Heiko Stuebner,
	Rob Herring

[-- Attachment #1: Type: text/plain, Size: 3920 bytes --]

On Sun, 6 Mar 2022, Lukas Wunner wrote:

> On Wed, Mar 02, 2022 at 11:56:00AM +0200, Ilpo Järvinen wrote:
>
> > +		rs485->flags &= SER_RS485_ENABLED;
> > +
> > +		tcr |= DW_UART_TCR_RS485_EN | DW_UART_TCR_XFER_MODE_DE_OR_RE;
> > +		dw8250_writel_ext(p, DW_UART_DE_EN, 1);
> > +		dw8250_writel_ext(p, DW_UART_RE_EN, 1);
> > +	} else {
> > +		rs485->flags = 0;
> > +
> > +		tcr &= ~DW_UART_TCR_RS485_EN;
> > +		dw8250_writel_ext(p, DW_UART_DE_EN, 0);
> > +		dw8250_writel_ext(p, DW_UART_RE_EN, 0);
> 
> Do the DW_UART_DE_EN and DW_UART_RE_EN registers have any effect at all
> if DW_UART_TCR_RS485_EN is disabled in the TCR register?
> 
> If they don't, there's no need to clear them here.  It would be sufficient
> to set them once (e.g. on probe).

They have no impact when in non-RS485 mode. I just removed them.

> > +	if (device_property_read_bool(p->dev, "snps,de-active-high"))
> > +		tcr |= DW_UART_TCR_DE_POL;
> 
> That device property is a duplication of the existing "rs485-rts-active-low"
> property.  Please use the existing one unless there are devices already
> in the field which use the new property (in which case that should be
> provided as justification in the commit message).
>
> Does the DesignWare UART use dedicated DE and RE pins instead of
> the RTS pin?  That would be quite unusual.
>
> > +	if (device_property_read_bool(p->dev, "snps,re-active-high"))
> > +		tcr |= DW_UART_TCR_RE_POL;
> 
> Heiko Stübner (+cc) posted patches in 2020 to support a separate RE pin
> in addition to a DE pin (which is usually simply the RTS pin):
> 
> https://lore.kernel.org/linux-serial/20200517215610.2131618-4-heiko@sntech.de/
> 
> He called the devicetree property for the pin "rs485-rx-enable",
> so perhaps "rs485-rx-active-low" would be a better name here.

While I believe there exist devices on the field with 
snps,re-active-high set to true, if the default matches to that, the 
impact of the naming mismatch will be near zero (likely zero).

Based on the Rob's earlier comment on the dt patch itself. I had already 
plans on changing these. My thought was to make it like this:
- rs485-de-active-low
- rs485-re-active-high

I don't have strong opinion on the actual names myself (every RS-485 
transceivers I've come across name their pins to DE and RE).

Given that you seemed to consider DE "unusual" despite being reality
with this hw, I don't know whether you still think the meaning of 
rs485-rts-active-low should be overloaded to also mean rs485-de-active-low?
(I think such overloading would be harmless so I'm not exactly opposing
other than noting FW/HW folks might find it odd to misname it to rts.)

What I think is more important though, is that RE would be by default
active low which matches to about every RS485 transceiver expectations.
Given what device_property_read_bool does when the property is missing,
it would make sense to have the property named as -active-high but I
don't know if that breaks some dt naming rule to have them opposites
of each other like that?

> > +	/*
> > +	 * XXX: Though we could interpret the "RTS" timings as Driver Enable
> > +	 * (DE) assertion/de-assertion timings, initially not supporting that.
> > +	 * Ideally we should have timing values for the Driver instead of the
> > +	 * RTS signal.
> > +	 */
> > +	rs485->delay_rts_before_send = 0;
> > +	rs485->delay_rts_after_send = 0;
> 
> I don't quite understand this code comment.

It seemed to be missing one "Enable" word.

Here's my interpretation of it (this comment was written by somebody 
else, perhaps either Heikki or Andy):

Since this HW has dedicated DE/RE in contrast to RTS, it is not specified 
anywhere that delay_rts_* should apply to them as well and that the 
writer of that comment was hoping to have something dedicated to them
rather than repurposing RTS-related fields.

I could of course change this if everything called RTS should be applied 
to DE as well?


-- 
 i.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 1/7] serial: 8250_dwlib: RS485 HW half duplex support
  2022-03-07  9:19       ` Ilpo Järvinen
@ 2022-03-07 19:18         ` Lukas Wunner
  2022-03-07 19:39           ` Andy Shevchenko
  0 siblings, 1 reply; 48+ messages in thread
From: Lukas Wunner @ 2022-03-07 19:18 UTC (permalink / raw)
  To: Ilpo Järvinen
  Cc: Andy Shevchenko, open list:SERIAL DRIVERS, Jiri Slaby,
	Greg Kroah-Hartman, Linux Kernel Mailing List, Johan Hovold,
	Andy Shevchenko, Heikki Krogerus, Raymond Tan, Heiko Stuebner

On Mon, Mar 07, 2022 at 11:19:59AM +0200, Ilpo Järvinen wrote:
> On Mon, 7 Mar 2022, Andy Shevchenko wrote:
> > On Mon, Mar 7, 2022 at 12:00 AM Lukas Wunner <lukas@wunner.de> wrote:
> > > On Wed, Mar 02, 2022 at 11:56:00AM +0200, Ilpo Järvinen wrote:
> > > > +     d->hw_rs485_support = device_property_read_bool(p->dev, "snps,rs485-interface-en");
> > > > +     if (d->hw_rs485_support)
> > > > +             p->rs485_config = dw8250_rs485_config;
> > > > +
> > >
> > > You wrote in the commit message that rs485 support is present from
> > > version 4.0 onward.  Can't we just check the IP version and enable
> > > rs485 support for >= 4.0?  That would seem more appropriate instead
> > > of introducing yet another new property.
> > 
> > AFAIU this is dependent on the IP syntheses. I.o.w. version 4.0+ is a
> > prerequisite, but doesn't automatically mean that there is a support.
> > Unfortunately there is no way to tell this clearly in the IP
> > configuration register.
> 
> And the IP synthesis only part of the picture, in general case, it'd
> also matter that there's something connected to that RE (i.e.,
> an RS485 transceiver).

If an RS-485 transceiver is *soldered* to the UART, the devicetree
is supposed to contain the property "linux,rs485-enabled-at-boot-time"
under the UART's of_node.  In that case the UART driver can (and should)
enable rs485 mode already on ->probe.

Of course there's also the possibility to enable RS-485 after ->open
with the TIOCSRS485 ioctl.  That can be used if the transceiver is
attached at runtime (which is likely a rare use case) or as a legacy
enablement method if the driver lacks linux,rs485-enabled-at-boot-time
support.

That's for DT platforms, but I suppose you've got ACPI.  Not sure
how it's handled there, the ACPI 6.4 spec contains a "UART Serial Bus
Connection Resource Descriptor" but nothing on RS-485, so I guess
the only option is to use regular DT properties in a _DSD object?


> I initially had additional version check here while developing this
> patch series but it seemed to not provide any added value due those
> other factors that need to be considered.

Here's another idea:

Read TCR register on ->probe.  It's POR value is 0x6 if RS-485 is
supported by the chip, else 0x0.  (Page 220 of the 4.01a spec says
UCV register does not exist if additional features are not implemented
and reading from this register address returns 0, I suppose the same
applies to TCR if RS-485 is not implemented.)

Since the driver may change the polarity in the TCR register, be sure
to write 0x6 to it on ->remove so that you can still correctly detect
presence of the RS-485 feature after unbind/rebind of the driver.

Thanks,

Lukas

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 1/7] serial: 8250_dwlib: RS485 HW half duplex support
  2022-03-07 19:18         ` Lukas Wunner
@ 2022-03-07 19:39           ` Andy Shevchenko
  2022-03-08 12:16             ` Ilpo Järvinen
  0 siblings, 1 reply; 48+ messages in thread
From: Andy Shevchenko @ 2022-03-07 19:39 UTC (permalink / raw)
  To: Lukas Wunner
  Cc: Ilpo Järvinen, open list:SERIAL DRIVERS, Jiri Slaby,
	Greg Kroah-Hartman, Linux Kernel Mailing List, Johan Hovold,
	Heikki Krogerus, Raymond Tan, Heiko Stuebner

On Mon, Mar 07, 2022 at 08:18:54PM +0100, Lukas Wunner wrote:
> On Mon, Mar 07, 2022 at 11:19:59AM +0200, Ilpo Järvinen wrote:
> > On Mon, 7 Mar 2022, Andy Shevchenko wrote:

...

> That's for DT platforms, but I suppose you've got ACPI.  Not sure
> how it's handled there, the ACPI 6.4 spec contains a "UART Serial Bus
> Connection Resource Descriptor" but nothing on RS-485, so I guess
> the only option is to use regular DT properties in a _DSD object?

Which make me think that this series needs an additional patch to
describe RS485 enumeration for ACPI case (somewhere in
Documentation/firmware-guide/acpi/enumeration.rst IIRC the filename).

...

> > I initially had additional version check here while developing this
> > patch series but it seemed to not provide any added value due those
> > other factors that need to be considered.
> 
> Here's another idea:
> 
> Read TCR register on ->probe.  It's POR value is 0x6 if RS-485 is
> supported by the chip, else 0x0.  (Page 220 of the 4.01a spec says
> UCV register does not exist if additional features are not implemented
> and reading from this register address returns 0, I suppose the same
> applies to TCR if RS-485 is not implemented.)
> 
> Since the driver may change the polarity in the TCR register, be sure
> to write 0x6 to it on ->remove so that you can still correctly detect
> presence of the RS-485 feature after unbind/rebind of the driver.

What to do in the case when DE pin is muxed to RTS and locked in pin control
IP by firmware (no possibility to change the muxing in the OS)?

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 1/7] serial: 8250_dwlib: RS485 HW half duplex support
  2022-03-07 19:39           ` Andy Shevchenko
@ 2022-03-08 12:16             ` Ilpo Järvinen
  2022-03-08 12:22               ` Lukas Wunner
  0 siblings, 1 reply; 48+ messages in thread
From: Ilpo Järvinen @ 2022-03-08 12:16 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Lukas Wunner, open list:SERIAL DRIVERS, Jiri Slaby,
	Greg Kroah-Hartman, Linux Kernel Mailing List, Johan Hovold,
	Heikki Krogerus, Raymond Tan, Heiko Stuebner

[-- Attachment #1: Type: text/plain, Size: 1852 bytes --]

On Mon, 7 Mar 2022, Andy Shevchenko wrote:

> On Mon, Mar 07, 2022 at 08:18:54PM +0100, Lukas Wunner wrote:
> > On Mon, Mar 07, 2022 at 11:19:59AM +0200, Ilpo Järvinen wrote:
> > > On Mon, 7 Mar 2022, Andy Shevchenko wrote:
> 
> ...
> 
> > That's for DT platforms, but I suppose you've got ACPI.  Not sure
> > how it's handled there, the ACPI 6.4 spec contains a "UART Serial Bus
> > Connection Resource Descriptor" but nothing on RS-485, so I guess
> > the only option is to use regular DT properties in a _DSD object?
> 
> Which make me think that this series needs an additional patch to
> describe RS485 enumeration for ACPI case (somewhere in
> Documentation/firmware-guide/acpi/enumeration.rst IIRC the filename).
> 
> ...
> 
> > > I initially had additional version check here while developing this
> > > patch series but it seemed to not provide any added value due those
> > > other factors that need to be considered.
> > 
> > Here's another idea:
> > 
> > Read TCR register on ->probe.  It's POR value is 0x6 if RS-485 is
> > supported by the chip, else 0x0.  (Page 220 of the 4.01a spec says
> > UCV register does not exist if additional features are not implemented
> > and reading from this register address returns 0, I suppose the same
> > applies to TCR if RS-485 is not implemented.)
> > 
> > Since the driver may change the polarity in the TCR register, be sure
> > to write 0x6 to it on ->remove so that you can still correctly detect
> > presence of the RS-485 feature after unbind/rebind of the driver.
> 
> What to do in the case when DE pin is muxed to RTS and locked in pin control
> IP by firmware (no possibility to change the muxing in the OS)?

The SoC also has a pin to select between RS485 and RS232. With a combo 
transceiver, TCR-based heuristic just runs into the same problems as the 
version-based one did.


-- 
 i.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 1/7] serial: 8250_dwlib: RS485 HW half duplex support
  2022-03-08 12:16             ` Ilpo Järvinen
@ 2022-03-08 12:22               ` Lukas Wunner
  2022-03-08 12:59                 ` Ilpo Järvinen
  0 siblings, 1 reply; 48+ messages in thread
From: Lukas Wunner @ 2022-03-08 12:22 UTC (permalink / raw)
  To: Ilpo Järvinen
  Cc: Andy Shevchenko, open list:SERIAL DRIVERS, Jiri Slaby,
	Greg Kroah-Hartman, Linux Kernel Mailing List, Johan Hovold,
	Heikki Krogerus, Raymond Tan, Heiko Stuebner

On Tue, Mar 08, 2022 at 02:16:56PM +0200, Ilpo Järvinen wrote:
> The SoC also has a pin to select between RS485 and RS232. With a combo 
> transceiver, TCR-based heuristic just runs into the same problems as the 
> version-based one did.

I thought this was about detecting whether hardware-assisted DE assertion
may be used (versus software-controlled), not about whether to enable
RS-485 mode.  Right?

Thanks,

Lukas

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 1/7] serial: 8250_dwlib: RS485 HW half duplex support
  2022-03-08 12:22               ` Lukas Wunner
@ 2022-03-08 12:59                 ` Ilpo Järvinen
  2022-03-08 14:50                   ` Lukas Wunner
  0 siblings, 1 reply; 48+ messages in thread
From: Ilpo Järvinen @ 2022-03-08 12:59 UTC (permalink / raw)
  To: Lukas Wunner
  Cc: Andy Shevchenko, open list:SERIAL DRIVERS, Jiri Slaby,
	Greg Kroah-Hartman, Linux Kernel Mailing List, Johan Hovold,
	Heikki Krogerus, Raymond Tan, Heiko Stuebner

[-- Attachment #1: Type: text/plain, Size: 670 bytes --]

On Tue, 8 Mar 2022, Lukas Wunner wrote:

> On Tue, Mar 08, 2022 at 02:16:56PM +0200, Ilpo Järvinen wrote:
> > The SoC also has a pin to select between RS485 and RS232. With a combo 
> > transceiver, TCR-based heuristic just runs into the same problems as the 
> > version-based one did.
> 
> I thought this was about detecting whether hardware-assisted DE assertion
> may be used (versus software-controlled), not about whether to enable
> RS-485 mode.  Right?

HW DE assertion only works when RS485 mode is enabled so I don't see how 
these questions could be easily decoupled like that. That's assuming with 
"software-controlled" you mean RTS(RS232)+em485?


-- 
 i.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 1/7] serial: 8250_dwlib: RS485 HW half duplex support
  2022-03-08 12:59                 ` Ilpo Järvinen
@ 2022-03-08 14:50                   ` Lukas Wunner
  2022-03-08 14:53                     ` Andy Shevchenko
  0 siblings, 1 reply; 48+ messages in thread
From: Lukas Wunner @ 2022-03-08 14:50 UTC (permalink / raw)
  To: Ilpo Järvinen
  Cc: Andy Shevchenko, open list:SERIAL DRIVERS, Jiri Slaby,
	Greg Kroah-Hartman, Linux Kernel Mailing List, Johan Hovold,
	Heikki Krogerus, Raymond Tan, Heiko Stuebner

On Tue, Mar 08, 2022 at 02:59:59PM +0200, Ilpo Järvinen wrote:
> On Tue, 8 Mar 2022, Lukas Wunner wrote:
> > On Tue, Mar 08, 2022 at 02:16:56PM +0200, Ilpo Järvinen wrote:
> > > The SoC also has a pin to select between RS485 and RS232. With a combo 
> > > transceiver, TCR-based heuristic just runs into the same problems as the 
> > > version-based one did.
> > 
> > I thought this was about detecting whether hardware-assisted DE assertion
> > may be used (versus software-controlled), not about whether to enable
> > RS-485 mode.  Right?
> 
> HW DE assertion only works when RS485 mode is enabled so I don't see how 
> these questions could be easily decoupled like that. That's assuming with 
> "software-controlled" you mean RTS(RS232)+em485?

Right, that's what I meant.

Enabling RS-485 mode is only supposed to happen upon a TIOCSRS485 ioctl
or if the "linux,rs485-enabled-at-boot-time" property is present.
We don't need to second-guess the user's decision to enable RS-485 mode.
If that's what they've asked for, then we can and should assume that an
RS-485 transceiver is attached.

Of course, if hardware-assisted DE assertion requires a particular pinmux
state, we could double-check whether that pinmux state is set.  If the
RTS/DE pin is not muxed as a DE pin but rather as an RTS pin, one option
would be to fall back to software-controlled RTS assertion.  A warning
message may be warranted in that case.

Whether hardware-assisted DE assertion is supported by the chip can not
only be detected by checking for the POR 0x6 value in the TCR register:
You can alternatively write a non-zero value to any of the RS-485 registers,
then check if reading the register back returns a non-zero value
(RE_EN is probably a good candidate).  That approach is more robust
than relying on the POR value 0x6 in TCR because you never know if
boot firmware fiddled with the registers before passing control to the
kernel.

Thanks,

Lukas

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 1/7] serial: 8250_dwlib: RS485 HW half duplex support
  2022-03-08 14:50                   ` Lukas Wunner
@ 2022-03-08 14:53                     ` Andy Shevchenko
  2022-03-08 20:30                       ` Lukas Wunner
  0 siblings, 1 reply; 48+ messages in thread
From: Andy Shevchenko @ 2022-03-08 14:53 UTC (permalink / raw)
  To: Lukas Wunner
  Cc: Ilpo Järvinen, open list:SERIAL DRIVERS, Jiri Slaby,
	Greg Kroah-Hartman, Linux Kernel Mailing List, Johan Hovold,
	Heikki Krogerus, Raymond Tan, Heiko Stuebner

On Tue, Mar 8, 2022 at 4:50 PM Lukas Wunner <lukas@wunner.de> wrote:
> On Tue, Mar 08, 2022 at 02:59:59PM +0200, Ilpo Järvinen wrote:

...

> Of course, if hardware-assisted DE assertion requires a particular pinmux
> state, we could double-check whether that pinmux state is set.

I'm wondering how to achieve this.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 1/7] serial: 8250_dwlib: RS485 HW half duplex support
  2022-03-08 14:53                     ` Andy Shevchenko
@ 2022-03-08 20:30                       ` Lukas Wunner
  2022-03-09  9:51                         ` Ilpo Järvinen
  0 siblings, 1 reply; 48+ messages in thread
From: Lukas Wunner @ 2022-03-08 20:30 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Ilpo Järvinen, open list:SERIAL DRIVERS, Jiri Slaby,
	Greg Kroah-Hartman, Linux Kernel Mailing List, Johan Hovold,
	Heikki Krogerus, Raymond Tan, Heiko Stuebner

On Tue, Mar 08, 2022 at 04:53:56PM +0200, Andy Shevchenko wrote:
> On Tue, Mar 8, 2022 at 4:50 PM Lukas Wunner <lukas@wunner.de> wrote:
> > Of course, if hardware-assisted DE assertion requires a particular pinmux
> > state, we could double-check whether that pinmux state is set.
> 
> I'm wondering how to achieve this.

On DT platforms, the devicetree specifies the pin controller settings
which need to be configured for a device to be usable, e.g.:

  pinctrl-names = "default";
  pinctrl-0 = <...>;

Before a driver is bound to the device, really_probe() in drivers/base/dd.c
calls pinctrl_bind_pins() which configures the pin controller accordingly.
In other words, the OS is fully in charge of configuring the pinmux.

I'm not sure how this is done on ACPI platforms.  If the pinmux is
exclusively under the control of the platform firmware and the OS has
no way of getting or setting the pinmux configuration, then that would
be a competitive disadvantage vis-à-vis DT platforms which should really
be addressed.  However I notice there are various drivers for Intel
chipsets in drivers/pinctrl/intel/, so surely there's a way to let the
OS handle pinmux settings?

Thanks,

Lukas

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 1/7] serial: 8250_dwlib: RS485 HW half duplex support
  2022-03-07 10:54     ` Ilpo Järvinen
@ 2022-03-09  8:52       ` Lukas Wunner
  2022-03-09 12:19       ` Ilpo Järvinen
  1 sibling, 0 replies; 48+ messages in thread
From: Lukas Wunner @ 2022-03-09  8:52 UTC (permalink / raw)
  To: Ilpo Järvinen
  Cc: linux-serial, Jiri Slaby, Greg Kroah-Hartman, LKML, Johan Hovold,
	Andy Shevchenko, Heikki Krogerus, Raymond Tan, Heiko Stuebner,
	Rob Herring

On Mon, Mar 07, 2022 at 12:54:19PM +0200, Ilpo Järvinen wrote:
> I don't have strong opinion on the actual names myself (every RS-485 
> transceivers I've come across name their pins to DE and RE).

It's true that transceiver datasheets usually call these pins DE and RE,
but on the UART side, by convention the RTS pin is used to drive DE.

And RTS is then either asserted/deasserted in software (by the kernel
driver), or by the UART hardware if it's capable of it.

Hence the properties in Documentation/devicetree/bindings/serial/rs485.yaml
and the members in struct serial_rs485 refer to "rts".  It's synonymous
to DE.  I suppose Synopsys wanted to afford the integrator of the IP core
as much freedom as possible and therefore offers separate RTS+DE pins
as well as an RE pin.  But that degree of freedom also leads to confusion,
particularly if firmware might mux the pins in an unexpected way
behind the OS's back.

The RE pin of transceivers is usually either pulled-up (i.e. always
asserted, full-duplex) or connected to negated RTS (half-duplex).
A lot of transceivers have a !RE pin so RTS can be wired directly
to DE and !RE.

Full-duplex is primarily for RS-422.  If full-duplex is enabled with
RS-485, you'll receive your own echo, which is often (but not always)
undesirable (depends on the application).

For simplicity and consistency, it is best if the existing properties
defined in rs485.yaml are used, instead of defining new ones which
have the same meaning.  For this reason I'd recommend using
rs485-rts-active-low for the polarity of the DE pin.


> What I think is more important though, is that RE would be by default
> active low which matches to about every RS485 transceiver expectations.
> Given what device_property_read_bool does when the property is missing,
> it would make sense to have the property named as -active-high but I
> don't know if that breaks some dt naming rule to have them opposites
> of each other like that?

That's a good point, I agree.  I don't think that would violate any
DT naming rule.

Thanks,

Lukas

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 1/7] serial: 8250_dwlib: RS485 HW half duplex support
  2022-03-08 20:30                       ` Lukas Wunner
@ 2022-03-09  9:51                         ` Ilpo Järvinen
  0 siblings, 0 replies; 48+ messages in thread
From: Ilpo Järvinen @ 2022-03-09  9:51 UTC (permalink / raw)
  To: Lukas Wunner
  Cc: Andy Shevchenko, open list:SERIAL DRIVERS, Jiri Slaby,
	Greg Kroah-Hartman, Linux Kernel Mailing List, Johan Hovold,
	Heikki Krogerus, Raymond Tan, Heiko Stuebner

[-- Attachment #1: Type: text/plain, Size: 2155 bytes --]

On Tue, 8 Mar 2022, Lukas Wunner wrote:

> On Tue, Mar 08, 2022 at 04:53:56PM +0200, Andy Shevchenko wrote:
> > On Tue, Mar 8, 2022 at 4:50 PM Lukas Wunner <lukas@wunner.de> wrote:
> > > Of course, if hardware-assisted DE assertion requires a particular pinmux
> > > state, we could double-check whether that pinmux state is set.
> > 
> > I'm wondering how to achieve this.
> 
> On DT platforms, the devicetree specifies the pin controller settings
> which need to be configured for a device to be usable, e.g.:
> 
>   pinctrl-names = "default";
>   pinctrl-0 = <...>;
> 
> Before a driver is bound to the device, really_probe() in drivers/base/dd.c
> calls pinctrl_bind_pins() which configures the pin controller accordingly.
> In other words, the OS is fully in charge of configuring the pinmux.
> 
> I'm not sure how this is done on ACPI platforms.  If the pinmux is
> exclusively under the control of the platform firmware and the OS has
> no way of getting or setting the pinmux configuration, then that would
> be a competitive disadvantage vis-à-vis DT platforms which should really
> be addressed.  However I notice there are various drivers for Intel
> chipsets in drivers/pinctrl/intel/, so surely there's a way to let the
> OS handle pinmux settings?

The problem here is that the driver ("we could double-check" in your 
initial suggestion above) doesn't know which pins it should check the 
states for. I don't think any general mapping exists between drivers and 
pins.

Based on what I read, the mapping is a feature not wanted into pinmuxing.
Assuming I understood them correctly, they don't want to do such thing
on kernel side (based on experience with earlier approaches with 
mapping. It probably got too messy/unmaintainable in the end :-)).
So at best, one can only read and control pin mux states but that's about 
as far as pinmuxing in kernel goes (and control could be locked by FW).

Anyway, I've implemented the detection now based on RE_EN non-zero write + 
read + check based on your suggestion (despite still thinking myself it 
has these obvious problems with pinmux & other hw config unrelated dw uart 
itself).


-- 
 i.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 1/7] serial: 8250_dwlib: RS485 HW half duplex support
  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
  1 sibling, 1 reply; 48+ messages in thread
From: Ilpo Järvinen @ 2022-03-09 12:19 UTC (permalink / raw)
  To: Lukas Wunner
  Cc: linux-serial, Jiri Slaby, Greg Kroah-Hartman, LKML, Johan Hovold,
	Andy Shevchenko, Heikki Krogerus, Raymond Tan, Heiko Stuebner,
	Rob Herring

[-- Attachment #1: Type: text/plain, Size: 2116 bytes --]

On Mon, 7 Mar 2022, Ilpo Järvinen wrote:

> On Sun, 6 Mar 2022, Lukas Wunner wrote:
> 
> > On Wed, Mar 02, 2022 at 11:56:00AM +0200, Ilpo Järvinen wrote:
> 
> > > +	/*
> > > +	 * XXX: Though we could interpret the "RTS" timings as Driver Enable
> > > +	 * (DE) assertion/de-assertion timings, initially not supporting that.
> > > +	 * Ideally we should have timing values for the Driver instead of the
> > > +	 * RTS signal.
> > > +	 */
> > > +	rs485->delay_rts_before_send = 0;
> > > +	rs485->delay_rts_after_send = 0;
> > 
> > I don't quite understand this code comment.
> 
> It seemed to be missing one "Enable" word.
> 
> Here's my interpretation of it (this comment was written by somebody 
> else, perhaps either Heikki or Andy):
> 
> Since this HW has dedicated DE/RE in contrast to RTS, it is not specified 
> anywhere that delay_rts_* should apply to them as well and that the 
> writer of that comment was hoping to have something dedicated to them
> rather than repurposing RTS-related fields.
> 
> I could of course change this if everything called RTS should be applied 
> to DE as well?

Now that it has been pretty much established that anything called "rts" 
should be applied to DE as well, I took another look on implementing these 
delays.

It turns out to be impractical to do/ineffective because "serial clock 
periods" are used as the unit by the HW ("serial clock periods" is not as 
clearly defined by the datasheet as I'd like but it is most likely based 
on the high-rated uartclk cycles). With the uartclk I've on test HW, the 
combined delay with max turnaround time and DE assert/de-assert timings 
cannot do even the smallest possible non-zero value (1 msec). That's 
because the TAT and DET registers allow only 16-bit and 8-bit values for 
delays.

I also attempted to test it by writing the maximum values into them and 
got no visible difference. There a note about +1 for delay in TAT so to 
play safe I put 0xfff0 instead 0xffff (if the HW couldn't handle that 
16-bit overflow properly).

Perhaps the SW half-duplex with DE/RE will have to be used to cover this 
case?


-- 
 i.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 1/7] serial: 8250_dwlib: RS485 HW half duplex support
  2022-03-09 12:19       ` Ilpo Järvinen
@ 2022-03-09 12:59         ` Lukas Wunner
  0 siblings, 0 replies; 48+ messages in thread
From: Lukas Wunner @ 2022-03-09 12:59 UTC (permalink / raw)
  To: Ilpo Järvinen
  Cc: linux-serial, Jiri Slaby, Greg Kroah-Hartman, LKML, Johan Hovold,
	Andy Shevchenko, Heikki Krogerus, Raymond Tan, Heiko Stuebner,
	Rob Herring

On Wed, Mar 09, 2022 at 02:19:39PM +0200, Ilpo Järvinen wrote:
> Now that it has been pretty much established that anything called "rts" 
> should be applied to DE as well, I took another look on implementing these 
> delays.
> 
> It turns out to be impractical to do/ineffective because "serial clock 
> periods" are used as the unit by the HW ("serial clock periods" is not as 
> clearly defined by the datasheet as I'd like but it is most likely based 
> on the high-rated uartclk cycles). With the uartclk I've on test HW, the 
> combined delay with max turnaround time and DE assert/de-assert timings 
> cannot do even the smallest possible non-zero value (1 msec). That's 
> because the TAT and DET registers allow only 16-bit and 8-bit values for 
> delays.

A mistake was made when RS-485 support was introduced in the kernel
more than 10 years ago with commits c26c56c0 and 93f3350c:

The delays were defined in msec, but if you look at datasheets of
RS-485 transceivers, they only need a delay in the nanosecond or
single-digit usec range.

Here's a collection of delays I compiled two years ago:

                                 DrvEnable-to-Output    DriverPropagation
          MAX13450E/MAX13451E    5200 ns                 800 ns
          MAXM22510              2540 ns                1040 ns
          MAXM22511                80 ns                  65 ns
          SN65HVD72              9000 ns                1000 ns
          SN65HVD75              7000 ns                  17 ns
          SN65HVD78              8000 ns                  15 ns
          SN65HVD485E            2600 ns                  30 ns
          ADM1486                  15 ns                  17 ns
          ADM3485/ADM3490/ADM3491 900 ns                  35 ns
          ADM3483/ADM3488        1300 ns                1500 ns
          XR33193                2000 ns                1300 ns

Because these delays are so short, it is usually sufficient to set
them to zero in struct serial_rs485.

I've begun a commit to change the delays to nsec, it's still a WIP:

https://github.com/l1k/linux/commit/2c08878b63d6

This is a little tricky because the delays are user-space ABI,
so great care is needed to avoid breakage.  Also, every rs485
driver with support for delays needs to be touched.  Some
UARTs have fixed delays which depend on different clocks,
other UARTs support configurable delays.  Another complication
is that delay calculations easily overflow with nsec because
the numbers become quite large.

A positive side effect of changing the delays to nsec is that
the horrible hrtimer kludge for rs485 software emulation in the
8250_port.c can be eliminated.  Also, all the illegal mdelay()s
in spinlocked context (e.g. serial console output) are replaced
by much more reasonable ndelay()s.

Eliminating the hrtimer kludge in 8250_port.c might also make these
runtime PM patches by Andy simpler:

https://lore.kernel.org/linux-serial/20211115084203.56478-8-tony@atomide.com/

My suggestion would be to set the delays to zero for now in 8250_dw.c
and implement proper delay handling after I've finished the conversion
to nsec.

Thanks,

Lukas

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH 6/7] serial: General support for multipoint addresses
  2022-03-07  9:48       ` Ilpo Järvinen
  (?)
@ 2022-03-09 19:05         ` Lukas Wunner
  -1 siblings, 0 replies; 48+ messages in thread
From: Lukas Wunner @ 2022-03-09 19:05 UTC (permalink / raw)
  To: Ilpo Järvinen
  Cc: linux-serial, Jiri Slaby, Greg Kroah-Hartman, LKML, Johan Hovold,
	Andy Shevchenko, Heikki Krogerus, linux-api, Richard Henderson,
	Ivan Kokshaysky, Matt Turner, linux-alpha, Thomas Bogendoerfer,
	linux-mips, James E.J. Bottomley, Helge Deller, linux-parisc,
	Michael Ellerman, Benjamin Herrenschmidt, Paul Mackerras,
	linuxppc-dev, Yoshinori Sato, Rich Felker, linux-sh,
	David S. Miller, sparclinux, Chris Zankel, Max Filippov,
	linux-xtensa, Arnd Bergmann, linux-arch, linux-doc

On Mon, Mar 07, 2022 at 11:48:01AM +0200, Ilpo Järvinen wrote:
> On Sun, 6 Mar 2022, Lukas Wunner wrote:
> > On Wed, Mar 02, 2022 at 11:56:05AM +0200, Ilpo Järvinen wrote:
> > > This change is necessary for supporting devices with RS485
> > > multipoint addressing [*].
> > 
> > If this is only used with RS485, why can't we just store the
> > addresses in struct serial_rs485 and use the existing TIOCSRS485
> > and TIOCGRS485 ioctls?  There's 20 bytes of padding left in
> > struct serial_rs485 which you could use.  No need to add more
> > user-space ABI.
> 
> It could if it is agreed that serial multipoint addressing is just
> a thing in RS-485 and nowhere else? In that case, there is no point
> in adding more generic support for it.

It's just that the above-quoted sentence in the commit message
specifically mentions RS485.  If you intend to use it with RS232
as well, that should be made explicit, otherwise one wonders why
it wasn't integrated into struct serial_rs485.

I have no idea how common 9th bit addressing mode is with RS232.
Goggle turns up links saying it's mainly used with RS485, "but also
RS232".  Since RS232 isn't a bus but a point-to-point link,
9th bit addressing doesn't seem to make as much sense.


> > > [*] Technically, RS485 is just an electronic spec and does not
> > > itself specify the 9th bit addressing mode but 9th bit seems
> > > at least "semi-standard" way to do addressing with RS485.
> > 
> > Is 9th bit addressing actually used by an Intel customer or was
> > it implemented just for feature completeness? I think this mode
> > isn't used often (I've never seen a use case myself), primarily
> > because it requires disabling parity.
> 
> On what basis? ...The datasheet I'm looking at has a timing diagram 
> with both D8 (9th bit) and parity so I think your information must be
> incorrect.

E.g. the discussion here says that 9th bit addressing requires that
parity is disabled or the character size is reduced to 7-bit:

https://www.microchip.com/forums/m299904.aspx

I guess that applies only to some UARTs, the Synopsys databook doesn't
mention any such constraints.

Thanks,

Lukas

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH 6/7] serial: General support for multipoint addresses
@ 2022-03-09 19:05         ` Lukas Wunner
  0 siblings, 0 replies; 48+ messages in thread
From: Lukas Wunner @ 2022-03-09 19:05 UTC (permalink / raw)
  To: Ilpo Järvinen
  Cc: Heikki Krogerus, linux-sh, LKML, James E.J. Bottomley,
	Max Filippov, Rich Felker, Paul Mackerras, sparclinux, linux-api,
	Jiri Slaby, linux-arch, Yoshinori Sato, Helge Deller, linux-doc,
	linux-serial, Matt Turner, linux-xtensa, Arnd Bergmann,
	Johan Hovold, Ivan Kokshaysky, Andy Shevchenko,
	Richard Henderson, Chris Zankel, Thomas Bogendoerfer,
	linux-parisc, Greg Kroah-Hartman, linux-mips, linux-alpha,
	linuxppc-dev, David S. Miller

On Mon, Mar 07, 2022 at 11:48:01AM +0200, Ilpo Järvinen wrote:
> On Sun, 6 Mar 2022, Lukas Wunner wrote:
> > On Wed, Mar 02, 2022 at 11:56:05AM +0200, Ilpo Järvinen wrote:
> > > This change is necessary for supporting devices with RS485
> > > multipoint addressing [*].
> > 
> > If this is only used with RS485, why can't we just store the
> > addresses in struct serial_rs485 and use the existing TIOCSRS485
> > and TIOCGRS485 ioctls?  There's 20 bytes of padding left in
> > struct serial_rs485 which you could use.  No need to add more
> > user-space ABI.
> 
> It could if it is agreed that serial multipoint addressing is just
> a thing in RS-485 and nowhere else? In that case, there is no point
> in adding more generic support for it.

It's just that the above-quoted sentence in the commit message
specifically mentions RS485.  If you intend to use it with RS232
as well, that should be made explicit, otherwise one wonders why
it wasn't integrated into struct serial_rs485.

I have no idea how common 9th bit addressing mode is with RS232.
Goggle turns up links saying it's mainly used with RS485, "but also
RS232".  Since RS232 isn't a bus but a point-to-point link,
9th bit addressing doesn't seem to make as much sense.


> > > [*] Technically, RS485 is just an electronic spec and does not
> > > itself specify the 9th bit addressing mode but 9th bit seems
> > > at least "semi-standard" way to do addressing with RS485.
> > 
> > Is 9th bit addressing actually used by an Intel customer or was
> > it implemented just for feature completeness? I think this mode
> > isn't used often (I've never seen a use case myself), primarily
> > because it requires disabling parity.
> 
> On what basis? ...The datasheet I'm looking at has a timing diagram 
> with both D8 (9th bit) and parity so I think your information must be
> incorrect.

E.g. the discussion here says that 9th bit addressing requires that
parity is disabled or the character size is reduced to 7-bit:

https://www.microchip.com/forums/m299904.aspx

I guess that applies only to some UARTs, the Synopsys databook doesn't
mention any such constraints.

Thanks,

Lukas

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH 6/7] serial: General support for multipoint addresses
@ 2022-03-09 19:05         ` Lukas Wunner
  0 siblings, 0 replies; 48+ messages in thread
From: Lukas Wunner @ 2022-03-09 19:05 UTC (permalink / raw)
  To: Ilpo Järvinen
  Cc: linux-serial, Jiri Slaby, Greg Kroah-Hartman, LKML, Johan Hovold,
	Andy Shevchenko, Heikki Krogerus, linux-api, Richard Henderson,
	Ivan Kokshaysky, Matt Turner, linux-alpha, Thomas Bogendoerfer,
	linux-mips, James E.J. Bottomley, Helge Deller, linux-parisc,
	Michael Ellerman, Benjamin Herrenschmidt, Pau

On Mon, Mar 07, 2022 at 11:48:01AM +0200, Ilpo Järvinen wrote:
> On Sun, 6 Mar 2022, Lukas Wunner wrote:
> > On Wed, Mar 02, 2022 at 11:56:05AM +0200, Ilpo Järvinen wrote:
> > > This change is necessary for supporting devices with RS485
> > > multipoint addressing [*].
> > 
> > If this is only used with RS485, why can't we just store the
> > addresses in struct serial_rs485 and use the existing TIOCSRS485
> > and TIOCGRS485 ioctls?  There's 20 bytes of padding left in
> > struct serial_rs485 which you could use.  No need to add more
> > user-space ABI.
> 
> It could if it is agreed that serial multipoint addressing is just
> a thing in RS-485 and nowhere else? In that case, there is no point
> in adding more generic support for it.

It's just that the above-quoted sentence in the commit message
specifically mentions RS485.  If you intend to use it with RS232
as well, that should be made explicit, otherwise one wonders why
it wasn't integrated into struct serial_rs485.

I have no idea how common 9th bit addressing mode is with RS232.
Goggle turns up links saying it's mainly used with RS485, "but also
RS232".  Since RS232 isn't a bus but a point-to-point link,
9th bit addressing doesn't seem to make as much sense.


> > > [*] Technically, RS485 is just an electronic spec and does not
> > > itself specify the 9th bit addressing mode but 9th bit seems
> > > at least "semi-standard" way to do addressing with RS485.
> > 
> > Is 9th bit addressing actually used by an Intel customer or was
> > it implemented just for feature completeness? I think this mode
> > isn't used often (I've never seen a use case myself), primarily
> > because it requires disabling parity.
> 
> On what basis? ...The datasheet I'm looking at has a timing diagram 
> with both D8 (9th bit) and parity so I think your information must be
> incorrect.

E.g. the discussion here says that 9th bit addressing requires that
parity is disabled or the character size is reduced to 7-bit:

https://www.microchip.com/forums/m299904.aspx

I guess that applies only to some UARTs, the Synopsys databook doesn't
mention any such constraints.

Thanks,

Lukas

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH 6/7] serial: General support for multipoint addresses
  2022-03-09 19:05         ` Lukas Wunner
  (?)
@ 2022-03-10 12:29           ` Ilpo Järvinen
  -1 siblings, 0 replies; 48+ messages in thread
From: Ilpo Järvinen @ 2022-03-10 12:29 UTC (permalink / raw)
  To: Lukas Wunner
  Cc: linux-serial, Jiri Slaby, Greg Kroah-Hartman, LKML, Johan Hovold,
	Andy Shevchenko, Heikki Krogerus, linux-api, Richard Henderson,
	Ivan Kokshaysky, Matt Turner, linux-alpha, Thomas Bogendoerfer,
	linux-mips, James E.J. Bottomley, Helge Deller, linux-parisc,
	Michael Ellerman, Benjamin Herrenschmidt, Paul Mackerras,
	linuxppc-dev, Yoshinori Sato, Rich Felker, linux-sh,
	David S. Miller, sparclinux, Chris Zankel, Max Filippov,
	linux-xtensa, Arnd Bergmann, linux-arch, linux-doc

[-- Attachment #1: Type: text/plain, Size: 1718 bytes --]

On Wed, 9 Mar 2022, Lukas Wunner wrote:

> On Mon, Mar 07, 2022 at 11:48:01AM +0200, Ilpo Järvinen wrote:
> > On Sun, 6 Mar 2022, Lukas Wunner wrote:
> > > On Wed, Mar 02, 2022 at 11:56:05AM +0200, Ilpo Järvinen wrote:
> > > > This change is necessary for supporting devices with RS485
> > > > multipoint addressing [*].
> > > 
> > > If this is only used with RS485, why can't we just store the
> > > addresses in struct serial_rs485 and use the existing TIOCSRS485
> > > and TIOCGRS485 ioctls?  There's 20 bytes of padding left in
> > > struct serial_rs485 which you could use.  No need to add more
> > > user-space ABI.
> > 
> > It could if it is agreed that serial multipoint addressing is just
> > a thing in RS-485 and nowhere else? In that case, there is no point
> > in adding more generic support for it.
> 
> It's just that the above-quoted sentence in the commit message
> specifically mentions RS485.

That sentence is just to justify why addressing mode is needed,
not to take a stance on whether it is only used with RS485 or not.

> If you intend to use it with RS232
> as well, that should be made explicit, otherwise one wonders why
> it wasn't integrated into struct serial_rs485.
> 
> I have no idea how common 9th bit addressing mode is with RS232.
> Goggle turns up links saying it's mainly used with RS485, "but also
> RS232".  Since RS232 isn't a bus but a point-to-point link,
> 9th bit addressing doesn't seem to make as much sense.

While I don't know any better, I can image though that with an 
RS232-to-RS485 converter, it could make some sense.

If I put them back to serial_rs485 / rs485 config, it's basically just 
where I initially started from with this patchset (offlist).


-- 
 i.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH 6/7] serial: General support for multipoint addresses
@ 2022-03-10 12:29           ` Ilpo Järvinen
  0 siblings, 0 replies; 48+ messages in thread
From: Ilpo Järvinen @ 2022-03-10 12:29 UTC (permalink / raw)
  To: Lukas Wunner
  Cc: Heikki Krogerus, linux-sh, LKML, James E.J. Bottomley,
	Max Filippov, Rich Felker, Paul Mackerras, sparclinux, linux-api,
	Jiri Slaby, linux-arch, Yoshinori Sato, Helge Deller, linux-doc,
	linux-serial, Matt Turner, linux-xtensa, Arnd Bergmann,
	Johan Hovold, Ivan Kokshaysky, Andy Shevchenko,
	Richard Henderson, Chris Zankel, Thomas Bogendoerfer,
	linux-parisc, Greg Kroah-Hartman, linux-mips, linux-alpha,
	linuxppc-dev, David S. Miller

[-- Attachment #1: Type: text/plain, Size: 1718 bytes --]

On Wed, 9 Mar 2022, Lukas Wunner wrote:

> On Mon, Mar 07, 2022 at 11:48:01AM +0200, Ilpo Järvinen wrote:
> > On Sun, 6 Mar 2022, Lukas Wunner wrote:
> > > On Wed, Mar 02, 2022 at 11:56:05AM +0200, Ilpo Järvinen wrote:
> > > > This change is necessary for supporting devices with RS485
> > > > multipoint addressing [*].
> > > 
> > > If this is only used with RS485, why can't we just store the
> > > addresses in struct serial_rs485 and use the existing TIOCSRS485
> > > and TIOCGRS485 ioctls?  There's 20 bytes of padding left in
> > > struct serial_rs485 which you could use.  No need to add more
> > > user-space ABI.
> > 
> > It could if it is agreed that serial multipoint addressing is just
> > a thing in RS-485 and nowhere else? In that case, there is no point
> > in adding more generic support for it.
> 
> It's just that the above-quoted sentence in the commit message
> specifically mentions RS485.

That sentence is just to justify why addressing mode is needed,
not to take a stance on whether it is only used with RS485 or not.

> If you intend to use it with RS232
> as well, that should be made explicit, otherwise one wonders why
> it wasn't integrated into struct serial_rs485.
> 
> I have no idea how common 9th bit addressing mode is with RS232.
> Goggle turns up links saying it's mainly used with RS485, "but also
> RS232".  Since RS232 isn't a bus but a point-to-point link,
> 9th bit addressing doesn't seem to make as much sense.

While I don't know any better, I can image though that with an 
RS232-to-RS485 converter, it could make some sense.

If I put them back to serial_rs485 / rs485 config, it's basically just 
where I initially started from with this patchset (offlist).


-- 
 i.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH 6/7] serial: General support for multipoint addresses
@ 2022-03-10 12:29           ` Ilpo Järvinen
  0 siblings, 0 replies; 48+ messages in thread
From: Ilpo Järvinen @ 2022-03-10 12:29 UTC (permalink / raw)
  To: Lukas Wunner
  Cc: linux-serial, Jiri Slaby, Greg Kroah-Hartman, LKML, Johan Hovold,
	Andy Shevchenko, Heikki Krogerus, linux-api, Richard Henderson,
	Ivan Kokshaysky, Matt Turner, linux-alpha, Thomas Bogendoerfer,
	linux-mips, James E.J. Bottomley, Helge Deller, linux-parisc,
	Michael Ellerman, Benjamin Herrenschmidt, Pau

[-- Attachment #1: Type: text/plain, Size: 1760 bytes --]

On Wed, 9 Mar 2022, Lukas Wunner wrote:

> On Mon, Mar 07, 2022 at 11:48:01AM +0200, Ilpo Järvinen wrote:
> > On Sun, 6 Mar 2022, Lukas Wunner wrote:
> > > On Wed, Mar 02, 2022 at 11:56:05AM +0200, Ilpo Järvinen wrote:
> > > > This change is necessary for supporting devices with RS485
> > > > multipoint addressing [*].
> > > 
> > > If this is only used with RS485, why can't we just store the
> > > addresses in struct serial_rs485 and use the existing TIOCSRS485
> > > and TIOCGRS485 ioctls?  There's 20 bytes of padding left in
> > > struct serial_rs485 which you could use.  No need to add more
> > > user-space ABI.
> > 
> > It could if it is agreed that serial multipoint addressing is just
> > a thing in RS-485 and nowhere else? In that case, there is no point
> > in adding more generic support for it.
> 
> It's just that the above-quoted sentence in the commit message
> specifically mentions RS485.

That sentence is just to justify why addressing mode is needed,
not to take a stance on whether it is only used with RS485 or not.

> If you intend to use it with RS232
> as well, that should be made explicit, otherwise one wonders why
> it wasn't integrated into struct serial_rs485.
> 
> I have no idea how common 9th bit addressing mode is with RS232.
> Goggle turns up links saying it's mainly used with RS485, "but also
> RS232".  Since RS232 isn't a bus but a point-to-point link,
> 9th bit addressing doesn't seem to make as much sense.

While I don't know any better, I can image though that with an 
RS232-to-RS485 converter, it could make some sense.

If I put them back to serial_rs485 / rs485 config, it's basically just 
where I initially started from with this patchset (offlist).


-- 
 i.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH 6/7] serial: General support for multipoint addresses
  2022-03-09 19:05         ` Lukas Wunner
  (?)
@ 2022-03-10 14:09           ` Andy Shevchenko
  -1 siblings, 0 replies; 48+ messages in thread
From: Andy Shevchenko @ 2022-03-10 14:09 UTC (permalink / raw)
  To: Lukas Wunner
  Cc: Ilpo Järvinen, linux-serial, Jiri Slaby, Greg Kroah-Hartman,
	LKML, Johan Hovold, Heikki Krogerus, linux-api,
	Richard Henderson, Ivan Kokshaysky, Matt Turner, linux-alpha,
	Thomas Bogendoerfer, linux-mips, James E.J. Bottomley,
	Helge Deller, linux-parisc, Michael Ellerman,
	Benjamin Herrenschmidt, Paul Mackerras, linuxppc-dev,
	Yoshinori Sato, Rich Felker, linux-sh, David S. Miller,
	sparclinux, Chris Zankel, Max Filippov, linux-xtensa,
	Arnd Bergmann, linux-arch, linux-doc

On Wed, Mar 09, 2022 at 08:05:21PM +0100, Lukas Wunner wrote:
> On Mon, Mar 07, 2022 at 11:48:01AM +0200, Ilpo Järvinen wrote:
> > On Sun, 6 Mar 2022, Lukas Wunner wrote:
> > > On Wed, Mar 02, 2022 at 11:56:05AM +0200, Ilpo Järvinen wrote:
> > > > This change is necessary for supporting devices with RS485
> > > > multipoint addressing [*].
> > > 
> > > If this is only used with RS485, why can't we just store the
> > > addresses in struct serial_rs485 and use the existing TIOCSRS485
> > > and TIOCGRS485 ioctls?  There's 20 bytes of padding left in
> > > struct serial_rs485 which you could use.  No need to add more
> > > user-space ABI.
> > 
> > It could if it is agreed that serial multipoint addressing is just
> > a thing in RS-485 and nowhere else? In that case, there is no point
> > in adding more generic support for it.
> 
> It's just that the above-quoted sentence in the commit message
> specifically mentions RS485.  If you intend to use it with RS232
> as well, that should be made explicit, otherwise one wonders why
> it wasn't integrated into struct serial_rs485.
> 
> I have no idea how common 9th bit addressing mode is with RS232.
> Goggle turns up links saying it's mainly used with RS485, "but also
> RS232".  Since RS232 isn't a bus but a point-to-point link,
> 9th bit addressing doesn't seem to make as much sense.

In my student years I have an exercise to use 9-bit addressing mode on RS232.
Obviously I forgot all of the details, but I remember that that has a practical
application.

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH 6/7] serial: General support for multipoint addresses
@ 2022-03-10 14:09           ` Andy Shevchenko
  0 siblings, 0 replies; 48+ messages in thread
From: Andy Shevchenko @ 2022-03-10 14:09 UTC (permalink / raw)
  To: Lukas Wunner
  Cc: Heikki Krogerus, linux-sh, linux-mips, James E.J. Bottomley,
	Max Filippov, Rich Felker, Paul Mackerras, sparclinux, linux-api,
	Jiri Slaby, linux-arch, Yoshinori Sato, Helge Deller, linux-doc,
	linux-serial, Ilpo Järvinen, Matt Turner, linux-xtensa,
	Arnd Bergmann, Johan Hovold, Ivan Kokshaysky, Richard Henderson,
	Chris Zankel, Thomas Bogendoerfer, linux-parisc,
	Greg Kroah-Hartman, LKML, linux-alpha, linuxppc-dev,
	David S. Miller

On Wed, Mar 09, 2022 at 08:05:21PM +0100, Lukas Wunner wrote:
> On Mon, Mar 07, 2022 at 11:48:01AM +0200, Ilpo Järvinen wrote:
> > On Sun, 6 Mar 2022, Lukas Wunner wrote:
> > > On Wed, Mar 02, 2022 at 11:56:05AM +0200, Ilpo Järvinen wrote:
> > > > This change is necessary for supporting devices with RS485
> > > > multipoint addressing [*].
> > > 
> > > If this is only used with RS485, why can't we just store the
> > > addresses in struct serial_rs485 and use the existing TIOCSRS485
> > > and TIOCGRS485 ioctls?  There's 20 bytes of padding left in
> > > struct serial_rs485 which you could use.  No need to add more
> > > user-space ABI.
> > 
> > It could if it is agreed that serial multipoint addressing is just
> > a thing in RS-485 and nowhere else? In that case, there is no point
> > in adding more generic support for it.
> 
> It's just that the above-quoted sentence in the commit message
> specifically mentions RS485.  If you intend to use it with RS232
> as well, that should be made explicit, otherwise one wonders why
> it wasn't integrated into struct serial_rs485.
> 
> I have no idea how common 9th bit addressing mode is with RS232.
> Goggle turns up links saying it's mainly used with RS485, "but also
> RS232".  Since RS232 isn't a bus but a point-to-point link,
> 9th bit addressing doesn't seem to make as much sense.

In my student years I have an exercise to use 9-bit addressing mode on RS232.
Obviously I forgot all of the details, but I remember that that has a practical
application.

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH 6/7] serial: General support for multipoint addresses
@ 2022-03-10 14:09           ` Andy Shevchenko
  0 siblings, 0 replies; 48+ messages in thread
From: Andy Shevchenko @ 2022-03-10 14:09 UTC (permalink / raw)
  To: Lukas Wunner
  Cc: Ilpo Järvinen, linux-serial, Jiri Slaby, Greg Kroah-Hartman,
	LKML, Johan Hovold, Heikki Krogerus,
	linux-api-u79uwXL29TY76Z2rM5mHXA, Richard Henderson,
	Ivan Kokshaysky, Matt Turner, linux-alpha-u79uwXL29TY76Z2rM5mHXA,
	Thomas Bogendoerfer, linux-mips-u79uwXL29TY76Z2rM5mHXA,
	James E.J. Bottomley, Helge Deller,
	linux-parisc-u79uwXL29TY76Z2rM5mHXA, Michael Ellerman,
	Benjamin Herrenschmidt

On Wed, Mar 09, 2022 at 08:05:21PM +0100, Lukas Wunner wrote:
> On Mon, Mar 07, 2022 at 11:48:01AM +0200, Ilpo Järvinen wrote:
> > On Sun, 6 Mar 2022, Lukas Wunner wrote:
> > > On Wed, Mar 02, 2022 at 11:56:05AM +0200, Ilpo Järvinen wrote:
> > > > This change is necessary for supporting devices with RS485
> > > > multipoint addressing [*].
> > > 
> > > If this is only used with RS485, why can't we just store the
> > > addresses in struct serial_rs485 and use the existing TIOCSRS485
> > > and TIOCGRS485 ioctls?  There's 20 bytes of padding left in
> > > struct serial_rs485 which you could use.  No need to add more
> > > user-space ABI.
> > 
> > It could if it is agreed that serial multipoint addressing is just
> > a thing in RS-485 and nowhere else? In that case, there is no point
> > in adding more generic support for it.
> 
> It's just that the above-quoted sentence in the commit message
> specifically mentions RS485.  If you intend to use it with RS232
> as well, that should be made explicit, otherwise one wonders why
> it wasn't integrated into struct serial_rs485.
> 
> I have no idea how common 9th bit addressing mode is with RS232.
> Goggle turns up links saying it's mainly used with RS485, "but also
> RS232".  Since RS232 isn't a bus but a point-to-point link,
> 9th bit addressing doesn't seem to make as much sense.

In my student years I have an exercise to use 9-bit addressing mode on RS232.
Obviously I forgot all of the details, but I remember that that has a practical
application.

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 48+ messages in thread

end of thread, other threads:[~2022-03-10 14:12 UTC | newest]

Thread overview: 48+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [RFC PATCH 3/7] serial: 8250_dwlib: Implement SW half " Ilpo Järvinen
2022-03-06 19:21   ` 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

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.