summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPranav Sanwal <[email protected]>2026-07-30 15:18:17 +0530
committerTom Rini <[email protected]>2026-08-19 08:48:18 -0600
commitef019bb9ebce5f3025cd93f2da6d3b586a13293d (patch)
tree058870f9084e5fb863161358c32853172f1f5338
parent7b1ae01ed37ae3527422fdf5bd7ac8110e80c288 (diff)
test: dm: add sandbox coverage for gpio-delay
gpio-delay had no sandbox coverage, which is how two bugs in it went unnoticed: gpio_delay_xlate() never propagated the requested index into the descriptor offset, so every consumer past the first silently collided with the first consumer's already-claimed offset 0; and the claimed/name tracking arrays were sized and bounds-checked against a hardcoded 32 instead of the driver's actual GPIO count. Both are fixed by a companion series that is a dependency of this patch: applied without it, this test fails outright, since it directly exercises both fixes. Add a test requesting both consumers wired up by gpio-delay-test in test.dts (gpio_a 9 and 18): a third consumer colliding with an already-claimed offset must fail with -EBUSY, each consumer's write must land on its own wrapped GPIO line, and a request past the wrapped GPIO count must fail with -EINVAL rather than succeed against a hardcoded bound of 32. Gated on CONFIG_GPIO_DELAY, since not every sandbox variant that builds test/dm/gpio.c enables it (sandbox_vpl, sandbox_spl, sandbox_noinst, sandbox_flattree). Signed-off-by: Pranav Sanwal <[email protected]> Reviewed-by: Simon Glass <[email protected]>
-rw-r--r--test/dm/gpio.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/test/dm/gpio.c b/test/dm/gpio.c
index e9fa41ce9d4..3d966e0d1a6 100644
--- a/test/dm/gpio.c
+++ b/test/dm/gpio.c
@@ -446,6 +446,75 @@ static int dm_test_gpio_get_dir_flags(struct unit_test_state *uts)
}
DM_TEST(dm_test_gpio_get_dir_flags, UTF_SCAN_PDATA | UTF_SCAN_FDT);
+/*
+ * Test that gpio-delay correctly routes each consumer to its own wrapped
+ * real GPIO line. See gpio-delay-test in test.dts, which wraps gpio_a 9
+ * and gpio_a 18.
+ */
+#if IS_ENABLED(CONFIG_GPIO_DELAY)
+static int dm_test_gpio_delay(struct unit_test_state *uts)
+{
+ struct gpio_desc desc0, desc1, desc2, desc3;
+ struct udevice *dev, *gpio_a;
+
+ ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
+ ut_assertok(uclass_get_device(UCLASS_GPIO, 1, &gpio_a));
+ ut_asserteq_str("base-gpios", gpio_a->name);
+
+ /*
+ * Requesting both consumers must succeed. Before the offset was
+ * propagated in gpio_delay_xlate(), both descriptors came back with
+ * offset 0, so this second request would fail with -EBUSY as it
+ * collided with the first consumer's already-claimed offset.
+ */
+ ut_assertok(gpio_request_by_name(dev, "test6-gpios", 0, &desc0, 0));
+ ut_assertok(gpio_request_by_name(dev, "test6-gpios", 1, &desc1, 0));
+
+ ut_asserteq_ptr(desc0.dev, desc1.dev);
+ ut_asserteq(0, desc0.offset);
+ ut_asserteq(1, desc1.offset);
+
+ /*
+ * A third consumer mapped to the same offset as the first must be
+ * rejected as already requested.
+ */
+ ut_asserteq(-EBUSY, gpio_request_by_name(dev, "test6-gpios", 2, &desc2,
+ 0));
+
+ /*
+ * Drive each consumer to a different level and confirm the write
+ * lands on its own wrapped real GPIO line, not the other one's.
+ * gpio_a has no set_value op of its own (it implements set_flags),
+ * so dm_gpio_set_value() routes through GPIOD_IS_OUT_ACTIVE.
+ */
+ ut_assertok(dm_gpio_set_value(&desc0, 0));
+ ut_assertok(dm_gpio_set_value(&desc1, 1));
+ ut_asserteq(0, sandbox_gpio_get_flags(gpio_a, 9) & GPIOD_IS_OUT_ACTIVE);
+ ut_asserteq(GPIOD_IS_OUT_ACTIVE,
+ sandbox_gpio_get_flags(gpio_a, 18) & GPIOD_IS_OUT_ACTIVE);
+
+ ut_assertok(dm_gpio_set_value(&desc0, 1));
+ ut_assertok(dm_gpio_set_value(&desc1, 0));
+ ut_asserteq(GPIOD_IS_OUT_ACTIVE,
+ sandbox_gpio_get_flags(gpio_a, 9) & GPIOD_IS_OUT_ACTIVE);
+ ut_asserteq(0, sandbox_gpio_get_flags(gpio_a, 18) & GPIOD_IS_OUT_ACTIVE);
+
+ ut_assertok(dm_gpio_free(dev, &desc0));
+ ut_assertok(dm_gpio_free(dev, &desc1));
+
+ /*
+ * An index beyond the wrapped GPIO count (2 here) must be rejected.
+ * Before gpio_count was set from the "gpios" property, this bound
+ * was checked against a hardcoded 32 and would have been let through.
+ */
+ ut_asserteq(-EINVAL, gpio_request_by_name(dev, "test7-gpios", 0, &desc3,
+ 0));
+
+ return 0;
+}
+DM_TEST(dm_test_gpio_delay, UTF_SCAN_PDATA | UTF_SCAN_FDT);
+#endif /* CONFIG_GPIO_DELAY */
+
/* Test of gpio_get_acpi() */
static int dm_test_gpio_get_acpi(struct unit_test_state *uts)
{