Message ID | 20240126-dev-rx-enable-v5-2-5d934eda05ca@theobroma-systems.com |
---|---|
State | Superseded |
Headers | show |
Series | serial: 8250: Add support for rs485 half/full duplex on puma/ringneck-haikou | expand |
Hi, On 26.01.24 18:27, Farouk Bouabid wrote: > From: Heiko Stuebner <heiko.stuebner@cherry.de> > > The RE signal is used to control the duplex mode of transmissions, > aka receiving data while sending in full duplex mode, while stopping > receiving data in half-duplex mode. > > On a number of boards the !RE signal is tied to ground so reception > is always enabled except if the UART allows disabling the receiver. > This can be taken advantage of to implement half-duplex mode - like > done on 8250_bcm2835aux. > > Another solution is to tie !RE to RTS always forcing half-duplex mode. > > And finally there is the option to control the RE signal separately, > like done here by introducing a new rs485-specific gpio that can be > set depending on the RX_DURING_TX setting in the common em485 callbacks. > we just added the rx_during_tx_gpio to the serial core. Why cant you use this GPIO for your purpose? Regards, Lino
Hi, On 26.01.24 20:58, Lino Sanfilippo wrote: > [Some people who received this message don't often get email from linosanfilippo@gmx.de. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ] > > Hi, > > On 26.01.24 18:27, Farouk Bouabid wrote: >> From: Heiko Stuebner <heiko.stuebner@cherry.de> >> >> The RE signal is used to control the duplex mode of transmissions, >> aka receiving data while sending in full duplex mode, while stopping >> receiving data in half-duplex mode. >> >> On a number of boards the !RE signal is tied to ground so reception >> is always enabled except if the UART allows disabling the receiver. >> This can be taken advantage of to implement half-duplex mode - like >> done on 8250_bcm2835aux. >> >> Another solution is to tie !RE to RTS always forcing half-duplex mode. >> >> And finally there is the option to control the RE signal separately, >> like done here by introducing a new rs485-specific gpio that can be >> set depending on the RX_DURING_TX setting in the common em485 callbacks. >> > we just added the rx_during_tx_gpio to the serial core. > Why cant you use this GPIO for your purpose? > > Regards, > Lino. What we are trying to implement is a gpio that emulates the RTS signal itself as we do not have a dedicated RTS signal that can be controlled through MCR. The rx during tx state in our case is a fixed state of "NO_RX_WHILE_TX" Regards, >
Hi Christoph, On 30.01.24 13:29, Christoph Niedermaier wrote: > [Einige Personen, die diese Nachricht erhalten haben, erhalten häufig keine E-Mails von cniedermaier@dh-electronics.com. Weitere Informationen, warum dies wichtig ist, finden Sie unter https://aka.ms/LearnAboutSenderIdentification ] > > From: Farouk Bouabid > Sent: Monday, January 29, 2024 9:57 AM > > Hi, > >> On 26.01.24 20:58, Lino Sanfilippo wrote: >>> [Some people who received this message don't often get email from linosanfilippo@gmx.de. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ] >>> >>> Hi, >>> >>> On 26.01.24 18:27, Farouk Bouabid wrote: >>>> From: Heiko Stuebner <heiko.stuebner@cherry.de> >>>> >>>> The RE signal is used to control the duplex mode of transmissions, >>>> aka receiving data while sending in full duplex mode, while stopping >>>> receiving data in half-duplex mode. >>>> >>>> On a number of boards the !RE signal is tied to ground so reception >>>> is always enabled except if the UART allows disabling the receiver. >>>> This can be taken advantage of to implement half-duplex mode - like >>>> done on 8250_bcm2835aux. >>>> >>>> Another solution is to tie !RE to RTS always forcing half-duplex mode. >>>> >>>> And finally there is the option to control the RE signal separately, >>>> like done here by introducing a new rs485-specific gpio that can be >>>> set depending on the RX_DURING_TX setting in the common em485 callbacks. >>>> >>> we just added the rx_during_tx_gpio to the serial core. >>> Why cant you use this GPIO for your purpose? >>> >>> Regards, >>> Lino. >> What we are trying to implement is a gpio that emulates the RTS signal >> itself as we do not have a dedicated RTS signal that can be controlled >> through MCR. The rx during tx state in our case is a fixed state of >> "NO_RX_WHILE_TX" > Why can't the property rts-gpios be used here for this purpose? Yes that indeed serves our purpose. Thank you for the suggestion. Regards Farouk > > > Regards > Christoph
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 8ca061d3bbb9..54d8f809b81e 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1402,6 +1402,7 @@ static void serial8250_stop_rx(struct uart_port *port) void serial8250_em485_stop_tx(struct uart_8250_port *p) { unsigned char mcr = serial8250_in_MCR(p); + struct uart_port *port = &p->port; /* Port locked to synchronize UART_IER access against the console. */ lockdep_assert_held_once(&p->port.lock); @@ -1418,6 +1419,7 @@ void serial8250_em485_stop_tx(struct uart_8250_port *p) * Enable previously disabled RX interrupts. */ if (!(p->port.rs485.flags & SER_RS485_RX_DURING_TX)) { + gpiod_set_value(port->rs485_re_gpio, 1); serial8250_clear_and_reinit_fifos(p); p->ier |= UART_IER_RLSI | UART_IER_RDI; @@ -1567,9 +1569,12 @@ static inline void __start_tx(struct uart_port *port) void serial8250_em485_start_tx(struct uart_8250_port *up) { unsigned char mcr = serial8250_in_MCR(up); + struct uart_port *port = &up->port; - if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) + if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) { + gpiod_set_value(port->rs485_re_gpio, 0); serial8250_stop_rx(&up->port); + } if (up->port.rs485.flags & SER_RS485_RTS_ON_SEND) mcr |= UART_MCR_RTS; diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index b56ed8c376b2..8067d20c5275 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -3663,6 +3663,13 @@ int uart_get_rs485_mode(struct uart_port *port) if (port->rs485_rx_during_tx_gpio) port->rs485_supported.flags |= SER_RS485_RX_DURING_TX; + port->rs485_re_gpio = devm_gpiod_get_optional(dev, "rs485-rx-enable", GPIOD_OUT_HIGH); + if (IS_ERR(port->rs485_re_gpio)) { + ret = PTR_ERR(port->rs485_re_gpio); + port->rs485_re_gpio = NULL; + return dev_err_probe(dev, ret, "Cannot get rs485-rx-enable-gpios\n"); + } + return 0; } EXPORT_SYMBOL_GPL(uart_get_rs485_mode); diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 536b2581d3e2..364583203a24 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -584,6 +584,7 @@ struct uart_port { struct serial_rs485 rs485_supported; /* Supported mask for serial_rs485 */ struct gpio_desc *rs485_term_gpio; /* enable RS485 bus termination */ struct gpio_desc *rs485_rx_during_tx_gpio; /* Output GPIO that sets the state of RS485 RX during TX */ + struct gpio_desc *rs485_re_gpio; /* gpio RS485 receive enable */ struct serial_iso7816 iso7816; void *private_data; /* generic platform data pointer */ };