[RFC PATCH 07/15] dm: core: Add uclass-adjunct data structures
Simon Glass
sjg at chromium.org
Thu Mar 19 22:35:37 CET 2026
Add the data structures needed to support uclass adjuncts, which allow
a device to belong to more than one uclass.
Make the dev back-pointer in struct uclass_member unconditional so it
works for both primary (embedded) and adjunct (standalone) memberships.
This simplifies the list traversal at a cost of an extra pointer in
every device (even without DM_UC_ADJUNCT).
Add adj_head to struct udevice and adj_node to struct uclass_member
(both conditional on DM_UC_ADJUNCT) for chaining a device's uclass
memberships.
Update dtoc to generate the .dev field in ucm initialisers.
No functional change is intended.
Signed-off-by: Simon Glass <sjg at chromium.org>
---
drivers/core/Kconfig | 10 ++++++++++
include/dm/device.h | 9 +++++----
include/dm/uclass.h | 4 +++-
tools/dtoc/dtb_platdata.py | 1 +
tools/dtoc/test_dtoc.py | 7 +++++++
5 files changed, 26 insertions(+), 5 deletions(-)
diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index c9253099e6e..8d72c7838b8 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -85,6 +85,16 @@ config DM_STATS
To display the memory stats, use the 'dm mem' command.
+config DM_UC_ADJUNCT
+ bool "Support uclass adjuncts for devices"
+ depends on DM
+ default y if SANDBOX
+ help
+ Allow a device to belong to more than one uclass.
+ A device bound to one uclass (e.g. UCLASS_PHY) can register
+ adjunct uclasses (e.g. UCLASS_CLK) at bind/probe-time via
+ device_add_uclass_adj(). If unsure, say N.
+
config SPL_DM_STATS
bool "Collect and show driver model stats in SPL"
depends on SPL_DM
diff --git a/include/dm/device.h b/include/dm/device.h
index 5824476f91d..ebc253397a4 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -131,10 +131,9 @@ enum {
* @uc_priv: Per-device private data owned by the uclass
* @uc_plat: Per-device platform data owned by the uclass
* @seq: Sequence number within this uclass (-1 = none)
+ * @dev: Owning device (set for both primary and adjunct memberships)
* @ops: Ops provided by this device for the uclass
- * @dev: Owning device (adjuncts only; for the primary uclass use
- * container_of)
- * @adj_node: Node in the device's list of adjuncts
+ * @adj_node: Node in the owning device's adj_head list (struct udevice)
*/
struct uclass_member {
struct uclass *uc;
@@ -142,9 +141,9 @@ struct uclass_member {
void *uc_priv;
void *uc_plat;
int seq;
+ struct udevice *dev;
const void *ops;
#if CONFIG_IS_ENABLED(DM_UC_ADJUNCT)
- struct udevice *dev;
struct list_head adj_node;
#endif
};
@@ -177,6 +176,8 @@ struct uclass_member {
* @parent: Parent of this device, or NULL for the top level device
* @priv_: Private data for this device (do not access outside driver model)
* @ucm: Primary uclass membership (do not access outside driver model)
+ * @adj_head: List of all uclass memberships including the primary (struct
+ * uclass_member via adj_node)
* @parent_priv_: The parent's private data for this device (do not access
* outside driver model)
* @child_head: List of children of this device
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index b76797eeabd..ad49d675570 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -28,7 +28,8 @@
* @uc_drv: The driver for the uclass itself, not to be confused with a
* 'struct driver'
* @dev_head: List of devices in this uclass (devices are attached to their
- * uclass when their bind method is called)
+ * uclass when their bind method is called). Adjunct registrations also appear
+ * on this list as standalone struct uclass_member entries.
* @sibling_node: Next uclass in the linked list of uclasses
*/
struct uclass {
@@ -39,6 +40,7 @@ struct uclass {
};
struct driver;
+struct uclass_member;
struct udevice;
/* Members of this uclass sequence themselves with aliases */
diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py
index a570fd3b9a9..b6b8dd4a477 100644
--- a/tools/dtoc/dtb_platdata.py
+++ b/tools/dtoc/dtb_platdata.py
@@ -769,6 +769,7 @@ class DtbPlatdata():
self.buf('\t\t.uc_plat = %s,\n' % uclass_plat_name)
self.list_node('uc_node', uclass.node_refs, node.uclass_seq, indent=2)
self.buf('\t\t.seq\t= %d,\n' % node.seq)
+ self.buf('\t\t.dev\t= DM_DEVICE_REF(%s),\n' % node.var_name)
self.buf('\t},\n')
if parent_priv_name:
diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py
index 6bbf800adec..e4542b174a5 100755
--- a/tools/dtoc/test_dtoc.py
+++ b/tools/dtoc/test_dtoc.py
@@ -566,6 +566,7 @@ DM_DEVICE_INST(i2c) = {
\t\t\t.next = &DM_UCLASS_REF(i2c)->dev_head,
\t\t},
\t\t.seq\t= 4,
+\t\t.dev\t= DM_DEVICE_REF(i2c),
\t},
\t.child_head\t= {
\t\t.prev = &DM_DEVICE_REF(i2c)->child_head,
@@ -595,6 +596,7 @@ DM_DEVICE_INST(root) = {
\t\t\t.next = &DM_UCLASS_REF(root)->dev_head,
\t\t},
\t\t.seq\t= 0,
+\t\t.dev\t= DM_DEVICE_REF(root),
\t},
\t.child_head\t= {
\t\t.prev = &DM_DEVICE_REF(spl_test3)->sibling_node,
@@ -642,6 +644,7 @@ DM_DEVICE_INST(some_bus) = {
\t\t\t.next = &DM_UCLASS_REF(testbus)->dev_head,
\t\t},
\t\t.seq\t= 2,
+\t\t.dev\t= DM_DEVICE_REF(some_bus),
\t},
\t.child_head\t= {
\t\t.prev = &DM_DEVICE_REF(test0)->sibling_node,
@@ -673,6 +676,7 @@ DM_DEVICE_INST(spl_test) = {
\t\t\t.next = &DM_DEVICE_REF(spl_test3)->ucm.uc_node,
\t\t},
\t\t.seq\t= 0,
+\t\t.dev\t= DM_DEVICE_REF(spl_test),
\t},
\t.child_head\t= {
\t\t.prev = &DM_DEVICE_REF(spl_test)->child_head,
@@ -704,6 +708,7 @@ DM_DEVICE_INST(spl_test3) = {
\t\t\t.next = &DM_UCLASS_REF(misc)->dev_head,
\t\t},
\t\t.seq\t= 1,
+\t\t.dev\t= DM_DEVICE_REF(spl_test3),
\t},
\t.child_head\t= {
\t\t.prev = &DM_DEVICE_REF(spl_test3)->child_head,
@@ -754,6 +759,7 @@ DM_DEVICE_INST(test) = {
\t\t\t.next = &DM_DEVICE_REF(test0)->ucm.uc_node,
\t\t},
\t\t.seq\t= 1,
+\t\t.dev\t= DM_DEVICE_REF(test),
\t},
\t.parent_priv_\t= _denx_u_boot_fdt_test_parent_priv_test,
\t.child_head\t= {
@@ -802,6 +808,7 @@ DM_DEVICE_INST(test0) = {
\t\t\t.next = &DM_UCLASS_REF(testfdt)->dev_head,
\t\t},
\t\t.seq\t= 2,
+\t\t.dev\t= DM_DEVICE_REF(test0),
\t},
\t.parent_priv_\t= _denx_u_boot_fdt_test_parent_priv_test0,
\t.child_head\t= {
--
2.43.0
More information about the U-Boot
mailing list