[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