13746d5c1STitus Rwantare /*
23746d5c1STitus Rwantare * PMBus wrapper over SMBus
33746d5c1STitus Rwantare *
43746d5c1STitus Rwantare * Copyright 2021 Google LLC
53746d5c1STitus Rwantare *
63746d5c1STitus Rwantare * SPDX-License-Identifier: GPL-2.0-or-later
73746d5c1STitus Rwantare */
83746d5c1STitus Rwantare
93746d5c1STitus Rwantare #include "qemu/osdep.h"
103746d5c1STitus Rwantare #include <math.h>
113746d5c1STitus Rwantare #include "hw/i2c/pmbus_device.h"
123746d5c1STitus Rwantare #include "migration/vmstate.h"
133746d5c1STitus Rwantare #include "qemu/module.h"
143746d5c1STitus Rwantare #include "qemu/log.h"
153746d5c1STitus Rwantare
pmbus_data2direct_mode(PMBusCoefficients c,uint32_t value)163746d5c1STitus Rwantare uint16_t pmbus_data2direct_mode(PMBusCoefficients c, uint32_t value)
173746d5c1STitus Rwantare {
183746d5c1STitus Rwantare /* R is usually negative to fit large readings into 16 bits */
193746d5c1STitus Rwantare uint16_t y = (c.m * value + c.b) * pow(10, c.R);
203746d5c1STitus Rwantare return y;
213746d5c1STitus Rwantare }
223746d5c1STitus Rwantare
pmbus_direct_mode2data(PMBusCoefficients c,uint16_t value)233746d5c1STitus Rwantare uint32_t pmbus_direct_mode2data(PMBusCoefficients c, uint16_t value)
243746d5c1STitus Rwantare {
253746d5c1STitus Rwantare /* X = (Y * 10^-R - b) / m */
263746d5c1STitus Rwantare uint32_t x = (value / pow(10, c.R) - c.b) / c.m;
273746d5c1STitus Rwantare return x;
283746d5c1STitus Rwantare }
293746d5c1STitus Rwantare
pmbus_data2linear_mode(uint16_t value,int exp)30648a4882SShengtan Mao uint16_t pmbus_data2linear_mode(uint16_t value, int exp)
31648a4882SShengtan Mao {
32648a4882SShengtan Mao /* L = D * 2^(-e) */
33648a4882SShengtan Mao if (exp < 0) {
34648a4882SShengtan Mao return value << (-exp);
35648a4882SShengtan Mao }
36648a4882SShengtan Mao return value >> exp;
37648a4882SShengtan Mao }
38648a4882SShengtan Mao
pmbus_linear_mode2data(uint16_t value,int exp)39648a4882SShengtan Mao uint16_t pmbus_linear_mode2data(uint16_t value, int exp)
40648a4882SShengtan Mao {
41648a4882SShengtan Mao /* D = L * 2^e */
42648a4882SShengtan Mao if (exp < 0) {
43648a4882SShengtan Mao return value >> (-exp);
44648a4882SShengtan Mao }
45648a4882SShengtan Mao return value << exp;
46648a4882SShengtan Mao }
47648a4882SShengtan Mao
pmbus_send(PMBusDevice * pmdev,const uint8_t * data,uint16_t len)483746d5c1STitus Rwantare void pmbus_send(PMBusDevice *pmdev, const uint8_t *data, uint16_t len)
493746d5c1STitus Rwantare {
503746d5c1STitus Rwantare if (pmdev->out_buf_len + len > SMBUS_DATA_MAX_LEN) {
513746d5c1STitus Rwantare qemu_log_mask(LOG_GUEST_ERROR,
523746d5c1STitus Rwantare "PMBus device tried to send too much data");
533746d5c1STitus Rwantare len = 0;
543746d5c1STitus Rwantare }
553746d5c1STitus Rwantare
563746d5c1STitus Rwantare for (int i = len - 1; i >= 0; i--) {
573746d5c1STitus Rwantare pmdev->out_buf[i + pmdev->out_buf_len] = data[len - i - 1];
583746d5c1STitus Rwantare }
593746d5c1STitus Rwantare pmdev->out_buf_len += len;
603746d5c1STitus Rwantare }
613746d5c1STitus Rwantare
623746d5c1STitus Rwantare /* Internal only, convert unsigned ints to the little endian bus */
pmbus_send_uint(PMBusDevice * pmdev,uint64_t data,uint8_t size)633746d5c1STitus Rwantare static void pmbus_send_uint(PMBusDevice *pmdev, uint64_t data, uint8_t size)
643746d5c1STitus Rwantare {
653746d5c1STitus Rwantare uint8_t bytes[8];
663746d5c1STitus Rwantare g_assert(size <= 8);
673746d5c1STitus Rwantare
683746d5c1STitus Rwantare for (int i = 0; i < size; i++) {
693746d5c1STitus Rwantare bytes[i] = data & 0xFF;
703746d5c1STitus Rwantare data = data >> 8;
713746d5c1STitus Rwantare }
723746d5c1STitus Rwantare pmbus_send(pmdev, bytes, size);
733746d5c1STitus Rwantare }
743746d5c1STitus Rwantare
pmbus_send8(PMBusDevice * pmdev,uint8_t data)753746d5c1STitus Rwantare void pmbus_send8(PMBusDevice *pmdev, uint8_t data)
763746d5c1STitus Rwantare {
773746d5c1STitus Rwantare pmbus_send_uint(pmdev, data, 1);
783746d5c1STitus Rwantare }
793746d5c1STitus Rwantare
pmbus_send16(PMBusDevice * pmdev,uint16_t data)803746d5c1STitus Rwantare void pmbus_send16(PMBusDevice *pmdev, uint16_t data)
813746d5c1STitus Rwantare {
823746d5c1STitus Rwantare pmbus_send_uint(pmdev, data, 2);
833746d5c1STitus Rwantare }
843746d5c1STitus Rwantare
pmbus_send32(PMBusDevice * pmdev,uint32_t data)853746d5c1STitus Rwantare void pmbus_send32(PMBusDevice *pmdev, uint32_t data)
863746d5c1STitus Rwantare {
873746d5c1STitus Rwantare pmbus_send_uint(pmdev, data, 4);
883746d5c1STitus Rwantare }
893746d5c1STitus Rwantare
pmbus_send64(PMBusDevice * pmdev,uint64_t data)903746d5c1STitus Rwantare void pmbus_send64(PMBusDevice *pmdev, uint64_t data)
913746d5c1STitus Rwantare {
923746d5c1STitus Rwantare pmbus_send_uint(pmdev, data, 8);
933746d5c1STitus Rwantare }
943746d5c1STitus Rwantare
pmbus_send_string(PMBusDevice * pmdev,const char * data)953746d5c1STitus Rwantare void pmbus_send_string(PMBusDevice *pmdev, const char *data)
963746d5c1STitus Rwantare {
9795bf3418STitus Rwantare if (!data) {
9895bf3418STitus Rwantare qemu_log_mask(LOG_GUEST_ERROR,
9995bf3418STitus Rwantare "%s: %s: uninitialised read from 0x%02x\n",
10095bf3418STitus Rwantare __func__, DEVICE(pmdev)->canonical_path, pmdev->code);
10195bf3418STitus Rwantare return;
10295bf3418STitus Rwantare }
10395bf3418STitus Rwantare
1043746d5c1STitus Rwantare size_t len = strlen(data);
1053746d5c1STitus Rwantare g_assert(len + pmdev->out_buf_len < SMBUS_DATA_MAX_LEN);
1063746d5c1STitus Rwantare pmdev->out_buf[len + pmdev->out_buf_len] = len;
1073746d5c1STitus Rwantare
1083746d5c1STitus Rwantare for (int i = len - 1; i >= 0; i--) {
1093746d5c1STitus Rwantare pmdev->out_buf[i + pmdev->out_buf_len] = data[len - 1 - i];
1103746d5c1STitus Rwantare }
1113746d5c1STitus Rwantare pmdev->out_buf_len += len + 1;
1123746d5c1STitus Rwantare }
1133746d5c1STitus Rwantare
pmbus_receive_block(PMBusDevice * pmdev,uint8_t * dest,size_t len)114cfb0884cSTitus Rwantare uint8_t pmbus_receive_block(PMBusDevice *pmdev, uint8_t *dest, size_t len)
115cfb0884cSTitus Rwantare {
116cfb0884cSTitus Rwantare /* dest may contain data from previous writes */
117cfb0884cSTitus Rwantare memset(dest, 0, len);
118cfb0884cSTitus Rwantare
119cfb0884cSTitus Rwantare /* Exclude command code from return value */
120cfb0884cSTitus Rwantare pmdev->in_buf++;
121cfb0884cSTitus Rwantare pmdev->in_buf_len--;
122cfb0884cSTitus Rwantare
123cfb0884cSTitus Rwantare /* The byte after the command code denotes the length */
124cfb0884cSTitus Rwantare uint8_t sent_len = pmdev->in_buf[0];
125cfb0884cSTitus Rwantare
126cfb0884cSTitus Rwantare if (sent_len != pmdev->in_buf_len - 1) {
127cfb0884cSTitus Rwantare qemu_log_mask(LOG_GUEST_ERROR,
128cfb0884cSTitus Rwantare "%s: length mismatch. Expected %d bytes, got %d bytes\n",
129cfb0884cSTitus Rwantare __func__, sent_len, pmdev->in_buf_len - 1);
130cfb0884cSTitus Rwantare }
131cfb0884cSTitus Rwantare
132cfb0884cSTitus Rwantare /* exclude length byte */
133cfb0884cSTitus Rwantare pmdev->in_buf++;
134cfb0884cSTitus Rwantare pmdev->in_buf_len--;
135cfb0884cSTitus Rwantare
136cfb0884cSTitus Rwantare if (pmdev->in_buf_len < len) {
137cfb0884cSTitus Rwantare len = pmdev->in_buf_len;
138cfb0884cSTitus Rwantare }
139cfb0884cSTitus Rwantare memcpy(dest, pmdev->in_buf, len);
140cfb0884cSTitus Rwantare return len;
141cfb0884cSTitus Rwantare }
142cfb0884cSTitus Rwantare
1433746d5c1STitus Rwantare
pmbus_receive_uint(PMBusDevice * pmdev)14478fdfc59STitus Rwantare static uint64_t pmbus_receive_uint(PMBusDevice *pmdev)
1453746d5c1STitus Rwantare {
1463746d5c1STitus Rwantare uint64_t ret = 0;
1473746d5c1STitus Rwantare
1483746d5c1STitus Rwantare /* Exclude command code from return value */
14978fdfc59STitus Rwantare pmdev->in_buf++;
15078fdfc59STitus Rwantare pmdev->in_buf_len--;
1513746d5c1STitus Rwantare
15278fdfc59STitus Rwantare for (int i = pmdev->in_buf_len - 1; i >= 0; i--) {
15378fdfc59STitus Rwantare ret = ret << 8 | pmdev->in_buf[i];
1543746d5c1STitus Rwantare }
1553746d5c1STitus Rwantare return ret;
1563746d5c1STitus Rwantare }
1573746d5c1STitus Rwantare
pmbus_receive8(PMBusDevice * pmdev)1583746d5c1STitus Rwantare uint8_t pmbus_receive8(PMBusDevice *pmdev)
1593746d5c1STitus Rwantare {
1603746d5c1STitus Rwantare if (pmdev->in_buf_len - 1 != 1) {
1613746d5c1STitus Rwantare qemu_log_mask(LOG_GUEST_ERROR,
1623746d5c1STitus Rwantare "%s: length mismatch. Expected 1 byte, got %d bytes\n",
1633746d5c1STitus Rwantare __func__, pmdev->in_buf_len - 1);
1643746d5c1STitus Rwantare }
16578fdfc59STitus Rwantare return pmbus_receive_uint(pmdev);
1663746d5c1STitus Rwantare }
1673746d5c1STitus Rwantare
pmbus_receive16(PMBusDevice * pmdev)1683746d5c1STitus Rwantare uint16_t pmbus_receive16(PMBusDevice *pmdev)
1693746d5c1STitus Rwantare {
1703746d5c1STitus Rwantare if (pmdev->in_buf_len - 1 != 2) {
1713746d5c1STitus Rwantare qemu_log_mask(LOG_GUEST_ERROR,
1723746d5c1STitus Rwantare "%s: length mismatch. Expected 2 bytes, got %d bytes\n",
1733746d5c1STitus Rwantare __func__, pmdev->in_buf_len - 1);
1743746d5c1STitus Rwantare }
17578fdfc59STitus Rwantare return pmbus_receive_uint(pmdev);
1763746d5c1STitus Rwantare }
1773746d5c1STitus Rwantare
pmbus_receive32(PMBusDevice * pmdev)1783746d5c1STitus Rwantare uint32_t pmbus_receive32(PMBusDevice *pmdev)
1793746d5c1STitus Rwantare {
1803746d5c1STitus Rwantare if (pmdev->in_buf_len - 1 != 4) {
1813746d5c1STitus Rwantare qemu_log_mask(LOG_GUEST_ERROR,
1823746d5c1STitus Rwantare "%s: length mismatch. Expected 4 bytes, got %d bytes\n",
1833746d5c1STitus Rwantare __func__, pmdev->in_buf_len - 1);
1843746d5c1STitus Rwantare }
18578fdfc59STitus Rwantare return pmbus_receive_uint(pmdev);
1863746d5c1STitus Rwantare }
1873746d5c1STitus Rwantare
pmbus_receive64(PMBusDevice * pmdev)1883746d5c1STitus Rwantare uint64_t pmbus_receive64(PMBusDevice *pmdev)
1893746d5c1STitus Rwantare {
1903746d5c1STitus Rwantare if (pmdev->in_buf_len - 1 != 8) {
1913746d5c1STitus Rwantare qemu_log_mask(LOG_GUEST_ERROR,
1923746d5c1STitus Rwantare "%s: length mismatch. Expected 8 bytes, got %d bytes\n",
1933746d5c1STitus Rwantare __func__, pmdev->in_buf_len - 1);
1943746d5c1STitus Rwantare }
19578fdfc59STitus Rwantare return pmbus_receive_uint(pmdev);
1963746d5c1STitus Rwantare }
1973746d5c1STitus Rwantare
pmbus_out_buf_pop(PMBusDevice * pmdev)1983746d5c1STitus Rwantare static uint8_t pmbus_out_buf_pop(PMBusDevice *pmdev)
1993746d5c1STitus Rwantare {
2003746d5c1STitus Rwantare if (pmdev->out_buf_len == 0) {
2013746d5c1STitus Rwantare qemu_log_mask(LOG_GUEST_ERROR,
2023746d5c1STitus Rwantare "%s: tried to read from empty buffer",
2033746d5c1STitus Rwantare __func__);
20438870253STitus Rwantare return PMBUS_ERR_BYTE;
2053746d5c1STitus Rwantare }
2063746d5c1STitus Rwantare uint8_t data = pmdev->out_buf[pmdev->out_buf_len - 1];
2073746d5c1STitus Rwantare pmdev->out_buf_len--;
2083746d5c1STitus Rwantare return data;
2093746d5c1STitus Rwantare }
2103746d5c1STitus Rwantare
pmbus_quick_cmd(SMBusDevice * smd,uint8_t read)2113746d5c1STitus Rwantare static void pmbus_quick_cmd(SMBusDevice *smd, uint8_t read)
2123746d5c1STitus Rwantare {
2133746d5c1STitus Rwantare PMBusDevice *pmdev = PMBUS_DEVICE(smd);
2143746d5c1STitus Rwantare PMBusDeviceClass *pmdc = PMBUS_DEVICE_GET_CLASS(pmdev);
2153746d5c1STitus Rwantare
2163746d5c1STitus Rwantare if (pmdc->quick_cmd) {
2173746d5c1STitus Rwantare pmdc->quick_cmd(pmdev, read);
2183746d5c1STitus Rwantare }
2193746d5c1STitus Rwantare }
2203746d5c1STitus Rwantare
pmbus_pages_num(PMBusDevice * pmdev)221f0e4588fSPhilippe Mathieu-Daudé static uint8_t pmbus_pages_num(PMBusDevice *pmdev)
222f0e4588fSPhilippe Mathieu-Daudé {
223f0e4588fSPhilippe Mathieu-Daudé const PMBusDeviceClass *k = PMBUS_DEVICE_GET_CLASS(pmdev);
224f0e4588fSPhilippe Mathieu-Daudé
225f0e4588fSPhilippe Mathieu-Daudé /* some PMBus devices don't use the PAGE command, so they get 1 page */
226f0e4588fSPhilippe Mathieu-Daudé return k->device_num_pages ? : 1;
227f0e4588fSPhilippe Mathieu-Daudé }
228f0e4588fSPhilippe Mathieu-Daudé
pmbus_pages_alloc(PMBusDevice * pmdev)2293746d5c1STitus Rwantare static void pmbus_pages_alloc(PMBusDevice *pmdev)
2303746d5c1STitus Rwantare {
231f0e4588fSPhilippe Mathieu-Daudé pmdev->num_pages = pmbus_pages_num(pmdev);
232f0e4588fSPhilippe Mathieu-Daudé pmdev->pages = g_new0(PMBusPage, pmdev->num_pages);
2333746d5c1STitus Rwantare }
2343746d5c1STitus Rwantare
pmbus_check_limits(PMBusDevice * pmdev)2353746d5c1STitus Rwantare void pmbus_check_limits(PMBusDevice *pmdev)
2363746d5c1STitus Rwantare {
2373746d5c1STitus Rwantare for (int i = 0; i < pmdev->num_pages; i++) {
2383746d5c1STitus Rwantare if ((pmdev->pages[i].operation & PB_OP_ON) == 0) {
2393746d5c1STitus Rwantare continue; /* don't check powered off devices */
2403746d5c1STitus Rwantare }
2413746d5c1STitus Rwantare
2423746d5c1STitus Rwantare if (pmdev->pages[i].read_vout > pmdev->pages[i].vout_ov_fault_limit) {
2433746d5c1STitus Rwantare pmdev->pages[i].status_word |= PB_STATUS_VOUT;
2443746d5c1STitus Rwantare pmdev->pages[i].status_vout |= PB_STATUS_VOUT_OV_FAULT;
2453746d5c1STitus Rwantare }
2463746d5c1STitus Rwantare
2473746d5c1STitus Rwantare if (pmdev->pages[i].read_vout > pmdev->pages[i].vout_ov_warn_limit) {
2483746d5c1STitus Rwantare pmdev->pages[i].status_word |= PB_STATUS_VOUT;
2493746d5c1STitus Rwantare pmdev->pages[i].status_vout |= PB_STATUS_VOUT_OV_WARN;
2503746d5c1STitus Rwantare }
2513746d5c1STitus Rwantare
2523746d5c1STitus Rwantare if (pmdev->pages[i].read_vout < pmdev->pages[i].vout_uv_warn_limit) {
2533746d5c1STitus Rwantare pmdev->pages[i].status_word |= PB_STATUS_VOUT;
2543746d5c1STitus Rwantare pmdev->pages[i].status_vout |= PB_STATUS_VOUT_UV_WARN;
2553746d5c1STitus Rwantare }
2563746d5c1STitus Rwantare
2573746d5c1STitus Rwantare if (pmdev->pages[i].read_vout < pmdev->pages[i].vout_uv_fault_limit) {
2583746d5c1STitus Rwantare pmdev->pages[i].status_word |= PB_STATUS_VOUT;
2593746d5c1STitus Rwantare pmdev->pages[i].status_vout |= PB_STATUS_VOUT_UV_FAULT;
2603746d5c1STitus Rwantare }
2613746d5c1STitus Rwantare
2623746d5c1STitus Rwantare if (pmdev->pages[i].read_vin > pmdev->pages[i].vin_ov_warn_limit) {
2633746d5c1STitus Rwantare pmdev->pages[i].status_word |= PB_STATUS_INPUT;
2643746d5c1STitus Rwantare pmdev->pages[i].status_input |= PB_STATUS_INPUT_VIN_OV_WARN;
2653746d5c1STitus Rwantare }
2663746d5c1STitus Rwantare
2673746d5c1STitus Rwantare if (pmdev->pages[i].read_vin < pmdev->pages[i].vin_uv_warn_limit) {
2683746d5c1STitus Rwantare pmdev->pages[i].status_word |= PB_STATUS_INPUT;
2693746d5c1STitus Rwantare pmdev->pages[i].status_input |= PB_STATUS_INPUT_VIN_UV_WARN;
2703746d5c1STitus Rwantare }
2713746d5c1STitus Rwantare
2723746d5c1STitus Rwantare if (pmdev->pages[i].read_iout > pmdev->pages[i].iout_oc_warn_limit) {
2733746d5c1STitus Rwantare pmdev->pages[i].status_word |= PB_STATUS_IOUT_POUT;
2743746d5c1STitus Rwantare pmdev->pages[i].status_iout |= PB_STATUS_IOUT_OC_WARN;
2753746d5c1STitus Rwantare }
2763746d5c1STitus Rwantare
2773746d5c1STitus Rwantare if (pmdev->pages[i].read_iout > pmdev->pages[i].iout_oc_fault_limit) {
2783746d5c1STitus Rwantare pmdev->pages[i].status_word |= PB_STATUS_IOUT_POUT;
2793746d5c1STitus Rwantare pmdev->pages[i].status_iout |= PB_STATUS_IOUT_OC_FAULT;
2803746d5c1STitus Rwantare }
2813746d5c1STitus Rwantare
2823746d5c1STitus Rwantare if (pmdev->pages[i].read_pin > pmdev->pages[i].pin_op_warn_limit) {
2833746d5c1STitus Rwantare pmdev->pages[i].status_word |= PB_STATUS_INPUT;
2843746d5c1STitus Rwantare pmdev->pages[i].status_input |= PB_STATUS_INPUT_PIN_OP_WARN;
2853746d5c1STitus Rwantare }
2863746d5c1STitus Rwantare
2873746d5c1STitus Rwantare if (pmdev->pages[i].read_temperature_1
2883746d5c1STitus Rwantare > pmdev->pages[i].ot_fault_limit) {
2893746d5c1STitus Rwantare pmdev->pages[i].status_word |= PB_STATUS_TEMPERATURE;
2903746d5c1STitus Rwantare pmdev->pages[i].status_temperature |= PB_STATUS_OT_FAULT;
2913746d5c1STitus Rwantare }
2923746d5c1STitus Rwantare
2933746d5c1STitus Rwantare if (pmdev->pages[i].read_temperature_1
2943746d5c1STitus Rwantare > pmdev->pages[i].ot_warn_limit) {
2953746d5c1STitus Rwantare pmdev->pages[i].status_word |= PB_STATUS_TEMPERATURE;
2963746d5c1STitus Rwantare pmdev->pages[i].status_temperature |= PB_STATUS_OT_WARN;
2973746d5c1STitus Rwantare }
2983746d5c1STitus Rwantare }
2993746d5c1STitus Rwantare }
3003746d5c1STitus Rwantare
pmbus_idle(PMBusDevice * pmdev)301d272d141SPeter Delevoryas void pmbus_idle(PMBusDevice *pmdev)
302d272d141SPeter Delevoryas {
303d272d141SPeter Delevoryas pmdev->code = PMBUS_IDLE_STATE;
304d272d141SPeter Delevoryas }
305d272d141SPeter Delevoryas
30638870253STitus Rwantare /* assert the status_cml error upon receipt of malformed command */
pmbus_cml_error(PMBusDevice * pmdev)30738870253STitus Rwantare static void pmbus_cml_error(PMBusDevice *pmdev)
30838870253STitus Rwantare {
30938870253STitus Rwantare for (int i = 0; i < pmdev->num_pages; i++) {
31038870253STitus Rwantare pmdev->pages[i].status_word |= PMBUS_STATUS_CML;
31138870253STitus Rwantare pmdev->pages[i].status_cml |= PB_CML_FAULT_INVALID_CMD;
31238870253STitus Rwantare }
31338870253STitus Rwantare }
31438870253STitus Rwantare
pmbus_receive_byte(SMBusDevice * smd)3153746d5c1STitus Rwantare static uint8_t pmbus_receive_byte(SMBusDevice *smd)
3163746d5c1STitus Rwantare {
3173746d5c1STitus Rwantare PMBusDevice *pmdev = PMBUS_DEVICE(smd);
3183746d5c1STitus Rwantare PMBusDeviceClass *pmdc = PMBUS_DEVICE_GET_CLASS(pmdev);
31938870253STitus Rwantare uint8_t ret = PMBUS_ERR_BYTE;
32038870253STitus Rwantare uint8_t index;
3213746d5c1STitus Rwantare
3223746d5c1STitus Rwantare if (pmdev->out_buf_len != 0) {
3233746d5c1STitus Rwantare ret = pmbus_out_buf_pop(pmdev);
3243746d5c1STitus Rwantare return ret;
3253746d5c1STitus Rwantare }
3263746d5c1STitus Rwantare
32738870253STitus Rwantare /*
32838870253STitus Rwantare * Reading from all pages will return the value from page 0,
329dd0b3271SMaheswara Kurapati * means that all subsequent commands are to be applied to all output.
33038870253STitus Rwantare */
33138870253STitus Rwantare if (pmdev->page == PB_ALL_PAGES) {
33238870253STitus Rwantare index = 0;
33338870253STitus Rwantare } else if (pmdev->page > pmdev->num_pages - 1) {
33438870253STitus Rwantare qemu_log_mask(LOG_GUEST_ERROR,
33538870253STitus Rwantare "%s: page %d is out of range\n",
33638870253STitus Rwantare __func__, pmdev->page);
33738870253STitus Rwantare pmbus_cml_error(pmdev);
33838870253STitus Rwantare return PMBUS_ERR_BYTE;
33938870253STitus Rwantare } else {
34038870253STitus Rwantare index = pmdev->page;
34138870253STitus Rwantare }
34238870253STitus Rwantare
3433746d5c1STitus Rwantare switch (pmdev->code) {
3443746d5c1STitus Rwantare case PMBUS_PAGE:
3453746d5c1STitus Rwantare pmbus_send8(pmdev, pmdev->page);
3463746d5c1STitus Rwantare break;
3473746d5c1STitus Rwantare
3483746d5c1STitus Rwantare case PMBUS_OPERATION: /* R/W byte */
3493746d5c1STitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].operation);
3503746d5c1STitus Rwantare break;
3513746d5c1STitus Rwantare
3523746d5c1STitus Rwantare case PMBUS_ON_OFF_CONFIG: /* R/W byte */
3533746d5c1STitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].on_off_config);
3543746d5c1STitus Rwantare break;
3553746d5c1STitus Rwantare
3563746d5c1STitus Rwantare case PMBUS_PHASE: /* R/W byte */
3573746d5c1STitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].phase);
3583746d5c1STitus Rwantare break;
3593746d5c1STitus Rwantare
3603746d5c1STitus Rwantare case PMBUS_WRITE_PROTECT: /* R/W byte */
3613746d5c1STitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].write_protect);
3623746d5c1STitus Rwantare break;
3633746d5c1STitus Rwantare
3643746d5c1STitus Rwantare case PMBUS_CAPABILITY:
3653746d5c1STitus Rwantare pmbus_send8(pmdev, pmdev->capability);
3662192aaaeSTitus Rwantare if (pmdev->capability & BIT(7)) {
3672192aaaeSTitus Rwantare qemu_log_mask(LOG_UNIMP,
3682192aaaeSTitus Rwantare "%s: PEC is enabled but not yet supported.\n",
3692192aaaeSTitus Rwantare __func__);
3702192aaaeSTitus Rwantare }
3713746d5c1STitus Rwantare break;
3723746d5c1STitus Rwantare
3733746d5c1STitus Rwantare case PMBUS_VOUT_MODE: /* R/W byte */
3743746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT_MODE) {
3753746d5c1STitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].vout_mode);
3763746d5c1STitus Rwantare } else {
3773746d5c1STitus Rwantare goto passthough;
3783746d5c1STitus Rwantare }
3793746d5c1STitus Rwantare break;
3803746d5c1STitus Rwantare
3813746d5c1STitus Rwantare case PMBUS_VOUT_COMMAND: /* R/W word */
3823746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
3833746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].vout_command);
3843746d5c1STitus Rwantare } else {
3853746d5c1STitus Rwantare goto passthough;
3863746d5c1STitus Rwantare }
3873746d5c1STitus Rwantare break;
3883746d5c1STitus Rwantare
3893746d5c1STitus Rwantare case PMBUS_VOUT_TRIM: /* R/W word */
3903746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
3913746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].vout_trim);
3923746d5c1STitus Rwantare } else {
3933746d5c1STitus Rwantare goto passthough;
3943746d5c1STitus Rwantare }
3953746d5c1STitus Rwantare break;
3963746d5c1STitus Rwantare
3973746d5c1STitus Rwantare case PMBUS_VOUT_CAL_OFFSET: /* R/W word */
3983746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
3993746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].vout_cal_offset);
4003746d5c1STitus Rwantare } else {
4013746d5c1STitus Rwantare goto passthough;
4023746d5c1STitus Rwantare }
4033746d5c1STitus Rwantare break;
4043746d5c1STitus Rwantare
4053746d5c1STitus Rwantare case PMBUS_VOUT_MAX: /* R/W word */
4063746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
4073746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].vout_max);
4083746d5c1STitus Rwantare } else {
4093746d5c1STitus Rwantare goto passthough;
4103746d5c1STitus Rwantare }
4113746d5c1STitus Rwantare break;
4123746d5c1STitus Rwantare
4133746d5c1STitus Rwantare case PMBUS_VOUT_MARGIN_HIGH: /* R/W word */
4143746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT_MARGIN) {
4153746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].vout_margin_high);
4163746d5c1STitus Rwantare } else {
4173746d5c1STitus Rwantare goto passthough;
4183746d5c1STitus Rwantare }
4193746d5c1STitus Rwantare break;
4203746d5c1STitus Rwantare
4213746d5c1STitus Rwantare case PMBUS_VOUT_MARGIN_LOW: /* R/W word */
4223746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT_MARGIN) {
4233746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].vout_margin_low);
4243746d5c1STitus Rwantare } else {
4253746d5c1STitus Rwantare goto passthough;
4263746d5c1STitus Rwantare }
4273746d5c1STitus Rwantare break;
4283746d5c1STitus Rwantare
4293746d5c1STitus Rwantare case PMBUS_VOUT_TRANSITION_RATE: /* R/W word */
4303746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
4313746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].vout_transition_rate);
4323746d5c1STitus Rwantare } else {
4333746d5c1STitus Rwantare goto passthough;
4343746d5c1STitus Rwantare }
4353746d5c1STitus Rwantare break;
4363746d5c1STitus Rwantare
4373746d5c1STitus Rwantare case PMBUS_VOUT_DROOP: /* R/W word */
4383746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
4393746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].vout_droop);
4403746d5c1STitus Rwantare } else {
4413746d5c1STitus Rwantare goto passthough;
4423746d5c1STitus Rwantare }
4433746d5c1STitus Rwantare break;
4443746d5c1STitus Rwantare
4453746d5c1STitus Rwantare case PMBUS_VOUT_SCALE_LOOP: /* R/W word */
4463746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
4473746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].vout_scale_loop);
4483746d5c1STitus Rwantare } else {
4493746d5c1STitus Rwantare goto passthough;
4503746d5c1STitus Rwantare }
4513746d5c1STitus Rwantare break;
4523746d5c1STitus Rwantare
4533746d5c1STitus Rwantare case PMBUS_VOUT_SCALE_MONITOR: /* R/W word */
4543746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
4553746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].vout_scale_monitor);
4563746d5c1STitus Rwantare } else {
4573746d5c1STitus Rwantare goto passthough;
4583746d5c1STitus Rwantare }
4593746d5c1STitus Rwantare break;
4603746d5c1STitus Rwantare
46132480293STitus Rwantare case PMBUS_VOUT_MIN: /* R/W word */
46232480293STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT_RATING) {
46332480293STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].vout_min);
46432480293STitus Rwantare } else {
46532480293STitus Rwantare goto passthough;
46632480293STitus Rwantare }
46732480293STitus Rwantare break;
46832480293STitus Rwantare
4693746d5c1STitus Rwantare /* TODO: implement coefficients support */
4703746d5c1STitus Rwantare
4713746d5c1STitus Rwantare case PMBUS_POUT_MAX: /* R/W word */
4723746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_POUT) {
4733746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].pout_max);
4743746d5c1STitus Rwantare } else {
4753746d5c1STitus Rwantare goto passthough;
4763746d5c1STitus Rwantare }
4773746d5c1STitus Rwantare break;
4783746d5c1STitus Rwantare
4793746d5c1STitus Rwantare case PMBUS_VIN_ON: /* R/W word */
4803746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VIN) {
4813746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].vin_on);
4823746d5c1STitus Rwantare } else {
4833746d5c1STitus Rwantare goto passthough;
4843746d5c1STitus Rwantare }
4853746d5c1STitus Rwantare break;
4863746d5c1STitus Rwantare
4873746d5c1STitus Rwantare case PMBUS_VIN_OFF: /* R/W word */
4883746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VIN) {
4893746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].vin_off);
4903746d5c1STitus Rwantare } else {
4913746d5c1STitus Rwantare goto passthough;
4923746d5c1STitus Rwantare }
4933746d5c1STitus Rwantare break;
4943746d5c1STitus Rwantare
4953746d5c1STitus Rwantare case PMBUS_IOUT_CAL_GAIN: /* R/W word */
4963746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_IOUT_GAIN) {
4973746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].iout_cal_gain);
4983746d5c1STitus Rwantare } else {
4993746d5c1STitus Rwantare goto passthough;
5003746d5c1STitus Rwantare }
5013746d5c1STitus Rwantare break;
5023746d5c1STitus Rwantare
503b7fba25eSTitus Rwantare case PMBUS_FAN_CONFIG_1_2: /* R/W byte */
504b7fba25eSTitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_FAN) {
505b7fba25eSTitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].fan_config_1_2);
506b7fba25eSTitus Rwantare } else {
507b7fba25eSTitus Rwantare goto passthough;
508b7fba25eSTitus Rwantare }
509b7fba25eSTitus Rwantare break;
510b7fba25eSTitus Rwantare
511b7fba25eSTitus Rwantare case PMBUS_FAN_COMMAND_1: /* R/W word */
512b7fba25eSTitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_FAN) {
513b7fba25eSTitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].fan_command_1);
514b7fba25eSTitus Rwantare } else {
515b7fba25eSTitus Rwantare goto passthough;
516b7fba25eSTitus Rwantare }
517b7fba25eSTitus Rwantare break;
518b7fba25eSTitus Rwantare
519b7fba25eSTitus Rwantare case PMBUS_FAN_COMMAND_2: /* R/W word */
520b7fba25eSTitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_FAN) {
521b7fba25eSTitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].fan_command_2);
522b7fba25eSTitus Rwantare } else {
523b7fba25eSTitus Rwantare goto passthough;
524b7fba25eSTitus Rwantare }
525b7fba25eSTitus Rwantare break;
526b7fba25eSTitus Rwantare
527b7fba25eSTitus Rwantare case PMBUS_FAN_CONFIG_3_4: /* R/W byte */
528b7fba25eSTitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_FAN) {
529b7fba25eSTitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].fan_config_3_4);
530b7fba25eSTitus Rwantare } else {
531b7fba25eSTitus Rwantare goto passthough;
532b7fba25eSTitus Rwantare }
533b7fba25eSTitus Rwantare break;
534b7fba25eSTitus Rwantare
535b7fba25eSTitus Rwantare case PMBUS_FAN_COMMAND_3: /* R/W word */
536b7fba25eSTitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_FAN) {
537b7fba25eSTitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].fan_command_3);
538b7fba25eSTitus Rwantare } else {
539b7fba25eSTitus Rwantare goto passthough;
540b7fba25eSTitus Rwantare }
541b7fba25eSTitus Rwantare break;
542b7fba25eSTitus Rwantare
543b7fba25eSTitus Rwantare case PMBUS_FAN_COMMAND_4: /* R/W word */
544b7fba25eSTitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_FAN) {
545b7fba25eSTitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].fan_command_4);
546b7fba25eSTitus Rwantare } else {
547b7fba25eSTitus Rwantare goto passthough;
548b7fba25eSTitus Rwantare }
549b7fba25eSTitus Rwantare break;
550b7fba25eSTitus Rwantare
5513746d5c1STitus Rwantare case PMBUS_VOUT_OV_FAULT_LIMIT: /* R/W word */
5523746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
5533746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].vout_ov_fault_limit);
5543746d5c1STitus Rwantare } else {
5553746d5c1STitus Rwantare goto passthough;
5563746d5c1STitus Rwantare }
5573746d5c1STitus Rwantare break;
5583746d5c1STitus Rwantare
5593746d5c1STitus Rwantare case PMBUS_VOUT_OV_FAULT_RESPONSE: /* R/W byte */
5603746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
5613746d5c1STitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].vout_ov_fault_response);
5623746d5c1STitus Rwantare } else {
5633746d5c1STitus Rwantare goto passthough;
5643746d5c1STitus Rwantare }
5653746d5c1STitus Rwantare break;
5663746d5c1STitus Rwantare
5673746d5c1STitus Rwantare case PMBUS_VOUT_OV_WARN_LIMIT: /* R/W word */
5683746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
5693746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].vout_ov_warn_limit);
5703746d5c1STitus Rwantare } else {
5713746d5c1STitus Rwantare goto passthough;
5723746d5c1STitus Rwantare }
5733746d5c1STitus Rwantare break;
5743746d5c1STitus Rwantare
5753746d5c1STitus Rwantare case PMBUS_VOUT_UV_WARN_LIMIT: /* R/W word */
5763746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
5773746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].vout_uv_warn_limit);
5783746d5c1STitus Rwantare } else {
5793746d5c1STitus Rwantare goto passthough;
5803746d5c1STitus Rwantare }
5813746d5c1STitus Rwantare break;
5823746d5c1STitus Rwantare
5833746d5c1STitus Rwantare case PMBUS_VOUT_UV_FAULT_LIMIT: /* R/W word */
5843746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
5853746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].vout_uv_fault_limit);
5863746d5c1STitus Rwantare } else {
5873746d5c1STitus Rwantare goto passthough;
5883746d5c1STitus Rwantare }
5893746d5c1STitus Rwantare break;
5903746d5c1STitus Rwantare
5913746d5c1STitus Rwantare case PMBUS_VOUT_UV_FAULT_RESPONSE: /* R/W byte */
5923746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
5933746d5c1STitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].vout_uv_fault_response);
5943746d5c1STitus Rwantare } else {
5953746d5c1STitus Rwantare goto passthough;
5963746d5c1STitus Rwantare }
5973746d5c1STitus Rwantare break;
5983746d5c1STitus Rwantare
5993746d5c1STitus Rwantare case PMBUS_IOUT_OC_FAULT_LIMIT: /* R/W word */
6003746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_IOUT) {
6013746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].iout_oc_fault_limit);
6023746d5c1STitus Rwantare } else {
6033746d5c1STitus Rwantare goto passthough;
6043746d5c1STitus Rwantare }
6053746d5c1STitus Rwantare break;
6063746d5c1STitus Rwantare
6073746d5c1STitus Rwantare case PMBUS_IOUT_OC_FAULT_RESPONSE: /* R/W byte */
6083746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_IOUT) {
6093746d5c1STitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].iout_oc_fault_response);
6103746d5c1STitus Rwantare } else {
6113746d5c1STitus Rwantare goto passthough;
6123746d5c1STitus Rwantare }
6133746d5c1STitus Rwantare break;
6143746d5c1STitus Rwantare
6153746d5c1STitus Rwantare case PMBUS_IOUT_OC_LV_FAULT_LIMIT: /* R/W word */
6163746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_IOUT) {
6173746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].iout_oc_lv_fault_limit);
6183746d5c1STitus Rwantare } else {
6193746d5c1STitus Rwantare goto passthough;
6203746d5c1STitus Rwantare }
6213746d5c1STitus Rwantare break;
6223746d5c1STitus Rwantare
6233746d5c1STitus Rwantare case PMBUS_IOUT_OC_LV_FAULT_RESPONSE: /* R/W byte */
6243746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_IOUT) {
6253746d5c1STitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].iout_oc_lv_fault_response);
6263746d5c1STitus Rwantare } else {
6273746d5c1STitus Rwantare goto passthough;
6283746d5c1STitus Rwantare }
6293746d5c1STitus Rwantare break;
6303746d5c1STitus Rwantare
6313746d5c1STitus Rwantare case PMBUS_IOUT_OC_WARN_LIMIT: /* R/W word */
6323746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_IOUT) {
6333746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].iout_oc_warn_limit);
6343746d5c1STitus Rwantare } else {
6353746d5c1STitus Rwantare goto passthough;
6363746d5c1STitus Rwantare }
6373746d5c1STitus Rwantare break;
6383746d5c1STitus Rwantare
6393746d5c1STitus Rwantare case PMBUS_IOUT_UC_FAULT_LIMIT: /* R/W word */
6403746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_IOUT) {
6413746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].iout_uc_fault_limit);
6423746d5c1STitus Rwantare } else {
6433746d5c1STitus Rwantare goto passthough;
6443746d5c1STitus Rwantare }
6453746d5c1STitus Rwantare break;
6463746d5c1STitus Rwantare
6473746d5c1STitus Rwantare case PMBUS_IOUT_UC_FAULT_RESPONSE: /* R/W byte */
6483746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_IOUT) {
6493746d5c1STitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].iout_uc_fault_response);
6503746d5c1STitus Rwantare } else {
6513746d5c1STitus Rwantare goto passthough;
6523746d5c1STitus Rwantare }
6533746d5c1STitus Rwantare break;
6543746d5c1STitus Rwantare
6553746d5c1STitus Rwantare case PMBUS_OT_FAULT_LIMIT: /* R/W word */
6563746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_TEMPERATURE) {
6573746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].ot_fault_limit);
6583746d5c1STitus Rwantare } else {
6593746d5c1STitus Rwantare goto passthough;
6603746d5c1STitus Rwantare }
6613746d5c1STitus Rwantare break;
6623746d5c1STitus Rwantare
6633746d5c1STitus Rwantare case PMBUS_OT_FAULT_RESPONSE: /* R/W byte */
6643746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_TEMPERATURE) {
6653746d5c1STitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].ot_fault_response);
6663746d5c1STitus Rwantare } else {
6673746d5c1STitus Rwantare goto passthough;
6683746d5c1STitus Rwantare }
6693746d5c1STitus Rwantare break;
6703746d5c1STitus Rwantare
6713746d5c1STitus Rwantare case PMBUS_OT_WARN_LIMIT: /* R/W word */
6723746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_TEMPERATURE) {
6733746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].ot_warn_limit);
6743746d5c1STitus Rwantare } else {
6753746d5c1STitus Rwantare goto passthough;
6763746d5c1STitus Rwantare }
6773746d5c1STitus Rwantare break;
6783746d5c1STitus Rwantare
6793746d5c1STitus Rwantare case PMBUS_UT_WARN_LIMIT: /* R/W word */
6803746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_TEMPERATURE) {
6813746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].ut_warn_limit);
6823746d5c1STitus Rwantare } else {
6833746d5c1STitus Rwantare goto passthough;
6843746d5c1STitus Rwantare }
6853746d5c1STitus Rwantare break;
6863746d5c1STitus Rwantare
6873746d5c1STitus Rwantare case PMBUS_UT_FAULT_LIMIT: /* R/W word */
6883746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_TEMPERATURE) {
6893746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].ut_fault_limit);
6903746d5c1STitus Rwantare } else {
6913746d5c1STitus Rwantare goto passthough;
6923746d5c1STitus Rwantare }
6933746d5c1STitus Rwantare break;
6943746d5c1STitus Rwantare
6953746d5c1STitus Rwantare case PMBUS_UT_FAULT_RESPONSE: /* R/W byte */
6963746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_TEMPERATURE) {
6973746d5c1STitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].ut_fault_response);
6983746d5c1STitus Rwantare } else {
6993746d5c1STitus Rwantare goto passthough;
7003746d5c1STitus Rwantare }
7013746d5c1STitus Rwantare break;
7023746d5c1STitus Rwantare
7033746d5c1STitus Rwantare case PMBUS_VIN_OV_FAULT_LIMIT: /* R/W word */
7043746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VIN) {
7053746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].vin_ov_fault_limit);
7063746d5c1STitus Rwantare } else {
7073746d5c1STitus Rwantare goto passthough;
7083746d5c1STitus Rwantare }
7093746d5c1STitus Rwantare break;
7103746d5c1STitus Rwantare
7113746d5c1STitus Rwantare case PMBUS_VIN_OV_FAULT_RESPONSE: /* R/W byte */
7123746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VIN) {
7133746d5c1STitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].vin_ov_fault_response);
7143746d5c1STitus Rwantare } else {
7153746d5c1STitus Rwantare goto passthough;
7163746d5c1STitus Rwantare }
7173746d5c1STitus Rwantare break;
7183746d5c1STitus Rwantare
7193746d5c1STitus Rwantare case PMBUS_VIN_OV_WARN_LIMIT: /* R/W word */
7203746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VIN) {
7213746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].vin_ov_warn_limit);
7223746d5c1STitus Rwantare } else {
7233746d5c1STitus Rwantare goto passthough;
7243746d5c1STitus Rwantare }
7253746d5c1STitus Rwantare break;
7263746d5c1STitus Rwantare
7273746d5c1STitus Rwantare case PMBUS_VIN_UV_WARN_LIMIT: /* R/W word */
7283746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VIN) {
7293746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].vin_uv_warn_limit);
7303746d5c1STitus Rwantare } else {
7313746d5c1STitus Rwantare goto passthough;
7323746d5c1STitus Rwantare }
7333746d5c1STitus Rwantare break;
7343746d5c1STitus Rwantare
7353746d5c1STitus Rwantare case PMBUS_VIN_UV_FAULT_LIMIT: /* R/W word */
7363746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VIN) {
7373746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].vin_uv_fault_limit);
7383746d5c1STitus Rwantare } else {
7393746d5c1STitus Rwantare goto passthough;
7403746d5c1STitus Rwantare }
7413746d5c1STitus Rwantare break;
7423746d5c1STitus Rwantare
7433746d5c1STitus Rwantare case PMBUS_VIN_UV_FAULT_RESPONSE: /* R/W byte */
7443746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VIN) {
7453746d5c1STitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].vin_uv_fault_response);
7463746d5c1STitus Rwantare } else {
7473746d5c1STitus Rwantare goto passthough;
7483746d5c1STitus Rwantare }
7493746d5c1STitus Rwantare break;
7503746d5c1STitus Rwantare
7513746d5c1STitus Rwantare case PMBUS_IIN_OC_FAULT_LIMIT: /* R/W word */
7523746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_IIN) {
7533746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].iin_oc_fault_limit);
7543746d5c1STitus Rwantare } else {
7553746d5c1STitus Rwantare goto passthough;
7563746d5c1STitus Rwantare }
7573746d5c1STitus Rwantare break;
7583746d5c1STitus Rwantare
7593746d5c1STitus Rwantare case PMBUS_IIN_OC_FAULT_RESPONSE: /* R/W byte */
7603746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_IIN) {
7613746d5c1STitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].iin_oc_fault_response);
7623746d5c1STitus Rwantare } else {
7633746d5c1STitus Rwantare goto passthough;
7643746d5c1STitus Rwantare }
7653746d5c1STitus Rwantare break;
7663746d5c1STitus Rwantare
7673746d5c1STitus Rwantare case PMBUS_IIN_OC_WARN_LIMIT: /* R/W word */
7683746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_IIN) {
7693746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].iin_oc_warn_limit);
7703746d5c1STitus Rwantare } else {
7713746d5c1STitus Rwantare goto passthough;
7723746d5c1STitus Rwantare }
7733746d5c1STitus Rwantare break;
7743746d5c1STitus Rwantare
7753746d5c1STitus Rwantare case PMBUS_POUT_OP_FAULT_LIMIT: /* R/W word */
7763746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_POUT) {
7773746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].pout_op_fault_limit);
7783746d5c1STitus Rwantare } else {
7793746d5c1STitus Rwantare goto passthough;
7803746d5c1STitus Rwantare }
7813746d5c1STitus Rwantare break;
7823746d5c1STitus Rwantare
7833746d5c1STitus Rwantare case PMBUS_POUT_OP_FAULT_RESPONSE: /* R/W byte */
7843746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_POUT) {
7853746d5c1STitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].pout_op_fault_response);
7863746d5c1STitus Rwantare } else {
7873746d5c1STitus Rwantare goto passthough;
7883746d5c1STitus Rwantare }
7893746d5c1STitus Rwantare break;
7903746d5c1STitus Rwantare
7913746d5c1STitus Rwantare case PMBUS_POUT_OP_WARN_LIMIT: /* R/W word */
7923746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_POUT) {
7933746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].pout_op_warn_limit);
7943746d5c1STitus Rwantare } else {
7953746d5c1STitus Rwantare goto passthough;
7963746d5c1STitus Rwantare }
7973746d5c1STitus Rwantare break;
7983746d5c1STitus Rwantare
7993746d5c1STitus Rwantare case PMBUS_PIN_OP_WARN_LIMIT: /* R/W word */
8003746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_PIN) {
8013746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].pin_op_warn_limit);
8023746d5c1STitus Rwantare } else {
8033746d5c1STitus Rwantare goto passthough;
8043746d5c1STitus Rwantare }
8053746d5c1STitus Rwantare break;
8063746d5c1STitus Rwantare
8073746d5c1STitus Rwantare case PMBUS_STATUS_BYTE: /* R/W byte */
8083746d5c1STitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].status_word & 0xFF);
8093746d5c1STitus Rwantare break;
8103746d5c1STitus Rwantare
8113746d5c1STitus Rwantare case PMBUS_STATUS_WORD: /* R/W word */
8123746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].status_word);
8133746d5c1STitus Rwantare break;
8143746d5c1STitus Rwantare
8153746d5c1STitus Rwantare case PMBUS_STATUS_VOUT: /* R/W byte */
8163746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
8173746d5c1STitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].status_vout);
8183746d5c1STitus Rwantare } else {
8193746d5c1STitus Rwantare goto passthough;
8203746d5c1STitus Rwantare }
8213746d5c1STitus Rwantare break;
8223746d5c1STitus Rwantare
8233746d5c1STitus Rwantare case PMBUS_STATUS_IOUT: /* R/W byte */
8243746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_IOUT) {
8253746d5c1STitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].status_iout);
8263746d5c1STitus Rwantare } else {
8273746d5c1STitus Rwantare goto passthough;
8283746d5c1STitus Rwantare }
8293746d5c1STitus Rwantare break;
8303746d5c1STitus Rwantare
8313746d5c1STitus Rwantare case PMBUS_STATUS_INPUT: /* R/W byte */
8323746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VIN ||
8333746d5c1STitus Rwantare pmdev->pages[index].page_flags & PB_HAS_IIN ||
8343746d5c1STitus Rwantare pmdev->pages[index].page_flags & PB_HAS_PIN) {
8353746d5c1STitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].status_input);
8363746d5c1STitus Rwantare } else {
8373746d5c1STitus Rwantare goto passthough;
8383746d5c1STitus Rwantare }
8393746d5c1STitus Rwantare break;
8403746d5c1STitus Rwantare
8413746d5c1STitus Rwantare case PMBUS_STATUS_TEMPERATURE: /* R/W byte */
8423746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_TEMPERATURE) {
8433746d5c1STitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].status_temperature);
8443746d5c1STitus Rwantare } else {
8453746d5c1STitus Rwantare goto passthough;
8463746d5c1STitus Rwantare }
8473746d5c1STitus Rwantare break;
8483746d5c1STitus Rwantare
8493746d5c1STitus Rwantare case PMBUS_STATUS_CML: /* R/W byte */
8503746d5c1STitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].status_cml);
8513746d5c1STitus Rwantare break;
8523746d5c1STitus Rwantare
8533746d5c1STitus Rwantare case PMBUS_STATUS_OTHER: /* R/W byte */
8543746d5c1STitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].status_other);
8553746d5c1STitus Rwantare break;
8563746d5c1STitus Rwantare
85732480293STitus Rwantare case PMBUS_STATUS_MFR_SPECIFIC: /* R/W byte */
85832480293STitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].status_mfr_specific);
85932480293STitus Rwantare break;
86032480293STitus Rwantare
861b7fba25eSTitus Rwantare case PMBUS_STATUS_FANS_1_2: /* R/W byte */
862b7fba25eSTitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_FAN) {
863b7fba25eSTitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].status_fans_1_2);
864b7fba25eSTitus Rwantare } else {
865b7fba25eSTitus Rwantare goto passthough;
866b7fba25eSTitus Rwantare }
867b7fba25eSTitus Rwantare break;
868b7fba25eSTitus Rwantare
869b7fba25eSTitus Rwantare case PMBUS_STATUS_FANS_3_4: /* R/W byte */
870b7fba25eSTitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_FAN) {
871b7fba25eSTitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].status_fans_3_4);
872b7fba25eSTitus Rwantare } else {
873b7fba25eSTitus Rwantare goto passthough;
874b7fba25eSTitus Rwantare }
875b7fba25eSTitus Rwantare break;
876b7fba25eSTitus Rwantare
8773746d5c1STitus Rwantare case PMBUS_READ_EIN: /* Read-Only block 5 bytes */
8783746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_EIN) {
8793746d5c1STitus Rwantare pmbus_send(pmdev, pmdev->pages[index].read_ein, 5);
8803746d5c1STitus Rwantare } else {
8813746d5c1STitus Rwantare goto passthough;
8823746d5c1STitus Rwantare }
8833746d5c1STitus Rwantare break;
8843746d5c1STitus Rwantare
8853746d5c1STitus Rwantare case PMBUS_READ_EOUT: /* Read-Only block 5 bytes */
8863746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_EOUT) {
8873746d5c1STitus Rwantare pmbus_send(pmdev, pmdev->pages[index].read_eout, 5);
8883746d5c1STitus Rwantare } else {
8893746d5c1STitus Rwantare goto passthough;
8903746d5c1STitus Rwantare }
8913746d5c1STitus Rwantare break;
8923746d5c1STitus Rwantare
8933746d5c1STitus Rwantare case PMBUS_READ_VIN: /* Read-Only word */
8943746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VIN) {
8953746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].read_vin);
8963746d5c1STitus Rwantare } else {
8973746d5c1STitus Rwantare goto passthough;
8983746d5c1STitus Rwantare }
8993746d5c1STitus Rwantare break;
9003746d5c1STitus Rwantare
9013746d5c1STitus Rwantare case PMBUS_READ_IIN: /* Read-Only word */
9023746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_IIN) {
9033746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].read_iin);
9043746d5c1STitus Rwantare } else {
9053746d5c1STitus Rwantare goto passthough;
9063746d5c1STitus Rwantare }
9073746d5c1STitus Rwantare break;
9083746d5c1STitus Rwantare
9093401b1ddSTitus Rwantare case PMBUS_READ_VCAP: /* Read-Only word */
9103401b1ddSTitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VCAP) {
9113401b1ddSTitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].read_vcap);
9123401b1ddSTitus Rwantare } else {
9133401b1ddSTitus Rwantare goto passthough;
9143401b1ddSTitus Rwantare }
9153401b1ddSTitus Rwantare break;
9163401b1ddSTitus Rwantare
9173746d5c1STitus Rwantare case PMBUS_READ_VOUT: /* Read-Only word */
9183746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
9193746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].read_vout);
9203746d5c1STitus Rwantare } else {
9213746d5c1STitus Rwantare goto passthough;
9223746d5c1STitus Rwantare }
9233746d5c1STitus Rwantare break;
9243746d5c1STitus Rwantare
9253746d5c1STitus Rwantare case PMBUS_READ_IOUT: /* Read-Only word */
9263746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_IOUT) {
9273746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].read_iout);
9283746d5c1STitus Rwantare } else {
9293746d5c1STitus Rwantare goto passthough;
9303746d5c1STitus Rwantare }
9313746d5c1STitus Rwantare break;
9323746d5c1STitus Rwantare
9333746d5c1STitus Rwantare case PMBUS_READ_TEMPERATURE_1: /* Read-Only word */
9343746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_TEMPERATURE) {
9353746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].read_temperature_1);
9363746d5c1STitus Rwantare } else {
9373746d5c1STitus Rwantare goto passthough;
9383746d5c1STitus Rwantare }
9393746d5c1STitus Rwantare break;
9403746d5c1STitus Rwantare
9413746d5c1STitus Rwantare case PMBUS_READ_TEMPERATURE_2: /* Read-Only word */
9423746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_TEMP2) {
9433746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].read_temperature_2);
9443746d5c1STitus Rwantare } else {
9453746d5c1STitus Rwantare goto passthough;
9463746d5c1STitus Rwantare }
9473746d5c1STitus Rwantare break;
9483746d5c1STitus Rwantare
9493746d5c1STitus Rwantare case PMBUS_READ_TEMPERATURE_3: /* Read-Only word */
9503746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_TEMP3) {
9513746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].read_temperature_3);
9523746d5c1STitus Rwantare } else {
9533746d5c1STitus Rwantare goto passthough;
9543746d5c1STitus Rwantare }
9553746d5c1STitus Rwantare break;
9563746d5c1STitus Rwantare
957b7fba25eSTitus Rwantare case PMBUS_READ_FAN_SPEED_1: /* Read-Only word */
958b7fba25eSTitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_FAN) {
959b7fba25eSTitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].read_fan_speed_1);
960b7fba25eSTitus Rwantare } else {
961b7fba25eSTitus Rwantare goto passthough;
962b7fba25eSTitus Rwantare }
963b7fba25eSTitus Rwantare break;
964b7fba25eSTitus Rwantare
965b7fba25eSTitus Rwantare case PMBUS_READ_FAN_SPEED_2: /* Read-Only word */
966b7fba25eSTitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_FAN) {
967b7fba25eSTitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].read_fan_speed_2);
968b7fba25eSTitus Rwantare } else {
969b7fba25eSTitus Rwantare goto passthough;
970b7fba25eSTitus Rwantare }
971b7fba25eSTitus Rwantare break;
972b7fba25eSTitus Rwantare
973b7fba25eSTitus Rwantare case PMBUS_READ_FAN_SPEED_3: /* Read-Only word */
974b7fba25eSTitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_FAN) {
975b7fba25eSTitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].read_fan_speed_3);
976b7fba25eSTitus Rwantare } else {
977b7fba25eSTitus Rwantare goto passthough;
978b7fba25eSTitus Rwantare }
979b7fba25eSTitus Rwantare break;
980b7fba25eSTitus Rwantare
981b7fba25eSTitus Rwantare case PMBUS_READ_FAN_SPEED_4: /* Read-Only word */
982b7fba25eSTitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_FAN) {
983b7fba25eSTitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].read_fan_speed_4);
984b7fba25eSTitus Rwantare } else {
985b7fba25eSTitus Rwantare goto passthough;
986b7fba25eSTitus Rwantare }
987b7fba25eSTitus Rwantare break;
988b7fba25eSTitus Rwantare
989b7fba25eSTitus Rwantare case PMBUS_READ_DUTY_CYCLE: /* Read-Only word */
990b7fba25eSTitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_FAN) {
991b7fba25eSTitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].read_duty_cycle);
992b7fba25eSTitus Rwantare } else {
993b7fba25eSTitus Rwantare goto passthough;
994b7fba25eSTitus Rwantare }
995b7fba25eSTitus Rwantare break;
996b7fba25eSTitus Rwantare
997b7fba25eSTitus Rwantare case PMBUS_READ_FREQUENCY: /* Read-Only word */
998b7fba25eSTitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_FAN) {
999b7fba25eSTitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].read_frequency);
1000b7fba25eSTitus Rwantare } else {
1001b7fba25eSTitus Rwantare goto passthough;
1002b7fba25eSTitus Rwantare }
1003b7fba25eSTitus Rwantare break;
1004b7fba25eSTitus Rwantare
10053746d5c1STitus Rwantare case PMBUS_READ_POUT: /* Read-Only word */
10063746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_POUT) {
10073746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].read_pout);
10083746d5c1STitus Rwantare } else {
10093746d5c1STitus Rwantare goto passthough;
10103746d5c1STitus Rwantare }
10113746d5c1STitus Rwantare break;
10123746d5c1STitus Rwantare
10133746d5c1STitus Rwantare case PMBUS_READ_PIN: /* Read-Only word */
10143746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_PIN) {
10153746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].read_pin);
10163746d5c1STitus Rwantare } else {
10173746d5c1STitus Rwantare goto passthough;
10183746d5c1STitus Rwantare }
10193746d5c1STitus Rwantare break;
10203746d5c1STitus Rwantare
10213746d5c1STitus Rwantare case PMBUS_REVISION: /* Read-Only byte */
10223746d5c1STitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].revision);
10233746d5c1STitus Rwantare break;
10243746d5c1STitus Rwantare
10253746d5c1STitus Rwantare case PMBUS_MFR_ID: /* R/W block */
10263746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_MFR_INFO) {
10273746d5c1STitus Rwantare pmbus_send_string(pmdev, pmdev->pages[index].mfr_id);
10283746d5c1STitus Rwantare } else {
10293746d5c1STitus Rwantare goto passthough;
10303746d5c1STitus Rwantare }
10313746d5c1STitus Rwantare break;
10323746d5c1STitus Rwantare
10333746d5c1STitus Rwantare case PMBUS_MFR_MODEL: /* R/W block */
10343746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_MFR_INFO) {
10353746d5c1STitus Rwantare pmbus_send_string(pmdev, pmdev->pages[index].mfr_model);
10363746d5c1STitus Rwantare } else {
10373746d5c1STitus Rwantare goto passthough;
10383746d5c1STitus Rwantare }
10393746d5c1STitus Rwantare break;
10403746d5c1STitus Rwantare
10413746d5c1STitus Rwantare case PMBUS_MFR_REVISION: /* R/W block */
10423746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_MFR_INFO) {
10433746d5c1STitus Rwantare pmbus_send_string(pmdev, pmdev->pages[index].mfr_revision);
10443746d5c1STitus Rwantare } else {
10453746d5c1STitus Rwantare goto passthough;
10463746d5c1STitus Rwantare }
10473746d5c1STitus Rwantare break;
10483746d5c1STitus Rwantare
10493746d5c1STitus Rwantare case PMBUS_MFR_LOCATION: /* R/W block */
10503746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_MFR_INFO) {
10513746d5c1STitus Rwantare pmbus_send_string(pmdev, pmdev->pages[index].mfr_location);
10523746d5c1STitus Rwantare } else {
10533746d5c1STitus Rwantare goto passthough;
10543746d5c1STitus Rwantare }
10553746d5c1STitus Rwantare break;
10563746d5c1STitus Rwantare
10573746d5c1STitus Rwantare case PMBUS_MFR_VIN_MIN: /* Read-Only word */
10583746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VIN_RATING) {
10593746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].mfr_vin_min);
10603746d5c1STitus Rwantare } else {
10613746d5c1STitus Rwantare goto passthough;
10623746d5c1STitus Rwantare }
10633746d5c1STitus Rwantare break;
10643746d5c1STitus Rwantare
10653746d5c1STitus Rwantare case PMBUS_MFR_VIN_MAX: /* Read-Only word */
10663746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VIN_RATING) {
10673746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].mfr_vin_max);
10683746d5c1STitus Rwantare } else {
10693746d5c1STitus Rwantare goto passthough;
10703746d5c1STitus Rwantare }
10713746d5c1STitus Rwantare break;
10723746d5c1STitus Rwantare
10733746d5c1STitus Rwantare case PMBUS_MFR_IIN_MAX: /* Read-Only word */
10743746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_IIN_RATING) {
10753746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].mfr_iin_max);
10763746d5c1STitus Rwantare } else {
10773746d5c1STitus Rwantare goto passthough;
10783746d5c1STitus Rwantare }
10793746d5c1STitus Rwantare break;
10803746d5c1STitus Rwantare
10813746d5c1STitus Rwantare case PMBUS_MFR_PIN_MAX: /* Read-Only word */
10823746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_PIN_RATING) {
10833746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].mfr_pin_max);
10843746d5c1STitus Rwantare } else {
10853746d5c1STitus Rwantare goto passthough;
10863746d5c1STitus Rwantare }
10873746d5c1STitus Rwantare break;
10883746d5c1STitus Rwantare
10893746d5c1STitus Rwantare case PMBUS_MFR_VOUT_MIN: /* Read-Only word */
10903746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT_RATING) {
10913746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].mfr_vout_min);
10923746d5c1STitus Rwantare } else {
10933746d5c1STitus Rwantare goto passthough;
10943746d5c1STitus Rwantare }
10953746d5c1STitus Rwantare break;
10963746d5c1STitus Rwantare
10973746d5c1STitus Rwantare case PMBUS_MFR_VOUT_MAX: /* Read-Only word */
10983746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT_RATING) {
10993746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].mfr_vout_max);
11003746d5c1STitus Rwantare } else {
11013746d5c1STitus Rwantare goto passthough;
11023746d5c1STitus Rwantare }
11033746d5c1STitus Rwantare break;
11043746d5c1STitus Rwantare
11053746d5c1STitus Rwantare case PMBUS_MFR_IOUT_MAX: /* Read-Only word */
11063746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_IOUT_RATING) {
11073746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].mfr_iout_max);
11083746d5c1STitus Rwantare } else {
11093746d5c1STitus Rwantare goto passthough;
11103746d5c1STitus Rwantare }
11113746d5c1STitus Rwantare break;
11123746d5c1STitus Rwantare
11133746d5c1STitus Rwantare case PMBUS_MFR_POUT_MAX: /* Read-Only word */
11143746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_POUT_RATING) {
11153746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].mfr_pout_max);
11163746d5c1STitus Rwantare } else {
11173746d5c1STitus Rwantare goto passthough;
11183746d5c1STitus Rwantare }
11193746d5c1STitus Rwantare break;
11203746d5c1STitus Rwantare
11213746d5c1STitus Rwantare case PMBUS_MFR_MAX_TEMP_1: /* R/W word */
11223746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_TEMP_RATING) {
11233746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].mfr_max_temp_1);
11243746d5c1STitus Rwantare } else {
11253746d5c1STitus Rwantare goto passthough;
11263746d5c1STitus Rwantare }
11273746d5c1STitus Rwantare break;
11283746d5c1STitus Rwantare
11293746d5c1STitus Rwantare case PMBUS_MFR_MAX_TEMP_2: /* R/W word */
11303746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_TEMP_RATING) {
11313746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].mfr_max_temp_2);
11323746d5c1STitus Rwantare } else {
11333746d5c1STitus Rwantare goto passthough;
11343746d5c1STitus Rwantare }
11353746d5c1STitus Rwantare break;
11363746d5c1STitus Rwantare
11373746d5c1STitus Rwantare case PMBUS_MFR_MAX_TEMP_3: /* R/W word */
11383746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_TEMP_RATING) {
11393746d5c1STitus Rwantare pmbus_send16(pmdev, pmdev->pages[index].mfr_max_temp_3);
11403746d5c1STitus Rwantare } else {
11413746d5c1STitus Rwantare goto passthough;
11423746d5c1STitus Rwantare }
11433746d5c1STitus Rwantare break;
11443746d5c1STitus Rwantare
1145d272d141SPeter Delevoryas case PMBUS_IDLE_STATE:
1146d272d141SPeter Delevoryas pmbus_send8(pmdev, PMBUS_ERR_BYTE);
1147d272d141SPeter Delevoryas break;
1148d272d141SPeter Delevoryas
11493746d5c1STitus Rwantare case PMBUS_CLEAR_FAULTS: /* Send Byte */
11503746d5c1STitus Rwantare case PMBUS_PAGE_PLUS_WRITE: /* Block Write-only */
11513746d5c1STitus Rwantare case PMBUS_STORE_DEFAULT_ALL: /* Send Byte */
11523746d5c1STitus Rwantare case PMBUS_RESTORE_DEFAULT_ALL: /* Send Byte */
11533746d5c1STitus Rwantare case PMBUS_STORE_DEFAULT_CODE: /* Write-only Byte */
11543746d5c1STitus Rwantare case PMBUS_RESTORE_DEFAULT_CODE: /* Write-only Byte */
11553746d5c1STitus Rwantare case PMBUS_STORE_USER_ALL: /* Send Byte */
11563746d5c1STitus Rwantare case PMBUS_RESTORE_USER_ALL: /* Send Byte */
11573746d5c1STitus Rwantare case PMBUS_STORE_USER_CODE: /* Write-only Byte */
11583746d5c1STitus Rwantare case PMBUS_RESTORE_USER_CODE: /* Write-only Byte */
11593746d5c1STitus Rwantare case PMBUS_QUERY: /* Write-Only */
11603746d5c1STitus Rwantare qemu_log_mask(LOG_GUEST_ERROR,
11613746d5c1STitus Rwantare "%s: reading from write only register 0x%02x\n",
11623746d5c1STitus Rwantare __func__, pmdev->code);
11633746d5c1STitus Rwantare break;
11643746d5c1STitus Rwantare
11653746d5c1STitus Rwantare passthough:
11663746d5c1STitus Rwantare default:
11673746d5c1STitus Rwantare /* Pass through read request if not handled */
11683746d5c1STitus Rwantare if (pmdc->receive_byte) {
11693746d5c1STitus Rwantare ret = pmdc->receive_byte(pmdev);
11703746d5c1STitus Rwantare }
11713746d5c1STitus Rwantare break;
11723746d5c1STitus Rwantare }
11733746d5c1STitus Rwantare
11743746d5c1STitus Rwantare if (pmdev->out_buf_len != 0) {
11753746d5c1STitus Rwantare ret = pmbus_out_buf_pop(pmdev);
11763746d5c1STitus Rwantare return ret;
11773746d5c1STitus Rwantare }
11783746d5c1STitus Rwantare
11793746d5c1STitus Rwantare return ret;
11803746d5c1STitus Rwantare }
11813746d5c1STitus Rwantare
11823746d5c1STitus Rwantare /*
11833746d5c1STitus Rwantare * PMBus clear faults command applies to all status registers, existing faults
11843746d5c1STitus Rwantare * should separately get re-asserted.
11853746d5c1STitus Rwantare */
pmbus_clear_faults(PMBusDevice * pmdev)11863746d5c1STitus Rwantare static void pmbus_clear_faults(PMBusDevice *pmdev)
11873746d5c1STitus Rwantare {
11883746d5c1STitus Rwantare for (uint8_t i = 0; i < pmdev->num_pages; i++) {
11893746d5c1STitus Rwantare pmdev->pages[i].status_word = 0;
11903746d5c1STitus Rwantare pmdev->pages[i].status_vout = 0;
11913746d5c1STitus Rwantare pmdev->pages[i].status_iout = 0;
11923746d5c1STitus Rwantare pmdev->pages[i].status_input = 0;
11933746d5c1STitus Rwantare pmdev->pages[i].status_temperature = 0;
11943746d5c1STitus Rwantare pmdev->pages[i].status_cml = 0;
11953746d5c1STitus Rwantare pmdev->pages[i].status_other = 0;
11963746d5c1STitus Rwantare pmdev->pages[i].status_mfr_specific = 0;
11973746d5c1STitus Rwantare pmdev->pages[i].status_fans_1_2 = 0;
11983746d5c1STitus Rwantare pmdev->pages[i].status_fans_3_4 = 0;
11993746d5c1STitus Rwantare }
12003746d5c1STitus Rwantare
12013746d5c1STitus Rwantare }
12023746d5c1STitus Rwantare
12033746d5c1STitus Rwantare /*
12043746d5c1STitus Rwantare * PMBus operation is used to turn On and Off PSUs
12053746d5c1STitus Rwantare * Therefore, default value for the Operation should be PB_OP_ON or 0x80
12063746d5c1STitus Rwantare */
pmbus_operation(PMBusDevice * pmdev)12073746d5c1STitus Rwantare static void pmbus_operation(PMBusDevice *pmdev)
12083746d5c1STitus Rwantare {
12093746d5c1STitus Rwantare uint8_t index = pmdev->page;
12103746d5c1STitus Rwantare if ((pmdev->pages[index].operation & PB_OP_ON) == 0) {
12113746d5c1STitus Rwantare pmdev->pages[index].read_vout = 0;
12123746d5c1STitus Rwantare pmdev->pages[index].read_iout = 0;
12133746d5c1STitus Rwantare pmdev->pages[index].read_pout = 0;
12143746d5c1STitus Rwantare return;
12153746d5c1STitus Rwantare }
12163746d5c1STitus Rwantare
12173746d5c1STitus Rwantare if (pmdev->pages[index].operation & (PB_OP_ON | PB_OP_MARGIN_HIGH)) {
12183746d5c1STitus Rwantare pmdev->pages[index].read_vout = pmdev->pages[index].vout_margin_high;
12193746d5c1STitus Rwantare }
12203746d5c1STitus Rwantare
12213746d5c1STitus Rwantare if (pmdev->pages[index].operation & (PB_OP_ON | PB_OP_MARGIN_LOW)) {
12223746d5c1STitus Rwantare pmdev->pages[index].read_vout = pmdev->pages[index].vout_margin_low;
12233746d5c1STitus Rwantare }
12243746d5c1STitus Rwantare pmbus_check_limits(pmdev);
12253746d5c1STitus Rwantare }
12263746d5c1STitus Rwantare
pmbus_write_data(SMBusDevice * smd,uint8_t * buf,uint8_t len)12273746d5c1STitus Rwantare static int pmbus_write_data(SMBusDevice *smd, uint8_t *buf, uint8_t len)
12283746d5c1STitus Rwantare {
12293746d5c1STitus Rwantare PMBusDevice *pmdev = PMBUS_DEVICE(smd);
12303746d5c1STitus Rwantare PMBusDeviceClass *pmdc = PMBUS_DEVICE_GET_CLASS(pmdev);
12313746d5c1STitus Rwantare int ret = 0;
12323746d5c1STitus Rwantare uint8_t index;
12333746d5c1STitus Rwantare
12343746d5c1STitus Rwantare if (len == 0) {
12353746d5c1STitus Rwantare qemu_log_mask(LOG_GUEST_ERROR, "%s: writing empty data\n", __func__);
123638870253STitus Rwantare return PMBUS_ERR_BYTE;
12373746d5c1STitus Rwantare }
12383746d5c1STitus Rwantare
12393746d5c1STitus Rwantare if (!pmdev->pages) { /* allocate memory for pages on first use */
12403746d5c1STitus Rwantare pmbus_pages_alloc(pmdev);
12413746d5c1STitus Rwantare }
12423746d5c1STitus Rwantare
12433746d5c1STitus Rwantare pmdev->in_buf_len = len;
12443746d5c1STitus Rwantare pmdev->in_buf = buf;
12453746d5c1STitus Rwantare
12463746d5c1STitus Rwantare pmdev->code = buf[0]; /* PMBus command code */
124784db503eSTitus Rwantare
124884db503eSTitus Rwantare if (pmdev->code == PMBUS_CLEAR_FAULTS) {
124984db503eSTitus Rwantare pmbus_clear_faults(pmdev);
125084db503eSTitus Rwantare }
125184db503eSTitus Rwantare
12523746d5c1STitus Rwantare if (len == 1) { /* Single length writes are command codes only */
12533746d5c1STitus Rwantare return 0;
12543746d5c1STitus Rwantare }
12553746d5c1STitus Rwantare
12563746d5c1STitus Rwantare if (pmdev->code == PMBUS_PAGE) {
12573746d5c1STitus Rwantare pmdev->page = pmbus_receive8(pmdev);
1258ff051128STitus Rwantare
1259ff051128STitus Rwantare if (pmdev->page > pmdev->num_pages - 1 && pmdev->page != PB_ALL_PAGES) {
1260ff051128STitus Rwantare qemu_log_mask(LOG_GUEST_ERROR,
1261ff051128STitus Rwantare "%s: page %u is out of range\n",
1262ff051128STitus Rwantare __func__, pmdev->page);
1263ff051128STitus Rwantare pmdev->page = 0; /* undefined behaviour - reset to page 0 */
1264ff051128STitus Rwantare pmbus_cml_error(pmdev);
1265ff051128STitus Rwantare return PMBUS_ERR_BYTE;
1266ff051128STitus Rwantare }
12673746d5c1STitus Rwantare return 0;
12683746d5c1STitus Rwantare }
126938870253STitus Rwantare
12703746d5c1STitus Rwantare /* loop through all the pages when 0xFF is received */
12713746d5c1STitus Rwantare if (pmdev->page == PB_ALL_PAGES) {
12723746d5c1STitus Rwantare for (int i = 0; i < pmdev->num_pages; i++) {
12733746d5c1STitus Rwantare pmdev->page = i;
12743746d5c1STitus Rwantare pmbus_write_data(smd, buf, len);
12753746d5c1STitus Rwantare }
12763746d5c1STitus Rwantare pmdev->page = PB_ALL_PAGES;
12773746d5c1STitus Rwantare return 0;
12783746d5c1STitus Rwantare }
12793746d5c1STitus Rwantare
12803746d5c1STitus Rwantare index = pmdev->page;
12813746d5c1STitus Rwantare
12823746d5c1STitus Rwantare switch (pmdev->code) {
12833746d5c1STitus Rwantare case PMBUS_OPERATION: /* R/W byte */
12843746d5c1STitus Rwantare pmdev->pages[index].operation = pmbus_receive8(pmdev);
12853746d5c1STitus Rwantare pmbus_operation(pmdev);
12863746d5c1STitus Rwantare break;
12873746d5c1STitus Rwantare
12883746d5c1STitus Rwantare case PMBUS_ON_OFF_CONFIG: /* R/W byte */
12893746d5c1STitus Rwantare pmdev->pages[index].on_off_config = pmbus_receive8(pmdev);
12903746d5c1STitus Rwantare break;
12913746d5c1STitus Rwantare
12923746d5c1STitus Rwantare case PMBUS_CLEAR_FAULTS: /* Send Byte */
12933746d5c1STitus Rwantare pmbus_clear_faults(pmdev);
12943746d5c1STitus Rwantare break;
12953746d5c1STitus Rwantare
12963746d5c1STitus Rwantare case PMBUS_PHASE: /* R/W byte */
12973746d5c1STitus Rwantare pmdev->pages[index].phase = pmbus_receive8(pmdev);
12983746d5c1STitus Rwantare break;
12993746d5c1STitus Rwantare
13003746d5c1STitus Rwantare case PMBUS_PAGE_PLUS_WRITE: /* Block Write-only */
13013746d5c1STitus Rwantare case PMBUS_WRITE_PROTECT: /* R/W byte */
13023746d5c1STitus Rwantare pmdev->pages[index].write_protect = pmbus_receive8(pmdev);
13033746d5c1STitus Rwantare break;
13043746d5c1STitus Rwantare
13053746d5c1STitus Rwantare case PMBUS_VOUT_MODE: /* R/W byte */
13063746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT_MODE) {
13073746d5c1STitus Rwantare pmdev->pages[index].vout_mode = pmbus_receive8(pmdev);
13083746d5c1STitus Rwantare } else {
13093746d5c1STitus Rwantare goto passthrough;
13103746d5c1STitus Rwantare }
13113746d5c1STitus Rwantare break;
13123746d5c1STitus Rwantare
13133746d5c1STitus Rwantare case PMBUS_VOUT_COMMAND: /* R/W word */
13143746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
13153746d5c1STitus Rwantare pmdev->pages[index].vout_command = pmbus_receive16(pmdev);
13163746d5c1STitus Rwantare } else {
13173746d5c1STitus Rwantare goto passthrough;
13183746d5c1STitus Rwantare }
13193746d5c1STitus Rwantare break;
13203746d5c1STitus Rwantare
13213746d5c1STitus Rwantare case PMBUS_VOUT_TRIM: /* R/W word */
13223746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
13233746d5c1STitus Rwantare pmdev->pages[index].vout_trim = pmbus_receive16(pmdev);
13243746d5c1STitus Rwantare } else {
13253746d5c1STitus Rwantare goto passthrough;
13263746d5c1STitus Rwantare }
13273746d5c1STitus Rwantare break;
13283746d5c1STitus Rwantare
13293746d5c1STitus Rwantare case PMBUS_VOUT_CAL_OFFSET: /* R/W word */
13303746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
13313746d5c1STitus Rwantare pmdev->pages[index].vout_cal_offset = pmbus_receive16(pmdev);
13323746d5c1STitus Rwantare } else {
13333746d5c1STitus Rwantare goto passthrough;
13343746d5c1STitus Rwantare }
13353746d5c1STitus Rwantare break;
13363746d5c1STitus Rwantare
13373746d5c1STitus Rwantare case PMBUS_VOUT_MAX: /* R/W word */
13383746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
13393746d5c1STitus Rwantare pmdev->pages[index].vout_max = pmbus_receive16(pmdev);
13403746d5c1STitus Rwantare } else {
13413746d5c1STitus Rwantare goto passthrough;
13423746d5c1STitus Rwantare }
13433746d5c1STitus Rwantare break;
13443746d5c1STitus Rwantare
13453746d5c1STitus Rwantare case PMBUS_VOUT_MARGIN_HIGH: /* R/W word */
13463746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT_MARGIN) {
13473746d5c1STitus Rwantare pmdev->pages[index].vout_margin_high = pmbus_receive16(pmdev);
13483746d5c1STitus Rwantare } else {
13493746d5c1STitus Rwantare goto passthrough;
13503746d5c1STitus Rwantare }
13513746d5c1STitus Rwantare break;
13523746d5c1STitus Rwantare
13533746d5c1STitus Rwantare case PMBUS_VOUT_MARGIN_LOW: /* R/W word */
13543746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT_MARGIN) {
13553746d5c1STitus Rwantare pmdev->pages[index].vout_margin_low = pmbus_receive16(pmdev);
13563746d5c1STitus Rwantare } else {
13573746d5c1STitus Rwantare goto passthrough;
13583746d5c1STitus Rwantare }
13593746d5c1STitus Rwantare break;
13603746d5c1STitus Rwantare
13613746d5c1STitus Rwantare case PMBUS_VOUT_TRANSITION_RATE: /* R/W word */
13623746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
13633746d5c1STitus Rwantare pmdev->pages[index].vout_transition_rate = pmbus_receive16(pmdev);
13643746d5c1STitus Rwantare } else {
13653746d5c1STitus Rwantare goto passthrough;
13663746d5c1STitus Rwantare }
13673746d5c1STitus Rwantare break;
13683746d5c1STitus Rwantare
13693746d5c1STitus Rwantare case PMBUS_VOUT_DROOP: /* R/W word */
13703746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
13713746d5c1STitus Rwantare pmdev->pages[index].vout_droop = pmbus_receive16(pmdev);
13723746d5c1STitus Rwantare } else {
13733746d5c1STitus Rwantare goto passthrough;
13743746d5c1STitus Rwantare }
13753746d5c1STitus Rwantare break;
13763746d5c1STitus Rwantare
13773746d5c1STitus Rwantare case PMBUS_VOUT_SCALE_LOOP: /* R/W word */
13783746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
13793746d5c1STitus Rwantare pmdev->pages[index].vout_scale_loop = pmbus_receive16(pmdev);
13803746d5c1STitus Rwantare } else {
13813746d5c1STitus Rwantare goto passthrough;
13823746d5c1STitus Rwantare }
13833746d5c1STitus Rwantare break;
13843746d5c1STitus Rwantare
13853746d5c1STitus Rwantare case PMBUS_VOUT_SCALE_MONITOR: /* R/W word */
13863746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
13873746d5c1STitus Rwantare pmdev->pages[index].vout_scale_monitor = pmbus_receive16(pmdev);
13883746d5c1STitus Rwantare } else {
13893746d5c1STitus Rwantare goto passthrough;
13903746d5c1STitus Rwantare }
13913746d5c1STitus Rwantare break;
13923746d5c1STitus Rwantare
139332480293STitus Rwantare case PMBUS_VOUT_MIN: /* R/W word */
139432480293STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT_RATING) {
139532480293STitus Rwantare pmdev->pages[index].vout_min = pmbus_receive16(pmdev);
139632480293STitus Rwantare } else {
139732480293STitus Rwantare goto passthrough;
139832480293STitus Rwantare }
139932480293STitus Rwantare break;
140032480293STitus Rwantare
14013746d5c1STitus Rwantare case PMBUS_POUT_MAX: /* R/W word */
14023746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
14033746d5c1STitus Rwantare pmdev->pages[index].pout_max = pmbus_receive16(pmdev);
14043746d5c1STitus Rwantare } else {
14053746d5c1STitus Rwantare goto passthrough;
14063746d5c1STitus Rwantare }
14073746d5c1STitus Rwantare break;
14083746d5c1STitus Rwantare
14093746d5c1STitus Rwantare case PMBUS_VIN_ON: /* R/W word */
14103746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VIN) {
14113746d5c1STitus Rwantare pmdev->pages[index].vin_on = pmbus_receive16(pmdev);
14123746d5c1STitus Rwantare } else {
14133746d5c1STitus Rwantare goto passthrough;
14143746d5c1STitus Rwantare }
14153746d5c1STitus Rwantare break;
14163746d5c1STitus Rwantare
14173746d5c1STitus Rwantare case PMBUS_VIN_OFF: /* R/W word */
14183746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VIN) {
14193746d5c1STitus Rwantare pmdev->pages[index].vin_off = pmbus_receive16(pmdev);
14203746d5c1STitus Rwantare } else {
14213746d5c1STitus Rwantare goto passthrough;
14223746d5c1STitus Rwantare }
14233746d5c1STitus Rwantare break;
14243746d5c1STitus Rwantare
14253746d5c1STitus Rwantare case PMBUS_IOUT_CAL_GAIN: /* R/W word */
14263746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_IOUT_GAIN) {
14273746d5c1STitus Rwantare pmdev->pages[index].iout_cal_gain = pmbus_receive16(pmdev);
14283746d5c1STitus Rwantare } else {
14293746d5c1STitus Rwantare goto passthrough;
14303746d5c1STitus Rwantare }
14313746d5c1STitus Rwantare break;
14323746d5c1STitus Rwantare
1433b7fba25eSTitus Rwantare case PMBUS_FAN_CONFIG_1_2: /* R/W byte */
1434b7fba25eSTitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_FAN) {
1435b7fba25eSTitus Rwantare pmdev->pages[index].fan_config_1_2 = pmbus_receive8(pmdev);
1436b7fba25eSTitus Rwantare } else {
1437b7fba25eSTitus Rwantare goto passthrough;
1438b7fba25eSTitus Rwantare }
1439b7fba25eSTitus Rwantare break;
1440b7fba25eSTitus Rwantare
1441b7fba25eSTitus Rwantare case PMBUS_FAN_COMMAND_1: /* R/W word */
1442b7fba25eSTitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_FAN) {
1443b7fba25eSTitus Rwantare pmdev->pages[index].fan_command_1 = pmbus_receive16(pmdev);
1444b7fba25eSTitus Rwantare } else {
1445b7fba25eSTitus Rwantare goto passthrough;
1446b7fba25eSTitus Rwantare }
1447b7fba25eSTitus Rwantare break;
1448b7fba25eSTitus Rwantare
1449b7fba25eSTitus Rwantare case PMBUS_FAN_COMMAND_2: /* R/W word */
1450b7fba25eSTitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_FAN) {
1451b7fba25eSTitus Rwantare pmdev->pages[index].fan_command_2 = pmbus_receive16(pmdev);
1452b7fba25eSTitus Rwantare } else {
1453b7fba25eSTitus Rwantare goto passthrough;
1454b7fba25eSTitus Rwantare }
1455b7fba25eSTitus Rwantare break;
1456b7fba25eSTitus Rwantare
1457b7fba25eSTitus Rwantare case PMBUS_FAN_CONFIG_3_4: /* R/W byte */
1458b7fba25eSTitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_FAN) {
1459b7fba25eSTitus Rwantare pmdev->pages[index].fan_config_3_4 = pmbus_receive8(pmdev);
1460b7fba25eSTitus Rwantare } else {
1461b7fba25eSTitus Rwantare goto passthrough;
1462b7fba25eSTitus Rwantare }
1463b7fba25eSTitus Rwantare break;
1464b7fba25eSTitus Rwantare
1465b7fba25eSTitus Rwantare case PMBUS_FAN_COMMAND_3: /* R/W word */
1466b7fba25eSTitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_FAN) {
1467b7fba25eSTitus Rwantare pmdev->pages[index].fan_command_3 = pmbus_receive16(pmdev);
1468b7fba25eSTitus Rwantare } else {
1469b7fba25eSTitus Rwantare goto passthrough;
1470b7fba25eSTitus Rwantare }
1471b7fba25eSTitus Rwantare break;
1472b7fba25eSTitus Rwantare
1473b7fba25eSTitus Rwantare case PMBUS_FAN_COMMAND_4: /* R/W word */
1474b7fba25eSTitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_FAN) {
1475b7fba25eSTitus Rwantare pmdev->pages[index].fan_command_4 = pmbus_receive16(pmdev);
1476b7fba25eSTitus Rwantare } else {
1477b7fba25eSTitus Rwantare goto passthrough;
1478b7fba25eSTitus Rwantare }
1479b7fba25eSTitus Rwantare break;
1480b7fba25eSTitus Rwantare
14813746d5c1STitus Rwantare case PMBUS_VOUT_OV_FAULT_LIMIT: /* R/W word */
14823746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
14833746d5c1STitus Rwantare pmdev->pages[index].vout_ov_fault_limit = pmbus_receive16(pmdev);
14843746d5c1STitus Rwantare } else {
14853746d5c1STitus Rwantare goto passthrough;
14863746d5c1STitus Rwantare }
14873746d5c1STitus Rwantare break;
14883746d5c1STitus Rwantare
14893746d5c1STitus Rwantare case PMBUS_VOUT_OV_FAULT_RESPONSE: /* R/W byte */
14903746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
14913746d5c1STitus Rwantare pmdev->pages[index].vout_ov_fault_response = pmbus_receive8(pmdev);
14923746d5c1STitus Rwantare } else {
14933746d5c1STitus Rwantare goto passthrough;
14943746d5c1STitus Rwantare }
14953746d5c1STitus Rwantare break;
14963746d5c1STitus Rwantare
14973746d5c1STitus Rwantare case PMBUS_VOUT_OV_WARN_LIMIT: /* R/W word */
14983746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
14993746d5c1STitus Rwantare pmdev->pages[index].vout_ov_warn_limit = pmbus_receive16(pmdev);
15003746d5c1STitus Rwantare } else {
15013746d5c1STitus Rwantare goto passthrough;
15023746d5c1STitus Rwantare }
15033746d5c1STitus Rwantare break;
15043746d5c1STitus Rwantare
15053746d5c1STitus Rwantare case PMBUS_VOUT_UV_WARN_LIMIT: /* R/W word */
15063746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
15073746d5c1STitus Rwantare pmdev->pages[index].vout_uv_warn_limit = pmbus_receive16(pmdev);
15083746d5c1STitus Rwantare } else {
15093746d5c1STitus Rwantare goto passthrough;
15103746d5c1STitus Rwantare }
15113746d5c1STitus Rwantare break;
15123746d5c1STitus Rwantare
15133746d5c1STitus Rwantare case PMBUS_VOUT_UV_FAULT_LIMIT: /* R/W word */
15143746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
15153746d5c1STitus Rwantare pmdev->pages[index].vout_uv_fault_limit = pmbus_receive16(pmdev);
15163746d5c1STitus Rwantare } else {
15173746d5c1STitus Rwantare goto passthrough;
15183746d5c1STitus Rwantare }
15193746d5c1STitus Rwantare break;
15203746d5c1STitus Rwantare
15213746d5c1STitus Rwantare case PMBUS_VOUT_UV_FAULT_RESPONSE: /* R/W byte */
15223746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
15233746d5c1STitus Rwantare pmdev->pages[index].vout_uv_fault_response = pmbus_receive8(pmdev);
15243746d5c1STitus Rwantare } else {
15253746d5c1STitus Rwantare goto passthrough;
15263746d5c1STitus Rwantare }
15273746d5c1STitus Rwantare break;
15283746d5c1STitus Rwantare
15293746d5c1STitus Rwantare case PMBUS_IOUT_OC_FAULT_LIMIT: /* R/W word */
15303746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_IOUT) {
15313746d5c1STitus Rwantare pmdev->pages[index].iout_oc_fault_limit = pmbus_receive16(pmdev);
15323746d5c1STitus Rwantare } else {
15333746d5c1STitus Rwantare goto passthrough;
15343746d5c1STitus Rwantare }
15353746d5c1STitus Rwantare break;
15363746d5c1STitus Rwantare
15373746d5c1STitus Rwantare case PMBUS_IOUT_OC_FAULT_RESPONSE: /* R/W byte */
15383746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_IOUT) {
15393746d5c1STitus Rwantare pmdev->pages[index].iout_oc_fault_response = pmbus_receive8(pmdev);
15403746d5c1STitus Rwantare } else {
15413746d5c1STitus Rwantare goto passthrough;
15423746d5c1STitus Rwantare }
15433746d5c1STitus Rwantare break;
15443746d5c1STitus Rwantare
15453746d5c1STitus Rwantare case PMBUS_IOUT_OC_LV_FAULT_LIMIT: /* R/W word */
15463746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_IOUT) {
15473746d5c1STitus Rwantare pmdev->pages[index].iout_oc_lv_fault_limit = pmbus_receive16(pmdev);
15483746d5c1STitus Rwantare } else {
15493746d5c1STitus Rwantare goto passthrough;
15503746d5c1STitus Rwantare }
15513746d5c1STitus Rwantare break;
15523746d5c1STitus Rwantare
15533746d5c1STitus Rwantare case PMBUS_IOUT_OC_LV_FAULT_RESPONSE: /* R/W byte */
15543746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_IOUT) {
15553746d5c1STitus Rwantare pmdev->pages[index].iout_oc_lv_fault_response
15563746d5c1STitus Rwantare = pmbus_receive8(pmdev);
15573746d5c1STitus Rwantare } else {
15583746d5c1STitus Rwantare goto passthrough;
15593746d5c1STitus Rwantare }
15603746d5c1STitus Rwantare break;
15613746d5c1STitus Rwantare
15623746d5c1STitus Rwantare case PMBUS_IOUT_OC_WARN_LIMIT: /* R/W word */
15633746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_IOUT) {
15643746d5c1STitus Rwantare pmdev->pages[index].iout_oc_warn_limit = pmbus_receive16(pmdev);
15653746d5c1STitus Rwantare } else {
15663746d5c1STitus Rwantare goto passthrough;
15673746d5c1STitus Rwantare }
15683746d5c1STitus Rwantare break;
15693746d5c1STitus Rwantare
15703746d5c1STitus Rwantare case PMBUS_IOUT_UC_FAULT_LIMIT: /* R/W word */
15713746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_IOUT) {
15723746d5c1STitus Rwantare pmdev->pages[index].iout_uc_fault_limit = pmbus_receive16(pmdev);
15733746d5c1STitus Rwantare } else {
15743746d5c1STitus Rwantare goto passthrough;
15753746d5c1STitus Rwantare }
15763746d5c1STitus Rwantare break;
15773746d5c1STitus Rwantare
15783746d5c1STitus Rwantare case PMBUS_IOUT_UC_FAULT_RESPONSE: /* R/W byte */
15793746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_IOUT) {
15803746d5c1STitus Rwantare pmdev->pages[index].iout_uc_fault_response = pmbus_receive8(pmdev);
15813746d5c1STitus Rwantare } else {
15823746d5c1STitus Rwantare goto passthrough;
15833746d5c1STitus Rwantare }
15843746d5c1STitus Rwantare break;
15853746d5c1STitus Rwantare
15863746d5c1STitus Rwantare case PMBUS_OT_FAULT_LIMIT: /* R/W word */
15873746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_TEMPERATURE) {
15883746d5c1STitus Rwantare pmdev->pages[index].ot_fault_limit = pmbus_receive16(pmdev);
15893746d5c1STitus Rwantare } else {
15903746d5c1STitus Rwantare goto passthrough;
15913746d5c1STitus Rwantare }
15923746d5c1STitus Rwantare break;
15933746d5c1STitus Rwantare
15943746d5c1STitus Rwantare case PMBUS_OT_FAULT_RESPONSE: /* R/W byte */
15953746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_TEMPERATURE) {
15963746d5c1STitus Rwantare pmdev->pages[index].ot_fault_response = pmbus_receive8(pmdev);
15973746d5c1STitus Rwantare } else {
15983746d5c1STitus Rwantare goto passthrough;
15993746d5c1STitus Rwantare }
16003746d5c1STitus Rwantare break;
16013746d5c1STitus Rwantare
16023746d5c1STitus Rwantare case PMBUS_OT_WARN_LIMIT: /* R/W word */
16033746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_TEMPERATURE) {
16043746d5c1STitus Rwantare pmdev->pages[index].ot_warn_limit = pmbus_receive16(pmdev);
16053746d5c1STitus Rwantare } else {
16063746d5c1STitus Rwantare goto passthrough;
16073746d5c1STitus Rwantare }
16083746d5c1STitus Rwantare break;
16093746d5c1STitus Rwantare
16103746d5c1STitus Rwantare case PMBUS_UT_WARN_LIMIT: /* R/W word */
16113746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_TEMPERATURE) {
16123746d5c1STitus Rwantare pmdev->pages[index].ut_warn_limit = pmbus_receive16(pmdev);
16133746d5c1STitus Rwantare } else {
16143746d5c1STitus Rwantare goto passthrough;
16153746d5c1STitus Rwantare }
16163746d5c1STitus Rwantare break;
16173746d5c1STitus Rwantare
16183746d5c1STitus Rwantare case PMBUS_UT_FAULT_LIMIT: /* R/W word */
16193746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_TEMPERATURE) {
16203746d5c1STitus Rwantare pmdev->pages[index].ut_fault_limit = pmbus_receive16(pmdev);
16213746d5c1STitus Rwantare } else {
16223746d5c1STitus Rwantare goto passthrough;
16233746d5c1STitus Rwantare }
16243746d5c1STitus Rwantare break;
16253746d5c1STitus Rwantare
16263746d5c1STitus Rwantare case PMBUS_UT_FAULT_RESPONSE: /* R/W byte */
16273746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_TEMPERATURE) {
16283746d5c1STitus Rwantare pmdev->pages[index].ut_fault_response = pmbus_receive8(pmdev);
16293746d5c1STitus Rwantare } else {
16303746d5c1STitus Rwantare goto passthrough;
16313746d5c1STitus Rwantare }
16323746d5c1STitus Rwantare break;
16333746d5c1STitus Rwantare
16343746d5c1STitus Rwantare case PMBUS_VIN_OV_FAULT_LIMIT: /* R/W word */
16353746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VIN) {
16363746d5c1STitus Rwantare pmdev->pages[index].vin_ov_fault_limit = pmbus_receive16(pmdev);
16373746d5c1STitus Rwantare } else {
16383746d5c1STitus Rwantare goto passthrough;
16393746d5c1STitus Rwantare }
16403746d5c1STitus Rwantare break;
16413746d5c1STitus Rwantare
16423746d5c1STitus Rwantare case PMBUS_VIN_OV_FAULT_RESPONSE: /* R/W byte */
16433746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VIN) {
16443746d5c1STitus Rwantare pmdev->pages[index].vin_ov_fault_response = pmbus_receive8(pmdev);
16453746d5c1STitus Rwantare } else {
16463746d5c1STitus Rwantare goto passthrough;
16473746d5c1STitus Rwantare }
16483746d5c1STitus Rwantare break;
16493746d5c1STitus Rwantare
16503746d5c1STitus Rwantare case PMBUS_VIN_OV_WARN_LIMIT: /* R/W word */
16513746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VIN) {
16523746d5c1STitus Rwantare pmdev->pages[index].vin_ov_warn_limit = pmbus_receive16(pmdev);
16533746d5c1STitus Rwantare } else {
16543746d5c1STitus Rwantare goto passthrough;
16553746d5c1STitus Rwantare }
16563746d5c1STitus Rwantare break;
16573746d5c1STitus Rwantare
16583746d5c1STitus Rwantare case PMBUS_VIN_UV_WARN_LIMIT: /* R/W word */
16593746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VIN) {
16603746d5c1STitus Rwantare pmdev->pages[index].vin_uv_warn_limit = pmbus_receive16(pmdev);
16613746d5c1STitus Rwantare } else {
16623746d5c1STitus Rwantare goto passthrough;
16633746d5c1STitus Rwantare }
16643746d5c1STitus Rwantare break;
16653746d5c1STitus Rwantare
16663746d5c1STitus Rwantare case PMBUS_VIN_UV_FAULT_LIMIT: /* R/W word */
16673746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VIN) {
16683746d5c1STitus Rwantare pmdev->pages[index].vin_uv_fault_limit = pmbus_receive16(pmdev);
16693746d5c1STitus Rwantare } else {
16703746d5c1STitus Rwantare goto passthrough;
16713746d5c1STitus Rwantare }
16723746d5c1STitus Rwantare break;
16733746d5c1STitus Rwantare
16743746d5c1STitus Rwantare case PMBUS_VIN_UV_FAULT_RESPONSE: /* R/W byte */
16753746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VIN) {
16763746d5c1STitus Rwantare pmdev->pages[index].vin_uv_fault_response = pmbus_receive8(pmdev);
16773746d5c1STitus Rwantare } else {
16783746d5c1STitus Rwantare goto passthrough;
16793746d5c1STitus Rwantare }
16803746d5c1STitus Rwantare break;
16813746d5c1STitus Rwantare
16823746d5c1STitus Rwantare case PMBUS_IIN_OC_FAULT_LIMIT: /* R/W word */
16833746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_IIN) {
16843746d5c1STitus Rwantare pmdev->pages[index].iin_oc_fault_limit = pmbus_receive16(pmdev);
16853746d5c1STitus Rwantare } else {
16863746d5c1STitus Rwantare goto passthrough;
16873746d5c1STitus Rwantare }
16883746d5c1STitus Rwantare break;
16893746d5c1STitus Rwantare
16903746d5c1STitus Rwantare case PMBUS_IIN_OC_FAULT_RESPONSE: /* R/W byte */
16913746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_IIN) {
16923746d5c1STitus Rwantare pmdev->pages[index].iin_oc_fault_response = pmbus_receive8(pmdev);
16933746d5c1STitus Rwantare } else {
16943746d5c1STitus Rwantare goto passthrough;
16953746d5c1STitus Rwantare }
16963746d5c1STitus Rwantare break;
16973746d5c1STitus Rwantare
16983746d5c1STitus Rwantare case PMBUS_IIN_OC_WARN_LIMIT: /* R/W word */
16993746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_IIN) {
17003746d5c1STitus Rwantare pmdev->pages[index].iin_oc_warn_limit = pmbus_receive16(pmdev);
17013746d5c1STitus Rwantare } else {
17023746d5c1STitus Rwantare goto passthrough;
17033746d5c1STitus Rwantare }
17043746d5c1STitus Rwantare break;
17053746d5c1STitus Rwantare
17063746d5c1STitus Rwantare case PMBUS_POUT_OP_FAULT_LIMIT: /* R/W word */
17073746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
17083746d5c1STitus Rwantare pmdev->pages[index].pout_op_fault_limit = pmbus_receive16(pmdev);
17093746d5c1STitus Rwantare } else {
17103746d5c1STitus Rwantare goto passthrough;
17113746d5c1STitus Rwantare }
17123746d5c1STitus Rwantare break;
17133746d5c1STitus Rwantare
17143746d5c1STitus Rwantare case PMBUS_POUT_OP_FAULT_RESPONSE: /* R/W byte */
17153746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
17163746d5c1STitus Rwantare pmdev->pages[index].pout_op_fault_response = pmbus_receive8(pmdev);
17173746d5c1STitus Rwantare } else {
17183746d5c1STitus Rwantare goto passthrough;
17193746d5c1STitus Rwantare }
17203746d5c1STitus Rwantare break;
17213746d5c1STitus Rwantare
17223746d5c1STitus Rwantare case PMBUS_POUT_OP_WARN_LIMIT: /* R/W word */
17233746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
17243746d5c1STitus Rwantare pmdev->pages[index].pout_op_warn_limit = pmbus_receive16(pmdev);
17253746d5c1STitus Rwantare } else {
17263746d5c1STitus Rwantare goto passthrough;
17273746d5c1STitus Rwantare }
17283746d5c1STitus Rwantare break;
17293746d5c1STitus Rwantare
17303746d5c1STitus Rwantare case PMBUS_PIN_OP_WARN_LIMIT: /* R/W word */
17313746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_PIN) {
17323746d5c1STitus Rwantare pmdev->pages[index].pin_op_warn_limit = pmbus_receive16(pmdev);
17333746d5c1STitus Rwantare } else {
17343746d5c1STitus Rwantare goto passthrough;
17353746d5c1STitus Rwantare }
17363746d5c1STitus Rwantare break;
17373746d5c1STitus Rwantare
17383746d5c1STitus Rwantare case PMBUS_STATUS_BYTE: /* R/W byte */
17393746d5c1STitus Rwantare pmdev->pages[index].status_word = pmbus_receive8(pmdev);
17403746d5c1STitus Rwantare break;
17413746d5c1STitus Rwantare
17423746d5c1STitus Rwantare case PMBUS_STATUS_WORD: /* R/W word */
17433746d5c1STitus Rwantare pmdev->pages[index].status_word = pmbus_receive16(pmdev);
17443746d5c1STitus Rwantare break;
17453746d5c1STitus Rwantare
17463746d5c1STitus Rwantare case PMBUS_STATUS_VOUT: /* R/W byte */
17473746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_VOUT) {
17483746d5c1STitus Rwantare pmdev->pages[index].status_vout = pmbus_receive8(pmdev);
17493746d5c1STitus Rwantare } else {
17503746d5c1STitus Rwantare goto passthrough;
17513746d5c1STitus Rwantare }
17523746d5c1STitus Rwantare break;
17533746d5c1STitus Rwantare
17543746d5c1STitus Rwantare case PMBUS_STATUS_IOUT: /* R/W byte */
17553746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_IOUT) {
17563746d5c1STitus Rwantare pmdev->pages[index].status_iout = pmbus_receive8(pmdev);
17573746d5c1STitus Rwantare } else {
17583746d5c1STitus Rwantare goto passthrough;
17593746d5c1STitus Rwantare }
17603746d5c1STitus Rwantare break;
17613746d5c1STitus Rwantare
17623746d5c1STitus Rwantare case PMBUS_STATUS_INPUT: /* R/W byte */
17633746d5c1STitus Rwantare pmdev->pages[index].status_input = pmbus_receive8(pmdev);
17643746d5c1STitus Rwantare break;
17653746d5c1STitus Rwantare
17663746d5c1STitus Rwantare case PMBUS_STATUS_TEMPERATURE: /* R/W byte */
17673746d5c1STitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_TEMPERATURE) {
17683746d5c1STitus Rwantare pmdev->pages[index].status_temperature = pmbus_receive8(pmdev);
17693746d5c1STitus Rwantare } else {
17703746d5c1STitus Rwantare goto passthrough;
17713746d5c1STitus Rwantare }
17723746d5c1STitus Rwantare break;
17733746d5c1STitus Rwantare
17743746d5c1STitus Rwantare case PMBUS_STATUS_CML: /* R/W byte */
17753746d5c1STitus Rwantare pmdev->pages[index].status_cml = pmbus_receive8(pmdev);
17763746d5c1STitus Rwantare break;
17773746d5c1STitus Rwantare
17783746d5c1STitus Rwantare case PMBUS_STATUS_OTHER: /* R/W byte */
17793746d5c1STitus Rwantare pmdev->pages[index].status_other = pmbus_receive8(pmdev);
17803746d5c1STitus Rwantare break;
17813746d5c1STitus Rwantare
178232480293STitus Rwantare case PMBUS_STATUS_MFR_SPECIFIC: /* R/W byte */
178332480293STitus Rwantare pmdev->pages[index].status_mfr_specific = pmbus_receive8(pmdev);
178432480293STitus Rwantare break;
178532480293STitus Rwantare
1786b7fba25eSTitus Rwantare case PMBUS_STATUS_FANS_1_2: /* R/W byte */
1787b7fba25eSTitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_FAN) {
1788b7fba25eSTitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].status_fans_1_2);
1789b7fba25eSTitus Rwantare } else {
1790b7fba25eSTitus Rwantare goto passthrough;
1791b7fba25eSTitus Rwantare }
1792b7fba25eSTitus Rwantare break;
1793b7fba25eSTitus Rwantare
1794b7fba25eSTitus Rwantare case PMBUS_STATUS_FANS_3_4: /* R/W byte */
1795b7fba25eSTitus Rwantare if (pmdev->pages[index].page_flags & PB_HAS_FAN) {
1796b7fba25eSTitus Rwantare pmbus_send8(pmdev, pmdev->pages[index].status_fans_3_4);
1797b7fba25eSTitus Rwantare } else {
1798b7fba25eSTitus Rwantare goto passthrough;
1799b7fba25eSTitus Rwantare }
1800b7fba25eSTitus Rwantare break;
1801b7fba25eSTitus Rwantare
18023746d5c1STitus Rwantare case PMBUS_PAGE_PLUS_READ: /* Block Read-only */
18033746d5c1STitus Rwantare case PMBUS_CAPABILITY: /* Read-Only byte */
18043746d5c1STitus Rwantare case PMBUS_COEFFICIENTS: /* Read-only block 5 bytes */
18053746d5c1STitus Rwantare case PMBUS_READ_EIN: /* Read-Only block 5 bytes */
18063746d5c1STitus Rwantare case PMBUS_READ_EOUT: /* Read-Only block 5 bytes */
18073746d5c1STitus Rwantare case PMBUS_READ_VIN: /* Read-Only word */
18083746d5c1STitus Rwantare case PMBUS_READ_IIN: /* Read-Only word */
18093746d5c1STitus Rwantare case PMBUS_READ_VCAP: /* Read-Only word */
18103746d5c1STitus Rwantare case PMBUS_READ_VOUT: /* Read-Only word */
18113746d5c1STitus Rwantare case PMBUS_READ_IOUT: /* Read-Only word */
18123746d5c1STitus Rwantare case PMBUS_READ_TEMPERATURE_1: /* Read-Only word */
18133746d5c1STitus Rwantare case PMBUS_READ_TEMPERATURE_2: /* Read-Only word */
18143746d5c1STitus Rwantare case PMBUS_READ_TEMPERATURE_3: /* Read-Only word */
18153746d5c1STitus Rwantare case PMBUS_READ_FAN_SPEED_1: /* Read-Only word */
18163746d5c1STitus Rwantare case PMBUS_READ_FAN_SPEED_2: /* Read-Only word */
18173746d5c1STitus Rwantare case PMBUS_READ_FAN_SPEED_3: /* Read-Only word */
18183746d5c1STitus Rwantare case PMBUS_READ_FAN_SPEED_4: /* Read-Only word */
18193746d5c1STitus Rwantare case PMBUS_READ_DUTY_CYCLE: /* Read-Only word */
18203746d5c1STitus Rwantare case PMBUS_READ_FREQUENCY: /* Read-Only word */
18213746d5c1STitus Rwantare case PMBUS_READ_POUT: /* Read-Only word */
18223746d5c1STitus Rwantare case PMBUS_READ_PIN: /* Read-Only word */
18233746d5c1STitus Rwantare case PMBUS_REVISION: /* Read-Only byte */
18243746d5c1STitus Rwantare case PMBUS_APP_PROFILE_SUPPORT: /* Read-Only block-read */
18253746d5c1STitus Rwantare case PMBUS_MFR_VIN_MIN: /* Read-Only word */
18263746d5c1STitus Rwantare case PMBUS_MFR_VIN_MAX: /* Read-Only word */
18273746d5c1STitus Rwantare case PMBUS_MFR_IIN_MAX: /* Read-Only word */
18283746d5c1STitus Rwantare case PMBUS_MFR_PIN_MAX: /* Read-Only word */
18293746d5c1STitus Rwantare case PMBUS_MFR_VOUT_MIN: /* Read-Only word */
18303746d5c1STitus Rwantare case PMBUS_MFR_VOUT_MAX: /* Read-Only word */
18313746d5c1STitus Rwantare case PMBUS_MFR_IOUT_MAX: /* Read-Only word */
18323746d5c1STitus Rwantare case PMBUS_MFR_POUT_MAX: /* Read-Only word */
18333746d5c1STitus Rwantare case PMBUS_MFR_TAMBIENT_MAX: /* Read-Only word */
18343746d5c1STitus Rwantare case PMBUS_MFR_TAMBIENT_MIN: /* Read-Only word */
18353746d5c1STitus Rwantare case PMBUS_MFR_EFFICIENCY_LL: /* Read-Only block 14 bytes */
18363746d5c1STitus Rwantare case PMBUS_MFR_EFFICIENCY_HL: /* Read-Only block 14 bytes */
18373746d5c1STitus Rwantare case PMBUS_MFR_PIN_ACCURACY: /* Read-Only byte */
18383746d5c1STitus Rwantare case PMBUS_IC_DEVICE_ID: /* Read-Only block-read */
18393746d5c1STitus Rwantare case PMBUS_IC_DEVICE_REV: /* Read-Only block-read */
18403746d5c1STitus Rwantare qemu_log_mask(LOG_GUEST_ERROR,
18413746d5c1STitus Rwantare "%s: writing to read-only register 0x%02x\n",
18423746d5c1STitus Rwantare __func__, pmdev->code);
18433746d5c1STitus Rwantare break;
18443746d5c1STitus Rwantare
18453746d5c1STitus Rwantare passthrough:
18468fa21b80SMichael Tokarev /* Unimplemented registers get passed to the device */
18473746d5c1STitus Rwantare default:
18483746d5c1STitus Rwantare if (pmdc->write_data) {
18493746d5c1STitus Rwantare ret = pmdc->write_data(pmdev, buf, len);
18503746d5c1STitus Rwantare }
18513746d5c1STitus Rwantare break;
18523746d5c1STitus Rwantare }
18533746d5c1STitus Rwantare pmbus_check_limits(pmdev);
18543746d5c1STitus Rwantare pmdev->in_buf_len = 0;
18553746d5c1STitus Rwantare return ret;
18563746d5c1STitus Rwantare }
18573746d5c1STitus Rwantare
pmbus_page_config(PMBusDevice * pmdev,uint8_t index,uint64_t flags)18583746d5c1STitus Rwantare int pmbus_page_config(PMBusDevice *pmdev, uint8_t index, uint64_t flags)
18593746d5c1STitus Rwantare {
18603746d5c1STitus Rwantare if (!pmdev->pages) { /* allocate memory for pages on first use */
18613746d5c1STitus Rwantare pmbus_pages_alloc(pmdev);
18623746d5c1STitus Rwantare }
18633746d5c1STitus Rwantare
18643746d5c1STitus Rwantare /* The 0xFF page is special for commands applying to all pages */
18653746d5c1STitus Rwantare if (index == PB_ALL_PAGES) {
18663746d5c1STitus Rwantare for (int i = 0; i < pmdev->num_pages; i++) {
18673746d5c1STitus Rwantare pmdev->pages[i].page_flags = flags;
18683746d5c1STitus Rwantare }
18693746d5c1STitus Rwantare return 0;
18703746d5c1STitus Rwantare }
18713746d5c1STitus Rwantare
18723746d5c1STitus Rwantare if (index > pmdev->num_pages - 1) {
18733746d5c1STitus Rwantare qemu_log_mask(LOG_GUEST_ERROR,
18743746d5c1STitus Rwantare "%s: index %u is out of range\n",
18753746d5c1STitus Rwantare __func__, index);
18763746d5c1STitus Rwantare return -1;
18773746d5c1STitus Rwantare }
18783746d5c1STitus Rwantare
18793746d5c1STitus Rwantare pmdev->pages[index].page_flags = flags;
18803746d5c1STitus Rwantare
18813746d5c1STitus Rwantare return 0;
18823746d5c1STitus Rwantare }
18833746d5c1STitus Rwantare
18843746d5c1STitus Rwantare /* TODO: include pmbus page info in vmstate */
18853746d5c1STitus Rwantare const VMStateDescription vmstate_pmbus_device = {
18863746d5c1STitus Rwantare .name = TYPE_PMBUS_DEVICE,
18873746d5c1STitus Rwantare .version_id = 0,
18883746d5c1STitus Rwantare .minimum_version_id = 0,
1889*01d9442aSRichard Henderson .fields = (const VMStateField[]) {
18903746d5c1STitus Rwantare VMSTATE_SMBUS_DEVICE(smb, PMBusDevice),
18913746d5c1STitus Rwantare VMSTATE_UINT8(num_pages, PMBusDevice),
18923746d5c1STitus Rwantare VMSTATE_UINT8(code, PMBusDevice),
18933746d5c1STitus Rwantare VMSTATE_UINT8(page, PMBusDevice),
18943746d5c1STitus Rwantare VMSTATE_UINT8(capability, PMBusDevice),
18953746d5c1STitus Rwantare VMSTATE_END_OF_LIST()
18963746d5c1STitus Rwantare }
18973746d5c1STitus Rwantare };
18983746d5c1STitus Rwantare
pmbus_device_finalize(Object * obj)18993746d5c1STitus Rwantare static void pmbus_device_finalize(Object *obj)
19003746d5c1STitus Rwantare {
19013746d5c1STitus Rwantare PMBusDevice *pmdev = PMBUS_DEVICE(obj);
19023746d5c1STitus Rwantare g_free(pmdev->pages);
19033746d5c1STitus Rwantare }
19043746d5c1STitus Rwantare
pmbus_device_class_init(ObjectClass * klass,void * data)19053746d5c1STitus Rwantare static void pmbus_device_class_init(ObjectClass *klass, void *data)
19063746d5c1STitus Rwantare {
19073746d5c1STitus Rwantare SMBusDeviceClass *k = SMBUS_DEVICE_CLASS(klass);
19083746d5c1STitus Rwantare
19093746d5c1STitus Rwantare k->quick_cmd = pmbus_quick_cmd;
19103746d5c1STitus Rwantare k->write_data = pmbus_write_data;
19113746d5c1STitus Rwantare k->receive_byte = pmbus_receive_byte;
19123746d5c1STitus Rwantare }
19133746d5c1STitus Rwantare
19143746d5c1STitus Rwantare static const TypeInfo pmbus_device_type_info = {
19153746d5c1STitus Rwantare .name = TYPE_PMBUS_DEVICE,
19163746d5c1STitus Rwantare .parent = TYPE_SMBUS_DEVICE,
19173746d5c1STitus Rwantare .instance_size = sizeof(PMBusDevice),
19183746d5c1STitus Rwantare .instance_finalize = pmbus_device_finalize,
19193746d5c1STitus Rwantare .abstract = true,
19203746d5c1STitus Rwantare .class_size = sizeof(PMBusDeviceClass),
19213746d5c1STitus Rwantare .class_init = pmbus_device_class_init,
19223746d5c1STitus Rwantare };
19233746d5c1STitus Rwantare
pmbus_device_register_types(void)19243746d5c1STitus Rwantare static void pmbus_device_register_types(void)
19253746d5c1STitus Rwantare {
19263746d5c1STitus Rwantare type_register_static(&pmbus_device_type_info);
19273746d5c1STitus Rwantare }
19283746d5c1STitus Rwantare
19293746d5c1STitus Rwantare type_init(pmbus_device_register_types)
1930