1*7215456aSTitus Rwantare /* 2*7215456aSTitus Rwantare * Maxim MAX34451 PMBus 16-Channel V/I monitor and 12-Channel Sequencer/Marginer 3*7215456aSTitus Rwantare * 4*7215456aSTitus Rwantare * Copyright 2021 Google LLC 5*7215456aSTitus Rwantare * 6*7215456aSTitus Rwantare * SPDX-License-Identifier: GPL-2.0-or-later 7*7215456aSTitus Rwantare */ 8*7215456aSTitus Rwantare 9*7215456aSTitus Rwantare #include "qemu/osdep.h" 10*7215456aSTitus Rwantare #include "hw/i2c/pmbus_device.h" 11*7215456aSTitus Rwantare #include "hw/irq.h" 12*7215456aSTitus Rwantare #include "migration/vmstate.h" 13*7215456aSTitus Rwantare #include "qapi/error.h" 14*7215456aSTitus Rwantare #include "qapi/visitor.h" 15*7215456aSTitus Rwantare #include "qemu/log.h" 16*7215456aSTitus Rwantare #include "qemu/module.h" 17*7215456aSTitus Rwantare 18*7215456aSTitus Rwantare #define TYPE_MAX34451 "max34451" 19*7215456aSTitus Rwantare #define MAX34451(obj) OBJECT_CHECK(MAX34451State, (obj), TYPE_MAX34451) 20*7215456aSTitus Rwantare 21*7215456aSTitus Rwantare #define MAX34451_MFR_MODE 0xD1 22*7215456aSTitus Rwantare #define MAX34451_MFR_PSEN_CONFIG 0xD2 23*7215456aSTitus Rwantare #define MAX34451_MFR_VOUT_PEAK 0xD4 24*7215456aSTitus Rwantare #define MAX34451_MFR_IOUT_PEAK 0xD5 25*7215456aSTitus Rwantare #define MAX34451_MFR_TEMPERATURE_PEAK 0xD6 26*7215456aSTitus Rwantare #define MAX34451_MFR_VOUT_MIN 0xD7 27*7215456aSTitus Rwantare #define MAX34451_MFR_NV_LOG_CONFIG 0xD8 28*7215456aSTitus Rwantare #define MAX34451_MFR_FAULT_RESPONSE 0xD9 29*7215456aSTitus Rwantare #define MAX34451_MFR_FAULT_RETRY 0xDA 30*7215456aSTitus Rwantare #define MAX34451_MFR_NV_FAULT_LOG 0xDC 31*7215456aSTitus Rwantare #define MAX34451_MFR_TIME_COUNT 0xDD 32*7215456aSTitus Rwantare #define MAX34451_MFR_MARGIN_CONFIG 0xDF 33*7215456aSTitus Rwantare #define MAX34451_MFR_FW_SERIAL 0xE0 34*7215456aSTitus Rwantare #define MAX34451_MFR_IOUT_AVG 0xE2 35*7215456aSTitus Rwantare #define MAX34451_MFR_CHANNEL_CONFIG 0xE4 36*7215456aSTitus Rwantare #define MAX34451_MFR_TON_SEQ_MAX 0xE6 37*7215456aSTitus Rwantare #define MAX34451_MFR_PWM_CONFIG 0xE7 38*7215456aSTitus Rwantare #define MAX34451_MFR_SEQ_CONFIG 0xE8 39*7215456aSTitus Rwantare #define MAX34451_MFR_STORE_ALL 0xEE 40*7215456aSTitus Rwantare #define MAX34451_MFR_RESTORE_ALL 0xEF 41*7215456aSTitus Rwantare #define MAX34451_MFR_TEMP_SENSOR_CONFIG 0xF0 42*7215456aSTitus Rwantare #define MAX34451_MFR_STORE_SINGLE 0xFC 43*7215456aSTitus Rwantare #define MAX34451_MFR_CRC 0xFE 44*7215456aSTitus Rwantare 45*7215456aSTitus Rwantare #define MAX34451_NUM_MARGINED_PSU 12 46*7215456aSTitus Rwantare #define MAX34451_NUM_PWR_DEVICES 16 47*7215456aSTitus Rwantare #define MAX34451_NUM_TEMP_DEVICES 5 48*7215456aSTitus Rwantare #define MAX34451_NUM_PAGES 21 49*7215456aSTitus Rwantare 50*7215456aSTitus Rwantare #define DEFAULT_OP_ON 0x80 51*7215456aSTitus Rwantare #define DEFAULT_CAPABILITY 0x20 52*7215456aSTitus Rwantare #define DEFAULT_ON_OFF_CONFIG 0x1a 53*7215456aSTitus Rwantare #define DEFAULT_VOUT_MODE 0x40 54*7215456aSTitus Rwantare #define DEFAULT_TEMPERATURE 2500 55*7215456aSTitus Rwantare #define DEFAULT_SCALE 0x7FFF 56*7215456aSTitus Rwantare #define DEFAULT_OV_LIMIT 0x7FFF 57*7215456aSTitus Rwantare #define DEFAULT_OC_LIMIT 0x7FFF 58*7215456aSTitus Rwantare #define DEFAULT_OT_LIMIT 0x7FFF 59*7215456aSTitus Rwantare #define DEFAULT_VMIN 0x7FFF 60*7215456aSTitus Rwantare #define DEFAULT_TON_FAULT_LIMIT 0xFFFF 61*7215456aSTitus Rwantare #define DEFAULT_CHANNEL_CONFIG 0x20 62*7215456aSTitus Rwantare #define DEFAULT_TEXT 0x3130313031303130 63*7215456aSTitus Rwantare 64*7215456aSTitus Rwantare /** 65*7215456aSTitus Rwantare * MAX34451State: 66*7215456aSTitus Rwantare * @code: The command code received 67*7215456aSTitus Rwantare * @page: Each page corresponds to a device monitored by the Max 34451 68*7215456aSTitus Rwantare * The page register determines the available commands depending on device 69*7215456aSTitus Rwantare ___________________________________________________________________________ 70*7215456aSTitus Rwantare | 0 | Power supply monitored by RS0, controlled by PSEN0, and | 71*7215456aSTitus Rwantare | | margined with PWM0. | 72*7215456aSTitus Rwantare |_______|___________________________________________________________________| 73*7215456aSTitus Rwantare | 1 | Power supply monitored by RS1, controlled by PSEN1, and | 74*7215456aSTitus Rwantare | | margined with PWM1. | 75*7215456aSTitus Rwantare |_______|___________________________________________________________________| 76*7215456aSTitus Rwantare | 2 | Power supply monitored by RS2, controlled by PSEN2, and | 77*7215456aSTitus Rwantare | | margined with PWM2. | 78*7215456aSTitus Rwantare |_______|___________________________________________________________________| 79*7215456aSTitus Rwantare | 3 | Power supply monitored by RS3, controlled by PSEN3, and | 80*7215456aSTitus Rwantare | | margined with PWM3. | 81*7215456aSTitus Rwantare |_______|___________________________________________________________________| 82*7215456aSTitus Rwantare | 4 | Power supply monitored by RS4, controlled by PSEN4, and | 83*7215456aSTitus Rwantare | | margined with PWM4. | 84*7215456aSTitus Rwantare |_______|___________________________________________________________________| 85*7215456aSTitus Rwantare | 5 | Power supply monitored by RS5, controlled by PSEN5, and | 86*7215456aSTitus Rwantare | | margined with PWM5. | 87*7215456aSTitus Rwantare |_______|___________________________________________________________________| 88*7215456aSTitus Rwantare | 6 | Power supply monitored by RS6, controlled by PSEN6, and | 89*7215456aSTitus Rwantare | | margined with PWM6. | 90*7215456aSTitus Rwantare |_______|___________________________________________________________________| 91*7215456aSTitus Rwantare | 7 | Power supply monitored by RS7, controlled by PSEN7, and | 92*7215456aSTitus Rwantare | | margined with PWM7. | 93*7215456aSTitus Rwantare |_______|___________________________________________________________________| 94*7215456aSTitus Rwantare | 8 | Power supply monitored by RS8, controlled by PSEN8, and | 95*7215456aSTitus Rwantare | | optionally margined by OUT0 of external DS4424 at I2C address A0h.| 96*7215456aSTitus Rwantare |_______|___________________________________________________________________| 97*7215456aSTitus Rwantare | 9 | Power supply monitored by RS9, controlled by PSEN9, and | 98*7215456aSTitus Rwantare | | optionally margined by OUT1 of external DS4424 at I2C address A0h.| 99*7215456aSTitus Rwantare |_______|___________________________________________________________________| 100*7215456aSTitus Rwantare | 10 | Power supply monitored by RS10, controlled by PSEN10, and | 101*7215456aSTitus Rwantare | | optionally margined by OUT2 of external DS4424 at I2C address A0h.| 102*7215456aSTitus Rwantare |_______|___________________________________________________________________| 103*7215456aSTitus Rwantare | 11 | Power supply monitored by RS11, controlled by PSEN11, and | 104*7215456aSTitus Rwantare | | optionally margined by OUT3 of external DS4424 at I2C address A0h.| 105*7215456aSTitus Rwantare |_______|___________________________________________________________________| 106*7215456aSTitus Rwantare | 12 | ADC channel 12 (monitors voltage or current) or GPI. | 107*7215456aSTitus Rwantare |_______|___________________________________________________________________| 108*7215456aSTitus Rwantare | 13 | ADC channel 13 (monitors voltage or current) or GPI. | 109*7215456aSTitus Rwantare |_______|___________________________________________________________________| 110*7215456aSTitus Rwantare | 14 | ADC channel 14 (monitors voltage or current) or GPI. | 111*7215456aSTitus Rwantare |_______|___________________________________________________________________| 112*7215456aSTitus Rwantare | 15 | ADC channel 15 (monitors voltage or current) or GPI. | 113*7215456aSTitus Rwantare |_______|___________________________________________________________________| 114*7215456aSTitus Rwantare | 16 | Internal temperature sensor. | 115*7215456aSTitus Rwantare |_______|___________________________________________________________________| 116*7215456aSTitus Rwantare | 17 | External DS75LV temperature sensor with I2C address 90h. | 117*7215456aSTitus Rwantare |_______|___________________________________________________________________| 118*7215456aSTitus Rwantare | 18 | External DS75LV temperature sensor with I2C address 92h. | 119*7215456aSTitus Rwantare |_______|___________________________________________________________________| 120*7215456aSTitus Rwantare | 19 | External DS75LV temperature sensor with I2C address 94h. | 121*7215456aSTitus Rwantare |_______|___________________________________________________________________| 122*7215456aSTitus Rwantare | 20 | External DS75LV temperature sensor with I2C address 96h. | 123*7215456aSTitus Rwantare |_______|___________________________________________________________________| 124*7215456aSTitus Rwantare | 21=E2=80=93254| Reserved. | 125*7215456aSTitus Rwantare |_______|___________________________________________________________________| 126*7215456aSTitus Rwantare | 255 | Applies to all pages. | 127*7215456aSTitus Rwantare |_______|___________________________________________________________________| 128*7215456aSTitus Rwantare * 129*7215456aSTitus Rwantare * @operation: Turn on and off power supplies 130*7215456aSTitus Rwantare * @on_off_config: Configure the power supply on and off transition behaviour 131*7215456aSTitus Rwantare * @write_protect: protect against changes to the device's memory 132*7215456aSTitus Rwantare * @vout_margin_high: the voltage when OPERATION is set to margin high 133*7215456aSTitus Rwantare * @vout_margin_low: the voltage when OPERATION is set to margin low 134*7215456aSTitus Rwantare * @vout_scale: scale ADC reading to actual device reading if different 135*7215456aSTitus Rwantare * @iout_cal_gain: set ratio of the voltage at the ADC input to sensed current 136*7215456aSTitus Rwantare */ 137*7215456aSTitus Rwantare typedef struct MAX34451State { 138*7215456aSTitus Rwantare PMBusDevice parent; 139*7215456aSTitus Rwantare 140*7215456aSTitus Rwantare uint16_t power_good_on[MAX34451_NUM_PWR_DEVICES]; 141*7215456aSTitus Rwantare uint16_t power_good_off[MAX34451_NUM_PWR_DEVICES]; 142*7215456aSTitus Rwantare uint16_t ton_delay[MAX34451_NUM_MARGINED_PSU]; 143*7215456aSTitus Rwantare uint16_t ton_max_fault_limit[MAX34451_NUM_MARGINED_PSU]; 144*7215456aSTitus Rwantare uint16_t toff_delay[MAX34451_NUM_MARGINED_PSU]; 145*7215456aSTitus Rwantare uint8_t status_mfr_specific[MAX34451_NUM_PWR_DEVICES]; 146*7215456aSTitus Rwantare /* Manufacturer specific function */ 147*7215456aSTitus Rwantare uint64_t mfr_location; 148*7215456aSTitus Rwantare uint64_t mfr_date; 149*7215456aSTitus Rwantare uint64_t mfr_serial; 150*7215456aSTitus Rwantare uint16_t mfr_mode; 151*7215456aSTitus Rwantare uint32_t psen_config[MAX34451_NUM_MARGINED_PSU]; 152*7215456aSTitus Rwantare uint16_t vout_peak[MAX34451_NUM_PWR_DEVICES]; 153*7215456aSTitus Rwantare uint16_t iout_peak[MAX34451_NUM_PWR_DEVICES]; 154*7215456aSTitus Rwantare uint16_t temperature_peak[MAX34451_NUM_TEMP_DEVICES]; 155*7215456aSTitus Rwantare uint16_t vout_min[MAX34451_NUM_PWR_DEVICES]; 156*7215456aSTitus Rwantare uint16_t nv_log_config; 157*7215456aSTitus Rwantare uint32_t fault_response[MAX34451_NUM_PWR_DEVICES]; 158*7215456aSTitus Rwantare uint16_t fault_retry; 159*7215456aSTitus Rwantare uint32_t fault_log; 160*7215456aSTitus Rwantare uint32_t time_count; 161*7215456aSTitus Rwantare uint16_t margin_config[MAX34451_NUM_MARGINED_PSU]; 162*7215456aSTitus Rwantare uint16_t fw_serial; 163*7215456aSTitus Rwantare uint16_t iout_avg[MAX34451_NUM_PWR_DEVICES]; 164*7215456aSTitus Rwantare uint16_t channel_config[MAX34451_NUM_PWR_DEVICES]; 165*7215456aSTitus Rwantare uint16_t ton_seq_max[MAX34451_NUM_MARGINED_PSU]; 166*7215456aSTitus Rwantare uint32_t pwm_config[MAX34451_NUM_MARGINED_PSU]; 167*7215456aSTitus Rwantare uint32_t seq_config[MAX34451_NUM_MARGINED_PSU]; 168*7215456aSTitus Rwantare uint16_t temp_sensor_config[MAX34451_NUM_TEMP_DEVICES]; 169*7215456aSTitus Rwantare uint16_t store_single; 170*7215456aSTitus Rwantare uint16_t crc; 171*7215456aSTitus Rwantare } MAX34451State; 172*7215456aSTitus Rwantare 173*7215456aSTitus Rwantare 174*7215456aSTitus Rwantare static void max34451_check_limits(MAX34451State *s) 175*7215456aSTitus Rwantare { 176*7215456aSTitus Rwantare PMBusDevice *pmdev = PMBUS_DEVICE(s); 177*7215456aSTitus Rwantare 178*7215456aSTitus Rwantare pmbus_check_limits(pmdev); 179*7215456aSTitus Rwantare 180*7215456aSTitus Rwantare for (int i = 0; i < MAX34451_NUM_PWR_DEVICES; i++) { 181*7215456aSTitus Rwantare if (pmdev->pages[i].read_vout == 0) { /* PSU disabled */ 182*7215456aSTitus Rwantare continue; 183*7215456aSTitus Rwantare } 184*7215456aSTitus Rwantare 185*7215456aSTitus Rwantare if (pmdev->pages[i].read_vout > s->vout_peak[i]) { 186*7215456aSTitus Rwantare s->vout_peak[i] = pmdev->pages[i].read_vout; 187*7215456aSTitus Rwantare } 188*7215456aSTitus Rwantare 189*7215456aSTitus Rwantare if (pmdev->pages[i].read_vout < s->vout_min[i]) { 190*7215456aSTitus Rwantare s->vout_min[i] = pmdev->pages[i].read_vout; 191*7215456aSTitus Rwantare } 192*7215456aSTitus Rwantare 193*7215456aSTitus Rwantare if (pmdev->pages[i].read_iout > s->iout_peak[i]) { 194*7215456aSTitus Rwantare s->iout_peak[i] = pmdev->pages[i].read_iout; 195*7215456aSTitus Rwantare } 196*7215456aSTitus Rwantare } 197*7215456aSTitus Rwantare 198*7215456aSTitus Rwantare for (int i = 0; i < MAX34451_NUM_TEMP_DEVICES; i++) { 199*7215456aSTitus Rwantare if (pmdev->pages[i + 16].read_temperature_1 > s->temperature_peak[i]) { 200*7215456aSTitus Rwantare s->temperature_peak[i] = pmdev->pages[i + 16].read_temperature_1; 201*7215456aSTitus Rwantare } 202*7215456aSTitus Rwantare } 203*7215456aSTitus Rwantare } 204*7215456aSTitus Rwantare 205*7215456aSTitus Rwantare static uint8_t max34451_read_byte(PMBusDevice *pmdev) 206*7215456aSTitus Rwantare { 207*7215456aSTitus Rwantare MAX34451State *s = MAX34451(pmdev); 208*7215456aSTitus Rwantare switch (pmdev->code) { 209*7215456aSTitus Rwantare 210*7215456aSTitus Rwantare case PMBUS_POWER_GOOD_ON: 211*7215456aSTitus Rwantare if (pmdev->page < 16) { 212*7215456aSTitus Rwantare pmbus_send16(pmdev, s->power_good_on[pmdev->page]); 213*7215456aSTitus Rwantare } 214*7215456aSTitus Rwantare break; 215*7215456aSTitus Rwantare 216*7215456aSTitus Rwantare case PMBUS_POWER_GOOD_OFF: 217*7215456aSTitus Rwantare if (pmdev->page < 16) { 218*7215456aSTitus Rwantare pmbus_send16(pmdev, s->power_good_off[pmdev->page]); 219*7215456aSTitus Rwantare } 220*7215456aSTitus Rwantare break; 221*7215456aSTitus Rwantare 222*7215456aSTitus Rwantare case PMBUS_TON_DELAY: 223*7215456aSTitus Rwantare if (pmdev->page < 12) { 224*7215456aSTitus Rwantare pmbus_send16(pmdev, s->ton_delay[pmdev->page]); 225*7215456aSTitus Rwantare } 226*7215456aSTitus Rwantare break; 227*7215456aSTitus Rwantare 228*7215456aSTitus Rwantare case PMBUS_TON_MAX_FAULT_LIMIT: 229*7215456aSTitus Rwantare if (pmdev->page < 12) { 230*7215456aSTitus Rwantare pmbus_send16(pmdev, s->ton_max_fault_limit[pmdev->page]); 231*7215456aSTitus Rwantare } 232*7215456aSTitus Rwantare break; 233*7215456aSTitus Rwantare 234*7215456aSTitus Rwantare case PMBUS_TOFF_DELAY: 235*7215456aSTitus Rwantare if (pmdev->page < 12) { 236*7215456aSTitus Rwantare pmbus_send16(pmdev, s->toff_delay[pmdev->page]); 237*7215456aSTitus Rwantare } 238*7215456aSTitus Rwantare break; 239*7215456aSTitus Rwantare 240*7215456aSTitus Rwantare case PMBUS_STATUS_MFR_SPECIFIC: 241*7215456aSTitus Rwantare if (pmdev->page < 16) { 242*7215456aSTitus Rwantare pmbus_send8(pmdev, s->status_mfr_specific[pmdev->page]); 243*7215456aSTitus Rwantare } 244*7215456aSTitus Rwantare break; 245*7215456aSTitus Rwantare 246*7215456aSTitus Rwantare case PMBUS_MFR_ID: 247*7215456aSTitus Rwantare pmbus_send8(pmdev, 0x4d); /* Maxim */ 248*7215456aSTitus Rwantare break; 249*7215456aSTitus Rwantare 250*7215456aSTitus Rwantare case PMBUS_MFR_MODEL: 251*7215456aSTitus Rwantare pmbus_send8(pmdev, 0x59); 252*7215456aSTitus Rwantare break; 253*7215456aSTitus Rwantare 254*7215456aSTitus Rwantare case PMBUS_MFR_LOCATION: 255*7215456aSTitus Rwantare pmbus_send64(pmdev, s->mfr_location); 256*7215456aSTitus Rwantare break; 257*7215456aSTitus Rwantare 258*7215456aSTitus Rwantare case PMBUS_MFR_DATE: 259*7215456aSTitus Rwantare pmbus_send64(pmdev, s->mfr_date); 260*7215456aSTitus Rwantare break; 261*7215456aSTitus Rwantare 262*7215456aSTitus Rwantare case PMBUS_MFR_SERIAL: 263*7215456aSTitus Rwantare pmbus_send64(pmdev, s->mfr_serial); 264*7215456aSTitus Rwantare break; 265*7215456aSTitus Rwantare 266*7215456aSTitus Rwantare case MAX34451_MFR_MODE: 267*7215456aSTitus Rwantare pmbus_send16(pmdev, s->mfr_mode); 268*7215456aSTitus Rwantare break; 269*7215456aSTitus Rwantare 270*7215456aSTitus Rwantare case MAX34451_MFR_PSEN_CONFIG: 271*7215456aSTitus Rwantare if (pmdev->page < 12) { 272*7215456aSTitus Rwantare pmbus_send32(pmdev, s->psen_config[pmdev->page]); 273*7215456aSTitus Rwantare } 274*7215456aSTitus Rwantare break; 275*7215456aSTitus Rwantare 276*7215456aSTitus Rwantare case MAX34451_MFR_VOUT_PEAK: 277*7215456aSTitus Rwantare if (pmdev->page < 16) { 278*7215456aSTitus Rwantare pmbus_send16(pmdev, s->vout_peak[pmdev->page]); 279*7215456aSTitus Rwantare } 280*7215456aSTitus Rwantare break; 281*7215456aSTitus Rwantare 282*7215456aSTitus Rwantare case MAX34451_MFR_IOUT_PEAK: 283*7215456aSTitus Rwantare if (pmdev->page < 16) { 284*7215456aSTitus Rwantare pmbus_send16(pmdev, s->iout_peak[pmdev->page]); 285*7215456aSTitus Rwantare } 286*7215456aSTitus Rwantare break; 287*7215456aSTitus Rwantare 288*7215456aSTitus Rwantare case MAX34451_MFR_TEMPERATURE_PEAK: 289*7215456aSTitus Rwantare if (15 < pmdev->page && pmdev->page < 21) { 290*7215456aSTitus Rwantare pmbus_send16(pmdev, s->temperature_peak[pmdev->page % 16]); 291*7215456aSTitus Rwantare } else { 292*7215456aSTitus Rwantare pmbus_send16(pmdev, s->temperature_peak[0]); 293*7215456aSTitus Rwantare } 294*7215456aSTitus Rwantare break; 295*7215456aSTitus Rwantare 296*7215456aSTitus Rwantare case MAX34451_MFR_VOUT_MIN: 297*7215456aSTitus Rwantare if (pmdev->page < 16) { 298*7215456aSTitus Rwantare pmbus_send16(pmdev, s->vout_min[pmdev->page]); 299*7215456aSTitus Rwantare } 300*7215456aSTitus Rwantare break; 301*7215456aSTitus Rwantare 302*7215456aSTitus Rwantare case MAX34451_MFR_NV_LOG_CONFIG: 303*7215456aSTitus Rwantare pmbus_send16(pmdev, s->nv_log_config); 304*7215456aSTitus Rwantare break; 305*7215456aSTitus Rwantare 306*7215456aSTitus Rwantare case MAX34451_MFR_FAULT_RESPONSE: 307*7215456aSTitus Rwantare if (pmdev->page < 16) { 308*7215456aSTitus Rwantare pmbus_send32(pmdev, s->fault_response[pmdev->page]); 309*7215456aSTitus Rwantare } 310*7215456aSTitus Rwantare break; 311*7215456aSTitus Rwantare 312*7215456aSTitus Rwantare case MAX34451_MFR_FAULT_RETRY: 313*7215456aSTitus Rwantare pmbus_send32(pmdev, s->fault_retry); 314*7215456aSTitus Rwantare break; 315*7215456aSTitus Rwantare 316*7215456aSTitus Rwantare case MAX34451_MFR_NV_FAULT_LOG: 317*7215456aSTitus Rwantare pmbus_send32(pmdev, s->fault_log); 318*7215456aSTitus Rwantare break; 319*7215456aSTitus Rwantare 320*7215456aSTitus Rwantare case MAX34451_MFR_TIME_COUNT: 321*7215456aSTitus Rwantare pmbus_send32(pmdev, s->time_count); 322*7215456aSTitus Rwantare break; 323*7215456aSTitus Rwantare 324*7215456aSTitus Rwantare case MAX34451_MFR_MARGIN_CONFIG: 325*7215456aSTitus Rwantare if (pmdev->page < 12) { 326*7215456aSTitus Rwantare pmbus_send16(pmdev, s->margin_config[pmdev->page]); 327*7215456aSTitus Rwantare } 328*7215456aSTitus Rwantare break; 329*7215456aSTitus Rwantare 330*7215456aSTitus Rwantare case MAX34451_MFR_FW_SERIAL: 331*7215456aSTitus Rwantare if (pmdev->page == 255) { 332*7215456aSTitus Rwantare pmbus_send16(pmdev, 1); /* Firmware revision */ 333*7215456aSTitus Rwantare } 334*7215456aSTitus Rwantare break; 335*7215456aSTitus Rwantare 336*7215456aSTitus Rwantare case MAX34451_MFR_IOUT_AVG: 337*7215456aSTitus Rwantare if (pmdev->page < 16) { 338*7215456aSTitus Rwantare pmbus_send16(pmdev, s->iout_avg[pmdev->page]); 339*7215456aSTitus Rwantare } 340*7215456aSTitus Rwantare break; 341*7215456aSTitus Rwantare 342*7215456aSTitus Rwantare case MAX34451_MFR_CHANNEL_CONFIG: 343*7215456aSTitus Rwantare if (pmdev->page < 16) { 344*7215456aSTitus Rwantare pmbus_send16(pmdev, s->channel_config[pmdev->page]); 345*7215456aSTitus Rwantare } 346*7215456aSTitus Rwantare break; 347*7215456aSTitus Rwantare 348*7215456aSTitus Rwantare case MAX34451_MFR_TON_SEQ_MAX: 349*7215456aSTitus Rwantare if (pmdev->page < 12) { 350*7215456aSTitus Rwantare pmbus_send16(pmdev, s->ton_seq_max[pmdev->page]); 351*7215456aSTitus Rwantare } 352*7215456aSTitus Rwantare break; 353*7215456aSTitus Rwantare 354*7215456aSTitus Rwantare case MAX34451_MFR_PWM_CONFIG: 355*7215456aSTitus Rwantare if (pmdev->page < 12) { 356*7215456aSTitus Rwantare pmbus_send32(pmdev, s->pwm_config[pmdev->page]); 357*7215456aSTitus Rwantare } 358*7215456aSTitus Rwantare break; 359*7215456aSTitus Rwantare 360*7215456aSTitus Rwantare case MAX34451_MFR_SEQ_CONFIG: 361*7215456aSTitus Rwantare if (pmdev->page < 12) { 362*7215456aSTitus Rwantare pmbus_send32(pmdev, s->seq_config[pmdev->page]); 363*7215456aSTitus Rwantare } 364*7215456aSTitus Rwantare break; 365*7215456aSTitus Rwantare 366*7215456aSTitus Rwantare case MAX34451_MFR_TEMP_SENSOR_CONFIG: 367*7215456aSTitus Rwantare if (15 < pmdev->page && pmdev->page < 21) { 368*7215456aSTitus Rwantare pmbus_send32(pmdev, s->temp_sensor_config[pmdev->page % 16]); 369*7215456aSTitus Rwantare } 370*7215456aSTitus Rwantare break; 371*7215456aSTitus Rwantare 372*7215456aSTitus Rwantare case MAX34451_MFR_STORE_SINGLE: 373*7215456aSTitus Rwantare pmbus_send32(pmdev, s->store_single); 374*7215456aSTitus Rwantare break; 375*7215456aSTitus Rwantare 376*7215456aSTitus Rwantare case MAX34451_MFR_CRC: 377*7215456aSTitus Rwantare pmbus_send32(pmdev, s->crc); 378*7215456aSTitus Rwantare break; 379*7215456aSTitus Rwantare 380*7215456aSTitus Rwantare default: 381*7215456aSTitus Rwantare qemu_log_mask(LOG_GUEST_ERROR, 382*7215456aSTitus Rwantare "%s: reading from unsupported register: 0x%02x\n", 383*7215456aSTitus Rwantare __func__, pmdev->code); 384*7215456aSTitus Rwantare break; 385*7215456aSTitus Rwantare } 386*7215456aSTitus Rwantare return 0xFF; 387*7215456aSTitus Rwantare } 388*7215456aSTitus Rwantare 389*7215456aSTitus Rwantare static int max34451_write_data(PMBusDevice *pmdev, const uint8_t *buf, 390*7215456aSTitus Rwantare uint8_t len) 391*7215456aSTitus Rwantare { 392*7215456aSTitus Rwantare MAX34451State *s = MAX34451(pmdev); 393*7215456aSTitus Rwantare 394*7215456aSTitus Rwantare if (len == 0) { 395*7215456aSTitus Rwantare qemu_log_mask(LOG_GUEST_ERROR, "%s: writing empty data\n", __func__); 396*7215456aSTitus Rwantare return -1; 397*7215456aSTitus Rwantare } 398*7215456aSTitus Rwantare 399*7215456aSTitus Rwantare pmdev->code = buf[0]; /* PMBus command code */ 400*7215456aSTitus Rwantare 401*7215456aSTitus Rwantare if (len == 1) { 402*7215456aSTitus Rwantare return 0; 403*7215456aSTitus Rwantare } 404*7215456aSTitus Rwantare 405*7215456aSTitus Rwantare /* Exclude command code from buffer */ 406*7215456aSTitus Rwantare buf++; 407*7215456aSTitus Rwantare len--; 408*7215456aSTitus Rwantare uint8_t index = pmdev->page; 409*7215456aSTitus Rwantare 410*7215456aSTitus Rwantare switch (pmdev->code) { 411*7215456aSTitus Rwantare case MAX34451_MFR_STORE_ALL: 412*7215456aSTitus Rwantare case MAX34451_MFR_RESTORE_ALL: 413*7215456aSTitus Rwantare case MAX34451_MFR_STORE_SINGLE: 414*7215456aSTitus Rwantare /* 415*7215456aSTitus Rwantare * TODO: hardware behaviour is to move the contents of volatile 416*7215456aSTitus Rwantare * memory to non-volatile memory. 417*7215456aSTitus Rwantare */ 418*7215456aSTitus Rwantare break; 419*7215456aSTitus Rwantare 420*7215456aSTitus Rwantare case PMBUS_POWER_GOOD_ON: /* R/W word */ 421*7215456aSTitus Rwantare if (pmdev->page < MAX34451_NUM_PWR_DEVICES) { 422*7215456aSTitus Rwantare s->power_good_on[pmdev->page] = pmbus_receive16(pmdev); 423*7215456aSTitus Rwantare } 424*7215456aSTitus Rwantare break; 425*7215456aSTitus Rwantare 426*7215456aSTitus Rwantare case PMBUS_POWER_GOOD_OFF: /* R/W word */ 427*7215456aSTitus Rwantare if (pmdev->page < MAX34451_NUM_PWR_DEVICES) { 428*7215456aSTitus Rwantare s->power_good_off[pmdev->page] = pmbus_receive16(pmdev); 429*7215456aSTitus Rwantare } 430*7215456aSTitus Rwantare break; 431*7215456aSTitus Rwantare 432*7215456aSTitus Rwantare case PMBUS_TON_DELAY: /* R/W word */ 433*7215456aSTitus Rwantare if (pmdev->page < 12) { 434*7215456aSTitus Rwantare s->ton_delay[pmdev->page] = pmbus_receive16(pmdev); 435*7215456aSTitus Rwantare } 436*7215456aSTitus Rwantare break; 437*7215456aSTitus Rwantare 438*7215456aSTitus Rwantare case PMBUS_TON_MAX_FAULT_LIMIT: /* R/W word */ 439*7215456aSTitus Rwantare if (pmdev->page < 12) { 440*7215456aSTitus Rwantare s->ton_max_fault_limit[pmdev->page] 441*7215456aSTitus Rwantare = pmbus_receive16(pmdev); 442*7215456aSTitus Rwantare } 443*7215456aSTitus Rwantare break; 444*7215456aSTitus Rwantare 445*7215456aSTitus Rwantare case PMBUS_TOFF_DELAY: /* R/W word */ 446*7215456aSTitus Rwantare if (pmdev->page < 12) { 447*7215456aSTitus Rwantare s->toff_delay[pmdev->page] = pmbus_receive16(pmdev); 448*7215456aSTitus Rwantare } 449*7215456aSTitus Rwantare break; 450*7215456aSTitus Rwantare 451*7215456aSTitus Rwantare case PMBUS_MFR_LOCATION: /* R/W 64 */ 452*7215456aSTitus Rwantare s->mfr_location = pmbus_receive64(pmdev); 453*7215456aSTitus Rwantare break; 454*7215456aSTitus Rwantare 455*7215456aSTitus Rwantare case PMBUS_MFR_DATE: /* R/W 64 */ 456*7215456aSTitus Rwantare s->mfr_date = pmbus_receive64(pmdev); 457*7215456aSTitus Rwantare break; 458*7215456aSTitus Rwantare 459*7215456aSTitus Rwantare case PMBUS_MFR_SERIAL: /* R/W 64 */ 460*7215456aSTitus Rwantare s->mfr_serial = pmbus_receive64(pmdev); 461*7215456aSTitus Rwantare break; 462*7215456aSTitus Rwantare 463*7215456aSTitus Rwantare case MAX34451_MFR_MODE: /* R/W word */ 464*7215456aSTitus Rwantare s->mfr_mode = pmbus_receive16(pmdev); 465*7215456aSTitus Rwantare break; 466*7215456aSTitus Rwantare 467*7215456aSTitus Rwantare case MAX34451_MFR_PSEN_CONFIG: /* R/W 32 */ 468*7215456aSTitus Rwantare if (pmdev->page < 12) { 469*7215456aSTitus Rwantare s->psen_config[pmdev->page] = pmbus_receive32(pmdev); 470*7215456aSTitus Rwantare } 471*7215456aSTitus Rwantare break; 472*7215456aSTitus Rwantare 473*7215456aSTitus Rwantare case MAX34451_MFR_VOUT_PEAK: /* R/W word */ 474*7215456aSTitus Rwantare if (pmdev->page < 16) { 475*7215456aSTitus Rwantare s->vout_peak[pmdev->page] = pmbus_receive16(pmdev); 476*7215456aSTitus Rwantare } 477*7215456aSTitus Rwantare break; 478*7215456aSTitus Rwantare 479*7215456aSTitus Rwantare case MAX34451_MFR_IOUT_PEAK: /* R/W word */ 480*7215456aSTitus Rwantare if (pmdev->page < 16) { 481*7215456aSTitus Rwantare s->iout_peak[pmdev->page] = pmbus_receive16(pmdev); 482*7215456aSTitus Rwantare } 483*7215456aSTitus Rwantare break; 484*7215456aSTitus Rwantare 485*7215456aSTitus Rwantare case MAX34451_MFR_TEMPERATURE_PEAK: /* R/W word */ 486*7215456aSTitus Rwantare if (15 < pmdev->page && pmdev->page < 21) { 487*7215456aSTitus Rwantare s->temperature_peak[pmdev->page % 16] 488*7215456aSTitus Rwantare = pmbus_receive16(pmdev); 489*7215456aSTitus Rwantare } 490*7215456aSTitus Rwantare break; 491*7215456aSTitus Rwantare 492*7215456aSTitus Rwantare case MAX34451_MFR_VOUT_MIN: /* R/W word */ 493*7215456aSTitus Rwantare if (pmdev->page < 16) { 494*7215456aSTitus Rwantare s->vout_min[pmdev->page] = pmbus_receive16(pmdev); 495*7215456aSTitus Rwantare } 496*7215456aSTitus Rwantare break; 497*7215456aSTitus Rwantare 498*7215456aSTitus Rwantare case MAX34451_MFR_NV_LOG_CONFIG: /* R/W word */ 499*7215456aSTitus Rwantare s->nv_log_config = pmbus_receive16(pmdev); 500*7215456aSTitus Rwantare break; 501*7215456aSTitus Rwantare 502*7215456aSTitus Rwantare case MAX34451_MFR_FAULT_RESPONSE: /* R/W 32 */ 503*7215456aSTitus Rwantare if (pmdev->page < 16) { 504*7215456aSTitus Rwantare s->fault_response[pmdev->page] = pmbus_receive32(pmdev); 505*7215456aSTitus Rwantare } 506*7215456aSTitus Rwantare break; 507*7215456aSTitus Rwantare 508*7215456aSTitus Rwantare case MAX34451_MFR_FAULT_RETRY: /* R/W word */ 509*7215456aSTitus Rwantare s->fault_retry = pmbus_receive16(pmdev); 510*7215456aSTitus Rwantare break; 511*7215456aSTitus Rwantare 512*7215456aSTitus Rwantare case MAX34451_MFR_TIME_COUNT: /* R/W 32 */ 513*7215456aSTitus Rwantare s->time_count = pmbus_receive32(pmdev); 514*7215456aSTitus Rwantare break; 515*7215456aSTitus Rwantare 516*7215456aSTitus Rwantare case MAX34451_MFR_MARGIN_CONFIG: /* R/W word */ 517*7215456aSTitus Rwantare if (pmdev->page < 12) { 518*7215456aSTitus Rwantare s->margin_config[pmdev->page] = pmbus_receive16(pmdev); 519*7215456aSTitus Rwantare } 520*7215456aSTitus Rwantare break; 521*7215456aSTitus Rwantare 522*7215456aSTitus Rwantare case MAX34451_MFR_CHANNEL_CONFIG: /* R/W word */ 523*7215456aSTitus Rwantare if (pmdev->page < 16) { 524*7215456aSTitus Rwantare s->channel_config[pmdev->page] = pmbus_receive16(pmdev); 525*7215456aSTitus Rwantare } 526*7215456aSTitus Rwantare break; 527*7215456aSTitus Rwantare 528*7215456aSTitus Rwantare case MAX34451_MFR_TON_SEQ_MAX: /* R/W word */ 529*7215456aSTitus Rwantare if (pmdev->page < 12) { 530*7215456aSTitus Rwantare s->ton_seq_max[pmdev->page] = pmbus_receive16(pmdev); 531*7215456aSTitus Rwantare } 532*7215456aSTitus Rwantare break; 533*7215456aSTitus Rwantare 534*7215456aSTitus Rwantare case MAX34451_MFR_PWM_CONFIG: /* R/W 32 */ 535*7215456aSTitus Rwantare if (pmdev->page < 12) { 536*7215456aSTitus Rwantare s->pwm_config[pmdev->page] = pmbus_receive32(pmdev); 537*7215456aSTitus Rwantare } 538*7215456aSTitus Rwantare break; 539*7215456aSTitus Rwantare 540*7215456aSTitus Rwantare case MAX34451_MFR_SEQ_CONFIG: /* R/W 32 */ 541*7215456aSTitus Rwantare if (pmdev->page < 12) { 542*7215456aSTitus Rwantare s->seq_config[pmdev->page] = pmbus_receive32(pmdev); 543*7215456aSTitus Rwantare } 544*7215456aSTitus Rwantare break; 545*7215456aSTitus Rwantare 546*7215456aSTitus Rwantare case MAX34451_MFR_TEMP_SENSOR_CONFIG: /* R/W word */ 547*7215456aSTitus Rwantare if (15 < pmdev->page && pmdev->page < 21) { 548*7215456aSTitus Rwantare s->temp_sensor_config[pmdev->page % 16] 549*7215456aSTitus Rwantare = pmbus_receive16(pmdev); 550*7215456aSTitus Rwantare } 551*7215456aSTitus Rwantare break; 552*7215456aSTitus Rwantare 553*7215456aSTitus Rwantare case MAX34451_MFR_CRC: /* R/W word */ 554*7215456aSTitus Rwantare s->crc = pmbus_receive16(pmdev); 555*7215456aSTitus Rwantare break; 556*7215456aSTitus Rwantare 557*7215456aSTitus Rwantare case MAX34451_MFR_NV_FAULT_LOG: 558*7215456aSTitus Rwantare case MAX34451_MFR_FW_SERIAL: 559*7215456aSTitus Rwantare case MAX34451_MFR_IOUT_AVG: 560*7215456aSTitus Rwantare /* Read only commands */ 561*7215456aSTitus Rwantare pmdev->pages[index].status_word |= PMBUS_STATUS_CML; 562*7215456aSTitus Rwantare pmdev->pages[index].status_cml |= PB_CML_FAULT_INVALID_DATA; 563*7215456aSTitus Rwantare qemu_log_mask(LOG_GUEST_ERROR, 564*7215456aSTitus Rwantare "%s: writing to read-only register 0x%02x\n", 565*7215456aSTitus Rwantare __func__, pmdev->code); 566*7215456aSTitus Rwantare break; 567*7215456aSTitus Rwantare 568*7215456aSTitus Rwantare default: 569*7215456aSTitus Rwantare qemu_log_mask(LOG_GUEST_ERROR, 570*7215456aSTitus Rwantare "%s: writing to unsupported register: 0x%02x\n", 571*7215456aSTitus Rwantare __func__, pmdev->code); 572*7215456aSTitus Rwantare break; 573*7215456aSTitus Rwantare } 574*7215456aSTitus Rwantare 575*7215456aSTitus Rwantare return 0; 576*7215456aSTitus Rwantare } 577*7215456aSTitus Rwantare 578*7215456aSTitus Rwantare static void max34451_get(Object *obj, Visitor *v, const char *name, 579*7215456aSTitus Rwantare void *opaque, Error **errp) 580*7215456aSTitus Rwantare { 581*7215456aSTitus Rwantare visit_type_uint16(v, name, (uint16_t *)opaque, errp); 582*7215456aSTitus Rwantare } 583*7215456aSTitus Rwantare 584*7215456aSTitus Rwantare static void max34451_set(Object *obj, Visitor *v, const char *name, 585*7215456aSTitus Rwantare void *opaque, Error **errp) 586*7215456aSTitus Rwantare { 587*7215456aSTitus Rwantare MAX34451State *s = MAX34451(obj); 588*7215456aSTitus Rwantare uint16_t *internal = opaque; 589*7215456aSTitus Rwantare uint16_t value; 590*7215456aSTitus Rwantare if (!visit_type_uint16(v, name, &value, errp)) { 591*7215456aSTitus Rwantare return; 592*7215456aSTitus Rwantare } 593*7215456aSTitus Rwantare 594*7215456aSTitus Rwantare *internal = value; 595*7215456aSTitus Rwantare max34451_check_limits(s); 596*7215456aSTitus Rwantare } 597*7215456aSTitus Rwantare 598*7215456aSTitus Rwantare /* used to init uint16_t arrays */ 599*7215456aSTitus Rwantare static inline void *memset_word(void *s, uint16_t c, size_t n) 600*7215456aSTitus Rwantare { 601*7215456aSTitus Rwantare size_t i; 602*7215456aSTitus Rwantare uint16_t *p = s; 603*7215456aSTitus Rwantare 604*7215456aSTitus Rwantare for (i = 0; i < n; i++) { 605*7215456aSTitus Rwantare p[i] = c; 606*7215456aSTitus Rwantare } 607*7215456aSTitus Rwantare 608*7215456aSTitus Rwantare return s; 609*7215456aSTitus Rwantare } 610*7215456aSTitus Rwantare 611*7215456aSTitus Rwantare static void max34451_exit_reset(Object *obj) 612*7215456aSTitus Rwantare { 613*7215456aSTitus Rwantare PMBusDevice *pmdev = PMBUS_DEVICE(obj); 614*7215456aSTitus Rwantare MAX34451State *s = MAX34451(obj); 615*7215456aSTitus Rwantare pmdev->capability = DEFAULT_CAPABILITY; 616*7215456aSTitus Rwantare 617*7215456aSTitus Rwantare for (int i = 0; i < MAX34451_NUM_PAGES; i++) { 618*7215456aSTitus Rwantare pmdev->pages[i].operation = DEFAULT_OP_ON; 619*7215456aSTitus Rwantare pmdev->pages[i].on_off_config = DEFAULT_ON_OFF_CONFIG; 620*7215456aSTitus Rwantare pmdev->pages[i].revision = 0x11; 621*7215456aSTitus Rwantare pmdev->pages[i].vout_mode = DEFAULT_VOUT_MODE; 622*7215456aSTitus Rwantare } 623*7215456aSTitus Rwantare 624*7215456aSTitus Rwantare for (int i = 0; i < MAX34451_NUM_PWR_DEVICES; i++) { 625*7215456aSTitus Rwantare pmdev->pages[i].vout_scale_monitor = DEFAULT_SCALE; 626*7215456aSTitus Rwantare pmdev->pages[i].vout_ov_fault_limit = DEFAULT_OV_LIMIT; 627*7215456aSTitus Rwantare pmdev->pages[i].vout_ov_warn_limit = DEFAULT_OV_LIMIT; 628*7215456aSTitus Rwantare pmdev->pages[i].iout_oc_warn_limit = DEFAULT_OC_LIMIT; 629*7215456aSTitus Rwantare pmdev->pages[i].iout_oc_fault_limit = DEFAULT_OC_LIMIT; 630*7215456aSTitus Rwantare } 631*7215456aSTitus Rwantare 632*7215456aSTitus Rwantare for (int i = 0; i < MAX34451_NUM_MARGINED_PSU; i++) { 633*7215456aSTitus Rwantare pmdev->pages[i].ton_max_fault_limit = DEFAULT_TON_FAULT_LIMIT; 634*7215456aSTitus Rwantare } 635*7215456aSTitus Rwantare 636*7215456aSTitus Rwantare for (int i = 16; i < MAX34451_NUM_TEMP_DEVICES + 16; i++) { 637*7215456aSTitus Rwantare pmdev->pages[i].read_temperature_1 = DEFAULT_TEMPERATURE; 638*7215456aSTitus Rwantare pmdev->pages[i].ot_warn_limit = DEFAULT_OT_LIMIT; 639*7215456aSTitus Rwantare pmdev->pages[i].ot_fault_limit = DEFAULT_OT_LIMIT; 640*7215456aSTitus Rwantare } 641*7215456aSTitus Rwantare 642*7215456aSTitus Rwantare memset_word(s->ton_max_fault_limit, DEFAULT_TON_FAULT_LIMIT, 643*7215456aSTitus Rwantare MAX34451_NUM_MARGINED_PSU); 644*7215456aSTitus Rwantare memset_word(s->channel_config, DEFAULT_CHANNEL_CONFIG, 645*7215456aSTitus Rwantare MAX34451_NUM_PWR_DEVICES); 646*7215456aSTitus Rwantare memset_word(s->vout_min, DEFAULT_VMIN, MAX34451_NUM_PWR_DEVICES); 647*7215456aSTitus Rwantare 648*7215456aSTitus Rwantare s->mfr_location = DEFAULT_TEXT; 649*7215456aSTitus Rwantare s->mfr_date = DEFAULT_TEXT; 650*7215456aSTitus Rwantare s->mfr_serial = DEFAULT_TEXT; 651*7215456aSTitus Rwantare } 652*7215456aSTitus Rwantare 653*7215456aSTitus Rwantare static const VMStateDescription vmstate_max34451 = { 654*7215456aSTitus Rwantare .name = TYPE_MAX34451, 655*7215456aSTitus Rwantare .version_id = 0, 656*7215456aSTitus Rwantare .minimum_version_id = 0, 657*7215456aSTitus Rwantare .fields = (VMStateField[]){ 658*7215456aSTitus Rwantare VMSTATE_PMBUS_DEVICE(parent, MAX34451State), 659*7215456aSTitus Rwantare VMSTATE_UINT16_ARRAY(power_good_on, MAX34451State, 660*7215456aSTitus Rwantare MAX34451_NUM_PWR_DEVICES), 661*7215456aSTitus Rwantare VMSTATE_UINT16_ARRAY(power_good_off, MAX34451State, 662*7215456aSTitus Rwantare MAX34451_NUM_PWR_DEVICES), 663*7215456aSTitus Rwantare VMSTATE_UINT16_ARRAY(ton_delay, MAX34451State, 664*7215456aSTitus Rwantare MAX34451_NUM_MARGINED_PSU), 665*7215456aSTitus Rwantare VMSTATE_UINT16_ARRAY(ton_max_fault_limit, MAX34451State, 666*7215456aSTitus Rwantare MAX34451_NUM_MARGINED_PSU), 667*7215456aSTitus Rwantare VMSTATE_UINT16_ARRAY(toff_delay, MAX34451State, 668*7215456aSTitus Rwantare MAX34451_NUM_MARGINED_PSU), 669*7215456aSTitus Rwantare VMSTATE_UINT8_ARRAY(status_mfr_specific, MAX34451State, 670*7215456aSTitus Rwantare MAX34451_NUM_PWR_DEVICES), 671*7215456aSTitus Rwantare VMSTATE_UINT64(mfr_location, MAX34451State), 672*7215456aSTitus Rwantare VMSTATE_UINT64(mfr_date, MAX34451State), 673*7215456aSTitus Rwantare VMSTATE_UINT64(mfr_serial, MAX34451State), 674*7215456aSTitus Rwantare VMSTATE_UINT16(mfr_mode, MAX34451State), 675*7215456aSTitus Rwantare VMSTATE_UINT32_ARRAY(psen_config, MAX34451State, 676*7215456aSTitus Rwantare MAX34451_NUM_MARGINED_PSU), 677*7215456aSTitus Rwantare VMSTATE_UINT16_ARRAY(vout_peak, MAX34451State, 678*7215456aSTitus Rwantare MAX34451_NUM_PWR_DEVICES), 679*7215456aSTitus Rwantare VMSTATE_UINT16_ARRAY(iout_peak, MAX34451State, 680*7215456aSTitus Rwantare MAX34451_NUM_PWR_DEVICES), 681*7215456aSTitus Rwantare VMSTATE_UINT16_ARRAY(temperature_peak, MAX34451State, 682*7215456aSTitus Rwantare MAX34451_NUM_TEMP_DEVICES), 683*7215456aSTitus Rwantare VMSTATE_UINT16_ARRAY(vout_min, MAX34451State, MAX34451_NUM_PWR_DEVICES), 684*7215456aSTitus Rwantare VMSTATE_UINT16(nv_log_config, MAX34451State), 685*7215456aSTitus Rwantare VMSTATE_UINT32_ARRAY(fault_response, MAX34451State, 686*7215456aSTitus Rwantare MAX34451_NUM_PWR_DEVICES), 687*7215456aSTitus Rwantare VMSTATE_UINT16(fault_retry, MAX34451State), 688*7215456aSTitus Rwantare VMSTATE_UINT32(fault_log, MAX34451State), 689*7215456aSTitus Rwantare VMSTATE_UINT32(time_count, MAX34451State), 690*7215456aSTitus Rwantare VMSTATE_UINT16_ARRAY(margin_config, MAX34451State, 691*7215456aSTitus Rwantare MAX34451_NUM_MARGINED_PSU), 692*7215456aSTitus Rwantare VMSTATE_UINT16(fw_serial, MAX34451State), 693*7215456aSTitus Rwantare VMSTATE_UINT16_ARRAY(iout_avg, MAX34451State, MAX34451_NUM_PWR_DEVICES), 694*7215456aSTitus Rwantare VMSTATE_UINT16_ARRAY(channel_config, MAX34451State, 695*7215456aSTitus Rwantare MAX34451_NUM_PWR_DEVICES), 696*7215456aSTitus Rwantare VMSTATE_UINT16_ARRAY(ton_seq_max, MAX34451State, 697*7215456aSTitus Rwantare MAX34451_NUM_MARGINED_PSU), 698*7215456aSTitus Rwantare VMSTATE_UINT32_ARRAY(pwm_config, MAX34451State, 699*7215456aSTitus Rwantare MAX34451_NUM_MARGINED_PSU), 700*7215456aSTitus Rwantare VMSTATE_UINT32_ARRAY(seq_config, MAX34451State, 701*7215456aSTitus Rwantare MAX34451_NUM_MARGINED_PSU), 702*7215456aSTitus Rwantare VMSTATE_UINT16_ARRAY(temp_sensor_config, MAX34451State, 703*7215456aSTitus Rwantare MAX34451_NUM_TEMP_DEVICES), 704*7215456aSTitus Rwantare VMSTATE_UINT16(store_single, MAX34451State), 705*7215456aSTitus Rwantare VMSTATE_UINT16(crc, MAX34451State), 706*7215456aSTitus Rwantare VMSTATE_END_OF_LIST() 707*7215456aSTitus Rwantare } 708*7215456aSTitus Rwantare }; 709*7215456aSTitus Rwantare 710*7215456aSTitus Rwantare static void max34451_init(Object *obj) 711*7215456aSTitus Rwantare { 712*7215456aSTitus Rwantare PMBusDevice *pmdev = PMBUS_DEVICE(obj); 713*7215456aSTitus Rwantare uint64_t psu_flags = PB_HAS_VOUT | PB_HAS_IOUT | PB_HAS_VOUT_MODE | 714*7215456aSTitus Rwantare PB_HAS_IOUT_GAIN; 715*7215456aSTitus Rwantare 716*7215456aSTitus Rwantare for (int i = 0; i < MAX34451_NUM_PWR_DEVICES; i++) { 717*7215456aSTitus Rwantare pmbus_page_config(pmdev, i, psu_flags); 718*7215456aSTitus Rwantare } 719*7215456aSTitus Rwantare 720*7215456aSTitus Rwantare for (int i = 0; i < MAX34451_NUM_MARGINED_PSU; i++) { 721*7215456aSTitus Rwantare pmbus_page_config(pmdev, i, psu_flags | PB_HAS_VOUT_MARGIN); 722*7215456aSTitus Rwantare } 723*7215456aSTitus Rwantare 724*7215456aSTitus Rwantare for (int i = 16; i < MAX34451_NUM_TEMP_DEVICES + 16; i++) { 725*7215456aSTitus Rwantare pmbus_page_config(pmdev, i, PB_HAS_TEMPERATURE | PB_HAS_VOUT_MODE); 726*7215456aSTitus Rwantare } 727*7215456aSTitus Rwantare 728*7215456aSTitus Rwantare /* get and set the voltage in millivolts, max is 32767 mV */ 729*7215456aSTitus Rwantare for (int i = 0; i < MAX34451_NUM_PWR_DEVICES; i++) { 730*7215456aSTitus Rwantare object_property_add(obj, "vout[*]", "uint16", 731*7215456aSTitus Rwantare max34451_get, 732*7215456aSTitus Rwantare max34451_set, NULL, &pmdev->pages[i].read_vout); 733*7215456aSTitus Rwantare } 734*7215456aSTitus Rwantare 735*7215456aSTitus Rwantare /* 736*7215456aSTitus Rwantare * get and set the temperature of the internal temperature sensor in 737*7215456aSTitus Rwantare * centidegrees Celcius i.e.: 2500 -> 25.00 C, max is 327.67 C 738*7215456aSTitus Rwantare */ 739*7215456aSTitus Rwantare for (int i = 0; i < MAX34451_NUM_TEMP_DEVICES; i++) { 740*7215456aSTitus Rwantare object_property_add(obj, "temperature[*]", "uint16", 741*7215456aSTitus Rwantare max34451_get, 742*7215456aSTitus Rwantare max34451_set, 743*7215456aSTitus Rwantare NULL, 744*7215456aSTitus Rwantare &pmdev->pages[i + 16].read_temperature_1); 745*7215456aSTitus Rwantare } 746*7215456aSTitus Rwantare 747*7215456aSTitus Rwantare } 748*7215456aSTitus Rwantare 749*7215456aSTitus Rwantare static void max34451_class_init(ObjectClass *klass, void *data) 750*7215456aSTitus Rwantare { 751*7215456aSTitus Rwantare ResettableClass *rc = RESETTABLE_CLASS(klass); 752*7215456aSTitus Rwantare DeviceClass *dc = DEVICE_CLASS(klass); 753*7215456aSTitus Rwantare PMBusDeviceClass *k = PMBUS_DEVICE_CLASS(klass); 754*7215456aSTitus Rwantare dc->desc = "Maxim MAX34451 16-Channel V/I monitor"; 755*7215456aSTitus Rwantare dc->vmsd = &vmstate_max34451; 756*7215456aSTitus Rwantare k->write_data = max34451_write_data; 757*7215456aSTitus Rwantare k->receive_byte = max34451_read_byte; 758*7215456aSTitus Rwantare k->device_num_pages = MAX34451_NUM_PAGES; 759*7215456aSTitus Rwantare rc->phases.exit = max34451_exit_reset; 760*7215456aSTitus Rwantare } 761*7215456aSTitus Rwantare 762*7215456aSTitus Rwantare static const TypeInfo max34451_info = { 763*7215456aSTitus Rwantare .name = TYPE_MAX34451, 764*7215456aSTitus Rwantare .parent = TYPE_PMBUS_DEVICE, 765*7215456aSTitus Rwantare .instance_size = sizeof(MAX34451State), 766*7215456aSTitus Rwantare .instance_init = max34451_init, 767*7215456aSTitus Rwantare .class_init = max34451_class_init, 768*7215456aSTitus Rwantare }; 769*7215456aSTitus Rwantare 770*7215456aSTitus Rwantare static void max34451_register_types(void) 771*7215456aSTitus Rwantare { 772*7215456aSTitus Rwantare type_register_static(&max34451_info); 773*7215456aSTitus Rwantare } 774*7215456aSTitus Rwantare 775*7215456aSTitus Rwantare type_init(max34451_register_types) 776