Skip to content

Commit c538b94

Browse files
westerilinusw
authored andcommitted
pinctrl: intel: Only restore pins that are used by the driver
Dell XPS 13 (and maybe some others) uses a GPIO (CPU_GP_1) during suspend to explicitly disable USB touchscreen interrupt. This is done to prevent situation where the lid is closed the touchscreen is left functional. The pinctrl driver (wrongly) assumes it owns all pins which are owned by host and not locked down. It is perfectly fine for BIOS to use those pins as it is also considered as host in this context. What happens is that when the lid of Dell XPS 13 is closed, the BIOS configures CPU_GP_1 low disabling the touchscreen interrupt. During resume we restore all host owned pins to the known state which includes CPU_GP_1 and this overwrites what the BIOS has programmed there causing the touchscreen to fail as no interrupts are reaching the CPU anymore. Fix this by restoring only those pins we know are explicitly requested by the kernel one way or other. Cc: stable@vger.kernel.org Link: https://bugzilla.kernel.org/show_bug.cgi?id=176361 Reported-by: AceLan Kao <acelan.kao@canonical.com> Tested-by: AceLan Kao <acelan.kao@canonical.com> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
1 parent a171bc5 commit c538b94

File tree

1 file changed

+23
-2
lines changed

1 file changed

+23
-2
lines changed

drivers/pinctrl/intel/pinctrl-intel.c

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <linux/pinctrl/pinconf.h>
2020
#include <linux/pinctrl/pinconf-generic.h>
2121

22+
#include "../core.h"
2223
#include "pinctrl-intel.h"
2324

2425
/* Offset from regs */
@@ -1056,6 +1057,26 @@ int intel_pinctrl_remove(struct platform_device *pdev)
10561057
EXPORT_SYMBOL_GPL(intel_pinctrl_remove);
10571058

10581059
#ifdef CONFIG_PM_SLEEP
1060+
static bool intel_pinctrl_should_save(struct intel_pinctrl *pctrl, unsigned pin)
1061+
{
1062+
const struct pin_desc *pd = pin_desc_get(pctrl->pctldev, pin);
1063+
1064+
if (!pd || !intel_pad_usable(pctrl, pin))
1065+
return false;
1066+
1067+
/*
1068+
* Only restore the pin if it is actually in use by the kernel (or
1069+
* by userspace). It is possible that some pins are used by the
1070+
* BIOS during resume and those are not always locked down so leave
1071+
* them alone.
1072+
*/
1073+
if (pd->mux_owner || pd->gpio_owner ||
1074+
gpiochip_line_is_irq(&pctrl->chip, pin))
1075+
return true;
1076+
1077+
return false;
1078+
}
1079+
10591080
int intel_pinctrl_suspend(struct device *dev)
10601081
{
10611082
struct platform_device *pdev = to_platform_device(dev);
@@ -1069,7 +1090,7 @@ int intel_pinctrl_suspend(struct device *dev)
10691090
const struct pinctrl_pin_desc *desc = &pctrl->soc->pins[i];
10701091
u32 val;
10711092

1072-
if (!intel_pad_usable(pctrl, desc->number))
1093+
if (!intel_pinctrl_should_save(pctrl, desc->number))
10731094
continue;
10741095

10751096
val = readl(intel_get_padcfg(pctrl, desc->number, PADCFG0));
@@ -1130,7 +1151,7 @@ int intel_pinctrl_resume(struct device *dev)
11301151
void __iomem *padcfg;
11311152
u32 val;
11321153

1133-
if (!intel_pad_usable(pctrl, desc->number))
1154+
if (!intel_pinctrl_should_save(pctrl, desc->number))
11341155
continue;
11351156

11361157
padcfg = intel_get_padcfg(pctrl, desc->number, PADCFG0);

0 commit comments

Comments
 (0)