BUG: imx: initial UART receive causes IO errors

Stefan Wahren stefan.wahren at i2se.com
Mon Dec 7 09:09:36 EST 2020


Hi,

Am 17.11.20 um 09:14 schrieb Stefan Wahren:
> 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.
the issue still exists in Linux 5.10 rc6.
>
> 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
>
>



More information about the linux-arm-kernel mailing list