X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=drivers%2Fserial%2Fserial_meson.c;h=496a2ca2c35ba2a21e7658f14c3d7d287dd02c81;hb=6b7937821dfdd53a7a733b3f723de1d84500247d;hp=363affb8c5f8e2e07a83d56265c6e276ba025b68;hpb=a821c4af79e4f5ce9b629b20473863397bbe9b10;p=platform%2Fkernel%2Fu-boot.git diff --git a/drivers/serial/serial_meson.c b/drivers/serial/serial_meson.c index 363affb..496a2ca 100644 --- a/drivers/serial/serial_meson.c +++ b/drivers/serial/serial_meson.c @@ -1,18 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * (C) Copyright 2016 Beniamino Galvani - * - * SPDX-License-Identifier: GPL-2.0+ */ #include #include #include #include +#include #include #include -DECLARE_GLOBAL_DATA_PTR; - struct meson_uart { u32 wfifo; u32 rfifo; @@ -67,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; } @@ -97,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) @@ -108,7 +141,7 @@ static int meson_serial_ofdata_to_platdata(struct udevice *dev) struct meson_serial_platdata *plat = dev->platdata; fdt_addr_t addr; - addr = devfdt_get_addr(dev); + addr = dev_read_addr(dev); if (addr == FDT_ADDR_T_NONE) return -EINVAL; @@ -125,6 +158,7 @@ static const struct dm_serial_ops meson_serial_ops = { static const struct udevice_id meson_serial_ids[] = { { .compatible = "amlogic,meson-uart" }, + { .compatible = "amlogic,meson-gx-uart" }, { } }; @@ -134,7 +168,6 @@ U_BOOT_DRIVER(serial_meson) = { .of_match = meson_serial_ids, .probe = meson_serial_probe, .ops = &meson_serial_ops, - .flags = DM_FLAG_PRE_RELOC, .ofdata_to_platdata = meson_serial_ofdata_to_platdata, .platdata_auto_alloc_size = sizeof(struct meson_serial_platdata), };