[RFC PATCH 12/15] dm: test: Add tests for uclass adjuncts

Simon Glass sjg at chromium.org
Thu Mar 19 22:35:42 CET 2026


Add a test driver and test cases for the DM_UC_ADJUNCT feature:

- testadj_drv: a UCLASS_TEST driver that registers an adjunct
  UCLASS_TEST_FDT uclass with custom ping ops during probe
- DTS node test-adj with compatible "denx,u-boot-test-adj"

Test cases:
- dm_test_adj_add: verify the device is discoverable in the adjunct
  uclass via uclass_find_device_by_ofnode()
- dm_test_adj_ops: verify device_get_adj_ops() returns the correct ops
  and the adjunct ping() produces the expected result
- dm_test_adj_uclass_ops: verify device_get_uclass_ops() resolves the
  correct ops for both primary and adjunct uclasses
- dm_test_adj_remove: verify removing a device cleans up adjuncts
- dm_test_adj_uclass_priv: verify per_device_auto allocation for
  adjuncts when the uclass driver requests it

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

 arch/sandbox/dts/test.dts |   4 +
 drivers/misc/test_drv.c   |  35 ++-
 test/dm/Makefile          |   1 +
 test/dm/adjunct.c         | 455 ++++++++++++++++++++++++++++++++++++++
 test/dm/bus.c             |   9 +-
 test/dm/test-fdt.c        |  39 ++--
 test/dm/test-uclass.c     |   2 +-
 7 files changed, 518 insertions(+), 27 deletions(-)
 create mode 100644 test/dm/adjunct.c

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index ac92ebf1afd..fe2dea50f2c 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -536,6 +536,10 @@
 		compatible = "google,another-fdt-test";
 	};
 
+	test-adj {
+		compatible = "denx,u-boot-test-adj";
+	};
+
 	e-test {
 		reg = <3 1>;
 		ping-expect = <6>;
diff --git a/drivers/misc/test_drv.c b/drivers/misc/test_drv.c
index 9b1e357a139..4c7ce36625b 100644
--- a/drivers/misc/test_drv.c
+++ b/drivers/misc/test_drv.c
@@ -200,7 +200,7 @@ int testfdt_ping(struct udevice *dev, int pingval, int *pingret)
 {
 	const struct test_ops *ops = device_get_ops(dev);
 
-	if (!ops->ping)
+	if (!ops || !ops->ping)
 		return -ENOSYS;
 
 	return ops->ping(dev, pingval, pingret);
@@ -229,3 +229,36 @@ UCLASS_DRIVER(testfdtm) = {
 	.id		= UCLASS_TEST_FDT_MANUAL,
 	.flags		= DM_UC_FLAG_SEQ_ALIAS | DM_UC_FLAG_NO_AUTO_SEQ,
 };
+
+#if CONFIG_IS_ENABLED(DM_UC_ADJUNCT)
+
+static int testadj_ping(struct udevice *dev, int pingval, int *pingret)
+{
+	*pingret = pingval + 100;
+
+	return 0;
+}
+
+static const struct test_ops testadj_ops = {
+	.ping = testadj_ping,
+};
+
+static const struct driver_adjunct testadj_adjuncts[] = {
+	{ UCLASS_TEST_FDT, &testadj_ops },
+	{ }
+};
+
+static const struct udevice_id testadj_ids[] = {
+	{ .compatible = "denx,u-boot-test-adj" },
+	{ }
+};
+
+U_BOOT_DRIVER(denx_u_boot_test_adj) = {
+	.name	= "testadj_drv",
+	.of_match	= testadj_ids,
+	.id	= UCLASS_TEST,
+	.adjuncts	= testadj_adjuncts,
+	.priv_auto	= sizeof(struct dm_test_priv),
+	.plat_auto	= sizeof(struct dm_test_pdata),
+};
+#endif /* DM_UC_ADJUNCT */
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 771b703b737..40819065c53 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_DM_GPIO) += gpio.o
 obj-y += irq.o
 endif
 obj-$(CONFIG_ADC) += adc.o
+obj-$(CONFIG_DM_UC_ADJUNCT) += adjunct.o
 obj-$(CONFIG_AES_SOFTWARE) += aes.o
 obj-$(CONFIG_SOUND) += audio.o
 obj-$(CONFIG_AXI) += axi.o
diff --git a/test/dm/adjunct.c b/test/dm/adjunct.c
new file mode 100644
index 00000000000..3879f098c86
--- /dev/null
+++ b/test/dm/adjunct.c
@@ -0,0 +1,455 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Tests for uclass adjunct support (DM_UC_ADJUNCT)
+ *
+ * Copyright 2026 Canonical Ltd.
+ * Simon Glass <simon.glass at canonical.com>
+ */
+
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/test.h>
+#include <dm/uclass-internal.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+#if CONFIG_IS_ENABLED(DM_UC_ADJUNCT)
+
+/* Test that a bound device is findable in its adjunct uclass */
+static int dm_test_adj_add(struct unit_test_state *uts)
+{
+	struct udevice *dev, *found;
+	ofnode node;
+
+	uts->skip_post_probe = 1;
+	ut_assertok(uclass_find_device_by_name(UCLASS_TEST, "test-adj",
+					       &dev));
+
+	node = dev_ofnode(dev);
+	ut_assert(ofnode_valid(node));
+
+	/* Static adjuncts are bound at bind time, so findable without probe */
+	ut_assertok(uclass_find_device_by_ofnode(UCLASS_TEST_FDT, node,
+						 &found));
+	ut_asserteq_ptr(dev, found);
+
+	return 0;
+}
+DM_TEST(dm_test_adj_add, UTF_SCAN_FDT);
+
+/* Test that device_get_uclass_ops() resolves the right ops */
+static int dm_test_adj_uclass_ops(struct unit_test_state *uts)
+{
+	const struct test_ops *ops;
+	struct udevice *dev;
+	int pingret;
+
+	uts->skip_post_probe = 1;
+	ut_assertok(uclass_find_device_by_name(UCLASS_TEST, "test-adj",
+					       &dev));
+	ut_assertok(device_probe(dev));
+
+	/* Adjunct uclass should return the adjunct ops */
+	ops = (void *)device_get_uclass_ops(dev, UCLASS_TEST_FDT);
+	ut_assertnonnull(ops);
+	ut_assertok(ops->ping(dev, 7, &pingret));
+	ut_asserteq(107, pingret);
+
+	/* Primary uclass returns driver ops (NULL for this driver) */
+	ut_assertnull(device_get_uclass_ops(dev, UCLASS_TEST));
+
+	/* Unrelated uclass returns NULL */
+	ut_assertnull(device_get_uclass_ops(dev, UCLASS_NOP));
+
+	return 0;
+}
+DM_TEST(dm_test_adj_uclass_ops, UTF_SCAN_FDT);
+
+/* Test that removing and unbinding a device cleans up adjuncts */
+static int dm_test_adj_remove(struct unit_test_state *uts)
+{
+	struct udevice *dev, *found;
+	ofnode node;
+
+	uts->skip_post_probe = 1;
+	ut_assertok(uclass_find_device_by_name(UCLASS_TEST, "test-adj",
+					       &dev));
+	ut_assertok(device_probe(dev));
+
+	node = dev_ofnode(dev);
+
+	/* Verify it is findable before removal */
+	ut_assertok(uclass_find_device_by_ofnode(UCLASS_TEST_FDT, node,
+						 &found));
+
+	/* Remove frees priv but adjunct stays bound */
+	ut_assertok(device_remove(dev, DM_REMOVE_NORMAL));
+	ut_assertok(uclass_find_device_by_ofnode(UCLASS_TEST_FDT, node,
+						 &found));
+	ut_asserteq_ptr(dev, found);
+
+	/* Unbind removes the adjunct from the uclass */
+	ut_assertok(device_unbind(dev));
+	ut_asserteq(-ENODEV,
+		    uclass_find_device_by_ofnode(UCLASS_TEST_FDT, node,
+						 &found));
+
+	return 0;
+}
+DM_TEST(dm_test_adj_remove, UTF_SCAN_FDT);
+
+/*
+ * Test per_device_auto allocation for adjuncts.
+ *
+ * UCLASS_TEST_FDT does not have per_device_auto, so its uclass_priv_
+ * should be NULL. UCLASS_TEST_BUS has both per_device_auto and
+ * per_device_plat_auto, so adding it as an adjunct should allocate both.
+ *
+ * Also test the uclass-ID-keyed accessors (device_get_uclass_priv
+ * and device_get_uclass_plat).
+ */
+static int dm_test_adj_uclass_priv(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+
+	uts->skip_post_probe = 1;
+	ut_assertok(uclass_find_device_by_name(UCLASS_TEST, "test-adj",
+					       &dev));
+	ut_assertok(device_probe(dev));
+
+	/* UCLASS_TEST_FDT has no per_device_auto, so priv is NULL */
+	ut_assertnull(device_get_adj_uclass_priv(dev, UCLASS_TEST_FDT));
+	ut_assertnull(device_get_uclass_priv(dev, UCLASS_TEST_FDT));
+
+	/*
+	 * Add a second adjunct for UCLASS_TEST_BUS which has
+	 * per_device_auto and per_device_plat_auto set. Since the
+	 * device is already probed, both plat and priv are allocated.
+	 */
+	ut_assertok(device_add_uclass_adj(dev, UCLASS_TEST_BUS, NULL));
+
+	/* Plat should be allocated */
+	ut_assertnonnull(device_get_uclass_plat(dev, UCLASS_TEST_BUS));
+
+	/* Priv should be allocated (device is active) */
+	ut_assertnonnull(device_get_adj_uclass_priv(dev, UCLASS_TEST_BUS));
+	ut_asserteq_ptr(device_get_adj_uclass_priv(dev, UCLASS_TEST_BUS),
+			device_get_uclass_priv(dev, UCLASS_TEST_BUS));
+
+	/* Non-existent adjunct should return NULL */
+	ut_assertnull(device_get_uclass_priv(dev, UCLASS_NOP));
+	ut_assertnull(device_get_uclass_plat(dev, UCLASS_NOP));
+
+	return 0;
+}
+DM_TEST(dm_test_adj_uclass_priv, UTF_SCAN_FDT);
+
+/*
+ * Test ucm_find_first/ucm_find_next - walk every member of UCLASS_TEST_FDT,
+ * asserting the device name and uclass at each step. The adjunct (test-adj)
+ * has primary uclass UCLASS_TEST but appears here via its adjunct
+ * registration.
+ */
+static int dm_test_ucm_find(struct unit_test_state *uts)
+{
+	struct uclass_member *ucm;
+
+	uts->skip_post_probe = 1;
+
+	ut_assertok(ucm_find_first(UCLASS_TEST_FDT, &ucm));
+	ut_asserteq_str("a-test", ucm->dev->name);
+	ut_asserteq(UCLASS_TEST_FDT, device_get_uclass_id(ucm->dev));
+
+	ucm_find_next(&ucm);
+	ut_asserteq_str("b-test", ucm->dev->name);
+	ut_asserteq(UCLASS_TEST_FDT, device_get_uclass_id(ucm->dev));
+
+	ucm_find_next(&ucm);
+	ut_asserteq_str("d-test", ucm->dev->name);
+	ut_asserteq(UCLASS_TEST_FDT, device_get_uclass_id(ucm->dev));
+
+	/* The adjunct's device has primary uclass UCLASS_TEST */
+	ucm_find_next(&ucm);
+	ut_asserteq_str("test-adj", ucm->dev->name);
+	ut_asserteq(UCLASS_TEST, device_get_uclass_id(ucm->dev));
+
+	ucm_find_next(&ucm);
+	ut_asserteq_str("e-test", ucm->dev->name);
+	ut_asserteq(UCLASS_TEST_FDT, device_get_uclass_id(ucm->dev));
+
+	ucm_find_next(&ucm);
+	ut_asserteq_str("f-test", ucm->dev->name);
+
+	ucm_find_next(&ucm);
+	ut_asserteq_str("g-test", ucm->dev->name);
+
+	ucm_find_next(&ucm);
+	ut_asserteq_str("h-test", ucm->dev->name);
+
+	ucm_find_next(&ucm);
+	ut_asserteq_str("another-test", ucm->dev->name);
+
+	ucm_find_next(&ucm);
+	ut_asserteq_str("chosen-test", ucm->dev->name);
+
+	ucm_find_next(&ucm);
+	ut_assertnull(ucm);
+
+	return 0;
+}
+DM_TEST(dm_test_ucm_find, UTF_SCAN_FDT);
+
+/*
+ * Test ucm_first_check/ucm_next_check - iterate with probing, verify
+ * the adjunct device is found and probes OK.
+ */
+static int dm_test_ucm_check(struct unit_test_state *uts)
+{
+	struct uclass_member *ucm;
+
+	uts->skip_post_probe = 1;
+
+	/* ucm_first_check probes the first device */
+	ut_assertok(ucm_first_check(UCLASS_TEST_FDT, &ucm));
+	ut_asserteq_str("a-test", ucm->dev->name);
+
+	ut_assertok(ucm_next_check(&ucm));
+	ut_asserteq_str("b-test", ucm->dev->name);
+
+	ut_assertok(ucm_next_check(&ucm));
+	ut_asserteq_str("d-test", ucm->dev->name);
+
+	/* The adjunct device probes OK via its primary driver */
+	ut_assertok(ucm_next_check(&ucm));
+	ut_asserteq_str("test-adj", ucm->dev->name);
+	ut_asserteq(UCLASS_TEST, device_get_uclass_id(ucm->dev));
+
+	return 0;
+}
+DM_TEST(dm_test_ucm_check, UTF_SCAN_FDT);
+
+/* Test ucm_first/ucm_next (probe-and-skip) */
+static int dm_test_ucm_first(struct unit_test_state *uts)
+{
+	struct uclass_member *ucm;
+
+	uts->skip_post_probe = 1;
+
+	/* ucm_first probes and returns the first usable member */
+	ucm = ucm_first(UCLASS_TEST_FDT);
+	ut_asserteq_str("a-test", ucm->dev->name);
+
+	ucm = ucm_next(ucm);
+	ut_asserteq_str("b-test", ucm->dev->name);
+
+	ucm = ucm_next(ucm);
+	ut_asserteq_str("d-test", ucm->dev->name);
+
+	/* The adjunct device probes OK and appears in iteration */
+	ucm = ucm_next(ucm);
+	ut_asserteq_str("test-adj", ucm->dev->name);
+	ut_asserteq(UCLASS_TEST, device_get_uclass_id(ucm->dev));
+
+	return 0;
+}
+DM_TEST(dm_test_ucm_first, UTF_SCAN_FDT);
+
+/* Test ucm_first_drvdata */
+static int dm_test_ucm_drvdata(struct unit_test_state *uts)
+{
+	struct uclass_member *ucm;
+	struct udevice *dev;
+
+	uts->skip_post_probe = 1;
+
+	/* Find a device with DM_TEST_TYPE_FIRST */
+	ut_assertok(ucm_first_drvdata(UCLASS_TEST_FDT, DM_TEST_TYPE_FIRST,
+				      &ucm));
+	ut_assertnonnull(ucm);
+	ut_asserteq(DM_TEST_TYPE_FIRST, dev_get_driver_data(ucm->dev));
+
+	/* Find a device with DM_TEST_TYPE_SECOND */
+	ut_assertok(ucm_first_drvdata(UCLASS_TEST_FDT, DM_TEST_TYPE_SECOND,
+				      &ucm));
+	ut_assertnonnull(ucm);
+	ut_asserteq(DM_TEST_TYPE_SECOND, dev_get_driver_data(ucm->dev));
+
+	/* Non-existent driver data should return -ENODEV */
+	ut_asserteq(-ENODEV, ucm_first_drvdata(UCLASS_TEST_FDT, 999, &ucm));
+
+	/* Probe the adjunct (its driver_data defaults to 0 = FIRST) */
+	ut_assertok(uclass_find_device_by_name(UCLASS_TEST, "test-adj",
+					       &dev));
+	ut_assertok(device_probe(dev));
+
+	/*
+	 * The adjunct should be findable with DM_TEST_TYPE_FIRST. Walk
+	 * all matches and check the adjunct device appears.
+	 */
+	ut_assertok(ucm_first_drvdata(UCLASS_TEST_FDT, DM_TEST_TYPE_FIRST,
+				      &ucm));
+	ut_assertnonnull(ucm);
+
+	return 0;
+}
+DM_TEST(dm_test_ucm_drvdata, UTF_SCAN_FDT);
+
+/* Test ucm_try_first */
+static int dm_test_ucm_try_first(struct unit_test_state *uts)
+{
+	struct uclass_member *ucm;
+
+	uts->skip_post_probe = 1;
+
+	/* Valid uclass with devices should return non-NULL */
+	ucm = ucm_try_first(UCLASS_TEST_FDT);
+	ut_assertnonnull(ucm);
+	ut_assertnonnull(ucm->dev);
+
+	/* Non-existent uclass should return NULL */
+	ucm = ucm_try_first(UCLASS_COUNT);
+	ut_assertnull(ucm);
+
+	return 0;
+}
+DM_TEST(dm_test_ucm_try_first, UTF_SCAN_FDT);
+
+/*
+ * Test the full adjunct lifecycle: bind → probe → remove → re-probe →
+ * remove → unbind, verifying allocations and uclass membership at each step.
+ *
+ * Uses UCLASS_TEST_BUS as a dynamic adjunct because it has both
+ * per_device_auto and per_device_plat_auto, so we can track priv and
+ * plat allocation across lifecycle transitions.
+ */
+static int dm_test_adj_lifecycle(struct unit_test_state *uts)
+{
+	void *priv1, *plat;
+	struct udevice *dev, *found;
+	ofnode node;
+
+	uts->skip_post_probe = 1;
+
+	/* 1. BIND: device is bound via FDT scan, static adjunct too */
+	ut_assertok(uclass_find_device_by_name(UCLASS_TEST, "test-adj",
+					       &dev));
+	node = dev_ofnode(dev);
+	ut_assert(ofnode_valid(node));
+
+	/* Static adjunct (TEST_FDT) is in the uclass before probe */
+	ut_assertok(uclass_find_device_by_ofnode(UCLASS_TEST_FDT, node,
+						 &found));
+	ut_asserteq_ptr(dev, found);
+
+	/* No priv or plat yet (TEST_FDT has neither per_device_auto) */
+	ut_assertnull(device_get_adj_uclass_priv(dev, UCLASS_TEST_FDT));
+	ut_assertnull(device_get_adj_uclass_plat(dev, UCLASS_TEST_FDT));
+
+	/* Device should not be active */
+	ut_assert(!device_active(dev));
+
+	/* 2. PROBE: device and adjuncts get priv allocated */
+	ut_assertok(device_probe(dev));
+	ut_assert(device_active(dev));
+
+	/* Driver priv should now exist */
+	ut_assertnonnull(dev_get_priv(dev));
+
+	/* TEST_FDT still has no per_device_auto, so priv stays NULL */
+	ut_assertnull(device_get_adj_uclass_priv(dev, UCLASS_TEST_FDT));
+
+	/* 3. ADD DYNAMIC ADJUNCT: TEST_BUS has per_device_auto + plat_auto */
+	ut_assertok(device_add_uclass_adj(dev, UCLASS_TEST_BUS, NULL));
+
+	/* Device is active, so both should be allocated immediately */
+	plat = device_get_adj_uclass_plat(dev, UCLASS_TEST_BUS);
+	ut_assertnonnull(plat);
+	priv1 = device_get_adj_uclass_priv(dev, UCLASS_TEST_BUS);
+	ut_assertnonnull(priv1);
+
+	/* Findable in all three uclasses */
+	ut_assertok(uclass_find_device_by_ofnode(UCLASS_TEST_FDT, node,
+						 &found));
+	ut_asserteq_ptr(dev, found);
+	ut_assertok(uclass_find_device_by_ofnode(UCLASS_TEST_BUS, node,
+						 &found));
+	ut_asserteq_ptr(dev, found);
+
+	/* 4. REMOVE: priv freed, adjuncts stay bound, plat stays */
+	ut_assertok(device_remove(dev, DM_REMOVE_NORMAL));
+	ut_assert(!device_active(dev));
+
+	/* Priv is gone */
+	ut_assertnull(device_get_adj_uclass_priv(dev, UCLASS_TEST_BUS));
+
+	/* Plat survives removal (freed only at unbind) */
+	ut_asserteq_ptr(plat,
+			device_get_adj_uclass_plat(dev, UCLASS_TEST_BUS));
+
+	/* Both adjuncts still in their uclass lists */
+	ut_assertok(uclass_find_device_by_ofnode(UCLASS_TEST_FDT, node,
+						 &found));
+	ut_asserteq_ptr(dev, found);
+	ut_assertok(uclass_find_device_by_ofnode(UCLASS_TEST_BUS, node,
+						 &found));
+	ut_asserteq_ptr(dev, found);
+
+	/* 5. RE-PROBE: priv gets reallocated */
+	ut_assertok(device_probe(dev));
+	ut_assert(device_active(dev));
+	ut_assertnonnull(device_get_adj_uclass_priv(dev, UCLASS_TEST_BUS));
+
+	/* 6. REMOVE + UNBIND: everything cleaned up */
+	ut_assertok(device_remove(dev, DM_REMOVE_NORMAL));
+	ut_assertok(device_unbind(dev));
+
+	/* Adjuncts gone from their uclasses */
+	ut_asserteq(-ENODEV,
+		    uclass_find_device_by_ofnode(UCLASS_TEST_FDT, node,
+						 &found));
+	ut_asserteq(-ENODEV,
+		    uclass_find_device_by_ofnode(UCLASS_TEST_BUS, node,
+						 &found));
+
+	return 0;
+}
+DM_TEST(dm_test_adj_lifecycle, UTF_SCAN_FDT);
+
+/* Test uclass_foreach_dev_probe includes adjuncts */
+static int dm_test_ucm_foreach_probe(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	int count = 0;
+
+	uts->skip_post_probe = 1;
+
+	/* Walk the probed iteration - adjuncts are included */
+	uclass_foreach_dev_probe(UCLASS_TEST_FDT, dev) {
+		switch (count++) {
+		case 0:
+			ut_asserteq_str("a-test", dev->name);
+			break;
+		case 1:
+			ut_asserteq_str("b-test", dev->name);
+			break;
+		case 2:
+			ut_asserteq_str("d-test", dev->name);
+			break;
+		case 3:
+			ut_asserteq_str("test-adj", dev->name);
+			break;
+		case 4:
+			ut_asserteq_str("e-test", dev->name);
+			break;
+		case 5:
+			ut_asserteq_str("f-test", dev->name);
+			break;
+		}
+	}
+	ut_assert(count >= 6);
+
+	return 0;
+}
+DM_TEST(dm_test_ucm_foreach_probe, UTF_SCAN_FDT);
+
+#endif /* DM_UC_ADJUNCT */
diff --git a/test/dm/bus.c b/test/dm/bus.c
index 7dd0d040650..480bb2c7942 100644
--- a/test/dm/bus.c
+++ b/test/dm/bus.c
@@ -23,19 +23,16 @@ DECLARE_GLOBAL_DATA_PTR;
 /* Test that we can probe for children */
 static int dm_test_bus_children(struct unit_test_state *uts)
 {
-	int num_devices = 9;
+	int num_devices = 10;
 	struct udevice *bus;
-	struct uclass *uc;
 
-	ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc));
-	ut_asserteq(num_devices, list_count_nodes(&uc->dev_head));
+	ut_asserteq(num_devices, uclass_id_count(UCLASS_TEST_FDT));
 
 	/* Probe the bus, which should yield 3 more devices */
 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
 	num_devices += 3;
 
-	ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc));
-	ut_asserteq(num_devices, list_count_nodes(&uc->dev_head));
+	ut_asserteq(num_devices, uclass_id_count(UCLASS_TEST_FDT));
 
 	ut_assert(!dm_check_devices(uts, num_devices));
 
diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c
index 295fdcaa0d8..169f49a3cb0 100644
--- a/test/dm/test-fdt.c
+++ b/test/dm/test-fdt.c
@@ -129,6 +129,10 @@ int dm_check_devices(struct unit_test_state *uts, int num_devices)
 		ret = uclass_get_device(UCLASS_TEST_FDT, i, &dev);
 		ut_assert(!ret);
 
+		/* Skip adjunct members - they are tested separately */
+		if (device_get_uclass_id(dev) != UCLASS_TEST_FDT)
+			continue;
+
 		/*
 		 * Get the 'ping-expect' property, which tells us what the
 		 * ping add should be. We don't use the plat because we
@@ -150,20 +154,16 @@ int dm_check_devices(struct unit_test_state *uts, int num_devices)
 /* Test that FDT-based binding works correctly */
 static int dm_test_fdt(struct unit_test_state *uts)
 {
-	const int num_devices = 9;
+	const int num_devices = 10;
 	struct udevice *dev;
-	struct uclass *uc;
 	int ret;
 	int i;
 
 	ret = dm_extended_scan(false);
 	ut_assert(!ret);
 
-	ret = uclass_get(UCLASS_TEST_FDT, &uc);
-	ut_assert(!ret);
-
 	/* These are num_devices compatible root-level device tree nodes */
-	ut_asserteq(num_devices, list_count_nodes(&uc->dev_head));
+	ut_asserteq(num_devices, uclass_id_count(UCLASS_TEST_FDT));
 
 	/* Each should have platform data but no private data */
 	for (i = 0; i < num_devices; i++) {
@@ -271,10 +271,10 @@ static int dm_test_fdt_uclass_seq(struct unit_test_state *uts)
 	ut_asserteq_str("d-test", dev->name);
 	ut_asserteq(13, dev_seq(dev));
 
-	/* g-test gets the next value after f-test */
-	ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 15, &dev));
+	/* g-test gets the next value after f-test (adjunct takes 14) */
+	ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 16, &dev));
 	ut_asserteq_str("g-test", dev->name);
-	ut_asserteq(15, dev_seq(dev));
+	ut_asserteq(16, dev_seq(dev));
 
 	/* And we should still have holes in our sequence numbers */
 	ut_asserteq(-ENODEV, uclass_find_device_by_seq(UCLASS_TEST_FDT, 0,
@@ -342,21 +342,22 @@ static int dm_test_fdt_uclass_seq_more(struct unit_test_state *uts)
 	 * last alias is 12, so we have:
 	 *
 	 * 13 d-test
-	 * 14 f-test
-	 * 15 g-test
-	 * 16 h-test
-	 * 17 another-test
-	 * 18 chosen-test
+	 * 14 test-adj (adjunct)
+	 * 15 f-test
+	 * 16 g-test
+	 * 17 h-test
+	 * 18 another-test
+	 * 19 chosen-test
 	 *
-	 * So next available is 19
+	 * So next available is 20
 	 */
 	ut_assertok(device_bind(dm_root(), DM_DRIVER_GET(denx_u_boot_fdt_test),
 				"fred", NULL, ofnode_null(), &dev));
-	ut_asserteq(19, dev_seq(dev));
+	ut_asserteq(20, dev_seq(dev));
 
 	ut_assertok(device_bind(dm_root(), DM_DRIVER_GET(denx_u_boot_fdt_test),
 				"fred2", NULL, ofnode_null(), &dev));
-	ut_asserteq(20, dev_seq(dev));
+	ut_asserteq(21, dev_seq(dev));
 
 	return 0;
 }
@@ -467,12 +468,12 @@ static int dm_test_uclass_foreach(struct unit_test_state *uts)
 	count = 0;
 	uclass_id_foreach_dev(UCLASS_TEST_FDT, dev, uc)
 		count++;
-	ut_asserteq(9, count);
+	ut_asserteq(10, count);
 
 	count = 0;
 	uclass_foreach_dev(dev, uc)
 		count++;
-	ut_asserteq(9, count);
+	ut_asserteq(10, count);
 
 	return 0;
 }
diff --git a/test/dm/test-uclass.c b/test/dm/test-uclass.c
index ee2ed1b6643..b48f7d17b15 100644
--- a/test/dm/test-uclass.c
+++ b/test/dm/test-uclass.c
@@ -78,7 +78,7 @@ static int test_post_probe(struct udevice *dev)
 	priv->base_add = 0;
 	if (uts->skip_post_probe)
 		return 0;
-	if (&prev->ucm.uc_node != &uc->dev_head) {
+	if (&prev->ucm.uc_node != &uc->dev_head && device_active(prev)) {
 		struct dm_test_uclass_perdev_priv *prev_uc_priv
 				= dev_get_uclass_priv(prev);
 		struct dm_test_pdata *pdata = dev_get_plat(prev);
-- 
2.43.0



More information about the U-Boot mailing list