Merge tag 'pull-loongarch-20241016' of https://gitlab.com/gaosong/qemu into staging
[qemu/armbru.git] / hw / sensor / max34451.c
blob93b53f3db2fe60212a2aa356b493d4edcc0a28cc
1 /*
2 * Maxim MAX34451 PMBus 16-Channel V/I monitor and 12-Channel Sequencer/Marginer
4 * Copyright 2021 Google LLC
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
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"
18 #define TYPE_MAX34451 "max34451"
19 #define MAX34451(obj) OBJECT_CHECK(MAX34451State, (obj), TYPE_MAX34451)
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
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
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
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 |_______|___________________________________________________________________|
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
137 typedef struct MAX34451State {
138 PMBusDevice parent;
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;
174 static void max34451_check_limits(MAX34451State *s)
176 PMBusDevice *pmdev = PMBUS_DEVICE(s);
178 pmbus_check_limits(pmdev);
180 for (int i = 0; i < MAX34451_NUM_PWR_DEVICES; i++) {
181 if (pmdev->pages[i].read_vout == 0) { /* PSU disabled */
182 continue;
185 if (pmdev->pages[i].read_vout > s->vout_peak[i]) {
186 s->vout_peak[i] = pmdev->pages[i].read_vout;
189 if (pmdev->pages[i].read_vout < s->vout_min[i]) {
190 s->vout_min[i] = pmdev->pages[i].read_vout;
193 if (pmdev->pages[i].read_iout > s->iout_peak[i]) {
194 s->iout_peak[i] = pmdev->pages[i].read_iout;
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;
205 static uint8_t max34451_read_byte(PMBusDevice *pmdev)
207 MAX34451State *s = MAX34451(pmdev);
208 switch (pmdev->code) {
210 case PMBUS_POWER_GOOD_ON:
211 if (pmdev->page < 16) {
212 pmbus_send16(pmdev, s->power_good_on[pmdev->page]);
214 break;
216 case PMBUS_POWER_GOOD_OFF:
217 if (pmdev->page < 16) {
218 pmbus_send16(pmdev, s->power_good_off[pmdev->page]);
220 break;
222 case PMBUS_TON_DELAY:
223 if (pmdev->page < 12) {
224 pmbus_send16(pmdev, s->ton_delay[pmdev->page]);
226 break;
228 case PMBUS_TON_MAX_FAULT_LIMIT:
229 if (pmdev->page < 12) {
230 pmbus_send16(pmdev, s->ton_max_fault_limit[pmdev->page]);
232 break;
234 case PMBUS_TOFF_DELAY:
235 if (pmdev->page < 12) {
236 pmbus_send16(pmdev, s->toff_delay[pmdev->page]);
238 break;
240 case PMBUS_STATUS_MFR_SPECIFIC:
241 if (pmdev->page < 16) {
242 pmbus_send8(pmdev, s->status_mfr_specific[pmdev->page]);
244 break;
246 case PMBUS_MFR_ID:
247 pmbus_send8(pmdev, 0x4d); /* Maxim */
248 break;
250 case PMBUS_MFR_MODEL:
251 pmbus_send8(pmdev, 0x59);
252 break;
254 case PMBUS_MFR_LOCATION:
255 pmbus_send64(pmdev, s->mfr_location);
256 break;
258 case PMBUS_MFR_DATE:
259 pmbus_send64(pmdev, s->mfr_date);
260 break;
262 case PMBUS_MFR_SERIAL:
263 pmbus_send64(pmdev, s->mfr_serial);
264 break;
266 case MAX34451_MFR_MODE:
267 pmbus_send16(pmdev, s->mfr_mode);
268 break;
270 case MAX34451_MFR_PSEN_CONFIG:
271 if (pmdev->page < 12) {
272 pmbus_send32(pmdev, s->psen_config[pmdev->page]);
274 break;
276 case MAX34451_MFR_VOUT_PEAK:
277 if (pmdev->page < 16) {
278 pmbus_send16(pmdev, s->vout_peak[pmdev->page]);
280 break;
282 case MAX34451_MFR_IOUT_PEAK:
283 if (pmdev->page < 16) {
284 pmbus_send16(pmdev, s->iout_peak[pmdev->page]);
286 break;
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]);
294 break;
296 case MAX34451_MFR_VOUT_MIN:
297 if (pmdev->page < 16) {
298 pmbus_send16(pmdev, s->vout_min[pmdev->page]);
300 break;
302 case MAX34451_MFR_NV_LOG_CONFIG:
303 pmbus_send16(pmdev, s->nv_log_config);
304 break;
306 case MAX34451_MFR_FAULT_RESPONSE:
307 if (pmdev->page < 16) {
308 pmbus_send32(pmdev, s->fault_response[pmdev->page]);
310 break;
312 case MAX34451_MFR_FAULT_RETRY:
313 pmbus_send32(pmdev, s->fault_retry);
314 break;
316 case MAX34451_MFR_NV_FAULT_LOG:
317 pmbus_send32(pmdev, s->fault_log);
318 break;
320 case MAX34451_MFR_TIME_COUNT:
321 pmbus_send32(pmdev, s->time_count);
322 break;
324 case MAX34451_MFR_MARGIN_CONFIG:
325 if (pmdev->page < 12) {
326 pmbus_send16(pmdev, s->margin_config[pmdev->page]);
328 break;
330 case MAX34451_MFR_FW_SERIAL:
331 if (pmdev->page == 255) {
332 pmbus_send16(pmdev, 1); /* Firmware revision */
334 break;
336 case MAX34451_MFR_IOUT_AVG:
337 if (pmdev->page < 16) {
338 pmbus_send16(pmdev, s->iout_avg[pmdev->page]);
340 break;
342 case MAX34451_MFR_CHANNEL_CONFIG:
343 if (pmdev->page < 16) {
344 pmbus_send16(pmdev, s->channel_config[pmdev->page]);
346 break;
348 case MAX34451_MFR_TON_SEQ_MAX:
349 if (pmdev->page < 12) {
350 pmbus_send16(pmdev, s->ton_seq_max[pmdev->page]);
352 break;
354 case MAX34451_MFR_PWM_CONFIG:
355 if (pmdev->page < 12) {
356 pmbus_send32(pmdev, s->pwm_config[pmdev->page]);
358 break;
360 case MAX34451_MFR_SEQ_CONFIG:
361 if (pmdev->page < 12) {
362 pmbus_send32(pmdev, s->seq_config[pmdev->page]);
364 break;
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]);
370 break;
372 case MAX34451_MFR_STORE_SINGLE:
373 pmbus_send32(pmdev, s->store_single);
374 break;
376 case MAX34451_MFR_CRC:
377 pmbus_send32(pmdev, s->crc);
378 break;
380 default:
381 qemu_log_mask(LOG_GUEST_ERROR,
382 "%s: reading from unsupported register: 0x%02x\n",
383 __func__, pmdev->code);
384 break;
386 return 0xFF;
389 static int max34451_write_data(PMBusDevice *pmdev, const uint8_t *buf,
390 uint8_t len)
392 MAX34451State *s = MAX34451(pmdev);
394 if (len == 0) {
395 qemu_log_mask(LOG_GUEST_ERROR, "%s: writing empty data\n", __func__);
396 return -1;
399 pmdev->code = buf[0]; /* PMBus command code */
401 if (len == 1) {
402 return 0;
405 /* Exclude command code from buffer */
406 buf++;
407 len--;
408 uint8_t index = pmdev->page;
410 switch (pmdev->code) {
411 case MAX34451_MFR_STORE_ALL:
412 case MAX34451_MFR_RESTORE_ALL:
413 case MAX34451_MFR_STORE_SINGLE:
415 * TODO: hardware behaviour is to move the contents of volatile
416 * memory to non-volatile memory.
418 break;
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);
424 break;
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);
430 break;
432 case PMBUS_TON_DELAY: /* R/W word */
433 if (pmdev->page < 12) {
434 s->ton_delay[pmdev->page] = pmbus_receive16(pmdev);
436 break;
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);
443 break;
445 case PMBUS_TOFF_DELAY: /* R/W word */
446 if (pmdev->page < 12) {
447 s->toff_delay[pmdev->page] = pmbus_receive16(pmdev);
449 break;
451 case PMBUS_MFR_LOCATION: /* R/W 64 */
452 s->mfr_location = pmbus_receive64(pmdev);
453 break;
455 case PMBUS_MFR_DATE: /* R/W 64 */
456 s->mfr_date = pmbus_receive64(pmdev);
457 break;
459 case PMBUS_MFR_SERIAL: /* R/W 64 */
460 s->mfr_serial = pmbus_receive64(pmdev);
461 break;
463 case MAX34451_MFR_MODE: /* R/W word */
464 s->mfr_mode = pmbus_receive16(pmdev);
465 break;
467 case MAX34451_MFR_PSEN_CONFIG: /* R/W 32 */
468 if (pmdev->page < 12) {
469 s->psen_config[pmdev->page] = pmbus_receive32(pmdev);
471 break;
473 case MAX34451_MFR_VOUT_PEAK: /* R/W word */
474 if (pmdev->page < 16) {
475 s->vout_peak[pmdev->page] = pmbus_receive16(pmdev);
477 break;
479 case MAX34451_MFR_IOUT_PEAK: /* R/W word */
480 if (pmdev->page < 16) {
481 s->iout_peak[pmdev->page] = pmbus_receive16(pmdev);
483 break;
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);
490 break;
492 case MAX34451_MFR_VOUT_MIN: /* R/W word */
493 if (pmdev->page < 16) {
494 s->vout_min[pmdev->page] = pmbus_receive16(pmdev);
496 break;
498 case MAX34451_MFR_NV_LOG_CONFIG: /* R/W word */
499 s->nv_log_config = pmbus_receive16(pmdev);
500 break;
502 case MAX34451_MFR_FAULT_RESPONSE: /* R/W 32 */
503 if (pmdev->page < 16) {
504 s->fault_response[pmdev->page] = pmbus_receive32(pmdev);
506 break;
508 case MAX34451_MFR_FAULT_RETRY: /* R/W word */
509 s->fault_retry = pmbus_receive16(pmdev);
510 break;
512 case MAX34451_MFR_TIME_COUNT: /* R/W 32 */
513 s->time_count = pmbus_receive32(pmdev);
514 break;
516 case MAX34451_MFR_MARGIN_CONFIG: /* R/W word */
517 if (pmdev->page < 12) {
518 s->margin_config[pmdev->page] = pmbus_receive16(pmdev);
520 break;
522 case MAX34451_MFR_CHANNEL_CONFIG: /* R/W word */
523 if (pmdev->page < 16) {
524 s->channel_config[pmdev->page] = pmbus_receive16(pmdev);
526 break;
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);
532 break;
534 case MAX34451_MFR_PWM_CONFIG: /* R/W 32 */
535 if (pmdev->page < 12) {
536 s->pwm_config[pmdev->page] = pmbus_receive32(pmdev);
538 break;
540 case MAX34451_MFR_SEQ_CONFIG: /* R/W 32 */
541 if (pmdev->page < 12) {
542 s->seq_config[pmdev->page] = pmbus_receive32(pmdev);
544 break;
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);
551 break;
553 case MAX34451_MFR_CRC: /* R/W word */
554 s->crc = pmbus_receive16(pmdev);
555 break;
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;
568 default:
569 qemu_log_mask(LOG_GUEST_ERROR,
570 "%s: writing to unsupported register: 0x%02x\n",
571 __func__, pmdev->code);
572 break;
575 return 0;
578 static void max34451_get(Object *obj, Visitor *v, const char *name,
579 void *opaque, Error **errp)
581 visit_type_uint16(v, name, (uint16_t *)opaque, errp);
584 static void max34451_set(Object *obj, Visitor *v, const char *name,
585 void *opaque, Error **errp)
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;
594 *internal = value;
595 max34451_check_limits(s);
598 /* used to init uint16_t arrays */
599 static inline void *memset_word(void *s, uint16_t c, size_t n)
601 size_t i;
602 uint16_t *p = s;
604 for (i = 0; i < n; i++) {
605 p[i] = c;
608 return s;
611 static void max34451_exit_reset(Object *obj, ResetType type)
613 PMBusDevice *pmdev = PMBUS_DEVICE(obj);
614 MAX34451State *s = MAX34451(obj);
615 pmdev->capability = DEFAULT_CAPABILITY;
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;
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;
632 for (int i = 0; i < MAX34451_NUM_MARGINED_PSU; i++) {
633 pmdev->pages[i].ton_max_fault_limit = DEFAULT_TON_FAULT_LIMIT;
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;
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);
648 s->mfr_location = DEFAULT_TEXT;
649 s->mfr_date = DEFAULT_TEXT;
650 s->mfr_serial = DEFAULT_TEXT;
653 static const VMStateDescription vmstate_max34451 = {
654 .name = TYPE_MAX34451,
655 .version_id = 0,
656 .minimum_version_id = 0,
657 .fields = (const 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()
710 static void max34451_init(Object *obj)
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;
716 for (int i = 0; i < MAX34451_NUM_PWR_DEVICES; i++) {
717 pmbus_page_config(pmdev, i, psu_flags);
720 for (int i = 0; i < MAX34451_NUM_MARGINED_PSU; i++) {
721 pmbus_page_config(pmdev, i, psu_flags | PB_HAS_VOUT_MARGIN);
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);
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);
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
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);
749 static void max34451_class_init(ObjectClass *klass, void *data)
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;
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,
770 static void max34451_register_types(void)
772 type_register_static(&max34451_info);
775 type_init(max34451_register_types)