From patchwork Tue Feb 27 07:19:00 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrzej Hajda X-Patchwork-Id: 10244439 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 1CE9C60211 for ; Tue, 27 Feb 2018 07:19:24 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0446829989 for ; Tue, 27 Feb 2018 07:19:24 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id EAF8129EFF; Tue, 27 Feb 2018 07:19:23 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AAF1929989 for ; Tue, 27 Feb 2018 07:19:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752186AbeB0HTW (ORCPT ); Tue, 27 Feb 2018 02:19:22 -0500 Received: from mailout1.w1.samsung.com ([210.118.77.11]:49339 "EHLO mailout1.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752154AbeB0HTU (ORCPT ); Tue, 27 Feb 2018 02:19:20 -0500 Received: from eucas1p2.samsung.com (unknown [182.198.249.207]) by mailout1.w1.samsung.com (KnoxPortal) with ESMTP id 20180227071918euoutp01042505b8504cb4e30de04139fe4c8e0b~XHZzZpWQ32553525535euoutp01T; Tue, 27 Feb 2018 07:19:18 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout1.w1.samsung.com 20180227071918euoutp01042505b8504cb4e30de04139fe4c8e0b~XHZzZpWQ32553525535euoutp01T DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1519715958; bh=sIHEVyW0fyabIMfZVEfQFLAShP9aZyXMLCfiZWsQSsg=; h=From:To:Cc:Subject:Date:In-reply-to:References:From; b=LolJuaqxn+sb0l1Ed2Sk+xTQ8ByP13Vek0XImwDhznVc9sCOCmexT0Pw4o0kmc5ym Qw+4AARxjiBdmcEj8QWY3e0ApSuTGlovvNTwRYDzScRnTAQcTZVRxOnA1JRF1M/m3A 2sYdJOSuYzV4bndDI75oGRbAnEoAnDhek7thnNJA= Received: from eusmges1new.samsung.com (unknown [203.254.199.242]) by eucas1p2.samsung.com (KnoxPortal) with ESMTP id 20180227071917eucas1p25efd4a9d406d05043ade033485a2c8e0~XHZyAi71r0206002060eucas1p2t; Tue, 27 Feb 2018 07:19:17 +0000 (GMT) Received: from eucas1p2.samsung.com ( [182.198.249.207]) by eusmges1new.samsung.com (EUCPMTA) with SMTP id 75.9D.05700.476059A5; Tue, 27 Feb 2018 07:19:16 +0000 (GMT) Received: from eusmgms2.samsung.com (unknown [182.198.249.180]) by eucas1p2.samsung.com (KnoxPortal) with ESMTP id 20180227071916eucas1p284af2ef8432635877a28e2daa898a3d3~XHZw4Qv-V0229802298eucas1p2t; Tue, 27 Feb 2018 07:19:16 +0000 (GMT) X-AuditID: cbfec7f2-1c1ff70000011644-00-5a950674ee28 Received: from eusync3.samsung.com ( [203.254.199.213]) by eusmgms2.samsung.com (EUCPMTA) with SMTP id 56.BF.04183.376059A5; Tue, 27 Feb 2018 07:19:15 +0000 (GMT) Received: from AMDC2768.DIGITAL.local ([106.120.43.17]) by eusync3.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0P4S00LHISC3UU00@eusync3.samsung.com>; Tue, 27 Feb 2018 07:19:15 +0000 (GMT) From: Andrzej Hajda To: Wolfram Sang , Andi Shyti Cc: Andrzej Hajda , Bartlomiej Zolnierkiewicz , Marek Szyprowski , linux-i2c@vger.kernel.org (open list:I2C SUBSYSTEM), linux-samsung-soc@vger.kernel.org (moderated list:ARM/SAMSUNG EXYNOS ARM ARCHITECTURES) Subject: [PATCH v2] i2c: exynos5: rework HSI2C_MASTER_ST_LOSE state handling Date: Tue, 27 Feb 2018 08:19:00 +0100 Message-id: <20180227071900.29170-1-a.hajda@samsung.com> X-Mailer: git-send-email 2.16.2 In-reply-to: <20180226203014.hbxx6ljrrdmys2cn@ninjato> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrHIsWRmVeSWpSXmKPExsWy7djP87olbFOjDL5/17a4te4cq8X2I89Y LTbOWM9q0fH3C6PFjPP7mCzWHrnLbrHyxCxmB3aPvi2rGD1OnnrC4vF5k1wAcxSXTUpqTmZZ apG+XQJXxvXVp5gK5shXbG99y9jAeFSyi5GTQ0LAROJq123WLkYuDiGBFYwSB7e0QjmfGSVu /rrNBlO19f5qqMQyRonTV5axQTj/GSX2H5vNBFLFJqAp8XfzTbAOEQFPiVufW1hAipgFFjBJ vLjdA5YQFvCReDnjBpjNIqAqsffAX3YQm1fAQuLP3hdMEOvkJRaevcoMYnMKmEl86PjHBDJI QuAnq8Ts97vYIYpcJBa9fcwKYQtLvDq+BSouI3F5cjcLREM3o8SpfZ3MEM4URonzry5DrbCW OHz8Ilg3swCfxKRt04GKOIDivBIdbUIQJR4SjbfmQy1wlHi+bBkTxM+djBIvjv5lm8AotYCR YRWjeGppcW56arFhXmq5XnFibnFpXrpecn7uJkZgLJ7+d/zTDsavl5IOMQpwMCrx8M6QmxIl xJpYVlyZe4hRgoNZSYR35eLJUUK8KYmVValF+fFFpTmpxYcYpTlYlMR54zTqooQE0hNLUrNT UwtSi2CyTBycUg2Mwhsuvl16/M3sY3ccfgT1HbnAZ9nOZm43fa7KpbC6R4yFttr24svOpgv9 Zmi6Udnz90zhLvvFtw/u9VkivMLs7lZtloyUxzeOcf86Vf1P+FrUtgmn05ivuUSHXfKuvGl1 +H9e+fJZn47e9Uufz342NItVo8IvLfyaTPSBhIJfd8s9Dn1h7Jq/XYmlOCPRUIu5qDgRAL8p giTBAgAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrHJMWRmVeSWpSXmKPExsVy+t/xq7rFbFOjDDY9tLK4te4cq8X2I89Y LTbOWM9q0fH3C6PFjPP7mCzWHrnLbrHyxCxmB3aPvi2rGD1OnnrC4vF5k1wAcxSXTUpqTmZZ apG+XQJXxvXVp5gK5shXbG99y9jAeFSyi5GTQ0LARGLr/dWsXYxcHEICSxglZvS+YIdwGpkk Hm/YzQ5SxSagKfF38002EFtEwFPi1ucWFpAiZoFFTBJnu/aCFQkL+Ei8nHEDrIhFQFVi74G/ YHFeAQuJP3tfMEGsk5dYePYqM4jNKWAm8aHjH1hcSMBU4lvvBMYJjDwLGBlWMYqklhbnpucW G+kVJ+YWl+al6yXn525iBIbKtmM/t+xg7HoXfIhRgINRiYd3htyUKCHWxLLiytxDjBIczEoi vCsXT44S4k1JrKxKLcqPLyrNSS0+xCjNwaIkznveoDJKSCA9sSQ1OzW1ILUIJsvEwSnVwKhz RvBKxIuUnb2TbEu9kk6+r+9P3viuWNtkjqTez/ZLy312RIpv+Z125NRVttdqb7+abCiwMD50 uOLh6/blz0512KXtT7lw3Pzx67sz27WvfF8iess/NEXx/pI0VrvZvzYIcEk9vhW8bNMyVgaP m6VM0dEMb+x6ZjwwDWB4NSv6eLXtl4v/ki8osRRnJBpqMRcVJwIA9ZxtIBECAAA= X-CMS-MailID: 20180227071916eucas1p284af2ef8432635877a28e2daa898a3d3 X-Msg-Generator: CA CMS-TYPE: 201P X-CMS-RootMailID: 20180227071916eucas1p284af2ef8432635877a28e2daa898a3d3 X-RootMTR: 20180227071916eucas1p284af2ef8432635877a28e2daa898a3d3 References: <20180226203014.hbxx6ljrrdmys2cn@ninjato> Sender: linux-samsung-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-samsung-soc@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP HSI2C_MASTER_ST_LOSE state is not documented properly, extensive tests show that hardware is usually able to recover from this state without interrupting the transfer. Moreover documentation says that such state can be caused by slave clock stretching, and should not be treated as an error during transaction. The only place it indicates an error is just before starting transaction. In such case bus recovery procedure should be performed - master should pulse SCL line nine times and then send STOP condition, it can be repeated until SDA goes high. The procedure can be performed using manual commands HSI2C_CMD_READ_DATA and HSI2C_CMD_SEND_STOP. Signed-off-by: Andrzej Hajda --- v2: removed debug code Regards Andrzej drivers/i2c/busses/i2c-exynos5.c | 63 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c index b02428498f6d..12ec8484e653 100644 --- a/drivers/i2c/busses/i2c-exynos5.c +++ b/drivers/i2c/busses/i2c-exynos5.c @@ -128,6 +128,10 @@ #define HSI2C_TIMEOUT_EN (1u << 31) #define HSI2C_TIMEOUT_MASK 0xff +/* I2C_MANUAL_CMD register bits */ +#define HSI2C_CMD_READ_DATA (1u << 4) +#define HSI2C_CMD_SEND_STOP (1u << 2) + /* I2C_TRANS_STATUS register bits */ #define HSI2C_MASTER_BUSY (1u << 17) #define HSI2C_SLAVE_BUSY (1u << 16) @@ -441,12 +445,6 @@ static irqreturn_t exynos5_i2c_irq(int irqno, void *dev_id) i2c->state = -ETIMEDOUT; goto stop; } - - trans_status = readl(i2c->regs + HSI2C_TRANS_STATUS); - if ((trans_status & HSI2C_MASTER_ST_MASK) == HSI2C_MASTER_ST_LOSE) { - i2c->state = -EAGAIN; - goto stop; - } } else if (int_status & HSI2C_INT_I2C) { trans_status = readl(i2c->regs + HSI2C_TRANS_STATUS); if (trans_status & HSI2C_NO_DEV_ACK) { @@ -544,6 +542,57 @@ static int exynos5_i2c_wait_bus_idle(struct exynos5_i2c *i2c) return -EBUSY; } +static void exynos5_i2c_bus_recover(struct exynos5_i2c *i2c) +{ + u32 val; + + val = readl(i2c->regs + HSI2C_CTL) | HSI2C_RXCHON; + writel(val, i2c->regs + HSI2C_CTL); + val = readl(i2c->regs + HSI2C_CONF) & ~HSI2C_AUTO_MODE; + writel(val, i2c->regs + HSI2C_CONF); + + /* + * Specification says master should send nine clock pulses. It can be + * emulated by sending manual read command (nine pulses for read eight + * bits + one pulse for NACK). + */ + writel(HSI2C_CMD_READ_DATA, i2c->regs + HSI2C_MANUAL_CMD); + exynos5_i2c_wait_bus_idle(i2c); + writel(HSI2C_CMD_SEND_STOP, i2c->regs + HSI2C_MANUAL_CMD); + exynos5_i2c_wait_bus_idle(i2c); + + val = readl(i2c->regs + HSI2C_CTL) & ~HSI2C_RXCHON; + writel(val, i2c->regs + HSI2C_CTL); + val = readl(i2c->regs + HSI2C_CONF) | HSI2C_AUTO_MODE; + writel(val, i2c->regs + HSI2C_CONF); +} + +static void exynos5_i2c_bus_check(struct exynos5_i2c *i2c) +{ + unsigned long timeout; + + if (i2c->variant->hw != HSI2C_EXYNOS7) + return; + + /* + * HSI2C_MASTER_ST_LOSE state in EXYNOS7 variant before transaction + * indicates that bus is stuck (SDA is low). In such case bus recovery + * can be performed. + */ + timeout = jiffies + msecs_to_jiffies(100); + for (;;) { + u32 st = readl(i2c->regs + HSI2C_TRANS_STATUS); + + if ((st & HSI2C_MASTER_ST_MASK) != HSI2C_MASTER_ST_LOSE) + return; + + if (time_is_before_jiffies(timeout)) + return; + + exynos5_i2c_bus_recover(i2c); + } +} + /* * exynos5_i2c_message_start: Configures the bus and starts the xfer * i2c: struct exynos5_i2c pointer for the current bus @@ -598,6 +647,8 @@ static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop) writel(fifo_ctl, i2c->regs + HSI2C_FIFO_CTL); writel(i2c_ctl, i2c->regs + HSI2C_CTL); + exynos5_i2c_bus_check(i2c); + /* * Enable interrupts before starting the transfer so that we don't * miss any INT_I2C interrupts.