Reviewed-by: Glenn Miles <[email protected]> Thanks,
Glenn On Thu, 2026-07-09 at 17:23 +0200, Emmanuel Blot wrote: > Add tests for the I2C command protocol of the GPIO variant: the > auto-increment that toggles bit 0 within a register pair on reads and > writes, and the 3-bit command wrapping that aliases out-of-range register > addresses back into the register window. > > Signed-off-by: Emmanuel Blot <[email protected]> > --- > tests/qtest/pca9555-test.c | 88 > ++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 88 insertions(+) > > diff --git a/tests/qtest/pca9555-test.c b/tests/qtest/pca9555-test.c > index 2afa061bd2..84d771bcbb 100644 > --- a/tests/qtest/pca9555-test.c > +++ b/tests/qtest/pca9555-test.c > @@ -139,6 +139,87 @@ static void test_polarity_with_output(void *obj, void > *data, > g_assert_cmphex(i2c_get8(dev, PCA9535_OUTPUT0), ==, 0xA5); > } > > +/* > + * The PCA9555 auto-increments by toggling bit 0 of the command pointer > + * within a register pair. Reading two bytes from INPUT0 should yield > + * INPUT0 then INPUT1. > + */ > +static void test_auto_increment_read(void *obj, void *data, > + QGuestAllocator *alloc) > +{ > + QI2CDevice *dev = (QI2CDevice *)obj; > + uint8_t buf[2]; > + > + i2c_set8(dev, PCA9535_CONFIG0, 0x00); > + i2c_set8(dev, PCA9535_CONFIG1, 0x00); > + i2c_set8(dev, PCA9535_OUTPUT0, 0xAA); > + i2c_set8(dev, PCA9535_OUTPUT1, 0x55); > + > + i2c_read_block(dev, PCA9535_INPUT0, buf, 2); > + g_assert_cmphex(buf[0], ==, 0xAA); > + g_assert_cmphex(buf[1], ==, 0x55); > + > + i2c_read_block(dev, PCA9535_OUTPUT0, buf, 2); > + g_assert_cmphex(buf[0], ==, 0xAA); > + g_assert_cmphex(buf[1], ==, 0x55); > +} > + > +/* > + * Auto-increment write: writing two data bytes after a command byte > + * should write to port 0 then port 1 of the addressed register pair. > + */ > +static void test_auto_increment_write(void *obj, void *data, > + QGuestAllocator *alloc) > +{ > + QI2CDevice *dev = (QI2CDevice *)obj; > + uint8_t buf[2]; > + > + buf[0] = 0x12; > + buf[1] = 0x34; > + i2c_write_block(dev, PCA9535_OUTPUT0, buf, 2); > + > + g_assert_cmphex(i2c_get8(dev, PCA9535_OUTPUT0), ==, 0x12); > + g_assert_cmphex(i2c_get8(dev, PCA9535_OUTPUT1), ==, 0x34); > + > + buf[0] = 0x0F; > + buf[1] = 0xF0; > + i2c_write_block(dev, PCA9535_CONFIG0, buf, 2); > + > + g_assert_cmphex(i2c_get8(dev, PCA9535_CONFIG0), ==, 0x0F); > + g_assert_cmphex(i2c_get8(dev, PCA9535_CONFIG1), ==, 0xF0); > +} > + > +/* > + * Auto-increment toggles within the pair: starting from port 1 should > + * wrap back to port 0 (toggle bit 0). > + */ > +static void test_auto_increment_toggle(void *obj, void *data, > + QGuestAllocator *alloc) > +{ > + QI2CDevice *dev = (QI2CDevice *)obj; > + uint8_t buf[2]; > + > + i2c_set8(dev, PCA9535_OUTPUT0, 0xAA); > + i2c_set8(dev, PCA9535_OUTPUT1, 0x55); > + > + i2c_read_block(dev, PCA9535_OUTPUT1, buf, 2); > + g_assert_cmphex(buf[0], ==, 0x55); > + g_assert_cmphex(buf[1], ==, 0xAA); > +} > + > +/* > + * Verify the command byte wraps at 3 bits: register addresses > + * beyond 7 should alias to the same register (bits [2:0] only). > + */ > +static void test_command_wrapping(void *obj, void *data, QGuestAllocator > *alloc) > +{ > + QI2CDevice *dev = (QI2CDevice *)obj; > + > + i2c_set8(dev, PCA9535_OUTPUT0, 0x42); > + > + g_assert_cmphex(i2c_get8(dev, 0x0A), ==, 0x42); > +} > + > static void pca9555_register_nodes(void) > { > QOSGraphEdgeOptions opts = { > @@ -158,6 +239,13 @@ static void pca9555_register_nodes(void) > NULL); > qos_add_test("polarity-with-output", "pca9555", > test_polarity_with_output, > NULL); > + qos_add_test("auto-increment-read", "pca9555", test_auto_increment_read, > + NULL); > + qos_add_test("auto-increment-write", "pca9555", > test_auto_increment_write, > + NULL); > + qos_add_test("auto-increment-toggle", "pca9555", > test_auto_increment_toggle, > + NULL); > + qos_add_test("command-wrapping", "pca9555", test_command_wrapping, NULL); > } > > libqos_init(pca9555_register_nodes); >
