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: 6498551 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id A26E7C0020 for ; Thu, 28 May 2015 13:13:35 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 7E8EB205D8 for ; Thu, 28 May 2015 13:13:34 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7BA38205C4 for ; Thu, 28 May 2015 13:13:33 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1YxxaC-000863-BY; Thu, 28 May 2015 13:10:48 +0000 Received: from mail-pd0-f179.google.com ([209.85.192.179]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1YxxWc-00051i-VO for linux-arm-kernel@lists.infradead.org; Thu, 28 May 2015 13:07:10 +0000 Received: by pdea3 with SMTP id a3so41359904pde.2 for ; Thu, 28 May 2015 06:06:45 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=xmR8sKfKrxiGuNa0nf6KB4W3wZ5Egaifkat6GCMOiqQ=; b=GTeIdbVE5l7lOtAylzgoaRJ/T3QtqmqL1IE7vvJ6j2NuWrW60Z6KFavXfvtzQRXEuX SzUoRlx7eWxZWhJQtN5fOlFkm60q0UGojAde9URDC5IFedT2nqLiRUQIVMmTeRG7Hwaf huj34DtAm9uVYigc+ynKga+Sb7wFhC/rXuwJ24tNx5y3vOZKfb/TIg0r5J2uZLlcP0rJ 02tBfKyqDhuFrgqvwsWw2AJLJaGCK0bOfwhdA0u/vGYQnCZu+BsaC4eGf1Ik5ol9EUHG fGOTMtkXAhUEW/aUHbLEcCV21Jud2Fx3mdw9wUw5VjH47BPUmZuwmQg4NfCflBtylTDY fzNQ== X-Gm-Message-State: ALoCoQlm7zZamgr5hvOg6m47VGfjL198n91vn9UP2NuVG9oXkdFTV6JO+AGBKR62+HwZkwdov/3x 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 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> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150528_060707_099287_FEBDF3C8 X-CRM114-Status: GOOD ( 15.42 ) X-Spam-Score: -1.8 (-) Cc: Rob Herring , Vaibhav Hiremath , Leilei Shang , linux-arm-kernel@lists.infradead.org, Wolfram Sang X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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);