From patchwork Thu May 28 13:03:37 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vaibhav Hiremath X-Patchwork-Id: 49106 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-la0-f72.google.com (mail-la0-f72.google.com [209.85.215.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 4BF75202A3 for ; Thu, 28 May 2015 13:06:53 +0000 (UTC) Received: by lani11 with SMTP id i11sf10967463lan.3 for ; Thu, 28 May 2015 06:06:52 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:sender:precedence:list-id :x-original-sender:x-original-authentication-results:mailing-list :list-post:list-help:list-archive:list-unsubscribe; bh=gRq4Kgx7XOx4ggmmadXUmN3b7xEGyhCRh50MvqSXSM8=; b=DzL05u1YN9ZQ1j3E070GYgJjhsevR2C5VnQ7DmpxcK9ivJm+sUjPD42KkPRF/yZ1QW IhGOmleXXTda1NKJBp+Sv3ah26aRCyMRrUhnSSFPfiheOjfOenH/a4z5qLK0ow1/MBRe L0rEU47JthDcgyJMuIP5BG0e/JdHMH9yAcRd/Ubai8VQdttYJDWc0kHZE9OCGBt6An/v kgg63Th+zlisCIbLS+ef67sGWMFyTbT1JqSW9IMqZHutKI/Jvkd5In555XDLXSQsym7+ v4r6ftU10rzpaDWvay0bXfm1/71OO5MoXalAyQbcBUTT6dyugX08PqF53lOGblhKlfZo PTJw== X-Gm-Message-State: ALoCoQmOXpbaucnH4LlRg9GogTT2hw6q4EaA/wVYOEEJr/ULe/HdPmQ2m/+K7opnTx3sfuye3fno X-Received: by 10.152.2.169 with SMTP id 9mr2628373lav.1.1432818412343; Thu, 28 May 2015 06:06:52 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.204.168 with SMTP id kz8ls156426lac.105.gmail; Thu, 28 May 2015 06:06:52 -0700 (PDT) X-Received: by 10.152.21.136 with SMTP id v8mr2697980lae.19.1432818412194; Thu, 28 May 2015 06:06:52 -0700 (PDT) Received: from mail-la0-f47.google.com (mail-la0-f47.google.com. [209.85.215.47]) by mx.google.com with ESMTPS id j1si1927082lbp.23.2015.05.28.06.06.52 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 28 May 2015 06:06:52 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.47 as permitted sender) client-ip=209.85.215.47; Received: by laat2 with SMTP id t2so31239690laa.1 for ; Thu, 28 May 2015 06:06:52 -0700 (PDT) X-Received: by 10.112.234.200 with SMTP id ug8mr2628531lbc.117.1432818411958; Thu, 28 May 2015 06:06:51 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.108.230 with SMTP id hn6csp1144415lbb; Thu, 28 May 2015 06:06:50 -0700 (PDT) X-Received: by 10.70.128.34 with SMTP id nl2mr5356175pdb.43.1432818409580; Thu, 28 May 2015 06:06:49 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id em5si3485083pbb.256.2015.05.28.06.06.48; Thu, 28 May 2015 06:06:49 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-i2c-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753675AbbE1NGq (ORCPT + 1 other); Thu, 28 May 2015 09:06:46 -0400 Received: from mail-pd0-f177.google.com ([209.85.192.177]:36775 "EHLO mail-pd0-f177.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753221AbbE1NGp (ORCPT ); Thu, 28 May 2015 09:06:45 -0400 Received: by pdfh10 with SMTP id h10so41417429pdf.3 for ; Thu, 28 May 2015 06:06:45 -0700 (PDT) X-Received: by 10.68.232.10 with SMTP id tk10mr5316573pbc.106.1432818404881; Thu, 28 May 2015 06:06:44 -0700 (PDT) Received: from localhost.localdomain ([202.62.77.106]) by mx.google.com with ESMTPSA id dc5sm2392557pbc.53.2015.05.28.06.06.41 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 28 May 2015 06:06:43 -0700 (PDT) From: Vaibhav Hiremath To: linux-i2c@vger.kernel.org Cc: Wolfram Sang , linux-arm-kernel@lists.infradead.org, Rob Herring , Leilei Shang , Vaibhav Hiremath Subject: [PATCH 05/12] i2c: pxa: Add bus reset functionality Date: Thu, 28 May 2015 18:33:37 +0530 Message-Id: <1432818224-17070-6-git-send-email-vaibhav.hiremath@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1432818224-17070-1-git-send-email-vaibhav.hiremath@linaro.org> References: <1432818224-17070-1-git-send-email-vaibhav.hiremath@linaro.org> Sender: linux-i2c-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-i2c@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: vaibhav.hiremath@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.47 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , From: Rob Herring Since there is some problematic i2c slave devices on some platforms such as dkb (sometimes), it will drop down sda and make i2c bus hang, at that time, it need to config scl/sda into gpio to simulate "stop" sequence to recover i2c bus, so add this interface. Signed-off-by: Leilei Shang Signed-off-by: Rob Herring [vaibhav.hiremath@linaro.org: Updated Changelog] Signed-off-by: Vaibhav Hiremath Signed-off-by: Vaibhav Hiremath --- drivers/i2c/busses/i2c-pxa.c | 90 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 8ca5552..eb09071 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include @@ -177,6 +179,9 @@ struct pxa_i2c { bool highmode_enter; unsigned int ilcr; unsigned int iwcr; + struct pinctrl *pinctrl; + struct pinctrl_state *pin_i2c; + struct pinctrl_state *pin_gpio; }; #define _IBMR(i2c) ((i2c)->reg_ibmr) @@ -269,6 +274,62 @@ static void i2c_pxa_show_state(struct pxa_i2c *i2c, int lno, const char *fname) #define show_state(i2c) i2c_pxa_show_state(i2c, __LINE__, __func__) +static void i2c_bus_reset(struct pxa_i2c *i2c) +{ + int ret, ccnt, pins_scl, pins_sda; + struct device *dev = i2c->adap.dev.parent; + struct device_node *np = dev->of_node; + + if (!i2c->pinctrl) { + dev_warn(dev, "could not do i2c bus reset\n"); + return; + } + + ret = pinctrl_select_state(i2c->pinctrl, i2c->pin_gpio); + if (ret) { + dev_err(dev, "could not set gpio pins\n"); + return; + } + + pins_scl = of_get_named_gpio(np, "i2c-gpio", 0); + if (!gpio_is_valid(pins_scl)) { + dev_err(dev, "i2c scl gpio not set\n"); + goto err_out; + } + pins_sda = of_get_named_gpio(np, "i2c-gpio", 1); + if (!gpio_is_valid(pins_sda)) { + dev_err(dev, "i2c sda gpio not set\n"); + goto err_out; + } + + gpio_request(pins_scl, NULL); + gpio_request(pins_sda, NULL); + + gpio_direction_input(pins_sda); + for (ccnt = 20; ccnt; ccnt--) { + gpio_direction_output(pins_scl, ccnt & 0x01); + udelay(5); + } + gpio_direction_output(pins_scl, 0); + udelay(5); + gpio_direction_output(pins_sda, 0); + udelay(5); + /* stop signal */ + gpio_direction_output(pins_scl, 1); + udelay(5); + gpio_direction_output(pins_sda, 1); + udelay(5); + + gpio_free(pins_scl); + gpio_free(pins_sda); + +err_out: + ret = pinctrl_select_state(i2c->pinctrl, i2c->pin_i2c); + if (ret) + dev_err(dev, "could not set default(i2c) pins\n"); + return; +} + static void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why) { unsigned int i; @@ -281,6 +342,11 @@ static void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why) for (i = 0; i < i2c->irqlogidx; i++) printk("[%08x:%08x] ", i2c->isrlog[i], i2c->icrlog[i]); printk("\n"); + if (strcmp(why, "exhausted retries") != 0) { + i2c_bus_reset(i2c); + /* reset i2c contorler when it's fail */ + i2c_pxa_reset(i2c); + } } #else /* ifdef DEBUG */ @@ -1301,6 +1367,30 @@ static int i2c_pxa_probe(struct platform_device *dev) platform_set_drvdata(dev, i2c); + i2c->pinctrl = devm_pinctrl_get(&dev->dev); + if (IS_ERR(i2c->pinctrl)) { + i2c->pinctrl = NULL; + dev_warn(&dev->dev, "could not get pinctrl\n"); + } else { + i2c->pin_i2c = pinctrl_lookup_state(i2c->pinctrl, "default"); + if (IS_ERR(i2c->pin_i2c)) { + dev_err(&dev->dev, "could not get default(i2c) pinstate\n"); + ret = IS_ERR(i2c->pin_i2c); + } + + i2c->pin_gpio = pinctrl_lookup_state(i2c->pinctrl, "gpio"); + if (IS_ERR(i2c->pin_gpio)) { + dev_err(&dev->dev, "could not get gpio pinstate\n"); + ret = IS_ERR(i2c->pin_gpio); + } + + if (ret) { + i2c->pin_i2c = NULL; + i2c->pin_gpio = NULL; + i2c->pinctrl = NULL; + ret = 0; + } + } #ifdef CONFIG_I2C_PXA_SLAVE printk(KERN_INFO "I2C: %s: PXA I2C adapter, slave address %d\n", dev_name(&i2c->adap.dev), i2c->slave_addr);