Skip to content

Commit ba8c90c

Browse files
andy-shevbrgl
authored andcommitted
gpio: pca953x: Override IRQ for one of the expanders on Galileo Gen 2
ACPI table on Intel Galileo Gen 2 has wrong pin number for IRQ resource of one of the I²C GPIO expanders. Since we know what that number is and luckily have GPIO bases fixed for SoC's controllers, we may use a simple DMI quirk to match the platform and retrieve GpioInt() pin on it for the expander in question. Mika suggested the way to avoid a quirk in the GPIO ACPI library and here is the second, almost rewritten version of it. Fixes: f32517b ("gpio: pca953x: support ACPI devices found on Galileo Gen2") Depends-on: 25e3ef8 ("gpio: acpi: Split out acpi_gpio_get_irq_resource() helper") Suggested-by: Mika Westerberg <[email protected]> Reviewed-by: Mika Westerberg <[email protected]> Signed-off-by: Andy Shevchenko <[email protected]> Signed-off-by: Bartosz Golaszewski <[email protected]>
1 parent 064c73a commit ba8c90c

File tree

1 file changed

+79
-0
lines changed

1 file changed

+79
-0
lines changed

drivers/gpio/gpio-pca953x.c

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,79 @@ static const struct i2c_device_id pca953x_id[] = {
107107
};
108108
MODULE_DEVICE_TABLE(i2c, pca953x_id);
109109

110+
#ifdef CONFIG_GPIO_PCA953X_IRQ
111+
112+
#include <linux/dmi.h>
113+
#include <linux/gpio.h>
114+
#include <linux/list.h>
115+
116+
static const struct dmi_system_id pca953x_dmi_acpi_irq_info[] = {
117+
{
118+
/*
119+
* On Intel Galileo Gen 2 board the IRQ pin of one of
120+
* the I²C GPIO expanders, which has GpioInt() resource,
121+
* is provided as an absolute number instead of being
122+
* relative. Since first controller (gpio-sch.c) and
123+
* second (gpio-dwapb.c) are at the fixed bases, we may
124+
* safely refer to the number in the global space to get
125+
* an IRQ out of it.
126+
*/
127+
.matches = {
128+
DMI_EXACT_MATCH(DMI_BOARD_NAME, "GalileoGen2"),
129+
},
130+
},
131+
{}
132+
};
133+
134+
#ifdef CONFIG_ACPI
135+
static int pca953x_acpi_get_pin(struct acpi_resource *ares, void *data)
136+
{
137+
struct acpi_resource_gpio *agpio;
138+
int *pin = data;
139+
140+
if (acpi_gpio_get_irq_resource(ares, &agpio))
141+
*pin = agpio->pin_table[0];
142+
return 1;
143+
}
144+
145+
static int pca953x_acpi_find_pin(struct device *dev)
146+
{
147+
struct acpi_device *adev = ACPI_COMPANION(dev);
148+
int pin = -ENOENT, ret;
149+
LIST_HEAD(r);
150+
151+
ret = acpi_dev_get_resources(adev, &r, pca953x_acpi_get_pin, &pin);
152+
acpi_dev_free_resource_list(&r);
153+
if (ret < 0)
154+
return ret;
155+
156+
return pin;
157+
}
158+
#else
159+
static inline int pca953x_acpi_find_pin(struct device *dev) { return -ENXIO; }
160+
#endif
161+
162+
static int pca953x_acpi_get_irq(struct device *dev)
163+
{
164+
int pin, ret;
165+
166+
pin = pca953x_acpi_find_pin(dev);
167+
if (pin < 0)
168+
return pin;
169+
170+
dev_info(dev, "Applying ACPI interrupt quirk (GPIO %d)\n", pin);
171+
172+
if (!gpio_is_valid(pin))
173+
return -EINVAL;
174+
175+
ret = gpio_request(pin, "pca953x interrupt");
176+
if (ret)
177+
return ret;
178+
179+
return gpio_to_irq(pin);
180+
}
181+
#endif
182+
110183
static const struct acpi_device_id pca953x_acpi_ids[] = {
111184
{ "INT3491", 16 | PCA953X_TYPE | PCA_LATCH_INT, },
112185
{ }
@@ -754,6 +827,12 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, int irq_base)
754827
DECLARE_BITMAP(irq_stat, MAX_LINE);
755828
int ret;
756829

830+
if (dmi_first_match(pca953x_dmi_acpi_irq_info)) {
831+
ret = pca953x_acpi_get_irq(&client->dev);
832+
if (ret > 0)
833+
client->irq = ret;
834+
}
835+
757836
if (!client->irq)
758837
return 0;
759838

0 commit comments

Comments
 (0)