BUG: imx: initial UART receive causes IO errors

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

we are using a Modbus application on our customer i.MX6ULL board (RS-485
in hardware, no DMA). While porting the board support package to a
Mainline kernel, we noticed that after boot the initial UART receive
causes IO errors, which breaks our application (tested with Mainline
4.9, 4.19, 5.7, 5.9 but without success). The ancient vendor kernel
(imx-4.9.11) we are still using isn't affect by this issue.

So i bisected the vendor tree and found this huge patch which fixed the
issue [1]. After that i was able to narrow down the fix to the following
patch against Mainline Linux 5.9 (successful tested on i.MX6ULL):

diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 07974f2..3004b5c 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -1289,6 +1289,7 @@ static void imx_uart_clear_rx_errors(struct
imx_port *sport)
 
 #define TXTL_DEFAULT 2 /* reset default */
 #define RXTL_DEFAULT 1 /* reset default */
+#define RXTL_UART 16 /* For UART */
 #define TXTL_DMA 8 /* DMA burst setting */
 #define RXTL_DMA 9 /* DMA burst setting */
 
@@ -1415,6 +1416,7 @@ static int imx_uart_startup(struct uart_port *port)
     unsigned long flags;
     int dma_is_inited = 0;
     u32 ucr1, ucr2, ucr3, ucr4;
+    unsigned char rx_fifo_trig;
 
     retval = clk_prepare_enable(sport->clk_per);
     if (retval)
@@ -1425,7 +1427,12 @@ static int imx_uart_startup(struct uart_port *port)
         return retval;
     }
 
-    imx_uart_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
+    if (uart_console(&sport->port))
+        rx_fifo_trig = RXTL_DEFAULT;
+    else
+        rx_fifo_trig = RXTL_UART;
+
+    imx_uart_setup_ufcr(sport, TXTL_DEFAULT, rx_fifo_trig);
 
     /* disable the DREN bit (Data Ready interrupt enable) before
      * requesting IRQs
@@ -1674,7 +1681,7 @@ imx_uart_set_termios(struct uart_port *port,
struct ktermios *termios,
      * except those we will or may need to preserve.
      */
     old_ucr2 = imx_uart_readl(sport, UCR2);
-    ucr2 = old_ucr2 & (UCR2_TXEN | UCR2_RXEN | UCR2_ATEN | UCR2_CTS);
+    ucr2 = old_ucr2 & (UCR2_TXEN | UCR2_RXEN | UCR2_CTS);
 
     ucr2 |= UCR2_SRST | UCR2_IRTS;
     if ((termios->c_cflag & CSIZE) == CS8)
@@ -1795,6 +1802,9 @@ imx_uart_set_termios(struct uart_port *port,
struct ktermios *termios,
     if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
         imx_uart_enable_ms(&sport->port);
 
+    ucr2 = imx_uart_readl(sport, UCR2);
+    imx_uart_writel(sport, ucr2 | UCR2_ATEN, UCR2);
+
     spin_unlock_irqrestore(&sport->port.lock, flags);
 }

So i someone with a deeper insight can fix this properly.

Thanks Stefan

[1] -
https://source.codeaurora.org/external/imx/linux-imx/commit/drivers/tty/serial/imx.c?h=imx_4.9.11_1.0.0_ga&id=e287334648e0a0f6a76f3d9615eada6cd590cbd9





[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux