[U-Boot] [PATCH] dm: serial: Add .pre_probe() function to to wait for previous transmission end

Lukasz Majewski lukma at denx.de
Thu Oct 26 22:13:06 UTC 2017


It may happen that the serial IP block is performing some ongoing
transmission (started at e.g. board_init()) when the serial "probe" is
called.

As a result the serial port IP block is reset, so transmitted data is
corrupted:

    I2C:   ready
    DRAM:  1 GiB
    jSS('HH��SL_SDHC: 04 rev 0x0

This patch prevents from this situation, by defining pre_probe() callback
in which we wait till the TX buffer is empty (from previous transmission):

    I2C:   ready
    DRAM:  1 GiB
    ID:    unit type 0x4 rev 0x0

All defined ->pending callbacks at ./drivers/serial are non blocking
- just simple reading from registers and testing flags. Hence, it should
be enough to not use any timeout from timer.
One shall also note that we enable console very early - not all timers
may be ready for work - adding timeout here would impose implicit
dependency that timers are setup before serial.


Signed-off-by: Lukasz Majewski <lukma at denx.de>
---

 drivers/serial/serial-uclass.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
index 2e5116f..5e6964d 100644
--- a/drivers/serial/serial-uclass.c
+++ b/drivers/serial/serial-uclass.c
@@ -420,10 +420,30 @@ static int serial_pre_remove(struct udevice *dev)
 	return 0;
 }
 
+static int serial_pre_probe(struct udevice *dev)
+{
+	struct dm_serial_ops *ops = serial_get_ops(dev);
+	int ret = 0;
+
+	/*
+	 * Wait for any ongoing transmission to finish - for example
+	 * from pre-relocation enabled UART
+	 */
+	if (ops && ops->pending)
+		do {
+			ret = ops->pending(dev, false);
+			if (ret < 0)
+				break;
+		} while (ret > 0);
+
+	return ret;
+}
+
 UCLASS_DRIVER(serial) = {
 	.id		= UCLASS_SERIAL,
 	.name		= "serial",
 	.flags		= DM_UC_FLAG_SEQ_ALIAS,
+	.pre_probe	= serial_pre_probe,
 	.post_probe	= serial_post_probe,
 	.pre_remove	= serial_pre_remove,
 	.per_device_auto_alloc_size = sizeof(struct serial_dev_priv),
-- 
2.1.4



More information about the U-Boot mailing list