Skip to content

Commit 639949a

Browse files
Martin Fuzzeygregkh
authored andcommitted
tty: serial: imx: fix rs485 rx after tx
Since commit 79d0224 ("tty: serial: imx: Handle RS485 DE signal active high") RS485 reception no longer works after a transmission. The following scenario shows the problem: 1) Open a port in RS485 mode 2) Receive data from remote (OK) 3) Transmit data to remote (OK) 4) Receive data from remote (Nothing received) In RS485 mode, imx_uart_start_tx() calls imx_uart_stop_rx() and, when the transmission is complete, imx_uart_stop_tx() calls imx_uart_start_rx(). Since the above commit imx_uart_stop_rx() now sets the loopback bit but imx_uart_start_rx() does not clear it causing the hardware to remain in loopback mode and not receive external data. Fix this by moving the existing loopback disable code to a helper function and calling it from imx_uart_start_rx() too. Fixes: 79d0224 ("tty: serial: imx: Handle RS485 DE signal active high") Cc: stable@vger.kernel.org Signed-off-by: Martin Fuzzey <martin.fuzzey@flowbird.group> Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Link: https://lore.kernel.org/r/20230616104838.2729694-1-martin.fuzzey@flowbird.group Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent e8cc334 commit 639949a

1 file changed

Lines changed: 13 additions & 5 deletions

File tree

drivers/tty/serial/imx.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,16 @@ static void imx_uart_soft_reset(struct imx_port *sport)
369369
sport->idle_counter = 0;
370370
}
371371

372+
static void imx_uart_disable_loopback_rs485(struct imx_port *sport)
373+
{
374+
unsigned int uts;
375+
376+
/* See SER_RS485_ENABLED/UTS_LOOP comment in imx_uart_probe() */
377+
uts = imx_uart_readl(sport, imx_uart_uts_reg(sport));
378+
uts &= ~UTS_LOOP;
379+
imx_uart_writel(sport, uts, imx_uart_uts_reg(sport));
380+
}
381+
372382
/* called with port.lock taken and irqs off */
373383
static void imx_uart_start_rx(struct uart_port *port)
374384
{
@@ -390,6 +400,7 @@ static void imx_uart_start_rx(struct uart_port *port)
390400
/* Write UCR2 first as it includes RXEN */
391401
imx_uart_writel(sport, ucr2, UCR2);
392402
imx_uart_writel(sport, ucr1, UCR1);
403+
imx_uart_disable_loopback_rs485(sport);
393404
}
394405

395406
/* called with port.lock taken and irqs off */
@@ -1422,7 +1433,7 @@ static int imx_uart_startup(struct uart_port *port)
14221433
int retval;
14231434
unsigned long flags;
14241435
int dma_is_inited = 0;
1425-
u32 ucr1, ucr2, ucr3, ucr4, uts;
1436+
u32 ucr1, ucr2, ucr3, ucr4;
14261437

14271438
retval = clk_prepare_enable(sport->clk_per);
14281439
if (retval)
@@ -1521,10 +1532,7 @@ static int imx_uart_startup(struct uart_port *port)
15211532
imx_uart_writel(sport, ucr2, UCR2);
15221533
}
15231534

1524-
/* See SER_RS485_ENABLED/UTS_LOOP comment in imx_uart_probe() */
1525-
uts = imx_uart_readl(sport, imx_uart_uts_reg(sport));
1526-
uts &= ~UTS_LOOP;
1527-
imx_uart_writel(sport, uts, imx_uart_uts_reg(sport));
1535+
imx_uart_disable_loopback_rs485(sport);
15281536

15291537
spin_unlock_irqrestore(&sport->port.lock, flags);
15301538

0 commit comments

Comments
 (0)