[RFC PATCH] gpio-button-hotplug: gpio descriptor API update
Christian Lamparter
chunkeey at gmail.com
Thu Aug 5 06:54:03 PDT 2021
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 <chrisrblake93 at gmail.com>
Signed-off-by: Christian Lamparter <chunkeey at 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
More information about the openwrt-devel
mailing list