aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2016-10-10 09:39:31 -0400
committerLinus Walleij <linus.walleij@linaro.org>2016-10-18 08:38:16 -0400
commitc538b9436751a0be2e1246b48353bc23156bdbcc (patch)
tree02820b74cb7be356eb6603aa09d6243f6232baa5
parenta171bc51fa697021e1b2082d7e95c12a363bc0a9 (diff)
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>
-rw-r--r--drivers/pinctrl/intel/pinctrl-intel.c25
1 files changed, 23 insertions, 2 deletions
diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c
index 63387a40b973..01443762e570 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.c
+++ b/drivers/pinctrl/intel/pinctrl-intel.c
@@ -19,6 +19,7 @@
19#include <linux/pinctrl/pinconf.h> 19#include <linux/pinctrl/pinconf.h>
20#include <linux/pinctrl/pinconf-generic.h> 20#include <linux/pinctrl/pinconf-generic.h>
21 21
22#include "../core.h"
22#include "pinctrl-intel.h" 23#include "pinctrl-intel.h"
23 24
24/* Offset from regs */ 25/* Offset from regs */
@@ -1056,6 +1057,26 @@ int intel_pinctrl_remove(struct platform_device *pdev)
1056EXPORT_SYMBOL_GPL(intel_pinctrl_remove); 1057EXPORT_SYMBOL_GPL(intel_pinctrl_remove);
1057 1058
1058#ifdef CONFIG_PM_SLEEP 1059#ifdef CONFIG_PM_SLEEP
1060static 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
1059int intel_pinctrl_suspend(struct device *dev) 1080int intel_pinctrl_suspend(struct device *dev)
1060{ 1081{
1061 struct platform_device *pdev = to_platform_device(dev); 1082 struct platform_device *pdev = to_platform_device(dev);
@@ -1069,7 +1090,7 @@ int intel_pinctrl_suspend(struct device *dev)
1069 const struct pinctrl_pin_desc *desc = &pctrl->soc->pins[i]; 1090 const struct pinctrl_pin_desc *desc = &pctrl->soc->pins[i];
1070 u32 val; 1091 u32 val;
1071 1092
1072 if (!intel_pad_usable(pctrl, desc->number)) 1093 if (!intel_pinctrl_should_save(pctrl, desc->number))
1073 continue; 1094 continue;
1074 1095
1075 val = readl(intel_get_padcfg(pctrl, desc->number, PADCFG0)); 1096 val = readl(intel_get_padcfg(pctrl, desc->number, PADCFG0));
@@ -1130,7 +1151,7 @@ int intel_pinctrl_resume(struct device *dev)
1130 void __iomem *padcfg; 1151 void __iomem *padcfg;
1131 u32 val; 1152 u32 val;
1132 1153
1133 if (!intel_pad_usable(pctrl, desc->number)) 1154 if (!intel_pinctrl_should_save(pctrl, desc->number))
1134 continue; 1155 continue;
1135 1156
1136 padcfg = intel_get_padcfg(pctrl, desc->number, PADCFG0); 1157 padcfg = intel_get_padcfg(pctrl, desc->number, PADCFG0);