This driver still uses the Legacy GPIO Subsystem gpio_ API. While it does work fine, it won't supports the new GPIO LOOKUP tables that have been popping up upstream since v5.0.
For APU2 users > linux 5.4: Please test if this fixes your reset button. (DT devices needs to be re-tested as well) Reported-by: Chris Blake <chrisrblak...@gmail.com> Signed-off-by: Christian Lamparter <chunk...@gmail.com> --- .../src/gpio-button-hotplug.c | 83 ++++++++----------- 1 file changed, 35 insertions(+), 48 deletions(-) diff --git a/package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c b/package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c index 9575c6245b..bc151645e3 100644 --- a/package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c +++ b/package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c @@ -242,11 +242,11 @@ static int gpio_button_get_value(struct gpio_keys_button_data *bdata) int val; if (bdata->can_sleep) - val = !!gpio_get_value_cansleep(bdata->b->gpio); + val = !!gpiod_get_value_cansleep(bdata->gpiod); else - val = !!gpio_get_value(bdata->b->gpio); + val = !!gpiod_get_value(bdata->gpiod); - return val ^ bdata->b->active_low; + return val; } static void gpio_keys_handle_button(struct gpio_keys_button_data *bdata) @@ -391,35 +391,15 @@ gpio_keys_get_devtree_pdata(struct device *dev) of_property_read_u32(node, "poll-interval", &pdata->poll_interval); for_each_child_of_node(node, pp) { - enum of_gpio_flags flags; - - if (!of_find_property(pp, "gpios", NULL)) { - pdata->nbuttons--; - dev_warn(dev, "Found button without gpios\n"); - continue; - } - button = (struct gpio_keys_button *)(&pdata->buttons[i++]); - button->irq = irq_of_parse_and_map(pp, 0); + button->gpio = -ENOENT; /* gets filled in later */ - button->gpio = of_get_gpio_flags(pp, 0, &flags); - if (button->gpio < 0) { - error = button->gpio; - if (error != -ENOENT) { - if (error != -EPROBE_DEFER) - dev_err(dev, - "Failed to get gpio flags, error: %d\n", - error); - return ERR_PTR(error); - } - } else { - button->active_low = !!(flags & OF_GPIO_ACTIVE_LOW); - } + button->irq = irq_of_parse_and_map(pp, 0); if (of_property_read_u32(pp, "linux,code", &button->code)) { - dev_err(dev, "Button without keycode: 0x%x\n", - button->gpio); + dev_err(dev, "Button node '%s' without keycode\n", + pp->full_name); error = -EINVAL; goto err_out; } @@ -514,7 +494,6 @@ static int gpio_keys_button_probe(struct platform_device *pdev, for (i = 0; i < pdata->nbuttons; i++) { struct gpio_keys_button *button = &buttons[i]; struct gpio_keys_button_data *bdata = &bdev->data[i]; - unsigned int gpio = button->gpio; if (button->wakeup) { dev_err(dev, "does not support wakeup\n"); @@ -534,26 +513,37 @@ static int gpio_keys_button_probe(struct platform_device *pdev, continue; } - error = devm_gpio_request(dev, gpio, + bdata->gpiod = devm_gpiod_get_index(dev, + button->desc ? button->desc : DRV_NAME, i, GPIOD_IN); + if (IS_ERR(bdata->gpiod)) { + unsigned gpio; + + error = PTR_ERR(bdata->gpiod); + + /* + * In case of -ENOENT, there still hope that we might + * just be using legacy platform data, which has the + * button->gpio filled in. + */ + if (error != -ENOENT || !gpio_is_valid(button->gpio)) + return error; + + gpio = button->gpio; + error = devm_gpio_request_one(dev, gpio, GPIOF_IN | + (button->active_low ? GPIOF_ACTIVE_LOW : 0), button->desc ? button->desc : DRV_NAME); - if (error) { - dev_err(dev, "unable to claim gpio %u, err=%d\n", - gpio, error); - return error; - } - bdata->gpiod = gpio_to_desc(gpio); - if (!bdata->gpiod) - return -EINVAL; + if (error) { + dev_err(dev, "unable to claim gpio %u, err=%d\n", + gpio, error); + return error; + } - error = gpio_direction_input(gpio); - if (error) { - dev_err(dev, - "unable to set direction on gpio %u, err=%d\n", - gpio, error); - return error; + bdata->gpiod = gpio_to_desc(gpio); + if (!bdata->gpiod) + return -EINVAL; } - bdata->can_sleep = gpio_cansleep(gpio); + bdata->can_sleep = gpiod_cansleep(bdata->gpiod); bdata->last_state = -1; /* Unknown state on boot */ if (bdev->polled) { @@ -608,11 +598,8 @@ static int gpio_keys_probe(struct platform_device *pdev) INIT_DELAYED_WORK(&bdata->work, gpio_keys_irq_work_func); - if (!bdata->gpiod) - continue; - if (!button->irq) { - bdata->irq = gpio_to_irq(button->gpio); + bdata->irq = gpiod_to_irq(bdata->gpiod); if (bdata->irq < 0) { dev_err(&pdev->dev, "failed to get irq for gpio:%d\n", -- 2.32.0 _______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/mailman/listinfo/openwrt-devel