po 14. 9. 2020 v 11:28 odesÃlatel Michal Simek <[email protected]> napsal: > > From: T Karthik Reddy <[email protected]> > > 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 <[email protected]> > Signed-off-by: Ashok Reddy Soma <[email protected]> > Signed-off-by: Michal Simek <[email protected]> > --- > > 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

