[PATCH v2] serial: uartlite: Add support to work with any endianness
Michal Simek
monstr at monstr.eu
Wed Sep 23 14:05:12 CEST 2020
po 14. 9. 2020 v 11:28 odesílatel Michal Simek <michal.simek at xilinx.com> napsal:
>
> From: T Karthik Reddy <t.karthik.reddy at xilinx.com>
>
> This endinness changes are taken from linux uartlite driver.
> Reset TX fifo in control register and check TX fifo empty
> flag in lower byte of the status register to detect if it
> is a little endian system. Based on this check, program the
> registers with le32 or be32 through out the driver.
>
> Signed-off-by: T Karthik Reddy <t.karthik.reddy at xilinx.com>
> Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma at xilinx.com>
> Signed-off-by: Michal Simek <michal.simek at xilinx.com>
> ---
>
> Changes in v2:
> - Use simple mechanism to support le and be
> - Update debug uartlite to support le and be
> - Reset RX/TX FIFO for little endian systems
>
> drivers/serial/serial_xuartlite.c | 64 +++++++++++++++++++++++--------
> 1 file changed, 48 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/serial/serial_xuartlite.c b/drivers/serial/serial_xuartlite.c
> index 5116d13751de..236ab860ad87 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;
> -
> - out_be32(®s->control, 0);
> - out_be32(®s->control, ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX);
> - in_be32(®s->control);
> + int ret;
> +
> + 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;
> -
> - out_be32(®s->control, 0);
> - out_be32(®s->control, ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX);
> - in_be32(®s->control);
> + int ret;
> +
> + 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
> --
> 2.28.0
>
Applied.
M
--
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP/Versal SoCs
More information about the U-Boot
mailing list