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 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 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 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 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 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 */ 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 753746d5c1STitus Rwantare void pmbus_send8(PMBusDevice *pmdev, uint8_t data) 763746d5c1STitus Rwantare { 773746d5c1STitus Rwantare pmbus_send_uint(pmdev, data, 1); 783746d5c1STitus Rwantare } 793746d5c1STitus Rwantare 803746d5c1STitus Rwantare void pmbus_send16(PMBusDevice *pmdev, uint16_t data) 813746d5c1STitus Rwantare { 823746d5c1STitus Rwantare pmbus_send_uint(pmdev, data, 2); 833746d5c1STitus Rwantare } 843746d5c1STitus Rwantare 853746d5c1STitus Rwantare void pmbus_send32(PMBusDevice *pmdev, uint32_t data) 863746d5c1STitus Rwantare { 873746d5c1STitus Rwantare pmbus_send_uint(pmdev, data, 4); 883746d5c1STitus Rwantare } 893746d5c1STitus Rwantare 903746d5c1STitus Rwantare void pmbus_send64(PMBusDevice *pmdev, uint64_t data) 913746d5c1STitus Rwantare { 923746d5c1STitus Rwantare pmbus_send_uint(pmdev, data, 8); 933746d5c1STitus Rwantare } 943746d5c1STitus Rwantare 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 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 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 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 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 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 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 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 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 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é 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 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 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 */ 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 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 */ 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 */ 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 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 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, 188901d9442aSRichard 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 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 1905*12d1a768SPhilippe Mathieu-Daudé static void pmbus_device_class_init(ObjectClass *klass, const 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 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