diff --git a/drivers/serial/serial_xuartlite.c b/drivers/serial/serial_xuartlite.c index 5116d13751..236ab860ad 100644 --- a/drivers/serial/serial_xuartlite.c +++ b/drivers/serial/serial_xuartlite.c @@ -23,6 +23,8 @@ #define ULITE_CONTROL_RST_TX 0x01 #define ULITE_CONTROL_RST_RX 0x02 +static bool little_endian; + struct uartlite { unsigned int rx_fifo; unsigned int tx_fifo; @@ -34,15 +36,31 @@ struct uartlite_platdata { struct uartlite *regs; }; +static u32 uart_in32(void __iomem *addr) +{ + if (little_endian) + return in_le32(addr); + else + return in_be32(addr); +} + +static void uart_out32(void __iomem *addr, u32 val) +{ + if (little_endian) + out_le32(addr, val); + else + out_be32(addr, val); +} + static int uartlite_serial_putc(struct udevice *dev, const char ch) { struct uartlite_platdata *plat = dev_get_platdata(dev); struct uartlite *regs = plat->regs; - if (in_be32(®s->status) & SR_TX_FIFO_FULL) + if (uart_in32(®s->status) & SR_TX_FIFO_FULL) return -EAGAIN; - out_be32(®s->tx_fifo, ch & 0xff); + uart_out32(®s->tx_fifo, ch & 0xff); return 0; } @@ -52,10 +70,10 @@ static int uartlite_serial_getc(struct udevice *dev) struct uartlite_platdata *plat = dev_get_platdata(dev); struct uartlite *regs = plat->regs; - if (!(in_be32(®s->status) & SR_RX_FIFO_VALID_DATA)) + if (!(uart_in32(®s->status) & SR_RX_FIFO_VALID_DATA)) return -EAGAIN; - return in_be32(®s->rx_fifo) & 0xff; + return uart_in32(®s->rx_fifo) & 0xff; } static int uartlite_serial_pending(struct udevice *dev, bool input) @@ -64,19 +82,26 @@ static int uartlite_serial_pending(struct udevice *dev, bool input) struct uartlite *regs = plat->regs; if (input) - return in_be32(®s->status) & SR_RX_FIFO_VALID_DATA; + return uart_in32(®s->status) & SR_RX_FIFO_VALID_DATA; - return !(in_be32(®s->status) & SR_TX_FIFO_EMPTY); + return !(uart_in32(®s->status) & SR_TX_FIFO_EMPTY); } static int uartlite_serial_probe(struct udevice *dev) { struct uartlite_platdata *plat = dev_get_platdata(dev); struct uartlite *regs = plat->regs; + int ret; - out_be32(®s->control, 0); - out_be32(®s->control, ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX); - in_be32(®s->control); + uart_out32(®s->control, 0); + uart_out32(®s->control, ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX); + ret = uart_in32(®s->status); + /* Endianness detection */ + if ((ret & SR_TX_FIFO_EMPTY) != SR_TX_FIFO_EMPTY) { + little_endian = true; + uart_out32(®s->control, ULITE_CONTROL_RST_RX | + ULITE_CONTROL_RST_TX); + } return 0; } @@ -119,20 +144,27 @@ U_BOOT_DRIVER(serial_uartlite) = { static inline void _debug_uart_init(void) { struct uartlite *regs = (struct uartlite *)CONFIG_DEBUG_UART_BASE; + int ret; - out_be32(®s->control, 0); - out_be32(®s->control, ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX); - in_be32(®s->control); + uart_out32(®s->control, 0); + uart_out32(®s->control, ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX); + uart_in32(®s->status); + /* Endianness detection */ + if ((ret & SR_TX_FIFO_EMPTY) != SR_TX_FIFO_EMPTY) { + little_endian = true; + uart_out32(®s->control, ULITE_CONTROL_RST_RX | + ULITE_CONTROL_RST_TX); + } } static inline void _debug_uart_putc(int ch) { struct uartlite *regs = (struct uartlite *)CONFIG_DEBUG_UART_BASE; - while (in_be32(®s->status) & SR_TX_FIFO_FULL) + while (uart_in32(®s->status) & SR_TX_FIFO_FULL) ; - out_be32(®s->tx_fifo, ch & 0xff); + uart_out32(®s->tx_fifo, ch & 0xff); } DEBUG_UART_FUNCS