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