[PATCH v2 1/2] serial: mxc: Speed-up character transmission

Instead of waiting for empty FIFO condition before writing a character, wait for non-full FIFO condition.
This helps in saving several tens of milliseconds during boot (depending verbosity).
Signed-off-by: Loic Poulain loic.poulain@linaro.org --- v2: Add 2/2 fixing transfert abort & char corruption
drivers/serial/serial_mxc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/serial/serial_mxc.c b/drivers/serial/serial_mxc.c index 82c0d84628..f8c49865be 100644 --- a/drivers/serial/serial_mxc.c +++ b/drivers/serial/serial_mxc.c @@ -223,11 +223,11 @@ static void mxc_serial_putc(const char c) if (c == '\n') serial_putc('\r');
- writel(c, &mxc_base->txd); - /* wait for transmitter to be ready */ - while (!(readl(&mxc_base->ts) & UTS_TXEMPTY)) + while (readl(&mxc_base->ts) & UTS_TXFULL) schedule(); + + writel(c, &mxc_base->txd); }
/* Test whether a character is in the RX buffer */ @@ -311,7 +311,7 @@ static int mxc_serial_putc(struct udevice *dev, const char ch) struct mxc_serial_plat *plat = dev_get_plat(dev); struct mxc_uart *const uart = plat->reg;
- if (!(readl(&uart->ts) & UTS_TXEMPTY)) + if (readl(&uart->ts) & UTS_TXFULL) return -EAGAIN;
writel(ch, &uart->txd);

The u-boot console may show some corrupted characters when printing in board_init() due to reset 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 proceding 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.poulain@linaro.org --- v2: Add this commit to the series
drivers/serial/serial_mxc.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/drivers/serial/serial_mxc.c b/drivers/serial/serial_mxc.c index f8c49865be..9899155c00 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);
@@ -252,10 +267,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,
participants (1)
-
Loic Poulain