> From: Christoph Niedermaier <cniedermaier@xxxxxxxxxxxxxxxxxx> > Sent: Tuesday, February 20, 2024 10:56 AM > To: linux-serial@xxxxxxxxxxxxxxx > Cc: Christoph Niedermaier <cniedermaier@xxxxxxxxxxxxxxxxxx>; Greg Kroah-Hartman > <gregkh@xxxxxxxxxxxxxxxxxxx>; Jiri Slaby <jirislaby@xxxxxxxxxx>; Shawn Guo > <shawnguo@xxxxxxxxxx>; Marek Vasut <marex@xxxxxxx>; Fabio Estevam <festevam@xxxxxxx>; > Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>; Pengutronix Kernel Team <kernel@xxxxxxxxxxxxxx>; > NXP Linux Team <linux-imx@xxxxxxx>; Sergey Organov <sorganov@xxxxxxxxx>; Uwe Kleine-König > <u.kleine-koenig@xxxxxxxxxxxxxx>; Rob Herring <robh@xxxxxxxxxx>; Ilpo Järvinen > <ilpo.jarvinen@xxxxxxxxxxxxxxx>; Tom Rix <trix@xxxxxxxxxx>; Thomas Gleixner > <tglx@xxxxxxxxxxxxx>; Lukas Wunner <lukas@xxxxxxxxx> > Subject: [RFC][PATCH] serial: imx: Fix RS485 behaviour on disabled RX_DURING_TX > > I have made a patch that does not enable the loopback when > the RX_DURING_TX flag is disabled. Would you be so kind to > test my patch to see if it also solves your problem. > > Regards > Christoph +CC Rickard X Andersson, because missed to add him. > > > Commit 79d0224f6bf2 ("tty: serial: imx: Handle RS485 DE signal active high") > activated the loopback mode for RS485 controlled by UART CTS_B when the > function imx_uart_stop_rx() is called. But through that changes the RS485 > flag RX_DURING_TX isn’t able to turn off the receiver anymore. If the flag > RX_DURING_TX is disabled everything that was sent will be received due to > the active loopback. To turn off the receiver in this case the function > imx_uart_stop_rx() is extended by a wrapper function > imx_uart_stop_rx_with_loopback_rs485_ctrl() for the use of RS485 with > disabled flag RX_DURING_TX, where the receiver is turn off. For all other > cases there aren’t a functional change. > > When the receiver is turned off the UART CTS_B signal is always high. To > ensure that the RS485 bus won’t blocked by a disabled receiver caused by a > high UART CTS_B signal the function imx_uart_shutdown() is extended. So in > RS485 loopback mode the receiver is always on after shutdown the device. > > Fixes: 79d0224f6bf2 ("tty: serial: imx: Handle RS485 DE signal active high") > Signed-off-by: Christoph Niedermaier <cniedermaier@xxxxxxxxxxxxxxxxxx> > --- > Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> > Cc: Jiri Slaby <jirislaby@xxxxxxxxxx> > Cc: Shawn Guo <shawnguo@xxxxxxxxxx> > Cc: Marek Vasut <marex@xxxxxxx> > Cc: Fabio Estevam <festevam@xxxxxxx> > Cc: Sascha Hauer <s.hauer@xxxxxxxxxxxxxx> > Cc: Pengutronix Kernel Team <kernel@xxxxxxxxxxxxxx> > Cc: NXP Linux Team <linux-imx@xxxxxxx> > Cc: Sergey Organov <sorganov@xxxxxxxxx> > Cc: "Uwe Kleine-König" <u.kleine-koenig@xxxxxxxxxxxxxx> > Cc: Rob Herring <robh@xxxxxxxxxx> > Cc: "Ilpo Järvinen" <ilpo.jarvinen@xxxxxxxxxxxxxxx> > Cc: Tom Rix <trix@xxxxxxxxxx> > Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx> > Cc: Lukas Wunner <lukas@xxxxxxxxx> > To: linux-serial@xxxxxxxxxxxxxxx > --- > drivers/tty/serial/imx.c | 16 +++++++++++++--- > 1 file changed, 13 insertions(+), 3 deletions(-) > > diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c > index 4aa72d5aeafb..222e2c929bd7 100644 > --- a/drivers/tty/serial/imx.c > +++ b/drivers/tty/serial/imx.c > @@ -463,7 +463,8 @@ static void imx_uart_stop_tx(struct uart_port *port) > } > > /* called with port.lock taken and irqs off */ > -static void imx_uart_stop_rx(struct uart_port *port) > +static void imx_uart_stop_rx_with_loopback_rs485_ctrl(struct uart_port *port, > + bool loopback_rs485_enable) > { > struct imx_port *sport = (struct imx_port *)port; > u32 ucr1, ucr2, ucr4, uts; > @@ -483,7 +484,7 @@ static void imx_uart_stop_rx(struct uart_port *port) > imx_uart_writel(sport, ucr4, UCR4); > > /* See SER_RS485_ENABLED/UTS_LOOP comment in imx_uart_probe() */ > - if (port->rs485.flags & SER_RS485_ENABLED && > + if (port->rs485.flags & SER_RS485_ENABLED && loopback_rs485_enable && > port->rs485.flags & SER_RS485_RTS_ON_SEND && > sport->have_rtscts && !sport->have_rtsgpio) { > uts = imx_uart_readl(sport, imx_uart_uts_reg(sport)); > @@ -498,6 +499,12 @@ static void imx_uart_stop_rx(struct uart_port *port) > } > > /* called with port.lock taken and irqs off */ > +static void imx_uart_stop_rx(struct uart_port *port) > +{ > + imx_uart_stop_rx_with_loopback_rs485_ctrl(port, 1); > +} > + > +/* called with port.lock taken and irqs off */ > static void imx_uart_enable_ms(struct uart_port *port) > { > struct imx_port *sport = (struct imx_port *)port; > @@ -684,7 +691,7 @@ static void imx_uart_start_tx(struct uart_port *port) > > if (!(port->rs485.flags & SER_RS485_RX_DURING_TX) && > !port->rs485_rx_during_tx_gpio) > - imx_uart_stop_rx(port); > + imx_uart_stop_rx_with_loopback_rs485_ctrl(port, 0); > > sport->tx_state = WAIT_AFTER_RTS; > > @@ -1596,6 +1603,9 @@ static void imx_uart_shutdown(struct uart_port *port) > uts = imx_uart_readl(sport, imx_uart_uts_reg(sport)); > uts |= UTS_LOOP; > imx_uart_writel(sport, uts, imx_uart_uts_reg(sport)); > + ucr2 = imx_uart_readl(sport, UCR2); > + ucr2 |= UCR2_RXEN; > + imx_uart_writel(sport, ucr2, UCR2); > ucr1 |= UCR1_UARTEN; > } else { > ucr1 &= ~UCR1_UARTEN; > -- > 2.11.0