From patchwork Thu Oct 26 22:13:06 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Lukasz Majewski X-Patchwork-Id: 830957 X-Patchwork-Delegate: sjg@chromium.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3yNLr52pzQz9sxR for ; Fri, 27 Oct 2017 09:13:39 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 88C3EC21DC5; Thu, 26 Oct 2017 22:13:35 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 6BF3CC21C34; Thu, 26 Oct 2017 22:13:32 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 9FC85C21C34; Thu, 26 Oct 2017 22:13:30 +0000 (UTC) Received: from mail-out.m-online.net (mail-out.m-online.net [212.18.0.10]) by lists.denx.de (Postfix) with ESMTPS id 50443C21C29 for ; Thu, 26 Oct 2017 22:13:30 +0000 (UTC) Received: from frontend01.mail.m-online.net (unknown [192.168.8.182]) by mail-out.m-online.net (Postfix) with ESMTP id 3yNLqr4Ywlz1qtFW; Fri, 27 Oct 2017 00:13:28 +0200 (CEST) Received: from localhost (dynscan1.mnet-online.de [192.168.6.70]) by mail.m-online.net (Postfix) with ESMTP id 3yNLqr3pFyz1qqkr; Fri, 27 Oct 2017 00:13:28 +0200 (CEST) X-Virus-Scanned: amavisd-new at mnet-online.de Received: from mail.mnet-online.de ([192.168.8.182]) by localhost (dynscan1.mail.m-online.net [192.168.6.70]) (amavisd-new, port 10024) with ESMTP id NQDe_EeLz6t4; Fri, 27 Oct 2017 00:13:27 +0200 (CEST) X-Auth-Info: fTKadgAhvXJoReacmUMXTyJNcFpahh5No+1bx8GNAiM= Received: from localhost.localdomain (89-64-27-66.dynamic.chello.pl [89.64.27.66]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.mnet-online.de (Postfix) with ESMTPSA; Fri, 27 Oct 2017 00:13:26 +0200 (CEST) From: Lukasz Majewski To: u-boot@lists.denx.de Date: Fri, 27 Oct 2017 00:13:06 +0200 Message-Id: <1509055986-23719-1-git-send-email-lukma@denx.de> X-Mailer: git-send-email 2.1.4 MIME-Version: 1.0 Cc: Stefan Roese , Andy Yan Subject: [U-Boot] [PATCH] dm: serial: Add .pre_probe() function to to wait for previous transmission end X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" 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 --- 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),