On Tue, May 12, 2020 at 02:40:04PM +0200, Lukas Wunner wrote: > Commit e8759ad17d41 ("serial: uapi: Add support for bus termination") > introduced the ability to enable rs485 bus termination from user space. > So far the feature is only used by a single driver, 8250_exar.c, using a > hardcoded GPIO pin specific to Siemens IOT2040 products. Perhaps you need to Cc this to Jan Kiszka. > Provide for a more generic solution by allowing specification of an > rs485 bus termination GPIO pin in the device tree: Amend the serial > core to retrieve the GPIO from the device tree (or ACPI table) and amend > the default ->rs485_config() callback for 8250 drivers to change the > GPIO on request from user space. Perhaps the followup can be turning 8250_exar to request those GPIOs it provides (as hogs or regular ones, I don't know). FWIW, Reviewed-by: Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx> > Signed-off-by: Lukas Wunner <lukas@xxxxxxxxx> > --- > Changes v1 -> v2: > * Drop unnecessary devm_gpiod_put(). (Andy) > * Use GPIOD_OUT_LOW macro for brevity. (Andy) > * Document the rationale for disabling termination by default. > * Drop nonsensical read of GPIO after setting its direction to out. > > drivers/tty/serial/8250/8250_port.c | 4 ++++ > drivers/tty/serial/serial_core.c | 16 ++++++++++++++++ > include/linux/serial_core.h | 2 ++ > 3 files changed, 22 insertions(+) > > diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c > index f77bf820b7a3..b5b630d02110 100644 > --- a/drivers/tty/serial/8250/8250_port.c > +++ b/drivers/tty/serial/8250/8250_port.c > @@ -681,6 +681,10 @@ int serial8250_em485_config(struct uart_port *port, struct serial_rs485 *rs485) > memset(rs485->padding, 0, sizeof(rs485->padding)); > port->rs485 = *rs485; > > + if (port->rs485_term_gpio) > + gpiod_set_value(port->rs485_term_gpio, > + rs485->flags & SER_RS485_TERMINATE_BUS); > + > /* > * Both serial8250_em485_init() and serial8250_em485_destroy() > * are idempotent. > diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c > index 43b6682877d5..57840cf90388 100644 > --- a/drivers/tty/serial/serial_core.c > +++ b/drivers/tty/serial/serial_core.c > @@ -3317,6 +3317,7 @@ int uart_get_rs485_mode(struct uart_port *port) > * to get to a defined state with the following properties: > */ > rs485conf->flags &= ~(SER_RS485_RX_DURING_TX | SER_RS485_ENABLED | > + SER_RS485_TERMINATE_BUS | > SER_RS485_RTS_AFTER_SEND); > rs485conf->flags |= SER_RS485_RTS_ON_SEND; > > @@ -3331,6 +3332,21 @@ int uart_get_rs485_mode(struct uart_port *port) > rs485conf->flags |= SER_RS485_RTS_AFTER_SEND; > } > > + /* > + * Disabling termination by default is the safe choice: Else if many > + * bus participants enable it, no communication is possible at all. > + * Works fine for short cables and users may enable for longer cables. > + */ > + port->rs485_term_gpio = devm_gpiod_get_optional(dev, "rs485-term", > + GPIOD_OUT_LOW); > + if (IS_ERR(port->rs485_term_gpio)) { > + ret = PTR_ERR(port->rs485_term_gpio); > + port->rs485_term_gpio = NULL; > + if (ret != -EPROBE_DEFER) > + dev_err(dev, "Cannot get rs485-term-gpios\n"); > + return ret; > + } > + > return 0; > } > EXPORT_SYMBOL_GPL(uart_get_rs485_mode); > diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h > index b649a2b894e7..9fd550e7946a 100644 > --- a/include/linux/serial_core.h > +++ b/include/linux/serial_core.h > @@ -10,6 +10,7 @@ > #include <linux/bitops.h> > #include <linux/compiler.h> > #include <linux/console.h> > +#include <linux/gpio/consumer.h> > #include <linux/interrupt.h> > #include <linux/circ_buf.h> > #include <linux/spinlock.h> > @@ -251,6 +252,7 @@ struct uart_port { > struct attribute_group *attr_group; /* port specific attributes */ > const struct attribute_group **tty_groups; /* all attributes (serial core use only) */ > struct serial_rs485 rs485; > + struct gpio_desc *rs485_term_gpio; /* enable RS485 bus termination */ > struct serial_iso7816 iso7816; > void *private_data; /* generic platform data pointer */ > }; > -- > 2.26.2 > -- With Best Regards, Andy Shevchenko