xref: /openbmc/qemu/hw/sensor/max34451.c (revision 42fe7499)
1 /*
2  * Maxim MAX34451 PMBus 16-Channel V/I monitor and 12-Channel Sequencer/Marginer
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 "hw/irq.h"
12 #include "migration/vmstate.h"
13 #include "qapi/error.h"
14 #include "qapi/visitor.h"
15 #include "qemu/log.h"
16 #include "qemu/module.h"
17 
18 #define TYPE_MAX34451 "max34451"
19 #define MAX34451(obj) OBJECT_CHECK(MAX34451State, (obj), TYPE_MAX34451)
20 
21 #define MAX34451_MFR_MODE               0xD1
22 #define MAX34451_MFR_PSEN_CONFIG        0xD2
23 #define MAX34451_MFR_VOUT_PEAK          0xD4
24 #define MAX34451_MFR_IOUT_PEAK          0xD5
25 #define MAX34451_MFR_TEMPERATURE_PEAK   0xD6
26 #define MAX34451_MFR_VOUT_MIN           0xD7
27 #define MAX34451_MFR_NV_LOG_CONFIG      0xD8
28 #define MAX34451_MFR_FAULT_RESPONSE     0xD9
29 #define MAX34451_MFR_FAULT_RETRY        0xDA
30 #define MAX34451_MFR_NV_FAULT_LOG       0xDC
31 #define MAX34451_MFR_TIME_COUNT         0xDD
32 #define MAX34451_MFR_MARGIN_CONFIG      0xDF
33 #define MAX34451_MFR_FW_SERIAL          0xE0
34 #define MAX34451_MFR_IOUT_AVG           0xE2
35 #define MAX34451_MFR_CHANNEL_CONFIG     0xE4
36 #define MAX34451_MFR_TON_SEQ_MAX        0xE6
37 #define MAX34451_MFR_PWM_CONFIG         0xE7
38 #define MAX34451_MFR_SEQ_CONFIG         0xE8
39 #define MAX34451_MFR_STORE_ALL          0xEE
40 #define MAX34451_MFR_RESTORE_ALL        0xEF
41 #define MAX34451_MFR_TEMP_SENSOR_CONFIG 0xF0
42 #define MAX34451_MFR_STORE_SINGLE       0xFC
43 #define MAX34451_MFR_CRC                0xFE
44 
45 #define MAX34451_NUM_MARGINED_PSU       12
46 #define MAX34451_NUM_PWR_DEVICES        16
47 #define MAX34451_NUM_TEMP_DEVICES       5
48 #define MAX34451_NUM_PAGES              21
49 
50 #define DEFAULT_OP_ON                   0x80
51 #define DEFAULT_CAPABILITY              0x20
52 #define DEFAULT_ON_OFF_CONFIG           0x1a
53 #define DEFAULT_VOUT_MODE               0x40
54 #define DEFAULT_TEMPERATURE             2500
55 #define DEFAULT_SCALE                   0x7FFF
56 #define DEFAULT_OV_LIMIT                0x7FFF
57 #define DEFAULT_OC_LIMIT                0x7FFF
58 #define DEFAULT_OT_LIMIT                0x7FFF
59 #define DEFAULT_VMIN                    0x7FFF
60 #define DEFAULT_TON_FAULT_LIMIT         0xFFFF
61 #define DEFAULT_CHANNEL_CONFIG          0x20
62 #define DEFAULT_TEXT                    0x3130313031303130
63 
64 /**
65  * MAX34451State:
66  * @code: The command code received
67  * @page: Each page corresponds to a device monitored by the Max 34451
68  * The page register determines the available commands depending on device
69   ___________________________________________________________________________
70  |   0   |  Power supply monitored by RS0, controlled by PSEN0, and          |
71  |       |  margined with PWM0.                                              |
72  |_______|___________________________________________________________________|
73  |   1   |  Power supply monitored by RS1, controlled by PSEN1, and          |
74  |       |  margined with PWM1.                                              |
75  |_______|___________________________________________________________________|
76  |   2   |  Power supply monitored by RS2, controlled by PSEN2, and          |
77  |       |  margined with PWM2.                                              |
78  |_______|___________________________________________________________________|
79  |   3   |  Power supply monitored by RS3, controlled by PSEN3, and          |
80  |       |  margined with PWM3.                                              |
81  |_______|___________________________________________________________________|
82  |   4   |  Power supply monitored by RS4, controlled by PSEN4, and          |
83  |       |  margined with PWM4.                                              |
84  |_______|___________________________________________________________________|
85  |   5   |  Power supply monitored by RS5, controlled by PSEN5, and          |
86  |       |  margined with PWM5.                                              |
87  |_______|___________________________________________________________________|
88  |   6   |  Power supply monitored by RS6, controlled by PSEN6, and          |
89  |       |  margined with PWM6.                                              |
90  |_______|___________________________________________________________________|
91  |   7   |  Power supply monitored by RS7, controlled by PSEN7, and          |
92  |       |  margined with PWM7.                                              |
93  |_______|___________________________________________________________________|
94  |   8   |  Power supply monitored by RS8, controlled by PSEN8, and          |
95  |       | optionally margined by OUT0 of external DS4424 at I2C address A0h.|
96  |_______|___________________________________________________________________|
97  |   9   |  Power supply monitored by RS9, controlled by PSEN9, and          |
98  |       | optionally margined by OUT1 of external DS4424 at I2C address A0h.|
99  |_______|___________________________________________________________________|
100  |   10  |  Power supply monitored by RS10, controlled by PSEN10, and        |
101  |       | optionally margined by OUT2 of external DS4424 at I2C address A0h.|
102  |_______|___________________________________________________________________|
103  |   11  |  Power supply monitored by RS11, controlled by PSEN11, and        |
104  |       | optionally margined by OUT3 of external DS4424 at I2C address A0h.|
105  |_______|___________________________________________________________________|
106  |   12  |  ADC channel 12 (monitors voltage or current) or GPI.             |
107  |_______|___________________________________________________________________|
108  |   13  |  ADC channel 13 (monitors voltage or current) or GPI.             |
109  |_______|___________________________________________________________________|
110  |   14  |  ADC channel 14 (monitors voltage or current) or GPI.             |
111  |_______|___________________________________________________________________|
112  |   15  |  ADC channel 15 (monitors voltage or current) or GPI.             |
113  |_______|___________________________________________________________________|
114  |   16  |  Internal temperature sensor.                                     |
115  |_______|___________________________________________________________________|
116  |   17  |  External DS75LV temperature sensor with I2C address 90h.         |
117  |_______|___________________________________________________________________|
118  |   18  |  External DS75LV temperature sensor with I2C address 92h.         |
119  |_______|___________________________________________________________________|
120  |   19  |  External DS75LV temperature sensor with I2C address 94h.         |
121  |_______|___________________________________________________________________|
122  |   20  |  External DS75LV temperature sensor with I2C address 96h.         |
123  |_______|___________________________________________________________________|
124  | 21=E2=80=93254|  Reserved.                                                        |
125  |_______|___________________________________________________________________|
126  |   255 |  Applies to all pages.                                            |
127  |_______|___________________________________________________________________|
128  *
129  * @operation: Turn on and off power supplies
130  * @on_off_config: Configure the power supply on and off transition behaviour
131  * @write_protect: protect against changes to the device's memory
132  * @vout_margin_high: the voltage when OPERATION is set to margin high
133  * @vout_margin_low: the voltage when OPERATION is set to margin low
134  * @vout_scale: scale ADC reading to actual device reading if different
135  * @iout_cal_gain: set ratio of the voltage at the ADC input to sensed current
136  */
137 typedef struct MAX34451State {
138     PMBusDevice parent;
139 
140     uint16_t power_good_on[MAX34451_NUM_PWR_DEVICES];
141     uint16_t power_good_off[MAX34451_NUM_PWR_DEVICES];
142     uint16_t ton_delay[MAX34451_NUM_MARGINED_PSU];
143     uint16_t ton_max_fault_limit[MAX34451_NUM_MARGINED_PSU];
144     uint16_t toff_delay[MAX34451_NUM_MARGINED_PSU];
145     uint8_t status_mfr_specific[MAX34451_NUM_PWR_DEVICES];
146     /* Manufacturer specific function */
147     uint64_t mfr_location;
148     uint64_t mfr_date;
149     uint64_t mfr_serial;
150     uint16_t mfr_mode;
151     uint32_t psen_config[MAX34451_NUM_MARGINED_PSU];
152     uint16_t vout_peak[MAX34451_NUM_PWR_DEVICES];
153     uint16_t iout_peak[MAX34451_NUM_PWR_DEVICES];
154     uint16_t temperature_peak[MAX34451_NUM_TEMP_DEVICES];
155     uint16_t vout_min[MAX34451_NUM_PWR_DEVICES];
156     uint16_t nv_log_config;
157     uint32_t fault_response[MAX34451_NUM_PWR_DEVICES];
158     uint16_t fault_retry;
159     uint32_t fault_log;
160     uint32_t time_count;
161     uint16_t margin_config[MAX34451_NUM_MARGINED_PSU];
162     uint16_t fw_serial;
163     uint16_t iout_avg[MAX34451_NUM_PWR_DEVICES];
164     uint16_t channel_config[MAX34451_NUM_PWR_DEVICES];
165     uint16_t ton_seq_max[MAX34451_NUM_MARGINED_PSU];
166     uint32_t pwm_config[MAX34451_NUM_MARGINED_PSU];
167     uint32_t seq_config[MAX34451_NUM_MARGINED_PSU];
168     uint16_t temp_sensor_config[MAX34451_NUM_TEMP_DEVICES];
169     uint16_t store_single;
170     uint16_t crc;
171 } MAX34451State;
172 
173 
174 static void max34451_check_limits(MAX34451State *s)
175 {
176     PMBusDevice *pmdev = PMBUS_DEVICE(s);
177 
178     pmbus_check_limits(pmdev);
179 
180     for (int i = 0; i < MAX34451_NUM_PWR_DEVICES; i++) {
181         if (pmdev->pages[i].read_vout == 0) { /* PSU disabled */
182             continue;
183         }
184 
185         if (pmdev->pages[i].read_vout > s->vout_peak[i]) {
186             s->vout_peak[i] = pmdev->pages[i].read_vout;
187         }
188 
189         if (pmdev->pages[i].read_vout < s->vout_min[i]) {
190             s->vout_min[i] = pmdev->pages[i].read_vout;
191         }
192 
193         if (pmdev->pages[i].read_iout > s->iout_peak[i]) {
194             s->iout_peak[i] = pmdev->pages[i].read_iout;
195         }
196     }
197 
198     for (int i = 0; i < MAX34451_NUM_TEMP_DEVICES; i++) {
199         if (pmdev->pages[i + 16].read_temperature_1 > s->temperature_peak[i]) {
200             s->temperature_peak[i] = pmdev->pages[i + 16].read_temperature_1;
201         }
202     }
203 }
204 
205 static uint8_t max34451_read_byte(PMBusDevice *pmdev)
206 {
207     MAX34451State *s = MAX34451(pmdev);
208     switch (pmdev->code) {
209 
210     case PMBUS_POWER_GOOD_ON:
211         if (pmdev->page < 16) {
212             pmbus_send16(pmdev, s->power_good_on[pmdev->page]);
213         }
214         break;
215 
216     case PMBUS_POWER_GOOD_OFF:
217         if (pmdev->page < 16) {
218             pmbus_send16(pmdev, s->power_good_off[pmdev->page]);
219         }
220         break;
221 
222     case PMBUS_TON_DELAY:
223         if (pmdev->page < 12) {
224             pmbus_send16(pmdev, s->ton_delay[pmdev->page]);
225         }
226         break;
227 
228     case PMBUS_TON_MAX_FAULT_LIMIT:
229         if (pmdev->page < 12) {
230             pmbus_send16(pmdev, s->ton_max_fault_limit[pmdev->page]);
231         }
232         break;
233 
234     case PMBUS_TOFF_DELAY:
235         if (pmdev->page < 12) {
236             pmbus_send16(pmdev, s->toff_delay[pmdev->page]);
237         }
238         break;
239 
240     case PMBUS_STATUS_MFR_SPECIFIC:
241         if (pmdev->page < 16) {
242             pmbus_send8(pmdev, s->status_mfr_specific[pmdev->page]);
243         }
244         break;
245 
246     case PMBUS_MFR_ID:
247         pmbus_send8(pmdev, 0x4d); /* Maxim */
248         break;
249 
250     case PMBUS_MFR_MODEL:
251         pmbus_send8(pmdev, 0x59);
252         break;
253 
254     case PMBUS_MFR_LOCATION:
255         pmbus_send64(pmdev, s->mfr_location);
256         break;
257 
258     case PMBUS_MFR_DATE:
259         pmbus_send64(pmdev, s->mfr_date);
260         break;
261 
262     case PMBUS_MFR_SERIAL:
263         pmbus_send64(pmdev, s->mfr_serial);
264         break;
265 
266     case MAX34451_MFR_MODE:
267         pmbus_send16(pmdev, s->mfr_mode);
268         break;
269 
270     case MAX34451_MFR_PSEN_CONFIG:
271         if (pmdev->page < 12) {
272             pmbus_send32(pmdev, s->psen_config[pmdev->page]);
273         }
274         break;
275 
276     case MAX34451_MFR_VOUT_PEAK:
277         if (pmdev->page < 16) {
278             pmbus_send16(pmdev, s->vout_peak[pmdev->page]);
279         }
280         break;
281 
282     case MAX34451_MFR_IOUT_PEAK:
283         if (pmdev->page < 16) {
284             pmbus_send16(pmdev, s->iout_peak[pmdev->page]);
285         }
286         break;
287 
288     case MAX34451_MFR_TEMPERATURE_PEAK:
289         if (15 < pmdev->page && pmdev->page < 21) {
290             pmbus_send16(pmdev, s->temperature_peak[pmdev->page % 16]);
291         } else {
292             pmbus_send16(pmdev, s->temperature_peak[0]);
293         }
294         break;
295 
296     case MAX34451_MFR_VOUT_MIN:
297         if (pmdev->page < 16) {
298             pmbus_send16(pmdev, s->vout_min[pmdev->page]);
299         }
300         break;
301 
302     case MAX34451_MFR_NV_LOG_CONFIG:
303         pmbus_send16(pmdev, s->nv_log_config);
304         break;
305 
306     case MAX34451_MFR_FAULT_RESPONSE:
307         if (pmdev->page < 16) {
308             pmbus_send32(pmdev, s->fault_response[pmdev->page]);
309         }
310         break;
311 
312     case MAX34451_MFR_FAULT_RETRY:
313         pmbus_send32(pmdev, s->fault_retry);
314         break;
315 
316     case MAX34451_MFR_NV_FAULT_LOG:
317         pmbus_send32(pmdev, s->fault_log);
318         break;
319 
320     case MAX34451_MFR_TIME_COUNT:
321         pmbus_send32(pmdev, s->time_count);
322         break;
323 
324     case MAX34451_MFR_MARGIN_CONFIG:
325         if (pmdev->page < 12) {
326             pmbus_send16(pmdev, s->margin_config[pmdev->page]);
327         }
328         break;
329 
330     case MAX34451_MFR_FW_SERIAL:
331         if (pmdev->page == 255) {
332             pmbus_send16(pmdev, 1); /* Firmware revision */
333         }
334         break;
335 
336     case MAX34451_MFR_IOUT_AVG:
337         if (pmdev->page < 16) {
338             pmbus_send16(pmdev, s->iout_avg[pmdev->page]);
339         }
340         break;
341 
342     case MAX34451_MFR_CHANNEL_CONFIG:
343         if (pmdev->page < 16) {
344             pmbus_send16(pmdev, s->channel_config[pmdev->page]);
345         }
346         break;
347 
348     case MAX34451_MFR_TON_SEQ_MAX:
349         if (pmdev->page < 12) {
350             pmbus_send16(pmdev, s->ton_seq_max[pmdev->page]);
351         }
352         break;
353 
354     case MAX34451_MFR_PWM_CONFIG:
355         if (pmdev->page < 12) {
356             pmbus_send32(pmdev, s->pwm_config[pmdev->page]);
357         }
358         break;
359 
360     case MAX34451_MFR_SEQ_CONFIG:
361         if (pmdev->page < 12) {
362             pmbus_send32(pmdev, s->seq_config[pmdev->page]);
363         }
364         break;
365 
366     case MAX34451_MFR_TEMP_SENSOR_CONFIG:
367         if (15 < pmdev->page && pmdev->page < 21) {
368             pmbus_send32(pmdev, s->temp_sensor_config[pmdev->page % 16]);
369         }
370         break;
371 
372     case MAX34451_MFR_STORE_SINGLE:
373         pmbus_send32(pmdev, s->store_single);
374         break;
375 
376     case MAX34451_MFR_CRC:
377         pmbus_send32(pmdev, s->crc);
378         break;
379 
380     default:
381         qemu_log_mask(LOG_GUEST_ERROR,
382                       "%s: reading from unsupported register: 0x%02x\n",
383                       __func__, pmdev->code);
384         break;
385     }
386     return 0xFF;
387 }
388 
389 static int max34451_write_data(PMBusDevice *pmdev, const uint8_t *buf,
390                                uint8_t len)
391 {
392     MAX34451State *s = MAX34451(pmdev);
393 
394     if (len == 0) {
395         qemu_log_mask(LOG_GUEST_ERROR, "%s: writing empty data\n", __func__);
396         return -1;
397     }
398 
399     pmdev->code = buf[0]; /* PMBus command code */
400 
401     if (len == 1) {
402         return 0;
403     }
404 
405     /* Exclude command code from buffer */
406     buf++;
407     len--;
408     uint8_t index = pmdev->page;
409 
410     switch (pmdev->code) {
411     case MAX34451_MFR_STORE_ALL:
412     case MAX34451_MFR_RESTORE_ALL:
413     case MAX34451_MFR_STORE_SINGLE:
414         /*
415          * TODO: hardware behaviour is to move the contents of volatile
416          * memory to non-volatile memory.
417          */
418         break;
419 
420     case PMBUS_POWER_GOOD_ON: /* R/W word */
421         if (pmdev->page < MAX34451_NUM_PWR_DEVICES) {
422             s->power_good_on[pmdev->page] = pmbus_receive16(pmdev);
423         }
424         break;
425 
426     case PMBUS_POWER_GOOD_OFF: /* R/W word */
427         if (pmdev->page < MAX34451_NUM_PWR_DEVICES) {
428             s->power_good_off[pmdev->page] = pmbus_receive16(pmdev);
429         }
430         break;
431 
432     case PMBUS_TON_DELAY: /* R/W word */
433         if (pmdev->page < 12) {
434             s->ton_delay[pmdev->page] = pmbus_receive16(pmdev);
435         }
436         break;
437 
438     case PMBUS_TON_MAX_FAULT_LIMIT: /* R/W word */
439         if (pmdev->page < 12) {
440             s->ton_max_fault_limit[pmdev->page]
441                 = pmbus_receive16(pmdev);
442         }
443         break;
444 
445     case PMBUS_TOFF_DELAY: /* R/W word */
446         if (pmdev->page < 12) {
447             s->toff_delay[pmdev->page] = pmbus_receive16(pmdev);
448         }
449         break;
450 
451     case PMBUS_MFR_LOCATION: /* R/W 64 */
452         s->mfr_location = pmbus_receive64(pmdev);
453         break;
454 
455     case PMBUS_MFR_DATE: /* R/W 64 */
456         s->mfr_date = pmbus_receive64(pmdev);
457         break;
458 
459     case PMBUS_MFR_SERIAL: /* R/W 64 */
460         s->mfr_serial = pmbus_receive64(pmdev);
461         break;
462 
463     case MAX34451_MFR_MODE: /* R/W word */
464          s->mfr_mode = pmbus_receive16(pmdev);
465         break;
466 
467     case MAX34451_MFR_PSEN_CONFIG: /* R/W 32 */
468         if (pmdev->page < 12) {
469             s->psen_config[pmdev->page] = pmbus_receive32(pmdev);
470         }
471         break;
472 
473     case MAX34451_MFR_VOUT_PEAK: /* R/W word */
474         if (pmdev->page < 16) {
475             s->vout_peak[pmdev->page] = pmbus_receive16(pmdev);
476         }
477         break;
478 
479     case MAX34451_MFR_IOUT_PEAK: /* R/W word */
480         if (pmdev->page < 16) {
481             s->iout_peak[pmdev->page] = pmbus_receive16(pmdev);
482         }
483         break;
484 
485     case MAX34451_MFR_TEMPERATURE_PEAK: /* R/W word */
486         if (15 < pmdev->page && pmdev->page < 21) {
487             s->temperature_peak[pmdev->page % 16]
488                 = pmbus_receive16(pmdev);
489         }
490         break;
491 
492     case MAX34451_MFR_VOUT_MIN: /* R/W word */
493         if (pmdev->page < 16) {
494             s->vout_min[pmdev->page] = pmbus_receive16(pmdev);
495         }
496         break;
497 
498     case MAX34451_MFR_NV_LOG_CONFIG: /* R/W word */
499          s->nv_log_config = pmbus_receive16(pmdev);
500         break;
501 
502     case MAX34451_MFR_FAULT_RESPONSE: /* R/W 32 */
503         if (pmdev->page < 16) {
504             s->fault_response[pmdev->page] = pmbus_receive32(pmdev);
505         }
506         break;
507 
508     case MAX34451_MFR_FAULT_RETRY: /* R/W word */
509         s->fault_retry = pmbus_receive16(pmdev);
510         break;
511 
512     case MAX34451_MFR_TIME_COUNT: /* R/W 32 */
513         s->time_count = pmbus_receive32(pmdev);
514         break;
515 
516     case MAX34451_MFR_MARGIN_CONFIG: /* R/W word */
517         if (pmdev->page < 12) {
518             s->margin_config[pmdev->page] = pmbus_receive16(pmdev);
519         }
520         break;
521 
522     case MAX34451_MFR_CHANNEL_CONFIG: /* R/W word */
523         if (pmdev->page < 16) {
524             s->channel_config[pmdev->page] = pmbus_receive16(pmdev);
525         }
526         break;
527 
528     case MAX34451_MFR_TON_SEQ_MAX: /* R/W word */
529         if (pmdev->page < 12) {
530             s->ton_seq_max[pmdev->page] = pmbus_receive16(pmdev);
531         }
532         break;
533 
534     case MAX34451_MFR_PWM_CONFIG: /* R/W 32 */
535         if (pmdev->page < 12) {
536             s->pwm_config[pmdev->page] = pmbus_receive32(pmdev);
537         }
538         break;
539 
540     case MAX34451_MFR_SEQ_CONFIG:  /* R/W 32 */
541         if (pmdev->page < 12) {
542             s->seq_config[pmdev->page] = pmbus_receive32(pmdev);
543         }
544         break;
545 
546     case MAX34451_MFR_TEMP_SENSOR_CONFIG:  /* R/W word */
547         if (15 < pmdev->page && pmdev->page < 21) {
548             s->temp_sensor_config[pmdev->page % 16]
549                 = pmbus_receive16(pmdev);
550         }
551         break;
552 
553     case MAX34451_MFR_CRC: /* R/W word */
554         s->crc = pmbus_receive16(pmdev);
555         break;
556 
557     case MAX34451_MFR_NV_FAULT_LOG:
558     case MAX34451_MFR_FW_SERIAL:
559     case MAX34451_MFR_IOUT_AVG:
560         /* Read only commands */
561         pmdev->pages[index].status_word |= PMBUS_STATUS_CML;
562         pmdev->pages[index].status_cml |= PB_CML_FAULT_INVALID_DATA;
563         qemu_log_mask(LOG_GUEST_ERROR,
564                       "%s: writing to read-only register 0x%02x\n",
565                       __func__, pmdev->code);
566         break;
567 
568     default:
569         qemu_log_mask(LOG_GUEST_ERROR,
570                       "%s: writing to unsupported register: 0x%02x\n",
571                       __func__, pmdev->code);
572         break;
573     }
574 
575     return 0;
576 }
577 
578 static void max34451_get(Object *obj, Visitor *v, const char *name,
579                                      void *opaque, Error **errp)
580 {
581     visit_type_uint16(v, name, (uint16_t *)opaque, errp);
582 }
583 
584 static void max34451_set(Object *obj, Visitor *v, const char *name,
585                                  void *opaque, Error **errp)
586 {
587     MAX34451State *s = MAX34451(obj);
588     uint16_t *internal = opaque;
589     uint16_t value;
590     if (!visit_type_uint16(v, name, &value, errp)) {
591         return;
592     }
593 
594     *internal = value;
595     max34451_check_limits(s);
596 }
597 
598 /* used to init uint16_t arrays */
599 static inline void *memset_word(void *s, uint16_t c, size_t n)
600 {
601     size_t i;
602     uint16_t *p = s;
603 
604     for (i = 0; i < n; i++) {
605         p[i] = c;
606     }
607 
608     return s;
609 }
610 
611 static void max34451_exit_reset(Object *obj)
612 {
613     PMBusDevice *pmdev = PMBUS_DEVICE(obj);
614     MAX34451State *s = MAX34451(obj);
615     pmdev->capability = DEFAULT_CAPABILITY;
616 
617     for (int i = 0; i < MAX34451_NUM_PAGES; i++) {
618         pmdev->pages[i].operation = DEFAULT_OP_ON;
619         pmdev->pages[i].on_off_config = DEFAULT_ON_OFF_CONFIG;
620         pmdev->pages[i].revision = 0x11;
621         pmdev->pages[i].vout_mode = DEFAULT_VOUT_MODE;
622     }
623 
624     for (int i = 0; i < MAX34451_NUM_PWR_DEVICES; i++) {
625         pmdev->pages[i].vout_scale_monitor = DEFAULT_SCALE;
626         pmdev->pages[i].vout_ov_fault_limit = DEFAULT_OV_LIMIT;
627         pmdev->pages[i].vout_ov_warn_limit = DEFAULT_OV_LIMIT;
628         pmdev->pages[i].iout_oc_warn_limit = DEFAULT_OC_LIMIT;
629         pmdev->pages[i].iout_oc_fault_limit = DEFAULT_OC_LIMIT;
630     }
631 
632     for (int i = 0; i < MAX34451_NUM_MARGINED_PSU; i++) {
633         pmdev->pages[i].ton_max_fault_limit = DEFAULT_TON_FAULT_LIMIT;
634     }
635 
636     for (int i = 16; i < MAX34451_NUM_TEMP_DEVICES + 16; i++) {
637         pmdev->pages[i].read_temperature_1 = DEFAULT_TEMPERATURE;
638         pmdev->pages[i].ot_warn_limit = DEFAULT_OT_LIMIT;
639         pmdev->pages[i].ot_fault_limit = DEFAULT_OT_LIMIT;
640     }
641 
642     memset_word(s->ton_max_fault_limit, DEFAULT_TON_FAULT_LIMIT,
643                 MAX34451_NUM_MARGINED_PSU);
644     memset_word(s->channel_config, DEFAULT_CHANNEL_CONFIG,
645                 MAX34451_NUM_PWR_DEVICES);
646     memset_word(s->vout_min, DEFAULT_VMIN, MAX34451_NUM_PWR_DEVICES);
647 
648     s->mfr_location = DEFAULT_TEXT;
649     s->mfr_date = DEFAULT_TEXT;
650     s->mfr_serial = DEFAULT_TEXT;
651 }
652 
653 static const VMStateDescription vmstate_max34451 = {
654     .name = TYPE_MAX34451,
655     .version_id = 0,
656     .minimum_version_id = 0,
657     .fields = (VMStateField[]){
658         VMSTATE_PMBUS_DEVICE(parent, MAX34451State),
659         VMSTATE_UINT16_ARRAY(power_good_on, MAX34451State,
660                              MAX34451_NUM_PWR_DEVICES),
661         VMSTATE_UINT16_ARRAY(power_good_off, MAX34451State,
662                              MAX34451_NUM_PWR_DEVICES),
663         VMSTATE_UINT16_ARRAY(ton_delay, MAX34451State,
664                              MAX34451_NUM_MARGINED_PSU),
665         VMSTATE_UINT16_ARRAY(ton_max_fault_limit, MAX34451State,
666                              MAX34451_NUM_MARGINED_PSU),
667         VMSTATE_UINT16_ARRAY(toff_delay, MAX34451State,
668                              MAX34451_NUM_MARGINED_PSU),
669         VMSTATE_UINT8_ARRAY(status_mfr_specific, MAX34451State,
670                              MAX34451_NUM_PWR_DEVICES),
671         VMSTATE_UINT64(mfr_location, MAX34451State),
672         VMSTATE_UINT64(mfr_date, MAX34451State),
673         VMSTATE_UINT64(mfr_serial, MAX34451State),
674         VMSTATE_UINT16(mfr_mode, MAX34451State),
675         VMSTATE_UINT32_ARRAY(psen_config, MAX34451State,
676                              MAX34451_NUM_MARGINED_PSU),
677         VMSTATE_UINT16_ARRAY(vout_peak, MAX34451State,
678                              MAX34451_NUM_PWR_DEVICES),
679         VMSTATE_UINT16_ARRAY(iout_peak, MAX34451State,
680                              MAX34451_NUM_PWR_DEVICES),
681         VMSTATE_UINT16_ARRAY(temperature_peak, MAX34451State,
682                              MAX34451_NUM_TEMP_DEVICES),
683         VMSTATE_UINT16_ARRAY(vout_min, MAX34451State, MAX34451_NUM_PWR_DEVICES),
684         VMSTATE_UINT16(nv_log_config, MAX34451State),
685         VMSTATE_UINT32_ARRAY(fault_response, MAX34451State,
686                              MAX34451_NUM_PWR_DEVICES),
687         VMSTATE_UINT16(fault_retry, MAX34451State),
688         VMSTATE_UINT32(fault_log, MAX34451State),
689         VMSTATE_UINT32(time_count, MAX34451State),
690         VMSTATE_UINT16_ARRAY(margin_config, MAX34451State,
691                              MAX34451_NUM_MARGINED_PSU),
692         VMSTATE_UINT16(fw_serial, MAX34451State),
693         VMSTATE_UINT16_ARRAY(iout_avg, MAX34451State, MAX34451_NUM_PWR_DEVICES),
694         VMSTATE_UINT16_ARRAY(channel_config, MAX34451State,
695                              MAX34451_NUM_PWR_DEVICES),
696         VMSTATE_UINT16_ARRAY(ton_seq_max, MAX34451State,
697                              MAX34451_NUM_MARGINED_PSU),
698         VMSTATE_UINT32_ARRAY(pwm_config, MAX34451State,
699                              MAX34451_NUM_MARGINED_PSU),
700         VMSTATE_UINT32_ARRAY(seq_config, MAX34451State,
701                              MAX34451_NUM_MARGINED_PSU),
702         VMSTATE_UINT16_ARRAY(temp_sensor_config, MAX34451State,
703                              MAX34451_NUM_TEMP_DEVICES),
704         VMSTATE_UINT16(store_single, MAX34451State),
705         VMSTATE_UINT16(crc, MAX34451State),
706         VMSTATE_END_OF_LIST()
707     }
708 };
709 
710 static void max34451_init(Object *obj)
711 {
712     PMBusDevice *pmdev = PMBUS_DEVICE(obj);
713     uint64_t psu_flags = PB_HAS_VOUT | PB_HAS_IOUT | PB_HAS_VOUT_MODE |
714                          PB_HAS_IOUT_GAIN;
715 
716     for (int i = 0; i < MAX34451_NUM_PWR_DEVICES; i++) {
717         pmbus_page_config(pmdev, i, psu_flags);
718     }
719 
720     for (int i = 0; i < MAX34451_NUM_MARGINED_PSU; i++) {
721         pmbus_page_config(pmdev, i, psu_flags | PB_HAS_VOUT_MARGIN);
722     }
723 
724     for (int i = 16; i < MAX34451_NUM_TEMP_DEVICES + 16; i++) {
725         pmbus_page_config(pmdev, i, PB_HAS_TEMPERATURE | PB_HAS_VOUT_MODE);
726     }
727 
728     /* get and set the voltage in millivolts, max is 32767 mV */
729     for (int i = 0; i < MAX34451_NUM_PWR_DEVICES; i++) {
730         object_property_add(obj, "vout[*]", "uint16",
731                             max34451_get,
732                             max34451_set, NULL, &pmdev->pages[i].read_vout);
733     }
734 
735     /*
736      * get and set the temperature of the internal temperature sensor in
737      * centidegrees Celsius i.e.: 2500 -> 25.00 C, max is 327.67 C
738      */
739     for (int i = 0; i < MAX34451_NUM_TEMP_DEVICES; i++) {
740         object_property_add(obj, "temperature[*]", "uint16",
741                             max34451_get,
742                             max34451_set,
743                             NULL,
744                             &pmdev->pages[i + 16].read_temperature_1);
745     }
746 
747 }
748 
749 static void max34451_class_init(ObjectClass *klass, void *data)
750 {
751     ResettableClass *rc = RESETTABLE_CLASS(klass);
752     DeviceClass *dc = DEVICE_CLASS(klass);
753     PMBusDeviceClass *k = PMBUS_DEVICE_CLASS(klass);
754     dc->desc = "Maxim MAX34451 16-Channel V/I monitor";
755     dc->vmsd = &vmstate_max34451;
756     k->write_data = max34451_write_data;
757     k->receive_byte = max34451_read_byte;
758     k->device_num_pages = MAX34451_NUM_PAGES;
759     rc->phases.exit = max34451_exit_reset;
760 }
761 
762 static const TypeInfo max34451_info = {
763     .name = TYPE_MAX34451,
764     .parent = TYPE_PMBUS_DEVICE,
765     .instance_size = sizeof(MAX34451State),
766     .instance_init = max34451_init,
767     .class_init = max34451_class_init,
768 };
769 
770 static void max34451_register_types(void)
771 {
772     type_register_static(&max34451_info);
773 }
774 
775 type_init(max34451_register_types)
776