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
);
105 g_assert(len
+ pmdev
->out_buf_len
< SMBUS_DATA_MAX_LEN
);
106 pmdev
->out_buf
[len
+ pmdev
->out_buf_len
] = len
;
108 for (int i
= len
- 1; i
>= 0; i
--) {
109 pmdev
->out_buf
[i
+ pmdev
->out_buf_len
] = data
[len
- 1 - i
];
111 pmdev
->out_buf_len
+= len
+ 1;
114 uint8_t pmbus_receive_block(PMBusDevice
*pmdev
, uint8_t *dest
, size_t len
)
116 /* dest may contain data from previous writes */
117 memset(dest
, 0, len
);
119 /* Exclude command code from return value */
123 /* The byte after the command code denotes the length */
124 uint8_t sent_len
= pmdev
->in_buf
[0];
126 if (sent_len
!= pmdev
->in_buf_len
- 1) {
127 qemu_log_mask(LOG_GUEST_ERROR
,
128 "%s: length mismatch. Expected %d bytes, got %d bytes\n",
129 __func__
, sent_len
, pmdev
->in_buf_len
- 1);
132 /* exclude length byte */
136 if (pmdev
->in_buf_len
< len
) {
137 len
= pmdev
->in_buf_len
;
139 memcpy(dest
, pmdev
->in_buf
, len
);
144 static uint64_t pmbus_receive_uint(PMBusDevice
*pmdev
)
148 /* Exclude command code from return value */
152 for (int i
= pmdev
->in_buf_len
- 1; i
>= 0; i
--) {
153 ret
= ret
<< 8 | pmdev
->in_buf
[i
];
158 uint8_t pmbus_receive8(PMBusDevice
*pmdev
)
160 if (pmdev
->in_buf_len
- 1 != 1) {
161 qemu_log_mask(LOG_GUEST_ERROR
,
162 "%s: length mismatch. Expected 1 byte, got %d bytes\n",
163 __func__
, pmdev
->in_buf_len
- 1);
165 return pmbus_receive_uint(pmdev
);
168 uint16_t pmbus_receive16(PMBusDevice
*pmdev
)
170 if (pmdev
->in_buf_len
- 1 != 2) {
171 qemu_log_mask(LOG_GUEST_ERROR
,
172 "%s: length mismatch. Expected 2 bytes, got %d bytes\n",
173 __func__
, pmdev
->in_buf_len
- 1);
175 return pmbus_receive_uint(pmdev
);
178 uint32_t pmbus_receive32(PMBusDevice
*pmdev
)
180 if (pmdev
->in_buf_len
- 1 != 4) {
181 qemu_log_mask(LOG_GUEST_ERROR
,
182 "%s: length mismatch. Expected 4 bytes, got %d bytes\n",
183 __func__
, pmdev
->in_buf_len
- 1);
185 return pmbus_receive_uint(pmdev
);
188 uint64_t pmbus_receive64(PMBusDevice
*pmdev
)
190 if (pmdev
->in_buf_len
- 1 != 8) {
191 qemu_log_mask(LOG_GUEST_ERROR
,
192 "%s: length mismatch. Expected 8 bytes, got %d bytes\n",
193 __func__
, pmdev
->in_buf_len
- 1);
195 return pmbus_receive_uint(pmdev
);
198 static uint8_t pmbus_out_buf_pop(PMBusDevice
*pmdev
)
200 if (pmdev
->out_buf_len
== 0) {
201 qemu_log_mask(LOG_GUEST_ERROR
,
202 "%s: tried to read from empty buffer",
204 return PMBUS_ERR_BYTE
;
206 uint8_t data
= pmdev
->out_buf
[pmdev
->out_buf_len
- 1];
207 pmdev
->out_buf_len
--;
211 static void pmbus_quick_cmd(SMBusDevice
*smd
, uint8_t read
)
213 PMBusDevice
*pmdev
= PMBUS_DEVICE(smd
);
214 PMBusDeviceClass
*pmdc
= PMBUS_DEVICE_GET_CLASS(pmdev
);
216 if (pmdc
->quick_cmd
) {
217 pmdc
->quick_cmd(pmdev
, read
);
221 static uint8_t pmbus_pages_num(PMBusDevice
*pmdev
)
223 const PMBusDeviceClass
*k
= PMBUS_DEVICE_GET_CLASS(pmdev
);
225 /* some PMBus devices don't use the PAGE command, so they get 1 page */
226 return k
->device_num_pages
? : 1;
229 static void pmbus_pages_alloc(PMBusDevice
*pmdev
)
231 pmdev
->num_pages
= pmbus_pages_num(pmdev
);
232 pmdev
->pages
= g_new0(PMBusPage
, pmdev
->num_pages
);
235 void pmbus_check_limits(PMBusDevice
*pmdev
)
237 for (int i
= 0; i
< pmdev
->num_pages
; i
++) {
238 if ((pmdev
->pages
[i
].operation
& PB_OP_ON
) == 0) {
239 continue; /* don't check powered off devices */
242 if (pmdev
->pages
[i
].read_vout
> pmdev
->pages
[i
].vout_ov_fault_limit
) {
243 pmdev
->pages
[i
].status_word
|= PB_STATUS_VOUT
;
244 pmdev
->pages
[i
].status_vout
|= PB_STATUS_VOUT_OV_FAULT
;
247 if (pmdev
->pages
[i
].read_vout
> pmdev
->pages
[i
].vout_ov_warn_limit
) {
248 pmdev
->pages
[i
].status_word
|= PB_STATUS_VOUT
;
249 pmdev
->pages
[i
].status_vout
|= PB_STATUS_VOUT_OV_WARN
;
252 if (pmdev
->pages
[i
].read_vout
< pmdev
->pages
[i
].vout_uv_warn_limit
) {
253 pmdev
->pages
[i
].status_word
|= PB_STATUS_VOUT
;
254 pmdev
->pages
[i
].status_vout
|= PB_STATUS_VOUT_UV_WARN
;
257 if (pmdev
->pages
[i
].read_vout
< pmdev
->pages
[i
].vout_uv_fault_limit
) {
258 pmdev
->pages
[i
].status_word
|= PB_STATUS_VOUT
;
259 pmdev
->pages
[i
].status_vout
|= PB_STATUS_VOUT_UV_FAULT
;
262 if (pmdev
->pages
[i
].read_vin
> pmdev
->pages
[i
].vin_ov_warn_limit
) {
263 pmdev
->pages
[i
].status_word
|= PB_STATUS_INPUT
;
264 pmdev
->pages
[i
].status_input
|= PB_STATUS_INPUT_VIN_OV_WARN
;
267 if (pmdev
->pages
[i
].read_vin
< pmdev
->pages
[i
].vin_uv_warn_limit
) {
268 pmdev
->pages
[i
].status_word
|= PB_STATUS_INPUT
;
269 pmdev
->pages
[i
].status_input
|= PB_STATUS_INPUT_VIN_UV_WARN
;
272 if (pmdev
->pages
[i
].read_iout
> pmdev
->pages
[i
].iout_oc_warn_limit
) {
273 pmdev
->pages
[i
].status_word
|= PB_STATUS_IOUT_POUT
;
274 pmdev
->pages
[i
].status_iout
|= PB_STATUS_IOUT_OC_WARN
;
277 if (pmdev
->pages
[i
].read_iout
> pmdev
->pages
[i
].iout_oc_fault_limit
) {
278 pmdev
->pages
[i
].status_word
|= PB_STATUS_IOUT_POUT
;
279 pmdev
->pages
[i
].status_iout
|= PB_STATUS_IOUT_OC_FAULT
;
282 if (pmdev
->pages
[i
].read_pin
> pmdev
->pages
[i
].pin_op_warn_limit
) {
283 pmdev
->pages
[i
].status_word
|= PB_STATUS_INPUT
;
284 pmdev
->pages
[i
].status_input
|= PB_STATUS_INPUT_PIN_OP_WARN
;
287 if (pmdev
->pages
[i
].read_temperature_1
288 > pmdev
->pages
[i
].ot_fault_limit
) {
289 pmdev
->pages
[i
].status_word
|= PB_STATUS_TEMPERATURE
;
290 pmdev
->pages
[i
].status_temperature
|= PB_STATUS_OT_FAULT
;
293 if (pmdev
->pages
[i
].read_temperature_1
294 > pmdev
->pages
[i
].ot_warn_limit
) {
295 pmdev
->pages
[i
].status_word
|= PB_STATUS_TEMPERATURE
;
296 pmdev
->pages
[i
].status_temperature
|= PB_STATUS_OT_WARN
;
301 void pmbus_idle(PMBusDevice
*pmdev
)
303 pmdev
->code
= PMBUS_IDLE_STATE
;
306 /* assert the status_cml error upon receipt of malformed command */
307 static void pmbus_cml_error(PMBusDevice
*pmdev
)
309 for (int i
= 0; i
< pmdev
->num_pages
; i
++) {
310 pmdev
->pages
[i
].status_word
|= PMBUS_STATUS_CML
;
311 pmdev
->pages
[i
].status_cml
|= PB_CML_FAULT_INVALID_CMD
;
315 static uint8_t pmbus_receive_byte(SMBusDevice
*smd
)
317 PMBusDevice
*pmdev
= PMBUS_DEVICE(smd
);
318 PMBusDeviceClass
*pmdc
= PMBUS_DEVICE_GET_CLASS(pmdev
);
319 uint8_t ret
= PMBUS_ERR_BYTE
;
322 if (pmdev
->out_buf_len
!= 0) {
323 ret
= pmbus_out_buf_pop(pmdev
);
328 * Reading from all pages will return the value from page 0,
329 * means that all subsequent commands are to be applied to all output.
331 if (pmdev
->page
== PB_ALL_PAGES
) {
333 } else if (pmdev
->page
> pmdev
->num_pages
- 1) {
334 qemu_log_mask(LOG_GUEST_ERROR
,
335 "%s: page %d is out of range\n",
336 __func__
, pmdev
->page
);
337 pmbus_cml_error(pmdev
);
338 return PMBUS_ERR_BYTE
;
343 switch (pmdev
->code
) {
345 pmbus_send8(pmdev
, pmdev
->page
);
348 case PMBUS_OPERATION
: /* R/W byte */
349 pmbus_send8(pmdev
, pmdev
->pages
[index
].operation
);
352 case PMBUS_ON_OFF_CONFIG
: /* R/W byte */
353 pmbus_send8(pmdev
, pmdev
->pages
[index
].on_off_config
);
356 case PMBUS_PHASE
: /* R/W byte */
357 pmbus_send8(pmdev
, pmdev
->pages
[index
].phase
);
360 case PMBUS_WRITE_PROTECT
: /* R/W byte */
361 pmbus_send8(pmdev
, pmdev
->pages
[index
].write_protect
);
364 case PMBUS_CAPABILITY
:
365 pmbus_send8(pmdev
, pmdev
->capability
);
366 if (pmdev
->capability
& BIT(7)) {
367 qemu_log_mask(LOG_UNIMP
,
368 "%s: PEC is enabled but not yet supported.\n",
373 case PMBUS_VOUT_MODE
: /* R/W byte */
374 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT_MODE
) {
375 pmbus_send8(pmdev
, pmdev
->pages
[index
].vout_mode
);
381 case PMBUS_VOUT_COMMAND
: /* R/W word */
382 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
383 pmbus_send16(pmdev
, pmdev
->pages
[index
].vout_command
);
389 case PMBUS_VOUT_TRIM
: /* R/W word */
390 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
391 pmbus_send16(pmdev
, pmdev
->pages
[index
].vout_trim
);
397 case PMBUS_VOUT_CAL_OFFSET
: /* R/W word */
398 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
399 pmbus_send16(pmdev
, pmdev
->pages
[index
].vout_cal_offset
);
405 case PMBUS_VOUT_MAX
: /* R/W word */
406 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
407 pmbus_send16(pmdev
, pmdev
->pages
[index
].vout_max
);
413 case PMBUS_VOUT_MARGIN_HIGH
: /* R/W word */
414 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT_MARGIN
) {
415 pmbus_send16(pmdev
, pmdev
->pages
[index
].vout_margin_high
);
421 case PMBUS_VOUT_MARGIN_LOW
: /* R/W word */
422 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT_MARGIN
) {
423 pmbus_send16(pmdev
, pmdev
->pages
[index
].vout_margin_low
);
429 case PMBUS_VOUT_TRANSITION_RATE
: /* R/W word */
430 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
431 pmbus_send16(pmdev
, pmdev
->pages
[index
].vout_transition_rate
);
437 case PMBUS_VOUT_DROOP
: /* R/W word */
438 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
439 pmbus_send16(pmdev
, pmdev
->pages
[index
].vout_droop
);
445 case PMBUS_VOUT_SCALE_LOOP
: /* R/W word */
446 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
447 pmbus_send16(pmdev
, pmdev
->pages
[index
].vout_scale_loop
);
453 case PMBUS_VOUT_SCALE_MONITOR
: /* R/W word */
454 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
455 pmbus_send16(pmdev
, pmdev
->pages
[index
].vout_scale_monitor
);
461 case PMBUS_VOUT_MIN
: /* R/W word */
462 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT_RATING
) {
463 pmbus_send16(pmdev
, pmdev
->pages
[index
].vout_min
);
469 /* TODO: implement coefficients support */
471 case PMBUS_POUT_MAX
: /* R/W word */
472 if (pmdev
->pages
[index
].page_flags
& PB_HAS_POUT
) {
473 pmbus_send16(pmdev
, pmdev
->pages
[index
].pout_max
);
479 case PMBUS_VIN_ON
: /* R/W word */
480 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
481 pmbus_send16(pmdev
, pmdev
->pages
[index
].vin_on
);
487 case PMBUS_VIN_OFF
: /* R/W word */
488 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
489 pmbus_send16(pmdev
, pmdev
->pages
[index
].vin_off
);
495 case PMBUS_IOUT_CAL_GAIN
: /* R/W word */
496 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT_GAIN
) {
497 pmbus_send16(pmdev
, pmdev
->pages
[index
].iout_cal_gain
);
503 case PMBUS_FAN_CONFIG_1_2
: /* R/W byte */
504 if (pmdev
->pages
[index
].page_flags
& PB_HAS_FAN
) {
505 pmbus_send8(pmdev
, pmdev
->pages
[index
].fan_config_1_2
);
511 case PMBUS_FAN_COMMAND_1
: /* R/W word */
512 if (pmdev
->pages
[index
].page_flags
& PB_HAS_FAN
) {
513 pmbus_send16(pmdev
, pmdev
->pages
[index
].fan_command_1
);
519 case PMBUS_FAN_COMMAND_2
: /* R/W word */
520 if (pmdev
->pages
[index
].page_flags
& PB_HAS_FAN
) {
521 pmbus_send16(pmdev
, pmdev
->pages
[index
].fan_command_2
);
527 case PMBUS_FAN_CONFIG_3_4
: /* R/W byte */
528 if (pmdev
->pages
[index
].page_flags
& PB_HAS_FAN
) {
529 pmbus_send8(pmdev
, pmdev
->pages
[index
].fan_config_3_4
);
535 case PMBUS_FAN_COMMAND_3
: /* R/W word */
536 if (pmdev
->pages
[index
].page_flags
& PB_HAS_FAN
) {
537 pmbus_send16(pmdev
, pmdev
->pages
[index
].fan_command_3
);
543 case PMBUS_FAN_COMMAND_4
: /* R/W word */
544 if (pmdev
->pages
[index
].page_flags
& PB_HAS_FAN
) {
545 pmbus_send16(pmdev
, pmdev
->pages
[index
].fan_command_4
);
551 case PMBUS_VOUT_OV_FAULT_LIMIT
: /* R/W word */
552 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
553 pmbus_send16(pmdev
, pmdev
->pages
[index
].vout_ov_fault_limit
);
559 case PMBUS_VOUT_OV_FAULT_RESPONSE
: /* R/W byte */
560 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
561 pmbus_send8(pmdev
, pmdev
->pages
[index
].vout_ov_fault_response
);
567 case PMBUS_VOUT_OV_WARN_LIMIT
: /* R/W word */
568 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
569 pmbus_send16(pmdev
, pmdev
->pages
[index
].vout_ov_warn_limit
);
575 case PMBUS_VOUT_UV_WARN_LIMIT
: /* R/W word */
576 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
577 pmbus_send16(pmdev
, pmdev
->pages
[index
].vout_uv_warn_limit
);
583 case PMBUS_VOUT_UV_FAULT_LIMIT
: /* R/W word */
584 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
585 pmbus_send16(pmdev
, pmdev
->pages
[index
].vout_uv_fault_limit
);
591 case PMBUS_VOUT_UV_FAULT_RESPONSE
: /* R/W byte */
592 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
593 pmbus_send8(pmdev
, pmdev
->pages
[index
].vout_uv_fault_response
);
599 case PMBUS_IOUT_OC_FAULT_LIMIT
: /* R/W word */
600 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
601 pmbus_send16(pmdev
, pmdev
->pages
[index
].iout_oc_fault_limit
);
607 case PMBUS_IOUT_OC_FAULT_RESPONSE
: /* R/W byte */
608 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
609 pmbus_send8(pmdev
, pmdev
->pages
[index
].iout_oc_fault_response
);
615 case PMBUS_IOUT_OC_LV_FAULT_LIMIT
: /* R/W word */
616 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
617 pmbus_send16(pmdev
, pmdev
->pages
[index
].iout_oc_lv_fault_limit
);
623 case PMBUS_IOUT_OC_LV_FAULT_RESPONSE
: /* R/W byte */
624 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
625 pmbus_send8(pmdev
, pmdev
->pages
[index
].iout_oc_lv_fault_response
);
631 case PMBUS_IOUT_OC_WARN_LIMIT
: /* R/W word */
632 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
633 pmbus_send16(pmdev
, pmdev
->pages
[index
].iout_oc_warn_limit
);
639 case PMBUS_IOUT_UC_FAULT_LIMIT
: /* R/W word */
640 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
641 pmbus_send16(pmdev
, pmdev
->pages
[index
].iout_uc_fault_limit
);
647 case PMBUS_IOUT_UC_FAULT_RESPONSE
: /* R/W byte */
648 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
649 pmbus_send8(pmdev
, pmdev
->pages
[index
].iout_uc_fault_response
);
655 case PMBUS_OT_FAULT_LIMIT
: /* R/W word */
656 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMPERATURE
) {
657 pmbus_send16(pmdev
, pmdev
->pages
[index
].ot_fault_limit
);
663 case PMBUS_OT_FAULT_RESPONSE
: /* R/W byte */
664 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMPERATURE
) {
665 pmbus_send8(pmdev
, pmdev
->pages
[index
].ot_fault_response
);
671 case PMBUS_OT_WARN_LIMIT
: /* R/W word */
672 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMPERATURE
) {
673 pmbus_send16(pmdev
, pmdev
->pages
[index
].ot_warn_limit
);
679 case PMBUS_UT_WARN_LIMIT
: /* R/W word */
680 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMPERATURE
) {
681 pmbus_send16(pmdev
, pmdev
->pages
[index
].ut_warn_limit
);
687 case PMBUS_UT_FAULT_LIMIT
: /* R/W word */
688 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMPERATURE
) {
689 pmbus_send16(pmdev
, pmdev
->pages
[index
].ut_fault_limit
);
695 case PMBUS_UT_FAULT_RESPONSE
: /* R/W byte */
696 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMPERATURE
) {
697 pmbus_send8(pmdev
, pmdev
->pages
[index
].ut_fault_response
);
703 case PMBUS_VIN_OV_FAULT_LIMIT
: /* R/W word */
704 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
705 pmbus_send16(pmdev
, pmdev
->pages
[index
].vin_ov_fault_limit
);
711 case PMBUS_VIN_OV_FAULT_RESPONSE
: /* R/W byte */
712 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
713 pmbus_send8(pmdev
, pmdev
->pages
[index
].vin_ov_fault_response
);
719 case PMBUS_VIN_OV_WARN_LIMIT
: /* R/W word */
720 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
721 pmbus_send16(pmdev
, pmdev
->pages
[index
].vin_ov_warn_limit
);
727 case PMBUS_VIN_UV_WARN_LIMIT
: /* R/W word */
728 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
729 pmbus_send16(pmdev
, pmdev
->pages
[index
].vin_uv_warn_limit
);
735 case PMBUS_VIN_UV_FAULT_LIMIT
: /* R/W word */
736 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
737 pmbus_send16(pmdev
, pmdev
->pages
[index
].vin_uv_fault_limit
);
743 case PMBUS_VIN_UV_FAULT_RESPONSE
: /* R/W byte */
744 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
745 pmbus_send8(pmdev
, pmdev
->pages
[index
].vin_uv_fault_response
);
751 case PMBUS_IIN_OC_FAULT_LIMIT
: /* R/W word */
752 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IIN
) {
753 pmbus_send16(pmdev
, pmdev
->pages
[index
].iin_oc_fault_limit
);
759 case PMBUS_IIN_OC_FAULT_RESPONSE
: /* R/W byte */
760 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IIN
) {
761 pmbus_send8(pmdev
, pmdev
->pages
[index
].iin_oc_fault_response
);
767 case PMBUS_IIN_OC_WARN_LIMIT
: /* R/W word */
768 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IIN
) {
769 pmbus_send16(pmdev
, pmdev
->pages
[index
].iin_oc_warn_limit
);
775 case PMBUS_POUT_OP_FAULT_LIMIT
: /* R/W word */
776 if (pmdev
->pages
[index
].page_flags
& PB_HAS_POUT
) {
777 pmbus_send16(pmdev
, pmdev
->pages
[index
].pout_op_fault_limit
);
783 case PMBUS_POUT_OP_FAULT_RESPONSE
: /* R/W byte */
784 if (pmdev
->pages
[index
].page_flags
& PB_HAS_POUT
) {
785 pmbus_send8(pmdev
, pmdev
->pages
[index
].pout_op_fault_response
);
791 case PMBUS_POUT_OP_WARN_LIMIT
: /* R/W word */
792 if (pmdev
->pages
[index
].page_flags
& PB_HAS_POUT
) {
793 pmbus_send16(pmdev
, pmdev
->pages
[index
].pout_op_warn_limit
);
799 case PMBUS_PIN_OP_WARN_LIMIT
: /* R/W word */
800 if (pmdev
->pages
[index
].page_flags
& PB_HAS_PIN
) {
801 pmbus_send16(pmdev
, pmdev
->pages
[index
].pin_op_warn_limit
);
807 case PMBUS_STATUS_BYTE
: /* R/W byte */
808 pmbus_send8(pmdev
, pmdev
->pages
[index
].status_word
& 0xFF);
811 case PMBUS_STATUS_WORD
: /* R/W word */
812 pmbus_send16(pmdev
, pmdev
->pages
[index
].status_word
);
815 case PMBUS_STATUS_VOUT
: /* R/W byte */
816 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
817 pmbus_send8(pmdev
, pmdev
->pages
[index
].status_vout
);
823 case PMBUS_STATUS_IOUT
: /* R/W byte */
824 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
825 pmbus_send8(pmdev
, pmdev
->pages
[index
].status_iout
);
831 case PMBUS_STATUS_INPUT
: /* R/W byte */
832 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
||
833 pmdev
->pages
[index
].page_flags
& PB_HAS_IIN
||
834 pmdev
->pages
[index
].page_flags
& PB_HAS_PIN
) {
835 pmbus_send8(pmdev
, pmdev
->pages
[index
].status_input
);
841 case PMBUS_STATUS_TEMPERATURE
: /* R/W byte */
842 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMPERATURE
) {
843 pmbus_send8(pmdev
, pmdev
->pages
[index
].status_temperature
);
849 case PMBUS_STATUS_CML
: /* R/W byte */
850 pmbus_send8(pmdev
, pmdev
->pages
[index
].status_cml
);
853 case PMBUS_STATUS_OTHER
: /* R/W byte */
854 pmbus_send8(pmdev
, pmdev
->pages
[index
].status_other
);
857 case PMBUS_STATUS_MFR_SPECIFIC
: /* R/W byte */
858 pmbus_send8(pmdev
, pmdev
->pages
[index
].status_mfr_specific
);
861 case PMBUS_STATUS_FANS_1_2
: /* R/W byte */
862 if (pmdev
->pages
[index
].page_flags
& PB_HAS_FAN
) {
863 pmbus_send8(pmdev
, pmdev
->pages
[index
].status_fans_1_2
);
869 case PMBUS_STATUS_FANS_3_4
: /* R/W byte */
870 if (pmdev
->pages
[index
].page_flags
& PB_HAS_FAN
) {
871 pmbus_send8(pmdev
, pmdev
->pages
[index
].status_fans_3_4
);
877 case PMBUS_READ_EIN
: /* Read-Only block 5 bytes */
878 if (pmdev
->pages
[index
].page_flags
& PB_HAS_EIN
) {
879 pmbus_send(pmdev
, pmdev
->pages
[index
].read_ein
, 5);
885 case PMBUS_READ_EOUT
: /* Read-Only block 5 bytes */
886 if (pmdev
->pages
[index
].page_flags
& PB_HAS_EOUT
) {
887 pmbus_send(pmdev
, pmdev
->pages
[index
].read_eout
, 5);
893 case PMBUS_READ_VIN
: /* Read-Only word */
894 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
895 pmbus_send16(pmdev
, pmdev
->pages
[index
].read_vin
);
901 case PMBUS_READ_IIN
: /* Read-Only word */
902 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IIN
) {
903 pmbus_send16(pmdev
, pmdev
->pages
[index
].read_iin
);
909 case PMBUS_READ_VCAP
: /* Read-Only word */
910 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VCAP
) {
911 pmbus_send16(pmdev
, pmdev
->pages
[index
].read_vcap
);
917 case PMBUS_READ_VOUT
: /* Read-Only word */
918 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
919 pmbus_send16(pmdev
, pmdev
->pages
[index
].read_vout
);
925 case PMBUS_READ_IOUT
: /* Read-Only word */
926 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
927 pmbus_send16(pmdev
, pmdev
->pages
[index
].read_iout
);
933 case PMBUS_READ_TEMPERATURE_1
: /* Read-Only word */
934 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMPERATURE
) {
935 pmbus_send16(pmdev
, pmdev
->pages
[index
].read_temperature_1
);
941 case PMBUS_READ_TEMPERATURE_2
: /* Read-Only word */
942 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMP2
) {
943 pmbus_send16(pmdev
, pmdev
->pages
[index
].read_temperature_2
);
949 case PMBUS_READ_TEMPERATURE_3
: /* Read-Only word */
950 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMP3
) {
951 pmbus_send16(pmdev
, pmdev
->pages
[index
].read_temperature_3
);
957 case PMBUS_READ_FAN_SPEED_1
: /* Read-Only word */
958 if (pmdev
->pages
[index
].page_flags
& PB_HAS_FAN
) {
959 pmbus_send16(pmdev
, pmdev
->pages
[index
].read_fan_speed_1
);
965 case PMBUS_READ_FAN_SPEED_2
: /* Read-Only word */
966 if (pmdev
->pages
[index
].page_flags
& PB_HAS_FAN
) {
967 pmbus_send16(pmdev
, pmdev
->pages
[index
].read_fan_speed_2
);
973 case PMBUS_READ_FAN_SPEED_3
: /* Read-Only word */
974 if (pmdev
->pages
[index
].page_flags
& PB_HAS_FAN
) {
975 pmbus_send16(pmdev
, pmdev
->pages
[index
].read_fan_speed_3
);
981 case PMBUS_READ_FAN_SPEED_4
: /* Read-Only word */
982 if (pmdev
->pages
[index
].page_flags
& PB_HAS_FAN
) {
983 pmbus_send16(pmdev
, pmdev
->pages
[index
].read_fan_speed_4
);
989 case PMBUS_READ_DUTY_CYCLE
: /* Read-Only word */
990 if (pmdev
->pages
[index
].page_flags
& PB_HAS_FAN
) {
991 pmbus_send16(pmdev
, pmdev
->pages
[index
].read_duty_cycle
);
997 case PMBUS_READ_FREQUENCY
: /* Read-Only word */
998 if (pmdev
->pages
[index
].page_flags
& PB_HAS_FAN
) {
999 pmbus_send16(pmdev
, pmdev
->pages
[index
].read_frequency
);
1005 case PMBUS_READ_POUT
: /* Read-Only word */
1006 if (pmdev
->pages
[index
].page_flags
& PB_HAS_POUT
) {
1007 pmbus_send16(pmdev
, pmdev
->pages
[index
].read_pout
);
1013 case PMBUS_READ_PIN
: /* Read-Only word */
1014 if (pmdev
->pages
[index
].page_flags
& PB_HAS_PIN
) {
1015 pmbus_send16(pmdev
, pmdev
->pages
[index
].read_pin
);
1021 case PMBUS_REVISION
: /* Read-Only byte */
1022 pmbus_send8(pmdev
, pmdev
->pages
[index
].revision
);
1025 case PMBUS_MFR_ID
: /* R/W block */
1026 if (pmdev
->pages
[index
].page_flags
& PB_HAS_MFR_INFO
) {
1027 pmbus_send_string(pmdev
, pmdev
->pages
[index
].mfr_id
);
1033 case PMBUS_MFR_MODEL
: /* R/W block */
1034 if (pmdev
->pages
[index
].page_flags
& PB_HAS_MFR_INFO
) {
1035 pmbus_send_string(pmdev
, pmdev
->pages
[index
].mfr_model
);
1041 case PMBUS_MFR_REVISION
: /* R/W block */
1042 if (pmdev
->pages
[index
].page_flags
& PB_HAS_MFR_INFO
) {
1043 pmbus_send_string(pmdev
, pmdev
->pages
[index
].mfr_revision
);
1049 case PMBUS_MFR_LOCATION
: /* R/W block */
1050 if (pmdev
->pages
[index
].page_flags
& PB_HAS_MFR_INFO
) {
1051 pmbus_send_string(pmdev
, pmdev
->pages
[index
].mfr_location
);
1057 case PMBUS_MFR_VIN_MIN
: /* Read-Only word */
1058 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN_RATING
) {
1059 pmbus_send16(pmdev
, pmdev
->pages
[index
].mfr_vin_min
);
1065 case PMBUS_MFR_VIN_MAX
: /* Read-Only word */
1066 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN_RATING
) {
1067 pmbus_send16(pmdev
, pmdev
->pages
[index
].mfr_vin_max
);
1073 case PMBUS_MFR_IIN_MAX
: /* Read-Only word */
1074 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IIN_RATING
) {
1075 pmbus_send16(pmdev
, pmdev
->pages
[index
].mfr_iin_max
);
1081 case PMBUS_MFR_PIN_MAX
: /* Read-Only word */
1082 if (pmdev
->pages
[index
].page_flags
& PB_HAS_PIN_RATING
) {
1083 pmbus_send16(pmdev
, pmdev
->pages
[index
].mfr_pin_max
);
1089 case PMBUS_MFR_VOUT_MIN
: /* Read-Only word */
1090 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT_RATING
) {
1091 pmbus_send16(pmdev
, pmdev
->pages
[index
].mfr_vout_min
);
1097 case PMBUS_MFR_VOUT_MAX
: /* Read-Only word */
1098 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT_RATING
) {
1099 pmbus_send16(pmdev
, pmdev
->pages
[index
].mfr_vout_max
);
1105 case PMBUS_MFR_IOUT_MAX
: /* Read-Only word */
1106 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT_RATING
) {
1107 pmbus_send16(pmdev
, pmdev
->pages
[index
].mfr_iout_max
);
1113 case PMBUS_MFR_POUT_MAX
: /* Read-Only word */
1114 if (pmdev
->pages
[index
].page_flags
& PB_HAS_POUT_RATING
) {
1115 pmbus_send16(pmdev
, pmdev
->pages
[index
].mfr_pout_max
);
1121 case PMBUS_MFR_MAX_TEMP_1
: /* R/W word */
1122 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMP_RATING
) {
1123 pmbus_send16(pmdev
, pmdev
->pages
[index
].mfr_max_temp_1
);
1129 case PMBUS_MFR_MAX_TEMP_2
: /* R/W word */
1130 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMP_RATING
) {
1131 pmbus_send16(pmdev
, pmdev
->pages
[index
].mfr_max_temp_2
);
1137 case PMBUS_MFR_MAX_TEMP_3
: /* R/W word */
1138 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMP_RATING
) {
1139 pmbus_send16(pmdev
, pmdev
->pages
[index
].mfr_max_temp_3
);
1145 case PMBUS_IDLE_STATE
:
1146 pmbus_send8(pmdev
, PMBUS_ERR_BYTE
);
1149 case PMBUS_CLEAR_FAULTS
: /* Send Byte */
1150 case PMBUS_PAGE_PLUS_WRITE
: /* Block Write-only */
1151 case PMBUS_STORE_DEFAULT_ALL
: /* Send Byte */
1152 case PMBUS_RESTORE_DEFAULT_ALL
: /* Send Byte */
1153 case PMBUS_STORE_DEFAULT_CODE
: /* Write-only Byte */
1154 case PMBUS_RESTORE_DEFAULT_CODE
: /* Write-only Byte */
1155 case PMBUS_STORE_USER_ALL
: /* Send Byte */
1156 case PMBUS_RESTORE_USER_ALL
: /* Send Byte */
1157 case PMBUS_STORE_USER_CODE
: /* Write-only Byte */
1158 case PMBUS_RESTORE_USER_CODE
: /* Write-only Byte */
1159 case PMBUS_QUERY
: /* Write-Only */
1160 qemu_log_mask(LOG_GUEST_ERROR
,
1161 "%s: reading from write only register 0x%02x\n",
1162 __func__
, pmdev
->code
);
1167 /* Pass through read request if not handled */
1168 if (pmdc
->receive_byte
) {
1169 ret
= pmdc
->receive_byte(pmdev
);
1174 if (pmdev
->out_buf_len
!= 0) {
1175 ret
= pmbus_out_buf_pop(pmdev
);
1183 * PMBus clear faults command applies to all status registers, existing faults
1184 * should separately get re-asserted.
1186 static void pmbus_clear_faults(PMBusDevice
*pmdev
)
1188 for (uint8_t i
= 0; i
< pmdev
->num_pages
; i
++) {
1189 pmdev
->pages
[i
].status_word
= 0;
1190 pmdev
->pages
[i
].status_vout
= 0;
1191 pmdev
->pages
[i
].status_iout
= 0;
1192 pmdev
->pages
[i
].status_input
= 0;
1193 pmdev
->pages
[i
].status_temperature
= 0;
1194 pmdev
->pages
[i
].status_cml
= 0;
1195 pmdev
->pages
[i
].status_other
= 0;
1196 pmdev
->pages
[i
].status_mfr_specific
= 0;
1197 pmdev
->pages
[i
].status_fans_1_2
= 0;
1198 pmdev
->pages
[i
].status_fans_3_4
= 0;
1204 * PMBus operation is used to turn On and Off PSUs
1205 * Therefore, default value for the Operation should be PB_OP_ON or 0x80
1207 static void pmbus_operation(PMBusDevice
*pmdev
)
1209 uint8_t index
= pmdev
->page
;
1210 if ((pmdev
->pages
[index
].operation
& PB_OP_ON
) == 0) {
1211 pmdev
->pages
[index
].read_vout
= 0;
1212 pmdev
->pages
[index
].read_iout
= 0;
1213 pmdev
->pages
[index
].read_pout
= 0;
1217 if (pmdev
->pages
[index
].operation
& (PB_OP_ON
| PB_OP_MARGIN_HIGH
)) {
1218 pmdev
->pages
[index
].read_vout
= pmdev
->pages
[index
].vout_margin_high
;
1221 if (pmdev
->pages
[index
].operation
& (PB_OP_ON
| PB_OP_MARGIN_LOW
)) {
1222 pmdev
->pages
[index
].read_vout
= pmdev
->pages
[index
].vout_margin_low
;
1224 pmbus_check_limits(pmdev
);
1227 static int pmbus_write_data(SMBusDevice
*smd
, uint8_t *buf
, uint8_t len
)
1229 PMBusDevice
*pmdev
= PMBUS_DEVICE(smd
);
1230 PMBusDeviceClass
*pmdc
= PMBUS_DEVICE_GET_CLASS(pmdev
);
1235 qemu_log_mask(LOG_GUEST_ERROR
, "%s: writing empty data\n", __func__
);
1236 return PMBUS_ERR_BYTE
;
1239 if (!pmdev
->pages
) { /* allocate memory for pages on first use */
1240 pmbus_pages_alloc(pmdev
);
1243 pmdev
->in_buf_len
= len
;
1244 pmdev
->in_buf
= buf
;
1246 pmdev
->code
= buf
[0]; /* PMBus command code */
1248 if (pmdev
->code
== PMBUS_CLEAR_FAULTS
) {
1249 pmbus_clear_faults(pmdev
);
1252 if (len
== 1) { /* Single length writes are command codes only */
1256 if (pmdev
->code
== PMBUS_PAGE
) {
1257 pmdev
->page
= pmbus_receive8(pmdev
);
1259 if (pmdev
->page
> pmdev
->num_pages
- 1 && pmdev
->page
!= PB_ALL_PAGES
) {
1260 qemu_log_mask(LOG_GUEST_ERROR
,
1261 "%s: page %u is out of range\n",
1262 __func__
, pmdev
->page
);
1263 pmdev
->page
= 0; /* undefined behaviour - reset to page 0 */
1264 pmbus_cml_error(pmdev
);
1265 return PMBUS_ERR_BYTE
;
1270 /* loop through all the pages when 0xFF is received */
1271 if (pmdev
->page
== PB_ALL_PAGES
) {
1272 for (int i
= 0; i
< pmdev
->num_pages
; i
++) {
1274 pmbus_write_data(smd
, buf
, len
);
1276 pmdev
->page
= PB_ALL_PAGES
;
1280 index
= pmdev
->page
;
1282 switch (pmdev
->code
) {
1283 case PMBUS_OPERATION
: /* R/W byte */
1284 pmdev
->pages
[index
].operation
= pmbus_receive8(pmdev
);
1285 pmbus_operation(pmdev
);
1288 case PMBUS_ON_OFF_CONFIG
: /* R/W byte */
1289 pmdev
->pages
[index
].on_off_config
= pmbus_receive8(pmdev
);
1292 case PMBUS_CLEAR_FAULTS
: /* Send Byte */
1293 pmbus_clear_faults(pmdev
);
1296 case PMBUS_PHASE
: /* R/W byte */
1297 pmdev
->pages
[index
].phase
= pmbus_receive8(pmdev
);
1300 case PMBUS_PAGE_PLUS_WRITE
: /* Block Write-only */
1301 case PMBUS_WRITE_PROTECT
: /* R/W byte */
1302 pmdev
->pages
[index
].write_protect
= pmbus_receive8(pmdev
);
1305 case PMBUS_VOUT_MODE
: /* R/W byte */
1306 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT_MODE
) {
1307 pmdev
->pages
[index
].vout_mode
= pmbus_receive8(pmdev
);
1313 case PMBUS_VOUT_COMMAND
: /* R/W word */
1314 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1315 pmdev
->pages
[index
].vout_command
= pmbus_receive16(pmdev
);
1321 case PMBUS_VOUT_TRIM
: /* R/W word */
1322 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1323 pmdev
->pages
[index
].vout_trim
= pmbus_receive16(pmdev
);
1329 case PMBUS_VOUT_CAL_OFFSET
: /* R/W word */
1330 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1331 pmdev
->pages
[index
].vout_cal_offset
= pmbus_receive16(pmdev
);
1337 case PMBUS_VOUT_MAX
: /* R/W word */
1338 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1339 pmdev
->pages
[index
].vout_max
= pmbus_receive16(pmdev
);
1345 case PMBUS_VOUT_MARGIN_HIGH
: /* R/W word */
1346 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT_MARGIN
) {
1347 pmdev
->pages
[index
].vout_margin_high
= pmbus_receive16(pmdev
);
1353 case PMBUS_VOUT_MARGIN_LOW
: /* R/W word */
1354 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT_MARGIN
) {
1355 pmdev
->pages
[index
].vout_margin_low
= pmbus_receive16(pmdev
);
1361 case PMBUS_VOUT_TRANSITION_RATE
: /* R/W word */
1362 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1363 pmdev
->pages
[index
].vout_transition_rate
= pmbus_receive16(pmdev
);
1369 case PMBUS_VOUT_DROOP
: /* R/W word */
1370 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1371 pmdev
->pages
[index
].vout_droop
= pmbus_receive16(pmdev
);
1377 case PMBUS_VOUT_SCALE_LOOP
: /* R/W word */
1378 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1379 pmdev
->pages
[index
].vout_scale_loop
= pmbus_receive16(pmdev
);
1385 case PMBUS_VOUT_SCALE_MONITOR
: /* R/W word */
1386 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1387 pmdev
->pages
[index
].vout_scale_monitor
= pmbus_receive16(pmdev
);
1393 case PMBUS_VOUT_MIN
: /* R/W word */
1394 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT_RATING
) {
1395 pmdev
->pages
[index
].vout_min
= pmbus_receive16(pmdev
);
1401 case PMBUS_POUT_MAX
: /* R/W word */
1402 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1403 pmdev
->pages
[index
].pout_max
= pmbus_receive16(pmdev
);
1409 case PMBUS_VIN_ON
: /* R/W word */
1410 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
1411 pmdev
->pages
[index
].vin_on
= pmbus_receive16(pmdev
);
1417 case PMBUS_VIN_OFF
: /* R/W word */
1418 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
1419 pmdev
->pages
[index
].vin_off
= pmbus_receive16(pmdev
);
1425 case PMBUS_IOUT_CAL_GAIN
: /* R/W word */
1426 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT_GAIN
) {
1427 pmdev
->pages
[index
].iout_cal_gain
= pmbus_receive16(pmdev
);
1433 case PMBUS_FAN_CONFIG_1_2
: /* R/W byte */
1434 if (pmdev
->pages
[index
].page_flags
& PB_HAS_FAN
) {
1435 pmdev
->pages
[index
].fan_config_1_2
= pmbus_receive8(pmdev
);
1441 case PMBUS_FAN_COMMAND_1
: /* R/W word */
1442 if (pmdev
->pages
[index
].page_flags
& PB_HAS_FAN
) {
1443 pmdev
->pages
[index
].fan_command_1
= pmbus_receive16(pmdev
);
1449 case PMBUS_FAN_COMMAND_2
: /* R/W word */
1450 if (pmdev
->pages
[index
].page_flags
& PB_HAS_FAN
) {
1451 pmdev
->pages
[index
].fan_command_2
= pmbus_receive16(pmdev
);
1457 case PMBUS_FAN_CONFIG_3_4
: /* R/W byte */
1458 if (pmdev
->pages
[index
].page_flags
& PB_HAS_FAN
) {
1459 pmdev
->pages
[index
].fan_config_3_4
= pmbus_receive8(pmdev
);
1465 case PMBUS_FAN_COMMAND_3
: /* R/W word */
1466 if (pmdev
->pages
[index
].page_flags
& PB_HAS_FAN
) {
1467 pmdev
->pages
[index
].fan_command_3
= pmbus_receive16(pmdev
);
1473 case PMBUS_FAN_COMMAND_4
: /* R/W word */
1474 if (pmdev
->pages
[index
].page_flags
& PB_HAS_FAN
) {
1475 pmdev
->pages
[index
].fan_command_4
= pmbus_receive16(pmdev
);
1481 case PMBUS_VOUT_OV_FAULT_LIMIT
: /* R/W word */
1482 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1483 pmdev
->pages
[index
].vout_ov_fault_limit
= pmbus_receive16(pmdev
);
1489 case PMBUS_VOUT_OV_FAULT_RESPONSE
: /* R/W byte */
1490 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1491 pmdev
->pages
[index
].vout_ov_fault_response
= pmbus_receive8(pmdev
);
1497 case PMBUS_VOUT_OV_WARN_LIMIT
: /* R/W word */
1498 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1499 pmdev
->pages
[index
].vout_ov_warn_limit
= pmbus_receive16(pmdev
);
1505 case PMBUS_VOUT_UV_WARN_LIMIT
: /* R/W word */
1506 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1507 pmdev
->pages
[index
].vout_uv_warn_limit
= pmbus_receive16(pmdev
);
1513 case PMBUS_VOUT_UV_FAULT_LIMIT
: /* R/W word */
1514 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1515 pmdev
->pages
[index
].vout_uv_fault_limit
= pmbus_receive16(pmdev
);
1521 case PMBUS_VOUT_UV_FAULT_RESPONSE
: /* R/W byte */
1522 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1523 pmdev
->pages
[index
].vout_uv_fault_response
= pmbus_receive8(pmdev
);
1529 case PMBUS_IOUT_OC_FAULT_LIMIT
: /* R/W word */
1530 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
1531 pmdev
->pages
[index
].iout_oc_fault_limit
= pmbus_receive16(pmdev
);
1537 case PMBUS_IOUT_OC_FAULT_RESPONSE
: /* R/W byte */
1538 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
1539 pmdev
->pages
[index
].iout_oc_fault_response
= pmbus_receive8(pmdev
);
1545 case PMBUS_IOUT_OC_LV_FAULT_LIMIT
: /* R/W word */
1546 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
1547 pmdev
->pages
[index
].iout_oc_lv_fault_limit
= pmbus_receive16(pmdev
);
1553 case PMBUS_IOUT_OC_LV_FAULT_RESPONSE
: /* R/W byte */
1554 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
1555 pmdev
->pages
[index
].iout_oc_lv_fault_response
1556 = pmbus_receive8(pmdev
);
1562 case PMBUS_IOUT_OC_WARN_LIMIT
: /* R/W word */
1563 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
1564 pmdev
->pages
[index
].iout_oc_warn_limit
= pmbus_receive16(pmdev
);
1570 case PMBUS_IOUT_UC_FAULT_LIMIT
: /* R/W word */
1571 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
1572 pmdev
->pages
[index
].iout_uc_fault_limit
= pmbus_receive16(pmdev
);
1578 case PMBUS_IOUT_UC_FAULT_RESPONSE
: /* R/W byte */
1579 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
1580 pmdev
->pages
[index
].iout_uc_fault_response
= pmbus_receive8(pmdev
);
1586 case PMBUS_OT_FAULT_LIMIT
: /* R/W word */
1587 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMPERATURE
) {
1588 pmdev
->pages
[index
].ot_fault_limit
= pmbus_receive16(pmdev
);
1594 case PMBUS_OT_FAULT_RESPONSE
: /* R/W byte */
1595 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMPERATURE
) {
1596 pmdev
->pages
[index
].ot_fault_response
= pmbus_receive8(pmdev
);
1602 case PMBUS_OT_WARN_LIMIT
: /* R/W word */
1603 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMPERATURE
) {
1604 pmdev
->pages
[index
].ot_warn_limit
= pmbus_receive16(pmdev
);
1610 case PMBUS_UT_WARN_LIMIT
: /* R/W word */
1611 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMPERATURE
) {
1612 pmdev
->pages
[index
].ut_warn_limit
= pmbus_receive16(pmdev
);
1618 case PMBUS_UT_FAULT_LIMIT
: /* R/W word */
1619 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMPERATURE
) {
1620 pmdev
->pages
[index
].ut_fault_limit
= pmbus_receive16(pmdev
);
1626 case PMBUS_UT_FAULT_RESPONSE
: /* R/W byte */
1627 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMPERATURE
) {
1628 pmdev
->pages
[index
].ut_fault_response
= pmbus_receive8(pmdev
);
1634 case PMBUS_VIN_OV_FAULT_LIMIT
: /* R/W word */
1635 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
1636 pmdev
->pages
[index
].vin_ov_fault_limit
= pmbus_receive16(pmdev
);
1642 case PMBUS_VIN_OV_FAULT_RESPONSE
: /* R/W byte */
1643 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
1644 pmdev
->pages
[index
].vin_ov_fault_response
= pmbus_receive8(pmdev
);
1650 case PMBUS_VIN_OV_WARN_LIMIT
: /* R/W word */
1651 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
1652 pmdev
->pages
[index
].vin_ov_warn_limit
= pmbus_receive16(pmdev
);
1658 case PMBUS_VIN_UV_WARN_LIMIT
: /* R/W word */
1659 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
1660 pmdev
->pages
[index
].vin_uv_warn_limit
= pmbus_receive16(pmdev
);
1666 case PMBUS_VIN_UV_FAULT_LIMIT
: /* R/W word */
1667 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
1668 pmdev
->pages
[index
].vin_uv_fault_limit
= pmbus_receive16(pmdev
);
1674 case PMBUS_VIN_UV_FAULT_RESPONSE
: /* R/W byte */
1675 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VIN
) {
1676 pmdev
->pages
[index
].vin_uv_fault_response
= pmbus_receive8(pmdev
);
1682 case PMBUS_IIN_OC_FAULT_LIMIT
: /* R/W word */
1683 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IIN
) {
1684 pmdev
->pages
[index
].iin_oc_fault_limit
= pmbus_receive16(pmdev
);
1690 case PMBUS_IIN_OC_FAULT_RESPONSE
: /* R/W byte */
1691 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IIN
) {
1692 pmdev
->pages
[index
].iin_oc_fault_response
= pmbus_receive8(pmdev
);
1698 case PMBUS_IIN_OC_WARN_LIMIT
: /* R/W word */
1699 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IIN
) {
1700 pmdev
->pages
[index
].iin_oc_warn_limit
= pmbus_receive16(pmdev
);
1706 case PMBUS_POUT_OP_FAULT_LIMIT
: /* R/W word */
1707 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1708 pmdev
->pages
[index
].pout_op_fault_limit
= pmbus_receive16(pmdev
);
1714 case PMBUS_POUT_OP_FAULT_RESPONSE
: /* R/W byte */
1715 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1716 pmdev
->pages
[index
].pout_op_fault_response
= pmbus_receive8(pmdev
);
1722 case PMBUS_POUT_OP_WARN_LIMIT
: /* R/W word */
1723 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1724 pmdev
->pages
[index
].pout_op_warn_limit
= pmbus_receive16(pmdev
);
1730 case PMBUS_PIN_OP_WARN_LIMIT
: /* R/W word */
1731 if (pmdev
->pages
[index
].page_flags
& PB_HAS_PIN
) {
1732 pmdev
->pages
[index
].pin_op_warn_limit
= pmbus_receive16(pmdev
);
1738 case PMBUS_STATUS_BYTE
: /* R/W byte */
1739 pmdev
->pages
[index
].status_word
= pmbus_receive8(pmdev
);
1742 case PMBUS_STATUS_WORD
: /* R/W word */
1743 pmdev
->pages
[index
].status_word
= pmbus_receive16(pmdev
);
1746 case PMBUS_STATUS_VOUT
: /* R/W byte */
1747 if (pmdev
->pages
[index
].page_flags
& PB_HAS_VOUT
) {
1748 pmdev
->pages
[index
].status_vout
= pmbus_receive8(pmdev
);
1754 case PMBUS_STATUS_IOUT
: /* R/W byte */
1755 if (pmdev
->pages
[index
].page_flags
& PB_HAS_IOUT
) {
1756 pmdev
->pages
[index
].status_iout
= pmbus_receive8(pmdev
);
1762 case PMBUS_STATUS_INPUT
: /* R/W byte */
1763 pmdev
->pages
[index
].status_input
= pmbus_receive8(pmdev
);
1766 case PMBUS_STATUS_TEMPERATURE
: /* R/W byte */
1767 if (pmdev
->pages
[index
].page_flags
& PB_HAS_TEMPERATURE
) {
1768 pmdev
->pages
[index
].status_temperature
= pmbus_receive8(pmdev
);
1774 case PMBUS_STATUS_CML
: /* R/W byte */
1775 pmdev
->pages
[index
].status_cml
= pmbus_receive8(pmdev
);
1778 case PMBUS_STATUS_OTHER
: /* R/W byte */
1779 pmdev
->pages
[index
].status_other
= pmbus_receive8(pmdev
);
1782 case PMBUS_STATUS_MFR_SPECIFIC
: /* R/W byte */
1783 pmdev
->pages
[index
].status_mfr_specific
= pmbus_receive8(pmdev
);
1786 case PMBUS_STATUS_FANS_1_2
: /* R/W byte */
1787 if (pmdev
->pages
[index
].page_flags
& PB_HAS_FAN
) {
1788 pmbus_send8(pmdev
, pmdev
->pages
[index
].status_fans_1_2
);
1794 case PMBUS_STATUS_FANS_3_4
: /* R/W byte */
1795 if (pmdev
->pages
[index
].page_flags
& PB_HAS_FAN
) {
1796 pmbus_send8(pmdev
, pmdev
->pages
[index
].status_fans_3_4
);
1802 case PMBUS_PAGE_PLUS_READ
: /* Block Read-only */
1803 case PMBUS_CAPABILITY
: /* Read-Only byte */
1804 case PMBUS_COEFFICIENTS
: /* Read-only block 5 bytes */
1805 case PMBUS_READ_EIN
: /* Read-Only block 5 bytes */
1806 case PMBUS_READ_EOUT
: /* Read-Only block 5 bytes */
1807 case PMBUS_READ_VIN
: /* Read-Only word */
1808 case PMBUS_READ_IIN
: /* Read-Only word */
1809 case PMBUS_READ_VCAP
: /* Read-Only word */
1810 case PMBUS_READ_VOUT
: /* Read-Only word */
1811 case PMBUS_READ_IOUT
: /* Read-Only word */
1812 case PMBUS_READ_TEMPERATURE_1
: /* Read-Only word */
1813 case PMBUS_READ_TEMPERATURE_2
: /* Read-Only word */
1814 case PMBUS_READ_TEMPERATURE_3
: /* Read-Only word */
1815 case PMBUS_READ_FAN_SPEED_1
: /* Read-Only word */
1816 case PMBUS_READ_FAN_SPEED_2
: /* Read-Only word */
1817 case PMBUS_READ_FAN_SPEED_3
: /* Read-Only word */
1818 case PMBUS_READ_FAN_SPEED_4
: /* Read-Only word */
1819 case PMBUS_READ_DUTY_CYCLE
: /* Read-Only word */
1820 case PMBUS_READ_FREQUENCY
: /* Read-Only word */
1821 case PMBUS_READ_POUT
: /* Read-Only word */
1822 case PMBUS_READ_PIN
: /* Read-Only word */
1823 case PMBUS_REVISION
: /* Read-Only byte */
1824 case PMBUS_APP_PROFILE_SUPPORT
: /* Read-Only block-read */
1825 case PMBUS_MFR_VIN_MIN
: /* Read-Only word */
1826 case PMBUS_MFR_VIN_MAX
: /* Read-Only word */
1827 case PMBUS_MFR_IIN_MAX
: /* Read-Only word */
1828 case PMBUS_MFR_PIN_MAX
: /* Read-Only word */
1829 case PMBUS_MFR_VOUT_MIN
: /* Read-Only word */
1830 case PMBUS_MFR_VOUT_MAX
: /* Read-Only word */
1831 case PMBUS_MFR_IOUT_MAX
: /* Read-Only word */
1832 case PMBUS_MFR_POUT_MAX
: /* Read-Only word */
1833 case PMBUS_MFR_TAMBIENT_MAX
: /* Read-Only word */
1834 case PMBUS_MFR_TAMBIENT_MIN
: /* Read-Only word */
1835 case PMBUS_MFR_EFFICIENCY_LL
: /* Read-Only block 14 bytes */
1836 case PMBUS_MFR_EFFICIENCY_HL
: /* Read-Only block 14 bytes */
1837 case PMBUS_MFR_PIN_ACCURACY
: /* Read-Only byte */
1838 case PMBUS_IC_DEVICE_ID
: /* Read-Only block-read */
1839 case PMBUS_IC_DEVICE_REV
: /* Read-Only block-read */
1840 qemu_log_mask(LOG_GUEST_ERROR
,
1841 "%s: writing to read-only register 0x%02x\n",
1842 __func__
, pmdev
->code
);
1846 /* Unimplemented registers get passed to the device */
1848 if (pmdc
->write_data
) {
1849 ret
= pmdc
->write_data(pmdev
, buf
, len
);
1853 pmbus_check_limits(pmdev
);
1854 pmdev
->in_buf_len
= 0;
1858 int pmbus_page_config(PMBusDevice
*pmdev
, uint8_t index
, uint64_t flags
)
1860 if (!pmdev
->pages
) { /* allocate memory for pages on first use */
1861 pmbus_pages_alloc(pmdev
);
1864 /* The 0xFF page is special for commands applying to all pages */
1865 if (index
== PB_ALL_PAGES
) {
1866 for (int i
= 0; i
< pmdev
->num_pages
; i
++) {
1867 pmdev
->pages
[i
].page_flags
= flags
;
1872 if (index
> pmdev
->num_pages
- 1) {
1873 qemu_log_mask(LOG_GUEST_ERROR
,
1874 "%s: index %u is out of range\n",
1879 pmdev
->pages
[index
].page_flags
= flags
;
1884 /* TODO: include pmbus page info in vmstate */
1885 const VMStateDescription vmstate_pmbus_device
= {
1886 .name
= TYPE_PMBUS_DEVICE
,
1888 .minimum_version_id
= 0,
1889 .fields
= (const VMStateField
[]) {
1890 VMSTATE_SMBUS_DEVICE(smb
, PMBusDevice
),
1891 VMSTATE_UINT8(num_pages
, PMBusDevice
),
1892 VMSTATE_UINT8(code
, PMBusDevice
),
1893 VMSTATE_UINT8(page
, PMBusDevice
),
1894 VMSTATE_UINT8(capability
, PMBusDevice
),
1895 VMSTATE_END_OF_LIST()
1899 static void pmbus_device_finalize(Object
*obj
)
1901 PMBusDevice
*pmdev
= PMBUS_DEVICE(obj
);
1902 g_free(pmdev
->pages
);
1905 static void pmbus_device_class_init(ObjectClass
*klass
, void *data
)
1907 SMBusDeviceClass
*k
= SMBUS_DEVICE_CLASS(klass
);
1909 k
->quick_cmd
= pmbus_quick_cmd
;
1910 k
->write_data
= pmbus_write_data
;
1911 k
->receive_byte
= pmbus_receive_byte
;
1914 static const TypeInfo pmbus_device_type_info
= {
1915 .name
= TYPE_PMBUS_DEVICE
,
1916 .parent
= TYPE_SMBUS_DEVICE
,
1917 .instance_size
= sizeof(PMBusDevice
),
1918 .instance_finalize
= pmbus_device_finalize
,
1920 .class_size
= sizeof(PMBusDeviceClass
),
1921 .class_init
= pmbus_device_class_init
,
1924 static void pmbus_device_register_types(void)
1926 type_register_static(&pmbus_device_type_info
);
1929 type_init(pmbus_device_register_types
)