[PATCH v1 5/5] gpio: pca953x: Override GpioInt() pin for Intel Galileo Gen 2

Andy Shevchenko
2020-05-20T21:19:26Z

ACPI table on Intel Galileo Gen 2 has wrong pin number for IRQ resource
of one of the I²C GPIO expanders. ACPI GPIO library provides a special
quirk which we may use in this case. With help of it, override GpioInt()
pin for the affected platform.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
drivers/gpio/gpio-pca953x.c | 44 +++++++++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)

diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index 1fca8dd7824f..2014563309be 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -10,6 +10,7 @@

#include <linux/acpi.h>
#include <linux/bitmap.h>
+#include <linux/dmi.h>
#include <linux/gpio/driver.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
@@ -113,6 +114,39 @@ static const struct acpi_device_id pca953x_acpi_ids[] = {
};
MODULE_DEVICE_TABLE(acpi, pca953x_acpi_ids);

+#ifdef CONFIG_GPIO_PCA953X_IRQ
+static const struct acpi_gpio_params pca953x_interrupt_gpios = { 0, 0, true };
+
+static const struct acpi_gpio_mapping pca953x_acpi_interrupt_gpios[] = {
+ { "interrupt-gpios", &pca953x_interrupt_gpios, 1, ACPI_GPIO_QUIRK_FORCE_PIN, 1 },
+ { }
+};
+
+static int pca953x_acpi_interrupt_get_irq(struct device *dev)
+{
+ struct gpio_desc *desc;
+
+ if (devm_acpi_dev_add_driver_gpios(dev, pca953x_acpi_interrupt_gpios))
+ dev_warn(dev, "can't add GPIO ACPI mapping\n");
+
+ desc = devm_gpiod_get(dev, "interrupt", GPIOD_IN);
+ if (IS_ERR(desc))
+ return PTR_ERR(desc);
+
+ return gpiod_to_irq(desc);
+}
+
+static const struct dmi_system_id pca953x_dmi_acpi_interrupt_info[] = {
+ {
+ .ident = "Intel Galileo Gen 2",
+ .matches = {
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "GalileoGen2"),
+ },
+ },
+ {}
+};
+#endif
+
#define MAX_BANK 5
#define BANK_SZ 8
#define MAX_LINE (MAX_BANK * BANK_SZ)
@@ -750,8 +784,18 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, int irq_base)
struct irq_chip *irq_chip = &chip->irq_chip;
DECLARE_BITMAP(reg_direction, MAX_LINE);
DECLARE_BITMAP(irq_stat, MAX_LINE);
+ const struct dmi_system_id *id;
int ret;

+ id = dmi_first_match(pca953x_dmi_acpi_interrupt_info);
+ if (id) {
+ dev_info(&client->dev, "Applying ACPI interrupt quirk\n");
+
+ ret = pca953x_acpi_interrupt_get_irq(&client->dev);
+ if (ret > 0)
+ client->irq = ret;
+ }
+
if (!client->irq)
return 0;

--
2.26.2