2 * PMBus wrapper over SMBus
4 * Copyright 2021 Google LLC
6 * SPDX-License-Identifier: GPL-2.0-or-later
9 #include "qemu/osdep.h"
11 #include "hw/i2c/pmbus_device.h"
12 #include "migration/vmstate.h"
13 #include "qemu/module.h"
16 uint16_t pmbus_data2direct_mode(PMBusCoefficients c
, uint32_t value
)
18 /* R is usually negative to fit large readings into 16 bits */
19 uint16_t y
= (c
.m
* value
+ c
.b
) * pow(10, c
.R
);
23 uint32_t pmbus_direct_mode2data(PMBusCoefficients c
, uint16_t value
)
25 /* X = (Y * 10^-R - b) / m */
26 uint32_t x
= (value
/ pow(10, c
.R
) - c
.b
) / c
.m
;
30 uint16_t pmbus_data2linear_mode(uint16_t value
, int exp
)
34 return value
<< (-exp
);
39 uint16_t pmbus_linear_mode2data(uint16_t value
, int exp
)
43 return value
>> (-exp
);
48 void pmbus_send(PMBusDevice
*pmdev
, const uint8_t *data
, uint16_t len
)
50 if (pmdev
->out_buf_len
+ len
> SMBUS_DATA_MAX_LEN
) {
51 qemu_log_mask(LOG_GUEST_ERROR
,
52 "PMBus device tried to send too much data");
56 for (int i
= len
- 1; i
>= 0; i
--) {
57 pmdev
->out_buf
[i
+ pmdev
->out_buf_len
] = data
[len
- i
- 1];
59 pmdev
->out_buf_len
+= len
;
62 /* Internal only, convert unsigned ints to the little endian bus */
63 static void pmbus_send_uint(PMBusDevice
*pmdev
, uint64_t data
, uint8_t size
)
68 for (int i
= 0; i
< size
; i
++) {
69 bytes
[i
] = data
& 0xFF;
72 pmbus_send(pmdev
, bytes
, size
);
75 void pmbus_send8(PMBusDevice
*pmdev
, uint8_t data
)
77 pmbus_send_uint(pmdev
, data
, 1);
80 void pmbus_send16(PMBusDevice
*pmdev
, uint16_t data
)
82 pmbus_send_uint(pmdev
, data
, 2);
85 void pmbus_send32(PMBusDevice
*pmdev
, uint32_t data
)
87 pmbus_send_uint(pmdev
, data
, 4);
90 void pmbus_send64(PMBusDevice
*pmdev
, uint64_t data
)
92 pmbus_send_uint(pmdev
, data
, 8);
95 void pmbus_send_string(PMBusDevice
*pmdev
, const char *data
)
98 qemu_log_mask(LOG_GUEST_ERROR
,
99 "%s: %s: uninitialised read from 0x%02x\n",
100 __func__
, DEVICE(pmdev
)->canonical_path
, pmdev
->code
);
104 size_t len
= strlen(data
);
106 g_assert(len
+ pmdev
->out_buf_len
< SMBUS_DATA_MAX_LEN
);
107 pmdev
->out_buf
[len
+ pmdev
->out_buf_len
] = len
;
109 for (int i
= len
- 1; i
>= 0; i
--) {
110 pmdev
->out_buf
[i
+ pmdev
->out_buf_len
] = data
[len
- 1 - i
];
112 pmdev
->out_buf_len
+= len
+ 1;
116 static uint64_t pmbus_receive_uint(PMBusDevice
*pmdev
)
120 /* Exclude command code from return value */
124 for (int i
= pmdev
->in_buf_len
- 1; i
>= 0; i
--) {
125 ret
= ret
<< 8 | pmdev
->in_buf
[i
];
130 uint8_t pmbus_receive8(PMBusDevice
*pmdev
)
132 if (pmdev
->in_buf_len
- 1 != 1) {
133 qemu_log_mask(LOG_GUEST_ERROR
,
134 "%s: length mismatch. Expected 1 byte, got %d bytes\n",
135 __func__
, pmdev
->in_buf_len
- 1);
137 return pmbus_receive_uint(pmdev
);
140 uint16_t pmbus_receive16(PMBusDevice
*pmdev
)
142 if (pmdev
->in_buf_len
- 1 != 2) {
143 qemu_log_mask(LOG_GUEST_ERROR
,
144 "%s: length mismatch. Expected 2 bytes, got %d bytes\n",
145 __func__
, pmdev
->in_buf_len
- 1);
147 return pmbus_receive_uint(pmdev
);
150 uint32_t pmbus_receive32(PMBusDevice
*pmdev
)
152 if (pmdev
->in_buf_len
- 1 != 4) {
153 qemu_log_mask(LOG_GUEST_ERROR
,
154 "%s: length mismatch. Expected 4 bytes, got %d bytes\n",
155 __func__
, pmdev
->in_buf_len
- 1);
157 return pmbus_receive_uint(pmdev
);
160 uint64_t pmbus_receive64(PMBusDevice
*pmdev
)
162 if (pmdev
->in_buf_len
- 1 != 8) {
163 qemu_log_mask(LOG_GUEST_ERROR
,
164 "%s: length mismatch. Expected 8 bytes, got %d bytes\n",
165 __func__
, pmdev
->in_buf_len
- 1);
167 return pmbus_receive_uint(pmdev
);
170 static uint8_t pmbus_out_buf_pop(PMBusDevice
*pmdev
)
172 if (pmdev
->out_buf_len
== 0) {
173 qemu_log_mask(LOG_GUEST_ERROR
,
174 "%s: tried to read from empty buffer",
176 return PMBUS_ERR_BYTE
;
178 uint8_t data
= pmdev
->out_buf
[pmdev
->out_buf_len
- 1];
179 pmdev
->out_buf_len
--;
183 static void pmbus_quick_cmd(SMBusDevice
*smd
, uint8_t read
)
185 PMBusDevice
*pmdev
= PMBUS_DEVICE(smd
);
186 PMBusDeviceClass
*pmdc
= PMBUS_DEVICE_GET_CLASS(pmdev
);
188 if (pmdc
->quick_cmd
) {
189 pmdc
->quick_cmd(pmdev
, read
);
193 static uint8_t pmbus_pages_num(PMBusDevice
*pmdev
)
195 const PMBusDeviceClass
*k
= PMBUS_DEVICE_GET_CLASS(pmdev
);
197 /* some PMBus devices don't use the PAGE command, so they get 1 page */
198 return k
->device_num_pages
? : 1;
201 static void pmbus_pages_alloc(PMBusDevice
*pmdev
)
203 pmdev
->num_pages
= pmbus_pages_num(pmdev
);
204 pmdev
->pages
= g_new0(PMBusPage
, pmdev
->num_pages
);
207 void pmbus_check_limits(PMBusDevice
*pmdev
)
209 for (int i
= 0; i
< pmdev
->num_pages
; i
++) {
210 if ((pmdev
->pages
[i
].operation
& PB_OP_ON
) == 0) {
211 continue; /* don't check powered off devices */
214 if (pmdev
->pages
[i
].read_vout
> pmdev
->pages
[i
].vout_ov_fault_limit
) {
215 pmdev
->pages
[i
].status_word
|= PB_STATUS_VOUT
;
216 pmdev
->pages
[i
].status_vout
|= PB_STATUS_VOUT_OV_FAULT
;
219 if (pmdev
->pages
[i
].read_vout
> pmdev
->pages
[i
].vout_ov_warn_limit
) {
220 pmdev
->pages
[i
].status_word
|= PB_STATUS_VOUT
;
221 pmdev
->pages
[i
].status_vout
|= PB_STATUS_VOUT_OV_WARN
;
224 if (pmdev
->pages
[i
].read_vout
< pmdev
->pages
[i
].vout_uv_warn_limit
) {
225 pmdev
->pages
[i
].status_word
|= PB_STATUS_VOUT
;
226 pmdev
->pages
[i
].status_vout
|= PB_STATUS_VOUT_UV_WARN
;
229 if (pmdev
->pages
[i
].read_vout
< pmdev
->pages
[i
].vout_uv_fault_limit
) {
230 pmdev
->pages
[i
].status_word
|= PB_STATUS_VOUT
;
231 pmdev
->pages
[i
].status_vout
|= PB_STATUS_VOUT_UV_FAULT
;
234 if (pmdev
->pages
[i
].read_vin
> pmdev
->pages
[i
].vin_ov_warn_limit
) {
235 pmdev
->pages
[i
].status_word
|= PB_STATUS_INPUT
;
236 pmdev
->pages
[i
].status_input
|= PB_STATUS_INPUT_VIN_OV_WARN
;
239 if (pmdev
->pages
[i
].read_vin
< pmdev
->pages
[i
].vin_uv_warn_limit
) {
240 pmdev
->pages
[i
].status_word
|= PB_STATUS_INPUT
;
241 pmdev
->pages
[i
].status_input
|= PB_STATUS_INPUT_VIN_UV_WARN
;
244 if (pmdev
->pages
[i
].read_iout
> pmdev
->pages
[i
].iout_oc_warn_limit
) {
245 pmdev
->pages
[i
].status_word
|= PB_STATUS_IOUT_POUT
;
246 pmdev
->pages
[i
].status_iout
|= PB_STATUS_IOUT_OC_WARN
;
249 if (pmdev
->pages
[i
].read_iout
> pmdev
->pages
[i
].iout_oc_fault_limit
) {
250 pmdev
->pages
[i
].status_word
|= PB_STATUS_IOUT_POUT
;
251 pmdev
->pages
[i
].status_iout
|= PB_STATUS_IOUT_OC_FAULT
;
254 if (pmdev
->pages
[i
].read_pin
> pmdev
->pages
[i
].pin_op_warn_limit
) {
255 pmdev
->pages
[i
].status_word
|= PB_STATUS_INPUT
;
256 pmdev
->pages
[i
].status_input
|= PB_STATUS_INPUT_PIN_OP_WARN
;
259 if (pmdev
->pages
[i
].read_temperature_1
260 > pmdev
->pages
[i
].ot_fault_limit
) {
261 pmdev
->pages
[i
].status_word
|= PB_STATUS_TEMPERATURE
;
262 pmdev
->pages
[i
].status_temperature
|= PB_STATUS_OT_FAULT
;
265 if (pmdev
->pages
[i
].read_temperature_1
266 > pmdev
->pages
[i
].ot_warn_limit
) {
267 pmdev
->pages
[i
].status_word
|= PB_STATUS_TEMPERATURE
;
268 pmdev
->pages
[i
].status_temperature
|= PB_STATUS_OT_WARN
;
273 void pmbus_idle(PMBusDevice
*pmdev
)
275 pmdev
->code
= PMBUS_IDLE_STATE
;
278 /* assert the status_cml error upon receipt of malformed command */
279 static void pmbus_cml_error(PMBusDevice
*pmdev
)
281 for (int i
= 0; i
< pmdev
->num_pages
; i
++) {
282 pmdev
->pages
[i
].status_word
|= PMBUS_STATUS_CML
;
283 pmdev
->pages
[i
].status_cml
|= PB_CML_FAULT_INVALID_CMD
;
287 static uint8_t pmbus_receive_byte(SMBusDevice
*smd
)
289 PMBusDevice
*pmdev
= PMBUS_DEVICE(smd
);
290 PMBusDeviceClass
*pmdc
= PMBUS_DEVICE_GET_CLASS(pmdev
);
291 uint8_t ret
= PMBUS_ERR_BYTE
;
294 if (pmdev
->out_buf_len
!= 0) {
295 ret
= pmbus_out_buf_pop(pmdev
);
300 * Reading from all pages will return the value from page 0,
301 * means that all subsequent commands are to be applied to all output.
303 if (pmdev
->page
== PB_ALL_PAGES
) {
305 } else if (pmdev
->page
> pmdev
->num_pages
- 1) {
306 qemu_log_mask(LOG_GUEST_ERROR
,
307 "%s: page %d is out of range\n",
308 __func__
, pmdev
->page
);
309 pmbus_cml_error(pmdev
);
310 return PMBUS_ERR_BYTE
;
315 switch (pmdev
->code
) {
317 pmbus_send8(pmdev
, pmdev
->page
);
320 case PMBUS_OPERATION
: /* R/W byte */
321 pmbus_send8(pmdev
, pmdev
->pages
[index
].operation
);
324 case PMBUS_ON_OFF_CONFIG
: /* R/W byte */
325 pmbus_send8(pmdev
, pmdev
->pages
[index
].on_off_config
);
328 case PMBUS_PHASE
: /* R/W byte */
329 pmbus_send8(pmdev
, pmdev
->pages
[index
].phase
);
332 case PMBUS_WRITE_PROTECT
: /* R/W byte */
333 pmbus_send8(pmdev
, pmdev
->pages
[index
].write_protect
);
336 case PMBUS_CAPABILITY
:
337 pmbus_send8(pmdev
, pmdev
->capability
);
338 if (pmdev
->capability
& BIT(7)) {
339 qemu_log_mask(LOG_UNIMP
,
340 "%s: PEC is enabled but not yet supported.\n",
345 case PMBUS_VOUT_MODE
: /* R/W byte */
346 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT_MODE
) {
347 pmbus_send8(pmdev
, pmdev
->pages
[index
].vout_mode
);
353 case PMBUS_VOUT_COMMAND
: /* R/W word */
354 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
355 pmbus_send16(pmdev
, pmdev
->pages
[index
].vout_command
);
361 case PMBUS_VOUT_TRIM
: /* R/W word */
362 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
363 pmbus_send16(pmdev
, pmdev
->pages
[index
].vout_trim
);
369 case PMBUS_VOUT_CAL_OFFSET
: /* R/W word */
370 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
371 pmbus_send16(pmdev
, pmdev
->pages
[index
].vout_cal_offset
);
377 case PMBUS_VOUT_MAX
: /* R/W word */
378 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
379 pmbus_send16(pmdev
, pmdev
->pages
[index
].vout_max
);
385 case PMBUS_VOUT_MARGIN_HIGH
: /* R/W word */
386 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT_MARGIN
) {
387 pmbus_send16(pmdev
, pmdev
->pages
[index
].vout_margin_high
);
393 case PMBUS_VOUT_MARGIN_LOW
: /* R/W word */
394 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT_MARGIN
) {
395 pmbus_send16(pmdev
, pmdev
->pages
[index
].vout_margin_low
);
401 case PMBUS_VOUT_TRANSITION_RATE
: /* R/W word */
402 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
403 pmbus_send16(pmdev
, pmdev
->pages
[index
].vout_transition_rate
);
409 case PMBUS_VOUT_DROOP
: /* R/W word */
410 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
411 pmbus_send16(pmdev
, pmdev
->pages
[index
].vout_droop
);
417 case PMBUS_VOUT_SCALE_LOOP
: /* R/W word */
418 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
419 pmbus_send16(pmdev
, pmdev
->pages
[index
].vout_scale_loop
);
425 case PMBUS_VOUT_SCALE_MONITOR
: /* R/W word */
426 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
427 pmbus_send16(pmdev
, pmdev
->pages
[index
].vout_scale_monitor
);
433 case PMBUS_VOUT_MIN
: /* R/W word */
434 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT_RATING
) {
435 pmbus_send16(pmdev
, pmdev
->pages
[index
].vout_min
);
441 /* TODO: implement coefficients support */
443 case PMBUS_POUT_MAX
: /* R/W word */
444 if (pmdev
->pages
[index
].page_flags
& PB_HAS_POUT
) {
445 pmbus_send16(pmdev
, pmdev
->pages
[index
].pout_max
);
451 case PMBUS_VIN_ON
: /* R/W word */
452 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
453 pmbus_send16(pmdev
, pmdev
->pages
[index
].vin_on
);
459 case PMBUS_VIN_OFF
: /* R/W word */
460 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
461 pmbus_send16(pmdev
, pmdev
->pages
[index
].vin_off
);
467 case PMBUS_IOUT_CAL_GAIN
: /* R/W word */
468 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT_GAIN
) {
469 pmbus_send16(pmdev
, pmdev
->pages
[index
].iout_cal_gain
);
475 case PMBUS_VOUT_OV_FAULT_LIMIT
: /* R/W word */
476 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
477 pmbus_send16(pmdev
, pmdev
->pages
[index
].vout_ov_fault_limit
);
483 case PMBUS_VOUT_OV_FAULT_RESPONSE
: /* R/W byte */
484 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
485 pmbus_send8(pmdev
, pmdev
->pages
[index
].vout_ov_fault_response
);
491 case PMBUS_VOUT_OV_WARN_LIMIT
: /* R/W word */
492 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
493 pmbus_send16(pmdev
, pmdev
->pages
[index
].vout_ov_warn_limit
);
499 case PMBUS_VOUT_UV_WARN_LIMIT
: /* R/W word */
500 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
501 pmbus_send16(pmdev
, pmdev
->pages
[index
].vout_uv_warn_limit
);
507 case PMBUS_VOUT_UV_FAULT_LIMIT
: /* R/W word */
508 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
509 pmbus_send16(pmdev
, pmdev
->pages
[index
].vout_uv_fault_limit
);
515 case PMBUS_VOUT_UV_FAULT_RESPONSE
: /* R/W byte */
516 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
517 pmbus_send8(pmdev
, pmdev
->pages
[index
].vout_uv_fault_response
);
523 case PMBUS_IOUT_OC_FAULT_LIMIT
: /* R/W word */
524 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
525 pmbus_send16(pmdev
, pmdev
->pages
[index
].iout_oc_fault_limit
);
531 case PMBUS_IOUT_OC_FAULT_RESPONSE
: /* R/W byte */
532 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
533 pmbus_send8(pmdev
, pmdev
->pages
[index
].iout_oc_fault_response
);
539 case PMBUS_IOUT_OC_LV_FAULT_LIMIT
: /* R/W word */
540 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
541 pmbus_send16(pmdev
, pmdev
->pages
[index
].iout_oc_lv_fault_limit
);
547 case PMBUS_IOUT_OC_LV_FAULT_RESPONSE
: /* R/W byte */
548 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
549 pmbus_send8(pmdev
, pmdev
->pages
[index
].iout_oc_lv_fault_response
);
555 case PMBUS_IOUT_OC_WARN_LIMIT
: /* R/W word */
556 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
557 pmbus_send16(pmdev
, pmdev
->pages
[index
].iout_oc_warn_limit
);
563 case PMBUS_IOUT_UC_FAULT_LIMIT
: /* R/W word */
564 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
565 pmbus_send16(pmdev
, pmdev
->pages
[index
].iout_uc_fault_limit
);
571 case PMBUS_IOUT_UC_FAULT_RESPONSE
: /* R/W byte */
572 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
573 pmbus_send8(pmdev
, pmdev
->pages
[index
].iout_uc_fault_response
);
579 case PMBUS_OT_FAULT_LIMIT
: /* R/W word */
580 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMPERATURE
) {
581 pmbus_send16(pmdev
, pmdev
->pages
[index
].ot_fault_limit
);
587 case PMBUS_OT_FAULT_RESPONSE
: /* R/W byte */
588 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMPERATURE
) {
589 pmbus_send8(pmdev
, pmdev
->pages
[index
].ot_fault_response
);
595 case PMBUS_OT_WARN_LIMIT
: /* R/W word */
596 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMPERATURE
) {
597 pmbus_send16(pmdev
, pmdev
->pages
[index
].ot_warn_limit
);
603 case PMBUS_UT_WARN_LIMIT
: /* R/W word */
604 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMPERATURE
) {
605 pmbus_send16(pmdev
, pmdev
->pages
[index
].ut_warn_limit
);
611 case PMBUS_UT_FAULT_LIMIT
: /* R/W word */
612 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMPERATURE
) {
613 pmbus_send16(pmdev
, pmdev
->pages
[index
].ut_fault_limit
);
619 case PMBUS_UT_FAULT_RESPONSE
: /* R/W byte */
620 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMPERATURE
) {
621 pmbus_send8(pmdev
, pmdev
->pages
[index
].ut_fault_response
);
627 case PMBUS_VIN_OV_FAULT_LIMIT
: /* R/W word */
628 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
629 pmbus_send16(pmdev
, pmdev
->pages
[index
].vin_ov_fault_limit
);
635 case PMBUS_VIN_OV_FAULT_RESPONSE
: /* R/W byte */
636 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
637 pmbus_send8(pmdev
, pmdev
->pages
[index
].vin_ov_fault_response
);
643 case PMBUS_VIN_OV_WARN_LIMIT
: /* R/W word */
644 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
645 pmbus_send16(pmdev
, pmdev
->pages
[index
].vin_ov_warn_limit
);
651 case PMBUS_VIN_UV_WARN_LIMIT
: /* R/W word */
652 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
653 pmbus_send16(pmdev
, pmdev
->pages
[index
].vin_uv_warn_limit
);
659 case PMBUS_VIN_UV_FAULT_LIMIT
: /* R/W word */
660 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
661 pmbus_send16(pmdev
, pmdev
->pages
[index
].vin_uv_fault_limit
);
667 case PMBUS_VIN_UV_FAULT_RESPONSE
: /* R/W byte */
668 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
669 pmbus_send8(pmdev
, pmdev
->pages
[index
].vin_uv_fault_response
);
675 case PMBUS_IIN_OC_FAULT_LIMIT
: /* R/W word */
676 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IIN
) {
677 pmbus_send16(pmdev
, pmdev
->pages
[index
].iin_oc_fault_limit
);
683 case PMBUS_IIN_OC_FAULT_RESPONSE
: /* R/W byte */
684 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IIN
) {
685 pmbus_send8(pmdev
, pmdev
->pages
[index
].iin_oc_fault_response
);
691 case PMBUS_IIN_OC_WARN_LIMIT
: /* R/W word */
692 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IIN
) {
693 pmbus_send16(pmdev
, pmdev
->pages
[index
].iin_oc_warn_limit
);
699 case PMBUS_POUT_OP_FAULT_LIMIT
: /* R/W word */
700 if (pmdev
->pages
[index
].page_flags
& PB_HAS_POUT
) {
701 pmbus_send16(pmdev
, pmdev
->pages
[index
].pout_op_fault_limit
);
707 case PMBUS_POUT_OP_FAULT_RESPONSE
: /* R/W byte */
708 if (pmdev
->pages
[index
].page_flags
& PB_HAS_POUT
) {
709 pmbus_send8(pmdev
, pmdev
->pages
[index
].pout_op_fault_response
);
715 case PMBUS_POUT_OP_WARN_LIMIT
: /* R/W word */
716 if (pmdev
->pages
[index
].page_flags
& PB_HAS_POUT
) {
717 pmbus_send16(pmdev
, pmdev
->pages
[index
].pout_op_warn_limit
);
723 case PMBUS_PIN_OP_WARN_LIMIT
: /* R/W word */
724 if (pmdev
->pages
[index
].page_flags
& PB_HAS_PIN
) {
725 pmbus_send16(pmdev
, pmdev
->pages
[index
].pin_op_warn_limit
);
731 case PMBUS_STATUS_BYTE
: /* R/W byte */
732 pmbus_send8(pmdev
, pmdev
->pages
[index
].status_word
& 0xFF);
735 case PMBUS_STATUS_WORD
: /* R/W word */
736 pmbus_send16(pmdev
, pmdev
->pages
[index
].status_word
);
739 case PMBUS_STATUS_VOUT
: /* R/W byte */
740 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
741 pmbus_send8(pmdev
, pmdev
->pages
[index
].status_vout
);
747 case PMBUS_STATUS_IOUT
: /* R/W byte */
748 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
749 pmbus_send8(pmdev
, pmdev
->pages
[index
].status_iout
);
755 case PMBUS_STATUS_INPUT
: /* R/W byte */
756 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
||
757 pmdev
->pages
[index
].page_flags
& PB_HAS_IIN
||
758 pmdev
->pages
[index
].page_flags
& PB_HAS_PIN
) {
759 pmbus_send8(pmdev
, pmdev
->pages
[index
].status_input
);
765 case PMBUS_STATUS_TEMPERATURE
: /* R/W byte */
766 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMPERATURE
) {
767 pmbus_send8(pmdev
, pmdev
->pages
[index
].status_temperature
);
773 case PMBUS_STATUS_CML
: /* R/W byte */
774 pmbus_send8(pmdev
, pmdev
->pages
[index
].status_cml
);
777 case PMBUS_STATUS_OTHER
: /* R/W byte */
778 pmbus_send8(pmdev
, pmdev
->pages
[index
].status_other
);
781 case PMBUS_STATUS_MFR_SPECIFIC
: /* R/W byte */
782 pmbus_send8(pmdev
, pmdev
->pages
[index
].status_mfr_specific
);
785 case PMBUS_READ_EIN
: /* Read-Only block 5 bytes */
786 if (pmdev
->pages
[index
].page_flags
& PB_HAS_EIN
) {
787 pmbus_send(pmdev
, pmdev
->pages
[index
].read_ein
, 5);
793 case PMBUS_READ_EOUT
: /* Read-Only block 5 bytes */
794 if (pmdev
->pages
[index
].page_flags
& PB_HAS_EOUT
) {
795 pmbus_send(pmdev
, pmdev
->pages
[index
].read_eout
, 5);
801 case PMBUS_READ_VIN
: /* Read-Only word */
802 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
803 pmbus_send16(pmdev
, pmdev
->pages
[index
].read_vin
);
809 case PMBUS_READ_IIN
: /* Read-Only word */
810 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IIN
) {
811 pmbus_send16(pmdev
, pmdev
->pages
[index
].read_iin
);
817 case PMBUS_READ_VOUT
: /* Read-Only word */
818 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
819 pmbus_send16(pmdev
, pmdev
->pages
[index
].read_vout
);
825 case PMBUS_READ_IOUT
: /* Read-Only word */
826 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
827 pmbus_send16(pmdev
, pmdev
->pages
[index
].read_iout
);
833 case PMBUS_READ_TEMPERATURE_1
: /* Read-Only word */
834 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMPERATURE
) {
835 pmbus_send16(pmdev
, pmdev
->pages
[index
].read_temperature_1
);
841 case PMBUS_READ_TEMPERATURE_2
: /* Read-Only word */
842 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMP2
) {
843 pmbus_send16(pmdev
, pmdev
->pages
[index
].read_temperature_2
);
849 case PMBUS_READ_TEMPERATURE_3
: /* Read-Only word */
850 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMP3
) {
851 pmbus_send16(pmdev
, pmdev
->pages
[index
].read_temperature_3
);
857 case PMBUS_READ_POUT
: /* Read-Only word */
858 if (pmdev
->pages
[index
].page_flags
& PB_HAS_POUT
) {
859 pmbus_send16(pmdev
, pmdev
->pages
[index
].read_pout
);
865 case PMBUS_READ_PIN
: /* Read-Only word */
866 if (pmdev
->pages
[index
].page_flags
& PB_HAS_PIN
) {
867 pmbus_send16(pmdev
, pmdev
->pages
[index
].read_pin
);
873 case PMBUS_REVISION
: /* Read-Only byte */
874 pmbus_send8(pmdev
, pmdev
->pages
[index
].revision
);
877 case PMBUS_MFR_ID
: /* R/W block */
878 if (pmdev
->pages
[index
].page_flags
& PB_HAS_MFR_INFO
) {
879 pmbus_send_string(pmdev
, pmdev
->pages
[index
].mfr_id
);
885 case PMBUS_MFR_MODEL
: /* R/W block */
886 if (pmdev
->pages
[index
].page_flags
& PB_HAS_MFR_INFO
) {
887 pmbus_send_string(pmdev
, pmdev
->pages
[index
].mfr_model
);
893 case PMBUS_MFR_REVISION
: /* R/W block */
894 if (pmdev
->pages
[index
].page_flags
& PB_HAS_MFR_INFO
) {
895 pmbus_send_string(pmdev
, pmdev
->pages
[index
].mfr_revision
);
901 case PMBUS_MFR_LOCATION
: /* R/W block */
902 if (pmdev
->pages
[index
].page_flags
& PB_HAS_MFR_INFO
) {
903 pmbus_send_string(pmdev
, pmdev
->pages
[index
].mfr_location
);
909 case PMBUS_MFR_VIN_MIN
: /* Read-Only word */
910 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN_RATING
) {
911 pmbus_send16(pmdev
, pmdev
->pages
[index
].mfr_vin_min
);
917 case PMBUS_MFR_VIN_MAX
: /* Read-Only word */
918 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN_RATING
) {
919 pmbus_send16(pmdev
, pmdev
->pages
[index
].mfr_vin_max
);
925 case PMBUS_MFR_IIN_MAX
: /* Read-Only word */
926 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IIN_RATING
) {
927 pmbus_send16(pmdev
, pmdev
->pages
[index
].mfr_iin_max
);
933 case PMBUS_MFR_PIN_MAX
: /* Read-Only word */
934 if (pmdev
->pages
[index
].page_flags
& PB_HAS_PIN_RATING
) {
935 pmbus_send16(pmdev
, pmdev
->pages
[index
].mfr_pin_max
);
941 case PMBUS_MFR_VOUT_MIN
: /* Read-Only word */
942 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT_RATING
) {
943 pmbus_send16(pmdev
, pmdev
->pages
[index
].mfr_vout_min
);
949 case PMBUS_MFR_VOUT_MAX
: /* Read-Only word */
950 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT_RATING
) {
951 pmbus_send16(pmdev
, pmdev
->pages
[index
].mfr_vout_max
);
957 case PMBUS_MFR_IOUT_MAX
: /* Read-Only word */
958 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT_RATING
) {
959 pmbus_send16(pmdev
, pmdev
->pages
[index
].mfr_iout_max
);
965 case PMBUS_MFR_POUT_MAX
: /* Read-Only word */
966 if (pmdev
->pages
[index
].page_flags
& PB_HAS_POUT_RATING
) {
967 pmbus_send16(pmdev
, pmdev
->pages
[index
].mfr_pout_max
);
973 case PMBUS_MFR_MAX_TEMP_1
: /* R/W word */
974 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMP_RATING
) {
975 pmbus_send16(pmdev
, pmdev
->pages
[index
].mfr_max_temp_1
);
981 case PMBUS_MFR_MAX_TEMP_2
: /* R/W word */
982 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMP_RATING
) {
983 pmbus_send16(pmdev
, pmdev
->pages
[index
].mfr_max_temp_2
);
989 case PMBUS_MFR_MAX_TEMP_3
: /* R/W word */
990 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMP_RATING
) {
991 pmbus_send16(pmdev
, pmdev
->pages
[index
].mfr_max_temp_3
);
997 case PMBUS_IDLE_STATE
:
998 pmbus_send8(pmdev
, PMBUS_ERR_BYTE
);
1001 case PMBUS_CLEAR_FAULTS
: /* Send Byte */
1002 case PMBUS_PAGE_PLUS_WRITE
: /* Block Write-only */
1003 case PMBUS_STORE_DEFAULT_ALL
: /* Send Byte */
1004 case PMBUS_RESTORE_DEFAULT_ALL
: /* Send Byte */
1005 case PMBUS_STORE_DEFAULT_CODE
: /* Write-only Byte */
1006 case PMBUS_RESTORE_DEFAULT_CODE
: /* Write-only Byte */
1007 case PMBUS_STORE_USER_ALL
: /* Send Byte */
1008 case PMBUS_RESTORE_USER_ALL
: /* Send Byte */
1009 case PMBUS_STORE_USER_CODE
: /* Write-only Byte */
1010 case PMBUS_RESTORE_USER_CODE
: /* Write-only Byte */
1011 case PMBUS_QUERY
: /* Write-Only */
1012 qemu_log_mask(LOG_GUEST_ERROR
,
1013 "%s: reading from write only register 0x%02x\n",
1014 __func__
, pmdev
->code
);
1019 /* Pass through read request if not handled */
1020 if (pmdc
->receive_byte
) {
1021 ret
= pmdc
->receive_byte(pmdev
);
1026 if (pmdev
->out_buf_len
!= 0) {
1027 ret
= pmbus_out_buf_pop(pmdev
);
1035 * PMBus clear faults command applies to all status registers, existing faults
1036 * should separately get re-asserted.
1038 static void pmbus_clear_faults(PMBusDevice
*pmdev
)
1040 for (uint8_t i
= 0; i
< pmdev
->num_pages
; i
++) {
1041 pmdev
->pages
[i
].status_word
= 0;
1042 pmdev
->pages
[i
].status_vout
= 0;
1043 pmdev
->pages
[i
].status_iout
= 0;
1044 pmdev
->pages
[i
].status_input
= 0;
1045 pmdev
->pages
[i
].status_temperature
= 0;
1046 pmdev
->pages
[i
].status_cml
= 0;
1047 pmdev
->pages
[i
].status_other
= 0;
1048 pmdev
->pages
[i
].status_mfr_specific
= 0;
1049 pmdev
->pages
[i
].status_fans_1_2
= 0;
1050 pmdev
->pages
[i
].status_fans_3_4
= 0;
1056 * PMBus operation is used to turn On and Off PSUs
1057 * Therefore, default value for the Operation should be PB_OP_ON or 0x80
1059 static void pmbus_operation(PMBusDevice
*pmdev
)
1061 uint8_t index
= pmdev
->page
;
1062 if ((pmdev
->pages
[index
].operation
& PB_OP_ON
) == 0) {
1063 pmdev
->pages
[index
].read_vout
= 0;
1064 pmdev
->pages
[index
].read_iout
= 0;
1065 pmdev
->pages
[index
].read_pout
= 0;
1069 if (pmdev
->pages
[index
].operation
& (PB_OP_ON
| PB_OP_MARGIN_HIGH
)) {
1070 pmdev
->pages
[index
].read_vout
= pmdev
->pages
[index
].vout_margin_high
;
1073 if (pmdev
->pages
[index
].operation
& (PB_OP_ON
| PB_OP_MARGIN_LOW
)) {
1074 pmdev
->pages
[index
].read_vout
= pmdev
->pages
[index
].vout_margin_low
;
1076 pmbus_check_limits(pmdev
);
1079 static int pmbus_write_data(SMBusDevice
*smd
, uint8_t *buf
, uint8_t len
)
1081 PMBusDevice
*pmdev
= PMBUS_DEVICE(smd
);
1082 PMBusDeviceClass
*pmdc
= PMBUS_DEVICE_GET_CLASS(pmdev
);
1087 qemu_log_mask(LOG_GUEST_ERROR
, "%s: writing empty data\n", __func__
);
1088 return PMBUS_ERR_BYTE
;
1091 if (!pmdev
->pages
) { /* allocate memory for pages on first use */
1092 pmbus_pages_alloc(pmdev
);
1095 pmdev
->in_buf_len
= len
;
1096 pmdev
->in_buf
= buf
;
1098 pmdev
->code
= buf
[0]; /* PMBus command code */
1099 if (len
== 1) { /* Single length writes are command codes only */
1103 if (pmdev
->code
== PMBUS_PAGE
) {
1104 pmdev
->page
= pmbus_receive8(pmdev
);
1108 /* loop through all the pages when 0xFF is received */
1109 if (pmdev
->page
== PB_ALL_PAGES
) {
1110 for (int i
= 0; i
< pmdev
->num_pages
; i
++) {
1112 pmbus_write_data(smd
, buf
, len
);
1114 pmdev
->page
= PB_ALL_PAGES
;
1118 if (pmdev
->page
> pmdev
->num_pages
- 1) {
1119 qemu_log_mask(LOG_GUEST_ERROR
,
1120 "%s: page %u is out of range\n",
1121 __func__
, pmdev
->page
);
1122 pmdev
->page
= 0; /* undefined behaviour - reset to page 0 */
1123 pmbus_cml_error(pmdev
);
1124 return PMBUS_ERR_BYTE
;
1127 index
= pmdev
->page
;
1129 switch (pmdev
->code
) {
1130 case PMBUS_OPERATION
: /* R/W byte */
1131 pmdev
->pages
[index
].operation
= pmbus_receive8(pmdev
);
1132 pmbus_operation(pmdev
);
1135 case PMBUS_ON_OFF_CONFIG
: /* R/W byte */
1136 pmdev
->pages
[index
].on_off_config
= pmbus_receive8(pmdev
);
1139 case PMBUS_CLEAR_FAULTS
: /* Send Byte */
1140 pmbus_clear_faults(pmdev
);
1143 case PMBUS_PHASE
: /* R/W byte */
1144 pmdev
->pages
[index
].phase
= pmbus_receive8(pmdev
);
1147 case PMBUS_PAGE_PLUS_WRITE
: /* Block Write-only */
1148 case PMBUS_WRITE_PROTECT
: /* R/W byte */
1149 pmdev
->pages
[index
].write_protect
= pmbus_receive8(pmdev
);
1152 case PMBUS_VOUT_MODE
: /* R/W byte */
1153 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT_MODE
) {
1154 pmdev
->pages
[index
].vout_mode
= pmbus_receive8(pmdev
);
1160 case PMBUS_VOUT_COMMAND
: /* R/W word */
1161 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1162 pmdev
->pages
[index
].vout_command
= pmbus_receive16(pmdev
);
1168 case PMBUS_VOUT_TRIM
: /* R/W word */
1169 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1170 pmdev
->pages
[index
].vout_trim
= pmbus_receive16(pmdev
);
1176 case PMBUS_VOUT_CAL_OFFSET
: /* R/W word */
1177 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1178 pmdev
->pages
[index
].vout_cal_offset
= pmbus_receive16(pmdev
);
1184 case PMBUS_VOUT_MAX
: /* R/W word */
1185 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1186 pmdev
->pages
[index
].vout_max
= pmbus_receive16(pmdev
);
1192 case PMBUS_VOUT_MARGIN_HIGH
: /* R/W word */
1193 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT_MARGIN
) {
1194 pmdev
->pages
[index
].vout_margin_high
= pmbus_receive16(pmdev
);
1200 case PMBUS_VOUT_MARGIN_LOW
: /* R/W word */
1201 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT_MARGIN
) {
1202 pmdev
->pages
[index
].vout_margin_low
= pmbus_receive16(pmdev
);
1208 case PMBUS_VOUT_TRANSITION_RATE
: /* R/W word */
1209 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1210 pmdev
->pages
[index
].vout_transition_rate
= pmbus_receive16(pmdev
);
1216 case PMBUS_VOUT_DROOP
: /* R/W word */
1217 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1218 pmdev
->pages
[index
].vout_droop
= pmbus_receive16(pmdev
);
1224 case PMBUS_VOUT_SCALE_LOOP
: /* R/W word */
1225 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1226 pmdev
->pages
[index
].vout_scale_loop
= pmbus_receive16(pmdev
);
1232 case PMBUS_VOUT_SCALE_MONITOR
: /* R/W word */
1233 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1234 pmdev
->pages
[index
].vout_scale_monitor
= pmbus_receive16(pmdev
);
1240 case PMBUS_VOUT_MIN
: /* R/W word */
1241 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT_RATING
) {
1242 pmdev
->pages
[index
].vout_min
= pmbus_receive16(pmdev
);
1248 case PMBUS_POUT_MAX
: /* R/W word */
1249 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1250 pmdev
->pages
[index
].pout_max
= pmbus_receive16(pmdev
);
1256 case PMBUS_VIN_ON
: /* R/W word */
1257 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
1258 pmdev
->pages
[index
].vin_on
= pmbus_receive16(pmdev
);
1264 case PMBUS_VIN_OFF
: /* R/W word */
1265 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
1266 pmdev
->pages
[index
].vin_off
= pmbus_receive16(pmdev
);
1272 case PMBUS_IOUT_CAL_GAIN
: /* R/W word */
1273 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT_GAIN
) {
1274 pmdev
->pages
[index
].iout_cal_gain
= pmbus_receive16(pmdev
);
1280 case PMBUS_VOUT_OV_FAULT_LIMIT
: /* R/W word */
1281 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1282 pmdev
->pages
[index
].vout_ov_fault_limit
= pmbus_receive16(pmdev
);
1288 case PMBUS_VOUT_OV_FAULT_RESPONSE
: /* R/W byte */
1289 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1290 pmdev
->pages
[index
].vout_ov_fault_response
= pmbus_receive8(pmdev
);
1296 case PMBUS_VOUT_OV_WARN_LIMIT
: /* R/W word */
1297 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1298 pmdev
->pages
[index
].vout_ov_warn_limit
= pmbus_receive16(pmdev
);
1304 case PMBUS_VOUT_UV_WARN_LIMIT
: /* R/W word */
1305 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1306 pmdev
->pages
[index
].vout_uv_warn_limit
= pmbus_receive16(pmdev
);
1312 case PMBUS_VOUT_UV_FAULT_LIMIT
: /* R/W word */
1313 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1314 pmdev
->pages
[index
].vout_uv_fault_limit
= pmbus_receive16(pmdev
);
1320 case PMBUS_VOUT_UV_FAULT_RESPONSE
: /* R/W byte */
1321 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1322 pmdev
->pages
[index
].vout_uv_fault_response
= pmbus_receive8(pmdev
);
1328 case PMBUS_IOUT_OC_FAULT_LIMIT
: /* R/W word */
1329 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
1330 pmdev
->pages
[index
].iout_oc_fault_limit
= pmbus_receive16(pmdev
);
1336 case PMBUS_IOUT_OC_FAULT_RESPONSE
: /* R/W byte */
1337 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
1338 pmdev
->pages
[index
].iout_oc_fault_response
= pmbus_receive8(pmdev
);
1344 case PMBUS_IOUT_OC_LV_FAULT_LIMIT
: /* R/W word */
1345 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
1346 pmdev
->pages
[index
].iout_oc_lv_fault_limit
= pmbus_receive16(pmdev
);
1352 case PMBUS_IOUT_OC_LV_FAULT_RESPONSE
: /* R/W byte */
1353 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
1354 pmdev
->pages
[index
].iout_oc_lv_fault_response
1355 = pmbus_receive8(pmdev
);
1361 case PMBUS_IOUT_OC_WARN_LIMIT
: /* R/W word */
1362 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
1363 pmdev
->pages
[index
].iout_oc_warn_limit
= pmbus_receive16(pmdev
);
1369 case PMBUS_IOUT_UC_FAULT_LIMIT
: /* R/W word */
1370 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
1371 pmdev
->pages
[index
].iout_uc_fault_limit
= pmbus_receive16(pmdev
);
1377 case PMBUS_IOUT_UC_FAULT_RESPONSE
: /* R/W byte */
1378 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
1379 pmdev
->pages
[index
].iout_uc_fault_response
= pmbus_receive8(pmdev
);
1385 case PMBUS_OT_FAULT_LIMIT
: /* R/W word */
1386 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMPERATURE
) {
1387 pmdev
->pages
[index
].ot_fault_limit
= pmbus_receive16(pmdev
);
1393 case PMBUS_OT_FAULT_RESPONSE
: /* R/W byte */
1394 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMPERATURE
) {
1395 pmdev
->pages
[index
].ot_fault_response
= pmbus_receive8(pmdev
);
1401 case PMBUS_OT_WARN_LIMIT
: /* R/W word */
1402 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMPERATURE
) {
1403 pmdev
->pages
[index
].ot_warn_limit
= pmbus_receive16(pmdev
);
1409 case PMBUS_UT_WARN_LIMIT
: /* R/W word */
1410 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMPERATURE
) {
1411 pmdev
->pages
[index
].ut_warn_limit
= pmbus_receive16(pmdev
);
1417 case PMBUS_UT_FAULT_LIMIT
: /* R/W word */
1418 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMPERATURE
) {
1419 pmdev
->pages
[index
].ut_fault_limit
= pmbus_receive16(pmdev
);
1425 case PMBUS_UT_FAULT_RESPONSE
: /* R/W byte */
1426 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMPERATURE
) {
1427 pmdev
->pages
[index
].ut_fault_response
= pmbus_receive8(pmdev
);
1433 case PMBUS_VIN_OV_FAULT_LIMIT
: /* R/W word */
1434 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
1435 pmdev
->pages
[index
].vin_ov_fault_limit
= pmbus_receive16(pmdev
);
1441 case PMBUS_VIN_OV_FAULT_RESPONSE
: /* R/W byte */
1442 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
1443 pmdev
->pages
[index
].vin_ov_fault_response
= pmbus_receive8(pmdev
);
1449 case PMBUS_VIN_OV_WARN_LIMIT
: /* R/W word */
1450 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
1451 pmdev
->pages
[index
].vin_ov_warn_limit
= pmbus_receive16(pmdev
);
1457 case PMBUS_VIN_UV_WARN_LIMIT
: /* R/W word */
1458 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
1459 pmdev
->pages
[index
].vin_uv_warn_limit
= pmbus_receive16(pmdev
);
1465 case PMBUS_VIN_UV_FAULT_LIMIT
: /* R/W word */
1466 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
1467 pmdev
->pages
[index
].vin_uv_fault_limit
= pmbus_receive16(pmdev
);
1473 case PMBUS_VIN_UV_FAULT_RESPONSE
: /* R/W byte */
1474 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
1475 pmdev
->pages
[index
].vin_uv_fault_response
= pmbus_receive8(pmdev
);
1481 case PMBUS_IIN_OC_FAULT_LIMIT
: /* R/W word */
1482 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IIN
) {
1483 pmdev
->pages
[index
].iin_oc_fault_limit
= pmbus_receive16(pmdev
);
1489 case PMBUS_IIN_OC_FAULT_RESPONSE
: /* R/W byte */
1490 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IIN
) {
1491 pmdev
->pages
[index
].iin_oc_fault_response
= pmbus_receive8(pmdev
);
1497 case PMBUS_IIN_OC_WARN_LIMIT
: /* R/W word */
1498 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IIN
) {
1499 pmdev
->pages
[index
].iin_oc_warn_limit
= pmbus_receive16(pmdev
);
1505 case PMBUS_POUT_OP_FAULT_LIMIT
: /* R/W word */
1506 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1507 pmdev
->pages
[index
].pout_op_fault_limit
= pmbus_receive16(pmdev
);
1513 case PMBUS_POUT_OP_FAULT_RESPONSE
: /* R/W byte */
1514 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1515 pmdev
->pages
[index
].pout_op_fault_response
= pmbus_receive8(pmdev
);
1521 case PMBUS_POUT_OP_WARN_LIMIT
: /* R/W word */
1522 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1523 pmdev
->pages
[index
].pout_op_warn_limit
= pmbus_receive16(pmdev
);
1529 case PMBUS_PIN_OP_WARN_LIMIT
: /* R/W word */
1530 if (pmdev
->pages
[index
].page_flags
& PB_HAS_PIN
) {
1531 pmdev
->pages
[index
].pin_op_warn_limit
= pmbus_receive16(pmdev
);
1537 case PMBUS_STATUS_BYTE
: /* R/W byte */
1538 pmdev
->pages
[index
].status_word
= pmbus_receive8(pmdev
);
1541 case PMBUS_STATUS_WORD
: /* R/W word */
1542 pmdev
->pages
[index
].status_word
= pmbus_receive16(pmdev
);
1545 case PMBUS_STATUS_VOUT
: /* R/W byte */
1546 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1547 pmdev
->pages
[index
].status_vout
= pmbus_receive8(pmdev
);
1553 case PMBUS_STATUS_IOUT
: /* R/W byte */
1554 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
1555 pmdev
->pages
[index
].status_iout
= pmbus_receive8(pmdev
);
1561 case PMBUS_STATUS_INPUT
: /* R/W byte */
1562 pmdev
->pages
[index
].status_input
= pmbus_receive8(pmdev
);
1565 case PMBUS_STATUS_TEMPERATURE
: /* R/W byte */
1566 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMPERATURE
) {
1567 pmdev
->pages
[index
].status_temperature
= pmbus_receive8(pmdev
);
1573 case PMBUS_STATUS_CML
: /* R/W byte */
1574 pmdev
->pages
[index
].status_cml
= pmbus_receive8(pmdev
);
1577 case PMBUS_STATUS_OTHER
: /* R/W byte */
1578 pmdev
->pages
[index
].status_other
= pmbus_receive8(pmdev
);
1581 case PMBUS_STATUS_MFR_SPECIFIC
: /* R/W byte */
1582 pmdev
->pages
[index
].status_mfr_specific
= pmbus_receive8(pmdev
);
1585 case PMBUS_PAGE_PLUS_READ
: /* Block Read-only */
1586 case PMBUS_CAPABILITY
: /* Read-Only byte */
1587 case PMBUS_COEFFICIENTS
: /* Read-only block 5 bytes */
1588 case PMBUS_READ_EIN
: /* Read-Only block 5 bytes */
1589 case PMBUS_READ_EOUT
: /* Read-Only block 5 bytes */
1590 case PMBUS_READ_VIN
: /* Read-Only word */
1591 case PMBUS_READ_IIN
: /* Read-Only word */
1592 case PMBUS_READ_VCAP
: /* Read-Only word */
1593 case PMBUS_READ_VOUT
: /* Read-Only word */
1594 case PMBUS_READ_IOUT
: /* Read-Only word */
1595 case PMBUS_READ_TEMPERATURE_1
: /* Read-Only word */
1596 case PMBUS_READ_TEMPERATURE_2
: /* Read-Only word */
1597 case PMBUS_READ_TEMPERATURE_3
: /* Read-Only word */
1598 case PMBUS_READ_FAN_SPEED_1
: /* Read-Only word */
1599 case PMBUS_READ_FAN_SPEED_2
: /* Read-Only word */
1600 case PMBUS_READ_FAN_SPEED_3
: /* Read-Only word */
1601 case PMBUS_READ_FAN_SPEED_4
: /* Read-Only word */
1602 case PMBUS_READ_DUTY_CYCLE
: /* Read-Only word */
1603 case PMBUS_READ_FREQUENCY
: /* Read-Only word */
1604 case PMBUS_READ_POUT
: /* Read-Only word */
1605 case PMBUS_READ_PIN
: /* Read-Only word */
1606 case PMBUS_REVISION
: /* Read-Only byte */
1607 case PMBUS_APP_PROFILE_SUPPORT
: /* Read-Only block-read */
1608 case PMBUS_MFR_VIN_MIN
: /* Read-Only word */
1609 case PMBUS_MFR_VIN_MAX
: /* Read-Only word */
1610 case PMBUS_MFR_IIN_MAX
: /* Read-Only word */
1611 case PMBUS_MFR_PIN_MAX
: /* Read-Only word */
1612 case PMBUS_MFR_VOUT_MIN
: /* Read-Only word */
1613 case PMBUS_MFR_VOUT_MAX
: /* Read-Only word */
1614 case PMBUS_MFR_IOUT_MAX
: /* Read-Only word */
1615 case PMBUS_MFR_POUT_MAX
: /* Read-Only word */
1616 case PMBUS_MFR_TAMBIENT_MAX
: /* Read-Only word */
1617 case PMBUS_MFR_TAMBIENT_MIN
: /* Read-Only word */
1618 case PMBUS_MFR_EFFICIENCY_LL
: /* Read-Only block 14 bytes */
1619 case PMBUS_MFR_EFFICIENCY_HL
: /* Read-Only block 14 bytes */
1620 case PMBUS_MFR_PIN_ACCURACY
: /* Read-Only byte */
1621 case PMBUS_IC_DEVICE_ID
: /* Read-Only block-read */
1622 case PMBUS_IC_DEVICE_REV
: /* Read-Only block-read */
1623 qemu_log_mask(LOG_GUEST_ERROR
,
1624 "%s: writing to read-only register 0x%02x\n",
1625 __func__
, pmdev
->code
);
1629 /* Unimplemented registers get passed to the device */
1631 if (pmdc
->write_data
) {
1632 ret
= pmdc
->write_data(pmdev
, buf
, len
);
1636 pmbus_check_limits(pmdev
);
1637 pmdev
->in_buf_len
= 0;
1641 int pmbus_page_config(PMBusDevice
*pmdev
, uint8_t index
, uint64_t flags
)
1643 if (!pmdev
->pages
) { /* allocate memory for pages on first use */
1644 pmbus_pages_alloc(pmdev
);
1647 /* The 0xFF page is special for commands applying to all pages */
1648 if (index
== PB_ALL_PAGES
) {
1649 for (int i
= 0; i
< pmdev
->num_pages
; i
++) {
1650 pmdev
->pages
[i
].page_flags
= flags
;
1655 if (index
> pmdev
->num_pages
- 1) {
1656 qemu_log_mask(LOG_GUEST_ERROR
,
1657 "%s: index %u is out of range\n",
1662 pmdev
->pages
[index
].page_flags
= flags
;
1667 /* TODO: include pmbus page info in vmstate */
1668 const VMStateDescription vmstate_pmbus_device
= {
1669 .name
= TYPE_PMBUS_DEVICE
,
1671 .minimum_version_id
= 0,
1672 .fields
= (VMStateField
[]) {
1673 VMSTATE_SMBUS_DEVICE(smb
, PMBusDevice
),
1674 VMSTATE_UINT8(num_pages
, PMBusDevice
),
1675 VMSTATE_UINT8(code
, PMBusDevice
),
1676 VMSTATE_UINT8(page
, PMBusDevice
),
1677 VMSTATE_UINT8(capability
, PMBusDevice
),
1678 VMSTATE_END_OF_LIST()
1682 static void pmbus_device_finalize(Object
*obj
)
1684 PMBusDevice
*pmdev
= PMBUS_DEVICE(obj
);
1685 g_free(pmdev
->pages
);
1688 static void pmbus_device_class_init(ObjectClass
*klass
, void *data
)
1690 SMBusDeviceClass
*k
= SMBUS_DEVICE_CLASS(klass
);
1692 k
->quick_cmd
= pmbus_quick_cmd
;
1693 k
->write_data
= pmbus_write_data
;
1694 k
->receive_byte
= pmbus_receive_byte
;
1697 static const TypeInfo pmbus_device_type_info
= {
1698 .name
= TYPE_PMBUS_DEVICE
,
1699 .parent
= TYPE_SMBUS_DEVICE
,
1700 .instance_size
= sizeof(PMBusDevice
),
1701 .instance_finalize
= pmbus_device_finalize
,
1703 .class_size
= sizeof(PMBusDeviceClass
),
1704 .class_init
= pmbus_device_class_init
,
1707 static void pmbus_device_register_types(void)
1709 type_register_static(&pmbus_device_type_info
);
1712 type_init(pmbus_device_register_types
)