Linux GPIO subsystem development
 help / color / mirror / Atom feed
* [PATCH v2 00/10] gpio: make gpiolib-shared more fwnode-centric
@ 2026-11-13 15:47 Bartosz Golaszewski
  2026-11-13 15:47 ` [PATCH v2 01/10] lib: string_helpers: export and rename struct strarray Bartosz Golaszewski
                   ` (9 more replies)
  0 siblings, 10 replies; 18+ messages in thread
From: Bartosz Golaszewski @ 2026-11-13 15:47 UTC (permalink / raw)
  To: Andy Shevchenko, Daniel Scally, Heikki Krogerus, Sakari Ailus,
	Bartosz Golaszewski, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Johan Hovold, Hans Verkuil, Laurent Pinchart,
	Kees Cook, Andy Shevchenko, Len Brown, Rob Herring,
	Saravana Kannan, Linus Walleij, Andrew Morton,
	Gustavo A. R. Silva
  Cc: linux-acpi, driver-core, linux-kernel, linux-hardening,
	devicetree, linux-gpio, Bartosz Golaszewski

Currently the code in gpiolib-shared.c only supports OF nodes and uses a
lot of OF-specific APIs. This series attempts to make the code more
generic, ahead of extending support for sharing GPIOs to other types of
firmware nodes, by defining two new fwnode operations, implementing them
for OF nodes and using them in GPIOLIB in order to limit the OF-specific
API usage to only a few places guarded by ifdefs.

The new fwnode APIs are:
a) property_get_names() - this closes the gap between OF nodes and
   fwnodes: OF nodes allow users to iterate over all properties while
   fwnodes don't advertise all properties in any way at the moment
b) count_references() - there's currently no way of counting references
   in an fwnode reliably: using fwnode_property_get_reference_args()
   does not work for empty references (e.g.: phandle = <0>, <&foo 1 2>;)

The first patch adds a CLASS() for string arrays. The following 6 define
and implement new fwnode operations. The final patch generalizes the code
in gpiolib-shared.c.

Merging strategy: patches 1-8 should go through the driver core tree and
be provided on an immutable branch to me so that I can pull it and queue
the final 2 patches via the GPIO tree.

This series depends on the series from Alejandro Colomar adding
strprefix() as indicated in the b4 tracking.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
Changes in v2:
- Integrate the series from from Alejandro Colomar adding strprefix() into
  this series as a b4 dependency
- Reuse the existing struct strarray in the new CLASS() for string
  arrays
- Make sure that props != NULL in fwnode_property_get_names()
- Replace string.h with string_helpers.h instead of including both
- Tweak the kerneldocs (Andy)
- Use size_add() from overflow.h
- Mark gpio_shared_fwnode_traverse() as __maybe_unused for !CONFIG_OF
- Return early in the OF variant of fwnode_property_get_names() if no
  properties are defined
- Add commit removing unused leftover code
- Remove useless alias variables
- Link to v1: https://patch.msgid.link/20261104-fwnode-for-each-prop-v1-0-6e28fe1c72c4@oss.qualcomm.com

---
Bartosz Golaszewski (10):
      lib: string_helpers: export and rename struct strarray
      lib: string_helpers: implement a CLASS() for string arrays
      fwnode: define the property_get_names() operation
      device property: provide fwnode_property_get_names()
      of: property: implement the .property_get_names() fwnode operation
      fwnode: define the count_references() fwnode operation
      device property: provide fwnode_property_count_references()
      of: property: implement the count_references() fwnode operation
      gpio: shared: removed unused field from struct gpio_shared_entry
      gpio: shared: generalize most code to firmware nodes

 drivers/base/property.c        | 115 +++++++++++++++++++-
 drivers/gpio/gpiolib-shared.c  | 242 ++++++++++++++++++++++-------------------
 drivers/of/property.c          |  41 ++++++-
 include/linux/fwnode.h         |  15 +++
 include/linux/property.h       |   4 +
 include/linux/string_helpers.h |  12 ++
 lib/string_helpers.c           |   9 +-
 7 files changed, 315 insertions(+), 123 deletions(-)
---
base-commit: 161837d37055642b03475137461d4438c65dbddf
change-id: 20260916-fwnode-for-each-prop-d7a6f90e7338
prerequisite-message-id: <cover.1794574496.git.alx@kernel.org>
prerequisite-patch-id: 6c8ea11afdfadea1c72457e460596f9140195f8a
prerequisite-patch-id: 81834766a605fc75e62501a8459944c87aa7848e
prerequisite-patch-id: 49110713d1b10ae2972ae738da383215d9be001b
prerequisite-patch-id: 97bf1ce8e594218715d5df30711d0523c7f07bc5
prerequisite-patch-id: c94cdf0377763fbdcb942add8a058161503f9024
prerequisite-patch-id: d0e6af689d680619ee07aabb50635328052bc9af
prerequisite-patch-id: 1006c25c87a8e46129fdba68822b9592c3f5e0e9

Best regards,
-- 
Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v2 01/10] lib: string_helpers: export and rename struct strarray
  2026-11-13 15:47 [PATCH v2 00/10] gpio: make gpiolib-shared more fwnode-centric Bartosz Golaszewski
@ 2026-11-13 15:47 ` Bartosz Golaszewski
  2026-11-13 16:09   ` Andy Shevchenko
  2026-11-13 15:47 ` [PATCH v2 02/10] lib: string_helpers: implement a CLASS() for string arrays Bartosz Golaszewski
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 18+ messages in thread
From: Bartosz Golaszewski @ 2026-11-13 15:47 UTC (permalink / raw)
  To: Andy Shevchenko, Daniel Scally, Heikki Krogerus, Sakari Ailus,
	Bartosz Golaszewski, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Johan Hovold, Hans Verkuil, Laurent Pinchart,
	Kees Cook, Andy Shevchenko, Len Brown, Rob Herring,
	Saravana Kannan, Linus Walleij, Andrew Morton,
	Gustavo A. R. Silva
  Cc: linux-acpi, driver-core, linux-kernel, linux-hardening,
	devicetree, linux-gpio, Bartosz Golaszewski

Ahead of introducing a CLASS() for string arrays, make the existing
struct strarray public in linux/string_helpers.h. Rename it to kstrarray
to avoid any potential conflicts in the future and make it clear, it's a
kernel type.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
 include/linux/string_helpers.h | 5 +++++
 lib/string_helpers.c           | 9 ++-------
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/include/linux/string_helpers.h b/include/linux/string_helpers.h
index 3fb88a1e989833ad5ea1a46858efa16e3971bf08..c9f08066439bdd33cc26e2054dbe1ba2e867aee7 100644
--- a/include/linux/string_helpers.h
+++ b/include/linux/string_helpers.h
@@ -116,6 +116,11 @@ char *kstrdup_quotable_file(struct file *file, gfp_t gfp);
 
 char *kstrdup_and_replace(const char *src, char old, char new, gfp_t gfp);
 
+struct kstrarray {
+	char **array __counted_by_ptr(n);
+	size_t n;
+};
+
 char **kasprintf_strarray(gfp_t gfp, const char *prefix, size_t n);
 void kfree_strarray(char **array, size_t n);
 
diff --git a/lib/string_helpers.c b/lib/string_helpers.c
index 98d6ed0eaab7e9f3d54e420c404629a28b925bf4..8ec7ff6dac1212fe8a1f242654944ba6e5568e20 100644
--- a/lib/string_helpers.c
+++ b/lib/string_helpers.c
@@ -804,21 +804,16 @@ void kfree_strarray(char **array, size_t n)
 }
 EXPORT_SYMBOL_GPL(kfree_strarray);
 
-struct strarray {
-	char **array __counted_by_ptr(n);
-	size_t n;
-};
-
 static void devm_kfree_strarray(struct device *dev, void *res)
 {
-	struct strarray *array = res;
+	struct kstrarray *array = res;
 
 	kfree_strarray(array->array, array->n);
 }
 
 char **devm_kasprintf_strarray(struct device *dev, const char *prefix, size_t n)
 {
-	struct strarray *ptr;
+	struct kstrarray *ptr;
 
 	ptr = devres_alloc(devm_kfree_strarray, sizeof(*ptr), GFP_KERNEL);
 	if (!ptr)

-- 
2.47.3


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 02/10] lib: string_helpers: implement a CLASS() for string arrays
  2026-11-13 15:47 [PATCH v2 00/10] gpio: make gpiolib-shared more fwnode-centric Bartosz Golaszewski
  2026-11-13 15:47 ` [PATCH v2 01/10] lib: string_helpers: export and rename struct strarray Bartosz Golaszewski
@ 2026-11-13 15:47 ` Bartosz Golaszewski
  2026-11-13 16:09   ` Andy Shevchenko
  2026-11-13 15:47 ` [PATCH v2 03/10] fwnode: define the property_get_names() operation Bartosz Golaszewski
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 18+ messages in thread
From: Bartosz Golaszewski @ 2026-11-13 15:47 UTC (permalink / raw)
  To: Andy Shevchenko, Daniel Scally, Heikki Krogerus, Sakari Ailus,
	Bartosz Golaszewski, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Johan Hovold, Hans Verkuil, Laurent Pinchart,
	Kees Cook, Andy Shevchenko, Len Brown, Rob Herring,
	Saravana Kannan, Linus Walleij, Andrew Morton,
	Gustavo A. R. Silva
  Cc: linux-acpi, driver-core, linux-kernel, linux-hardening,
	devicetree, linux-gpio, Bartosz Golaszewski

Provide a CLASS() for managed arrays of strings. It can be used for
automated release of temporary string arrays when they go out of scope.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
 include/linux/string_helpers.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/include/linux/string_helpers.h b/include/linux/string_helpers.h
index c9f08066439bdd33cc26e2054dbe1ba2e867aee7..4db73bc7d4623cf45954cc8794c5baff6fb23241 100644
--- a/include/linux/string_helpers.h
+++ b/include/linux/string_helpers.h
@@ -3,6 +3,7 @@
 #define _LINUX_STRING_HELPERS_H_
 
 #include <linux/bits.h>
+#include <linux/cleanup.h>
 #include <linux/ctype.h>
 #include <linux/string_choices.h>
 #include <linux/string.h>
@@ -124,6 +125,12 @@ struct kstrarray {
 char **kasprintf_strarray(gfp_t gfp, const char *prefix, size_t n);
 void kfree_strarray(char **array, size_t n);
 
+DEFINE_CLASS(strarray,
+	     struct kstrarray,
+	     kfree_strarray(_T.array, _T.n),
+	     ((struct kstrarray){ .array = array, .n = size }),
+	     char **array, size_t size);
+
 char **devm_kasprintf_strarray(struct device *dev, const char *prefix, size_t n);
 
 #endif

-- 
2.47.3


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 03/10] fwnode: define the property_get_names() operation
  2026-11-13 15:47 [PATCH v2 00/10] gpio: make gpiolib-shared more fwnode-centric Bartosz Golaszewski
  2026-11-13 15:47 ` [PATCH v2 01/10] lib: string_helpers: export and rename struct strarray Bartosz Golaszewski
  2026-11-13 15:47 ` [PATCH v2 02/10] lib: string_helpers: implement a CLASS() for string arrays Bartosz Golaszewski
@ 2026-11-13 15:47 ` Bartosz Golaszewski
  2026-11-13 15:47 ` [PATCH v2 04/10] device property: provide fwnode_property_get_names() Bartosz Golaszewski
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 18+ messages in thread
From: Bartosz Golaszewski @ 2026-11-13 15:47 UTC (permalink / raw)
  To: Andy Shevchenko, Daniel Scally, Heikki Krogerus, Sakari Ailus,
	Bartosz Golaszewski, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Johan Hovold, Hans Verkuil, Laurent Pinchart,
	Kees Cook, Andy Shevchenko, Len Brown, Rob Herring,
	Saravana Kannan, Linus Walleij, Andrew Morton,
	Gustavo A. R. Silva
  Cc: linux-acpi, driver-core, linux-kernel, linux-hardening,
	devicetree, linux-gpio, Bartosz Golaszewski

Define a new fwnode operation allowing to retrieve the list of all
properties of given firmware node in a dynamically allocated array of
strings.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
 include/linux/fwnode.h | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h
index a9dcaf7e70765637a0c33af2ae0ac541e15752ad..2d7e0b9245d445d473c7317bd27058abe5750b40 100644
--- a/include/linux/fwnode.h
+++ b/include/linux/fwnode.h
@@ -125,6 +125,13 @@ struct fwnode_reference_args {
  *			     success, a negative error code otherwise.
  * @property_read_string_array: Read an array of string properties. Return zero
  *				on success, a negative error code otherwise.
+ * @property_get_names: Retrieve the list of all properties of this firmware
+ *			node. On success: returns the number of properties and
+ *			sets *props to an array of NULL-terminated strings that
+ *			must be freed by the user with kfree_strarray(). If
+ *			there are no properties, 0 is returned and the props
+ *			pointer is not changed. Returns negative error number on
+ *			failure.
  * @get_name: Return the name of an fwnode.
  * @get_name_prefix: Get a prefix for a node (for printing purposes).
  * @get_parent: Return the parent of an fwnode.
@@ -162,6 +169,8 @@ struct fwnode_operations {
 	(*property_read_string_array)(const struct fwnode_handle *fwnode_handle,
 				      const char *propname, const char **val,
 				      size_t nval);
+	int (*property_get_names)(const struct fwnode_handle *fwnode,
+				  char ***props);
 	const char *(*get_name)(const struct fwnode_handle *fwnode);
 	const char *(*get_name_prefix)(const struct fwnode_handle *fwnode);
 	struct fwnode_handle *(*get_parent)(const struct fwnode_handle *fwnode);

-- 
2.47.3


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 04/10] device property: provide fwnode_property_get_names()
  2026-11-13 15:47 [PATCH v2 00/10] gpio: make gpiolib-shared more fwnode-centric Bartosz Golaszewski
                   ` (2 preceding siblings ...)
  2026-11-13 15:47 ` [PATCH v2 03/10] fwnode: define the property_get_names() operation Bartosz Golaszewski
@ 2026-11-13 15:47 ` Bartosz Golaszewski
  2026-11-13 16:13   ` Andy Shevchenko
  2026-11-13 15:47 ` [PATCH v2 05/10] of: property: implement the .property_get_names() fwnode operation Bartosz Golaszewski
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 18+ messages in thread
From: Bartosz Golaszewski @ 2026-11-13 15:47 UTC (permalink / raw)
  To: Andy Shevchenko, Daniel Scally, Heikki Krogerus, Sakari Ailus,
	Bartosz Golaszewski, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Johan Hovold, Hans Verkuil, Laurent Pinchart,
	Kees Cook, Andy Shevchenko, Len Brown, Rob Herring,
	Saravana Kannan, Linus Walleij, Andrew Morton,
	Gustavo A. R. Silva
  Cc: linux-acpi, driver-core, linux-kernel, linux-hardening,
	devicetree, linux-gpio, Bartosz Golaszewski

Provide fwnode_property_get_names() - a new fwnode function that allows
callers to retrieve the list of all properties of given firmware node.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
 drivers/base/property.c  | 80 +++++++++++++++++++++++++++++++++++++++++++++++-
 include/linux/property.h |  1 +
 2 files changed, 80 insertions(+), 1 deletion(-)

diff --git a/drivers/base/property.c b/drivers/base/property.c
index 7728116e296872b7ea4d4475aee72d95edf63eb6..d3c54c3d11c42ba4aef68687fc27291c7f33beb6 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -11,11 +11,13 @@
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/export.h>
+#include <linux/minmax.h>
 #include <linux/of.h>
+#include <linux/overflow.h>
 #include <linux/property.h>
 #include <linux/phy.h>
 #include <linux/slab.h>
-#include <linux/string.h>
+#include <linux/string_helpers.h>
 #include <linux/types.h>
 
 struct fwnode_handle *__dev_fwnode(struct device *dev)
@@ -542,6 +544,82 @@ int fwnode_property_match_string(const struct fwnode_handle *fwnode,
 }
 EXPORT_SYMBOL_GPL(fwnode_property_match_string);
 
+/**
+ * fwnode_property_get_names - get the list of all properties of this fwnode
+ * @fwnode: Firmware node to get the list of properties for
+ * @props: Pointer to an array of strings. It will contain the address of the
+ *	   string list containing the property names. Must not be NULL.
+ *
+ * The list also includes the properties of the secondary firmware node, if
+ * any. Properties present in both nodes are listed once with the ones from the
+ * primary node taking precedence.
+ *
+ * Return: Number of property names written into *props. If > 0, the caller must
+ *	   free the array with kfree_strarray(). If the node contains no
+ *	   properties or an error occurred, *props is left untouched.
+ *	   %-EINVAL if arguments are not valid
+ *	   %-ENXIO if no suitable firmware interface is present
+ *	   %-ENOMEM if memory allocation failed
+ */
+int fwnode_property_get_names(const struct fwnode_handle *fwnode, char ***props)
+{
+	int ret1, ret2 = -ENXIO, n1, n2, i, j, count;
+	char **prim = NULL, **sec = NULL, **merged;
+
+	if (IS_ERR_OR_NULL(fwnode) || !props)
+		return -EINVAL;
+
+	ret1 = fwnode_call_int_op(fwnode, property_get_names, &prim);
+	if (!IS_ERR_OR_NULL(fwnode->secondary))
+		ret2 = fwnode_call_int_op(fwnode->secondary, property_get_names, &sec);
+
+	if (ret1 == -ENXIO && ret2 == -ENXIO)
+		return -ENXIO;
+
+	n1 = max(ret1, 0);
+	n2 = max(ret2, 0);
+
+	CLASS(strarray, prim_props)(prim, n1);
+	CLASS(strarray, sec_props)(sec, n2);
+
+	if (ret1 < 0 && ret1 != -ENXIO)
+		return ret1;
+
+	if (ret2 < 0 && ret2 != -ENXIO)
+		return ret2;
+
+	if (n1 == 0 && n2 == 0)
+		return 0;
+
+	merged = kcalloc(size_add(n1, n2), sizeof(*merged), GFP_KERNEL);
+	if (!merged)
+		return -ENOMEM;
+
+	/* The strings are now owned by merged, only free the container. */
+	for (i = 0; i < n1; i++) {
+		merged[i] = prim_props.array[i];
+		prim_props.array[i] = NULL;
+	}
+	count = n1;
+
+	/* Properties from the primary node take precedence. */
+	for (i = 0; i < n2; i++) {
+		for (j = 0; j < n1; j++) {
+			if (!strcmp(merged[j], sec_props.array[i]))
+				break;
+		}
+
+		if (j >= n1) {
+			merged[count++] = sec_props.array[i];
+			sec_props.array[i] = NULL;
+		}
+	}
+
+	*props = merged;
+	return count;
+}
+EXPORT_SYMBOL_GPL(fwnode_property_get_names);
+
 /**
  * fwnode_property_match_property_string - find a property string value in an array and return index
  * @fwnode: Firmware node to get the property of
diff --git a/include/linux/property.h b/include/linux/property.h
index 9143fe4f5c05179e595ba875aafbcb006a740824..a70f3c4c087dd85390951da950c3632f89c6cfd1 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -77,6 +77,7 @@ int fwnode_property_read_string(const struct fwnode_handle *fwnode,
 				const char *propname, const char **val);
 int fwnode_property_match_string(const struct fwnode_handle *fwnode,
 				 const char *propname, const char *string);
+int fwnode_property_get_names(const struct fwnode_handle *fwnode, char ***props);
 
 bool fwnode_device_is_available(const struct fwnode_handle *fwnode);
 

-- 
2.47.3


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 05/10] of: property: implement the .property_get_names() fwnode operation
  2026-11-13 15:47 [PATCH v2 00/10] gpio: make gpiolib-shared more fwnode-centric Bartosz Golaszewski
                   ` (3 preceding siblings ...)
  2026-11-13 15:47 ` [PATCH v2 04/10] device property: provide fwnode_property_get_names() Bartosz Golaszewski
@ 2026-11-13 15:47 ` Bartosz Golaszewski
  2026-11-13 15:47 ` [PATCH v2 06/10] fwnode: define the count_references() " Bartosz Golaszewski
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 18+ messages in thread
From: Bartosz Golaszewski @ 2026-11-13 15:47 UTC (permalink / raw)
  To: Andy Shevchenko, Daniel Scally, Heikki Krogerus, Sakari Ailus,
	Bartosz Golaszewski, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Johan Hovold, Hans Verkuil, Laurent Pinchart,
	Kees Cook, Andy Shevchenko, Len Brown, Rob Herring,
	Saravana Kannan, Linus Walleij, Andrew Morton,
	Gustavo A. R. Silva
  Cc: linux-acpi, driver-core, linux-kernel, linux-hardening,
	devicetree, linux-gpio, Bartosz Golaszewski

Implement the property_get_names() callback from the fwnode interface
for OF nodes.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
 drivers/of/property.c | 34 +++++++++++++++++++++++++++++++++-
 1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/drivers/of/property.c b/drivers/of/property.c
index 45e55f61848801ed497702c6cfe501009904c49d..53f2c84bcb96d3a00f3cd2371010628493d49bc4 100644
--- a/drivers/of/property.c
+++ b/drivers/of/property.c
@@ -27,7 +27,7 @@
 #include <linux/of_device.h>
 #include <linux/of_graph.h>
 #include <linux/of_irq.h>
-#include <linux/string.h>
+#include <linux/string_helpers.h>
 #include <linux/moduleparam.h>
 
 #include "of_private.h"
@@ -1120,6 +1120,37 @@ of_fwnode_property_read_string_array(const struct fwnode_handle *fwnode,
 		of_property_count_strings(node, propname);
 }
 
+static int of_fwnode_property_get_names(const struct fwnode_handle *fwnode,
+					char ***props)
+{
+	const struct device_node *node = to_of_node(fwnode);
+	struct property *prop;
+	int count = 0, i = 0;
+	char **names;
+
+	for_each_property_of_node(node, prop)
+		count++;
+
+	if (count == 0)
+		return 0;
+
+	names = kcalloc(count, sizeof(*names), GFP_KERNEL);
+	if (!names)
+		return -ENOMEM;
+
+	for_each_property_of_node(node, prop) {
+		names[i] = kstrdup(prop->name, GFP_KERNEL);
+		if (!names[i]) {
+			kfree_strarray(names, i);
+			return -ENOMEM;
+		}
+		i++;
+	}
+
+	*props = names;
+	return count;
+}
+
 static const char *of_fwnode_get_name(const struct fwnode_handle *fwnode)
 {
 	return kbasename(to_of_node(fwnode)->full_name);
@@ -1712,6 +1743,7 @@ const struct fwnode_operations of_fwnode_ops = {
 	.property_read_bool = of_fwnode_property_read_bool,
 	.property_read_int_array = of_fwnode_property_read_int_array,
 	.property_read_string_array = of_fwnode_property_read_string_array,
+	.property_get_names = of_fwnode_property_get_names,
 	.get_name = of_fwnode_get_name,
 	.get_name_prefix = of_fwnode_get_name_prefix,
 	.get_parent = of_fwnode_get_parent,

-- 
2.47.3


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 06/10] fwnode: define the count_references() fwnode operation
  2026-11-13 15:47 [PATCH v2 00/10] gpio: make gpiolib-shared more fwnode-centric Bartosz Golaszewski
                   ` (4 preceding siblings ...)
  2026-11-13 15:47 ` [PATCH v2 05/10] of: property: implement the .property_get_names() fwnode operation Bartosz Golaszewski
@ 2026-11-13 15:47 ` Bartosz Golaszewski
  2026-11-13 15:47 ` [PATCH v2 07/10] device property: provide fwnode_property_count_references() Bartosz Golaszewski
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 18+ messages in thread
From: Bartosz Golaszewski @ 2026-11-13 15:47 UTC (permalink / raw)
  To: Andy Shevchenko, Daniel Scally, Heikki Krogerus, Sakari Ailus,
	Bartosz Golaszewski, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Johan Hovold, Hans Verkuil, Laurent Pinchart,
	Kees Cook, Andy Shevchenko, Len Brown, Rob Herring,
	Saravana Kannan, Linus Walleij, Andrew Morton,
	Gustavo A. R. Silva
  Cc: linux-acpi, driver-core, linux-kernel, linux-hardening,
	devicetree, linux-gpio, Bartosz Golaszewski

Add a new fwnode callback allowing to count all references of given
firmware node.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
 include/linux/fwnode.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h
index 2d7e0b9245d445d473c7317bd27058abe5750b40..15acade60564ddb5f5a48f2235b626466d77dbdf 100644
--- a/include/linux/fwnode.h
+++ b/include/linux/fwnode.h
@@ -137,6 +137,10 @@ struct fwnode_reference_args {
  * @get_parent: Return the parent of an fwnode.
  * @get_next_child_node: Return the next child node in an iteration.
  * @get_named_child_node: Return a child node with a given name.
+ * @count_references: Return the number of references in a property, including
+ *		      empty ones. @nargs_prop names the property in the
+ *		      referenced node holding the number of arguments, if NULL
+ *		      the references have no arguments.
  * @get_reference_args: Return a reference pointed to by a property, with args
  * @graph_get_next_endpoint: Return an endpoint node in an iteration.
  * @graph_get_remote_endpoint: Return the remote endpoint node of a local
@@ -180,6 +184,8 @@ struct fwnode_operations {
 	struct fwnode_handle *
 	(*get_named_child_node)(const struct fwnode_handle *fwnode,
 				const char *name);
+	int (*count_references)(const struct fwnode_handle *fwnode,
+				const char *prop, const char *nargs_prop);
 	int (*get_reference_args)(const struct fwnode_handle *fwnode,
 				  const char *prop, const char *nargs_prop,
 				  unsigned int nargs, unsigned int index,

-- 
2.47.3


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 07/10] device property: provide fwnode_property_count_references()
  2026-11-13 15:47 [PATCH v2 00/10] gpio: make gpiolib-shared more fwnode-centric Bartosz Golaszewski
                   ` (5 preceding siblings ...)
  2026-11-13 15:47 ` [PATCH v2 06/10] fwnode: define the count_references() " Bartosz Golaszewski
@ 2026-11-13 15:47 ` Bartosz Golaszewski
  2026-11-13 16:13   ` Andy Shevchenko
  2026-11-13 15:47 ` [PATCH v2 08/10] of: property: implement the count_references() fwnode operation Bartosz Golaszewski
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 18+ messages in thread
From: Bartosz Golaszewski @ 2026-11-13 15:47 UTC (permalink / raw)
  To: Andy Shevchenko, Daniel Scally, Heikki Krogerus, Sakari Ailus,
	Bartosz Golaszewski, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Johan Hovold, Hans Verkuil, Laurent Pinchart,
	Kees Cook, Andy Shevchenko, Len Brown, Rob Herring,
	Saravana Kannan, Linus Walleij, Andrew Morton,
	Gustavo A. R. Silva
  Cc: linux-acpi, driver-core, linux-kernel, linux-hardening,
	devicetree, linux-gpio, Bartosz Golaszewski

Provide fwnode_property_count_references() - a new fwnode function that
allows callers to retrieve the number of references in given property.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
 drivers/base/property.c  | 35 +++++++++++++++++++++++++++++++++++
 include/linux/property.h |  3 +++
 2 files changed, 38 insertions(+)

diff --git a/drivers/base/property.c b/drivers/base/property.c
index d3c54c3d11c42ba4aef68687fc27291c7f33beb6..3cbeb147134143cf68af3213ee75c371af363f2e 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -655,6 +655,41 @@ int fwnode_property_match_property_string(const struct fwnode_handle *fwnode,
 }
 EXPORT_SYMBOL_GPL(fwnode_property_match_property_string);
 
+/**
+ * fwnode_property_count_references() - Count the references in a property
+ * @fwnode:	Firmware node where to look for the property
+ * @prop:	The name of the property
+ * @nargs_prop:	The name of the property telling the number of arguments in the
+ *		referred node. NULL if the references have no arguments.
+ *
+ * Empty references count too, so every index in the range [0, count) can be
+ * passed to fwnode_property_get_reference_args(), which may still fail for
+ * empty entries.
+ *
+ * Return: Number of references on success,
+ *	   %-ENOENT if the property was not found,
+ *	   %-EINVAL on parse error.
+ */
+int fwnode_property_count_references(const struct fwnode_handle *fwnode,
+				     const char *prop, const char *nargs_prop)
+{
+	int ret;
+
+	if (IS_ERR_OR_NULL(fwnode))
+		return -ENOENT;
+
+	ret = fwnode_call_int_op(fwnode, count_references, prop, nargs_prop);
+	if (ret >= 0)
+		return ret;
+
+	if (IS_ERR_OR_NULL(fwnode->secondary))
+		return ret;
+
+	return fwnode_call_int_op(fwnode->secondary, count_references, prop,
+				  nargs_prop);
+}
+EXPORT_SYMBOL_GPL(fwnode_property_count_references);
+
 /**
  * fwnode_property_get_reference_args() - Find a reference with arguments
  * @fwnode:	Firmware node where to look for the reference
diff --git a/include/linux/property.h b/include/linux/property.h
index a70f3c4c087dd85390951da950c3632f89c6cfd1..9f0b9aab5920513cd468572fa96dbe3371609591 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -137,6 +137,9 @@ int device_property_match_property_string(const struct device *dev,
 	return fwnode_property_match_property_string(dev_fwnode(dev), propname, array, n);
 }
 
+int fwnode_property_count_references(const struct fwnode_handle *fwnode,
+				     const char *prop, const char *nargs_prop);
+
 int fwnode_property_get_reference_args(const struct fwnode_handle *fwnode,
 				       const char *prop, const char *nargs_prop,
 				       unsigned int nargs, unsigned int index,

-- 
2.47.3


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 08/10] of: property: implement the count_references() fwnode operation
  2026-11-13 15:47 [PATCH v2 00/10] gpio: make gpiolib-shared more fwnode-centric Bartosz Golaszewski
                   ` (6 preceding siblings ...)
  2026-11-13 15:47 ` [PATCH v2 07/10] device property: provide fwnode_property_count_references() Bartosz Golaszewski
@ 2026-11-13 15:47 ` Bartosz Golaszewski
  2026-11-13 15:47 ` [PATCH v2 09/10] gpio: shared: removed unused field from struct gpio_shared_entry Bartosz Golaszewski
  2026-11-13 15:47 ` [PATCH v2 10/10] gpio: shared: generalize most code to firmware nodes Bartosz Golaszewski
  9 siblings, 0 replies; 18+ messages in thread
From: Bartosz Golaszewski @ 2026-11-13 15:47 UTC (permalink / raw)
  To: Andy Shevchenko, Daniel Scally, Heikki Krogerus, Sakari Ailus,
	Bartosz Golaszewski, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Johan Hovold, Hans Verkuil, Laurent Pinchart,
	Kees Cook, Andy Shevchenko, Len Brown, Rob Herring,
	Saravana Kannan, Linus Walleij, Andrew Morton,
	Gustavo A. R. Silva
  Cc: linux-acpi, driver-core, linux-kernel, linux-hardening,
	devicetree, linux-gpio, Bartosz Golaszewski

Implement the property_count_references() fwnode operation for OF nodes
by wrapping the existing of_count_phandle_with_args().

Acked-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
 drivers/of/property.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/of/property.c b/drivers/of/property.c
index 53f2c84bcb96d3a00f3cd2371010628493d49bc4..c2f5c338b6d1e7f3515be76d21ba6ef097e65e04 100644
--- a/drivers/of/property.c
+++ b/drivers/of/property.c
@@ -1233,6 +1233,12 @@ of_fwnode_get_reference_args(const struct fwnode_handle *fwnode,
 	return 0;
 }
 
+static int of_fwnode_count_references(const struct fwnode_handle *fwnode,
+				      const char *prop, const char *nargs_prop)
+{
+	return of_count_phandle_with_args(to_of_node(fwnode), prop, nargs_prop);
+}
+
 static struct fwnode_handle *
 of_fwnode_graph_get_next_endpoint(const struct fwnode_handle *fwnode,
 				  struct fwnode_handle *prev)
@@ -1749,6 +1755,7 @@ const struct fwnode_operations of_fwnode_ops = {
 	.get_parent = of_fwnode_get_parent,
 	.get_next_child_node = of_fwnode_get_next_child_node,
 	.get_named_child_node = of_fwnode_get_named_child_node,
+	.count_references = of_fwnode_count_references,
 	.get_reference_args = of_fwnode_get_reference_args,
 	.graph_get_next_endpoint = of_fwnode_graph_get_next_endpoint,
 	.graph_get_remote_endpoint = of_fwnode_graph_get_remote_endpoint,

-- 
2.47.3


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 09/10] gpio: shared: removed unused field from struct gpio_shared_entry
  2026-11-13 15:47 [PATCH v2 00/10] gpio: make gpiolib-shared more fwnode-centric Bartosz Golaszewski
                   ` (7 preceding siblings ...)
  2026-11-13 15:47 ` [PATCH v2 08/10] of: property: implement the count_references() fwnode operation Bartosz Golaszewski
@ 2026-11-13 15:47 ` Bartosz Golaszewski
  2026-11-13 16:14   ` Andy Shevchenko
  2026-11-13 15:47 ` [PATCH v2 10/10] gpio: shared: generalize most code to firmware nodes Bartosz Golaszewski
  9 siblings, 1 reply; 18+ messages in thread
From: Bartosz Golaszewski @ 2026-11-13 15:47 UTC (permalink / raw)
  To: Andy Shevchenko, Daniel Scally, Heikki Krogerus, Sakari Ailus,
	Bartosz Golaszewski, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Johan Hovold, Hans Verkuil, Laurent Pinchart,
	Kees Cook, Andy Shevchenko, Len Brown, Rob Herring,
	Saravana Kannan, Linus Walleij, Andrew Morton,
	Gustavo A. R. Silva
  Cc: linux-acpi, driver-core, linux-kernel, linux-hardening,
	devicetree, linux-gpio, Bartosz Golaszewski

The index field in struct gpio_shared_entry is an unused leftover.
Remove it.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
 drivers/gpio/gpiolib-shared.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/gpio/gpiolib-shared.c b/drivers/gpio/gpiolib-shared.c
index edb04a5bb987e12faf96e5b70198a9fabf60ad0a..44af3bc1494e47310973844a0ef19ac3ec5cd719 100644
--- a/drivers/gpio/gpiolib-shared.c
+++ b/drivers/gpio/gpiolib-shared.c
@@ -51,8 +51,6 @@ struct gpio_shared_entry {
 	struct fwnode_handle *fwnode;
 	/* Hardware offset of the GPIO within its chip. */
 	unsigned int offset;
-	/* Index in the property value array. */
-	size_t index;
 	/* Synchronizes the modification of shared_desc and offset. */
 	struct mutex lock;
 	struct gpio_shared_desc *shared_desc;
@@ -233,7 +231,6 @@ static int gpio_shared_of_traverse(struct device_node *curr)
 
 				entry->fwnode = fwnode_handle_get(fwnode);
 				entry->offset = offset;
-				entry->index = count;
 				INIT_LIST_HEAD(&entry->refs);
 				mutex_init(&entry->lock);
 

-- 
2.47.3


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 10/10] gpio: shared: generalize most code to firmware nodes
  2026-11-13 15:47 [PATCH v2 00/10] gpio: make gpiolib-shared more fwnode-centric Bartosz Golaszewski
                   ` (8 preceding siblings ...)
  2026-11-13 15:47 ` [PATCH v2 09/10] gpio: shared: removed unused field from struct gpio_shared_entry Bartosz Golaszewski
@ 2026-11-13 15:47 ` Bartosz Golaszewski
  2026-11-13 15:57   ` sashiko-bot
  2026-11-13 16:19   ` Andy Shevchenko
  9 siblings, 2 replies; 18+ messages in thread
From: Bartosz Golaszewski @ 2026-11-13 15:47 UTC (permalink / raw)
  To: Andy Shevchenko, Daniel Scally, Heikki Krogerus, Sakari Ailus,
	Bartosz Golaszewski, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Johan Hovold, Hans Verkuil, Laurent Pinchart,
	Kees Cook, Andy Shevchenko, Len Brown, Rob Herring,
	Saravana Kannan, Linus Walleij, Andrew Morton,
	Gustavo A. R. Silva
  Cc: linux-acpi, driver-core, linux-kernel, linux-hardening,
	devicetree, linux-gpio, Bartosz Golaszewski

Ahead of adding support for sharing of GPIOs for other types of firmware
nodes, convert as much code in gpiolib-shared.c as possible to using
fwnode APIs and guard the remaining OF-specific bits with CONFIG_OF
guards.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
 drivers/gpio/gpiolib-shared.c | 239 ++++++++++++++++++++++--------------------
 1 file changed, 128 insertions(+), 111 deletions(-)

diff --git a/drivers/gpio/gpiolib-shared.c b/drivers/gpio/gpiolib-shared.c
index 44af3bc1494e47310973844a0ef19ac3ec5cd719..edd61d16f065f4e4f2c440ef0529a2365d0bda44 100644
--- a/drivers/gpio/gpiolib-shared.c
+++ b/drivers/gpio/gpiolib-shared.c
@@ -22,7 +22,7 @@
 #include <linux/printk.h>
 #include <linux/property.h>
 #include <linux/slab.h>
-#include <linux/string.h>
+#include <linux/string_helpers.h>
 
 #include "gpiolib.h"
 #include "gpiolib-shared.h"
@@ -61,7 +61,6 @@ struct gpio_shared_entry {
 static LIST_HEAD(gpio_shared_list);
 static DEFINE_IDA(gpio_shared_ida);
 
-#if IS_ENABLED(CONFIG_OF)
 static struct gpio_shared_entry *
 gpio_shared_find_entry(struct fwnode_handle *controller_node,
 		       unsigned int offset)
@@ -131,157 +130,159 @@ static int gpio_shared_setup_reset_proxy(struct gpio_shared_entry *entry,
 }
 
 /* Handle all special nodes that we should ignore. */
-static bool gpio_shared_of_node_ignore(struct device_node *node)
+static bool gpio_shared_fwnode_ignore(struct fwnode_handle *fwnode)
 {
 	/* Ignore disabled devices. */
-	if (!of_device_is_available(node))
+	if (!fwnode_device_is_available(fwnode))
 		return true;
 
 	/*
-	 * __symbols__ is a special, internal node and should not be considered
-	 * when scanning for shared GPIOs.
+	 * On OF-systems __symbols__ is a special, internal node and should not
+	 * be considered when scanning for shared GPIOs.
 	 */
-	if (of_node_name_eq(node, "__symbols__"))
+	if (fwnode_name_eq(fwnode, "__symbols__"))
 		return true;
 
 	/*
 	 * GPIO hogs have a "gpios" property which is not a phandle and can't
 	 * possibly refer to a shared GPIO.
 	 */
-	if (of_property_present(node, "gpio-hog"))
+	if (fwnode_property_present(fwnode, "gpio-hog"))
 		return true;
 
 	return false;
 }
 
-static int gpio_shared_of_traverse(struct device_node *curr)
+static int gpio_shared_fwnode_scan_property(struct fwnode_handle *curr,
+					    const char *propname)
 {
+	struct fwnode_reference_args args;
 	struct gpio_shared_entry *entry;
 	size_t con_id_len, suffix_len;
-	struct fwnode_handle *fwnode;
-	struct of_phandle_args args;
 	struct gpio_shared_ref *ref;
-	struct property *prop;
 	unsigned int offset;
 	const char *suffix;
-	int ret, count, i;
+	int ret, i, count;
 
-	if (gpio_shared_of_node_ignore(curr))
+	/*
+	 * The standard name for a GPIO property is "foo-gpios"
+	 * or "foo-gpio". Some bindings also use "gpios" or "gpio".
+	 * There are some legacy device-trees which have a different
+	 * naming convention and for which we have rename quirks in
+	 * place in gpiolib-of.c. I don't think any of them require
+	 * support for shared GPIOs so for now let's just ignore
+	 * them. We can always just export the quirk list and
+	 * iterate over it here.
+	 */
+	if (!strends(propname, "-gpios") && !strends(propname, "-gpio") &&
+	    strcmp(propname, "gpios") != 0 && strcmp(propname, "gpio") != 0)
 		return 0;
 
-	for_each_property_of_node(curr, prop) {
-		/*
-		 * The standard name for a GPIO property is "foo-gpios"
-		 * or "foo-gpio". Some bindings also use "gpios" or "gpio".
-		 * There are some legacy device-trees which have a different
-		 * naming convention and for which we have rename quirks in
-		 * place in gpiolib-of.c. I don't think any of them require
-		 * support for shared GPIOs so for now let's just ignore
-		 * them. We can always just export the quirk list and
-		 * iterate over it here.
-		 */
-		if (!strends(prop->name, "-gpios") &&
-		    !strends(prop->name, "-gpio") &&
-		    strcmp(prop->name, "gpios") != 0 &&
-		    strcmp(prop->name, "gpio") != 0)
-			continue;
-
-		count = of_count_phandle_with_args(curr, prop->name,
-						   "#gpio-cells");
-		if (count <= 0)
-			continue;
+	count = fwnode_property_count_references(curr, propname, "#gpio-cells");
+	if (count <= 0)
+		return 0;
 
-		for (i = 0; i < count; i++) {
-			struct device_node *np __free(device_node) = NULL;
-			char *con_id __free(kfree) = NULL;
+	for (i = 0; i < count; i++) {
+		struct fwnode_handle *fwnode __free(fwnode_handle) = NULL;
+		char *con_id __free(kfree) = NULL;
 
-			ret = of_parse_phandle_with_args(curr, prop->name,
-							 "#gpio-cells", i,
+		ret = fwnode_property_get_reference_args(curr, propname,
+							 "#gpio-cells", 0, i,
 							 &args);
-			if (ret)
-				continue;
+		if (ret)
+			continue;
 
-			np = args.np;
+		fwnode = args.fwnode;
 
-			if (!of_property_present(np, "gpio-controller"))
-				continue;
+		if (!fwnode_property_present(fwnode, "gpio-controller"))
+			continue;
 
-			/*
-			 * We support 1, 2 and 3 cell GPIO bindings in the
-			 * kernel currently. There's only one old MIPS dts that
-			 * has a one-cell binding but there's no associated
-			 * consumer so it may as well be an error. There don't
-			 * seem to be any 3-cell users of non-exclusive GPIOs,
-			 * so we can skip this as well. Let's occupy ourselves
-			 * with the predominant 2-cell binding with the first
-			 * cell indicating the hardware offset of the GPIO and
-			 * the second defining the GPIO flags of the request.
-			 */
-			if (args.args_count != 2)
-				continue;
+		/*
+		 * We support 1, 2 and 3 cell GPIO bindings in the
+		 * kernel currently. There's only one old MIPS dts that
+		 * has a one-cell binding but there's no associated
+		 * consumer so it may as well be an error. There don't
+		 * seem to be any 3-cell users of non-exclusive GPIOs,
+		 * so we can skip this as well. Let's occupy ourselves
+		 * with the predominant 2-cell binding with the first
+		 * cell indicating the hardware offset of the GPIO and
+		 * the second defining the GPIO flags of the request.
+		 */
+		if (args.nargs != 2)
+			continue;
 
-			fwnode = of_fwnode_handle(args.np);
-			offset = args.args[0];
+		offset = args.args[0];
 
-			entry = gpio_shared_find_entry(fwnode, offset);
-			if (!entry) {
-				entry = kzalloc_obj(*entry);
-				if (!entry)
-					return -ENOMEM;
+		entry = gpio_shared_find_entry(fwnode, offset);
+		if (!entry) {
+			entry = kzalloc_obj(*entry);
+			if (!entry)
+				return -ENOMEM;
 
-				entry->fwnode = fwnode_handle_get(fwnode);
-				entry->offset = offset;
-				INIT_LIST_HEAD(&entry->refs);
-				mutex_init(&entry->lock);
+			entry->fwnode = fwnode_handle_get(fwnode);
+			entry->offset = offset;
+			INIT_LIST_HEAD(&entry->refs);
+			mutex_init(&entry->lock);
 
-				list_add_tail(&entry->list, &gpio_shared_list);
-			}
+			list_add_tail(&entry->list, &gpio_shared_list);
+		}
 
-			if (strends(prop->name, "gpios"))
-				suffix = "-gpios";
-			else if (strends(prop->name, "gpio"))
-				suffix = "-gpio";
-			else
-				suffix = NULL;
-			if (!suffix)
-				continue;
+		if (strends(propname, "gpios"))
+			suffix = "-gpios";
+		else if (strends(propname, "gpio"))
+			suffix = "-gpio";
+		else
+			suffix = NULL;
+		if (!suffix)
+			continue;
 
-			/* We only set con_id if there's actually one. */
-			if (strcmp(prop->name, "gpios") && strcmp(prop->name, "gpio")) {
-				con_id = kstrdup(prop->name, GFP_KERNEL);
-				if (!con_id)
-					return -ENOMEM;
+		/* We only set con_id if there's actually one. */
+		if (strcmp(propname, "gpios") && strcmp(propname, "gpio")) {
+			con_id = kstrdup(propname, GFP_KERNEL);
+			if (!con_id)
+				return -ENOMEM;
 
-				con_id_len = strlen(con_id);
-				suffix_len = strlen(suffix);
+			con_id_len = strlen(con_id);
+			suffix_len = strlen(suffix);
 
-				con_id[con_id_len - suffix_len] = '\0';
-			}
+			con_id[con_id_len - suffix_len] = '\0';
+		}
 
-			struct fwnode_handle *curr_fwnode =
-				fwnode_handle_get(of_fwnode_handle(curr));
-			ref = gpio_shared_make_ref(curr_fwnode, con_id, args.args[1]);
-			if (!ref) {
-				fwnode_handle_put(curr_fwnode);
-				return -ENOMEM;
-			}
+		ref = gpio_shared_make_ref(fwnode_handle_get(curr), con_id, args.args[1]);
+		if (!ref) {
+			fwnode_handle_put(curr);
+			return -ENOMEM;
+		}
 
-			if (!list_empty(&entry->refs))
-				pr_debug("GPIO %u at %s is shared by multiple firmware nodes\n",
-					 entry->offset, fwnode_get_name(entry->fwnode));
+		if (!list_empty(&entry->refs))
+			pr_debug("GPIO %u at %s is shared by multiple firmware nodes\n",
+				 entry->offset, fwnode_get_name(entry->fwnode));
 
-			list_add_tail(&ref->list, &entry->refs);
+		list_add_tail(&ref->list, &entry->refs);
 
-			if (strcmp(prop->name, "reset-gpios") == 0) {
-				ret = gpio_shared_setup_reset_proxy(entry, args.args[1]);
-				if (ret)
-					return ret;
-			}
+		if (strcmp(propname, "reset-gpios") == 0) {
+			ret = gpio_shared_setup_reset_proxy(entry, args.args[1]);
+			if (ret)
+				return ret;
 		}
 	}
 
-	for_each_child_of_node_scoped(curr, child) {
-		ret = gpio_shared_of_traverse(child);
+	return 0;
+}
+
+static int gpio_shared_fwnode_scan_properties(struct fwnode_handle *curr)
+{
+	char **props;
+	int ret, i;
+
+	ret = fwnode_property_get_names(curr, &props);
+	if (ret <= 0)
+		return ret;
+
+	CLASS(strarray, names)(props, ret);
+
+	for (i = 0; i < names.n; i++) {
+		ret = gpio_shared_fwnode_scan_property(curr, names.array[i]);
 		if (ret)
 			return ret;
 	}
@@ -289,19 +290,35 @@ static int gpio_shared_of_traverse(struct device_node *curr)
 	return 0;
 }
 
-static int gpio_shared_of_scan(void)
+static __maybe_unused int gpio_shared_fwnode_traverse(struct fwnode_handle *curr)
 {
-	if (of_root)
-		return gpio_shared_of_traverse(of_root);
+	int ret;
+
+	if (gpio_shared_fwnode_ignore(curr))
+		return 0;
+
+	ret = gpio_shared_fwnode_scan_properties(curr);
+	if (ret)
+		return ret;
+
+	fwnode_for_each_child_node_scoped(curr, child) {
+		ret = gpio_shared_fwnode_traverse(child);
+		if (ret)
+			return ret;
+	}
 
 	return 0;
 }
-#else
+
 static int gpio_shared_of_scan(void)
 {
+#if IS_ENABLED(CONFIG_OF)
+	if (of_root)
+		return gpio_shared_fwnode_traverse(of_fwnode_handle(of_root));
+#endif
+
 	return 0;
 }
-#endif /* CONFIG_OF */
 
 static void gpio_shared_adev_release(struct device *dev)
 {

-- 
2.47.3


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH v2 10/10] gpio: shared: generalize most code to firmware nodes
  2026-11-13 15:47 ` [PATCH v2 10/10] gpio: shared: generalize most code to firmware nodes Bartosz Golaszewski
@ 2026-11-13 15:57   ` sashiko-bot
  2026-11-13 16:19   ` Andy Shevchenko
  1 sibling, 0 replies; 18+ messages in thread
From: sashiko-bot @ 2026-11-13 15:57 UTC (permalink / raw)
  To: Bartosz Golaszewski; +Cc: devicetree, linux-gpio, robh, conor+dt

Thank you for your contribution! Sashiko AI review found 1 potential
issue to consider:
- [Low] gpio: shared: define __free() fwnode in one statement in
  scan_property()
--

commit 78d07ba961e7635e708d83665d68a4604d21cd5c
Author: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>

gpio: shared: generalize most code to firmware nodes

This commit converts the device-tree scanning code in gpiolib-shared.c to
use generic fwnode APIs and guards the remaining OF-specific entry point
with CONFIG_OF.

> diff --git a/drivers/gpio/gpiolib-shared.c b/drivers/gpio/gpiolib-shared.c
> index 44af3bc1494e4..edd61d16f065f 100644
> --- a/drivers/gpio/gpiolib-shared.c
> +++ b/drivers/gpio/gpiolib-shared.c

[ ... ]

> @@ -131,157 +130,159 @@ static int gpio_shared_setup_reset_proxy(struct gpio_shared_entry *entry,

[ ... ]

> +	for (i = 0; i < count; i++) {
> +		struct fwnode_handle *fwnode __free(fwnode_handle) = NULL;
> +		char *con_id __free(kfree) = NULL;
>  
> -			ret = of_parse_phandle_with_args(curr, prop->name,
> -							 "#gpio-cells", i,
> +		ret = fwnode_property_get_reference_args(curr, propname,
> +							 "#gpio-cells", 0, i,
>  							 &args);
> -			if (ret)
> -				continue;
> +		if (ret)
> +			continue;
>  
> -			np = args.np;
> +		fwnode = args.fwnode;

[Severity: Low]
This isn't a bug, but fwnode is not used before
fwnode_property_get_reference_args() succeeds, so it can be defined and
initialized in a single statement as:

	struct fwnode_handle *fwnode __free(fwnode_handle) = args.fwnode;

rather than being initialized to NULL at the top of the loop body and
assigned later.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261113-fwnode-for-each-prop-v2-0-4edc23d5cf50@oss.qualcomm.com?part=10

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v2 01/10] lib: string_helpers: export and rename struct strarray
  2026-11-13 15:47 ` [PATCH v2 01/10] lib: string_helpers: export and rename struct strarray Bartosz Golaszewski
@ 2026-11-13 16:09   ` Andy Shevchenko
  0 siblings, 0 replies; 18+ messages in thread
From: Andy Shevchenko @ 2026-11-13 16:09 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Daniel Scally, Heikki Krogerus, Sakari Ailus, Bartosz Golaszewski,
	Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
	Johan Hovold, Hans Verkuil, Laurent Pinchart, Kees Cook,
	Andy Shevchenko, Len Brown, Rob Herring, Saravana Kannan,
	Linus Walleij, Andrew Morton, Gustavo A. R. Silva, linux-acpi,
	driver-core, linux-kernel, linux-hardening, devicetree,
	linux-gpio

On Fri, Nov 13, 2026 at 04:47:01PM +0100, Bartosz Golaszewski wrote:
> Ahead of introducing a CLASS() for string arrays, make the existing
> struct strarray public in linux/string_helpers.h. Rename it to kstrarray
> to avoid any potential conflicts in the future and make it clear, it's a
> kernel type.

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v2 02/10] lib: string_helpers: implement a CLASS() for string arrays
  2026-11-13 15:47 ` [PATCH v2 02/10] lib: string_helpers: implement a CLASS() for string arrays Bartosz Golaszewski
@ 2026-11-13 16:09   ` Andy Shevchenko
  0 siblings, 0 replies; 18+ messages in thread
From: Andy Shevchenko @ 2026-11-13 16:09 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Daniel Scally, Heikki Krogerus, Sakari Ailus, Bartosz Golaszewski,
	Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
	Johan Hovold, Hans Verkuil, Laurent Pinchart, Kees Cook,
	Andy Shevchenko, Len Brown, Rob Herring, Saravana Kannan,
	Linus Walleij, Andrew Morton, Gustavo A. R. Silva, linux-acpi,
	driver-core, linux-kernel, linux-hardening, devicetree,
	linux-gpio

On Fri, Nov 13, 2026 at 04:47:02PM +0100, Bartosz Golaszewski wrote:
> Provide a CLASS() for managed arrays of strings. It can be used for
> automated release of temporary string arrays when they go out of scope.

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v2 07/10] device property: provide fwnode_property_count_references()
  2026-11-13 15:47 ` [PATCH v2 07/10] device property: provide fwnode_property_count_references() Bartosz Golaszewski
@ 2026-11-13 16:13   ` Andy Shevchenko
  0 siblings, 0 replies; 18+ messages in thread
From: Andy Shevchenko @ 2026-11-13 16:13 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Daniel Scally, Heikki Krogerus, Sakari Ailus, Bartosz Golaszewski,
	Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
	Johan Hovold, Hans Verkuil, Laurent Pinchart, Kees Cook,
	Andy Shevchenko, Len Brown, Rob Herring, Saravana Kannan,
	Linus Walleij, Andrew Morton, Gustavo A. R. Silva, linux-acpi,
	driver-core, linux-kernel, linux-hardening, devicetree,
	linux-gpio

On Fri, Nov 13, 2026 at 04:47:07PM +0100, Bartosz Golaszewski wrote:
> Provide fwnode_property_count_references() - a new fwnode function that
> allows callers to retrieve the number of references in given property.

I don't understand why we have this patch separated from previous one?

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v2 04/10] device property: provide fwnode_property_get_names()
  2026-11-13 15:47 ` [PATCH v2 04/10] device property: provide fwnode_property_get_names() Bartosz Golaszewski
@ 2026-11-13 16:13   ` Andy Shevchenko
  0 siblings, 0 replies; 18+ messages in thread
From: Andy Shevchenko @ 2026-11-13 16:13 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Daniel Scally, Heikki Krogerus, Sakari Ailus, Bartosz Golaszewski,
	Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
	Johan Hovold, Hans Verkuil, Laurent Pinchart, Kees Cook,
	Andy Shevchenko, Len Brown, Rob Herring, Saravana Kannan,
	Linus Walleij, Andrew Morton, Gustavo A. R. Silva, linux-acpi,
	driver-core, linux-kernel, linux-hardening, devicetree,
	linux-gpio

On Fri, Nov 13, 2026 at 04:47:04PM +0100, Bartosz Golaszewski wrote:
> Provide fwnode_property_get_names() - a new fwnode function that allows
> callers to retrieve the list of all properties of given firmware node.

I don't understand why we have this patch separated from previous one?

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v2 09/10] gpio: shared: removed unused field from struct gpio_shared_entry
  2026-11-13 15:47 ` [PATCH v2 09/10] gpio: shared: removed unused field from struct gpio_shared_entry Bartosz Golaszewski
@ 2026-11-13 16:14   ` Andy Shevchenko
  0 siblings, 0 replies; 18+ messages in thread
From: Andy Shevchenko @ 2026-11-13 16:14 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Daniel Scally, Heikki Krogerus, Sakari Ailus, Bartosz Golaszewski,
	Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
	Johan Hovold, Hans Verkuil, Laurent Pinchart, Kees Cook,
	Andy Shevchenko, Len Brown, Rob Herring, Saravana Kannan,
	Linus Walleij, Andrew Morton, Gustavo A. R. Silva, linux-acpi,
	driver-core, linux-kernel, linux-hardening, devicetree,
	linux-gpio

On Fri, Nov 13, 2026 at 04:47:09PM +0100, Bartosz Golaszewski wrote:
> The index field in struct gpio_shared_entry is an unused leftover.
> Remove it.

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v2 10/10] gpio: shared: generalize most code to firmware nodes
  2026-11-13 15:47 ` [PATCH v2 10/10] gpio: shared: generalize most code to firmware nodes Bartosz Golaszewski
  2026-11-13 15:57   ` sashiko-bot
@ 2026-11-13 16:19   ` Andy Shevchenko
  1 sibling, 0 replies; 18+ messages in thread
From: Andy Shevchenko @ 2026-11-13 16:19 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Daniel Scally, Heikki Krogerus, Sakari Ailus, Bartosz Golaszewski,
	Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
	Johan Hovold, Hans Verkuil, Laurent Pinchart, Kees Cook,
	Andy Shevchenko, Len Brown, Rob Herring, Saravana Kannan,
	Linus Walleij, Andrew Morton, Gustavo A. R. Silva, linux-acpi,
	driver-core, linux-kernel, linux-hardening, devicetree,
	linux-gpio

On Fri, Nov 13, 2026 at 04:47:10PM +0100, Bartosz Golaszewski wrote:
> Ahead of adding support for sharing of GPIOs for other types of firmware
> nodes, convert as much code in gpiolib-shared.c as possible to using
> fwnode APIs and guard the remaining OF-specific bits with CONFIG_OF
> guards.

...

> -static int gpio_shared_of_scan(void)
> +static __maybe_unused int gpio_shared_fwnode_traverse(struct fwnode_handle *curr)
>  {
> -	if (of_root)
> -		return gpio_shared_of_traverse(of_root);
> +	int ret;
> +
> +	if (gpio_shared_fwnode_ignore(curr))
> +		return 0;
> +
> +	ret = gpio_shared_fwnode_scan_properties(curr);
> +	if (ret)
> +		return ret;
> +
> +	fwnode_for_each_child_node_scoped(curr, child) {
> +		ret = gpio_shared_fwnode_traverse(child);
> +		if (ret)
> +			return ret;
> +	}
>  
>  	return 0;
>  }
> -#else
> +
>  static int gpio_shared_of_scan(void)
>  {
> +#if IS_ENABLED(CONFIG_OF)
> +	if (of_root)
> +		return gpio_shared_fwnode_traverse(of_fwnode_handle(of_root));
> +#endif
> +
>  	return 0;
>  }
> -#endif /* CONFIG_OF */

Hmm... What do you exactly get from the compiler without this uglyfication?

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2026-11-13 16:19 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-13 15:47 [PATCH v2 00/10] gpio: make gpiolib-shared more fwnode-centric Bartosz Golaszewski
2026-11-13 15:47 ` [PATCH v2 01/10] lib: string_helpers: export and rename struct strarray Bartosz Golaszewski
2026-11-13 16:09   ` Andy Shevchenko
2026-11-13 15:47 ` [PATCH v2 02/10] lib: string_helpers: implement a CLASS() for string arrays Bartosz Golaszewski
2026-11-13 16:09   ` Andy Shevchenko
2026-11-13 15:47 ` [PATCH v2 03/10] fwnode: define the property_get_names() operation Bartosz Golaszewski
2026-11-13 15:47 ` [PATCH v2 04/10] device property: provide fwnode_property_get_names() Bartosz Golaszewski
2026-11-13 16:13   ` Andy Shevchenko
2026-11-13 15:47 ` [PATCH v2 05/10] of: property: implement the .property_get_names() fwnode operation Bartosz Golaszewski
2026-11-13 15:47 ` [PATCH v2 06/10] fwnode: define the count_references() " Bartosz Golaszewski
2026-11-13 15:47 ` [PATCH v2 07/10] device property: provide fwnode_property_count_references() Bartosz Golaszewski
2026-11-13 16:13   ` Andy Shevchenko
2026-11-13 15:47 ` [PATCH v2 08/10] of: property: implement the count_references() fwnode operation Bartosz Golaszewski
2026-11-13 15:47 ` [PATCH v2 09/10] gpio: shared: removed unused field from struct gpio_shared_entry Bartosz Golaszewski
2026-11-13 16:14   ` Andy Shevchenko
2026-11-13 15:47 ` [PATCH v2 10/10] gpio: shared: generalize most code to firmware nodes Bartosz Golaszewski
2026-11-13 15:57   ` sashiko-bot
2026-11-13 16:19   ` Andy Shevchenko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox