@samitouri / QOSamiQemu / commits / 464e655143

tests/qtest: adc128d818: add test harness and register access

Introduce the QOS test node and QMP property helpers for the ADC128D818, and cover basic register access: manufacturer and revision IDs, power-on-reset defaults, software reset, and the ain and temperature property readback. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> Link: https://lore.kernel.org/qemu-devel/20260707091609.97759-3-emmanuel.blot@free.fr Signed-off-by: Cédric Le Goater <clg@redhat.com>

Emmanuel Blot committed Jul 7, 2026 at 11:15 UTC 464e6551430d4d6e515f8a53a493b6fc860732c3
2 files changed +170
tests/qtest/adc128d818-test.c new
+169
@@ -0,0 +1,169 @@
1 +/*
2 + * QTest testcase for the ADC128D818 ADC
3 + *
4 + * Copyright (c) 2026 Meta Platforms, Inc. and affiliates.
5 + *
6 + * SPDX-License-Identifier: GPL-2.0-or-later
7 + */
8 +
9 +#include "qemu/osdep.h"
10 +#include "qemu/bitops.h"
11 +#include "libqos/i2c.h"
12 +#include "libqos/qgraph.h"
13 +#include "libqtest-single.h"
14 +#include "qobject/qdict.h"
15 +
16 +#define ADC128D818_TEST_ID "adc128d818-test"
17 +#define ADC128D818_TEST_ADDR 0x1f
18 +
19 +/* Register addresses */
20 +#define REG_CONFIG 0x00
21 +#define REG_INT_STATUS 0x01
22 +#define REG_INT_MASK 0x03
23 +#define REG_CONV_RATE 0x07
24 +#define REG_CH_DISABLE 0x08
25 +#define REG_ONE_SHOT 0x09
26 +#define REG_DEEP_SHUTDOWN 0x0a
27 +#define REG_ADV_CONFIG 0x0b
28 +#define REG_BUSY_STATUS 0x0c
29 +
30 +/* Channel Reading Registers (16-bit, read-only) */
31 +#define REG_CH_READING_BASE 0x20
32 +
33 +/* Limit Registers (8-bit, read/write) */
34 +#define REG_LIMIT_BASE 0x2a
35 +
36 +/* ID Registers (read-only) */
37 +#define REG_MANUFACTURER_ID 0x3e
38 +#define REG_REVISION_ID 0x3f
39 +
40 +/* Configuration Register (0x00) bitfields */
41 +#define CONFIG_START BIT(0)
42 +#define CONFIG_INT_ENABLE BIT(1)
43 +#define CONFIG_INT_CLEAR BIT(3)
44 +#define CONFIG_INITIALIZATION BIT(7)
45 +
46 +/* Advanced Configuration Register (0x0b) bitfields */
47 +#define ADV_CONFIG_EXT_REF_EN BIT(0)
48 +#define ADV_CONFIG_MODE_1 (1 << 1)
49 +#define ADV_CONFIG_MODE_2 (2 << 1)
50 +#define ADV_CONFIG_MODE_3 (3 << 1)
51 +
52 +/* Number of channels */
53 +#define NUM_CHANNELS 8
54 +
55 +/* Internal VREF in mV */
56 +#define INTERNAL_VREF_MV 2560
57 +
58 +/* QMP helpers for setting device properties */
59 +
60 +static void qmp_adc128d818_set(const char *property, int value)
61 +{
62 + QDict *resp;
63 +
64 + resp = qmp("{ 'execute': 'qom-set', 'arguments':"
65 + " { 'path': %s, 'property': %s, 'value': %d } }",
66 + ADC128D818_TEST_ID, property, value);
67 + g_assert(qdict_haskey(resp, "return"));
68 + qobject_unref(resp);
69 +}
70 +
71 +static int qmp_adc128d818_get(const char *property)
72 +{
73 + QDict *resp;
74 + int ret;
75 +
76 + resp = qmp("{ 'execute': 'qom-get', 'arguments':"
77 + " { 'path': %s, 'property': %s } }",
78 + ADC128D818_TEST_ID, property);
79 + g_assert(qdict_haskey(resp, "return"));
80 + ret = qdict_get_int(resp, "return");
81 + qobject_unref(resp);
82 + return ret;
83 +}
84 +
85 +/* Manufacturer and Revision ID registers */
86 +static void test_id_registers(void *obj, void *data, QGuestAllocator *alloc)
87 +{
88 + QI2CDevice *dev = (QI2CDevice *)obj;
89 +
90 + g_assert_cmphex(i2c_get8(dev, REG_MANUFACTURER_ID), ==, 0x01);
91 + g_assert_cmphex(i2c_get8(dev, REG_REVISION_ID), ==, 0x09);
92 +}
93 +
94 +/* Power-on-reset default values */
95 +static void test_defaults(void *obj, void *data, QGuestAllocator *alloc)
96 +{
97 + QI2CDevice *dev = (QI2CDevice *)obj;
98 + unsigned ch;
99 +
100 + g_assert_cmphex(i2c_get8(dev, REG_CONFIG), ==, 0x08);
101 + g_assert_cmphex(i2c_get8(dev, REG_INT_STATUS), ==, 0x00);
102 + g_assert_cmphex(i2c_get8(dev, REG_INT_MASK), ==, 0x00);
103 + g_assert_cmphex(i2c_get8(dev, REG_CONV_RATE), ==, 0x00);
104 + g_assert_cmphex(i2c_get8(dev, REG_CH_DISABLE), ==, 0x00);
105 + g_assert_cmphex(i2c_get8(dev, REG_DEEP_SHUTDOWN), ==, 0x00);
106 + g_assert_cmphex(i2c_get8(dev, REG_ADV_CONFIG), ==, 0x00);
107 + g_assert_cmphex(i2c_get8(dev, REG_BUSY_STATUS), ==, 0x02);
108 +
109 + for (ch = 0u; ch < NUM_CHANNELS; ch++) {
110 + g_assert_cmphex(i2c_get8(dev, REG_LIMIT_BASE + ch * 2u), ==, 0xFF);
111 + g_assert_cmphex(i2c_get8(dev, REG_LIMIT_BASE + ch * 2u + 1u), ==, 0x00);
112 + }
113 +}
114 +
115 +/* Software reset via INITIALIZATION bit */
116 +static void test_soft_reset(void *obj, void *data, QGuestAllocator *alloc)
117 +{
118 + QI2CDevice *dev = (QI2CDevice *)obj;
119 +
120 + i2c_set8(dev, REG_INT_MASK, 0xAA);
121 + i2c_set8(dev, REG_CH_DISABLE, 0x55);
122 + i2c_set8(dev, REG_LIMIT_BASE, 0x42);
123 +
124 + g_assert_cmphex(i2c_get8(dev, REG_INT_MASK), ==, 0xAA);
125 + g_assert_cmphex(i2c_get8(dev, REG_CH_DISABLE), ==, 0x55);
126 + g_assert_cmphex(i2c_get8(dev, REG_LIMIT_BASE), ==, 0x42);
127 +
128 + i2c_set8(dev, REG_CONFIG, CONFIG_INITIALIZATION);
129 +
130 + g_assert_cmphex(i2c_get8(dev, REG_CONFIG), ==, 0x08);
131 + g_assert_cmphex(i2c_get8(dev, REG_INT_MASK), ==, 0x00);
132 + g_assert_cmphex(i2c_get8(dev, REG_CH_DISABLE), ==, 0x00);
133 + g_assert_cmphex(i2c_get8(dev, REG_LIMIT_BASE), ==, 0xFF);
134 + g_assert_cmphex(i2c_get8(dev, REG_BUSY_STATUS), ==, 0x02);
135 +}
136 +
137 +/* Verify ain property readback via QMP */
138 +static void test_ain_property(void *obj, void *data, QGuestAllocator *alloc)
139 +{
140 + int value;
141 +
142 + qmp_adc128d818_set("ain3", 1500);
143 + value = qmp_adc128d818_get("ain3");
144 + g_test_message("Set ain3 = 1500 mV, readback = %d mV", value);
145 + g_assert_cmpint(value, ==, 1500);
146 +
147 + qmp_adc128d818_set("temperature", 37500);
148 + value = qmp_adc128d818_get("temperature");
149 + g_test_message("Set temperature = 37500 mC, readback = %d mC", value);
150 + g_assert_cmpint(value, ==, 37500);
151 +}
152 +
153 +static void adc128d818_register_nodes(void)
154 +{
155 + QOSGraphEdgeOptions opts = {
156 + .extra_device_opts = "id=" ADC128D818_TEST_ID
157 + ",address=0x1f"
158 + };
159 + add_qi2c_address(&opts, &(QI2CAddress) { ADC128D818_TEST_ADDR });
160 +
161 + qos_node_create_driver("adc128d818", i2c_device_create);
162 + qos_node_consumes("adc128d818", "i2c-bus", &opts);
163 +
164 + qos_add_test("id-registers", "adc128d818", test_id_registers, NULL);
165 + qos_add_test("defaults", "adc128d818", test_defaults, NULL);
166 + qos_add_test("soft-reset", "adc128d818", test_soft_reset, NULL);
167 + qos_add_test("ain-property", "adc128d818", test_ain_property, NULL);
168 +}
169 +libqos_init(adc128d818_register_nodes);
tests/qtest/meson.build
+1
@@ -304,6 +304,7 @@ qtests_hexagon = ['boot-serial-test']
304 qos_test_ss = ss.source_set()
305 qos_test_ss.add(
306 'ac97-test.c',
307 + 'adc128d818-test.c',
308 'adm1272-test.c',
309 'adm1266-test.c',
310 'ds1338-test.c',