[PATCH v2 37/45] dm: core: Add definitions for multiple ofnode trees

Simon Glass sjg at chromium.org
Wed Sep 7 04:27:25 CEST 2022


At present, unless OF_LIVE is enabled, ofnode only supports access to one
device tree, the control FDT. This is because only the node offset is
encoded in ofnode, with the tree being implicit.

This makes ofnode (without OF_LIVE) unsuitable for device tree fixups, as
implemented by ft_board_setup() and other such functions.

To solve this, we can use the top bits of the node offset to hold a tree
ID.

Add the definitions for this.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

(no changes since v1)

 drivers/core/Kconfig     | 24 ++++++++++++++++++++++++
 include/dm/ofnode_decl.h | 33 +++++++++++++++++++++++++++++++--
 2 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index 007dc6a1de3..c9bf5de4332 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -400,6 +400,30 @@ config DM_DEV_READ_INLINE
 	bool
 	default y if !OF_LIVE
 
+config OFNODE_MULTI_TREE
+	bool "Allow the ofnode interface to access any tree"
+	default y if EVENT && !DM_DEV_READ_INLINE && !DM_INLINE_OFNODE
+	help
+	  Normally U-Boot makes use of its control FDT, the one used to bind
+	  devices and provide options. In some cases, U-Boot must also process
+	  a separate FDT, e.g. one provided by the operating system, which
+	  needs additions to the /chosen node.
+
+	  This works fine with live tree (OF_LIVE), but with flat tree the
+	  offset provided in ofnode is only useful with the control FDT. This
+	  option adds a 'tree ID' to the offset, so that multiple trees can
+	  be used. Call oftree_from_fdt() to register a new tree.
+
+config OFNODE_MULTI_TREE_MAX
+	int "Maximum number of FDTs"
+	range 2 8
+	depends on OFNODE_MULTI_TREE
+	default 4
+	help
+	  Sets the maximum number of device trees which can be used with the
+	  ofnode interface when using flat trees (OF_LIVE). This is only
+	  available in U-Boot proper and only after relocation.
+
 config ACPIGEN
 	bool "Support ACPI table generation in driver model"
 	default y if SANDBOX || (GENERATE_ACPI_TABLE && !QEMU)
diff --git a/include/dm/ofnode_decl.h b/include/dm/ofnode_decl.h
index f666a0287ba..5c2115aab0b 100644
--- a/include/dm/ofnode_decl.h
+++ b/include/dm/ofnode_decl.h
@@ -31,8 +31,18 @@
  * this increases code size slightly due to the subtraction. Since it offers no
  * real benefit, the approach described here seems best.
  *
- * For now these points use constant types, since we don't allow writing
- * the DT.
+ * Where multiple trees are in use, this works without any trouble with live
+ * tree, except for aliases, such as ofnode_path("mmc0"), which only work on the
+ * control FDT. When the flat tree is in use, the trees are registered and a
+ * 'tree ID' is encoded into the top bits of @of_offset - see immediately below
+ * for the associated macro definitions. Note that 64-bit machines use the same
+ * encoding, even though there is more space available. This is partly because
+ * the FDT format contains 32-bit values for things like the string-table
+ * offset, therefore 64-bit offsets cannot be supported anyway.
+ *
+ * For the multiple-tree case, an invalid offset (i.e. with of_offset < 0) is
+ * still invalid. It does not contain a tree ID. So there is no way of knowing
+ * which tree produced the invalid offset.
  *
  * @np: Pointer to device node, used for live tree
  * @of_offset: Pointer into flat device tree, used for flat tree. Note that this
@@ -43,6 +53,25 @@ typedef union ofnode_union {
 	long of_offset;
 } ofnode;
 
+/* shift for the tree ID within of_offset */
+#define OF_TREE_SHIFT 28
+
+/* mask to obtain the device tree offset from of_offset */
+#define OF_TREE_MASK ((1 << OF_TREE_SHIFT) - 1)
+
+/* encode a tree ID and node offset into an of_offset value */
+#define OFTREE_NODE(tree_id, offs)	((tree_id) << OF_TREE_SHIFT | (offs))
+
+/* decode the node offset from an of_offset value */
+#define OFTREE_OFFSET(of_offs)		((of_offs) & OF_TREE_MASK)
+
+/* decode the tree ID from an of_offset value */
+#define OFTREE_TREE_ID(of_offs)		((of_offs) >> OF_TREE_SHIFT)
+
+/* encode a node offset in the tree given by another node's of_offset value */
+#define OFTREE_MAKE_NODE(other_of_offset, offs)	\
+		(((offs) & OF_TREE_MASK) | ((other_of_offset) & ~OF_TREE_MASK))
+
 /**
  * struct ofprop - reference to a property of a device tree node
  *
-- 
2.37.2.789.g6183377224-goog



More information about the U-Boot mailing list