Skip to contentSkip to conversation

gpiolib: Extend software-node support to support secondary software-nodes

PATCH Applied Hans de Goede 4 participants 5 messages Sep 20, 2025 – Sep 22, 2025

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

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.

Fixes e7f9ff5dc90c ("gpiolib: add support for software nodes")
Cc Dmitry Torokhov <[email protected]>

---
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
index 0d2b470a252e..74d54513730a 100644
@@ -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
Reviewed-by on v2 1/1
#1 lore raw
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 calling gpiod_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]>
Quoted 21 lines

---
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 +5 -0
index 0d2b470a252e..74d54513730a 100644
@@ -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
#2 lore raw
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 calling gpiod_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]>
Quoted 21 lines

---
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 +5 -0
index 0d2b470a252e..74d54513730a 100644
@@ -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.

#3 lore raw
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
#4 lore raw
In reply to Hans de Goede

From: 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]>