summaryrefslogtreecommitdiff
path: root/drivers/gpio
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2019-08-27 22:28:35 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-09-19 09:08:03 +0200
commit8b09f44b80e6a42007bafa8725a2a816b9dff266 (patch)
tree3bd436a33c7ab474eb55349c9c18f118a70fdff2 /drivers/gpio
parent1f1303882e7c0b5ebd65d5ef3540fadc63d5ad4e (diff)
gpiolib: acpi: Add gpiolib_acpi_run_edge_events_on_boot option and blacklist
commit 61f7f7c8f978b1c0d80e43c83b7d110ca0496eb4 upstream. Another day; another DSDT bug we need to workaround... Since commit ca876c7483b6 ("gpiolib-acpi: make sure we trigger edge events at least once on boot") we call _AEI edge handlers at boot. In some rare cases this causes problems. One example of this is the Minix Neo Z83-4 mini PC, this device has a clear DSDT bug where it has some copy and pasted code for dealing with Micro USB-B connector host/device role switching, while the mini PC does not even have a micro-USB connector. This code, which should not be there, messes with the DDC data pin from the HDMI connector (switching it to GPIO mode) breaking HDMI support. To avoid problems like this, this commit adds a new gpiolib_acpi.run_edge_events_on_boot kernel commandline option, which allows disabling the running of _AEI edge event handlers at boot. The default value is -1/auto which uses a DMI based blacklist, the initial version of this blacklist contains the Neo Z83-4 fixing the HDMI breakage. Cc: stable@vger.kernel.org Cc: Daniel Drake <drake@endlessm.com> Cc: Ian W MORRISON <ianwmorrison@gmail.com> Reported-by: Ian W MORRISON <ianwmorrison@gmail.com> Suggested-by: Ian W MORRISON <ianwmorrison@gmail.com> Fixes: ca876c7483b6 ("gpiolib-acpi: make sure we trigger edge events at least once on boot") Signed-off-by: Hans de Goede <hdegoede@redhat.com> Link: https://lore.kernel.org/r/20190827202835.213456-1-hdegoede@redhat.com Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Tested-by: Ian W MORRISON <ianwmorrison@gmail.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/gpiolib-acpi.c42
1 files changed, 38 insertions, 4 deletions
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index 57d157e94bd6..715babaa886a 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -10,6 +10,7 @@
* published by the Free Software Foundation.
*/
+#include <linux/dmi.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
@@ -23,6 +24,11 @@
#include "gpiolib.h"
+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");
+
/**
* struct acpi_gpio_event - ACPI GPIO event handler data
*
@@ -231,10 +237,13 @@ 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 */
- value = gpiod_get_raw_value_cansleep(event->desc);
- if (((event->irqflags & IRQF_TRIGGER_RISING) && value == 1) ||
- ((event->irqflags & IRQF_TRIGGER_FALLING) && value == 0))
- event->handler(event->irq, event);
+ if (run_edge_events_on_boot &&
+ (event->irqflags & (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))
+ event->handler(event->irq, event);
+ }
}
static void acpi_gpiochip_request_irqs(struct acpi_gpio_chip *acpi_gpio)
@@ -1302,3 +1311,28 @@ static int acpi_gpio_handle_deferred_request_irqs(void)
}
/* We must use _sync so that this runs after the first deferred_probe run */
late_initcall_sync(acpi_gpio_handle_deferred_request_irqs);
+
+static const struct dmi_system_id run_edge_events_on_boot_blacklist[] = {
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "MINIX"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Z83-4"),
+ }
+ },
+ {} /* Terminating entry */
+};
+
+static int acpi_gpio_setup_params(void)
+{
+ if (run_edge_events_on_boot < 0) {
+ if (dmi_check_system(run_edge_events_on_boot_blacklist))
+ run_edge_events_on_boot = 0;
+ else
+ run_edge_events_on_boot = 1;
+ }
+
+ return 0;
+}
+
+/* Directly after dmi_setup() which runs as core_initcall() */
+postcore_initcall(acpi_gpio_setup_params);