Commit 6989ea48 authored by Andy Shevchenko's avatar Andy Shevchenko Committed by Linus Walleij

pinctrl: intel: Save and restore pins in "direct IRQ" mode

The firmware on some systems may configure GPIO pins to be
an interrupt source in so called "direct IRQ" mode. In such
cases the GPIO controller driver has no idea if those pins
are being used or not. At the same time, there is a known bug
in the firmwares that don't restore the pin settings correctly
after suspend, i.e. by an unknown reason the Rx value becomes
inverted.

Hence, let's save and restore the pins that are configured
as GPIOs in the input mode with GPIROUTIOXAPIC bit set.

Cc: stable@vger.kernel.org
Reported-and-tested-by: default avatarDale Smith <dalepsmith@gmail.com>
Reported-and-tested-by: default avatarJohn Harris <jmharris@gmail.com>
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=214749Signed-off-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Acked-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
Link: https://lore.kernel.org/r/20221124222926.72326-1-andriy.shevchenko@linux.intel.comSigned-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent 11780e37
...@@ -436,9 +436,14 @@ static void __intel_gpio_set_direction(void __iomem *padcfg0, bool input) ...@@ -436,9 +436,14 @@ static void __intel_gpio_set_direction(void __iomem *padcfg0, bool input)
writel(value, padcfg0); writel(value, padcfg0);
} }
static int __intel_gpio_get_gpio_mode(u32 value)
{
return (value & PADCFG0_PMODE_MASK) >> PADCFG0_PMODE_SHIFT;
}
static int intel_gpio_get_gpio_mode(void __iomem *padcfg0) static int intel_gpio_get_gpio_mode(void __iomem *padcfg0)
{ {
return (readl(padcfg0) & PADCFG0_PMODE_MASK) >> PADCFG0_PMODE_SHIFT; return __intel_gpio_get_gpio_mode(readl(padcfg0));
} }
static void intel_gpio_set_gpio_mode(void __iomem *padcfg0) static void intel_gpio_set_gpio_mode(void __iomem *padcfg0)
...@@ -1674,6 +1679,7 @@ EXPORT_SYMBOL_GPL(intel_pinctrl_get_soc_data); ...@@ -1674,6 +1679,7 @@ EXPORT_SYMBOL_GPL(intel_pinctrl_get_soc_data);
static bool intel_pinctrl_should_save(struct intel_pinctrl *pctrl, unsigned int pin) static bool intel_pinctrl_should_save(struct intel_pinctrl *pctrl, unsigned int pin)
{ {
const struct pin_desc *pd = pin_desc_get(pctrl->pctldev, pin); const struct pin_desc *pd = pin_desc_get(pctrl->pctldev, pin);
u32 value;
if (!pd || !intel_pad_usable(pctrl, pin)) if (!pd || !intel_pad_usable(pctrl, pin))
return false; return false;
...@@ -1688,6 +1694,25 @@ static bool intel_pinctrl_should_save(struct intel_pinctrl *pctrl, unsigned int ...@@ -1688,6 +1694,25 @@ static bool intel_pinctrl_should_save(struct intel_pinctrl *pctrl, unsigned int
gpiochip_line_is_irq(&pctrl->chip, intel_pin_to_gpio(pctrl, pin))) gpiochip_line_is_irq(&pctrl->chip, intel_pin_to_gpio(pctrl, pin)))
return true; return true;
/*
* The firmware on some systems may configure GPIO pins to be
* an interrupt source in so called "direct IRQ" mode. In such
* cases the GPIO controller driver has no idea if those pins
* are being used or not. At the same time, there is a known bug
* in the firmwares that don't restore the pin settings correctly
* after suspend, i.e. by an unknown reason the Rx value becomes
* inverted.
*
* Hence, let's save and restore the pins that are configured
* as GPIOs in the input mode with GPIROUTIOXAPIC bit set.
*
* See https://bugzilla.kernel.org/show_bug.cgi?id=214749.
*/
value = readl(intel_get_padcfg(pctrl, pin, PADCFG0));
if ((value & PADCFG0_GPIROUTIOXAPIC) && (value & PADCFG0_GPIOTXDIS) &&
(__intel_gpio_get_gpio_mode(value) == PADCFG0_PMODE_GPIO))
return true;
return false; return false;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment