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