[RFC PATCH 2/2] software node: Add documentation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



API documentation for the software nodes.

Signed-off-by: Heikki Krogerus <heikki.krogerus@xxxxxxxxxxxxxxx>
---
 Documentation/driver-api/software_node.rst | 197 +++++++++++++++++++++
 1 file changed, 197 insertions(+)
 create mode 100644 Documentation/driver-api/software_node.rst

diff --git a/Documentation/driver-api/software_node.rst b/Documentation/driver-api/software_node.rst
new file mode 100644
index 000000000000..cf8a05c34e9e
--- /dev/null
+++ b/Documentation/driver-api/software_node.rst
@@ -0,0 +1,197 @@
+
+.. _software_node:
+
+==============
+Software nodes
+==============
+
+Introduction
+============
+
+Software node is a :c:type:`struct fwnode_handle <fwnode_handle>` type,
+analogous to the ACPI and DT firmware nodes except that the software nodes are
+created in kernel code (hence the name "software" node). The software nodes can
+be used to complement fwnodes representing real firmware nodes when they are
+incomplete, for example missing device properties, and to supply the primary
+fwnode when the firmware lacks hardware description for a device completely.
+
+NOTE! The primary hardware description should always come from either ACPI
+tables or DT. Describing an entire system with software nodes, though possible,
+is not acceptable! The software nodes should only complement the primary
+hardware description.
+
+Hierarchy
+=========
+
+The software nodes support hierarchy (i.e. the software nodes can have child
+software nodes and a parent software node) just like ACPI and DT firmware nodes,
+but there is no dedicated root software node object. It means that a software
+node at the root level does not have a parent.
+
+Note! Only other software nodes can be children and the parent for a software
+node.
+
+Device properties
+=================
+
+The software node device properties are described with :c:type:`struct
+property_entry <property_entry>`. When a software node is created that has
+device properties, it is supplied with a zero terminated array of property
+entries. Normally the properties are described with helper macros::
+
+	static const u8 u8_array[] = { 0, 1, 2, 3 };
+	static const u16 u16_array[] = { 0, 1, 2, 3 };
+	static const u32 u32_array[] = { 0, 1, 2, 3 };
+	static const u64 u64_array[] = { 0, 1, 2, 3 };
+
+	static const struct property_entry my_props[] = {
+		PROPERTY_ENTRY_U8_ARRAY("u8_array_example", u8_array),
+		PROPERTY_ENTRY_U16_ARRAY("u16_array_example", u16_array),
+		PROPERTY_ENTRY_U32_ARRAY("u32_array_example", u32_array),
+		PROPERTY_ENTRY_U64_ARRAY("u64_array_example", u64_array),
+		PROPERTY_ENTRY_U8("u8_example", 0xff),
+		PROPERTY_ENTRY_U16("u16_example", 0xffff),
+		PROPERTY_ENTRY_U32("u32_example", 0xffffffff),
+		PROPERTY_ENTRY_U64("u64_example", 0xffffffffffffffff),
+		PROPERTY_ENTRY_STRING("string_example", "string"),
+		{ }
+	};
+
+Note! If "build-in" device properties are supplied to already existing device
+entries by using :c:func:`device_add_properties`, a software node is actually
+created for that device. That software node is just assigned to the device
+automatically in the function.
+
+Usage
+=====
+
+Node creation
+-------------
+
+Static nodes
+~~~~~~~~~~~~
+
+In a normal case the software nodes are described statically with
+:c:type:`struct software_node <software_node>`, and then registered with
+:c:func:`software_node_register`. Usually there is more then one software node
+that needs to be registered. A helper :c:func:`software_node_register_nodes`
+registers a zero terminated array of software nodes::
+
+	static const struct property_entry props[] = {
+		PROPERTY_ENTRY_STRING("foo", "bar"),
+		{ }
+	};
+
+	static const struct software_node my_nodes[] = {
+		{ "grandparent" },		/* no parent nor properties */
+		{ "parent", &my_nodes[0] },	/* parent, but no propreties */
+		{ "child", &my_nodes[1], props }, /* parent and properties */
+		{ }
+	};
+
+	static int my_init(void)
+	{
+		return software_node_register_nodes(my_nodes);
+	}
+
+Note! The above example names the nodes "grandparent", "parent" and "child", but
+the software nodes don't actually have to be named. If no name is supplied for a
+software node when it's being registered, the API names the node "node<n>" where
+<n> is index number.
+
+Dynamic nodes
+~~~~~~~~~~~~~
+
+The Quick (and dirty) method. A software node can be created on the fly with
+:c:func:`fwnode_create_software_node`. The nodes create "on-the-fly" don't
+differ from statically described software nodes in any way, but for now the API
+does not support naming of these nodes::
+
+	static const struct property_entry my_props[] = {
+		PROPERTY_ENTRY_STRING("foo", "bar"),
+		{ }
+	};
+
+	static int my_init(void)
+	{
+		struct fwnode_handle *fwnode;
+
+		/* Software node without a parent. */
+		fwnode = fwnode_create_software_node(my_props, NULL);
+		if (IS_ERR(fwnode))
+			return PTR_ERR(fwnode);
+
+		return -1;
+	}
+
+Linking software nodes with the device (struct device) entries
+--------------------------------------------------------------
+
+Ideally the software node should be assigned to the device entry before the
+device is registered (just like any other fwnode).
+
+When the software node is the primary fwnode for the device, the fwnode of the
+device needs to simply point to the software node fwnode. Using a helper
+:c:func:`software_node_fwnode` in the following example::
+
+	static const struct software_node my_node = {
+		.name = "thenode",
+	};
+
+	static int my_init(void)
+	{
+		struct device my_device = { };
+		int ret;
+
+		ret = software_node_register(my_node);
+		if (ret)
+			return ret;
+
+		device_initialize(&my_device);
+		dev_set_name(&my_device, "thedevice")
+
+		my_device.fwnode = software_node_fwnode(swnode);
+
+		return device_add(&my_device);
+	}
+
+When the software node is the secondary fwnode for a device, i.e. the device has
+either ACPI or DT (or something else) firmware node as the primary fwnode, the
+node should be assigned with :c:func:`set_secondary_fwnode`. If the
+``secondary`` member of the primary fwnode needs to be manually made to point
+to the software node, the code needs to make sure that the ``secondary`` member
+of the software node fwnode points to a specific value of ``ERR_PTR(-ENODEV)``::
+
+	struct fwnode_handle *fwnode = software_node_fwnode(swnode);
+
+	fwnode->secondary = ERR_PTR(-ENODEV);
+	dev->fwnode->secondary = fwnode;
+
+Note! There is no requirement to bind a software node with a device entry, i.e.
+having "sub-nodes" that represent for example certain resources the parent
+software node has is not a problem.
+
+Node References
+---------------
+
+TODO
+
+Device graph
+------------
+
+TODO
+
+API
+===
+
+.. kernel-doc:: include/linux/property.h
+   :internal: software_node
+
+.. kernel-doc:: include/linux/fwnode.h
+   :internal: fwnode_handle
+
+.. kernel-doc:: drivers/base/core.c
+   :functions: set_secondary_fwnode
+
+.. kernel-doc:: drivers/base/swnode.c
+   :functions: is_software_node is_software_node software_node_fwnode software_node_find_by_name software_node_register_nodes software_node_unregister_nodes software_node_register software_node_register fwnode_create_software_node fwnode_remove_software_node
-- 
2.23.0




[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux FS]     [Yosemite Forum]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux