From patchwork Wed Nov 9 11:22:31 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 692710 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3tDP0w3Kzwz9vDn for ; Wed, 9 Nov 2016 22:22:40 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753125AbcKILWi (ORCPT ); Wed, 9 Nov 2016 06:22:38 -0500 Received: from mga07.intel.com ([134.134.136.100]:29140 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752611AbcKILWf (ORCPT ); Wed, 9 Nov 2016 06:22:35 -0500 Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by orsmga105.jf.intel.com with ESMTP; 09 Nov 2016 03:22:34 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.31,614,1473145200"; d="scan'208";a="784324304" Received: from black.fi.intel.com ([10.237.72.28]) by FMSMGA003.fm.intel.com with ESMTP; 09 Nov 2016 03:22:32 -0800 Received: by black.fi.intel.com (Postfix, from userid 1001) id 79829354; Wed, 9 Nov 2016 13:22:31 +0200 (EET) From: Mika Westerberg To: Linus Walleij Cc: Jarkko Nikula , Heikki Krogerus , linux-gpio@vger.kernel.org, Mika Westerberg Subject: [PATCH] pinctrl: intel: Configure pin as GPIO input when used directly through irqchip Date: Wed, 9 Nov 2016 13:22:31 +0200 Message-Id: <20161109112231.122700-1-mika.westerberg@linux.intel.com> X-Mailer: git-send-email 2.9.3 Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org If a pin is used directly through irqchip without requesting it first as GPIO, it might be in wrong mode (for example input buffer disabled). This means the user may never get any interrupts. Fix this by configuring the pin as GPIO input when its type is first set in irq_set_type(). Reported-by: Jarkko Nikula Signed-off-by: Mika Westerberg Tested-by: Jarkko Nikula --- Since we probably need to do this for cherryview and baytrail pinctrl drivers as well, I'm thinking is this something that the GPIO core could do automatically? drivers/pinctrl/intel/pinctrl-intel.c | 46 +++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index 01443762e570..a1a5e2a77f9e 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -353,6 +353,23 @@ static int intel_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned function, return 0; } +/* Called with pctrl->lock held */ +static void intel_gpio_set_gpio_mode(struct intel_pinctrl *pctrl, + void __iomem *padcfg0) +{ + u32 value; + + /* Put the pad into GPIO mode */ + value = readl(padcfg0) & ~PADCFG0_PMODE_MASK; + /* Disable SCI/SMI/NMI generation */ + value &= ~(PADCFG0_GPIROUTIOXAPIC | PADCFG0_GPIROUTSCI); + value &= ~(PADCFG0_GPIROUTSMI | PADCFG0_GPIROUTNMI); + /* Disable TX buffer and enable RX (this will be input) */ + value &= ~PADCFG0_GPIORXDIS; + value |= PADCFG0_GPIOTXDIS; + writel(value, padcfg0); +} + static int intel_gpio_request_enable(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, unsigned pin) @@ -360,29 +377,26 @@ static int intel_gpio_request_enable(struct pinctrl_dev *pctldev, struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); void __iomem *padcfg0; unsigned long flags; - u32 value; + int ret = 0; raw_spin_lock_irqsave(&pctrl->lock, flags); if (!intel_pad_usable(pctrl, pin)) { - raw_spin_unlock_irqrestore(&pctrl->lock, flags); - return -EBUSY; + ret = -EBUSY; + goto out; } padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0); - /* Put the pad into GPIO mode */ - value = readl(padcfg0) & ~PADCFG0_PMODE_MASK; - /* Disable SCI/SMI/NMI generation */ - value &= ~(PADCFG0_GPIROUTIOXAPIC | PADCFG0_GPIROUTSCI); - value &= ~(PADCFG0_GPIROUTSMI | PADCFG0_GPIROUTNMI); - /* Disable TX buffer and enable RX (this will be input) */ - value &= ~PADCFG0_GPIORXDIS; - value |= PADCFG0_GPIOTXDIS; - writel(value, padcfg0); + if (!padcfg0) { + ret = -EINVAL; + goto out; + } + /* Set to GPIO input */ + intel_gpio_set_gpio_mode(pctrl, padcfg0); +out: raw_spin_unlock_irqrestore(&pctrl->lock, flags); - - return 0; + return ret; } static int intel_gpio_set_direction(struct pinctrl_dev *pctldev, @@ -762,8 +776,10 @@ static int intel_gpio_irq_type(struct irq_data *d, unsigned type) raw_spin_lock_irqsave(&pctrl->lock, flags); - value = readl(reg); + /* Make sure the pin is GPIO input */ + intel_gpio_set_gpio_mode(pctrl, reg); + value = readl(reg); value &= ~(PADCFG0_RXEVCFG_MASK | PADCFG0_RXINV); if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {