On Thursday 12 January 2023 18:19:50 Loic Poulain wrote: > The u-boot console may show some corrupted characters when > printing in board_init() due to reset or baudrate change > of the UART (probe) before the TX FIFO has been completely > drained. > > To fix this issue, and in case UART is still running, we now > try to flush the FIFO before proceeding to UART reinitialization. > For this we're waiting for Transmitter Complete bit, indicating > that the FIFO and the shift register are empty. > > flushing has a 4ms timeout guard, which is normally more than > enough to consume the FIFO @ low baudrate (9600bps). > > Signed-off-by: Loic Poulain <loic.poul...@linaro.org> > Tested-by: Lothar Waßmann <l...@karo-electronics.de>
Acked-by: Pali Rohár <p...@kernel.org> > --- > v2: Add this commit to the series > v3: Fix typo & reordering commits for good bisectabilit > v4: Wait for transfer completion before baudrate change as well > > drivers/serial/serial_mxc.c | 26 +++++++++++++++++++++++++- > 1 file changed, 25 insertions(+), 1 deletion(-) > > diff --git a/drivers/serial/serial_mxc.c b/drivers/serial/serial_mxc.c > index 82c0d84628..9e5b987994 100644 > --- a/drivers/serial/serial_mxc.c > +++ b/drivers/serial/serial_mxc.c > @@ -13,6 +13,7 @@ > #include <dm/platform_data/serial_mxc.h> > #include <serial.h> > #include <linux/compiler.h> > +#include <linux/delay.h> > > /* UART Control Register Bit Fields.*/ > #define URXD_CHARRDY (1<<15) > @@ -144,8 +145,22 @@ struct mxc_uart { > u32 ts; > }; > > +static void _mxc_serial_flush(struct mxc_uart *base) > +{ > + unsigned int timeout = 4000; > + > + if (!(readl(&base->cr1) & UCR1_UARTEN) || > + !(readl(&base->cr2) & UCR2_TXEN)) > + return; > + > + while (!(readl(&base->sr2) & USR2_TXDC) && --timeout) > + udelay(1); > +} > + > static void _mxc_serial_init(struct mxc_uart *base, int use_dte) > { > + _mxc_serial_flush(base); > + > writel(0, &base->cr1); > writel(0, &base->cr2); > > @@ -169,6 +184,8 @@ static void _mxc_serial_setbrg(struct mxc_uart *base, > unsigned long clk, > { > u32 tmp; > > + _mxc_serial_flush(base); > + > tmp = RFDIV << UFCR_RFDIV_SHF; > if (use_dte) > tmp |= UFCR_DCEDTE; > @@ -252,10 +269,17 @@ static int mxc_serial_init(void) > return 0; > } > > +static int mxc_serial_stop(void) > +{ > + _mxc_serial_flush(mxc_base); > + > + return 0; > +} > + > static struct serial_device mxc_serial_drv = { > .name = "mxc_serial", > .start = mxc_serial_init, > - .stop = NULL, > + .stop = mxc_serial_stop, > .setbrg = mxc_serial_setbrg, > .putc = mxc_serial_putc, > .puts = default_serial_puts, > -- > 2.34.1 >