[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(&regs->status) & SR_TX_FIFO_FULL)
> +       if (uart_in32(&regs->status) & SR_TX_FIFO_FULL)
>                 return -EAGAIN;
>
> -       out_be32(&regs->tx_fifo, ch & 0xff);
> +       uart_out32(&regs->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(&regs->status) & SR_RX_FIFO_VALID_DATA))
> +       if (!(uart_in32(&regs->status) & SR_RX_FIFO_VALID_DATA))
>                 return -EAGAIN;
>
> -       return in_be32(&regs->rx_fifo) & 0xff;
> +       return uart_in32(&regs->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(&regs->status) & SR_RX_FIFO_VALID_DATA;
> +               return uart_in32(&regs->status) & SR_RX_FIFO_VALID_DATA;
>
> -       return !(in_be32(&regs->status) & SR_TX_FIFO_EMPTY);
> +       return !(uart_in32(&regs->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(&regs->control, 0);
> -       out_be32(&regs->control, ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX);
> -       in_be32(&regs->control);
> +       int ret;
> +
> +       uart_out32(&regs->control, 0);
> +       uart_out32(&regs->control, ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX);
> +       ret = uart_in32(&regs->status);
> +       /* Endianness detection */
> +       if ((ret & SR_TX_FIFO_EMPTY) != SR_TX_FIFO_EMPTY) {
> +               little_endian = true;
> +               uart_out32(&regs->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(&regs->control, 0);
> -       out_be32(&regs->control, ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX);
> -       in_be32(&regs->control);
> +       int ret;
> +
> +       uart_out32(&regs->control, 0);
> +       uart_out32(&regs->control, ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX);
> +       uart_in32(&regs->status);
> +       /* Endianness detection */
> +       if ((ret & SR_TX_FIFO_EMPTY) != SR_TX_FIFO_EMPTY) {
> +               little_endian = true;
> +               uart_out32(&regs->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(&regs->status) & SR_TX_FIFO_FULL)
> +       while (uart_in32(&regs->status) & SR_TX_FIFO_FULL)
>                 ;
>
> -       out_be32(&regs->tx_fifo, ch & 0xff);
> +       uart_out32(&regs->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