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 <jarkko.nikula@xxxxxxxxxxxxxxx> Signed-off-by: Mika Westerberg <mika.westerberg@xxxxxxxxxxxxxxx> --- 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) { -- 2.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-gpio" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html