diff mbox series

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

Message ID 20200520211916.25727-5-andriy.shevchenko@linux.intel.com
State New
Headers show
Series [v1,1/5] gpiolib: acpi: Introduce opaque data field for quirks | expand

Commit Message

Andy Shevchenko May 20, 2020, 9:19 p.m. UTC
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(+)

Comments

Mika Westerberg May 25, 2020, 9:20 a.m. UTC | #1
On Thu, May 21, 2020 at 12:19:16AM +0300, Andy Shevchenko wrote:
> 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"),
> +		},
> +	},
> +	{}

Since you do everything already in this driver, I think we can live
without adding ACPI_GPIO_QUIRK_FORCE_PIN to the core code at all.
Andy Shevchenko May 25, 2020, 9:31 a.m. UTC | #2
On Mon, May 25, 2020 at 12:20:28PM +0300, Mika Westerberg wrote:
> On Thu, May 21, 2020 at 12:19:16AM +0300, Andy Shevchenko wrote:
> > 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.

...

> > +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"),
> > +		},
> > +	},
> > +	{}
> 
> Since you do everything already in this driver, I think we can live
> without adding ACPI_GPIO_QUIRK_FORCE_PIN to the core code at all.

Hmm... I don't see how (perhaps need morning coffee). Any pointers?
Mika Westerberg May 25, 2020, 9:45 a.m. UTC | #3
On Mon, May 25, 2020 at 12:31:50PM +0300, Andy Shevchenko wrote:
> On Mon, May 25, 2020 at 12:20:28PM +0300, Mika Westerberg wrote:
> > On Thu, May 21, 2020 at 12:19:16AM +0300, Andy Shevchenko wrote:
> > > 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.
> 
> ...
> 
> > > +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"),
> > > +		},
> > > +	},
> > > +	{}
> > 
> > Since you do everything already in this driver, I think we can live
> > without adding ACPI_GPIO_QUIRK_FORCE_PIN to the core code at all.
> 
> Hmm... I don't see how (perhaps need morning coffee). Any pointers?

Well you already know all the details in this driver, no? Why you need
to pass any of this information to the core and the back to the same
driver?
Andy Shevchenko May 25, 2020, 10:13 a.m. UTC | #4
On Mon, May 25, 2020 at 12:45:53PM +0300, Mika Westerberg wrote:
> On Mon, May 25, 2020 at 12:31:50PM +0300, Andy Shevchenko wrote:
> > On Mon, May 25, 2020 at 12:20:28PM +0300, Mika Westerberg wrote:
> > > On Thu, May 21, 2020 at 12:19:16AM +0300, Andy Shevchenko wrote:
> > > > 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.

...

> > > > +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"),
> > > > +		},
> > > > +	},
> > > > +	{}

> > > Since you do everything already in this driver, I think we can live
> > > without adding ACPI_GPIO_QUIRK_FORCE_PIN to the core code at all.

> > Hmm... I don't see how (perhaps need morning coffee). Any pointers?

> Well you already know all the details in this driver, no? Why you need
> to pass any of this information to the core and the back to the same
> driver?

Due to parsing of ACPI tables. I don't want to copy'n'paste 25% of
gpiolib-acpi.c in here. I think provided solution is cleaner and (more)
flexible in terms of maintenance.
Mika Westerberg May 25, 2020, 11:05 a.m. UTC | #5
On Mon, May 25, 2020 at 01:13:35PM +0300, Andy Shevchenko wrote:
> Due to parsing of ACPI tables. I don't want to copy'n'paste 25% of
> gpiolib-acpi.c in here. I think provided solution is cleaner and (more)
> flexible in terms of maintenance.

Hmm, you seem to pass a hard-coded pin number (1) to the core that then
passes it back to the driver. Why you can't simple use that number here
directly? You don't need to parse anything. What I'm missing? :-)
Andy Shevchenko May 25, 2020, 11:35 a.m. UTC | #6
On Mon, May 25, 2020 at 02:05:56PM +0300, Mika Westerberg wrote:
> On Mon, May 25, 2020 at 01:13:35PM +0300, Andy Shevchenko wrote:
> > Due to parsing of ACPI tables. I don't want to copy'n'paste 25% of
> > gpiolib-acpi.c in here. I think provided solution is cleaner and (more)
> > flexible in terms of maintenance.
> 
> Hmm, you seem to pass a hard-coded pin number (1) to the core that then
> passes it back to the driver. Why you can't simple use that number here
> directly? You don't need to parse anything. What I'm missing? :-)

Okay, so, AFAIU you are proposing something like this:

1) find a GPIO controller by the ACPI path (somehow, I guess by finding a
   handle followed by physical device behind it); 2) somehow to request a
   pin from that device by number;
3) convert to IRQ and use.

Is it correct?
Andy Shevchenko May 25, 2020, 12:01 p.m. UTC | #7
On Mon, May 25, 2020 at 02:35:51PM +0300, Andy Shevchenko wrote:
> On Mon, May 25, 2020 at 02:05:56PM +0300, Mika Westerberg wrote:
> > On Mon, May 25, 2020 at 01:13:35PM +0300, Andy Shevchenko wrote:
> > > Due to parsing of ACPI tables. I don't want to copy'n'paste 25% of
> > > gpiolib-acpi.c in here. I think provided solution is cleaner and (more)
> > > flexible in terms of maintenance.
> > 
> > Hmm, you seem to pass a hard-coded pin number (1) to the core that then
> > passes it back to the driver. Why you can't simple use that number here
> > directly? You don't need to parse anything. What I'm missing? :-)
> 
> Okay, so, AFAIU you are proposing something like this:
> 
> 1) find a GPIO controller by the ACPI path (somehow, I guess by finding a
>    handle followed by physical device behind it); 2) somehow to request a
>    pin from that device by number;
> 3) convert to IRQ and use.
> 
> Is it correct?

Ah, and before all these, to detect properly the IO expander that actually has
that resource in the table (something like gpiod_count() or do we have better
approach to answer the question "does this device has a GpioInt() resource?").
Mika Westerberg May 25, 2020, 12:21 p.m. UTC | #8
On Mon, May 25, 2020 at 02:35:51PM +0300, Andy Shevchenko wrote:
> On Mon, May 25, 2020 at 02:05:56PM +0300, Mika Westerberg wrote:
> > On Mon, May 25, 2020 at 01:13:35PM +0300, Andy Shevchenko wrote:
> > > Due to parsing of ACPI tables. I don't want to copy'n'paste 25% of
> > > gpiolib-acpi.c in here. I think provided solution is cleaner and (more)
> > > flexible in terms of maintenance.
> > 
> > Hmm, you seem to pass a hard-coded pin number (1) to the core that then
> > passes it back to the driver. Why you can't simple use that number here
> > directly? You don't need to parse anything. What I'm missing? :-)
> 
> Okay, so, AFAIU you are proposing something like this:
> 
> 1) find a GPIO controller by the ACPI path (somehow, I guess by finding a
>    handle followed by physical device behind it); 2) somehow to request a
>    pin from that device by number;
> 3) convert to IRQ and use.
> 
> Is it correct?

Well, no. In the first patch you do this:

  pin = lookup->info.quirks_data;

and this essentially becomes 1 so you know the pin number upfront in the
driver. Why not simply get GPIO number 1 in the driver and use it as an
interrupt? You know already that this particular board with the matching
DMI identifier always uses the this number anyway.
Andy Shevchenko May 25, 2020, 1:01 p.m. UTC | #9
On Mon, May 25, 2020 at 03:21:36PM +0300, Mika Westerberg wrote:
> On Mon, May 25, 2020 at 02:35:51PM +0300, Andy Shevchenko wrote:
> > On Mon, May 25, 2020 at 02:05:56PM +0300, Mika Westerberg wrote:
> > > On Mon, May 25, 2020 at 01:13:35PM +0300, Andy Shevchenko wrote:
> > > > Due to parsing of ACPI tables. I don't want to copy'n'paste 25% of
> > > > gpiolib-acpi.c in here. I think provided solution is cleaner and (more)
> > > > flexible in terms of maintenance.
> > > 
> > > Hmm, you seem to pass a hard-coded pin number (1) to the core that then
> > > passes it back to the driver. Why you can't simple use that number here
> > > directly? You don't need to parse anything. What I'm missing? :-)
> > 
> > Okay, so, AFAIU you are proposing something like this:
> > 
> > 1) find a GPIO controller by the ACPI path (somehow, I guess by finding a
> >    handle followed by physical device behind it); 2) somehow to request a
> >    pin from that device by number;
> > 3) convert to IRQ and use.
> > 
> > Is it correct?
> 
> Well, no. In the first patch you do this:
> 
>   pin = lookup->info.quirks_data;
> 
> and this essentially becomes 1 so you know the pin number upfront in the
> driver. Why not simply get GPIO number 1 in the driver and use it as an
> interrupt? You know already that this particular board with the matching
> DMI identifier always uses the this number anyway.

But GPIO (relative!) number is not enough. We need to understand more, i.e.:
1) from which GPIO controller it comes from (okay, for this particular platform I know it);
2) which expander does have this resource (they all have same ACPI HID).

So, second one means to count GpioInt() resources (I don't remember if we have
helper for that, probably we can add one). For the first we need to get a GPIO
controller something (gpiochip?) And this first one I have no idea how we can
perform without talking to the core.

Basically, it may be done by reimplementing acpi_dev_gpio_irq_get(), followed
by acpi_get_gpiod_by_index(), followed by acpi_gpio_resource_lookup(), followed
by acpi_populate_gpio_lookup(), where at last this quirk should be applied.

It seems for me like an over duplicated solution.

I really don't understand how we can shortcut all these. What am I missing?
Mika Westerberg May 25, 2020, 1:47 p.m. UTC | #10
On Mon, May 25, 2020 at 04:01:08PM +0300, Andy Shevchenko wrote:
> On Mon, May 25, 2020 at 03:21:36PM +0300, Mika Westerberg wrote:
> > On Mon, May 25, 2020 at 02:35:51PM +0300, Andy Shevchenko wrote:
> > > On Mon, May 25, 2020 at 02:05:56PM +0300, Mika Westerberg wrote:
> > > > On Mon, May 25, 2020 at 01:13:35PM +0300, Andy Shevchenko wrote:
> > > > > Due to parsing of ACPI tables. I don't want to copy'n'paste 25% of
> > > > > gpiolib-acpi.c in here. I think provided solution is cleaner and (more)
> > > > > flexible in terms of maintenance.
> > > > 
> > > > Hmm, you seem to pass a hard-coded pin number (1) to the core that then
> > > > passes it back to the driver. Why you can't simple use that number here
> > > > directly? You don't need to parse anything. What I'm missing? :-)
> > > 
> > > Okay, so, AFAIU you are proposing something like this:
> > > 
> > > 1) find a GPIO controller by the ACPI path (somehow, I guess by finding a
> > >    handle followed by physical device behind it); 2) somehow to request a
> > >    pin from that device by number;
> > > 3) convert to IRQ and use.
> > > 
> > > Is it correct?
> > 
> > Well, no. In the first patch you do this:
> > 
> >   pin = lookup->info.quirks_data;
> > 
> > and this essentially becomes 1 so you know the pin number upfront in the
> > driver. Why not simply get GPIO number 1 in the driver and use it as an
> > interrupt? You know already that this particular board with the matching
> > DMI identifier always uses the this number anyway.
> 
> But GPIO (relative!) number is not enough. We need to understand more, i.e.:
> 1) from which GPIO controller it comes from (okay, for this particular platform I know it);
> 2) which expander does have this resource (they all have same ACPI HID).
> 
> So, second one means to count GpioInt() resources (I don't remember if we have
> helper for that, probably we can add one). For the first we need to get a GPIO
> controller something (gpiochip?) And this first one I have no idea how we can
> perform without talking to the core.
> 
> Basically, it may be done by reimplementing acpi_dev_gpio_irq_get(), followed
> by acpi_get_gpiod_by_index(), followed by acpi_gpio_resource_lookup(), followed
> by acpi_populate_gpio_lookup(), where at last this quirk should be applied.
> 
> It seems for me like an over duplicated solution.
> 
> I really don't understand how we can shortcut all these. What am I missing?

Why for example following would not work? If it is using global GPIO numbers
anyway.

static int pca953x_acpi_interrupt_get_irq(struct device *dev)
{
        struct gpio_desc *desc;                                                          
 
        desc = gpio_to_desc(1);
        if (!desc)
                return -ENODEV;

        return gpiod_to_irq(desc);
}
Andy Shevchenko May 25, 2020, 2:34 p.m. UTC | #11
On Mon, May 25, 2020 at 04:47:48PM +0300, Mika Westerberg wrote:
> On Mon, May 25, 2020 at 04:01:08PM +0300, Andy Shevchenko wrote:
> > On Mon, May 25, 2020 at 03:21:36PM +0300, Mika Westerberg wrote:
> > > On Mon, May 25, 2020 at 02:35:51PM +0300, Andy Shevchenko wrote:
> > > > On Mon, May 25, 2020 at 02:05:56PM +0300, Mika Westerberg wrote:
> > > > > On Mon, May 25, 2020 at 01:13:35PM +0300, Andy Shevchenko wrote:
> > > > > > Due to parsing of ACPI tables. I don't want to copy'n'paste 25% of
> > > > > > gpiolib-acpi.c in here. I think provided solution is cleaner and (more)
> > > > > > flexible in terms of maintenance.
> > > > > 
> > > > > Hmm, you seem to pass a hard-coded pin number (1) to the core that then
> > > > > passes it back to the driver. Why you can't simple use that number here
> > > > > directly? You don't need to parse anything. What I'm missing? :-)
> > > > 
> > > > Okay, so, AFAIU you are proposing something like this:
> > > > 
> > > > 1) find a GPIO controller by the ACPI path (somehow, I guess by finding a
> > > >    handle followed by physical device behind it); 2) somehow to request a
> > > >    pin from that device by number;
> > > > 3) convert to IRQ and use.
> > > > 
> > > > Is it correct?
> > > 
> > > Well, no. In the first patch you do this:
> > > 
> > >   pin = lookup->info.quirks_data;
> > > 
> > > and this essentially becomes 1 so you know the pin number upfront in the
> > > driver. Why not simply get GPIO number 1 in the driver and use it as an
> > > interrupt? You know already that this particular board with the matching
> > > DMI identifier always uses the this number anyway.
> > 
> > But GPIO (relative!) number is not enough. We need to understand more, i.e.:
> > 1) from which GPIO controller it comes from (okay, for this particular platform I know it);
> > 2) which expander does have this resource (they all have same ACPI HID).
> > 
> > So, second one means to count GpioInt() resources (I don't remember if we have
> > helper for that, probably we can add one). For the first we need to get a GPIO
> > controller something (gpiochip?) And this first one I have no idea how we can
> > perform without talking to the core.
> > 
> > Basically, it may be done by reimplementing acpi_dev_gpio_irq_get(), followed
> > by acpi_get_gpiod_by_index(), followed by acpi_gpio_resource_lookup(), followed
> > by acpi_populate_gpio_lookup(), where at last this quirk should be applied.
> > 
> > It seems for me like an over duplicated solution.
> > 
> > I really don't understand how we can shortcut all these. What am I missing?
> 
> Why for example following would not work? If it is using global GPIO numbers
> anyway.

Because GPIO 1 above and below is not global?
Okay, what we have in the table seems global.
Let me see if this will fly.

> static int pca953x_acpi_interrupt_get_irq(struct device *dev)
> {
>         struct gpio_desc *desc;
>  
>         desc = gpio_to_desc(1);
>         if (!desc)

Okay, this seems have no deferred probe support, but I think it's fine,
it will be unlikely we will have for the certain platform the SoC's GPIO
controller enumerated after the IO expander one.

>                 return -ENODEV;
> 
>         return gpiod_to_irq(desc);
> }
diff mbox series

Patch

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;