diff mbox series

[resend,2/3] gpiolib: acpi: Rename honor_wakeup option to ignore_wake, add extra quirk

Message ID 20200225102753.8351-3-hdegoede@redhat.com
State New
Headers show
Series None | expand

Commit Message

Hans de Goede Feb. 25, 2020, 10:27 a.m. UTC
Commit aa23ca3d98f7 ("gpiolib: acpi: Add honor_wakeup module-option +
quirk mechanism") was added to deal with spurious wakeups on one specific
model of the HP x2 10 series. In the mean time I have learned that there
are at least 3 variants of the HP x2 10 models:

Bay Trail SoC + AXP288 PMIC
Cherry Trail SoC + AXP288 PMIC
Cherry Trail SoC + TI PMIC

It turns out that the need to ignore wakeup on *all* ACPI GPIO event
handlers is unique to the Cherry Trail SoC + TI PMIC variant for which
the first quirk was added.

The 2 variants with the AXP288 PMIC only need to have wakeup disabled on
the embedded-controller event handler. We want to e.g. keep wakeup on the
event handler connected to the GPIO for the lid open/closed sensor.

Since the honor_wakeup option was added to be able to ignore wake events,
the name was perhaps not the best, this commit renames it to ignore_wake,
this version of the option has te following possible values:

values >= 0: a pin number on which to ignore wakeups, the ACPI wake flag
will still be honored on all other pins
value -1: auto: check for DMI quirk, otherwise honor the flag on all pins
value -2: all:  ignore the flag on all pins
value -3: none: honor wakeups on all pins

Note that it is possible for an ACPI table to request events on the same
pin-number on multiple GPIO controllers, in that case if such a pin-number
is used as ignore_wake value then wakeups will be ignored for that pin on
all GPIO controllers.

The existing quirk for the Cherry Trail + TI PMIC models is changed to
IGNORE_WAKE_ALL, keeping the current behavior; and a new quirk is added
for the Bay Trail + AXP288 model, ignoring wakeups on the EC GPIO pin only.

Fixes: aa23ca3d98f7 ("gpiolib: acpi: Add honor_wakeup module-option + quirk mechanism")
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/gpio/gpiolib-acpi.c | 59 +++++++++++++++++++++++++++++--------
 1 file changed, 47 insertions(+), 12 deletions(-)
diff mbox series

Patch

diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index bc96f28d4807..83103efa5862 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -21,19 +21,27 @@ 
 #include "gpiolib.h"
 #include "gpiolib-acpi.h"
 
-#define QUIRK_NO_EDGE_EVENTS_ON_BOOT		0x01l
-#define QUIRK_NO_WAKEUP				0x02l
+#define QUIRK_IGNORE_WAKE_MASK			GENMASK(15, 0)
+#define QUIRK_IGNORE_WAKE_SET			BIT(16)
+#define QUIRK_NO_EDGE_EVENTS_ON_BOOT		BIT(17)
+
+#define QUIRK_IGNORE_WAKE(x) \
+	(((x) & QUIRK_IGNORE_WAKE_MASK) | QUIRK_IGNORE_WAKE_SET)
+
+#define IGNORE_WAKE_AUTO			-1
+#define IGNORE_WAKE_ALL				-2
+#define IGNORE_WAKE_NONE			-3
+
+static int ignore_wake = IGNORE_WAKE_AUTO;
+module_param(ignore_wake, int, 0444);
+MODULE_PARM_DESC(ignore_wake,
+	"Ignore ACPI wake flag: x=ignore-for-pin-x, -1=auto, -2=all, -3=none");
 
 static int run_edge_events_on_boot = -1;
 module_param(run_edge_events_on_boot, int, 0444);
 MODULE_PARM_DESC(run_edge_events_on_boot,
 		 "Run edge _AEI event-handlers at boot: 0=no, 1=yes, -1=auto");
 
-static int honor_wakeup = -1;
-module_param(honor_wakeup, int, 0444);
-MODULE_PARM_DESC(honor_wakeup,
-		 "Honor the ACPI wake-capable flag: 0=no, 1=yes, -1=auto");
-
 /**
  * struct acpi_gpio_event - ACPI GPIO event handler data
  *
@@ -214,6 +222,7 @@  static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares,
 	irq_handler_t handler = NULL;
 	struct gpio_desc *desc;
 	int ret, pin, irq;
+	bool honor_wakeup;
 
 	if (!acpi_gpio_get_irq_resource(ares, &agpio))
 		return AE_OK;
@@ -286,6 +295,17 @@  static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares,
 		}
 	}
 
+	switch (ignore_wake) {
+	case IGNORE_WAKE_ALL:
+		honor_wakeup = false;
+		break;
+	case IGNORE_WAKE_NONE:
+		honor_wakeup = true;
+		break;
+	default:
+		honor_wakeup = ignore_wake != pin;
+	}
+
 	event->handle = evt_handle;
 	event->handler = handler;
 	event->irq = irq;
@@ -1363,7 +1383,22 @@  static const struct dmi_system_id gpiolib_acpi_quirks[] = {
 			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "HP x2 Detachable 10-p0XX"),
 		},
-		.driver_data = (void *)QUIRK_NO_WAKEUP,
+		.driver_data = (void *)QUIRK_IGNORE_WAKE(IGNORE_WAKE_ALL),
+	},
+	{
+		/*
+		 * HP X2 10 models with Bay Trail SoC + AXP288 PMIC use an
+		 * external embedded-controller connected via I2C + an ACPI
+		 * GPIO event handler for pin 0x1c, causing spurious wakeups.
+		 * Unlike the Cherry Trail + TI PMIC models, we do want to
+		 * honor the ACPI wake flag on the other GPIOs.
+		 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"),
+			DMI_MATCH(DMI_BOARD_NAME, "815D"),
+		},
+		.driver_data = (void *)QUIRK_IGNORE_WAKE(0x1c),
 	},
 	{} /* Terminating entry */
 };
@@ -1384,11 +1419,11 @@  static int acpi_gpio_setup_params(void)
 			run_edge_events_on_boot = 1;
 	}
 
-	if (honor_wakeup < 0) {
-		if (quirks & QUIRK_NO_WAKEUP)
-			honor_wakeup = 0;
+	if (ignore_wake == IGNORE_WAKE_AUTO) {
+		if (quirks & QUIRK_IGNORE_WAKE_SET)
+			ignore_wake = (s16)(quirks & QUIRK_IGNORE_WAKE_MASK);
 		else
-			honor_wakeup = 1;
+			ignore_wake = IGNORE_WAKE_NONE;
 	}
 
 	return 0;