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

Reply via email to