2022-02-22 04:16:10

by Lino Sanfilippo

[permalink] [raw]
Subject: Move RS485 implementation from drivers to serial core (v3)

This patch series is an attempt to simplify rs485 implementation in drivers
by moving the following tasks out of the drivers into the serial core:

- ensure sane RTS settings: in case of an invalid configuration (both RTS
after send and RTS on send set or both unset) enable RTS on send and
disable RTS after send

- nullify the padding field of the serial_rs485 struct before it is
returned to userspace

- copy the configuration stored in the serial_rs485 struct to the port
configuration if setting the configuration in the driver was successfull

- limit the RTS delay to 100ms


Redundant code has been removed from the following drivers for now:

- atmel
- fsl_lpuart
- amba
- imx
- max310x
- omap-serial
- sc16is7xx
- stm32-usart

The code has been tested with the amba pl011 driver. This series applies
against Gregs tty-testing branch.

Changes in v2:
- use a makro for max RTS delays and comment it (as requested by Jiri)
- add a comment concerning the memset of a structures padding field
- correct typos in the commit message (found by Uwe)
- rephrase all commit messages to make more clear that function
uart_set_rs485_config() has been extended by checks and other
functionalities (as requested by Uwe)

Changes in v3:
- add warning messages if the serial core corrects RS485 values (as requested by Lukas Wunner)
- dont expose the macro for max RTS delays to userspace (as requested by Greg)



2022-02-22 04:20:14

by Lino Sanfilippo

[permalink] [raw]
Subject: [PATCH v3 8/9] serial: fsl_lpuart: remove redundant code in rs485_config functions

In uart_set_rs485_config() the serial core already ensures that only one of
both options RTS on send or RTS after send is set. It also assigns the
passed serial_rs485 struct to the uart port.

So remove the check and the assignment from the drivers rs485_config()
function to avoid redundancy.

Signed-off-by: Lino Sanfilippo <[email protected]>
---
drivers/tty/serial/fsl_lpuart.c | 32 --------------------------------
1 file changed, 32 deletions(-)

diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 7d90c5a530ee..a201be44d68a 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -1377,19 +1377,6 @@ static int lpuart_config_rs485(struct uart_port *port,
/* Enable auto RS-485 RTS mode */
modem |= UARTMODEM_TXRTSE;

- /*
- * RTS needs to be logic HIGH either during transfer _or_ after
- * transfer, other variants are not supported by the hardware.
- */
-
- if (!(rs485->flags & (SER_RS485_RTS_ON_SEND |
- SER_RS485_RTS_AFTER_SEND)))
- rs485->flags |= SER_RS485_RTS_ON_SEND;
-
- if (rs485->flags & SER_RS485_RTS_ON_SEND &&
- rs485->flags & SER_RS485_RTS_AFTER_SEND)
- rs485->flags &= ~SER_RS485_RTS_AFTER_SEND;
-
/*
* The hardware defaults to RTS logic HIGH while transfer.
* Switch polarity in case RTS shall be logic HIGH
@@ -1402,9 +1389,6 @@ static int lpuart_config_rs485(struct uart_port *port,
modem |= UARTMODEM_TXRTSPOL;
}

- /* Store the new configuration */
- sport->port.rs485 = *rs485;
-
writeb(modem, sport->port.membase + UARTMODEM);
return 0;
}
@@ -1428,19 +1412,6 @@ static int lpuart32_config_rs485(struct uart_port *port,
/* Enable auto RS-485 RTS mode */
modem |= UARTMODEM_TXRTSE;

- /*
- * RTS needs to be logic HIGH either during transfer _or_ after
- * transfer, other variants are not supported by the hardware.
- */
-
- if (!(rs485->flags & (SER_RS485_RTS_ON_SEND |
- SER_RS485_RTS_AFTER_SEND)))
- rs485->flags |= SER_RS485_RTS_ON_SEND;
-
- if (rs485->flags & SER_RS485_RTS_ON_SEND &&
- rs485->flags & SER_RS485_RTS_AFTER_SEND)
- rs485->flags &= ~SER_RS485_RTS_AFTER_SEND;
-
/*
* The hardware defaults to RTS logic HIGH while transfer.
* Switch polarity in case RTS shall be logic HIGH
@@ -1453,9 +1424,6 @@ static int lpuart32_config_rs485(struct uart_port *port,
modem |= UARTMODEM_TXRTSPOL;
}

- /* Store the new configuration */
- sport->port.rs485 = *rs485;
-
lpuart32_write(&sport->port, modem, UARTMODIR);
return 0;
}
--
2.35.1

2022-02-22 04:55:46

by Lino Sanfilippo

[permalink] [raw]
Subject: [PATCH v3 6/9] serial: max310: remove redundant memset in rs485_config

In uart_set_rs485_config() the serial core already nullifies the padding
field of the passed serial_rs485 struct before returning it to userspace.

Doing the same in the drivers rs485_config() function is redundant, so
remove the concerning memset in this function.

Signed-off-by: Lino Sanfilippo <[email protected]>
---
drivers/tty/serial/max310x.c | 1 -
1 file changed, 1 deletion(-)

diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
index dde0824b2fa5..2ecc5f66deaf 100644
--- a/drivers/tty/serial/max310x.c
+++ b/drivers/tty/serial/max310x.c
@@ -1037,7 +1037,6 @@ static int max310x_rs485_config(struct uart_port *port,

rs485->flags &= SER_RS485_RTS_ON_SEND | SER_RS485_RX_DURING_TX |
SER_RS485_ENABLED;
- memset(rs485->padding, 0, sizeof(rs485->padding));
port->rs485 = *rs485;

schedule_work(&one->rs_work);
--
2.35.1

2022-02-22 04:57:33

by Lino Sanfilippo

[permalink] [raw]
Subject: [PATCH v3 3/9] serial: stm32: remove redundant code in rs485_config

In uart_set_rs485_config() the serial core already ensures that only one of
both options RTS on send or RTS after send is set. It also assigns the
passed serial_rs485 struct to the uart port.

So remove the check and the assignment from the drivers rs485_config()
function to avoid redundancy.

Signed-off-by: Lino Sanfilippo <[email protected]>
---
drivers/tty/serial/stm32-usart.c | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index 1b3a611ac39e..6a014168102c 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -107,8 +107,6 @@ static int stm32_usart_config_rs485(struct uart_port *port,

stm32_usart_clr_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit));

- port->rs485 = *rs485conf;
-
rs485conf->flags |= SER_RS485_RX_DURING_TX;

if (rs485conf->flags & SER_RS485_ENABLED) {
@@ -128,13 +126,10 @@ static int stm32_usart_config_rs485(struct uart_port *port,
rs485conf->delay_rts_after_send,
baud);

- if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
+ if (rs485conf->flags & SER_RS485_RTS_ON_SEND)
cr3 &= ~USART_CR3_DEP;
- rs485conf->flags &= ~SER_RS485_RTS_AFTER_SEND;
- } else {
+ else
cr3 |= USART_CR3_DEP;
- rs485conf->flags |= SER_RS485_RTS_AFTER_SEND;
- }

writel_relaxed(cr3, port->membase + ofs->cr3);
writel_relaxed(cr1, port->membase + ofs->cr1);
--
2.35.1

2022-02-22 05:09:33

by Lino Sanfilippo

[permalink] [raw]
Subject: [PATCH v3 4/9] serial: sc16is7xx: remove redundant check in rs485_config

In uart_set_rs485_config() the serial core already ensures that only one of
both options RTS on send or RTS after send is set.

So remove this check from the drivers rs485_config() function to avoid
redundancy.

Signed-off-by: Lino Sanfilippo <[email protected]>
---
drivers/tty/serial/sc16is7xx.c | 10 ----------
1 file changed, 10 deletions(-)

diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c
index 64e7e6c8145f..730f697bb517 100644
--- a/drivers/tty/serial/sc16is7xx.c
+++ b/drivers/tty/serial/sc16is7xx.c
@@ -959,16 +959,6 @@ static int sc16is7xx_config_rs485(struct uart_port *port,
struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);

if (rs485->flags & SER_RS485_ENABLED) {
- bool rts_during_rx, rts_during_tx;
-
- rts_during_rx = rs485->flags & SER_RS485_RTS_AFTER_SEND;
- rts_during_tx = rs485->flags & SER_RS485_RTS_ON_SEND;
-
- if (rts_during_rx == rts_during_tx)
- dev_err(port->dev,
- "unsupported RTS signalling on_send:%d after_send:%d - exactly one of RS485 RTS flags should be set\n",
- rts_during_tx, rts_during_rx);
-
/*
* RTS signal is handled by HW, it's timing can't be influenced.
* However, it's sometimes useful to delay TX even without RTS
--
2.35.1

2022-02-22 05:22:55

by Lino Sanfilippo

[permalink] [raw]
Subject: [PATCH v3 5/9] serial: omap: remove redundant code in rs485_config

In uart_set_rs485_config() the serial core already clamps the RTS delays.
It also assigns the passed serial_rs485 struct to the uart port.

So remove these tasks from the drivers rs485_config() function to avoid
redundancy.

Signed-off-by: Lino Sanfilippo <[email protected]>
---
drivers/tty/serial/omap-serial.c | 13 +++----------
1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 0862941862c8..a3afcccfbd96 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -1350,18 +1350,11 @@ serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485)
up->ier = 0;
serial_out(up, UART_IER, 0);

- /* Clamp the delays to [0, 100ms] */
- rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U);
- rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U);
-
- /* store new config */
- port->rs485 = *rs485;
-
if (up->rts_gpiod) {
/* enable / disable rts */
- val = (port->rs485.flags & SER_RS485_ENABLED) ?
+ val = (rs485->flags & SER_RS485_ENABLED) ?
SER_RS485_RTS_AFTER_SEND : SER_RS485_RTS_ON_SEND;
- val = (port->rs485.flags & val) ? 1 : 0;
+ val = (rs485->flags & val) ? 1 : 0;
gpiod_set_value(up->rts_gpiod, val);
}

@@ -1372,7 +1365,7 @@ serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485)
/* If RS-485 is disabled, make sure the THR interrupt is fired when
* TX FIFO is below the trigger level.
*/
- if (!(port->rs485.flags & SER_RS485_ENABLED) &&
+ if (!(rs485->flags & SER_RS485_ENABLED) &&
(up->scr & OMAP_UART_SCR_TX_EMPTY)) {
up->scr &= ~OMAP_UART_SCR_TX_EMPTY;
serial_out(up, UART_OMAP_SCR, up->scr);
--
2.35.1

2022-02-22 05:35:10

by Lino Sanfilippo

[permalink] [raw]
Subject: [PATCH v3 9/9] serial: atmel: remove redundant assignment in rs485_config

In uart_set_rs485_config() the serial core already assigns the passed
serial_rs485 struct to the uart port.

So remove the assignment from the drivers rs485_config() function to avoid
redundancy.

Acked-by: Richard Genoud <[email protected]>
Signed-off-by: Lino Sanfilippo <[email protected]>
---
drivers/tty/serial/atmel_serial.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 73d43919898d..18d3bbdcb7a2 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -299,11 +299,9 @@ static int atmel_config_rs485(struct uart_port *port,
/* Resetting serial mode to RS232 (0x0) */
mode &= ~ATMEL_US_USMODE;

- port->rs485 = *rs485conf;
-
if (rs485conf->flags & SER_RS485_ENABLED) {
dev_dbg(port->dev, "Setting UART to RS485\n");
- if (port->rs485.flags & SER_RS485_RX_DURING_TX)
+ if (rs485conf->flags & SER_RS485_RX_DURING_TX)
atmel_port->tx_done_mask = ATMEL_US_TXRDY;
else
atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
--
2.35.1

2022-02-22 05:50:04

by Lino Sanfilippo

[permalink] [raw]
Subject: [PATCH v3 7/9] serial: imx: remove redundant assignment in rs485_config

In uart_set_rs485_config() the serial core already assigns the passed
serial_rs485 struct to the uart port.

So remove the assignment in the drivers rs485_config() function to avoid
reduncancy.

Acked-by: Uwe Kleine-König <[email protected]>
Signed-off-by: Lino Sanfilippo <[email protected]>
---
drivers/tty/serial/imx.c | 2 --
1 file changed, 2 deletions(-)

diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 0b467ce8d737..ab56ff23e8a9 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -1937,8 +1937,6 @@ static int imx_uart_rs485_config(struct uart_port *port,
rs485conf->flags & SER_RS485_RX_DURING_TX)
imx_uart_start_rx(port);

- port->rs485 = *rs485conf;
-
return 0;
}

--
2.35.1