xref: /qemu/tests/qtest/adm1272-test.c (revision 727385c4)
1 /*
2  * QTests for the ADM1272 hotswap controller
3  *
4  * Copyright 2021 Google LLC
5  *
6  * SPDX-License-Identifier: GPL-2.0-or-later
7  */
8 
9 #include "qemu/osdep.h"
10 #include <math.h>
11 #include "hw/i2c/pmbus_device.h"
12 #include "libqtest-single.h"
13 #include "libqos/qgraph.h"
14 #include "libqos/i2c.h"
15 #include "qapi/qmp/qdict.h"
16 #include "qapi/qmp/qnum.h"
17 #include "qemu/bitops.h"
18 
19 #define TEST_ID "adm1272-test"
20 #define TEST_ADDR (0x10)
21 
22 #define ADM1272_RESTART_TIME            0xCC
23 #define ADM1272_MFR_PEAK_IOUT           0xD0
24 #define ADM1272_MFR_PEAK_VIN            0xD1
25 #define ADM1272_MFR_PEAK_VOUT           0xD2
26 #define ADM1272_MFR_PMON_CONTROL        0xD3
27 #define ADM1272_MFR_PMON_CONFIG         0xD4
28 #define ADM1272_MFR_ALERT1_CONFIG       0xD5
29 #define ADM1272_MFR_ALERT2_CONFIG       0xD6
30 #define ADM1272_MFR_PEAK_TEMPERATURE    0xD7
31 #define ADM1272_MFR_DEVICE_CONFIG       0xD8
32 #define ADM1272_MFR_POWER_CYCLE         0xD9
33 #define ADM1272_MFR_PEAK_PIN            0xDA
34 #define ADM1272_MFR_READ_PIN_EXT        0xDB
35 #define ADM1272_MFR_READ_EIN_EXT        0xDC
36 
37 #define ADM1272_HYSTERESIS_LOW          0xF2
38 #define ADM1272_HYSTERESIS_HIGH         0xF3
39 #define ADM1272_STATUS_HYSTERESIS       0xF4
40 #define ADM1272_STATUS_GPIO             0xF5
41 #define ADM1272_STRT_UP_IOUT_LIM        0xF6
42 
43 /* Defaults */
44 #define ADM1272_OPERATION_DEFAULT       0x80
45 #define ADM1272_CAPABILITY_DEFAULT      0xB0
46 #define ADM1272_CAPABILITY_NO_PEC       0x30
47 #define ADM1272_DIRECT_MODE             0x40
48 #define ADM1272_HIGH_LIMIT_DEFAULT      0x0FFF
49 #define ADM1272_PIN_OP_DEFAULT          0x7FFF
50 #define ADM1272_PMBUS_REVISION_DEFAULT  0x22
51 #define ADM1272_MFR_ID_DEFAULT          "ADI"
52 #define ADM1272_MODEL_DEFAULT           "ADM1272-A1"
53 #define ADM1272_MFR_DEFAULT_REVISION    "25"
54 #define ADM1272_DEFAULT_DATE            "160301"
55 #define ADM1272_RESTART_TIME_DEFAULT    0x64
56 #define ADM1272_PMON_CONTROL_DEFAULT    0x1
57 #define ADM1272_PMON_CONFIG_DEFAULT     0x3F35
58 #define ADM1272_DEVICE_CONFIG_DEFAULT   0x8
59 #define ADM1272_HYSTERESIS_HIGH_DEFAULT     0xFFFF
60 #define ADM1272_STRT_UP_IOUT_LIM_DEFAULT    0x000F
61 #define ADM1272_VOLT_DEFAULT            12000
62 #define ADM1272_IOUT_DEFAULT            25000
63 #define ADM1272_PWR_DEFAULT             300  /* 12V 25A */
64 #define ADM1272_SHUNT                   300 /* micro-ohms */
65 #define ADM1272_VOLTAGE_COEFF_DEFAULT   1
66 #define ADM1272_CURRENT_COEFF_DEFAULT   3
67 #define ADM1272_PWR_COEFF_DEFAULT       7
68 #define ADM1272_IOUT_OFFSET             0x5000
69 #define ADM1272_IOUT_OFFSET             0x5000
70 
71 static const PMBusCoefficients adm1272_coefficients[] = {
72     [0] = { 6770, 0, -2 },       /* voltage, vrange 60V */
73     [1] = { 4062, 0, -2 },       /* voltage, vrange 100V */
74     [2] = { 1326, 20480, -1 },   /* current, vsense range 15mV */
75     [3] = { 663, 20480, -1 },    /* current, vsense range 30mV */
76     [4] = { 3512, 0, -2 },       /* power, vrange 60V, irange 15mV */
77     [5] = { 21071, 0, -3 },      /* power, vrange 100V, irange 15mV */
78     [6] = { 17561, 0, -3 },      /* power, vrange 60V, irange 30mV */
79     [7] = { 10535, 0, -3 },      /* power, vrange 100V, irange 30mV */
80     [8] = { 42, 31871, -1 },     /* temperature */
81 };
82 
83 uint16_t pmbus_data2direct_mode(PMBusCoefficients c, uint32_t value)
84 {
85     /* R is usually negative to fit large readings into 16 bits */
86     uint16_t y = (c.m * value + c.b) * pow(10, c.R);
87     return y;
88 }
89 
90 uint32_t pmbus_direct_mode2data(PMBusCoefficients c, uint16_t value)
91 {
92     /* X = (Y * 10^-R - b) / m */
93     uint32_t x = (value / pow(10, c.R) - c.b) / c.m;
94     return x;
95 }
96 
97 
98 static uint16_t adm1272_millivolts_to_direct(uint32_t value)
99 {
100     PMBusCoefficients c = adm1272_coefficients[ADM1272_VOLTAGE_COEFF_DEFAULT];
101     c.b = c.b * 1000;
102     c.R = c.R - 3;
103     return pmbus_data2direct_mode(c, value);
104 }
105 
106 static uint32_t adm1272_direct_to_millivolts(uint16_t value)
107 {
108     PMBusCoefficients c = adm1272_coefficients[ADM1272_VOLTAGE_COEFF_DEFAULT];
109     c.b = c.b * 1000;
110     c.R = c.R - 3;
111     return pmbus_direct_mode2data(c, value);
112 }
113 
114 static uint16_t adm1272_milliamps_to_direct(uint32_t value)
115 {
116     PMBusCoefficients c = adm1272_coefficients[ADM1272_CURRENT_COEFF_DEFAULT];
117     /* Y = (m * r_sense * x - b) * 10^R */
118     c.m = c.m * ADM1272_SHUNT / 1000; /* micro-ohms */
119     c.b = c.b * 1000;
120     c.R = c.R - 3;
121     return pmbus_data2direct_mode(c, value);
122 }
123 
124 static uint32_t adm1272_direct_to_milliamps(uint16_t value)
125 {
126     PMBusCoefficients c = adm1272_coefficients[ADM1272_CURRENT_COEFF_DEFAULT];
127     c.m = c.m * ADM1272_SHUNT / 1000;
128     c.b = c.b * 1000;
129     c.R = c.R - 3;
130     return pmbus_direct_mode2data(c, value);
131 }
132 
133 static uint16_t adm1272_watts_to_direct(uint32_t value)
134 {
135     PMBusCoefficients c = adm1272_coefficients[ADM1272_PWR_COEFF_DEFAULT];
136     c.m = c.m * ADM1272_SHUNT / 1000;
137     return pmbus_data2direct_mode(c, value);
138 }
139 
140 static uint32_t adm1272_direct_to_watts(uint16_t value)
141 {
142     PMBusCoefficients c = adm1272_coefficients[ADM1272_PWR_COEFF_DEFAULT];
143     c.m = c.m * ADM1272_SHUNT / 1000;
144     return pmbus_direct_mode2data(c, value);
145 }
146 
147 static uint16_t qmp_adm1272_get(const char *id, const char *property)
148 {
149     QDict *response;
150     uint64_t ret;
151 
152     response = qmp("{ 'execute': 'qom-get', 'arguments': { 'path': %s, "
153                    "'property': %s } }", id, property);
154     g_assert(qdict_haskey(response, "return"));
155     ret = qnum_get_uint(qobject_to(QNum, qdict_get(response, "return")));
156     qobject_unref(response);
157     return ret;
158 }
159 
160 static void qmp_adm1272_set(const char *id,
161                             const char *property,
162                             uint16_t value)
163 {
164     QDict *response;
165 
166     response = qmp("{ 'execute': 'qom-set', 'arguments': { 'path': %s, "
167                    "'property': %s, 'value': %u } }", id, property, value);
168     g_assert(qdict_haskey(response, "return"));
169     qobject_unref(response);
170 }
171 
172 /* PMBus commands are little endian vs i2c_set16 in i2c.h which is big endian */
173 static uint16_t adm1272_i2c_get16(QI2CDevice *i2cdev, uint8_t reg)
174 {
175     uint8_t resp[2];
176     i2c_read_block(i2cdev, reg, resp, sizeof(resp));
177     return (resp[1] << 8) | resp[0];
178 }
179 
180 /* PMBus commands are little endian vs i2c_set16 in i2c.h which is big endian */
181 static void adm1272_i2c_set16(QI2CDevice *i2cdev, uint8_t reg, uint16_t value)
182 {
183     uint8_t data[2];
184 
185     data[0] = value & 255;
186     data[1] = value >> 8;
187     i2c_write_block(i2cdev, reg, data, sizeof(data));
188 }
189 
190 static void test_defaults(void *obj, void *data, QGuestAllocator *alloc)
191 {
192     uint16_t value, i2c_value;
193     int16_t err;
194     QI2CDevice *i2cdev = (QI2CDevice *)obj;
195     value = qmp_adm1272_get(TEST_ID, "vout");
196     err = ADM1272_VOLT_DEFAULT - value;
197     g_assert_cmpuint(abs(err), <, ADM1272_VOLT_DEFAULT / 20);
198 
199     i2c_value = i2c_get8(i2cdev, PMBUS_OPERATION);
200     g_assert_cmphex(i2c_value, ==, ADM1272_OPERATION_DEFAULT);
201 
202     i2c_value = i2c_get8(i2cdev, PMBUS_VOUT_MODE);
203     g_assert_cmphex(i2c_value, ==, ADM1272_DIRECT_MODE);
204 
205     i2c_value = adm1272_i2c_get16(i2cdev, PMBUS_VOUT_OV_WARN_LIMIT);
206     g_assert_cmphex(i2c_value, ==, ADM1272_HIGH_LIMIT_DEFAULT);
207 
208     i2c_value = adm1272_i2c_get16(i2cdev, PMBUS_VOUT_UV_WARN_LIMIT);
209     g_assert_cmphex(i2c_value, ==, 0);
210 
211     i2c_value = adm1272_i2c_get16(i2cdev, PMBUS_IOUT_OC_WARN_LIMIT);
212     g_assert_cmphex(i2c_value, ==, ADM1272_HIGH_LIMIT_DEFAULT);
213 
214     i2c_value = adm1272_i2c_get16(i2cdev, PMBUS_OT_FAULT_LIMIT);
215     g_assert_cmphex(i2c_value, ==, ADM1272_HIGH_LIMIT_DEFAULT);
216 
217     i2c_value = adm1272_i2c_get16(i2cdev, PMBUS_OT_WARN_LIMIT);
218     g_assert_cmphex(i2c_value, ==, ADM1272_HIGH_LIMIT_DEFAULT);
219 
220     i2c_value = adm1272_i2c_get16(i2cdev, PMBUS_VIN_OV_WARN_LIMIT);
221     g_assert_cmphex(i2c_value, ==, ADM1272_HIGH_LIMIT_DEFAULT);
222 
223     i2c_value = adm1272_i2c_get16(i2cdev, PMBUS_VIN_UV_WARN_LIMIT);
224     g_assert_cmphex(i2c_value, ==, 0);
225 
226     i2c_value = adm1272_i2c_get16(i2cdev, PMBUS_PIN_OP_WARN_LIMIT);
227     g_assert_cmphex(i2c_value, ==, ADM1272_PIN_OP_DEFAULT);
228 
229     i2c_value = i2c_get8(i2cdev, PMBUS_REVISION);
230     g_assert_cmphex(i2c_value, ==, ADM1272_PMBUS_REVISION_DEFAULT);
231 
232     i2c_value = i2c_get8(i2cdev, ADM1272_MFR_PMON_CONTROL);
233     g_assert_cmphex(i2c_value, ==, ADM1272_PMON_CONTROL_DEFAULT);
234 
235     i2c_value = adm1272_i2c_get16(i2cdev, ADM1272_MFR_PMON_CONFIG);
236     g_assert_cmphex(i2c_value, ==, ADM1272_PMON_CONFIG_DEFAULT);
237 
238     i2c_value = adm1272_i2c_get16(i2cdev, ADM1272_MFR_DEVICE_CONFIG);
239     g_assert_cmphex(i2c_value, ==, ADM1272_DEVICE_CONFIG_DEFAULT);
240 
241     i2c_value = adm1272_i2c_get16(i2cdev, ADM1272_HYSTERESIS_HIGH);
242     g_assert_cmphex(i2c_value, ==, ADM1272_HYSTERESIS_HIGH_DEFAULT);
243 
244     i2c_value = adm1272_i2c_get16(i2cdev, ADM1272_STRT_UP_IOUT_LIM);
245     g_assert_cmphex(i2c_value, ==, ADM1272_STRT_UP_IOUT_LIM_DEFAULT);
246 }
247 
248 /* test qmp access */
249 static void test_tx_rx(void *obj, void *data, QGuestAllocator *alloc)
250 {
251     uint16_t i2c_value, value, i2c_voltage, i2c_pwr, lossy_value;
252     QI2CDevice *i2cdev = (QI2CDevice *)obj;
253 
254     /* converting to direct mode is lossy - we generate the same loss here */
255     lossy_value =
256         adm1272_direct_to_millivolts(adm1272_millivolts_to_direct(1000));
257     qmp_adm1272_set(TEST_ID, "vin", 1000);
258     value = qmp_adm1272_get(TEST_ID, "vin");
259     i2c_value = adm1272_i2c_get16(i2cdev, PMBUS_READ_VIN);
260     i2c_voltage = adm1272_direct_to_millivolts(i2c_value);
261     g_assert_cmpuint(value, ==, i2c_voltage);
262     g_assert_cmpuint(i2c_voltage, ==, lossy_value);
263 
264     lossy_value =
265         adm1272_direct_to_millivolts(adm1272_millivolts_to_direct(1500));
266     qmp_adm1272_set(TEST_ID, "vout", 1500);
267     value = qmp_adm1272_get(TEST_ID, "vout");
268     i2c_value = adm1272_i2c_get16(i2cdev, PMBUS_READ_VOUT);
269     i2c_voltage = adm1272_direct_to_millivolts(i2c_value);
270     g_assert_cmpuint(value, ==, i2c_voltage);
271     g_assert_cmpuint(i2c_voltage, ==, lossy_value);
272 
273     lossy_value =
274         adm1272_direct_to_milliamps(adm1272_milliamps_to_direct(1600));
275     qmp_adm1272_set(TEST_ID, "iout", 1600);
276     value = qmp_adm1272_get(TEST_ID, "iout");
277     i2c_value = adm1272_i2c_get16(i2cdev, PMBUS_READ_IOUT);
278     i2c_value = adm1272_direct_to_milliamps(i2c_value);
279     g_assert_cmphex(value, ==, i2c_value);
280     g_assert_cmphex(i2c_value, ==, lossy_value);
281 
282     lossy_value =
283         adm1272_direct_to_watts(adm1272_watts_to_direct(320));
284     qmp_adm1272_set(TEST_ID, "pin", 320);
285     value = qmp_adm1272_get(TEST_ID, "pin");
286     i2c_value = adm1272_i2c_get16(i2cdev, PMBUS_READ_PIN);
287     i2c_pwr = adm1272_direct_to_watts(i2c_value);
288     g_assert_cmphex(value, ==, i2c_pwr);
289     g_assert_cmphex(i2c_pwr, ==, lossy_value);
290 }
291 
292 /* test r/w registers */
293 static void test_rw_regs(void *obj, void *data, QGuestAllocator *alloc)
294 {
295     uint16_t i2c_value;
296     QI2CDevice *i2cdev = (QI2CDevice *)obj;
297 
298     adm1272_i2c_set16(i2cdev, PMBUS_VOUT_OV_WARN_LIMIT, 0xABCD);
299     i2c_value = adm1272_i2c_get16(i2cdev, PMBUS_VOUT_OV_WARN_LIMIT);
300     g_assert_cmphex(i2c_value, ==, 0xABCD);
301 
302     adm1272_i2c_set16(i2cdev, PMBUS_VOUT_UV_WARN_LIMIT, 0xCDEF);
303     i2c_value = adm1272_i2c_get16(i2cdev, PMBUS_VOUT_UV_WARN_LIMIT);
304     g_assert_cmphex(i2c_value, ==, 0xCDEF);
305 
306     adm1272_i2c_set16(i2cdev, PMBUS_IOUT_OC_WARN_LIMIT, 0x1234);
307     i2c_value = adm1272_i2c_get16(i2cdev, PMBUS_IOUT_OC_WARN_LIMIT);
308     g_assert_cmphex(i2c_value, ==, 0x1234);
309 
310     adm1272_i2c_set16(i2cdev, PMBUS_OT_FAULT_LIMIT, 0x5678);
311     i2c_value = adm1272_i2c_get16(i2cdev, PMBUS_OT_FAULT_LIMIT);
312     g_assert_cmphex(i2c_value, ==, 0x5678);
313 
314     adm1272_i2c_set16(i2cdev, PMBUS_OT_WARN_LIMIT, 0xABDC);
315     i2c_value = adm1272_i2c_get16(i2cdev, PMBUS_OT_WARN_LIMIT);
316     g_assert_cmphex(i2c_value, ==, 0xABDC);
317 
318     adm1272_i2c_set16(i2cdev, PMBUS_VIN_OV_WARN_LIMIT, 0xCDEF);
319     i2c_value = adm1272_i2c_get16(i2cdev, PMBUS_VIN_OV_WARN_LIMIT);
320     g_assert_cmphex(i2c_value, ==, 0xCDEF);
321 
322     adm1272_i2c_set16(i2cdev, PMBUS_VIN_UV_WARN_LIMIT, 0x2345);
323     i2c_value = adm1272_i2c_get16(i2cdev, PMBUS_VIN_UV_WARN_LIMIT);
324     g_assert_cmphex(i2c_value, ==, 0x2345);
325 
326     i2c_set8(i2cdev, ADM1272_RESTART_TIME, 0xF8);
327     i2c_value = i2c_get8(i2cdev, ADM1272_RESTART_TIME);
328     g_assert_cmphex(i2c_value, ==, 0xF8);
329 
330     i2c_set8(i2cdev, ADM1272_MFR_PMON_CONTROL, 0);
331     i2c_value = i2c_get8(i2cdev, ADM1272_MFR_PMON_CONTROL);
332     g_assert_cmpuint(i2c_value, ==, 0);
333 
334     adm1272_i2c_set16(i2cdev, ADM1272_MFR_PMON_CONFIG, 0xDEF0);
335     i2c_value = adm1272_i2c_get16(i2cdev, ADM1272_MFR_PMON_CONFIG);
336     g_assert_cmphex(i2c_value, ==, 0xDEF0);
337 
338     adm1272_i2c_set16(i2cdev, ADM1272_MFR_ALERT1_CONFIG, 0x0123);
339     i2c_value = adm1272_i2c_get16(i2cdev, ADM1272_MFR_ALERT1_CONFIG);
340     g_assert_cmphex(i2c_value, ==, 0x0123);
341 
342     adm1272_i2c_set16(i2cdev, ADM1272_MFR_ALERT2_CONFIG, 0x9876);
343     i2c_value = adm1272_i2c_get16(i2cdev, ADM1272_MFR_ALERT2_CONFIG);
344     g_assert_cmphex(i2c_value, ==, 0x9876);
345 
346     adm1272_i2c_set16(i2cdev, ADM1272_MFR_DEVICE_CONFIG, 0x3456);
347     i2c_value = adm1272_i2c_get16(i2cdev, ADM1272_MFR_DEVICE_CONFIG);
348     g_assert_cmphex(i2c_value, ==, 0x3456);
349 
350     adm1272_i2c_set16(i2cdev, ADM1272_HYSTERESIS_LOW, 0xCABA);
351     i2c_value = adm1272_i2c_get16(i2cdev, ADM1272_HYSTERESIS_LOW);
352     g_assert_cmphex(i2c_value, ==, 0xCABA);
353 
354     adm1272_i2c_set16(i2cdev, ADM1272_HYSTERESIS_HIGH, 0x6789);
355     i2c_value = adm1272_i2c_get16(i2cdev, ADM1272_HYSTERESIS_HIGH);
356     g_assert_cmphex(i2c_value, ==, 0x6789);
357 
358     adm1272_i2c_set16(i2cdev, ADM1272_STRT_UP_IOUT_LIM, 0x9876);
359     i2c_value = adm1272_i2c_get16(i2cdev, ADM1272_STRT_UP_IOUT_LIM);
360     g_assert_cmphex(i2c_value, ==, 0x9876);
361 
362     adm1272_i2c_set16(i2cdev, PMBUS_OPERATION, 0xA);
363     i2c_value = i2c_get8(i2cdev, PMBUS_OPERATION);
364     g_assert_cmphex(i2c_value, ==, 0xA);
365 }
366 
367 /* test read-only registers */
368 static void test_ro_regs(void *obj, void *data, QGuestAllocator *alloc)
369 {
370     uint16_t i2c_init_value, i2c_value;
371     QI2CDevice *i2cdev = (QI2CDevice *)obj;
372 
373     i2c_init_value = adm1272_i2c_get16(i2cdev, PMBUS_READ_VIN);
374     adm1272_i2c_set16(i2cdev, PMBUS_READ_VIN, 0xBEEF);
375     i2c_value = adm1272_i2c_get16(i2cdev, PMBUS_READ_VIN);
376     g_assert_cmphex(i2c_init_value, ==, i2c_value);
377 
378     i2c_init_value = adm1272_i2c_get16(i2cdev, PMBUS_READ_VOUT);
379     adm1272_i2c_set16(i2cdev, PMBUS_READ_VOUT, 0x1234);
380     i2c_value = adm1272_i2c_get16(i2cdev, PMBUS_READ_VOUT);
381     g_assert_cmphex(i2c_init_value, ==, i2c_value);
382 
383     i2c_init_value = adm1272_i2c_get16(i2cdev, PMBUS_READ_IOUT);
384     adm1272_i2c_set16(i2cdev, PMBUS_READ_IOUT, 0x6547);
385     i2c_value = adm1272_i2c_get16(i2cdev, PMBUS_READ_IOUT);
386     g_assert_cmphex(i2c_init_value, ==, i2c_value);
387 
388     i2c_init_value = adm1272_i2c_get16(i2cdev, PMBUS_READ_TEMPERATURE_1);
389     adm1272_i2c_set16(i2cdev, PMBUS_READ_TEMPERATURE_1, 0x1597);
390     i2c_value = adm1272_i2c_get16(i2cdev, PMBUS_READ_TEMPERATURE_1);
391     g_assert_cmphex(i2c_init_value, ==, i2c_value);
392 
393     i2c_init_value = adm1272_i2c_get16(i2cdev, PMBUS_READ_PIN);
394     adm1272_i2c_set16(i2cdev, PMBUS_READ_PIN, 0xDEAD);
395     i2c_value = adm1272_i2c_get16(i2cdev, PMBUS_READ_PIN);
396     g_assert_cmphex(i2c_init_value, ==, i2c_value);
397 }
398 
399 /* test voltage fault handling */
400 static void test_voltage_faults(void *obj, void *data, QGuestAllocator *alloc)
401 {
402     uint16_t i2c_value;
403     uint8_t i2c_byte;
404     QI2CDevice *i2cdev = (QI2CDevice *)obj;
405 
406     adm1272_i2c_set16(i2cdev, PMBUS_VOUT_OV_WARN_LIMIT,
407                       adm1272_millivolts_to_direct(5000));
408     qmp_adm1272_set(TEST_ID, "vout", 5100);
409 
410     i2c_value = adm1272_i2c_get16(i2cdev, PMBUS_STATUS_WORD);
411     i2c_byte = i2c_get8(i2cdev, PMBUS_STATUS_VOUT);
412     g_assert_true((i2c_value & PB_STATUS_VOUT) != 0);
413     g_assert_true((i2c_byte & PB_STATUS_VOUT_OV_WARN) != 0);
414 
415     qmp_adm1272_set(TEST_ID, "vout", 4500);
416     i2c_set8(i2cdev, PMBUS_CLEAR_FAULTS, 0);
417     i2c_byte = i2c_get8(i2cdev, PMBUS_STATUS_VOUT);
418     g_assert_true((i2c_byte & PB_STATUS_VOUT_OV_WARN) == 0);
419 
420     adm1272_i2c_set16(i2cdev, PMBUS_VOUT_UV_WARN_LIMIT,
421                       adm1272_millivolts_to_direct(4600));
422     i2c_value = adm1272_i2c_get16(i2cdev, PMBUS_STATUS_WORD);
423     i2c_byte = i2c_get8(i2cdev, PMBUS_STATUS_VOUT);
424     g_assert_true((i2c_value & PB_STATUS_VOUT) != 0);
425     g_assert_true((i2c_byte & PB_STATUS_VOUT_UV_WARN) != 0);
426 
427 }
428 
429 static void adm1272_register_nodes(void)
430 {
431     QOSGraphEdgeOptions opts = {
432         .extra_device_opts = "id=" TEST_ID ",address=0x10"
433     };
434     add_qi2c_address(&opts, &(QI2CAddress) { TEST_ADDR });
435 
436     qos_node_create_driver("adm1272", i2c_device_create);
437     qos_node_consumes("adm1272", "i2c-bus", &opts);
438 
439     qos_add_test("test_defaults", "adm1272", test_defaults, NULL);
440     qos_add_test("test_tx_rx", "adm1272", test_tx_rx, NULL);
441     qos_add_test("test_rw_regs", "adm1272", test_rw_regs, NULL);
442     qos_add_test("test_ro_regs", "adm1272", test_ro_regs, NULL);
443     qos_add_test("test_ov_faults", "adm1272", test_voltage_faults, NULL);
444 }
445 libqos_init(adm1272_register_nodes);
446