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
pmbus_data2direct_mode(PMBusCoefficients c,uint32_t value)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
pmbus_direct_mode2data(PMBusCoefficients c,uint16_t value)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
adm1272_millivolts_to_direct(uint32_t value)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
adm1272_direct_to_millivolts(uint16_t value)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
adm1272_milliamps_to_direct(uint32_t value)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
adm1272_direct_to_milliamps(uint16_t value)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
adm1272_watts_to_direct(uint32_t value)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
adm1272_direct_to_watts(uint16_t value)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
qmp_adm1272_get(const char * id,const char * property)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
qmp_adm1272_set(const char * id,const char * property,uint16_t value)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 */
adm1272_i2c_get16(QI2CDevice * i2cdev,uint8_t reg)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 */
adm1272_i2c_set16(QI2CDevice * i2cdev,uint8_t reg,uint16_t value)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
test_defaults(void * obj,void * data,QGuestAllocator * alloc)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 */
test_tx_rx(void * obj,void * data,QGuestAllocator * alloc)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 */
test_rw_regs(void * obj,void * data,QGuestAllocator * alloc)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 */
test_ro_regs(void * obj,void * data,QGuestAllocator * alloc)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 */
test_voltage_faults(void * obj,void * data,QGuestAllocator * alloc)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
adm1272_register_nodes(void)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