Skip to content

Commit 672448c

Browse files
Rickard x Anderssongregkh
authored andcommitted
tty: serial: imx: Fix broken RS485
When about to transmit the function imx_uart_start_tx is called and in some RS485 configurations this function will call imx_uart_stop_rx. The problem is that imx_uart_stop_rx will enable loopback in order to release the RS485 bus, but when loopback is enabled transmitted data will just be looped to RX. This patch fixes the above problem by not enabling loopback when about to transmit. This driver now works well when used for RS485 half duplex master configurations. Fixes: 79d0224 ("tty: serial: imx: Handle RS485 DE signal active high") Cc: stable <stable@kernel.org> Signed-off-by: Rickard x Andersson <rickaran@axis.com> Tested-by: Christoph Niedermaier <cniedermaier@dh-electronics.com> Link: https://lore.kernel.org/r/20240221115304.509811-1-rickaran@axis.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent d206a76 commit 672448c

File tree

1 file changed

+18
-4
lines changed

1 file changed

+18
-4
lines changed

drivers/tty/serial/imx.c

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -462,8 +462,7 @@ static void imx_uart_stop_tx(struct uart_port *port)
462462
}
463463
}
464464

465-
/* called with port.lock taken and irqs off */
466-
static void imx_uart_stop_rx(struct uart_port *port)
465+
static void imx_uart_stop_rx_with_loopback_ctrl(struct uart_port *port, bool loopback)
467466
{
468467
struct imx_port *sport = (struct imx_port *)port;
469468
u32 ucr1, ucr2, ucr4, uts;
@@ -485,7 +484,7 @@ static void imx_uart_stop_rx(struct uart_port *port)
485484
/* See SER_RS485_ENABLED/UTS_LOOP comment in imx_uart_probe() */
486485
if (port->rs485.flags & SER_RS485_ENABLED &&
487486
port->rs485.flags & SER_RS485_RTS_ON_SEND &&
488-
sport->have_rtscts && !sport->have_rtsgpio) {
487+
sport->have_rtscts && !sport->have_rtsgpio && loopback) {
489488
uts = imx_uart_readl(sport, imx_uart_uts_reg(sport));
490489
uts |= UTS_LOOP;
491490
imx_uart_writel(sport, uts, imx_uart_uts_reg(sport));
@@ -497,6 +496,16 @@ static void imx_uart_stop_rx(struct uart_port *port)
497496
imx_uart_writel(sport, ucr2, UCR2);
498497
}
499498

499+
/* called with port.lock taken and irqs off */
500+
static void imx_uart_stop_rx(struct uart_port *port)
501+
{
502+
/*
503+
* Stop RX and enable loopback in order to make sure RS485 bus
504+
* is not blocked. Se comment in imx_uart_probe().
505+
*/
506+
imx_uart_stop_rx_with_loopback_ctrl(port, true);
507+
}
508+
500509
/* called with port.lock taken and irqs off */
501510
static void imx_uart_enable_ms(struct uart_port *port)
502511
{
@@ -682,9 +691,14 @@ static void imx_uart_start_tx(struct uart_port *port)
682691
imx_uart_rts_inactive(sport, &ucr2);
683692
imx_uart_writel(sport, ucr2, UCR2);
684693

694+
/*
695+
* Since we are about to transmit we can not stop RX
696+
* with loopback enabled because that will make our
697+
* transmitted data being just looped to RX.
698+
*/
685699
if (!(port->rs485.flags & SER_RS485_RX_DURING_TX) &&
686700
!port->rs485_rx_during_tx_gpio)
687-
imx_uart_stop_rx(port);
701+
imx_uart_stop_rx_with_loopback_ctrl(port, false);
688702

689703
sport->tx_state = WAIT_AFTER_RTS;
690704

0 commit comments

Comments
 (0)