[PATCH] serial: meson: handle RX errors

Neil Armstrong narmstrong at baylibre.com
Thu Jul 23 10:38:14 CEST 2020


On 21/07/2020 13:41, Neil Armstrong wrote:
> This checks and handles RX errors on the Amlogic UART controller
> after experiencing errors on the Khadas VIM3 & VIM3L when UART AO A
> lines are not connected.
> 
> When the RX line is not connected, the first byte is erroneous and breaks
> the U-Boot autoboot, breaking automatic boot.
> 
> This checks and drops any erroneous RX byte on pending and getc callbacks
> to avoid returning true to pending when an error byte is in the FIFO.
> 
> Fixes: bfcef28ae4 ("arm: add initial support for Amlogic Meson and ODROID-C2")
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---
>  drivers/serial/serial_meson.c | 43 +++++++++++++++++++++++++++++++----
>  1 file changed, 39 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/serial/serial_meson.c b/drivers/serial/serial_meson.c
> index 439057b1b9..1b1725f6aa 100644
> --- a/drivers/serial/serial_meson.c
> +++ b/drivers/serial/serial_meson.c
> @@ -65,14 +65,36 @@ static int meson_serial_probe(struct udevice *dev)
>  	return 0;
>  }
>  
> +static void meson_serial_rx_error(struct udevice *dev)
> +{
> +	struct meson_serial_platdata *plat = dev->platdata;
> +	struct meson_uart *const uart = plat->reg;
> +	u32 val = readl(&uart->control);
> +
> +	/* Clear error */
> +	val |= AML_UART_CLR_ERR;
> +	writel(val, &uart->control);
> +	val &= ~AML_UART_CLR_ERR;
> +	writel(val, &uart->control);
> +
> +	/* Remove spurious byte from fifo */
> +	readl(&uart->rfifo);
> +}
> +
>  static int meson_serial_getc(struct udevice *dev)
>  {
>  	struct meson_serial_platdata *plat = dev->platdata;
>  	struct meson_uart *const uart = plat->reg;
> +	uint32_t status = readl(&uart->status);
>  
> -	if (readl(&uart->status) & AML_UART_RX_EMPTY)
> +	if (status & AML_UART_RX_EMPTY)
>  		return -EAGAIN;
>  
> +	if (status & AML_UART_ERR) {
> +		meson_serial_rx_error(dev);
> +		return -EIO;
> +	}
> +
>  	return readl(&uart->rfifo) & 0xff;
>  }
>  
> @@ -95,10 +117,23 @@ static int meson_serial_pending(struct udevice *dev, bool input)
>  	struct meson_uart *const uart = plat->reg;
>  	uint32_t status = readl(&uart->status);
>  
> -	if (input)
> -		return !(status & AML_UART_RX_EMPTY);
> -	else
> +	if (input) {
> +		if (status & AML_UART_RX_EMPTY)
> +			return false;
> +
> +		/*
> +		 * Handle and drop any RX error here to avoid
> +		 * returning true here when an error byte is in the FIFO
> +		 */
> +		if (status & AML_UART_ERR) {
> +			meson_serial_rx_error(dev);
> +			return false;
> +		}
> +
> +		return true;
> +	} else {
>  		return !(status & AML_UART_TX_FULL);
> +	}
>  }
>  
>  static int meson_serial_ofdata_to_platdata(struct udevice *dev)
> 

Applied to u-boot-amlogic

Neil


More information about the U-Boot mailing list