From patchwork Tue Apr 30 01:48:25 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marek_Beh=C3=BAn?= X-Patchwork-Id: 1092932 X-Patchwork-Delegate: sr@denx.de 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=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=nic.cz Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; secure) header.d=nic.cz header.i=@nic.cz header.b="HvtpPteS"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 44tPj66K0Sz9s9T for ; Tue, 30 Apr 2019 11:54:34 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 823B1C21E15; Tue, 30 Apr 2019 01:50:53 +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=T_DKIM_INVALID 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 531D5C21E4E; Tue, 30 Apr 2019 01:48:35 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 8E782C21C51; Tue, 30 Apr 2019 01:48:28 +0000 (UTC) Received: from mail.nic.cz (mail.nic.cz [217.31.204.67]) by lists.denx.de (Postfix) with ESMTPS id DDA7EC21CB6 for ; Tue, 30 Apr 2019 01:48:27 +0000 (UTC) Received: from dellmb.labs.office.nic.cz (unknown [172.20.6.125]) by mail.nic.cz (Postfix) with ESMTP id 7E8E563836; Tue, 30 Apr 2019 03:48:27 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=nic.cz; s=default; t=1556588907; bh=qV4HbwrsX/1/ubreg9Sv5QBA/3VC/B5LIkqrfG9ksIU=; h=From:To:Date; b=HvtpPteSBjGYH/qd+dpEssOn1I4jrI8xIKsc6KeCzryUnIcdSEy4mNnhT8/oK/ZCX Z3TukaixDoChjrfEtsXGvl09Q+nUw0J9LsdHirq5wLN2HfaLa1XPJ2U95WgiJLZUUn 1ECoGat5omCJgXdndVuW0SJTavbUGEvguf68CLic= From: =?utf-8?q?Marek_Beh=C3=BAn?= To: u-boot@lists.denx.de Date: Tue, 30 Apr 2019 03:48:25 +0200 Message-Id: <20190430014825.30553-16-marek.behun@nic.cz> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190430014825.30553-1-marek.behun@nic.cz> References: <20190430014825.30553-1-marek.behun@nic.cz> MIME-Version: 1.0 X-Virus-Scanned: clamav-milter 0.99.2 at mail X-Virus-Status: Clean Cc: Baruch Siach , Stefan Roese Subject: [U-Boot] [PATCH u-boot-marvell v2 15/15] i2c: mvtwsi: fix reading status register after interrupt 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" The twsi_wait function reads the control register for interrupt flag, and if interrupt flag is present, it immediately reads status register. On our device this sometimes causes bad value being read from status register, as if the value was not yet updated. My theory is that the controller does approximately this: 1. sets interrupt flag in control register, 2. sets the value of status register, 3. causes an interrupt In U-Boot we do not use interrupts, so I think that it is possible that sometimes the status register in the twsi_wait function is read between points 1 and 2. The bug does not appear if I add a small delay before reading status register. Wait 100ns (which in U-Boot currently means 1 us, because ndelay(i) function calls udelay(DIV_ROUND_UP(i, 1000))) before reading the status register. Signed-off-by: Marek BehĂșn Cc: Mario Six Cc: Stefan Roese Cc: Baruch Siach Cc: Heiko Schocher Acked-by: Heiko Schocher --- drivers/i2c/mvtwsi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/i2c/mvtwsi.c b/drivers/i2c/mvtwsi.c index 74ac0a4aa7..483a71ba12 100644 --- a/drivers/i2c/mvtwsi.c +++ b/drivers/i2c/mvtwsi.c @@ -271,6 +271,7 @@ static int twsi_wait(struct mvtwsi_registers *twsi, int expected_status, do { control = readl(&twsi->control); if (control & MVTWSI_CONTROL_IFLG) { + ndelay(100); status = readl(&twsi->status); if (status == expected_status) return 0;