linux-doc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Documentation: gpio: add documentation about using software nodes
@ 2025-08-11 21:30 Dmitry Torokhov
  2025-08-12  0:46 ` Randy Dunlap
  2025-08-19 11:35 ` Linus Walleij
  0 siblings, 2 replies; 7+ messages in thread
From: Dmitry Torokhov @ 2025-08-11 21:30 UTC (permalink / raw)
  To: Linus Walleij, Bartosz Golaszewski, Jonathan Corbet
  Cc: Andy Shevchenko, Arnd Bergmann, Hans de Goede, linux-gpio,
	linux-doc, linux-kernel

Introduce documentation regarding use of software nodes to describe
GPIOs on legacy boards that have not been converted to device tree.

Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
 Documentation/driver-api/gpio/board.rst       |  64 ++++
 Documentation/driver-api/gpio/index.rst       |   1 +
 .../driver-api/gpio/legacy-boards.rst         | 298 ++++++++++++++++++
 3 files changed, 363 insertions(+)

diff --git a/Documentation/driver-api/gpio/board.rst b/Documentation/driver-api/gpio/board.rst
index 4fd1cbd8296e..0cf64e1f2623 100644
--- a/Documentation/driver-api/gpio/board.rst
+++ b/Documentation/driver-api/gpio/board.rst
@@ -94,6 +94,70 @@ with the help of _DSD (Device Specific Data), introduced in ACPI 5.1::
 For more information about the ACPI GPIO bindings see
 Documentation/firmware-guide/acpi/gpio-properties.rst.
 
+Software Nodes
+--------------
+Software nodes allows to construct an in-memory, device-tree-like structure
+using ``struct software_node`` and ``struct property_entry``. This structure
+can then be associated with a platform device, allowing drivers to use the
+standard device properties API to query configuration, just as they would on an
+ACPI or device tree systems.
+
+Software-node-backed GPIOs are described using ``PROPERTY_ENTRY_GPIO()``
+macro, which ties a sotfware node representing GPIO controller with consumer
+device. It allows consumers to use regular gpiolib APIs, such as ``gpiod_get()``,
+``gpiod_get_optional()``.
+
+The software node representing GPIO controller need not be attached to the
+GPIO controller device. The only requirement that the node must be registered
+and its name much match the GPIO controller's label.
+
+For example, here is how to describe a single GPIO-connected LED. This is an
+alternative to using platform_data on legacy systems.
+
+.. code-block:: c
+
+	#include <linux/property.h>
+	#include <linux/gpio/machine.h>
+	#include <linux/gpio/property.h>
+
+	/*
+	 * 1. Define a node for the GPIO controller. Its .name must match the
+	 *    controller's label.
+	 */
+	static const struct software_node gpio_controller_node = {
+		.name = "gpio-foo",
+	};
+
+	/* 2. Define the properties for the LED device. */
+	static const struct property_entry led_device_props[] = {
+		PROPERTY_ENTRY_STRING("label", "myboard:green:status"),
+		PROPERTY_ENTRY_STRING("linux,default-trigger", "heartbeat"),
+		PROPERTY_ENTRY_GPIO("gpios", &gpio_controller_node, 42, GPIO_ACTIVE_HIGH),
+		{ }
+	};
+
+	/* 3. Define the software node for the LED device. */
+	static const struct software_node led_device_swnode = {
+		.name = "status-led",
+		.properties = led_device_props,
+	};
+
+	/*
+	 * 4. Register the software nodes and the platform device.
+	 */
+	const struct software_node *swnodes[] = {
+		&gpio_controller_node,
+		&led_device_swnode,
+		NULL
+	};
+	software_node_register_node_group(swnodes);
+
+	// Then register a platform_device for "leds-gpio" and associate
+	// it with &led_device_swnode via .fwnode.
+
+For a complete guide on converting board files to use software nodes, see
+Documentation/driver-api/gpio/legacy-boards.rst.
+
 Platform Data
 -------------
 Finally, GPIOs can be bound to devices and functions using platform data. Board
diff --git a/Documentation/driver-api/gpio/index.rst b/Documentation/driver-api/gpio/index.rst
index 43f6a3afe10b..87929840e85a 100644
--- a/Documentation/driver-api/gpio/index.rst
+++ b/Documentation/driver-api/gpio/index.rst
@@ -12,6 +12,7 @@ Contents:
    driver
    consumer
    board
+   legacy-boards
    drivers-on-gpio
    bt8xxgpio
 
diff --git a/Documentation/driver-api/gpio/legacy-boards.rst b/Documentation/driver-api/gpio/legacy-boards.rst
new file mode 100644
index 000000000000..6700a2549220
--- /dev/null
+++ b/Documentation/driver-api/gpio/legacy-boards.rst
@@ -0,0 +1,298 @@
+Supporting Legacy Boards
+========================
+
+Many drivers in the kernel, such as ``leds-gpio`` and ``gpio-keys``, are
+migrating away from using board-specific ``platform_data`` to a unified device
+properties interface. This interface allows drivers to be simpler and more
+generic, as they can query properties in a standardized way.
+
+On modern systems, these properties are provided via device tree. However, some
+older platforms have not been converted to device tree and instead rely on
+board files to describe their hardware configuration. To bridge this gap and
+allow these legacy boards to work with modern, generic drivers, the kernel
+provides a mechanism called **software nodes**.
+
+This document provides a guide on how to convert a legacy board file from using
+``platform_data`` and ``gpiod_lookup_table`` to the modern software node
+approach for describing GPIO-connected devices.
+
+The Core Idea: Software Nodes
+-----------------------------
+
+Software nodes allows to construct an in-memory, device-tree-like structure
+using ``struct software_node`` and ``struct property_entry``. This structure
+can then be associated with a platform device, allowing drivers to use the
+standard device properties API (e.g., ``device_property_read_u32()``,
+``device_property_read_string()``) to query configuration, just as they would
+on an ACPI or device tree systems.
+
+The gpiolib code has support for handling software nodes, so that if GPIO is
+described properly, as detailed in the section below, then regular gpiolib APIs,
+such as ``gpiod_get()``, ``gpiod_get_optional()`` and others will work.
+
+Requirements for GPIO Properties
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When using software nodes to describe GPIO connections, the following
+requirements must be met for the GPIO core to correctly resolve the reference:
+
+1.  **The GPIO controller's software node ``name`` must match the controller's
+    ``label``.** The gpiolib core uses this name to find the corresponding
+    ``struct gpio_chip`` at runtime.
+    This software node has to be registered, but need not be attached to the
+    device representing GPIO controller that is providing GPIO in question.
+    It may be left as a "free floating" node.
+
+2.  **The GPIO property must be a reference.** The ``PROPERTY_ENTRY_GPIO()``
+    macro handles this as it is an alias for ``PROPERTY_ENTRY_REF()``.
+
+3.  **The reference must have exactly two arguments:**
+
+    - The first argument is the GPIO offset within the controller.
+    - The second argument is the flags for the GPIO line (e.g.,
+      ``GPIO_ACTIVE_HIGH``, ``GPIO_ACTIVE_LOW``).
+
+The ``PROPERTY_ENTRY_GPIO()`` macro is the preferred way of defining GPIO
+properties in software nodes.
+
+Conversion Example
+------------------
+
+Let's walk through an example of converting a board file that defines a GPIO-
+connected LED and a button.
+
+Before: Using Platform Data
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A typical legacy board file might look like this:
+
+.. code-block:: c
+
+  #include <linux/platform_device.h>
+  #include <linux/leds.h>
+  #include <linux/gpio_keys.h>
+  #include <linux/gpio/machine.h>
+
+  #define MYBOARD_GPIO_CONTROLLER "gpio-foo"
+
+  /* LED setup */
+  static const struct gpio_led myboard_leds[] = {
+  	{
+  		.name = "myboard:green:status",
+  		.default_trigger = "heartbeat",
+  	},
+  };
+
+  static const struct gpio_led_platform_data myboard_leds_pdata = {
+  	.num_leds = ARRAY_SIZE(myboard_leds),
+  	.leds = myboard_leds,
+  };
+
+  static struct gpiod_lookup_table myboard_leds_gpios = {
+  	.dev_id = "leds-gpio",
+  	.table = {
+  		GPIO_LOOKUP_IDX(MYBOARD_GPIO_CONTROLLER, 42, NULL, 0, GPIO_ACTIVE_HIGH),
+  		{ },
+  	},
+  };
+
+  /* Button setup */
+  static struct gpio_keys_button myboard_buttons[] = {
+  	{
+  		.code = KEY_WPS_BUTTON,
+  		.desc = "WPS Button",
+  		.active_low = 1,
+  	},
+  };
+
+  static const struct gpio_keys_platform_data myboard_buttons_pdata = {
+  	.buttons = myboard_buttons,
+  	.nbuttons = ARRAY_SIZE(myboard_buttons),
+  };
+
+  static struct gpiod_lookup_table myboard_buttons_gpios = {
+  	.dev_id = "gpio-keys",
+  	.table = {
+  		GPIO_LOOKUP_IDX(MYBOARD_GPIO_CONTROLLER, 15, NULL, 0, GPIO_ACTIVE_LOW),
+  		{ },
+  	},
+  };
+
+  /* Device registration */
+  static int __init myboard_init(void)
+  {
+  	gpiod_add_lookup_table(&myboard_leds_gpios);
+  	gpiod_add_lookup_table(&myboard_buttons_gpios);
+
+  	platform_device_register_data(NULL, "leds-gpio", -1,
+  				      &myboard_leds_pdata, sizeof(myboard_leds_pdata));
+  	platform_device_register_data(NULL, "gpio-keys", -1,
+  				      &myboard_buttons_pdata, sizeof(myboard_buttons_pdata));
+
+  	return 0;
+  }
+
+After: Using Software Nodes
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Here is how the same configuration can be expressed using software nodes.
+
+Step 1: Define the GPIO Controller Node
+***************************************
+
+First, define a software node that represents the GPIO controller that the
+LEDs and buttons are connected to. The ``name`` of this node must match the
+name of the driver for the GPIO controller (e.g., "gpio-foo").
+
+.. code-block:: c
+
+  #include <linux/property.h>
+  #include <linux/gpio/property.h>
+
+  #define MYBOARD_GPIO_CONTROLLER "gpio-foo"
+
+  static const struct software_node myboard_gpio_controller_node = {
+  	.name = MYBOARD_GPIO_CONTROLLER,
+  };
+
+Step 2: Define Consumer Device Nodes and Properties
+***************************************************
+
+Next, define the software nodes for the consumer devices (the LEDs and buttons).
+This involves creating a parent node for each device type and child nodes for
+each individual LED or button.
+
+.. code-block:: c
+
+  /* LED setup */
+  static const struct software_node myboard_leds_node = {
+  	.name = "myboard-leds",
+  };
+
+  static const struct property_entry myboard_status_led_props[] = {
+  	PROPERTY_ENTRY_STRING("label", "myboard:green:status"),
+  	PROPERTY_ENTRY_STRING("linux,default-trigger", "heartbeat"),
+  	PROPERTY_ENTRY_GPIO("gpios", &myboard_gpio_controller_node, 42, GPIO_ACTIVE_HIGH),
+  	{ }
+  };
+
+  static const struct software_node myboard_status_led_swnode = {
+  	.name = "status-led",
+  	.parent = &myboard_leds_node,
+  	.properties = myboard_status_led_props,
+  };
+
+  /* Button setup */
+  static const struct software_node myboard_keys_node = {
+  	.name = "myboard-keys",
+  };
+
+  static const struct property_entry myboard_wps_button_props[] = {
+  	PROPERTY_ENTRY_STRING("label", "WPS Button"),
+  	PROPERTY_ENTRY_U32("linux,code", KEY_WPS_BUTTON),
+  	PROPERTY_ENTRY_GPIO("gpios", &myboard_gpio_controller_node, 15, GPIO_ACTIVE_LOW),
+  	{ }
+  };
+
+  static const struct software_node myboard_wps_button_swnode = {
+  	.name = "wps-button",
+  	.parent = &myboard_keys_node,
+  	.properties = myboard_wps_button_props,
+  };
+
+
+
+Step 3: Group and Register the Nodes
+************************************
+
+For maintainability, it is often beneficial to group all software nodes into a
+single array and register them with one call.
+
+.. code-block:: c
+
+  static const struct software_node * const myboard_swnodes[] __initconst = {
+  	&myboard_gpio_controller_node,
+  	&myboard_leds_node,
+  	&myboard_status_led_swnode,
+  	&myboard_keys_node,
+  	&myboard_wps_button_swnode,
+  	NULL
+  };
+
+  static int __init myboard_init(void)
+  {
+  	int error;
+
+  	error = software_node_register_node_group(myboard_swnodes);
+  	if (error) {
+  		pr_err("Failed to register software nodes: %d\n", error);
+  		return error;
+  	}
+
+  	// ... platform device registration follows
+  }
+
+.. note::
+  When splitting registration of nodes by devices that they represent, it is
+  essential that the software node representing the GPIO controller itself
+  is registered first, before any of the nodes that reference it.
+
+Step 4: Register Platform Devices with Software Nodes
+*****************************************************
+
+Finally, register the platform devices and associate them with their respective
+software nodes using the ``fwnode`` field in ``struct platform_device_info``.
+
+.. code-block:: c
+
+  static struct platform_device *leds_pdev;
+  static struct platform_device *keys_pdev;
+
+  static int __init myboard_init(void)
+  {
+  	struct platform_device_info pdev_info;
+  	int error;
+
+  	error = software_node_register_node_group(myboard_swnodes);
+  	if (error)
+  		return error;
+
+  	memset(&pdev_info, 0, sizeof(pdev_info));
+  	pdev_info.name = "leds-gpio";
+  	pdev_info.id = PLATFORM_DEVID_NONE;
+  	pdev_info.fwnode = software_node_fwnode(&myboard_leds_node);
+  	leds_pdev = platform_device_register_full(&pdev_info);
+  	if (IS_ERR(leds_pdev)) {
+  		error = PTR_ERR(leds_pdev);
+  		goto err_unregister_nodes;
+  	}
+
+  	memset(&pdev_info, 0, sizeof(pdev_info));
+  	pdev_info.name = "gpio-keys";
+  	pdev_info.id = PLATFORM_DEVID_NONE;
+  	pdev_info.fwnode = software_node_fwnode(&myboard_keys_node);
+  	keys_pdev = platform_device_register_full(&pdev_info);
+  	if (IS_ERR(keys_pdev)) {
+  		error = PTR_ERR(keys_pdev);
+  		platform_device_unregister(leds_pdev);
+  		goto err_unregister_nodes;
+  	}
+
+  	return 0;
+
+  err_unregister_nodes:
+  	software_node_unregister_node_group(myboard_swnodes);
+  	return error;
+  }
+
+  static void __exit myboard_exit(void)
+  {
+  	platform_device_unregister(keys_pdev);
+  	platform_device_unregister(leds_pdev);
+  	software_node_unregister_node_group(myboard_swnodes);
+  }
+
+With these changes, the generic ``leds-gpio`` and ``gpio-keys`` drivers will
+be able to probe successfully and get their configuration from the properties
+defined in the software nodes, removing the need for board-specific platform
+data.
-- 
2.51.0.rc0.155.g4a0f42376b-goog


-- 
Dmitry

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

* Re: [PATCH] Documentation: gpio: add documentation about using software nodes
  2025-08-11 21:30 [PATCH] Documentation: gpio: add documentation about using software nodes Dmitry Torokhov
@ 2025-08-12  0:46 ` Randy Dunlap
  2025-08-12  5:17   ` Dmitry Torokhov
  2025-08-19 11:35 ` Linus Walleij
  1 sibling, 1 reply; 7+ messages in thread
From: Randy Dunlap @ 2025-08-12  0:46 UTC (permalink / raw)
  To: Dmitry Torokhov, Linus Walleij, Bartosz Golaszewski,
	Jonathan Corbet
  Cc: Andy Shevchenko, Arnd Bergmann, Hans de Goede, linux-gpio,
	linux-doc, linux-kernel

Hi,

On 8/11/25 2:30 PM, Dmitry Torokhov wrote:
> Introduce documentation regarding use of software nodes to describe
> GPIOs on legacy boards that have not been converted to device tree.
> 

Thanks for the additional documentation.

> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> ---
>  Documentation/driver-api/gpio/board.rst       |  64 ++++
>  Documentation/driver-api/gpio/index.rst       |   1 +
>  .../driver-api/gpio/legacy-boards.rst         | 298 ++++++++++++++++++
>  3 files changed, 363 insertions(+)
> 
> diff --git a/Documentation/driver-api/gpio/board.rst b/Documentation/driver-api/gpio/board.rst
> index 4fd1cbd8296e..0cf64e1f2623 100644
> --- a/Documentation/driver-api/gpio/board.rst
> +++ b/Documentation/driver-api/gpio/board.rst
> @@ -94,6 +94,70 @@ with the help of _DSD (Device Specific Data), introduced in ACPI 5.1::
>  For more information about the ACPI GPIO bindings see
>  Documentation/firmware-guide/acpi/gpio-properties.rst.
>  
> +Software Nodes
> +--------------
> +Software nodes allows to construct an in-memory, device-tree-like structure

                  allow { drivers | modules | software | us}

although "software" seems redundant.

> +using ``struct software_node`` and ``struct property_entry``. This structure

Quoting Jon (for a different struct):
  Better to just say "struct list_head", and the automarkup logic should
  take care of the rest.

@Jon: ISTM that we need something in Documentation/doc-guide/sphinx.rst (?) about which
keywords are handled by automarkup logic. AFAIK, they are struct, union, enum,
and typedef (keywords) and function() as indicated by the "()".



> +can then be associated with a platform device, allowing drivers to use the
> +standard device properties API to query configuration, just as they would on an
> +ACPI or device tree systems.

                       system.

> +
> +Software-node-backed GPIOs are described using ``PROPERTY_ENTRY_GPIO()``
> +macro, which ties a sotfware node representing GPIO controller with consumer

                       software

> +device. It allows consumers to use regular gpiolib APIs, such as ``gpiod_get()``,
> +``gpiod_get_optional()``.
> +
> +The software node representing GPIO controller need not be attached to the
> +GPIO controller device. The only requirement that the node must be registered

                                    requirement is that

> +and its name much match the GPIO controller's label.

                must

> +
> +For example, here is how to describe a single GPIO-connected LED. This is an
> +alternative to using platform_data on legacy systems.
> +
> +.. code-block:: c
> +
> +	#include <linux/property.h>
> +	#include <linux/gpio/machine.h>
> +	#include <linux/gpio/property.h>
> +
> +	/*
> +	 * 1. Define a node for the GPIO controller. Its .name must match the
> +	 *    controller's label.
> +	 */
> +	static const struct software_node gpio_controller_node = {
> +		.name = "gpio-foo",
> +	};
> +
> +	/* 2. Define the properties for the LED device. */
> +	static const struct property_entry led_device_props[] = {
> +		PROPERTY_ENTRY_STRING("label", "myboard:green:status"),
> +		PROPERTY_ENTRY_STRING("linux,default-trigger", "heartbeat"),
> +		PROPERTY_ENTRY_GPIO("gpios", &gpio_controller_node, 42, GPIO_ACTIVE_HIGH),
> +		{ }
> +	};
> +
> +	/* 3. Define the software node for the LED device. */
> +	static const struct software_node led_device_swnode = {
> +		.name = "status-led",
> +		.properties = led_device_props,
> +	};
> +
> +	/*
> +	 * 4. Register the software nodes and the platform device.
> +	 */
> +	const struct software_node *swnodes[] = {
> +		&gpio_controller_node,
> +		&led_device_swnode,
> +		NULL
> +	};
> +	software_node_register_node_group(swnodes);
> +
> +	// Then register a platform_device for "leds-gpio" and associate
> +	// it with &led_device_swnode via .fwnode.
> +
> +For a complete guide on converting board files to use software nodes, see
> +Documentation/driver-api/gpio/legacy-boards.rst.
> +
>  Platform Data
>  -------------
>  Finally, GPIOs can be bound to devices and functions using platform data. Board



> diff --git a/Documentation/driver-api/gpio/legacy-boards.rst b/Documentation/driver-api/gpio/legacy-boards.rst
> new file mode 100644
> index 000000000000..6700a2549220
> --- /dev/null
> +++ b/Documentation/driver-api/gpio/legacy-boards.rst
> @@ -0,0 +1,298 @@
> +Supporting Legacy Boards
> +========================
> +
> +Many drivers in the kernel, such as ``leds-gpio`` and ``gpio-keys``, are
> +migrating away from using board-specific ``platform_data`` to a unified device
> +properties interface. This interface allows drivers to be simpler and more
> +generic, as they can query properties in a standardized way.
> +
> +On modern systems, these properties are provided via device tree. However, some
> +older platforms have not been converted to device tree and instead rely on
> +board files to describe their hardware configuration. To bridge this gap and
> +allow these legacy boards to work with modern, generic drivers, the kernel
> +provides a mechanism called **software nodes**.
> +
> +This document provides a guide on how to convert a legacy board file from using
> +``platform_data`` and ``gpiod_lookup_table`` to the modern software node
> +approach for describing GPIO-connected devices.
> +
> +The Core Idea: Software Nodes
> +-----------------------------
> +
> +Software nodes allows to construct an in-memory, device-tree-like structure

                  allow {some object of the verb, as suggested above}

> +using ``struct software_node`` and ``struct property_entry``. This structure

Please drop the "``" markups. They aren't needed.

> +can then be associated with a platform device, allowing drivers to use the
> +standard device properties API (e.g., ``device_property_read_u32()``,
> +``device_property_read_string()``) to query configuration, just as they would
> +on an ACPI or device tree systems.

                             system.

> +
> +The gpiolib code has support for handling software nodes, so that if GPIO is
> +described properly, as detailed in the section below, then regular gpiolib APIs,
> +such as ``gpiod_get()``, ``gpiod_get_optional()`` and others will work.
> +
> +Requirements for GPIO Properties
> +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +When using software nodes to describe GPIO connections, the following
> +requirements must be met for the GPIO core to correctly resolve the reference:
> +
> +1.  **The GPIO controller's software node ``name`` must match the controller's
> +    ``label``.** The gpiolib core uses this name to find the corresponding
> +    ``struct gpio_chip`` at runtime.

"``" not needed.

> +    This software node has to be registered, but need not be attached to the
> +    device representing GPIO controller that is providing GPIO in question.
> +    It may be left as a "free floating" node.
> +
> +2.  **The GPIO property must be a reference.** The ``PROPERTY_ENTRY_GPIO()``
> +    macro handles this as it is an alias for ``PROPERTY_ENTRY_REF()``.
> +
> +3.  **The reference must have exactly two arguments:**
> +
> +    - The first argument is the GPIO offset within the controller.
> +    - The second argument is the flags for the GPIO line (e.g.,
> +      ``GPIO_ACTIVE_HIGH``, ``GPIO_ACTIVE_LOW``).
> +
> +The ``PROPERTY_ENTRY_GPIO()`` macro is the preferred way of defining GPIO
> +properties in software nodes.
> +
> +Conversion Example
> +------------------
> +
> +Let's walk through an example of converting a board file that defines a GPIO-
> +connected LED and a button.
> +
> +Before: Using Platform Data
> +~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +A typical legacy board file might look like this:
> +
> +.. code-block:: c
> +
> +  #include <linux/platform_device.h>
> +  #include <linux/leds.h>
> +  #include <linux/gpio_keys.h>
> +  #include <linux/gpio/machine.h>
> +
> +  #define MYBOARD_GPIO_CONTROLLER "gpio-foo"
> +
> +  /* LED setup */
> +  static const struct gpio_led myboard_leds[] = {
> +  	{
> +  		.name = "myboard:green:status",
> +  		.default_trigger = "heartbeat",
> +  	},
> +  };
> +
> +  static const struct gpio_led_platform_data myboard_leds_pdata = {
> +  	.num_leds = ARRAY_SIZE(myboard_leds),
> +  	.leds = myboard_leds,
> +  };
> +
> +  static struct gpiod_lookup_table myboard_leds_gpios = {
> +  	.dev_id = "leds-gpio",
> +  	.table = {
> +  		GPIO_LOOKUP_IDX(MYBOARD_GPIO_CONTROLLER, 42, NULL, 0, GPIO_ACTIVE_HIGH),
> +  		{ },
> +  	},
> +  };
> +
> +  /* Button setup */
> +  static struct gpio_keys_button myboard_buttons[] = {
> +  	{
> +  		.code = KEY_WPS_BUTTON,
> +  		.desc = "WPS Button",
> +  		.active_low = 1,
> +  	},
> +  };
> +
> +  static const struct gpio_keys_platform_data myboard_buttons_pdata = {
> +  	.buttons = myboard_buttons,
> +  	.nbuttons = ARRAY_SIZE(myboard_buttons),
> +  };
> +
> +  static struct gpiod_lookup_table myboard_buttons_gpios = {
> +  	.dev_id = "gpio-keys",
> +  	.table = {
> +  		GPIO_LOOKUP_IDX(MYBOARD_GPIO_CONTROLLER, 15, NULL, 0, GPIO_ACTIVE_LOW),
> +  		{ },
> +  	},
> +  };
> +
> +  /* Device registration */
> +  static int __init myboard_init(void)
> +  {
> +  	gpiod_add_lookup_table(&myboard_leds_gpios);
> +  	gpiod_add_lookup_table(&myboard_buttons_gpios);
> +
> +  	platform_device_register_data(NULL, "leds-gpio", -1,
> +  				      &myboard_leds_pdata, sizeof(myboard_leds_pdata));
> +  	platform_device_register_data(NULL, "gpio-keys", -1,
> +  				      &myboard_buttons_pdata, sizeof(myboard_buttons_pdata));
> +
> +  	return 0;
> +  }
> +
> +After: Using Software Nodes
> +~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +Here is how the same configuration can be expressed using software nodes.
> +
> +Step 1: Define the GPIO Controller Node
> +***************************************
> +
> +First, define a software node that represents the GPIO controller that the
> +LEDs and buttons are connected to. The ``name`` of this node must match the
> +name of the driver for the GPIO controller (e.g., "gpio-foo").
> +
> +.. code-block:: c
> +
> +  #include <linux/property.h>
> +  #include <linux/gpio/property.h>
> +
> +  #define MYBOARD_GPIO_CONTROLLER "gpio-foo"
> +
> +  static const struct software_node myboard_gpio_controller_node = {
> +  	.name = MYBOARD_GPIO_CONTROLLER,
> +  };
> +
> +Step 2: Define Consumer Device Nodes and Properties
> +***************************************************
> +
> +Next, define the software nodes for the consumer devices (the LEDs and buttons).
> +This involves creating a parent node for each device type and child nodes for
> +each individual LED or button.
> +
> +.. code-block:: c
> +
> +  /* LED setup */
> +  static const struct software_node myboard_leds_node = {
> +  	.name = "myboard-leds",
> +  };
> +
> +  static const struct property_entry myboard_status_led_props[] = {
> +  	PROPERTY_ENTRY_STRING("label", "myboard:green:status"),
> +  	PROPERTY_ENTRY_STRING("linux,default-trigger", "heartbeat"),
> +  	PROPERTY_ENTRY_GPIO("gpios", &myboard_gpio_controller_node, 42, GPIO_ACTIVE_HIGH),
> +  	{ }
> +  };
> +
> +  static const struct software_node myboard_status_led_swnode = {
> +  	.name = "status-led",
> +  	.parent = &myboard_leds_node,
> +  	.properties = myboard_status_led_props,
> +  };
> +
> +  /* Button setup */
> +  static const struct software_node myboard_keys_node = {
> +  	.name = "myboard-keys",
> +  };
> +
> +  static const struct property_entry myboard_wps_button_props[] = {
> +  	PROPERTY_ENTRY_STRING("label", "WPS Button"),
> +  	PROPERTY_ENTRY_U32("linux,code", KEY_WPS_BUTTON),
> +  	PROPERTY_ENTRY_GPIO("gpios", &myboard_gpio_controller_node, 15, GPIO_ACTIVE_LOW),
> +  	{ }
> +  };
> +
> +  static const struct software_node myboard_wps_button_swnode = {
> +  	.name = "wps-button",
> +  	.parent = &myboard_keys_node,
> +  	.properties = myboard_wps_button_props,
> +  };
> +
> +
> +
> +Step 3: Group and Register the Nodes
> +************************************
> +
> +For maintainability, it is often beneficial to group all software nodes into a
> +single array and register them with one call.
> +
> +.. code-block:: c
> +
> +  static const struct software_node * const myboard_swnodes[] __initconst = {
> +  	&myboard_gpio_controller_node,
> +  	&myboard_leds_node,
> +  	&myboard_status_led_swnode,
> +  	&myboard_keys_node,
> +  	&myboard_wps_button_swnode,
> +  	NULL
> +  };
> +
> +  static int __init myboard_init(void)
> +  {
> +  	int error;
> +
> +  	error = software_node_register_node_group(myboard_swnodes);
> +  	if (error) {
> +  		pr_err("Failed to register software nodes: %d\n", error);
> +  		return error;
> +  	}
> +
> +  	// ... platform device registration follows
> +  }
> +
> +.. note::
> +  When splitting registration of nodes by devices that they represent, it is
> +  essential that the software node representing the GPIO controller itself
> +  is registered first, before any of the nodes that reference it.
> +
> +Step 4: Register Platform Devices with Software Nodes
> +*****************************************************
> +
> +Finally, register the platform devices and associate them with their respective
> +software nodes using the ``fwnode`` field in ``struct platform_device_info``.

Drop the "``" on struct platform_device_info.

> +
> +.. code-block:: c
> +
> +  static struct platform_device *leds_pdev;
> +  static struct platform_device *keys_pdev;
> +
> +  static int __init myboard_init(void)
> +  {
> +  	struct platform_device_info pdev_info;
> +  	int error;
> +
> +  	error = software_node_register_node_group(myboard_swnodes);
> +  	if (error)
> +  		return error;
> +
> +  	memset(&pdev_info, 0, sizeof(pdev_info));
> +  	pdev_info.name = "leds-gpio";
> +  	pdev_info.id = PLATFORM_DEVID_NONE;
> +  	pdev_info.fwnode = software_node_fwnode(&myboard_leds_node);
> +  	leds_pdev = platform_device_register_full(&pdev_info);
> +  	if (IS_ERR(leds_pdev)) {
> +  		error = PTR_ERR(leds_pdev);
> +  		goto err_unregister_nodes;
> +  	}
> +
> +  	memset(&pdev_info, 0, sizeof(pdev_info));
> +  	pdev_info.name = "gpio-keys";
> +  	pdev_info.id = PLATFORM_DEVID_NONE;
> +  	pdev_info.fwnode = software_node_fwnode(&myboard_keys_node);
> +  	keys_pdev = platform_device_register_full(&pdev_info);
> +  	if (IS_ERR(keys_pdev)) {
> +  		error = PTR_ERR(keys_pdev);
> +  		platform_device_unregister(leds_pdev);
> +  		goto err_unregister_nodes;
> +  	}
> +
> +  	return 0;
> +
> +  err_unregister_nodes:
> +  	software_node_unregister_node_group(myboard_swnodes);
> +  	return error;
> +  }
> +
> +  static void __exit myboard_exit(void)
> +  {
> +  	platform_device_unregister(keys_pdev);
> +  	platform_device_unregister(leds_pdev);
> +  	software_node_unregister_node_group(myboard_swnodes);
> +  }
> +
> +With these changes, the generic ``leds-gpio`` and ``gpio-keys`` drivers will
> +be able to probe successfully and get their configuration from the properties
> +defined in the software nodes, removing the need for board-specific platform
> +data.
.

-- 
~Randy


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

* Re: [PATCH] Documentation: gpio: add documentation about using software nodes
  2025-08-12  0:46 ` Randy Dunlap
@ 2025-08-12  5:17   ` Dmitry Torokhov
  2025-08-12  5:37     ` Randy Dunlap
  0 siblings, 1 reply; 7+ messages in thread
From: Dmitry Torokhov @ 2025-08-12  5:17 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: Linus Walleij, Bartosz Golaszewski, Jonathan Corbet,
	Andy Shevchenko, Arnd Bergmann, Hans de Goede, linux-gpio,
	linux-doc, linux-kernel

Hi Randy,

On Mon, Aug 11, 2025 at 05:46:02PM -0700, Randy Dunlap wrote:
> Hi,
> 
> On 8/11/25 2:30 PM, Dmitry Torokhov wrote:
> > Introduce documentation regarding use of software nodes to describe
> > GPIOs on legacy boards that have not been converted to device tree.
> > 
> 
> Thanks for the additional documentation.

Thanks for the review.

> 
> > Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> > ---
> >  Documentation/driver-api/gpio/board.rst       |  64 ++++
> >  Documentation/driver-api/gpio/index.rst       |   1 +
> >  .../driver-api/gpio/legacy-boards.rst         | 298 ++++++++++++++++++
> >  3 files changed, 363 insertions(+)
> > 
> > diff --git a/Documentation/driver-api/gpio/board.rst b/Documentation/driver-api/gpio/board.rst
> > index 4fd1cbd8296e..0cf64e1f2623 100644
> > --- a/Documentation/driver-api/gpio/board.rst
> > +++ b/Documentation/driver-api/gpio/board.rst
> > @@ -94,6 +94,70 @@ with the help of _DSD (Device Specific Data), introduced in ACPI 5.1::
> >  For more information about the ACPI GPIO bindings see
> >  Documentation/firmware-guide/acpi/gpio-properties.rst.
> >  
> > +Software Nodes
> > +--------------
> > +Software nodes allows to construct an in-memory, device-tree-like structure
> 
>                   allow { drivers | modules | software | us}
> 
> although "software" seems redundant.

I changed it to "... allows board specific code ..."

> 
> > +using ``struct software_node`` and ``struct property_entry``. This structure
> 
> Quoting Jon (for a different struct):
>   Better to just say "struct list_head", and the automarkup logic should
>   take care of the rest.
> 
> @Jon: ISTM that we need something in Documentation/doc-guide/sphinx.rst (?) about which
> keywords are handled by automarkup logic. AFAIK, they are struct, union, enum,
> and typedef (keywords) and function() as indicated by the "()".

Unfortunately device properties/software nodes are not yet hooked to the
documentations, so automatic markup/cross referencing does not work.

I changed this to :c:type:`struct software_node <software_node>`.

> 
> 
> 
> > +can then be associated with a platform device, allowing drivers to use the
> > +standard device properties API to query configuration, just as they would on an
> > +ACPI or device tree systems.
> 
>                        system.

OK.

> 
> > +
> > +Software-node-backed GPIOs are described using ``PROPERTY_ENTRY_GPIO()``
> > +macro, which ties a sotfware node representing GPIO controller with consumer
> 
>                        software

Yep, thanks.

> 
> > +device. It allows consumers to use regular gpiolib APIs, such as ``gpiod_get()``,
> > +``gpiod_get_optional()``.
> > +
> > +The software node representing GPIO controller need not be attached to the
> > +GPIO controller device. The only requirement that the node must be registered
> 
>                                     requirement is that

OK.

> 
> > +and its name much match the GPIO controller's label.
> 
>                 must

OK.

> 
> > +
> > +For example, here is how to describe a single GPIO-connected LED. This is an
> > +alternative to using platform_data on legacy systems.
> > +
> > +.. code-block:: c
> > +
> > +	#include <linux/property.h>
> > +	#include <linux/gpio/machine.h>
> > +	#include <linux/gpio/property.h>
> > +
> > +	/*
> > +	 * 1. Define a node for the GPIO controller. Its .name must match the
> > +	 *    controller's label.
> > +	 */
> > +	static const struct software_node gpio_controller_node = {
> > +		.name = "gpio-foo",
> > +	};
> > +
> > +	/* 2. Define the properties for the LED device. */
> > +	static const struct property_entry led_device_props[] = {
> > +		PROPERTY_ENTRY_STRING("label", "myboard:green:status"),
> > +		PROPERTY_ENTRY_STRING("linux,default-trigger", "heartbeat"),
> > +		PROPERTY_ENTRY_GPIO("gpios", &gpio_controller_node, 42, GPIO_ACTIVE_HIGH),
> > +		{ }
> > +	};
> > +
> > +	/* 3. Define the software node for the LED device. */
> > +	static const struct software_node led_device_swnode = {
> > +		.name = "status-led",
> > +		.properties = led_device_props,
> > +	};
> > +
> > +	/*
> > +	 * 4. Register the software nodes and the platform device.
> > +	 */
> > +	const struct software_node *swnodes[] = {
> > +		&gpio_controller_node,
> > +		&led_device_swnode,
> > +		NULL
> > +	};
> > +	software_node_register_node_group(swnodes);
> > +
> > +	// Then register a platform_device for "leds-gpio" and associate
> > +	// it with &led_device_swnode via .fwnode.
> > +
> > +For a complete guide on converting board files to use software nodes, see
> > +Documentation/driver-api/gpio/legacy-boards.rst.
> > +
> >  Platform Data
> >  -------------
> >  Finally, GPIOs can be bound to devices and functions using platform data. Board
> 
> 
> 
> > diff --git a/Documentation/driver-api/gpio/legacy-boards.rst b/Documentation/driver-api/gpio/legacy-boards.rst
> > new file mode 100644
> > index 000000000000..6700a2549220
> > --- /dev/null
> > +++ b/Documentation/driver-api/gpio/legacy-boards.rst
> > @@ -0,0 +1,298 @@
> > +Supporting Legacy Boards
> > +========================
> > +
> > +Many drivers in the kernel, such as ``leds-gpio`` and ``gpio-keys``, are
> > +migrating away from using board-specific ``platform_data`` to a unified device
> > +properties interface. This interface allows drivers to be simpler and more
> > +generic, as they can query properties in a standardized way.
> > +
> > +On modern systems, these properties are provided via device tree. However, some
> > +older platforms have not been converted to device tree and instead rely on
> > +board files to describe their hardware configuration. To bridge this gap and
> > +allow these legacy boards to work with modern, generic drivers, the kernel
> > +provides a mechanism called **software nodes**.
> > +
> > +This document provides a guide on how to convert a legacy board file from using
> > +``platform_data`` and ``gpiod_lookup_table`` to the modern software node
> > +approach for describing GPIO-connected devices.
> > +
> > +The Core Idea: Software Nodes
> > +-----------------------------
> > +
> > +Software nodes allows to construct an in-memory, device-tree-like structure
> 
>                   allow {some object of the verb, as suggested above}

Done.

> 
> > +using ``struct software_node`` and ``struct property_entry``. This structure
> 
> Please drop the "``" markups. They aren't needed.

As I mentioned above some kind of markups currently is needed.

> 
> > +can then be associated with a platform device, allowing drivers to use the
> > +standard device properties API (e.g., ``device_property_read_u32()``,
> > +``device_property_read_string()``) to query configuration, just as they would
> > +on an ACPI or device tree systems.
> 
>                              system.

OK.

> 
> > +
> > +The gpiolib code has support for handling software nodes, so that if GPIO is
> > +described properly, as detailed in the section below, then regular gpiolib APIs,
> > +such as ``gpiod_get()``, ``gpiod_get_optional()`` and others will work.
> > +
> > +Requirements for GPIO Properties
> > +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > +
> > +When using software nodes to describe GPIO connections, the following
> > +requirements must be met for the GPIO core to correctly resolve the reference:
> > +
> > +1.  **The GPIO controller's software node ``name`` must match the controller's
> > +    ``label``.** The gpiolib core uses this name to find the corresponding
> > +    ``struct gpio_chip`` at runtime.
> 
> "``" not needed.

Dropped.

> 
> > +    This software node has to be registered, but need not be attached to the
> > +    device representing GPIO controller that is providing GPIO in question.
> > +    It may be left as a "free floating" node.
> > +
> > +2.  **The GPIO property must be a reference.** The ``PROPERTY_ENTRY_GPIO()``
> > +    macro handles this as it is an alias for ``PROPERTY_ENTRY_REF()``.
> > +
> > +3.  **The reference must have exactly two arguments:**
> > +
> > +    - The first argument is the GPIO offset within the controller.
> > +    - The second argument is the flags for the GPIO line (e.g.,
> > +      ``GPIO_ACTIVE_HIGH``, ``GPIO_ACTIVE_LOW``).
> > +
> > +The ``PROPERTY_ENTRY_GPIO()`` macro is the preferred way of defining GPIO
> > +properties in software nodes.
> > +
> > +Conversion Example
> > +------------------
> > +
> > +Let's walk through an example of converting a board file that defines a GPIO-
> > +connected LED and a button.
> > +
> > +Before: Using Platform Data
> > +~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > +
> > +A typical legacy board file might look like this:
> > +
> > +.. code-block:: c
> > +
> > +  #include <linux/platform_device.h>
> > +  #include <linux/leds.h>
> > +  #include <linux/gpio_keys.h>
> > +  #include <linux/gpio/machine.h>
> > +
> > +  #define MYBOARD_GPIO_CONTROLLER "gpio-foo"
> > +
> > +  /* LED setup */
> > +  static const struct gpio_led myboard_leds[] = {
> > +  	{
> > +  		.name = "myboard:green:status",
> > +  		.default_trigger = "heartbeat",
> > +  	},
> > +  };
> > +
> > +  static const struct gpio_led_platform_data myboard_leds_pdata = {
> > +  	.num_leds = ARRAY_SIZE(myboard_leds),
> > +  	.leds = myboard_leds,
> > +  };
> > +
> > +  static struct gpiod_lookup_table myboard_leds_gpios = {
> > +  	.dev_id = "leds-gpio",
> > +  	.table = {
> > +  		GPIO_LOOKUP_IDX(MYBOARD_GPIO_CONTROLLER, 42, NULL, 0, GPIO_ACTIVE_HIGH),
> > +  		{ },
> > +  	},
> > +  };
> > +
> > +  /* Button setup */
> > +  static struct gpio_keys_button myboard_buttons[] = {
> > +  	{
> > +  		.code = KEY_WPS_BUTTON,
> > +  		.desc = "WPS Button",
> > +  		.active_low = 1,
> > +  	},
> > +  };
> > +
> > +  static const struct gpio_keys_platform_data myboard_buttons_pdata = {
> > +  	.buttons = myboard_buttons,
> > +  	.nbuttons = ARRAY_SIZE(myboard_buttons),
> > +  };
> > +
> > +  static struct gpiod_lookup_table myboard_buttons_gpios = {
> > +  	.dev_id = "gpio-keys",
> > +  	.table = {
> > +  		GPIO_LOOKUP_IDX(MYBOARD_GPIO_CONTROLLER, 15, NULL, 0, GPIO_ACTIVE_LOW),
> > +  		{ },
> > +  	},
> > +  };
> > +
> > +  /* Device registration */
> > +  static int __init myboard_init(void)
> > +  {
> > +  	gpiod_add_lookup_table(&myboard_leds_gpios);
> > +  	gpiod_add_lookup_table(&myboard_buttons_gpios);
> > +
> > +  	platform_device_register_data(NULL, "leds-gpio", -1,
> > +  				      &myboard_leds_pdata, sizeof(myboard_leds_pdata));
> > +  	platform_device_register_data(NULL, "gpio-keys", -1,
> > +  				      &myboard_buttons_pdata, sizeof(myboard_buttons_pdata));
> > +
> > +  	return 0;
> > +  }
> > +
> > +After: Using Software Nodes
> > +~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > +
> > +Here is how the same configuration can be expressed using software nodes.
> > +
> > +Step 1: Define the GPIO Controller Node
> > +***************************************
> > +
> > +First, define a software node that represents the GPIO controller that the
> > +LEDs and buttons are connected to. The ``name`` of this node must match the
> > +name of the driver for the GPIO controller (e.g., "gpio-foo").
> > +
> > +.. code-block:: c
> > +
> > +  #include <linux/property.h>
> > +  #include <linux/gpio/property.h>
> > +
> > +  #define MYBOARD_GPIO_CONTROLLER "gpio-foo"
> > +
> > +  static const struct software_node myboard_gpio_controller_node = {
> > +  	.name = MYBOARD_GPIO_CONTROLLER,
> > +  };
> > +
> > +Step 2: Define Consumer Device Nodes and Properties
> > +***************************************************
> > +
> > +Next, define the software nodes for the consumer devices (the LEDs and buttons).
> > +This involves creating a parent node for each device type and child nodes for
> > +each individual LED or button.
> > +
> > +.. code-block:: c
> > +
> > +  /* LED setup */
> > +  static const struct software_node myboard_leds_node = {
> > +  	.name = "myboard-leds",
> > +  };
> > +
> > +  static const struct property_entry myboard_status_led_props[] = {
> > +  	PROPERTY_ENTRY_STRING("label", "myboard:green:status"),
> > +  	PROPERTY_ENTRY_STRING("linux,default-trigger", "heartbeat"),
> > +  	PROPERTY_ENTRY_GPIO("gpios", &myboard_gpio_controller_node, 42, GPIO_ACTIVE_HIGH),
> > +  	{ }
> > +  };
> > +
> > +  static const struct software_node myboard_status_led_swnode = {
> > +  	.name = "status-led",
> > +  	.parent = &myboard_leds_node,
> > +  	.properties = myboard_status_led_props,
> > +  };
> > +
> > +  /* Button setup */
> > +  static const struct software_node myboard_keys_node = {
> > +  	.name = "myboard-keys",
> > +  };
> > +
> > +  static const struct property_entry myboard_wps_button_props[] = {
> > +  	PROPERTY_ENTRY_STRING("label", "WPS Button"),
> > +  	PROPERTY_ENTRY_U32("linux,code", KEY_WPS_BUTTON),
> > +  	PROPERTY_ENTRY_GPIO("gpios", &myboard_gpio_controller_node, 15, GPIO_ACTIVE_LOW),
> > +  	{ }
> > +  };
> > +
> > +  static const struct software_node myboard_wps_button_swnode = {
> > +  	.name = "wps-button",
> > +  	.parent = &myboard_keys_node,
> > +  	.properties = myboard_wps_button_props,
> > +  };
> > +
> > +
> > +
> > +Step 3: Group and Register the Nodes
> > +************************************
> > +
> > +For maintainability, it is often beneficial to group all software nodes into a
> > +single array and register them with one call.
> > +
> > +.. code-block:: c
> > +
> > +  static const struct software_node * const myboard_swnodes[] __initconst = {
> > +  	&myboard_gpio_controller_node,
> > +  	&myboard_leds_node,
> > +  	&myboard_status_led_swnode,
> > +  	&myboard_keys_node,
> > +  	&myboard_wps_button_swnode,
> > +  	NULL
> > +  };
> > +
> > +  static int __init myboard_init(void)
> > +  {
> > +  	int error;
> > +
> > +  	error = software_node_register_node_group(myboard_swnodes);
> > +  	if (error) {
> > +  		pr_err("Failed to register software nodes: %d\n", error);
> > +  		return error;
> > +  	}
> > +
> > +  	// ... platform device registration follows
> > +  }
> > +
> > +.. note::
> > +  When splitting registration of nodes by devices that they represent, it is
> > +  essential that the software node representing the GPIO controller itself
> > +  is registered first, before any of the nodes that reference it.
> > +
> > +Step 4: Register Platform Devices with Software Nodes
> > +*****************************************************
> > +
> > +Finally, register the platform devices and associate them with their respective
> > +software nodes using the ``fwnode`` field in ``struct platform_device_info``.
> 
> Drop the "``" on struct platform_device_info.

It is not documented anywhere, so used :c:type:`....` for it.

Thanks.

-- 
Dmitry

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

* Re: [PATCH] Documentation: gpio: add documentation about using software nodes
  2025-08-12  5:17   ` Dmitry Torokhov
@ 2025-08-12  5:37     ` Randy Dunlap
  2025-08-12 16:10       ` Dmitry Torokhov
  0 siblings, 1 reply; 7+ messages in thread
From: Randy Dunlap @ 2025-08-12  5:37 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Linus Walleij, Bartosz Golaszewski, Jonathan Corbet,
	Andy Shevchenko, Arnd Bergmann, Hans de Goede, linux-gpio,
	linux-doc, linux-kernel



On 8/11/25 10:17 PM, Dmitry Torokhov wrote:
> Hi Randy,
> 
> On Mon, Aug 11, 2025 at 05:46:02PM -0700, Randy Dunlap wrote:
>> Hi,
>>
>> On 8/11/25 2:30 PM, Dmitry Torokhov wrote:
>>> Introduce documentation regarding use of software nodes to describe
>>> GPIOs on legacy boards that have not been converted to device tree.
>>>
>>
>> Thanks for the additional documentation.
> 
> Thanks for the review.
> 
>>
>>> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
>>> ---
>>>  Documentation/driver-api/gpio/board.rst       |  64 ++++
>>>  Documentation/driver-api/gpio/index.rst       |   1 +
>>>  .../driver-api/gpio/legacy-boards.rst         | 298 ++++++++++++++++++
>>>  3 files changed, 363 insertions(+)
>>>
>>> diff --git a/Documentation/driver-api/gpio/board.rst b/Documentation/driver-api/gpio/board.rst
>>> index 4fd1cbd8296e..0cf64e1f2623 100644
>>> --- a/Documentation/driver-api/gpio/board.rst
>>> +++ b/Documentation/driver-api/gpio/board.rst
>>> @@ -94,6 +94,70 @@ with the help of _DSD (Device Specific Data), introduced in ACPI 5.1::
>>>  For more information about the ACPI GPIO bindings see
>>>  Documentation/firmware-guide/acpi/gpio-properties.rst.
>>>  
>>> +Software Nodes
>>> +--------------
>>> +Software nodes allows to construct an in-memory, device-tree-like structure
>>
>>                   allow { drivers | modules | software | us}
>>
>> although "software" seems redundant.
> 
> I changed it to "... allows board specific code ..."
> 
>>
>>> +using ``struct software_node`` and ``struct property_entry``. This structure
>>
>> Quoting Jon (for a different struct):
>>   Better to just say "struct list_head", and the automarkup logic should
>>   take care of the rest.
>>
>> @Jon: ISTM that we need something in Documentation/doc-guide/sphinx.rst (?) about which
>> keywords are handled by automarkup logic. AFAIK, they are struct, union, enum,
>> and typedef (keywords) and function() as indicated by the "()".
> 
> Unfortunately device properties/software nodes are not yet hooked to the
> documentations, so automatic markup/cross referencing does not work.
> 
> I changed this to :c:type:`struct software_node <software_node>`.

Oh no, that's worse from a human readability standpoint. :(

We try (would like to) keep .rst files as readable as .txt files.
All of that extra markup and notation is noisy and usually not needed.
Are you saying that the extra markup (as you listed above) is needed?
for cross-referencing?

The original would be better.

(same in the other .rst file)

-- 
~Randy


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

* Re: [PATCH] Documentation: gpio: add documentation about using software nodes
  2025-08-12  5:37     ` Randy Dunlap
@ 2025-08-12 16:10       ` Dmitry Torokhov
  2025-08-13 12:47         ` Andy Shevchenko
  0 siblings, 1 reply; 7+ messages in thread
From: Dmitry Torokhov @ 2025-08-12 16:10 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: Linus Walleij, Bartosz Golaszewski, Jonathan Corbet,
	Andy Shevchenko, Arnd Bergmann, Hans de Goede, linux-gpio,
	linux-doc, linux-kernel

On Mon, Aug 11, 2025 at 10:37:04PM -0700, Randy Dunlap wrote:
> 
> 
> On 8/11/25 10:17 PM, Dmitry Torokhov wrote:
> > Hi Randy,
> > 
> > On Mon, Aug 11, 2025 at 05:46:02PM -0700, Randy Dunlap wrote:
> >> Hi,
> >>
> >> On 8/11/25 2:30 PM, Dmitry Torokhov wrote:
> >>> Introduce documentation regarding use of software nodes to describe
> >>> GPIOs on legacy boards that have not been converted to device tree.
> >>>
> >>
> >> Thanks for the additional documentation.
> > 
> > Thanks for the review.
> > 
> >>
> >>> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> >>> ---
> >>>  Documentation/driver-api/gpio/board.rst       |  64 ++++
> >>>  Documentation/driver-api/gpio/index.rst       |   1 +
> >>>  .../driver-api/gpio/legacy-boards.rst         | 298 ++++++++++++++++++
> >>>  3 files changed, 363 insertions(+)
> >>>
> >>> diff --git a/Documentation/driver-api/gpio/board.rst b/Documentation/driver-api/gpio/board.rst
> >>> index 4fd1cbd8296e..0cf64e1f2623 100644
> >>> --- a/Documentation/driver-api/gpio/board.rst
> >>> +++ b/Documentation/driver-api/gpio/board.rst
> >>> @@ -94,6 +94,70 @@ with the help of _DSD (Device Specific Data), introduced in ACPI 5.1::
> >>>  For more information about the ACPI GPIO bindings see
> >>>  Documentation/firmware-guide/acpi/gpio-properties.rst.
> >>>  
> >>> +Software Nodes
> >>> +--------------
> >>> +Software nodes allows to construct an in-memory, device-tree-like structure
> >>
> >>                   allow { drivers | modules | software | us}
> >>
> >> although "software" seems redundant.
> > 
> > I changed it to "... allows board specific code ..."
> > 
> >>
> >>> +using ``struct software_node`` and ``struct property_entry``. This structure
> >>
> >> Quoting Jon (for a different struct):
> >>   Better to just say "struct list_head", and the automarkup logic should
> >>   take care of the rest.
> >>
> >> @Jon: ISTM that we need something in Documentation/doc-guide/sphinx.rst (?) about which
> >> keywords are handled by automarkup logic. AFAIK, they are struct, union, enum,
> >> and typedef (keywords) and function() as indicated by the "()".
> > 
> > Unfortunately device properties/software nodes are not yet hooked to the
> > documentations, so automatic markup/cross referencing does not work.
> > 
> > I changed this to :c:type:`struct software_node <software_node>`.
> 
> Oh no, that's worse from a human readability standpoint. :(
> 
> We try (would like to) keep .rst files as readable as .txt files.
> All of that extra markup and notation is noisy and usually not needed.
> Are you saying that the extra markup (as you listed above) is needed?
> for cross-referencing?
> 
> The original would be better.
> 
> (same in the other .rst file)

OK, I  was trying to make html output look pretty. If we want to favor
.rst readability that is fine, I'll drop the :c:*: annotations.

Thanks.

-- 
Dmitry

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

* Re: [PATCH] Documentation: gpio: add documentation about using software nodes
  2025-08-12 16:10       ` Dmitry Torokhov
@ 2025-08-13 12:47         ` Andy Shevchenko
  0 siblings, 0 replies; 7+ messages in thread
From: Andy Shevchenko @ 2025-08-13 12:47 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Randy Dunlap, Linus Walleij, Bartosz Golaszewski, Jonathan Corbet,
	Arnd Bergmann, Hans de Goede, linux-gpio, linux-doc, linux-kernel

On Tue, Aug 12, 2025 at 09:10:23AM -0700, Dmitry Torokhov wrote:
> On Mon, Aug 11, 2025 at 10:37:04PM -0700, Randy Dunlap wrote:
> > On 8/11/25 10:17 PM, Dmitry Torokhov wrote:
> > > On Mon, Aug 11, 2025 at 05:46:02PM -0700, Randy Dunlap wrote:
> > >> On 8/11/25 2:30 PM, Dmitry Torokhov wrote:

...

> > >> Thanks for the additional documentation.

+1, thank you for this, it's really helpful to avoid mistakes and confusion during reviews.

...

> OK, I  was trying to make html output look pretty. If we want to favor
> .rst readability that is fine, I'll drop the :c:*: annotations.

I'm with Randy on this, let's try to make the text (source reST file) less noisy.

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH] Documentation: gpio: add documentation about using software nodes
  2025-08-11 21:30 [PATCH] Documentation: gpio: add documentation about using software nodes Dmitry Torokhov
  2025-08-12  0:46 ` Randy Dunlap
@ 2025-08-19 11:35 ` Linus Walleij
  1 sibling, 0 replies; 7+ messages in thread
From: Linus Walleij @ 2025-08-19 11:35 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Bartosz Golaszewski, Jonathan Corbet, Andy Shevchenko,
	Arnd Bergmann, Hans de Goede, linux-gpio, linux-doc, linux-kernel

On Mon, Aug 11, 2025 at 11:30 PM Dmitry Torokhov
<dmitry.torokhov@gmail.com> wrote:

> Introduce documentation regarding use of software nodes to describe
> GPIOs on legacy boards that have not been converted to device tree.
>
> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

Thanks for doing this!
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

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

end of thread, other threads:[~2025-08-19 11:35 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-11 21:30 [PATCH] Documentation: gpio: add documentation about using software nodes Dmitry Torokhov
2025-08-12  0:46 ` Randy Dunlap
2025-08-12  5:17   ` Dmitry Torokhov
2025-08-12  5:37     ` Randy Dunlap
2025-08-12 16:10       ` Dmitry Torokhov
2025-08-13 12:47         ` Andy Shevchenko
2025-08-19 11:35 ` Linus Walleij

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).