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