Commit c6ccc4dd authored by Hans de Goede's avatar Hans de Goede Committed by Bartosz Golaszewski
Browse files

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: e7f9ff5d ("gpiolib: add support for software nodes")
Cc: stable@vger.kernel.org
Signed-off-by: default avatarHans de Goede <hansg@kernel.org>
Reviewed-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
Link: https://lore.kernel.org/r/20250920200955.20403-1-hansg@kernel.org


Signed-off-by: default avatarBartosz Golaszewski <bartosz.golaszewski@linaro.org>
parent 07e27ad1
Loading
Loading
Loading
Loading
+19 −2
Original line number Diff line number Diff line
@@ -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,7 +4639,7 @@ 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,
		desc = gpiod_fwnode_lookup(fwnode, consumer, con_id, idx,
					   &flags, &lookupflags);
		if (gpiod_not_found(desc) && platform_lookup_allowed) {
			/*