From patchwork Thu Aug 14 08:29:14 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nimrod Andy X-Patchwork-Id: 379873 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 07A951400AB for ; Thu, 14 Aug 2014 18:44:16 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754390AbaHNIoI (ORCPT ); Thu, 14 Aug 2014 04:44:08 -0400 Received: from dns-bn1lp0143.outbound.protection.outlook.com ([207.46.163.143]:7696 "EHLO na01-bn1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1754375AbaHNIoF (ORCPT ); Thu, 14 Aug 2014 04:44:05 -0400 Received: from BN3PR0301CA0075.namprd03.prod.outlook.com (25.160.152.171) by BLUPR03MB375.namprd03.prod.outlook.com (10.141.75.149) with Microsoft SMTP Server (TLS) id 15.0.1005.10; Thu, 14 Aug 2014 08:44:02 +0000 Received: from BN1AFFO11FD027.protection.gbl (2a01:111:f400:7c10::195) by BN3PR0301CA0075.outlook.office365.com (2a01:111:e400:401e::43) with Microsoft SMTP Server (TLS) id 15.0.1005.10 via Frontend Transport; Thu, 14 Aug 2014 08:44:02 +0000 Received: from tx30smr01.am.freescale.net (192.88.168.50) by BN1AFFO11FD027.mail.protection.outlook.com (10.58.52.87) with Microsoft SMTP Server (TLS) id 15.0.1010.11 via Frontend Transport; Thu, 14 Aug 2014 08:44:02 +0000 Received: from shlinux1.ap.freescale.net (shlinux1.ap.freescale.net [10.192.225.216]) by tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id s7E8hwxp015447; Thu, 14 Aug 2014 01:44:00 -0700 From: Fugang Duan To: CC: , , Subject: [PATCH] i2c: imx: double check IIF in case interrupt lost Date: Thu, 14 Aug 2014 16:29:14 +0800 Message-ID: <1408004954-29418-1-git-send-email-b38611@freescale.com> X-Mailer: git-send-email 1.7.8 X-EOPAttributedMessage: 0 X-Forefront-Antispam-Report: CIP:192.88.168.50; CTRY:US; IPV:CAL; IPV:NLI; EFV:NLI; SFV:NSPM; SFS:(6009001)(189002)(199003)(2351001)(97736001)(68736004)(229853001)(102836001)(87286001)(21056001)(104016003)(4396001)(26826002)(107046002)(83322001)(85306004)(19580395003)(44976005)(87936001)(77982001)(50226001)(36756003)(19580405001)(62966002)(92726001)(74502001)(33646002)(79102001)(31966008)(46102001)(76482001)(64706001)(20776003)(104166001)(50986999)(89996001)(74662001)(85852003)(92566001)(99396002)(110136001)(95666004)(93916002)(84676001)(6806004)(81542001)(48376002)(106466001)(83072002)(88136002)(47776003)(77156001)(80022001)(105606002)(50466002)(81342001)(42262002); DIR:OUT; SFP:; SCL:1; SRVR:BLUPR03MB375; H:tx30smr01.am.freescale.net; FPR:; MLV:ovrnspm; PTR:InfoDomainNonexistent; MX:1; A:1; LANG:en; MIME-Version: 1.0 X-Microsoft-Antispam: BCL:0;PCL:0;RULEID:;UriScan:; X-Forefront-PRVS: 03030B9493 Received-SPF: Fail (protection.outlook.com: domain of freescale.com does not designate 192.88.168.50 as permitted sender) receiver=protection.outlook.com; client-ip=192.88.168.50; helo=tx30smr01.am.freescale.net; Authentication-Results: spf=fail (sender IP is 192.88.168.50) smtp.mailfrom=fugang.duan@freescale.com; X-OriginatorOrg: freescale.com Sender: linux-i2c-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org In i2c_imx_read(): ... result = i2c_imx_trx_complete(i2c_imx); if (result) return result; .. If the current byte read complete, "IIF" status is set, and pend up one GIC interrupt. In irq handler, wake up the wait queue in .i2c_imx_trx_complete(). But, for imx6q platform with high bus and cpu loading test cases, after long time test, sometime i2c interrupt is lost, but "IIF" is set, according to current logic code, i2c_imx_trx_complete() still return "-ETIMEDOUT", and then i2c host don't read the rest of data, i2c driver stop transmit, disable controller and clock. Thus, i2c device cannot wait clock and always drive the SDA line. So, SDA is pulled down by i2c device, which needs 9 clocks to recovery the SDA line. To avoid the issue, we can double check IIF bit after timeout for waiting event in .i2c_imx_trx_complete(), if IIF bit is set, process it in normal flow. The patch just to double check IIF in case interrupt lost. Signed-off-by: Fugang Duan --- drivers/i2c/busses/i2c-imx.c | 10 ++++++++-- 1 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index aa8bc14..4b63771 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -285,11 +285,17 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy) static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx) { + unsigned int temp; + wait_event_timeout(i2c_imx->queue, i2c_imx->i2csr & I2SR_IIF, HZ / 10); if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) { - dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__); - return -ETIMEDOUT; + /* Double check IIF to avoid interrupt lost */ + temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR); + if (!(temp & I2SR_IIF)) { + dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__); + return -ETIMEDOUT; + } } dev_dbg(&i2c_imx->adapter.dev, "<%s> TRX complete\n", __func__); i2c_imx->i2csr = 0;