Message ID | 113756fda74a683fe15728fabdf96f0599750172.1598530214.git.michal.simek@xilinx.com |
---|---|
State | Deferred |
Delegated to: | Tom Rini |
Headers | show |
Series | serial: uartlite: Add support to work with any endianness | expand |
Hi, čt 27. 8. 2020 v 14:10 odesílatel Michal Simek <michal.simek@xilinx.com> napsal: > > From: T Karthik Reddy <t.karthik.reddy@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@xilinx.com> > Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com> > Signed-off-by: Michal Simek <michal.simek@xilinx.com> > --- > > drivers/serial/serial_xuartlite.c | 74 ++++++++++++++++++++++++++----- > 1 file changed, 64 insertions(+), 10 deletions(-) > > diff --git a/drivers/serial/serial_xuartlite.c b/drivers/serial/serial_xuartlite.c > index 5116d13751de..e16642504b16 100644 > --- a/drivers/serial/serial_xuartlite.c > +++ b/drivers/serial/serial_xuartlite.c > @@ -32,17 +32,64 @@ struct uartlite { > > struct uartlite_platdata { > struct uartlite *regs; > + const struct uartlite_reg_ops *reg_ops; > }; > > +struct uartlite_reg_ops { > + u32 (*in)(void __iomem *addr); > + void (*out)(u32 val, void __iomem *addr); > +}; > + > +static u32 uartlite_inle32(void __iomem *addr) > +{ > + return in_le32(addr); > +} > + > +static void uartlite_outle32(u32 val, void __iomem *addr) > +{ > + out_le32(addr, val); > +} > + > +static const struct uartlite_reg_ops uartlite_le = { > + .in = uartlite_inle32, > + .out = uartlite_outle32, > +}; > + > +static u32 uartlite_inbe32(void __iomem *addr) > +{ > + return in_be32(addr); > +} > + > +static void uartlite_outbe32(u32 val, void __iomem *addr) > +{ > + out_be32(addr, val); > +} > + > +static const struct uartlite_reg_ops uartlite_be = { > + .in = uartlite_inbe32, > + .out = uartlite_outbe32, > +}; > + > +static u32 uart_in32(void __iomem *addr, struct uartlite_platdata *plat) > +{ > + return plat->reg_ops->in(addr); > +} > + > +static void uart_out32(void __iomem *addr, u32 val, > + struct uartlite_platdata *plat) > +{ > + plat->reg_ops->out(val, addr); > +} > + > 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, plat) & SR_TX_FIFO_FULL) > return -EAGAIN; > > - out_be32(®s->tx_fifo, ch & 0xff); > + uart_out32(®s->tx_fifo, ch & 0xff, plat); > > return 0; > } > @@ -52,10 +99,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, plat) & SR_RX_FIFO_VALID_DATA)) > return -EAGAIN; > > - return in_be32(®s->rx_fifo) & 0xff; > + return uart_in32(®s->rx_fifo, plat) & 0xff; > } > > static int uartlite_serial_pending(struct udevice *dev, bool input) > @@ -64,19 +111,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, plat) & SR_RX_FIFO_VALID_DATA; > > - return !(in_be32(®s->status) & SR_TX_FIFO_EMPTY); > + return !(uart_in32(®s->status, plat) & 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; > + > + plat->reg_ops = &uartlite_be; > + ret = uart_in32(®s->control, plat); > + uart_out32(®s->control, 0, plat); > + uart_out32(®s->control, > + ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX, plat); > + ret = uart_in32(®s->status, plat); > + /* Endianness detection */ > + if ((ret & SR_TX_FIFO_EMPTY) != SR_TX_FIFO_EMPTY) > + plat->reg_ops = &uartlite_le; > > return 0; > } > -- > 2.28.0 > We found some issues with this patch that's why please ignore it - v2 will be sent. Thanks, Michal
diff --git a/drivers/serial/serial_xuartlite.c b/drivers/serial/serial_xuartlite.c index 5116d13751de..e16642504b16 100644 --- a/drivers/serial/serial_xuartlite.c +++ b/drivers/serial/serial_xuartlite.c @@ -32,17 +32,64 @@ struct uartlite { struct uartlite_platdata { struct uartlite *regs; + const struct uartlite_reg_ops *reg_ops; }; +struct uartlite_reg_ops { + u32 (*in)(void __iomem *addr); + void (*out)(u32 val, void __iomem *addr); +}; + +static u32 uartlite_inle32(void __iomem *addr) +{ + return in_le32(addr); +} + +static void uartlite_outle32(u32 val, void __iomem *addr) +{ + out_le32(addr, val); +} + +static const struct uartlite_reg_ops uartlite_le = { + .in = uartlite_inle32, + .out = uartlite_outle32, +}; + +static u32 uartlite_inbe32(void __iomem *addr) +{ + return in_be32(addr); +} + +static void uartlite_outbe32(u32 val, void __iomem *addr) +{ + out_be32(addr, val); +} + +static const struct uartlite_reg_ops uartlite_be = { + .in = uartlite_inbe32, + .out = uartlite_outbe32, +}; + +static u32 uart_in32(void __iomem *addr, struct uartlite_platdata *plat) +{ + return plat->reg_ops->in(addr); +} + +static void uart_out32(void __iomem *addr, u32 val, + struct uartlite_platdata *plat) +{ + plat->reg_ops->out(val, addr); +} + 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, plat) & SR_TX_FIFO_FULL) return -EAGAIN; - out_be32(®s->tx_fifo, ch & 0xff); + uart_out32(®s->tx_fifo, ch & 0xff, plat); return 0; } @@ -52,10 +99,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, plat) & SR_RX_FIFO_VALID_DATA)) return -EAGAIN; - return in_be32(®s->rx_fifo) & 0xff; + return uart_in32(®s->rx_fifo, plat) & 0xff; } static int uartlite_serial_pending(struct udevice *dev, bool input) @@ -64,19 +111,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, plat) & SR_RX_FIFO_VALID_DATA; - return !(in_be32(®s->status) & SR_TX_FIFO_EMPTY); + return !(uart_in32(®s->status, plat) & 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; + + plat->reg_ops = &uartlite_be; + ret = uart_in32(®s->control, plat); + uart_out32(®s->control, 0, plat); + uart_out32(®s->control, + ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX, plat); + ret = uart_in32(®s->status, plat); + /* Endianness detection */ + if ((ret & SR_TX_FIFO_EMPTY) != SR_TX_FIFO_EMPTY) + plat->reg_ops = &uartlite_le; return 0; }