@samitouri / QOSamiQemu / commits / e5f73c36db

tests/qtest: pca9554: test output-to-input reflection and pull-ups

Check that a pin configured as output drives its OUTPUT register level onto the pin (push-pull) as reflected by the INPUT register, and that a pin configured as input floats high through its pull-up. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> Reviewed-by: Glenn Miles <milesg@linux.ibm.com> Link: https://lore.kernel.org/qemu-devel/20260709-catalina-upgrade-v1-20-82a63fead90c@free.fr Signed-off-by: Cédric Le Goater <clg@redhat.com>

Emmanuel Blot committed Jul 9, 2026 at 17:23 UTC e5f73c36dbf0f52e1006d907d5ef283c9c01b52c
1 file changed +45
tests/qtest/pca9554-test.c
+45
@@ -25,6 +25,48 @@ static void test_reset_defaults(void *obj, void *data, QGuestAllocator *alloc)
25 g_assert_cmphex(i2c_get8(dev, PCA9554_CONFIG), ==, 0xFF);
26 }
27
28 +/*
29 + * A pin configured as output (config=0) drives its OUTPUT register level onto
30 + * the pin (push-pull), which the INPUT register reflects. A pin configured as
31 + * input (config=1) floats high through its pull-up.
32 + */
33 +static void test_output_drives_input(void *obj, void *data,
34 + QGuestAllocator *alloc)
35 +{
36 + QI2CDevice *dev = (QI2CDevice *)obj;
37 +
38 + /* Low nibble output, high nibble input (pull-up). */
39 + i2c_set8(dev, PCA9554_CONFIG, 0xF0);
40 + i2c_set8(dev, PCA9554_OUTPUT, 0xFA);
41 + g_assert_cmphex(i2c_get8(dev, PCA9554_INPUT), ==, 0xFA);
42 +
43 + /* All outputs, driven low then high. */
44 + i2c_set8(dev, PCA9554_CONFIG, 0x00);
45 + i2c_set8(dev, PCA9554_OUTPUT, 0x00);
46 + g_assert_cmphex(i2c_get8(dev, PCA9554_INPUT), ==, 0x00);
47 +
48 + i2c_set8(dev, PCA9554_OUTPUT, 0xFF);
49 + g_assert_cmphex(i2c_get8(dev, PCA9554_INPUT), ==, 0xFF);
50 +}
51 +
52 +/*
53 + * With all pins configured as inputs the pull-ups make the INPUT register read
54 + * all ones regardless of the OUTPUT register; switching a pin to output with
55 + * output=0 drives it low.
56 + */
57 +static void test_input_pullup(void *obj, void *data, QGuestAllocator *alloc)
58 +{
59 + QI2CDevice *dev = (QI2CDevice *)obj;
60 +
61 + g_assert_cmphex(i2c_get8(dev, PCA9554_INPUT), ==, 0xFF);
62 +
63 + i2c_set8(dev, PCA9554_OUTPUT, 0x00);
64 + g_assert_cmphex(i2c_get8(dev, PCA9554_INPUT), ==, 0xFF);
65 +
66 + i2c_set8(dev, PCA9554_CONFIG, 0x00);
67 + g_assert_cmphex(i2c_get8(dev, PCA9554_INPUT), ==, 0x00);
68 +}
69 +
70 static void pca9554_register_nodes(void)
71 {
72 QOSGraphEdgeOptions opts = {
@@ -36,6 +78,9 @@ static void pca9554_register_nodes(void)
78 qos_node_consumes("pca9554", "i2c-bus", &opts);
79
80 qos_add_test("reset-defaults", "pca9554", test_reset_defaults, NULL);
81 + qos_add_test("output-drives-input", "pca9554", test_output_drives_input,
82 + NULL);
83 + qos_add_test("input-pullup", "pca9554", test_input_pullup, NULL);
84 }
85
86 libqos_init(pca9554_register_nodes);