Commit 4a3033ef authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'gpio-v5.5-3' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio

Pull GPIO fixes from Linus Walleij:
 "Here is a host of GPIO fixes for the v5.5 series. The ACPI fix is
  especially important, see summary below and in the commit for details:

   - Select GPIOLIB_IRQCHIP on the max77620 GPIO expander

   - Fix context restore in the Zynq driver

   - Create a new ACPI quirk handler for disabling wakeups on
     problematic hardware.

   - Fix a coding style issue on the mockup device"

* tag 'gpio-v5.5-3' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio:
  gpiolib: acpi: Add honor_wakeup module-option + quirk mechanism
  gpiolib: acpi: Turn dmi_system_id table into a generic quirk table
  gpio: zynq: Fix for bug in zynq_gpio_restore_context API
  gpio: max77620: Add missing dependency on GPIOLIB_IRQCHIP
  gpio: mockup: fix coding style
parents a6a55b52 aa23ca3d
...@@ -1148,6 +1148,7 @@ config GPIO_MADERA ...@@ -1148,6 +1148,7 @@ config GPIO_MADERA
config GPIO_MAX77620 config GPIO_MAX77620
tristate "GPIO support for PMIC MAX77620 and MAX20024" tristate "GPIO support for PMIC MAX77620 and MAX20024"
depends on MFD_MAX77620 depends on MFD_MAX77620
select GPIOLIB_IRQCHIP
help help
GPIO driver for MAX77620 and MAX20024 PMIC from Maxim Semiconductor. GPIO driver for MAX77620 and MAX20024 PMIC from Maxim Semiconductor.
MAX77620 PMIC has 8 pins that can be configured as GPIOs. The MAX77620 PMIC has 8 pins that can be configured as GPIOs. The
......
...@@ -156,7 +156,7 @@ static int gpio_mockup_apply_pull(struct gpio_mockup_chip *chip, ...@@ -156,7 +156,7 @@ static int gpio_mockup_apply_pull(struct gpio_mockup_chip *chip,
mutex_lock(&chip->lock); mutex_lock(&chip->lock);
if (test_bit(FLAG_REQUESTED, &desc->flags) && if (test_bit(FLAG_REQUESTED, &desc->flags) &&
!test_bit(FLAG_IS_OUT, &desc->flags)) { !test_bit(FLAG_IS_OUT, &desc->flags)) {
curr = __gpio_mockup_get(chip, offset); curr = __gpio_mockup_get(chip, offset);
if (curr == value) if (curr == value)
goto out; goto out;
...@@ -165,7 +165,7 @@ static int gpio_mockup_apply_pull(struct gpio_mockup_chip *chip, ...@@ -165,7 +165,7 @@ static int gpio_mockup_apply_pull(struct gpio_mockup_chip *chip,
irq_type = irq_get_trigger_type(irq); irq_type = irq_get_trigger_type(irq);
if ((value == 1 && (irq_type & IRQ_TYPE_EDGE_RISING)) || if ((value == 1 && (irq_type & IRQ_TYPE_EDGE_RISING)) ||
(value == 0 && (irq_type & IRQ_TYPE_EDGE_FALLING))) (value == 0 && (irq_type & IRQ_TYPE_EDGE_FALLING)))
irq_sim_fire(sim, offset); irq_sim_fire(sim, offset);
} }
......
...@@ -684,6 +684,8 @@ static void zynq_gpio_restore_context(struct zynq_gpio *gpio) ...@@ -684,6 +684,8 @@ static void zynq_gpio_restore_context(struct zynq_gpio *gpio)
unsigned int bank_num; unsigned int bank_num;
for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) { for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) {
writel_relaxed(ZYNQ_GPIO_IXR_DISABLE_ALL, gpio->base_addr +
ZYNQ_GPIO_INTDIS_OFFSET(bank_num));
writel_relaxed(gpio->context.datalsw[bank_num], writel_relaxed(gpio->context.datalsw[bank_num],
gpio->base_addr + gpio->base_addr +
ZYNQ_GPIO_DATA_LSW_OFFSET(bank_num)); ZYNQ_GPIO_DATA_LSW_OFFSET(bank_num));
...@@ -693,9 +695,6 @@ static void zynq_gpio_restore_context(struct zynq_gpio *gpio) ...@@ -693,9 +695,6 @@ static void zynq_gpio_restore_context(struct zynq_gpio *gpio)
writel_relaxed(gpio->context.dirm[bank_num], writel_relaxed(gpio->context.dirm[bank_num],
gpio->base_addr + gpio->base_addr +
ZYNQ_GPIO_DIRM_OFFSET(bank_num)); ZYNQ_GPIO_DIRM_OFFSET(bank_num));
writel_relaxed(gpio->context.int_en[bank_num],
gpio->base_addr +
ZYNQ_GPIO_INTEN_OFFSET(bank_num));
writel_relaxed(gpio->context.int_type[bank_num], writel_relaxed(gpio->context.int_type[bank_num],
gpio->base_addr + gpio->base_addr +
ZYNQ_GPIO_INTTYPE_OFFSET(bank_num)); ZYNQ_GPIO_INTTYPE_OFFSET(bank_num));
...@@ -705,6 +704,9 @@ static void zynq_gpio_restore_context(struct zynq_gpio *gpio) ...@@ -705,6 +704,9 @@ static void zynq_gpio_restore_context(struct zynq_gpio *gpio)
writel_relaxed(gpio->context.int_any[bank_num], writel_relaxed(gpio->context.int_any[bank_num],
gpio->base_addr + gpio->base_addr +
ZYNQ_GPIO_INTANY_OFFSET(bank_num)); ZYNQ_GPIO_INTANY_OFFSET(bank_num));
writel_relaxed(~(gpio->context.int_en[bank_num]),
gpio->base_addr +
ZYNQ_GPIO_INTEN_OFFSET(bank_num));
} }
} }
......
...@@ -21,11 +21,19 @@ ...@@ -21,11 +21,19 @@
#include "gpiolib.h" #include "gpiolib.h"
#include "gpiolib-acpi.h" #include "gpiolib-acpi.h"
#define QUIRK_NO_EDGE_EVENTS_ON_BOOT 0x01l
#define QUIRK_NO_WAKEUP 0x02l
static int run_edge_events_on_boot = -1; static int run_edge_events_on_boot = -1;
module_param(run_edge_events_on_boot, int, 0444); module_param(run_edge_events_on_boot, int, 0444);
MODULE_PARM_DESC(run_edge_events_on_boot, MODULE_PARM_DESC(run_edge_events_on_boot,
"Run edge _AEI event-handlers at boot: 0=no, 1=yes, -1=auto"); "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 * struct acpi_gpio_event - ACPI GPIO event handler data
* *
...@@ -281,7 +289,7 @@ static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares, ...@@ -281,7 +289,7 @@ static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares,
event->handle = evt_handle; event->handle = evt_handle;
event->handler = handler; event->handler = handler;
event->irq = irq; event->irq = irq;
event->irq_is_wake = agpio->wake_capable == ACPI_WAKE_CAPABLE; event->irq_is_wake = honor_wakeup && agpio->wake_capable == ACPI_WAKE_CAPABLE;
event->pin = pin; event->pin = pin;
event->desc = desc; event->desc = desc;
...@@ -1309,7 +1317,7 @@ static int acpi_gpio_handle_deferred_request_irqs(void) ...@@ -1309,7 +1317,7 @@ static int acpi_gpio_handle_deferred_request_irqs(void)
/* We must use _sync so that this runs after the first deferred_probe run */ /* We must use _sync so that this runs after the first deferred_probe run */
late_initcall_sync(acpi_gpio_handle_deferred_request_irqs); late_initcall_sync(acpi_gpio_handle_deferred_request_irqs);
static const struct dmi_system_id run_edge_events_on_boot_blacklist[] = { static const struct dmi_system_id gpiolib_acpi_quirks[] = {
{ {
/* /*
* The Minix Neo Z83-4 has a micro-USB-B id-pin handler for * The Minix Neo Z83-4 has a micro-USB-B id-pin handler for
...@@ -1319,7 +1327,8 @@ static const struct dmi_system_id run_edge_events_on_boot_blacklist[] = { ...@@ -1319,7 +1327,8 @@ static const struct dmi_system_id run_edge_events_on_boot_blacklist[] = {
.matches = { .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "MINIX"), DMI_MATCH(DMI_SYS_VENDOR, "MINIX"),
DMI_MATCH(DMI_PRODUCT_NAME, "Z83-4"), DMI_MATCH(DMI_PRODUCT_NAME, "Z83-4"),
} },
.driver_data = (void *)QUIRK_NO_EDGE_EVENTS_ON_BOOT,
}, },
{ {
/* /*
...@@ -1331,20 +1340,52 @@ static const struct dmi_system_id run_edge_events_on_boot_blacklist[] = { ...@@ -1331,20 +1340,52 @@ static const struct dmi_system_id run_edge_events_on_boot_blacklist[] = {
.matches = { .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Wortmann_AG"), DMI_MATCH(DMI_SYS_VENDOR, "Wortmann_AG"),
DMI_MATCH(DMI_PRODUCT_NAME, "TERRA_PAD_1061"), DMI_MATCH(DMI_PRODUCT_NAME, "TERRA_PAD_1061"),
} },
.driver_data = (void *)QUIRK_NO_EDGE_EVENTS_ON_BOOT,
},
{
/*
* Various HP X2 10 Cherry Trail models use an external
* embedded-controller connected via I2C + an ACPI GPIO
* event handler. The embedded controller generates various
* spurious wakeup events when suspended. So disable wakeup
* for its handler (it uses the only ACPI GPIO event handler).
* This breaks wakeup when opening the lid, the user needs
* to press the power-button to wakeup the system. The
* alternative is suspend simply not working, which is worse.
*/
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
DMI_MATCH(DMI_PRODUCT_NAME, "HP x2 Detachable 10-p0XX"),
},
.driver_data = (void *)QUIRK_NO_WAKEUP,
}, },
{} /* Terminating entry */ {} /* Terminating entry */
}; };
static int acpi_gpio_setup_params(void) static int acpi_gpio_setup_params(void)
{ {
const struct dmi_system_id *id;
long quirks = 0;
id = dmi_first_match(gpiolib_acpi_quirks);
if (id)
quirks = (long)id->driver_data;
if (run_edge_events_on_boot < 0) { if (run_edge_events_on_boot < 0) {
if (dmi_check_system(run_edge_events_on_boot_blacklist)) if (quirks & QUIRK_NO_EDGE_EVENTS_ON_BOOT)
run_edge_events_on_boot = 0; run_edge_events_on_boot = 0;
else else
run_edge_events_on_boot = 1; run_edge_events_on_boot = 1;
} }
if (honor_wakeup < 0) {
if (quirks & QUIRK_NO_WAKEUP)
honor_wakeup = 0;
else
honor_wakeup = 1;
}
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment