gpiolib: Extend software-node support to support secondary software-nodes
Subsystems (3)
PATCH v2 1/1 gpiolib: Extend software-node support to support secondary software-nodes
When a software-node gets added to a device which already has another fwnode as primary node it will become the secondary fwnode for that device.
Currently if a software-node with GPIO properties ends up as the secondary fwnode then gpiod_find_by_fwnode() will fail to find the GPIOs.
Add a new gpiod_fwnode_lookup() helper which falls back to calling gpiod_find_by_fwnode() with the secondary fwnode if the GPIO was not found in the primary fwnode.
---
Changes in v2:
- Add a new gpiod_fwnode_lookup() helper instead of putting the secondary fwnode check inside gpiod_find_by_fwnode()
--- drivers/gpio/gpiolib.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-)
drivers/gpio/gpiolib.c +19 -2
@@ -4604,6 +4604,23 @@ static struct gpio_desc *gpiod_find_by_fwnode(struct fwnode_handle *fwnode,return desc; } +static struct gpio_desc *gpiod_fwnode_lookup (struct fwnode_handle *fwnode, +struct device *consumer, +const char *con_id, +unsigned int idx, +enum gpiod_flags *flags, +unsigned long *lookupflags) +{ +struct gpio_desc *desc; + + desc =gpiod_find_by_fwnode (fwnode, consumer, con_id, idx, flags, lookupflags); +if (gpiod_not_found (desc) && !IS_ERR_OR_NULL (fwnode)) + desc =gpiod_find_by_fwnode (fwnode->secondary, consumer, con_id, + idx, flags, lookupflags); + +return desc; +} + struct gpio_desc *gpiod_find_and_request(struct device *consumer, struct fwnode_handle *fwnode, const char *con_id,
@@ -4622,8 +4639,8 @@ struct gpio_desc *gpiod_find_and_request(struct device *consumer,int ret =0 ; scoped_guard(srcu, &gpio_devices_srcu) { - desc =gpiod_find_by_fwnode (fwnode, consumer, con_id, idx, - &flags, &lookupflags); + desc =gpiod_fwnode_lookup (fwnode, consumer, con_id, idx, + &flags, &lookupflags);if (gpiod_not_found (desc) && platform_lookup_allowed) {/* * Either we are not using DT or ACPI, or their lookup
Signature · 1 line
2.51.0
Quoted 7 lines · Hans de Goede
When a software-node gets added to a device which already has another fwnode as primary node it will become the secondary fwnode for that device.
Currently if a software-node with GPIO properties ends up as the secondary fwnode then
gpiod_find_by_fwnode()will fail to find the GPIOs.
Quoted 8 lines
Add a new
gpiod_fwnode_lookup()helper which falls back to callinggpiod_find_by_fwnode()with the secondary fwnode if the GPIO was not found in the primary fwnode.Fixes e7f9ff5dc90c ("gpiolib: add support for software nodes")Cc Dmitry Torokhov <[email protected]>Signed-off-by Hans de Goede <[email protected]>
Quoted 21 lines
---
Changes in v2:
- Add a newgpiod_fwnode_lookup()helper instead of putting the secondary fwnode check insidegpiod_find_by_fwnode()--- drivers/gpio/gpiolib.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-)drivers/gpio/gpiolib.c +5
-0@@ -4604,6 +4604,23 @@ static struct gpio_desc *gpiod_find_by_fwnode(struct fwnode_handle *fwnode,return desc; } +static struct gpio_desc *gpiod_fwnode_lookup(struct fwnode_handle *fwnode, + struct device *consumer, + const char *con_id, + unsigned int idx, + enum gpiod_flags *flags,
drivers/gpio/gpiolib.c static struct gpio_desc *gpiod_find_by_fwnode(struct fwnode_handle *fwnode, · line 4621
Quoted 10 lines
drivers/gpio/gpiolib.c +10
-0+ unsigned long *lookupflags) +{ +struct gpio_desc *desc; + + desc =gpiod_find_by_fwnode (fwnode, consumer, con_id, idx, flags, lookupflags); +if (gpiod_not_found (desc) && !IS_ERR_OR_NULL (fwnode)) + desc =gpiod_find_by_fwnode (fwnode->secondary, consumer, con_id, + idx, flags, lookupflags); + +return desc;
Bikeshedding for later. Maybe do it like this in case we can have more than 2 nodes at some point?
do {
desc = gpiod_find_by_fwnode(fwnode, consumer, con_id, idx, flags, lookupflags);
if (!gpiod_not_found(desc))
return desc;
fwnode = fwnode->secondary;
} while (!IS_ERR_OR_NULL(fwnode));
return ERR_PTR(-ENOENT);Quoted 6 lines
drivers/gpio/gpiolib.c +2
-0+} + struct gpio_desc *gpiod_find_and_request(struct device *consumer, struct fwnode_handle *fwnode, const char *con_id,
drivers/gpio/gpiolib.c struct gpio_desc *gpiod_find_and_request(struct device *consumer, · line 4646
Quoted 10 lines
drivers/gpio/gpiolib.c +2
-2@@ -4622,8 +4639,8 @@ struct gpio_desc *gpiod_find_and_request(struct device *consumer,int ret =0 ; scoped_guard(srcu, &gpio_devices_srcu) { - desc =gpiod_find_by_fwnode (fwnode, consumer, con_id, idx, - &flags, &lookupflags); + desc =gpiod_fwnode_lookup (fwnode, consumer, con_id, idx, + &flags, &lookupflags);if (gpiod_not_found (desc) && platform_lookup_allowed) {/* * Either we are not using DT or ACPI, or their lookup
Thanks.
Signature · 1 line
Dmitry
Quoted 54 lines · Dmitry Torokhov
Quoted 7 lines · Hans de Goede
When a software-node gets added to a device which already has another fwnode as primary node it will become the secondary fwnode for that device.
Currently if a software-node with GPIO properties ends up as the secondary fwnode then
gpiod_find_by_fwnode()will fail to find the GPIOs.Quoted 8 lines
Add a new
gpiod_fwnode_lookup()helper which falls back to callinggpiod_find_by_fwnode()with the secondary fwnode if the GPIO was not found in the primary fwnode.Fixes e7f9ff5dc90c ("gpiolib: add support for software nodes")Cc Dmitry Torokhov <[email protected]>Signed-off-by Hans de Goede <[email protected]>Reviewed-by Dmitry Torokhov <[email protected]>Quoted 21 lines
---
Changes in v2:
- Add a newgpiod_fwnode_lookup()helper instead of putting the secondary fwnode check insidegpiod_find_by_fwnode()--- drivers/gpio/gpiolib.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-)drivers/gpio/gpiolib.c +5
-0@@ -4604,6 +4604,23 @@ static struct gpio_desc *gpiod_find_by_fwnode(struct fwnode_handle *fwnode,return desc; } +static struct gpio_desc *gpiod_fwnode_lookup(struct fwnode_handle *fwnode, + struct device *consumer, + const char *con_id, + unsigned int idx, + enum gpiod_flags *flags,drivers/gpio/gpiolib.c static struct gpio_desc *gpiod_find_by_fwnode(struct fwnode_handle *fwnode, · line 4621
Quoted 10 lines
drivers/gpio/gpiolib.c +10
-0+ unsigned long *lookupflags) +{ +struct gpio_desc *desc; + + desc =gpiod_find_by_fwnode (fwnode, consumer, con_id, idx, flags, lookupflags); +if (gpiod_not_found (desc) && !IS_ERR_OR_NULL (fwnode)) + desc =gpiod_find_by_fwnode (fwnode->secondary, consumer, con_id, + idx, flags, lookupflags); + +return desc;Bikeshedding for later. Maybe do it like this in case we can have more than 2 nodes at some point?
Quoted 9 lines
do {
desc = gpiod_find_by_fwnode(fwnode, consumer, con_id, idx, flags, lookupflags);
if (!gpiod_not_found(desc))
return desc;
fwnode = fwnode->secondary;
} while (!IS_ERR_OR_NULL(fwnode));
return ERR_PTR(-ENOENT);At a minimum this would need to a regular while () {} loop then, the initial fwnode may also be NULL and we don't want to deref that.
Andy did mention turning the fwnode-s into a regular linked-list in the future, but I think that would be using <linux/list.h> then, replacing the secondary pointer with a list head ?
Regards,
Hans
Quoted 20 lines
Quoted 7 lines
drivers/gpio/gpiolib.c +2
-0+} + struct gpio_desc *gpiod_find_and_request(struct device *consumer, struct fwnode_handle *fwnode, const char *con_id,drivers/gpio/gpiolib.c struct gpio_desc *gpiod_find_and_request(struct device *consumer, · line 4646
Quoted 10 lines
drivers/gpio/gpiolib.c +2
-2@@ -4622,8 +4639,8 @@ struct gpio_desc *gpiod_find_and_request(struct device *consumer,int ret =0 ; scoped_guard(srcu, &gpio_devices_srcu) { - desc =gpiod_find_by_fwnode (fwnode, consumer, con_id, idx, - &flags, &lookupflags); + desc =gpiod_fwnode_lookup (fwnode, consumer, con_id, idx, + &flags, &lookupflags);if (gpiod_not_found (desc) && platform_lookup_allowed) {/* * Either we are not using DT or ACPI, or their lookup Thanks.
Quoted 2 lines · Hans de Goede
Quoted 1 line · Dmitry Torokhov
On Sat, Sep 20, 2025 at 10:09:55PM +0200, Hans de Goede wrote:
...
Quoted 11 lines
Quoted 11 lines
Bikeshedding for later. Maybe do it like this in case we can have more than 2 nodes at some point?
do { desc = gpiod_find_by_fwnode(fwnode, consumer, con_id, idx, flags, lookupflags); if (!gpiod_not_found(desc)) return desc; fwnode = fwnode->secondary; } while (!IS_ERR_OR_NULL(fwnode));
Quoted 8 lines
Quoted 1 line
return ERR_PTR(-ENOENT);At a minimum this would need to a regular while () {} loop then, the initial fwnode may also be NULL and we don't want to deref that.
Andy did mention turning the fwnode-s into a regular linked-list in the future, but I think that would be using <
linux/list.h> then, replacing the secondary pointer with a list head ?
Dropping secondary in the struct fwnode_handle and use struct list_head somewhere else, e.g., struct device.
Quoted 1 line
Quoted 1 line
Quoted 1 line
+}
Signature · 2 lines
With Best Regards, Andy Shevchenko
Bartosz Golaszewski
AppliedFrom: Bartosz Golaszewski <[email protected]>
Quoted 8 lines · Hans de Goede
When a software-node gets added to a device which already has another fwnode as primary node it will become the secondary fwnode for that device.
Currently if a software-node with GPIO properties ends up as the secondary fwnode then
gpiod_find_by_fwnode()will fail to find the GPIOs.[...]
Applied, thanks!
[1/1] gpiolib: Extend software-node support to support secondary software-nodes
https://git.kernel.org/brgl/linux/c/c6ccc4dde17676dfe617b9a37bd9ba19a8fc87ee
Best regards,
Signature · 1 line
Bartosz Golaszewski <[email protected]>