Reviewed-by: Glenn Miles <[email protected]> Thanks,
Glenn On Mon, 2026-10-12 at 16:32 +0200, Emmanuel Blot via qemu development wrote: > Introduce the INA230 qtest: the qgraph node and the register map. Cover > the power-on-reset defaults and Die ID, the software reset, and the > Configuration register write mask. The QMP voltage-injection helpers > arrive with the following commit that exercises them. > > Signed-off-by: Emmanuel Blot <[email protected]> > --- > tests/qtest/ina230-test.c | 115 > ++++++++++++++++++++++++++++++++++++++++++++++ > tests/qtest/meson.build | 1 + > 2 files changed, 116 insertions(+) > > diff --git a/tests/qtest/ina230-test.c b/tests/qtest/ina230-test.c > new file mode 100644 > index 0000000000..f7aefd2d97 > --- /dev/null > +++ b/tests/qtest/ina230-test.c > @@ -0,0 +1,115 @@ > +/* > + * QTest testcase for the INA230 current/voltage/power monitor > + * > + * Copyright (c) 2026 Meta Platforms, Inc. and affiliates. > + * > + * SPDX-License-Identifier: GPL-2.0-or-later > + */ > + > +#include "qemu/osdep.h" > +#include "libqos/i2c.h" > +#include "libqos/qgraph.h" > +#include "libqtest-single.h" > +#include "qobject/qdict.h" > + > +#define INA230_TEST_ID "ina230-test" > +#define INA230_TEST_ADDR 0x40 > + > +/* Register pointer addresses */ > +#define REG_CONFIG 0x00 > +#define REG_SHUNT 0x01 > +#define REG_BUS 0x02 > +#define REG_POWER 0x03 > +#define REG_CURRENT 0x04 > +#define REG_CALIBRATION 0x05 > +#define REG_MASK_ENABLE 0x06 > +#define REG_ALERT_LIMIT 0x07 > +#define REG_DIE_ID 0xFF > + > +/* Configuration register bits */ > +#define CONFIG_POR 0x4127 > +#define CONFIG_RST 0x8000 > + > +/* Mask/Enable register bits */ > +#define ME_LEN 0x0001 > +#define ME_APOL 0x0002 > +#define ME_OVF 0x0004 > +#define ME_CVRF 0x0008 > +#define ME_AFF 0x0010 > +#define ME_CNVR 0x0400 > +#define ME_POL 0x0800 > +#define ME_BUL 0x1000 > +#define ME_BOL 0x2000 > +#define ME_SUL 0x4000 > +#define ME_SOL 0x8000 > + > +/* Injected-input scaling (datasheet fixed LSBs) */ > +#define SHUNT_LSB_NV 2500 > +#define BUS_LSB_UV 1250 > + > +#define DIE_ID_VAL 0x2310 > + > +/* Power-on-reset default values and the Die ID */ > +static void test_defaults(void *obj, void *data, QGuestAllocator *alloc) > +{ > + QI2CDevice *dev = (QI2CDevice *)obj; > + > + g_assert_cmphex(i2c_get16(dev, REG_CONFIG), ==, CONFIG_POR); > + g_assert_cmphex(i2c_get16(dev, REG_SHUNT), ==, 0x0000); > + g_assert_cmphex(i2c_get16(dev, REG_BUS), ==, 0x0000); > + g_assert_cmphex(i2c_get16(dev, REG_POWER), ==, 0x0000); > + g_assert_cmphex(i2c_get16(dev, REG_CURRENT), ==, 0x0000); > + g_assert_cmphex(i2c_get16(dev, REG_CALIBRATION), ==, 0x0000); > + g_assert_cmphex(i2c_get16(dev, REG_MASK_ENABLE), ==, 0x0000); > + g_assert_cmphex(i2c_get16(dev, REG_ALERT_LIMIT), ==, 0x0000); > + g_assert_cmphex(i2c_get16(dev, REG_DIE_ID), ==, DIE_ID_VAL); > +} > + > +/* Software reset via the Configuration RST bit */ > +static void test_soft_reset(void *obj, void *data, QGuestAllocator *alloc) > +{ > + QI2CDevice *dev = (QI2CDevice *)obj; > + > + i2c_set16(dev, REG_CALIBRATION, 0x1234); > + i2c_set16(dev, REG_MASK_ENABLE, ME_SOL); > + i2c_set16(dev, REG_ALERT_LIMIT, 0x0500); > + > + g_assert_cmphex(i2c_get16(dev, REG_CALIBRATION), ==, 0x1234); > + g_assert_cmphex(i2c_get16(dev, REG_ALERT_LIMIT), ==, 0x0500); > + > + i2c_set16(dev, REG_CONFIG, CONFIG_RST); > + > + g_assert_cmphex(i2c_get16(dev, REG_CONFIG), ==, CONFIG_POR); > + g_assert_cmphex(i2c_get16(dev, REG_CALIBRATION), ==, 0x0000); > + g_assert_cmphex(i2c_get16(dev, REG_MASK_ENABLE), ==, 0x0000); > + g_assert_cmphex(i2c_get16(dev, REG_ALERT_LIMIT), ==, 0x0000); > +} > + > +/* Every bit except the self-clearing RST is writable and reads back */ > +static void test_config_wmask(void *obj, void *data, QGuestAllocator *alloc) > +{ > + QI2CDevice *dev = (QI2CDevice *)obj; > + > + /* Reserved bits are not forced: the guest value is retained */ > + i2c_set16(dev, REG_CONFIG, 0x0007); > + g_assert_cmphex(i2c_get16(dev, REG_CONFIG), ==, 0x0007); > + > + i2c_set16(dev, REG_CONFIG, 0x7FFF); > + g_assert_cmphex(i2c_get16(dev, REG_CONFIG), ==, 0x7FFF); > +} > + > +static void ina230_register_nodes(void) > +{ > + QOSGraphEdgeOptions opts = { > + .extra_device_opts = "id=" INA230_TEST_ID ",address=0x40" > + }; > + add_qi2c_address(&opts, &(QI2CAddress) { INA230_TEST_ADDR }); > + > + qos_node_create_driver("ina230", i2c_device_create); > + qos_node_consumes("ina230", "i2c-bus", &opts); > + > + qos_add_test("defaults", "ina230", test_defaults, NULL); > + qos_add_test("soft-reset", "ina230", test_soft_reset, NULL); > + qos_add_test("config-wmask", "ina230", test_config_wmask, NULL); > +} > +libqos_init(ina230_register_nodes); > diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build > index e23eb9bbca..e413a0cc75 100644 > --- a/tests/qtest/meson.build > +++ b/tests/qtest/meson.build > @@ -330,6 +330,7 @@ qos_test_ss.add( > 'e1000-test.c', > 'eepro100-test.c', > 'es1370-test.c', > + 'ina230-test.c', > 'lsm303dlhc-mag-test.c', > 'isl_pmbus_vr-test.c', > 'max34451-test.c', >
