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;
}
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)