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',
> 


Reply via email to