gpio-button-hotplug: accept GPIO buttons with explicit IRQs

gpio-button-hotplug skips buttons with button->irq set because it cannot
handle true interrupt-only gpio-keys descriptions. That check also skips
valid GPIO-backed buttons that provide a separate interrupt specifier, such
as the Meraki MX60 reset button.

Try to acquire the GPIO descriptor before deciding that an explicit-IRQ
button is unsupported. Continue to skip true interrupt-only buttons, and
make the IRQ setup and teardown paths ignore skipped entries.

Tested on: Cisco Meraki MX60. Reset button now works.

Fixes: 23845fa10b ("gpio-button-hotplug: do not error on interrupt attached keys")
Assisted-by: Codex:GPT-5.5
Signed-off-by: Rosen Penev <rosenp@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/23382
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
This commit is contained in:
Rosen Penev
2026-05-16 15:14:50 -07:00
committed by Jonas Jelonek
parent c8dcb40229
commit fb1c7d7892
@@ -500,13 +500,6 @@ static int gpio_keys_button_probe(struct platform_device *pdev,
goto out;
}
if (button->irq) {
dev_err(dev, "skipping button %s (only gpio buttons supported)\n",
button->desc);
bdata->b = &pdata->buttons[i];
continue;
}
if (gpio_is_valid(button->gpio)) {
/* legacy platform data... but is it the lookup table? */
bdata->gpiod = devm_gpiod_get_index(dev, desc, i,
@@ -541,6 +534,13 @@ static int gpio_keys_button_probe(struct platform_device *pdev,
if (IS_ERR_OR_NULL(bdata->gpiod)) {
error = IS_ERR(bdata->gpiod) ? PTR_ERR(bdata->gpiod) :
-EINVAL;
if (button->irq && error == -ENOENT) {
dev_err(dev, "skipping button %s (only gpio buttons supported)\n",
button->desc);
continue;
}
goto out;
}
@@ -598,6 +598,9 @@ static int gpio_keys_probe(struct platform_device *pdev)
struct gpio_keys_button_data *bdata = &bdev->data[i];
unsigned long irqflags = IRQF_ONESHOT;
if (!bdata->gpiod)
continue;
INIT_DELAYED_WORK(&bdata->work, gpio_keys_irq_work_func);
if (!button->irq) {
@@ -662,8 +665,10 @@ static void gpio_keys_irq_close(struct gpio_keys_button_dev *bdev)
for (i = 0; i < pdata->nbuttons; i++) {
struct gpio_keys_button_data *bdata = &bdev->data[i];
disable_irq(bdata->irq);
cancel_delayed_work_sync(&bdata->work);
if (bdata->irq) {
disable_irq(bdata->irq);
cancel_delayed_work_sync(&bdata->work);
}
}
}