summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpio/gpiolib-acpi-core.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/drivers/gpio/gpiolib-acpi-core.c b/drivers/gpio/gpiolib-acpi-core.c
index fbd6945726bf..1a762a2988b7 100644
--- a/drivers/gpio/gpiolib-acpi-core.c
+++ b/drivers/gpio/gpiolib-acpi-core.c
@@ -229,12 +229,23 @@ static void acpi_gpiochip_request_irq(struct acpi_gpio_chip *acpi_gpio,
event->irq_requested = true;
- /* Make sure we trigger the initial state of edge-triggered IRQs */
+ /*
+ * Make sure we trigger the initial state of ActiveBoth IRQs.
+ *
+ * According to the Microsoft GPIO documentation, triggering GPIO
+ * interrupts marked as ActiveBoth during initialization is correct
+ * as long as the associated GPIO line is already "asserted"
+ * (logic level low). We should not trigger edge-based GPIO
+ * interrupts not marked as ActiveBoth.
+ *
+ * See: https://learn.microsoft.com/en-us/windows-hardware/drivers/bringup/general-purpose-i-o--gpio-
+ * Section: "GPIO controllers and ActiveBoth interrupts"
+ */
if (acpi_gpio_need_run_edge_events_on_boot() &&
- (event->irqflags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))) {
+ ((event->irqflags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) ==
+ (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))) {
value = gpiod_get_raw_value_cansleep(event->desc);
- if (((event->irqflags & IRQF_TRIGGER_RISING) && value == 1) ||
- ((event->irqflags & IRQF_TRIGGER_FALLING) && value == 0))
+ if (value == 0)
event->handler(event->irq, event);
}
}