Skip to content

Commit

Permalink
gpio: pca953x: Set IRQ type when handle Intel Galileo Gen 2
Browse files Browse the repository at this point in the history
commit eb44133 upstream.

The commit 0ea6839 ("gpio: dwapb: Convert driver to using the
GPIO-lib-based IRQ-chip") indeliberately made a regression on how
IRQ line from GPIO I²C expander is handled. I.e. it reveals that
the quirk for Intel Galileo Gen 2 misses the part of setting IRQ type
which previously was predefined by gpio-dwapb driver. Now, we have to
reorganize the approach to call necessary parts, which can be done via
ACPI_GPIO_QUIRK_ABSOLUTE_NUMBER quirk.

Without this fix and with above mentioned change the kernel hangs
on the first IRQ event with:

    gpio gpiochip3: Persistence not supported for GPIO 1
    irq 32, desc: 62f8fb50, depth: 0, count: 0, unhandled: 0
    ->handle_irq():  41c7b0ab, handle_bad_irq+0x0/0x40
    ->irq_data.chip(): e03f1e72, 0xc2539218
    ->action(): 0ecc7e6f
    ->action->handler(): 8a3db21e, irq_default_primary_handler+0x0/0x10
       IRQ_NOPROBE set
    unexpected IRQ trap at vector 20

Fixes: ba8c90c ("gpio: pca953x: Override IRQ for one of the expanders on Galileo Gen 2")
Depends-on: 0ea6839 ("gpio: dwapb: Convert driver to using the GPIO-lib-based IRQ-chip")
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
andy-shev authored and gregkh committed Mar 17, 2021
1 parent f60ffab commit 2e3c8a2
Showing 1 changed file with 23 additions and 55 deletions.
78 changes: 23 additions & 55 deletions drivers/gpio/gpio-pca953x.c
Expand Up @@ -112,8 +112,29 @@ MODULE_DEVICE_TABLE(i2c, pca953x_id);
#ifdef CONFIG_GPIO_PCA953X_IRQ

#include <linux/dmi.h>
#include <linux/gpio.h>
#include <linux/list.h>

static const struct acpi_gpio_params pca953x_irq_gpios = { 0, 0, true };

static const struct acpi_gpio_mapping pca953x_acpi_irq_gpios[] = {
{ "irq-gpios", &pca953x_irq_gpios, 1, ACPI_GPIO_QUIRK_ABSOLUTE_NUMBER },
{ }
};

static int pca953x_acpi_get_irq(struct device *dev)
{
int ret;

ret = devm_acpi_dev_add_driver_gpios(dev, pca953x_acpi_irq_gpios);
if (ret)
dev_warn(dev, "can't add GPIO ACPI mapping\n");

ret = acpi_dev_gpio_irq_get_by(ACPI_COMPANION(dev), "irq-gpios", 0);
if (ret < 0)
return ret;

dev_info(dev, "ACPI interrupt quirk (IRQ %d)\n", ret);
return ret;
}

static const struct dmi_system_id pca953x_dmi_acpi_irq_info[] = {
{
Expand All @@ -132,59 +153,6 @@ static const struct dmi_system_id pca953x_dmi_acpi_irq_info[] = {
},
{}
};

#ifdef CONFIG_ACPI
static int pca953x_acpi_get_pin(struct acpi_resource *ares, void *data)
{
struct acpi_resource_gpio *agpio;
int *pin = data;

if (acpi_gpio_get_irq_resource(ares, &agpio))
*pin = agpio->pin_table[0];
return 1;
}

static int pca953x_acpi_find_pin(struct device *dev)
{
struct acpi_device *adev = ACPI_COMPANION(dev);
int pin = -ENOENT, ret;
LIST_HEAD(r);

ret = acpi_dev_get_resources(adev, &r, pca953x_acpi_get_pin, &pin);
acpi_dev_free_resource_list(&r);
if (ret < 0)
return ret;

return pin;
}
#else
static inline int pca953x_acpi_find_pin(struct device *dev) { return -ENXIO; }
#endif

static int pca953x_acpi_get_irq(struct device *dev)
{
int pin, ret;

pin = pca953x_acpi_find_pin(dev);
if (pin < 0)
return pin;

dev_info(dev, "Applying ACPI interrupt quirk (GPIO %d)\n", pin);

if (!gpio_is_valid(pin))
return -EINVAL;

ret = gpio_request(pin, "pca953x interrupt");
if (ret)
return ret;

ret = gpio_to_irq(pin);

/* When pin is used as an IRQ, no need to keep it requested */
gpio_free(pin);

return ret;
}
#endif

static const struct acpi_device_id pca953x_acpi_ids[] = {
Expand Down

0 comments on commit 2e3c8a2

Please sign in to comment.