From patchwork Wed Apr 17 20:31:47 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Hunter, Jon" X-Patchwork-Id: 2456441 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) by patchwork1.kernel.org (Postfix) with ESMTP id 739C83FD8C for ; Wed, 17 Apr 2013 20:33:36 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1USZ1x-0006tZ-NC; Wed, 17 Apr 2013 20:32:39 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1USZ1O-00068p-TP; Wed, 17 Apr 2013 20:32:02 +0000 Received: from bear.ext.ti.com ([192.94.94.41]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1USZ1L-00068V-Ps for linux-arm-kernel@lists.infradead.org; Wed, 17 Apr 2013 20:32:00 +0000 Received: from dflxv15.itg.ti.com ([128.247.5.124]) by bear.ext.ti.com (8.13.7/8.13.7) with ESMTP id r3HKVvx5009726; Wed, 17 Apr 2013 15:31:57 -0500 Received: from DLEE70.ent.ti.com (dlee70.ent.ti.com [157.170.170.113]) by dflxv15.itg.ti.com (8.14.3/8.13.8) with ESMTP id r3HKVvbn011552; Wed, 17 Apr 2013 15:31:57 -0500 Received: from dlelxv24.itg.ti.com (172.17.1.199) by DLEE70.ent.ti.com (157.170.170.113) with Microsoft SMTP Server id 14.2.342.3; Wed, 17 Apr 2013 15:31:57 -0500 Received: from legion.dal.design.ti.com (legion.dal.design.ti.com [128.247.22.53]) by dlelxv24.itg.ti.com (8.13.8/8.13.8) with ESMTP id r3HKVv00032043; Wed, 17 Apr 2013 15:31:57 -0500 Received: from localhost (h16-90.vpn.ti.com [172.24.16.90]) by legion.dal.design.ti.com (8.11.7p1+Sun/8.11.7) with ESMTP id r3HKVuV12611; Wed, 17 Apr 2013 15:31:56 -0500 (CDT) From: Jon Hunter To: Linus Walleij , Grant Likely , Kevin Hilman , Santosh Shilimkar Subject: [PATCH] gpio/omap: ensure gpio context is initialised Date: Wed, 17 Apr 2013 15:31:47 -0500 Message-ID: <1366230707-32681-1-git-send-email-jon-hunter@ti.com> X-Mailer: git-send-email 1.7.10.4 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130417_163159_941171_9B967830 X-CRM114-Status: GOOD ( 16.70 ) 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 [192.94.94.41 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender 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: Tony Lindgren , linux-omap , Jon Hunter , linux-arm X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Commit a2797be (gpio/omap: force restore if context loss is not detectable) broke gpio support for OMAP when booting with device-tree because a restore of the gpio context being performed without ever initialising the gpio context. In other words, the context restored was bad. This problem could also occur in the non device-tree case, however, it is much less likely because when booting without device-tree we can detect context loss via a platform specific API and so context restore is performed less often. Nevertheless we should ensure that the gpio context is initialised during the probe for gpio banks that could lose their state regardless of whether we are booting with device-tree or not. Reported-by: Tony Lindgren Signed-off-by: Jon Hunter Tested-by: Tony Lindgren --- drivers/gpio/gpio-omap.c | 53 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 0557529..0ba5cb9 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -70,6 +70,7 @@ struct gpio_bank { bool is_mpuio; bool dbck_flag; bool loses_context; + bool context_valid; int stride; u32 width; int context_loss_count; @@ -1085,6 +1086,7 @@ static void omap_gpio_chip_init(struct gpio_bank *bank) } static const struct of_device_id omap_gpio_match[]; +static void omap_gpio_init_context(struct gpio_bank *p); static int omap_gpio_probe(struct platform_device *pdev) { @@ -1179,8 +1181,10 @@ static int omap_gpio_probe(struct platform_device *pdev) omap_gpio_chip_init(bank); omap_gpio_show_rev(bank); - if (bank->loses_context) + if (bank->loses_context) { bank->get_context_loss_count = pdata->get_context_loss_count; + omap_gpio_init_context(bank); + } pm_runtime_put(bank->dev); @@ -1269,6 +1273,14 @@ static int omap_gpio_runtime_resume(struct device *dev) int c; spin_lock_irqsave(&bank->lock, flags); + + /* + * On the first resume during the probe, the context has not + * been initialised and so if the context is not valid return. + */ + if (!bank->context_valid) + goto done; + _gpio_dbck_enable(bank); /* @@ -1287,19 +1299,15 @@ static int omap_gpio_runtime_resume(struct device *dev) omap_gpio_restore_context(bank); } else { c = bank->get_context_loss_count(bank->dev); - if (c != bank->context_loss_count) { + if (c != bank->context_loss_count) omap_gpio_restore_context(bank); - } else { - spin_unlock_irqrestore(&bank->lock, flags); - return 0; - } + else + goto done; } } - if (!bank->workaround_enabled) { - spin_unlock_irqrestore(&bank->lock, flags); - return 0; - } + if (!bank->workaround_enabled) + goto done; l = __raw_readl(bank->base + bank->regs->datain); @@ -1352,6 +1360,7 @@ static int omap_gpio_runtime_resume(struct device *dev) } bank->workaround_enabled = false; +done: spin_unlock_irqrestore(&bank->lock, flags); return 0; @@ -1385,6 +1394,29 @@ void omap2_gpio_resume_after_idle(void) } #if defined(CONFIG_PM_RUNTIME) +static void omap_gpio_init_context(struct gpio_bank *p) +{ + struct omap_gpio_reg_offs *regs = p->regs; + void __iomem *base = p->base; + + p->context.ctrl = __raw_readl(base + regs->ctrl); + p->context.oe = __raw_readl(base + regs->direction); + p->context.wake_en = __raw_readl(base + regs->wkup_en); + p->context.leveldetect0 = __raw_readl(base + regs->leveldetect0); + p->context.leveldetect1 = __raw_readl(base + regs->leveldetect1); + p->context.risingdetect = __raw_readl(base + regs->risingdetect); + p->context.fallingdetect = __raw_readl(base + regs->fallingdetect); + p->context.irqenable1 = __raw_readl(base + regs->irqenable); + p->context.irqenable2 = __raw_readl(base + regs->irqenable2); + + if (regs->set_dataout && p->regs->clr_dataout) + p->context.dataout = __raw_readl(base + regs->set_dataout); + else + p->context.dataout = __raw_readl(base + regs->dataout); + + p->context_valid = true; +} + static void omap_gpio_restore_context(struct gpio_bank *bank) { __raw_writel(bank->context.wake_en, @@ -1422,6 +1454,7 @@ static void omap_gpio_restore_context(struct gpio_bank *bank) #else #define omap_gpio_runtime_suspend NULL #define omap_gpio_runtime_resume NULL +static void omap_gpio_init_context(struct gpio_bank *p) {} #endif static const struct dev_pm_ops gpio_pm_ops = {