1 /* 2 * QTests for the MAX34451 device 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 "hw/i2c/pmbus_device.h" 11 #include "libqtest-single.h" 12 #include "libqos/qgraph.h" 13 #include "libqos/i2c.h" 14 #include "qapi/qmp/qdict.h" 15 #include "qapi/qmp/qnum.h" 16 #include "qemu/bitops.h" 17 18 #define TEST_ID "max34451-test" 19 #define TEST_ADDR (0x4e) 20 21 #define MAX34451_MFR_MODE 0xD1 22 #define MAX34451_MFR_VOUT_PEAK 0xD4 23 #define MAX34451_MFR_IOUT_PEAK 0xD5 24 #define MAX34451_MFR_TEMPERATURE_PEAK 0xD6 25 #define MAX34451_MFR_VOUT_MIN 0xD7 26 27 #define DEFAULT_VOUT 0 28 #define DEFAULT_UV_LIMIT 0 29 #define DEFAULT_TEMPERATURE 2500 30 #define DEFAULT_SCALE 0x7FFF 31 #define DEFAULT_OV_LIMIT 0x7FFF 32 #define DEFAULT_OC_LIMIT 0x7FFF 33 #define DEFAULT_OT_LIMIT 0x7FFF 34 #define DEFAULT_VMIN 0x7FFF 35 #define DEFAULT_TON_FAULT_LIMIT 0xFFFF 36 #define DEFAULT_CHANNEL_CONFIG 0x20 37 #define DEFAULT_TEXT 0x20 38 39 #define MAX34451_NUM_PWR_DEVICES 16 40 #define MAX34451_NUM_TEMP_DEVICES 5 41 42 43 static uint16_t qmp_max34451_get(const char *id, const char *property) 44 { 45 QDict *response; 46 uint16_t ret; 47 response = qmp("{ 'execute': 'qom-get', 'arguments': { 'path': %s, " 48 "'property': %s } }", id, property); 49 g_assert(qdict_haskey(response, "return")); 50 ret = qnum_get_uint(qobject_to(QNum, qdict_get(response, "return"))); 51 qobject_unref(response); 52 return ret; 53 } 54 55 static void qmp_max34451_set(const char *id, 56 const char *property, 57 uint16_t value) 58 { 59 QDict *response; 60 61 response = qmp("{ 'execute': 'qom-set', 'arguments': { 'path': %s, " 62 "'property': %s, 'value': %u } }", 63 id, property, value); 64 g_assert(qdict_haskey(response, "return")); 65 qobject_unref(response); 66 } 67 68 /* PMBus commands are little endian vs i2c_set16 in i2c.h which is big endian */ 69 static uint16_t max34451_i2c_get16(QI2CDevice *i2cdev, uint8_t reg) 70 { 71 uint8_t resp[2]; 72 i2c_read_block(i2cdev, reg, resp, sizeof(resp)); 73 return (resp[1] << 8) | resp[0]; 74 } 75 76 /* PMBus commands are little endian vs i2c_set16 in i2c.h which is big endian */ 77 static void max34451_i2c_set16(QI2CDevice *i2cdev, uint8_t reg, uint16_t value) 78 { 79 uint8_t data[2]; 80 81 data[0] = value & 255; 82 data[1] = value >> 8; 83 i2c_write_block(i2cdev, reg, data, sizeof(data)); 84 } 85 86 /* Test default values */ 87 static void test_defaults(void *obj, void *data, QGuestAllocator *alloc) 88 { 89 uint16_t value, i2c_value; 90 QI2CDevice *i2cdev = (QI2CDevice *)obj; 91 char *path; 92 93 /* Default temperatures and temperature fault limits */ 94 for (int i = 0; i < MAX34451_NUM_TEMP_DEVICES; i++) { 95 path = g_strdup_printf("temperature[%d]", i); 96 value = qmp_max34451_get(TEST_ID, path); 97 g_assert_cmpuint(value, ==, DEFAULT_TEMPERATURE); 98 g_free(path); 99 100 /* Temperature sensors start on page 16 */ 101 i2c_set8(i2cdev, PMBUS_PAGE, i + 16); 102 i2c_value = max34451_i2c_get16(i2cdev, PMBUS_READ_TEMPERATURE_1); 103 g_assert_cmpuint(i2c_value, ==, DEFAULT_TEMPERATURE); 104 105 i2c_value = max34451_i2c_get16(i2cdev, PMBUS_OT_FAULT_LIMIT); 106 g_assert_cmpuint(i2c_value, ==, DEFAULT_OT_LIMIT); 107 108 i2c_value = max34451_i2c_get16(i2cdev, PMBUS_OT_WARN_LIMIT); 109 g_assert_cmpuint(i2c_value, ==, DEFAULT_OT_LIMIT); 110 } 111 112 /* Default voltages and fault limits */ 113 for (int i = 0; i < MAX34451_NUM_PWR_DEVICES; i++) { 114 path = g_strdup_printf("vout[%d]", i); 115 value = qmp_max34451_get(TEST_ID, path); 116 g_assert_cmpuint(value, ==, DEFAULT_VOUT); 117 g_free(path); 118 119 i2c_set8(i2cdev, PMBUS_PAGE, i); 120 i2c_value = max34451_i2c_get16(i2cdev, PMBUS_READ_VOUT); 121 g_assert_cmpuint(i2c_value, ==, DEFAULT_VOUT); 122 123 i2c_value = max34451_i2c_get16(i2cdev, PMBUS_VOUT_OV_FAULT_LIMIT); 124 g_assert_cmpuint(i2c_value, ==, DEFAULT_OV_LIMIT); 125 126 i2c_value = max34451_i2c_get16(i2cdev, PMBUS_VOUT_OV_WARN_LIMIT); 127 g_assert_cmpuint(i2c_value, ==, DEFAULT_OV_LIMIT); 128 129 i2c_value = max34451_i2c_get16(i2cdev, PMBUS_VOUT_UV_WARN_LIMIT); 130 g_assert_cmpuint(i2c_value, ==, DEFAULT_UV_LIMIT); 131 132 i2c_value = max34451_i2c_get16(i2cdev, PMBUS_VOUT_UV_FAULT_LIMIT); 133 g_assert_cmpuint(i2c_value, ==, DEFAULT_UV_LIMIT); 134 135 i2c_value = max34451_i2c_get16(i2cdev, MAX34451_MFR_VOUT_MIN); 136 g_assert_cmpuint(i2c_value, ==, DEFAULT_VMIN); 137 } 138 139 i2c_value = i2c_get8(i2cdev, PMBUS_VOUT_MODE); 140 g_assert_cmphex(i2c_value, ==, 0x40); /* DIRECT mode */ 141 142 i2c_value = i2c_get8(i2cdev, PMBUS_REVISION); 143 g_assert_cmphex(i2c_value, ==, 0x11); /* Rev 1.1 */ 144 } 145 146 /* Test setting temperature */ 147 static void test_temperature(void *obj, void *data, QGuestAllocator *alloc) 148 { 149 uint16_t value, i2c_value; 150 QI2CDevice *i2cdev = (QI2CDevice *)obj; 151 char *path; 152 153 for (int i = 0; i < MAX34451_NUM_TEMP_DEVICES; i++) { 154 path = g_strdup_printf("temperature[%d]", i); 155 qmp_max34451_set(TEST_ID, path, 0xBE00 + i); 156 value = qmp_max34451_get(TEST_ID, path); 157 g_assert_cmphex(value, ==, 0xBE00 + i); 158 g_free(path); 159 } 160 161 /* compare qmp read with i2c read separately */ 162 for (int i = 0; i < MAX34451_NUM_TEMP_DEVICES; i++) { 163 /* temperature[0] is on page 16 */ 164 i2c_set8(i2cdev, PMBUS_PAGE, i + 16); 165 i2c_value = max34451_i2c_get16(i2cdev, PMBUS_READ_TEMPERATURE_1); 166 g_assert_cmphex(i2c_value, ==, 0xBE00 + i); 167 168 i2c_value = max34451_i2c_get16(i2cdev, MAX34451_MFR_TEMPERATURE_PEAK); 169 g_assert_cmphex(i2c_value, ==, 0xBE00 + i); 170 } 171 } 172 173 /* Test setting voltage */ 174 static void test_voltage(void *obj, void *data, QGuestAllocator *alloc) 175 { 176 uint16_t value, i2c_value; 177 QI2CDevice *i2cdev = (QI2CDevice *)obj; 178 char *path; 179 180 for (int i = 0; i < MAX34451_NUM_PWR_DEVICES; i++) { 181 path = g_strdup_printf("vout[%d]", i); 182 qmp_max34451_set(TEST_ID, path, 3000 + i); 183 value = qmp_max34451_get(TEST_ID, path); 184 g_assert_cmpuint(value, ==, 3000 + i); 185 g_free(path); 186 } 187 188 /* compare qmp read with i2c read separately */ 189 for (int i = 0; i < MAX34451_NUM_PWR_DEVICES; i++) { 190 i2c_set8(i2cdev, PMBUS_PAGE, i); 191 i2c_value = max34451_i2c_get16(i2cdev, PMBUS_READ_VOUT); 192 g_assert_cmpuint(i2c_value, ==, 3000 + i); 193 194 i2c_value = max34451_i2c_get16(i2cdev, MAX34451_MFR_VOUT_PEAK); 195 g_assert_cmpuint(i2c_value, ==, 3000 + i); 196 197 i2c_value = max34451_i2c_get16(i2cdev, MAX34451_MFR_VOUT_MIN); 198 g_assert_cmpuint(i2c_value, ==, 3000 + i); 199 } 200 } 201 202 /* Test setting some read/write registers */ 203 static void test_rw_regs(void *obj, void *data, QGuestAllocator *alloc) 204 { 205 uint16_t i2c_value; 206 QI2CDevice *i2cdev = (QI2CDevice *)obj; 207 208 i2c_set8(i2cdev, PMBUS_PAGE, 11); 209 i2c_value = i2c_get8(i2cdev, PMBUS_PAGE); 210 g_assert_cmpuint(i2c_value, ==, 11); 211 212 i2c_set8(i2cdev, PMBUS_OPERATION, 1); 213 i2c_value = i2c_get8(i2cdev, PMBUS_OPERATION); 214 g_assert_cmpuint(i2c_value, ==, 1); 215 216 max34451_i2c_set16(i2cdev, PMBUS_VOUT_MARGIN_HIGH, 5000); 217 i2c_value = max34451_i2c_get16(i2cdev, PMBUS_VOUT_MARGIN_HIGH); 218 g_assert_cmpuint(i2c_value, ==, 5000); 219 220 max34451_i2c_set16(i2cdev, PMBUS_VOUT_MARGIN_LOW, 4000); 221 i2c_value = max34451_i2c_get16(i2cdev, PMBUS_VOUT_MARGIN_LOW); 222 g_assert_cmpuint(i2c_value, ==, 4000); 223 224 max34451_i2c_set16(i2cdev, PMBUS_VOUT_OV_FAULT_LIMIT, 5500); 225 i2c_value = max34451_i2c_get16(i2cdev, PMBUS_VOUT_OV_FAULT_LIMIT); 226 g_assert_cmpuint(i2c_value, ==, 5500); 227 228 max34451_i2c_set16(i2cdev, PMBUS_VOUT_OV_WARN_LIMIT, 5600); 229 i2c_value = max34451_i2c_get16(i2cdev, PMBUS_VOUT_OV_WARN_LIMIT); 230 g_assert_cmpuint(i2c_value, ==, 5600); 231 232 max34451_i2c_set16(i2cdev, PMBUS_VOUT_UV_FAULT_LIMIT, 5700); 233 i2c_value = max34451_i2c_get16(i2cdev, PMBUS_VOUT_UV_FAULT_LIMIT); 234 g_assert_cmpuint(i2c_value, ==, 5700); 235 236 max34451_i2c_set16(i2cdev, PMBUS_VOUT_UV_WARN_LIMIT, 5800); 237 i2c_value = max34451_i2c_get16(i2cdev, PMBUS_VOUT_UV_WARN_LIMIT); 238 g_assert_cmpuint(i2c_value, ==, 5800); 239 240 max34451_i2c_set16(i2cdev, PMBUS_POWER_GOOD_ON, 5900); 241 i2c_value = max34451_i2c_get16(i2cdev, PMBUS_POWER_GOOD_ON); 242 g_assert_cmpuint(i2c_value, ==, 5900); 243 244 max34451_i2c_set16(i2cdev, PMBUS_POWER_GOOD_OFF, 6100); 245 i2c_value = max34451_i2c_get16(i2cdev, PMBUS_POWER_GOOD_OFF); 246 g_assert_cmpuint(i2c_value, ==, 6100); 247 } 248 249 /* Test that Read only registers can't be written */ 250 static void test_ro_regs(void *obj, void *data, QGuestAllocator *alloc) 251 { 252 uint16_t i2c_value, i2c_init_value; 253 QI2CDevice *i2cdev = (QI2CDevice *)obj; 254 255 i2c_set8(i2cdev, PMBUS_PAGE, 1); /* move to page 1 */ 256 i2c_init_value = i2c_get8(i2cdev, PMBUS_CAPABILITY); 257 i2c_set8(i2cdev, PMBUS_CAPABILITY, 0xF9); 258 i2c_value = i2c_get8(i2cdev, PMBUS_CAPABILITY); 259 g_assert_cmpuint(i2c_init_value, ==, i2c_value); 260 261 i2c_init_value = max34451_i2c_get16(i2cdev, PMBUS_READ_VOUT); 262 max34451_i2c_set16(i2cdev, PMBUS_READ_VOUT, 0xDEAD); 263 i2c_value = max34451_i2c_get16(i2cdev, PMBUS_READ_VOUT); 264 g_assert_cmpuint(i2c_init_value, ==, i2c_value); 265 g_assert_cmphex(i2c_value, !=, 0xDEAD); 266 267 i2c_set8(i2cdev, PMBUS_PAGE, 16); /* move to page 16 */ 268 i2c_init_value = max34451_i2c_get16(i2cdev, PMBUS_READ_TEMPERATURE_1); 269 max34451_i2c_set16(i2cdev, PMBUS_READ_TEMPERATURE_1, 0xABBA); 270 i2c_value = max34451_i2c_get16(i2cdev, PMBUS_READ_TEMPERATURE_1); 271 g_assert_cmpuint(i2c_init_value, ==, i2c_value); 272 g_assert_cmphex(i2c_value, !=, 0xABBA); 273 } 274 275 /* test over voltage faults */ 276 static void test_ov_faults(void *obj, void *data, QGuestAllocator *alloc) 277 { 278 uint16_t i2c_value; 279 uint8_t i2c_byte; 280 QI2CDevice *i2cdev = (QI2CDevice *)obj; 281 char *path; 282 /* Test ov fault reporting */ 283 for (int i = 0; i < MAX34451_NUM_PWR_DEVICES; i++) { 284 path = g_strdup_printf("vout[%d]", i); 285 i2c_set8(i2cdev, PMBUS_PAGE, i); 286 max34451_i2c_set16(i2cdev, PMBUS_VOUT_OV_FAULT_LIMIT, 5000); 287 qmp_max34451_set(TEST_ID, path, 5100); 288 g_free(path); 289 290 i2c_value = max34451_i2c_get16(i2cdev, PMBUS_STATUS_WORD); 291 i2c_byte = i2c_get8(i2cdev, PMBUS_STATUS_VOUT); 292 g_assert_true((i2c_value & PB_STATUS_VOUT) != 0); 293 g_assert_true((i2c_byte & PB_STATUS_VOUT_OV_FAULT) != 0); 294 } 295 } 296 297 /* test over temperature faults */ 298 static void test_ot_faults(void *obj, void *data, QGuestAllocator *alloc) 299 { 300 uint16_t i2c_value; 301 uint8_t i2c_byte; 302 QI2CDevice *i2cdev = (QI2CDevice *)obj; 303 char *path; 304 305 for (int i = 0; i < MAX34451_NUM_TEMP_DEVICES; i++) { 306 path = g_strdup_printf("temperature[%d]", i); 307 i2c_set8(i2cdev, PMBUS_PAGE, i + 16); 308 max34451_i2c_set16(i2cdev, PMBUS_OT_FAULT_LIMIT, 6000); 309 qmp_max34451_set(TEST_ID, path, 6100); 310 g_free(path); 311 312 i2c_value = max34451_i2c_get16(i2cdev, PMBUS_STATUS_WORD); 313 i2c_byte = i2c_get8(i2cdev, PMBUS_STATUS_TEMPERATURE); 314 g_assert_true((i2c_value & PB_STATUS_TEMPERATURE) != 0); 315 g_assert_true((i2c_byte & PB_STATUS_OT_FAULT) != 0); 316 } 317 } 318 319 #define RAND_ON_OFF_CONFIG 0x12 320 #define RAND_MFR_MODE 0x3456 321 322 /* test writes to all pages */ 323 static void test_all_pages(void *obj, void *data, QGuestAllocator *alloc) 324 { 325 uint16_t i2c_value; 326 QI2CDevice *i2cdev = (QI2CDevice *)obj; 327 328 i2c_set8(i2cdev, PMBUS_PAGE, PB_ALL_PAGES); 329 i2c_set8(i2cdev, PMBUS_ON_OFF_CONFIG, RAND_ON_OFF_CONFIG); 330 max34451_i2c_set16(i2cdev, MAX34451_MFR_MODE, RAND_MFR_MODE); 331 332 for (int i = 0; i < MAX34451_NUM_TEMP_DEVICES + MAX34451_NUM_PWR_DEVICES; 333 i++) { 334 i2c_value = i2c_get8(i2cdev, PMBUS_ON_OFF_CONFIG); 335 g_assert_cmphex(i2c_value, ==, RAND_ON_OFF_CONFIG); 336 i2c_value = max34451_i2c_get16(i2cdev, MAX34451_MFR_MODE); 337 g_assert_cmphex(i2c_value, ==, RAND_MFR_MODE); 338 } 339 } 340 341 static void max34451_register_nodes(void) 342 { 343 QOSGraphEdgeOptions opts = { 344 .extra_device_opts = "id=" TEST_ID ",address=0x4e" 345 }; 346 add_qi2c_address(&opts, &(QI2CAddress) { TEST_ADDR }); 347 348 qos_node_create_driver("max34451", i2c_device_create); 349 qos_node_consumes("max34451", "i2c-bus", &opts); 350 351 qos_add_test("test_defaults", "max34451", test_defaults, NULL); 352 qos_add_test("test_temperature", "max34451", test_temperature, NULL); 353 qos_add_test("test_voltage", "max34451", test_voltage, NULL); 354 qos_add_test("test_rw_regs", "max34451", test_rw_regs, NULL); 355 qos_add_test("test_ro_regs", "max34451", test_ro_regs, NULL); 356 qos_add_test("test_ov_faults", "max34451", test_ov_faults, NULL); 357 qos_add_test("test_ot_faults", "max34451", test_ot_faults, NULL); 358 qos_add_test("test_all_pages", "max34451", test_all_pages, NULL); 359 } 360 libqos_init(max34451_register_nodes); 361