qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

adm1272-test.c (16905B)


      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);