xref: /qemu/hw/sensor/adm1272.c (revision 727385c4)
1 /*
2  * Analog Devices ADM1272 High Voltage Positive Hot Swap Controller and Digital
3  * Power Monitor with PMBus
4  *
5  * Copyright 2021 Google LLC
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  */
9 
10 #include "qemu/osdep.h"
11 #include <string.h>
12 #include "hw/i2c/pmbus_device.h"
13 #include "hw/irq.h"
14 #include "migration/vmstate.h"
15 #include "qapi/error.h"
16 #include "qapi/visitor.h"
17 #include "qemu/log.h"
18 #include "qemu/module.h"
19 
20 #define TYPE_ADM1272 "adm1272"
21 #define ADM1272(obj) OBJECT_CHECK(ADM1272State, (obj), TYPE_ADM1272)
22 
23 #define ADM1272_RESTART_TIME            0xCC
24 #define ADM1272_MFR_PEAK_IOUT           0xD0
25 #define ADM1272_MFR_PEAK_VIN            0xD1
26 #define ADM1272_MFR_PEAK_VOUT           0xD2
27 #define ADM1272_MFR_PMON_CONTROL        0xD3
28 #define ADM1272_MFR_PMON_CONFIG         0xD4
29 #define ADM1272_MFR_ALERT1_CONFIG       0xD5
30 #define ADM1272_MFR_ALERT2_CONFIG       0xD6
31 #define ADM1272_MFR_PEAK_TEMPERATURE    0xD7
32 #define ADM1272_MFR_DEVICE_CONFIG       0xD8
33 #define ADM1272_MFR_POWER_CYCLE         0xD9
34 #define ADM1272_MFR_PEAK_PIN            0xDA
35 #define ADM1272_MFR_READ_PIN_EXT        0xDB
36 #define ADM1272_MFR_READ_EIN_EXT        0xDC
37 
38 #define ADM1272_HYSTERESIS_LOW          0xF2
39 #define ADM1272_HYSTERESIS_HIGH         0xF3
40 #define ADM1272_STATUS_HYSTERESIS       0xF4
41 #define ADM1272_STATUS_GPIO             0xF5
42 #define ADM1272_STRT_UP_IOUT_LIM        0xF6
43 
44 /* Defaults */
45 #define ADM1272_OPERATION_DEFAULT       0x80
46 #define ADM1272_CAPABILITY_DEFAULT      0xB0
47 #define ADM1272_CAPABILITY_NO_PEC       0x30
48 #define ADM1272_DIRECT_MODE             0x40
49 #define ADM1272_HIGH_LIMIT_DEFAULT      0x0FFF
50 #define ADM1272_PIN_OP_DEFAULT          0x7FFF
51 #define ADM1272_PMBUS_REVISION_DEFAULT  0x22
52 #define ADM1272_MFR_ID_DEFAULT          "ADI"
53 #define ADM1272_MODEL_DEFAULT           "ADM1272-A1"
54 #define ADM1272_MFR_DEFAULT_REVISION    "25"
55 #define ADM1272_DEFAULT_DATE            "160301"
56 #define ADM1272_RESTART_TIME_DEFAULT    0x64
57 #define ADM1272_PMON_CONTROL_DEFAULT    0x1
58 #define ADM1272_PMON_CONFIG_DEFAULT     0x3F35
59 #define ADM1272_DEVICE_CONFIG_DEFAULT   0x8
60 #define ADM1272_HYSTERESIS_HIGH_DEFAULT     0xFFFF
61 #define ADM1272_STRT_UP_IOUT_LIM_DEFAULT    0x000F
62 #define ADM1272_VOLT_DEFAULT            12000
63 #define ADM1272_IOUT_DEFAULT            25000
64 #define ADM1272_PWR_DEFAULT             300  /* 12V 25A */
65 #define ADM1272_SHUNT                   300 /* micro-ohms */
66 #define ADM1272_VOLTAGE_COEFF_DEFAULT   1
67 #define ADM1272_CURRENT_COEFF_DEFAULT   3
68 #define ADM1272_PWR_COEFF_DEFAULT       7
69 #define ADM1272_IOUT_OFFSET             0x5000
70 #define ADM1272_IOUT_OFFSET             0x5000
71 
72 
73 typedef struct ADM1272State {
74     PMBusDevice parent;
75 
76     uint64_t ein_ext;
77     uint32_t pin_ext;
78     uint8_t restart_time;
79 
80     uint16_t peak_vin;
81     uint16_t peak_vout;
82     uint16_t peak_iout;
83     uint16_t peak_temperature;
84     uint16_t peak_pin;
85 
86     uint8_t pmon_control;
87     uint16_t pmon_config;
88     uint16_t alert1_config;
89     uint16_t alert2_config;
90     uint16_t device_config;
91 
92     uint16_t hysteresis_low;
93     uint16_t hysteresis_high;
94     uint8_t status_hysteresis;
95     uint8_t status_gpio;
96 
97     uint16_t strt_up_iout_lim;
98 
99 } ADM1272State;
100 
101 static const PMBusCoefficients adm1272_coefficients[] = {
102     [0] = { 6770, 0, -2 },        /* voltage, vrange 60V */
103     [1] = { 4062, 0, -2 },        /* voltage, vrange 100V */
104     [2] = { 1326, 20480, -1 },    /* current, vsense range 15mV */
105     [3] = { 663, 20480, -1 },     /* current, vsense range 30mV */
106     [4] = { 3512, 0, -2 },        /* power, vrange 60V, irange 15mV */
107     [5] = { 21071, 0, -3 },       /* power, vrange 100V, irange 15mV */
108     [6] = { 17561, 0, -3 },       /* power, vrange 60V, irange 30mV */
109     [7] = { 10535, 0, -3 },       /* power, vrange 100V, irange 30mV */
110     [8] = { 42, 31871, -1 },      /* temperature */
111 };
112 
113 static void adm1272_check_limits(ADM1272State *s)
114 {
115     PMBusDevice *pmdev = PMBUS_DEVICE(s);
116 
117     pmbus_check_limits(pmdev);
118 
119     if (pmdev->pages[0].read_vout > s->peak_vout) {
120         s->peak_vout = pmdev->pages[0].read_vout;
121     }
122 
123     if (pmdev->pages[0].read_vin > s->peak_vin) {
124         s->peak_vin = pmdev->pages[0].read_vin;
125     }
126 
127     if (pmdev->pages[0].read_iout > s->peak_iout) {
128         s->peak_iout = pmdev->pages[0].read_iout;
129     }
130 
131     if (pmdev->pages[0].read_temperature_1 > s->peak_temperature) {
132         s->peak_temperature = pmdev->pages[0].read_temperature_1;
133     }
134 
135     if (pmdev->pages[0].read_pin > s->peak_pin) {
136         s->peak_pin = pmdev->pages[0].read_pin;
137     }
138 }
139 
140 static uint16_t adm1272_millivolts_to_direct(uint32_t value)
141 {
142     PMBusCoefficients c = adm1272_coefficients[ADM1272_VOLTAGE_COEFF_DEFAULT];
143     c.b = c.b * 1000;
144     c.R = c.R - 3;
145     return pmbus_data2direct_mode(c, value);
146 }
147 
148 static uint32_t adm1272_direct_to_millivolts(uint16_t value)
149 {
150     PMBusCoefficients c = adm1272_coefficients[ADM1272_VOLTAGE_COEFF_DEFAULT];
151     c.b = c.b * 1000;
152     c.R = c.R - 3;
153     return pmbus_direct_mode2data(c, value);
154 }
155 
156 static uint16_t adm1272_milliamps_to_direct(uint32_t value)
157 {
158     PMBusCoefficients c = adm1272_coefficients[ADM1272_CURRENT_COEFF_DEFAULT];
159     /* Y = (m * r_sense * x - b) * 10^R */
160     c.m = c.m * ADM1272_SHUNT / 1000; /* micro-ohms */
161     c.b = c.b * 1000;
162     c.R = c.R - 3;
163     return pmbus_data2direct_mode(c, value);
164 }
165 
166 static uint32_t adm1272_direct_to_milliamps(uint16_t value)
167 {
168     PMBusCoefficients c = adm1272_coefficients[ADM1272_CURRENT_COEFF_DEFAULT];
169     c.m = c.m * ADM1272_SHUNT / 1000;
170     c.b = c.b * 1000;
171     c.R = c.R - 3;
172     return pmbus_direct_mode2data(c, value);
173 }
174 
175 static uint16_t adm1272_watts_to_direct(uint32_t value)
176 {
177     PMBusCoefficients c = adm1272_coefficients[ADM1272_PWR_COEFF_DEFAULT];
178     c.m = c.m * ADM1272_SHUNT / 1000;
179     return pmbus_data2direct_mode(c, value);
180 }
181 
182 static uint32_t adm1272_direct_to_watts(uint16_t value)
183 {
184     PMBusCoefficients c = adm1272_coefficients[ADM1272_PWR_COEFF_DEFAULT];
185     c.m = c.m * ADM1272_SHUNT / 1000;
186     return pmbus_direct_mode2data(c, value);
187 }
188 
189 static void adm1272_exit_reset(Object *obj)
190 {
191     ADM1272State *s = ADM1272(obj);
192     PMBusDevice *pmdev = PMBUS_DEVICE(obj);
193 
194     pmdev->page = 0;
195     pmdev->pages[0].operation = ADM1272_OPERATION_DEFAULT;
196 
197 
198     pmdev->capability = ADM1272_CAPABILITY_NO_PEC;
199     pmdev->pages[0].revision = ADM1272_PMBUS_REVISION_DEFAULT;
200     pmdev->pages[0].vout_mode = ADM1272_DIRECT_MODE;
201     pmdev->pages[0].vout_ov_warn_limit = ADM1272_HIGH_LIMIT_DEFAULT;
202     pmdev->pages[0].vout_uv_warn_limit = 0;
203     pmdev->pages[0].iout_oc_warn_limit = ADM1272_HIGH_LIMIT_DEFAULT;
204     pmdev->pages[0].ot_fault_limit = ADM1272_HIGH_LIMIT_DEFAULT;
205     pmdev->pages[0].ot_warn_limit = ADM1272_HIGH_LIMIT_DEFAULT;
206     pmdev->pages[0].vin_ov_warn_limit = ADM1272_HIGH_LIMIT_DEFAULT;
207     pmdev->pages[0].vin_uv_warn_limit = 0;
208     pmdev->pages[0].pin_op_warn_limit = ADM1272_PIN_OP_DEFAULT;
209 
210     pmdev->pages[0].status_word = 0;
211     pmdev->pages[0].status_vout = 0;
212     pmdev->pages[0].status_iout = 0;
213     pmdev->pages[0].status_input = 0;
214     pmdev->pages[0].status_temperature = 0;
215     pmdev->pages[0].status_mfr_specific = 0;
216 
217     pmdev->pages[0].read_vin
218         = adm1272_millivolts_to_direct(ADM1272_VOLT_DEFAULT);
219     pmdev->pages[0].read_vout
220         = adm1272_millivolts_to_direct(ADM1272_VOLT_DEFAULT);
221     pmdev->pages[0].read_iout
222         = adm1272_milliamps_to_direct(ADM1272_IOUT_DEFAULT);
223     pmdev->pages[0].read_temperature_1 = 0;
224     pmdev->pages[0].read_pin = adm1272_watts_to_direct(ADM1272_PWR_DEFAULT);
225     pmdev->pages[0].revision = ADM1272_PMBUS_REVISION_DEFAULT;
226     pmdev->pages[0].mfr_id = ADM1272_MFR_ID_DEFAULT;
227     pmdev->pages[0].mfr_model = ADM1272_MODEL_DEFAULT;
228     pmdev->pages[0].mfr_revision = ADM1272_MFR_DEFAULT_REVISION;
229     pmdev->pages[0].mfr_date = ADM1272_DEFAULT_DATE;
230 
231     s->pin_ext = 0;
232     s->ein_ext = 0;
233     s->restart_time = ADM1272_RESTART_TIME_DEFAULT;
234 
235     s->peak_vin = 0;
236     s->peak_vout = 0;
237     s->peak_iout = 0;
238     s->peak_temperature = 0;
239     s->peak_pin = 0;
240 
241     s->pmon_control = ADM1272_PMON_CONTROL_DEFAULT;
242     s->pmon_config = ADM1272_PMON_CONFIG_DEFAULT;
243     s->alert1_config = 0;
244     s->alert2_config = 0;
245     s->device_config = ADM1272_DEVICE_CONFIG_DEFAULT;
246 
247     s->hysteresis_low = 0;
248     s->hysteresis_high = ADM1272_HYSTERESIS_HIGH_DEFAULT;
249     s->status_hysteresis = 0;
250     s->status_gpio = 0;
251 
252     s->strt_up_iout_lim = ADM1272_STRT_UP_IOUT_LIM_DEFAULT;
253 }
254 
255 static uint8_t adm1272_read_byte(PMBusDevice *pmdev)
256 {
257     ADM1272State *s = ADM1272(pmdev);
258 
259     switch (pmdev->code) {
260     case ADM1272_RESTART_TIME:
261         pmbus_send8(pmdev, s->restart_time);
262         break;
263 
264     case ADM1272_MFR_PEAK_IOUT:
265         pmbus_send16(pmdev, s->peak_iout);
266         break;
267 
268     case ADM1272_MFR_PEAK_VIN:
269         pmbus_send16(pmdev, s->peak_vin);
270         break;
271 
272     case ADM1272_MFR_PEAK_VOUT:
273         pmbus_send16(pmdev, s->peak_vout);
274         break;
275 
276     case ADM1272_MFR_PMON_CONTROL:
277         pmbus_send8(pmdev, s->pmon_control);
278         break;
279 
280     case ADM1272_MFR_PMON_CONFIG:
281         pmbus_send16(pmdev, s->pmon_config);
282         break;
283 
284     case ADM1272_MFR_ALERT1_CONFIG:
285         pmbus_send16(pmdev, s->alert1_config);
286         break;
287 
288     case ADM1272_MFR_ALERT2_CONFIG:
289         pmbus_send16(pmdev, s->alert2_config);
290         break;
291 
292     case ADM1272_MFR_PEAK_TEMPERATURE:
293         pmbus_send16(pmdev, s->peak_temperature);
294         break;
295 
296     case ADM1272_MFR_DEVICE_CONFIG:
297         pmbus_send16(pmdev, s->device_config);
298         break;
299 
300     case ADM1272_MFR_PEAK_PIN:
301         pmbus_send16(pmdev, s->peak_pin);
302         break;
303 
304     case ADM1272_MFR_READ_PIN_EXT:
305         pmbus_send32(pmdev, s->pin_ext);
306         break;
307 
308     case ADM1272_MFR_READ_EIN_EXT:
309         pmbus_send64(pmdev, s->ein_ext);
310         break;
311 
312     case ADM1272_HYSTERESIS_LOW:
313         pmbus_send16(pmdev, s->hysteresis_low);
314         break;
315 
316     case ADM1272_HYSTERESIS_HIGH:
317         pmbus_send16(pmdev, s->hysteresis_high);
318         break;
319 
320     case ADM1272_STATUS_HYSTERESIS:
321         pmbus_send16(pmdev, s->status_hysteresis);
322         break;
323 
324     case ADM1272_STATUS_GPIO:
325         pmbus_send16(pmdev, s->status_gpio);
326         break;
327 
328     case ADM1272_STRT_UP_IOUT_LIM:
329         pmbus_send16(pmdev, s->strt_up_iout_lim);
330         break;
331 
332     default:
333         qemu_log_mask(LOG_GUEST_ERROR,
334                       "%s: reading from unsupported register: 0x%02x\n",
335                       __func__, pmdev->code);
336         return 0xFF;
337         break;
338     }
339 
340     return 0;
341 }
342 
343 static int adm1272_write_data(PMBusDevice *pmdev, const uint8_t *buf,
344                               uint8_t len)
345 {
346     ADM1272State *s = ADM1272(pmdev);
347 
348     if (len == 0) {
349         qemu_log_mask(LOG_GUEST_ERROR, "%s: writing empty data\n", __func__);
350         return -1;
351     }
352 
353     pmdev->code = buf[0]; /* PMBus command code */
354 
355     if (len == 1) {
356         return 0;
357     }
358 
359     /* Exclude command code from buffer */
360     buf++;
361     len--;
362 
363     switch (pmdev->code) {
364 
365     case ADM1272_RESTART_TIME:
366         s->restart_time = pmbus_receive8(pmdev);
367         break;
368 
369     case ADM1272_MFR_PMON_CONTROL:
370         s->pmon_control = pmbus_receive8(pmdev);
371         break;
372 
373     case ADM1272_MFR_PMON_CONFIG:
374         s->pmon_config = pmbus_receive16(pmdev);
375         break;
376 
377     case ADM1272_MFR_ALERT1_CONFIG:
378         s->alert1_config = pmbus_receive16(pmdev);
379         break;
380 
381     case ADM1272_MFR_ALERT2_CONFIG:
382         s->alert2_config = pmbus_receive16(pmdev);
383         break;
384 
385     case ADM1272_MFR_DEVICE_CONFIG:
386         s->device_config = pmbus_receive16(pmdev);
387         break;
388 
389     case ADM1272_MFR_POWER_CYCLE:
390         adm1272_exit_reset((Object *)s);
391         break;
392 
393     case ADM1272_HYSTERESIS_LOW:
394         s->hysteresis_low = pmbus_receive16(pmdev);
395         break;
396 
397     case ADM1272_HYSTERESIS_HIGH:
398         s->hysteresis_high = pmbus_receive16(pmdev);
399         break;
400 
401     case ADM1272_STRT_UP_IOUT_LIM:
402         s->strt_up_iout_lim = pmbus_receive16(pmdev);
403         adm1272_check_limits(s);
404         break;
405 
406     default:
407         qemu_log_mask(LOG_GUEST_ERROR,
408                       "%s: writing to unsupported register: 0x%02x\n",
409                       __func__, pmdev->code);
410         break;
411     }
412     return 0;
413 }
414 
415 static void adm1272_get(Object *obj, Visitor *v, const char *name, void *opaque,
416                         Error **errp)
417 {
418     uint16_t value;
419 
420     if (strcmp(name, "vin") == 0 || strcmp(name, "vout") == 0) {
421         value = adm1272_direct_to_millivolts(*(uint16_t *)opaque);
422     } else if (strcmp(name, "iout") == 0) {
423         value = adm1272_direct_to_milliamps(*(uint16_t *)opaque);
424     } else if (strcmp(name, "pin") == 0) {
425         value = adm1272_direct_to_watts(*(uint16_t *)opaque);
426     } else {
427         value = *(uint16_t *)opaque;
428     }
429 
430     visit_type_uint16(v, name, &value, errp);
431 }
432 
433 static void adm1272_set(Object *obj, Visitor *v, const char *name, void *opaque,
434                         Error **errp)
435 {
436     ADM1272State *s = ADM1272(obj);
437     uint16_t *internal = opaque;
438     uint16_t value;
439 
440     if (!visit_type_uint16(v, name, &value, errp)) {
441         return;
442     }
443 
444     if (strcmp(name, "vin") == 0 || strcmp(name, "vout") == 0) {
445         *internal = adm1272_millivolts_to_direct(value);
446     } else if (strcmp(name, "iout") == 0) {
447         *internal = adm1272_milliamps_to_direct(value);
448     } else if (strcmp(name, "pin") == 0) {
449         *internal = adm1272_watts_to_direct(value);
450     } else {
451         *internal = value;
452     }
453 
454     adm1272_check_limits(s);
455 }
456 
457 static const VMStateDescription vmstate_adm1272 = {
458     .name = "ADM1272",
459     .version_id = 0,
460     .minimum_version_id = 0,
461     .fields = (VMStateField[]){
462         VMSTATE_PMBUS_DEVICE(parent, ADM1272State),
463         VMSTATE_UINT64(ein_ext, ADM1272State),
464         VMSTATE_UINT32(pin_ext, ADM1272State),
465         VMSTATE_UINT8(restart_time, ADM1272State),
466 
467         VMSTATE_UINT16(peak_vin, ADM1272State),
468         VMSTATE_UINT16(peak_vout, ADM1272State),
469         VMSTATE_UINT16(peak_iout, ADM1272State),
470         VMSTATE_UINT16(peak_temperature, ADM1272State),
471         VMSTATE_UINT16(peak_pin, ADM1272State),
472 
473         VMSTATE_UINT8(pmon_control, ADM1272State),
474         VMSTATE_UINT16(pmon_config, ADM1272State),
475         VMSTATE_UINT16(alert1_config, ADM1272State),
476         VMSTATE_UINT16(alert2_config, ADM1272State),
477         VMSTATE_UINT16(device_config, ADM1272State),
478 
479         VMSTATE_UINT16(hysteresis_low, ADM1272State),
480         VMSTATE_UINT16(hysteresis_high, ADM1272State),
481         VMSTATE_UINT8(status_hysteresis, ADM1272State),
482         VMSTATE_UINT8(status_gpio, ADM1272State),
483 
484         VMSTATE_UINT16(strt_up_iout_lim, ADM1272State),
485         VMSTATE_END_OF_LIST()
486     }
487 };
488 
489 static void adm1272_init(Object *obj)
490 {
491     PMBusDevice *pmdev = PMBUS_DEVICE(obj);
492     uint64_t flags = PB_HAS_VOUT_MODE | PB_HAS_VOUT | PB_HAS_VIN | PB_HAS_IOUT |
493                      PB_HAS_PIN | PB_HAS_TEMPERATURE | PB_HAS_MFR_INFO;
494 
495     pmbus_page_config(pmdev, 0, flags);
496 
497     object_property_add(obj, "vin", "uint16",
498                         adm1272_get,
499                         adm1272_set, NULL, &pmdev->pages[0].read_vin);
500 
501     object_property_add(obj, "vout", "uint16",
502                         adm1272_get,
503                         adm1272_set, NULL, &pmdev->pages[0].read_vout);
504 
505     object_property_add(obj, "iout", "uint16",
506                         adm1272_get,
507                         adm1272_set, NULL, &pmdev->pages[0].read_iout);
508 
509     object_property_add(obj, "pin", "uint16",
510                         adm1272_get,
511                         adm1272_set, NULL, &pmdev->pages[0].read_pin);
512 
513 }
514 
515 static void adm1272_class_init(ObjectClass *klass, void *data)
516 {
517     ResettableClass *rc = RESETTABLE_CLASS(klass);
518     DeviceClass *dc = DEVICE_CLASS(klass);
519     PMBusDeviceClass *k = PMBUS_DEVICE_CLASS(klass);
520 
521     dc->desc = "Analog Devices ADM1272 Hot Swap controller";
522     dc->vmsd = &vmstate_adm1272;
523     k->write_data = adm1272_write_data;
524     k->receive_byte = adm1272_read_byte;
525     k->device_num_pages = 1;
526 
527     rc->phases.exit = adm1272_exit_reset;
528 }
529 
530 static const TypeInfo adm1272_info = {
531     .name = TYPE_ADM1272,
532     .parent = TYPE_PMBUS_DEVICE,
533     .instance_size = sizeof(ADM1272State),
534     .instance_init = adm1272_init,
535     .class_init = adm1272_class_init,
536 };
537 
538 static void adm1272_register_types(void)
539 {
540     type_register_static(&adm1272_info);
541 }
542 
543 type_init(adm1272_register_types)
544