From patchwork Thu Nov 29 05:05:34 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naveen Krishna Chatradhi X-Patchwork-Id: 1820121 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork2.kernel.org (Postfix) with ESMTP id BF3C0DF24C for ; Thu, 29 Nov 2012 05:09:23 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TdwKi-0002iX-4E; Thu, 29 Nov 2012 05:06:44 +0000 Received: from mailout1.samsung.com ([203.254.224.24]) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TdwKO-0002ex-6S for linux-arm-kernel@lists.infradead.org; Thu, 29 Nov 2012 05:06:26 +0000 Received: from epcpsbgm2.samsung.com (epcpsbgm2 [203.254.230.27]) by mailout1.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0ME800GGHGUNFPK0@mailout1.samsung.com> for linux-arm-kernel@lists.infradead.org; Thu, 29 Nov 2012 14:06:23 +0900 (KST) Received: from epcpsbgm2.samsung.com ( [172.20.52.122]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id CB.67.12699.F4DE6B05; Thu, 29 Nov 2012 14:06:23 +0900 (KST) X-AuditID: cbfee61b-b7f616d00000319b-ce-50b6ed4f808b Received: from epmmp1.local.host ( [203.254.227.16]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id 4B.67.12699.E4DE6B05; Thu, 29 Nov 2012 14:06:23 +0900 (KST) Received: from naveen-linux.sisodomain.com ([107.108.83.161]) by mmp1.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0ME800FMEGU2L570@mmp1.samsung.com> for linux-arm-kernel@lists.infradead.org; Thu, 29 Nov 2012 14:06:22 +0900 (KST) From: Naveen Krishna Chatradhi To: linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, linux-i2c@vger.kernel.org Subject: [PATCH 1/2] i2c-s3c2410: Leave the bus disabled unless it is in use Date: Thu, 29 Nov 2012 10:35:34 +0530 Message-id: <1354165536-18529-2-git-send-email-ch.naveen@samsung.com> X-Mailer: git-send-email 1.7.9.5 In-reply-to: <1354165536-18529-1-git-send-email-ch.naveen@samsung.com> References: <1354165536-18529-1-git-send-email-ch.naveen@samsung.com> DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrOLMWRmVeSWpSXmKPExsWyRsSkStf/7bYAg393eCw2Pb7G6sDosXlJ fQBjFJdNSmpOZllqkb5dAldG28FPrAW7FSoWvMpsYNwm1cXIySEhYCLxe9YGNghbTOLCvfVA NheHkMBSRolfL3qZYYrmPvnFDJFYxCix4thhVghnK5PEpVVXmECq2ATMJA4uWs0OYosIZEgs ebSBEcRmFiiX+PRoO1ADB4ewgI/E56uhICaLgKrExEdRIBW8Aq4SHxeeYwcJSwgoSMyZZANi cgq4SWy7GARSIQRU0X17D9g1LAICEt8mH2KBqJaV2HQA7DAJgetsEiv6nzBCXCwpcXDFDZYJ jMILGBlWMYqmFiQXFCel5xrpFSfmFpfmpesl5+duYgSG3ul/z6R3MK5qsDjEKMDBqMTDu9Fy W4AQa2JZcWXuIUYJDmYlEV7LaqAQb0piZVVqUX58UWlOavEhRh+gSyYyS4km5wPjIq8k3tDY xNzU2NTSyMjM1BSHsJI4b7NHSoCQQHpiSWp2ampBahHMOCYOTqkGxtzbq8Q5yo/m7omo2Trl EMf0+Or7CWc/bz0bIZLBNW/X048+PA3zgirvHPDcs0t/InevbPWZ6Z5Prq/SsTnp/Jn9od+6 t9ypLLfPCzy+dKttivXHC2wXOTuW1K8Xt2PfsfMpj2iyTEukUmGb7b/Mti07L/jE3Uy0zM+Z PjNscrP47dagourD95VYijMSDbWYi4oTAZlPF8ZqAgAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFmpjkeLIzCtJLcpLzFFi42I5/e+xgK7/220BBu/XMFtsenyN1YHRY/OS +gDGqAZGm4zUxJTUIoXUvOT8lMy8dFsl7+B453hTMwNDXUNLC3MlhbzE3FRbJRefAF23zByg qUoKZYk5pUChgMTiYiV9O0wTQkPcdC1gGiN0fUOC4HqMDNBAwhrGjLaDn1gLditULHiV2cC4 TaqLkZNDQsBEYu6TX8wQtpjEhXvr2boYuTiEBBYxSqw4dpgVwtnKJHFp1RUmkCo2ATOJg4tW s4PYIgIZEksebWAEsZkFyiU+PdoO1MDBISzgI/H5aiiIySKgKjHxURRIBa+Aq8THhefYQcIS AgoScybZgJicAm4S2y4GgVQIAVV0397DPIGRdwEjwypG0dSC5ILipPRcI73ixNzi0rx0veT8 3E2M4MB+Jr2DcVWDxSFGAQ5GJR7ejZbbAoRYE8uKK3MPMUpwMCuJ8FpWA4V4UxIrq1KL8uOL SnNSiw8x+gCdNJFZSjQ5Hxh1eSXxhsYm5qbGppYmFiZmljiElcR5mz1SAoQE0hNLUrNTUwtS i2DGMXFwSjUwdq9+ob585amwDQ0amp7bHBxni4kuOrmz9o/H5k1dTy9uaP4t/KDRWH5SVcW2 X8va5u/61FabtlN/d9rqL7fPlai7uD8M/ZFV33FtVlh579/J62RFCpZ+2TNhovrSmW/rZl+O 2yU6LVSrdf688LVse9LlW38tTWiI53g4f6LTyhOdN2IXFPnP2afEUpyRaKjFXFScCABdX/NH mQIAAA== X-CFilter-Loop: Reflected X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20121129_000624_882386_15435AF4 X-CRM114-Status: GOOD ( 21.14 ) X-Spam-Score: -7.6 (-------) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-7.6 points) pts rule name description ---- ---------------------- -------------------------------------------------- -5.0 RCVD_IN_DNSWL_HI RBL: Sender listed at http://www.dnswl.org/, high trust [203.254.224.24 listed in list.dnswl.org] -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.7 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: grundler@chromium.org, sjg@chromium.org, naveen@chromium.org, w.sang@pengutronix.de, linux-kernel@vger.kernel.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org From: Simon Glass There is a rather odd feature of the exynos i2c controller that if it is left enabled, it can lock itself up with the clk line held low. This makes the bus unusable. Unfortunately, the s3c24xx_i2c_set_master() function does not notice this, and reports a timeout. From then on the bus cannot be used until the AP is rebooted. The problem happens when any sort of interrupt occurs (e.g. due to a bus transition) when we are not in the middle of a transaction. We have seen many instances of this when U-Boot leaves the bus apparently happy, but Linux cannot access it. The current code is therefore pretty fragile. This fixes things by leaving the bus disabled unless we are actually in a transaction. We enable the bus at the start of the transaction and disable it at the end. That way we won't get interrupts and will not lock up the bus. It might be possible to clear pending interrupts on start-up, but this seems to be a more robust solution. We can't service interrupts when we are not in a transaction, and anyway would rather not lock up the bus while we try. Signed-off-by: Simon Glass Cc: Grant Grundler Signed-off-by: Naveen Krishna Chatradhi Acked-by: Kyungmin Park --- drivers/i2c/busses/i2c-s3c2410.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index e93e7d6..2fd346d 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -186,6 +186,31 @@ static inline void s3c24xx_i2c_enable_irq(struct s3c24xx_i2c *i2c) writel(tmp | S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON); } +/* + * Disable the bus so that we won't get any interrupts from now on, or try + * to drive any lines. This is the default state when we don't have + * anything to send/receive. + * + * If there is an event on the bus, or we have a pre-existing event at + * kernel boot time, we may not notice the event and the I2C controller + * will lock the bus with the I2C clock line low indefinitely. + */ +static inline void s3c24xx_i2c_disable_bus(struct s3c24xx_i2c *i2c) +{ + unsigned long tmp; + + /* Stop driving the I2C pins */ + tmp = readl(i2c->regs + S3C2410_IICSTAT); + tmp &= ~S3C2410_IICSTAT_TXRXEN; + writel(tmp, i2c->regs + S3C2410_IICSTAT); + + /* We don't expect any interrupts now, and don't want send acks */ + tmp = readl(i2c->regs + S3C2410_IICCON); + tmp &= ~(S3C2410_IICCON_IRQEN | S3C2410_IICCON_IRQPEND | + S3C2410_IICCON_ACKEN); + writel(tmp, i2c->regs + S3C2410_IICCON); +} + /* s3c24xx_i2c_message_start * @@ -646,7 +671,11 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, s3c24xx_i2c_wait_idle(i2c); + s3c24xx_i2c_disable_bus(i2c); + out: + i2c->state = STATE_IDLE; + return ret; } @@ -912,7 +941,6 @@ static void s3c24xx_i2c_dt_gpio_free(struct s3c24xx_i2c *i2c) static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) { - unsigned long iicon = S3C2410_IICCON_IRQEN | S3C2410_IICCON_ACKEN; struct s3c2410_platform_i2c *pdata; unsigned int freq; @@ -926,12 +954,12 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) dev_info(i2c->dev, "slave address 0x%02x\n", pdata->slave_addr); - writel(iicon, i2c->regs + S3C2410_IICCON); + writel(0, i2c->regs + S3C2410_IICCON); + writel(0, i2c->regs + S3C2410_IICSTAT); /* we need to work out the divisors for the clock... */ if (s3c24xx_i2c_clockrate(i2c, &freq) != 0) { - writel(0, i2c->regs + S3C2410_IICCON); dev_err(i2c->dev, "cannot meet bus frequency required\n"); return -EINVAL; } @@ -939,7 +967,8 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) /* todo - check that the i2c lines aren't being dragged anywhere */ dev_info(i2c->dev, "bus frequency set to %d KHz\n", freq); - dev_dbg(i2c->dev, "S3C2410_IICCON=0x%02lx\n", iicon); + dev_dbg(i2c->dev, "S3C2410_IICCON=0x%02x\n", + readl(i2c->regs + S3C2410_IICCON)); return 0; }