17215456aSTitus Rwantare /* 27215456aSTitus Rwantare * Maxim MAX34451 PMBus 16-Channel V/I monitor and 12-Channel Sequencer/Marginer 37215456aSTitus Rwantare * 47215456aSTitus Rwantare * Copyright 2021 Google LLC 57215456aSTitus Rwantare * 67215456aSTitus Rwantare * SPDX-License-Identifier: GPL-2.0-or-later 77215456aSTitus Rwantare */ 87215456aSTitus Rwantare 97215456aSTitus Rwantare #include "qemu/osdep.h" 107215456aSTitus Rwantare #include "hw/i2c/pmbus_device.h" 117215456aSTitus Rwantare #include "hw/irq.h" 127215456aSTitus Rwantare #include "migration/vmstate.h" 137215456aSTitus Rwantare #include "qapi/error.h" 147215456aSTitus Rwantare #include "qapi/visitor.h" 157215456aSTitus Rwantare #include "qemu/log.h" 167215456aSTitus Rwantare #include "qemu/module.h" 177215456aSTitus Rwantare 187215456aSTitus Rwantare #define TYPE_MAX34451 "max34451" 197215456aSTitus Rwantare #define MAX34451(obj) OBJECT_CHECK(MAX34451State, (obj), TYPE_MAX34451) 207215456aSTitus Rwantare 217215456aSTitus Rwantare #define MAX34451_MFR_MODE 0xD1 227215456aSTitus Rwantare #define MAX34451_MFR_PSEN_CONFIG 0xD2 237215456aSTitus Rwantare #define MAX34451_MFR_VOUT_PEAK 0xD4 247215456aSTitus Rwantare #define MAX34451_MFR_IOUT_PEAK 0xD5 257215456aSTitus Rwantare #define MAX34451_MFR_TEMPERATURE_PEAK 0xD6 267215456aSTitus Rwantare #define MAX34451_MFR_VOUT_MIN 0xD7 277215456aSTitus Rwantare #define MAX34451_MFR_NV_LOG_CONFIG 0xD8 287215456aSTitus Rwantare #define MAX34451_MFR_FAULT_RESPONSE 0xD9 297215456aSTitus Rwantare #define MAX34451_MFR_FAULT_RETRY 0xDA 307215456aSTitus Rwantare #define MAX34451_MFR_NV_FAULT_LOG 0xDC 317215456aSTitus Rwantare #define MAX34451_MFR_TIME_COUNT 0xDD 327215456aSTitus Rwantare #define MAX34451_MFR_MARGIN_CONFIG 0xDF 337215456aSTitus Rwantare #define MAX34451_MFR_FW_SERIAL 0xE0 347215456aSTitus Rwantare #define MAX34451_MFR_IOUT_AVG 0xE2 357215456aSTitus Rwantare #define MAX34451_MFR_CHANNEL_CONFIG 0xE4 367215456aSTitus Rwantare #define MAX34451_MFR_TON_SEQ_MAX 0xE6 377215456aSTitus Rwantare #define MAX34451_MFR_PWM_CONFIG 0xE7 387215456aSTitus Rwantare #define MAX34451_MFR_SEQ_CONFIG 0xE8 397215456aSTitus Rwantare #define MAX34451_MFR_STORE_ALL 0xEE 407215456aSTitus Rwantare #define MAX34451_MFR_RESTORE_ALL 0xEF 417215456aSTitus Rwantare #define MAX34451_MFR_TEMP_SENSOR_CONFIG 0xF0 427215456aSTitus Rwantare #define MAX34451_MFR_STORE_SINGLE 0xFC 437215456aSTitus Rwantare #define MAX34451_MFR_CRC 0xFE 447215456aSTitus Rwantare 457215456aSTitus Rwantare #define MAX34451_NUM_MARGINED_PSU 12 467215456aSTitus Rwantare #define MAX34451_NUM_PWR_DEVICES 16 477215456aSTitus Rwantare #define MAX34451_NUM_TEMP_DEVICES 5 487215456aSTitus Rwantare #define MAX34451_NUM_PAGES 21 497215456aSTitus Rwantare 507215456aSTitus Rwantare #define DEFAULT_OP_ON 0x80 517215456aSTitus Rwantare #define DEFAULT_CAPABILITY 0x20 527215456aSTitus Rwantare #define DEFAULT_ON_OFF_CONFIG 0x1a 537215456aSTitus Rwantare #define DEFAULT_VOUT_MODE 0x40 547215456aSTitus Rwantare #define DEFAULT_TEMPERATURE 2500 557215456aSTitus Rwantare #define DEFAULT_SCALE 0x7FFF 567215456aSTitus Rwantare #define DEFAULT_OV_LIMIT 0x7FFF 577215456aSTitus Rwantare #define DEFAULT_OC_LIMIT 0x7FFF 587215456aSTitus Rwantare #define DEFAULT_OT_LIMIT 0x7FFF 597215456aSTitus Rwantare #define DEFAULT_VMIN 0x7FFF 607215456aSTitus Rwantare #define DEFAULT_TON_FAULT_LIMIT 0xFFFF 617215456aSTitus Rwantare #define DEFAULT_CHANNEL_CONFIG 0x20 627215456aSTitus Rwantare #define DEFAULT_TEXT 0x3130313031303130 637215456aSTitus Rwantare 647215456aSTitus Rwantare /** 657215456aSTitus Rwantare * MAX34451State: 667215456aSTitus Rwantare * @code: The command code received 677215456aSTitus Rwantare * @page: Each page corresponds to a device monitored by the Max 34451 687215456aSTitus Rwantare * The page register determines the available commands depending on device 697215456aSTitus Rwantare ___________________________________________________________________________ 707215456aSTitus Rwantare | 0 | Power supply monitored by RS0, controlled by PSEN0, and | 717215456aSTitus Rwantare | | margined with PWM0. | 727215456aSTitus Rwantare |_______|___________________________________________________________________| 737215456aSTitus Rwantare | 1 | Power supply monitored by RS1, controlled by PSEN1, and | 747215456aSTitus Rwantare | | margined with PWM1. | 757215456aSTitus Rwantare |_______|___________________________________________________________________| 767215456aSTitus Rwantare | 2 | Power supply monitored by RS2, controlled by PSEN2, and | 777215456aSTitus Rwantare | | margined with PWM2. | 787215456aSTitus Rwantare |_______|___________________________________________________________________| 797215456aSTitus Rwantare | 3 | Power supply monitored by RS3, controlled by PSEN3, and | 807215456aSTitus Rwantare | | margined with PWM3. | 817215456aSTitus Rwantare |_______|___________________________________________________________________| 827215456aSTitus Rwantare | 4 | Power supply monitored by RS4, controlled by PSEN4, and | 837215456aSTitus Rwantare | | margined with PWM4. | 847215456aSTitus Rwantare |_______|___________________________________________________________________| 857215456aSTitus Rwantare | 5 | Power supply monitored by RS5, controlled by PSEN5, and | 867215456aSTitus Rwantare | | margined with PWM5. | 877215456aSTitus Rwantare |_______|___________________________________________________________________| 887215456aSTitus Rwantare | 6 | Power supply monitored by RS6, controlled by PSEN6, and | 897215456aSTitus Rwantare | | margined with PWM6. | 907215456aSTitus Rwantare |_______|___________________________________________________________________| 917215456aSTitus Rwantare | 7 | Power supply monitored by RS7, controlled by PSEN7, and | 927215456aSTitus Rwantare | | margined with PWM7. | 937215456aSTitus Rwantare |_______|___________________________________________________________________| 947215456aSTitus Rwantare | 8 | Power supply monitored by RS8, controlled by PSEN8, and | 957215456aSTitus Rwantare | | optionally margined by OUT0 of external DS4424 at I2C address A0h.| 967215456aSTitus Rwantare |_______|___________________________________________________________________| 977215456aSTitus Rwantare | 9 | Power supply monitored by RS9, controlled by PSEN9, and | 987215456aSTitus Rwantare | | optionally margined by OUT1 of external DS4424 at I2C address A0h.| 997215456aSTitus Rwantare |_______|___________________________________________________________________| 1007215456aSTitus Rwantare | 10 | Power supply monitored by RS10, controlled by PSEN10, and | 1017215456aSTitus Rwantare | | optionally margined by OUT2 of external DS4424 at I2C address A0h.| 1027215456aSTitus Rwantare |_______|___________________________________________________________________| 1037215456aSTitus Rwantare | 11 | Power supply monitored by RS11, controlled by PSEN11, and | 1047215456aSTitus Rwantare | | optionally margined by OUT3 of external DS4424 at I2C address A0h.| 1057215456aSTitus Rwantare |_______|___________________________________________________________________| 1067215456aSTitus Rwantare | 12 | ADC channel 12 (monitors voltage or current) or GPI. | 1077215456aSTitus Rwantare |_______|___________________________________________________________________| 1087215456aSTitus Rwantare | 13 | ADC channel 13 (monitors voltage or current) or GPI. | 1097215456aSTitus Rwantare |_______|___________________________________________________________________| 1107215456aSTitus Rwantare | 14 | ADC channel 14 (monitors voltage or current) or GPI. | 1117215456aSTitus Rwantare |_______|___________________________________________________________________| 1127215456aSTitus Rwantare | 15 | ADC channel 15 (monitors voltage or current) or GPI. | 1137215456aSTitus Rwantare |_______|___________________________________________________________________| 1147215456aSTitus Rwantare | 16 | Internal temperature sensor. | 1157215456aSTitus Rwantare |_______|___________________________________________________________________| 1167215456aSTitus Rwantare | 17 | External DS75LV temperature sensor with I2C address 90h. | 1177215456aSTitus Rwantare |_______|___________________________________________________________________| 1187215456aSTitus Rwantare | 18 | External DS75LV temperature sensor with I2C address 92h. | 1197215456aSTitus Rwantare |_______|___________________________________________________________________| 1207215456aSTitus Rwantare | 19 | External DS75LV temperature sensor with I2C address 94h. | 1217215456aSTitus Rwantare |_______|___________________________________________________________________| 1227215456aSTitus Rwantare | 20 | External DS75LV temperature sensor with I2C address 96h. | 1237215456aSTitus Rwantare |_______|___________________________________________________________________| 1247215456aSTitus Rwantare | 21=E2=80=93254| Reserved. | 1257215456aSTitus Rwantare |_______|___________________________________________________________________| 1267215456aSTitus Rwantare | 255 | Applies to all pages. | 1277215456aSTitus Rwantare |_______|___________________________________________________________________| 1287215456aSTitus Rwantare * 1297215456aSTitus Rwantare * @operation: Turn on and off power supplies 1307215456aSTitus Rwantare * @on_off_config: Configure the power supply on and off transition behaviour 1317215456aSTitus Rwantare * @write_protect: protect against changes to the device's memory 1327215456aSTitus Rwantare * @vout_margin_high: the voltage when OPERATION is set to margin high 1337215456aSTitus Rwantare * @vout_margin_low: the voltage when OPERATION is set to margin low 1347215456aSTitus Rwantare * @vout_scale: scale ADC reading to actual device reading if different 1357215456aSTitus Rwantare * @iout_cal_gain: set ratio of the voltage at the ADC input to sensed current 1367215456aSTitus Rwantare */ 1377215456aSTitus Rwantare typedef struct MAX34451State { 1387215456aSTitus Rwantare PMBusDevice parent; 1397215456aSTitus Rwantare 1407215456aSTitus Rwantare uint16_t power_good_on[MAX34451_NUM_PWR_DEVICES]; 1417215456aSTitus Rwantare uint16_t power_good_off[MAX34451_NUM_PWR_DEVICES]; 1427215456aSTitus Rwantare uint16_t ton_delay[MAX34451_NUM_MARGINED_PSU]; 1437215456aSTitus Rwantare uint16_t ton_max_fault_limit[MAX34451_NUM_MARGINED_PSU]; 1447215456aSTitus Rwantare uint16_t toff_delay[MAX34451_NUM_MARGINED_PSU]; 1457215456aSTitus Rwantare uint8_t status_mfr_specific[MAX34451_NUM_PWR_DEVICES]; 1467215456aSTitus Rwantare /* Manufacturer specific function */ 1477215456aSTitus Rwantare uint64_t mfr_location; 1487215456aSTitus Rwantare uint64_t mfr_date; 1497215456aSTitus Rwantare uint64_t mfr_serial; 1507215456aSTitus Rwantare uint16_t mfr_mode; 1517215456aSTitus Rwantare uint32_t psen_config[MAX34451_NUM_MARGINED_PSU]; 1527215456aSTitus Rwantare uint16_t vout_peak[MAX34451_NUM_PWR_DEVICES]; 1537215456aSTitus Rwantare uint16_t iout_peak[MAX34451_NUM_PWR_DEVICES]; 1547215456aSTitus Rwantare uint16_t temperature_peak[MAX34451_NUM_TEMP_DEVICES]; 1557215456aSTitus Rwantare uint16_t vout_min[MAX34451_NUM_PWR_DEVICES]; 1567215456aSTitus Rwantare uint16_t nv_log_config; 1577215456aSTitus Rwantare uint32_t fault_response[MAX34451_NUM_PWR_DEVICES]; 1587215456aSTitus Rwantare uint16_t fault_retry; 1597215456aSTitus Rwantare uint32_t fault_log; 1607215456aSTitus Rwantare uint32_t time_count; 1617215456aSTitus Rwantare uint16_t margin_config[MAX34451_NUM_MARGINED_PSU]; 1627215456aSTitus Rwantare uint16_t fw_serial; 1637215456aSTitus Rwantare uint16_t iout_avg[MAX34451_NUM_PWR_DEVICES]; 1647215456aSTitus Rwantare uint16_t channel_config[MAX34451_NUM_PWR_DEVICES]; 1657215456aSTitus Rwantare uint16_t ton_seq_max[MAX34451_NUM_MARGINED_PSU]; 1667215456aSTitus Rwantare uint32_t pwm_config[MAX34451_NUM_MARGINED_PSU]; 1677215456aSTitus Rwantare uint32_t seq_config[MAX34451_NUM_MARGINED_PSU]; 1687215456aSTitus Rwantare uint16_t temp_sensor_config[MAX34451_NUM_TEMP_DEVICES]; 1697215456aSTitus Rwantare uint16_t store_single; 1707215456aSTitus Rwantare uint16_t crc; 1717215456aSTitus Rwantare } MAX34451State; 1727215456aSTitus Rwantare 1737215456aSTitus Rwantare 1747215456aSTitus Rwantare static void max34451_check_limits(MAX34451State *s) 1757215456aSTitus Rwantare { 1767215456aSTitus Rwantare PMBusDevice *pmdev = PMBUS_DEVICE(s); 1777215456aSTitus Rwantare 1787215456aSTitus Rwantare pmbus_check_limits(pmdev); 1797215456aSTitus Rwantare 1807215456aSTitus Rwantare for (int i = 0; i < MAX34451_NUM_PWR_DEVICES; i++) { 1817215456aSTitus Rwantare if (pmdev->pages[i].read_vout == 0) { /* PSU disabled */ 1827215456aSTitus Rwantare continue; 1837215456aSTitus Rwantare } 1847215456aSTitus Rwantare 1857215456aSTitus Rwantare if (pmdev->pages[i].read_vout > s->vout_peak[i]) { 1867215456aSTitus Rwantare s->vout_peak[i] = pmdev->pages[i].read_vout; 1877215456aSTitus Rwantare } 1887215456aSTitus Rwantare 1897215456aSTitus Rwantare if (pmdev->pages[i].read_vout < s->vout_min[i]) { 1907215456aSTitus Rwantare s->vout_min[i] = pmdev->pages[i].read_vout; 1917215456aSTitus Rwantare } 1927215456aSTitus Rwantare 1937215456aSTitus Rwantare if (pmdev->pages[i].read_iout > s->iout_peak[i]) { 1947215456aSTitus Rwantare s->iout_peak[i] = pmdev->pages[i].read_iout; 1957215456aSTitus Rwantare } 1967215456aSTitus Rwantare } 1977215456aSTitus Rwantare 1987215456aSTitus Rwantare for (int i = 0; i < MAX34451_NUM_TEMP_DEVICES; i++) { 1997215456aSTitus Rwantare if (pmdev->pages[i + 16].read_temperature_1 > s->temperature_peak[i]) { 2007215456aSTitus Rwantare s->temperature_peak[i] = pmdev->pages[i + 16].read_temperature_1; 2017215456aSTitus Rwantare } 2027215456aSTitus Rwantare } 2037215456aSTitus Rwantare } 2047215456aSTitus Rwantare 2057215456aSTitus Rwantare static uint8_t max34451_read_byte(PMBusDevice *pmdev) 2067215456aSTitus Rwantare { 2077215456aSTitus Rwantare MAX34451State *s = MAX34451(pmdev); 2087215456aSTitus Rwantare switch (pmdev->code) { 2097215456aSTitus Rwantare 2107215456aSTitus Rwantare case PMBUS_POWER_GOOD_ON: 2117215456aSTitus Rwantare if (pmdev->page < 16) { 2127215456aSTitus Rwantare pmbus_send16(pmdev, s->power_good_on[pmdev->page]); 2137215456aSTitus Rwantare } 2147215456aSTitus Rwantare break; 2157215456aSTitus Rwantare 2167215456aSTitus Rwantare case PMBUS_POWER_GOOD_OFF: 2177215456aSTitus Rwantare if (pmdev->page < 16) { 2187215456aSTitus Rwantare pmbus_send16(pmdev, s->power_good_off[pmdev->page]); 2197215456aSTitus Rwantare } 2207215456aSTitus Rwantare break; 2217215456aSTitus Rwantare 2227215456aSTitus Rwantare case PMBUS_TON_DELAY: 2237215456aSTitus Rwantare if (pmdev->page < 12) { 2247215456aSTitus Rwantare pmbus_send16(pmdev, s->ton_delay[pmdev->page]); 2257215456aSTitus Rwantare } 2267215456aSTitus Rwantare break; 2277215456aSTitus Rwantare 2287215456aSTitus Rwantare case PMBUS_TON_MAX_FAULT_LIMIT: 2297215456aSTitus Rwantare if (pmdev->page < 12) { 2307215456aSTitus Rwantare pmbus_send16(pmdev, s->ton_max_fault_limit[pmdev->page]); 2317215456aSTitus Rwantare } 2327215456aSTitus Rwantare break; 2337215456aSTitus Rwantare 2347215456aSTitus Rwantare case PMBUS_TOFF_DELAY: 2357215456aSTitus Rwantare if (pmdev->page < 12) { 2367215456aSTitus Rwantare pmbus_send16(pmdev, s->toff_delay[pmdev->page]); 2377215456aSTitus Rwantare } 2387215456aSTitus Rwantare break; 2397215456aSTitus Rwantare 2407215456aSTitus Rwantare case PMBUS_STATUS_MFR_SPECIFIC: 2417215456aSTitus Rwantare if (pmdev->page < 16) { 2427215456aSTitus Rwantare pmbus_send8(pmdev, s->status_mfr_specific[pmdev->page]); 2437215456aSTitus Rwantare } 2447215456aSTitus Rwantare break; 2457215456aSTitus Rwantare 2467215456aSTitus Rwantare case PMBUS_MFR_ID: 2477215456aSTitus Rwantare pmbus_send8(pmdev, 0x4d); /* Maxim */ 2487215456aSTitus Rwantare break; 2497215456aSTitus Rwantare 2507215456aSTitus Rwantare case PMBUS_MFR_MODEL: 2517215456aSTitus Rwantare pmbus_send8(pmdev, 0x59); 2527215456aSTitus Rwantare break; 2537215456aSTitus Rwantare 2547215456aSTitus Rwantare case PMBUS_MFR_LOCATION: 2557215456aSTitus Rwantare pmbus_send64(pmdev, s->mfr_location); 2567215456aSTitus Rwantare break; 2577215456aSTitus Rwantare 2587215456aSTitus Rwantare case PMBUS_MFR_DATE: 2597215456aSTitus Rwantare pmbus_send64(pmdev, s->mfr_date); 2607215456aSTitus Rwantare break; 2617215456aSTitus Rwantare 2627215456aSTitus Rwantare case PMBUS_MFR_SERIAL: 2637215456aSTitus Rwantare pmbus_send64(pmdev, s->mfr_serial); 2647215456aSTitus Rwantare break; 2657215456aSTitus Rwantare 2667215456aSTitus Rwantare case MAX34451_MFR_MODE: 2677215456aSTitus Rwantare pmbus_send16(pmdev, s->mfr_mode); 2687215456aSTitus Rwantare break; 2697215456aSTitus Rwantare 2707215456aSTitus Rwantare case MAX34451_MFR_PSEN_CONFIG: 2717215456aSTitus Rwantare if (pmdev->page < 12) { 2727215456aSTitus Rwantare pmbus_send32(pmdev, s->psen_config[pmdev->page]); 2737215456aSTitus Rwantare } 2747215456aSTitus Rwantare break; 2757215456aSTitus Rwantare 2767215456aSTitus Rwantare case MAX34451_MFR_VOUT_PEAK: 2777215456aSTitus Rwantare if (pmdev->page < 16) { 2787215456aSTitus Rwantare pmbus_send16(pmdev, s->vout_peak[pmdev->page]); 2797215456aSTitus Rwantare } 2807215456aSTitus Rwantare break; 2817215456aSTitus Rwantare 2827215456aSTitus Rwantare case MAX34451_MFR_IOUT_PEAK: 2837215456aSTitus Rwantare if (pmdev->page < 16) { 2847215456aSTitus Rwantare pmbus_send16(pmdev, s->iout_peak[pmdev->page]); 2857215456aSTitus Rwantare } 2867215456aSTitus Rwantare break; 2877215456aSTitus Rwantare 2887215456aSTitus Rwantare case MAX34451_MFR_TEMPERATURE_PEAK: 2897215456aSTitus Rwantare if (15 < pmdev->page && pmdev->page < 21) { 2907215456aSTitus Rwantare pmbus_send16(pmdev, s->temperature_peak[pmdev->page % 16]); 2917215456aSTitus Rwantare } else { 2927215456aSTitus Rwantare pmbus_send16(pmdev, s->temperature_peak[0]); 2937215456aSTitus Rwantare } 2947215456aSTitus Rwantare break; 2957215456aSTitus Rwantare 2967215456aSTitus Rwantare case MAX34451_MFR_VOUT_MIN: 2977215456aSTitus Rwantare if (pmdev->page < 16) { 2987215456aSTitus Rwantare pmbus_send16(pmdev, s->vout_min[pmdev->page]); 2997215456aSTitus Rwantare } 3007215456aSTitus Rwantare break; 3017215456aSTitus Rwantare 3027215456aSTitus Rwantare case MAX34451_MFR_NV_LOG_CONFIG: 3037215456aSTitus Rwantare pmbus_send16(pmdev, s->nv_log_config); 3047215456aSTitus Rwantare break; 3057215456aSTitus Rwantare 3067215456aSTitus Rwantare case MAX34451_MFR_FAULT_RESPONSE: 3077215456aSTitus Rwantare if (pmdev->page < 16) { 3087215456aSTitus Rwantare pmbus_send32(pmdev, s->fault_response[pmdev->page]); 3097215456aSTitus Rwantare } 3107215456aSTitus Rwantare break; 3117215456aSTitus Rwantare 3127215456aSTitus Rwantare case MAX34451_MFR_FAULT_RETRY: 3137215456aSTitus Rwantare pmbus_send32(pmdev, s->fault_retry); 3147215456aSTitus Rwantare break; 3157215456aSTitus Rwantare 3167215456aSTitus Rwantare case MAX34451_MFR_NV_FAULT_LOG: 3177215456aSTitus Rwantare pmbus_send32(pmdev, s->fault_log); 3187215456aSTitus Rwantare break; 3197215456aSTitus Rwantare 3207215456aSTitus Rwantare case MAX34451_MFR_TIME_COUNT: 3217215456aSTitus Rwantare pmbus_send32(pmdev, s->time_count); 3227215456aSTitus Rwantare break; 3237215456aSTitus Rwantare 3247215456aSTitus Rwantare case MAX34451_MFR_MARGIN_CONFIG: 3257215456aSTitus Rwantare if (pmdev->page < 12) { 3267215456aSTitus Rwantare pmbus_send16(pmdev, s->margin_config[pmdev->page]); 3277215456aSTitus Rwantare } 3287215456aSTitus Rwantare break; 3297215456aSTitus Rwantare 3307215456aSTitus Rwantare case MAX34451_MFR_FW_SERIAL: 3317215456aSTitus Rwantare if (pmdev->page == 255) { 3327215456aSTitus Rwantare pmbus_send16(pmdev, 1); /* Firmware revision */ 3337215456aSTitus Rwantare } 3347215456aSTitus Rwantare break; 3357215456aSTitus Rwantare 3367215456aSTitus Rwantare case MAX34451_MFR_IOUT_AVG: 3377215456aSTitus Rwantare if (pmdev->page < 16) { 3387215456aSTitus Rwantare pmbus_send16(pmdev, s->iout_avg[pmdev->page]); 3397215456aSTitus Rwantare } 3407215456aSTitus Rwantare break; 3417215456aSTitus Rwantare 3427215456aSTitus Rwantare case MAX34451_MFR_CHANNEL_CONFIG: 3437215456aSTitus Rwantare if (pmdev->page < 16) { 3447215456aSTitus Rwantare pmbus_send16(pmdev, s->channel_config[pmdev->page]); 3457215456aSTitus Rwantare } 3467215456aSTitus Rwantare break; 3477215456aSTitus Rwantare 3487215456aSTitus Rwantare case MAX34451_MFR_TON_SEQ_MAX: 3497215456aSTitus Rwantare if (pmdev->page < 12) { 3507215456aSTitus Rwantare pmbus_send16(pmdev, s->ton_seq_max[pmdev->page]); 3517215456aSTitus Rwantare } 3527215456aSTitus Rwantare break; 3537215456aSTitus Rwantare 3547215456aSTitus Rwantare case MAX34451_MFR_PWM_CONFIG: 3557215456aSTitus Rwantare if (pmdev->page < 12) { 3567215456aSTitus Rwantare pmbus_send32(pmdev, s->pwm_config[pmdev->page]); 3577215456aSTitus Rwantare } 3587215456aSTitus Rwantare break; 3597215456aSTitus Rwantare 3607215456aSTitus Rwantare case MAX34451_MFR_SEQ_CONFIG: 3617215456aSTitus Rwantare if (pmdev->page < 12) { 3627215456aSTitus Rwantare pmbus_send32(pmdev, s->seq_config[pmdev->page]); 3637215456aSTitus Rwantare } 3647215456aSTitus Rwantare break; 3657215456aSTitus Rwantare 3667215456aSTitus Rwantare case MAX34451_MFR_TEMP_SENSOR_CONFIG: 3677215456aSTitus Rwantare if (15 < pmdev->page && pmdev->page < 21) { 3687215456aSTitus Rwantare pmbus_send32(pmdev, s->temp_sensor_config[pmdev->page % 16]); 3697215456aSTitus Rwantare } 3707215456aSTitus Rwantare break; 3717215456aSTitus Rwantare 3727215456aSTitus Rwantare case MAX34451_MFR_STORE_SINGLE: 3737215456aSTitus Rwantare pmbus_send32(pmdev, s->store_single); 3747215456aSTitus Rwantare break; 3757215456aSTitus Rwantare 3767215456aSTitus Rwantare case MAX34451_MFR_CRC: 3777215456aSTitus Rwantare pmbus_send32(pmdev, s->crc); 3787215456aSTitus Rwantare break; 3797215456aSTitus Rwantare 3807215456aSTitus Rwantare default: 3817215456aSTitus Rwantare qemu_log_mask(LOG_GUEST_ERROR, 3827215456aSTitus Rwantare "%s: reading from unsupported register: 0x%02x\n", 3837215456aSTitus Rwantare __func__, pmdev->code); 3847215456aSTitus Rwantare break; 3857215456aSTitus Rwantare } 3867215456aSTitus Rwantare return 0xFF; 3877215456aSTitus Rwantare } 3887215456aSTitus Rwantare 3897215456aSTitus Rwantare static int max34451_write_data(PMBusDevice *pmdev, const uint8_t *buf, 3907215456aSTitus Rwantare uint8_t len) 3917215456aSTitus Rwantare { 3927215456aSTitus Rwantare MAX34451State *s = MAX34451(pmdev); 3937215456aSTitus Rwantare 3947215456aSTitus Rwantare if (len == 0) { 3957215456aSTitus Rwantare qemu_log_mask(LOG_GUEST_ERROR, "%s: writing empty data\n", __func__); 3967215456aSTitus Rwantare return -1; 3977215456aSTitus Rwantare } 3987215456aSTitus Rwantare 3997215456aSTitus Rwantare pmdev->code = buf[0]; /* PMBus command code */ 4007215456aSTitus Rwantare 4017215456aSTitus Rwantare if (len == 1) { 4027215456aSTitus Rwantare return 0; 4037215456aSTitus Rwantare } 4047215456aSTitus Rwantare 4057215456aSTitus Rwantare /* Exclude command code from buffer */ 4067215456aSTitus Rwantare buf++; 4077215456aSTitus Rwantare len--; 4087215456aSTitus Rwantare uint8_t index = pmdev->page; 4097215456aSTitus Rwantare 4107215456aSTitus Rwantare switch (pmdev->code) { 4117215456aSTitus Rwantare case MAX34451_MFR_STORE_ALL: 4127215456aSTitus Rwantare case MAX34451_MFR_RESTORE_ALL: 4137215456aSTitus Rwantare case MAX34451_MFR_STORE_SINGLE: 4147215456aSTitus Rwantare /* 4157215456aSTitus Rwantare * TODO: hardware behaviour is to move the contents of volatile 4167215456aSTitus Rwantare * memory to non-volatile memory. 4177215456aSTitus Rwantare */ 4187215456aSTitus Rwantare break; 4197215456aSTitus Rwantare 4207215456aSTitus Rwantare case PMBUS_POWER_GOOD_ON: /* R/W word */ 4217215456aSTitus Rwantare if (pmdev->page < MAX34451_NUM_PWR_DEVICES) { 4227215456aSTitus Rwantare s->power_good_on[pmdev->page] = pmbus_receive16(pmdev); 4237215456aSTitus Rwantare } 4247215456aSTitus Rwantare break; 4257215456aSTitus Rwantare 4267215456aSTitus Rwantare case PMBUS_POWER_GOOD_OFF: /* R/W word */ 4277215456aSTitus Rwantare if (pmdev->page < MAX34451_NUM_PWR_DEVICES) { 4287215456aSTitus Rwantare s->power_good_off[pmdev->page] = pmbus_receive16(pmdev); 4297215456aSTitus Rwantare } 4307215456aSTitus Rwantare break; 4317215456aSTitus Rwantare 4327215456aSTitus Rwantare case PMBUS_TON_DELAY: /* R/W word */ 4337215456aSTitus Rwantare if (pmdev->page < 12) { 4347215456aSTitus Rwantare s->ton_delay[pmdev->page] = pmbus_receive16(pmdev); 4357215456aSTitus Rwantare } 4367215456aSTitus Rwantare break; 4377215456aSTitus Rwantare 4387215456aSTitus Rwantare case PMBUS_TON_MAX_FAULT_LIMIT: /* R/W word */ 4397215456aSTitus Rwantare if (pmdev->page < 12) { 4407215456aSTitus Rwantare s->ton_max_fault_limit[pmdev->page] 4417215456aSTitus Rwantare = pmbus_receive16(pmdev); 4427215456aSTitus Rwantare } 4437215456aSTitus Rwantare break; 4447215456aSTitus Rwantare 4457215456aSTitus Rwantare case PMBUS_TOFF_DELAY: /* R/W word */ 4467215456aSTitus Rwantare if (pmdev->page < 12) { 4477215456aSTitus Rwantare s->toff_delay[pmdev->page] = pmbus_receive16(pmdev); 4487215456aSTitus Rwantare } 4497215456aSTitus Rwantare break; 4507215456aSTitus Rwantare 4517215456aSTitus Rwantare case PMBUS_MFR_LOCATION: /* R/W 64 */ 4527215456aSTitus Rwantare s->mfr_location = pmbus_receive64(pmdev); 4537215456aSTitus Rwantare break; 4547215456aSTitus Rwantare 4557215456aSTitus Rwantare case PMBUS_MFR_DATE: /* R/W 64 */ 4567215456aSTitus Rwantare s->mfr_date = pmbus_receive64(pmdev); 4577215456aSTitus Rwantare break; 4587215456aSTitus Rwantare 4597215456aSTitus Rwantare case PMBUS_MFR_SERIAL: /* R/W 64 */ 4607215456aSTitus Rwantare s->mfr_serial = pmbus_receive64(pmdev); 4617215456aSTitus Rwantare break; 4627215456aSTitus Rwantare 4637215456aSTitus Rwantare case MAX34451_MFR_MODE: /* R/W word */ 4647215456aSTitus Rwantare s->mfr_mode = pmbus_receive16(pmdev); 4657215456aSTitus Rwantare break; 4667215456aSTitus Rwantare 4677215456aSTitus Rwantare case MAX34451_MFR_PSEN_CONFIG: /* R/W 32 */ 4687215456aSTitus Rwantare if (pmdev->page < 12) { 4697215456aSTitus Rwantare s->psen_config[pmdev->page] = pmbus_receive32(pmdev); 4707215456aSTitus Rwantare } 4717215456aSTitus Rwantare break; 4727215456aSTitus Rwantare 4737215456aSTitus Rwantare case MAX34451_MFR_VOUT_PEAK: /* R/W word */ 4747215456aSTitus Rwantare if (pmdev->page < 16) { 4757215456aSTitus Rwantare s->vout_peak[pmdev->page] = pmbus_receive16(pmdev); 4767215456aSTitus Rwantare } 4777215456aSTitus Rwantare break; 4787215456aSTitus Rwantare 4797215456aSTitus Rwantare case MAX34451_MFR_IOUT_PEAK: /* R/W word */ 4807215456aSTitus Rwantare if (pmdev->page < 16) { 4817215456aSTitus Rwantare s->iout_peak[pmdev->page] = pmbus_receive16(pmdev); 4827215456aSTitus Rwantare } 4837215456aSTitus Rwantare break; 4847215456aSTitus Rwantare 4857215456aSTitus Rwantare case MAX34451_MFR_TEMPERATURE_PEAK: /* R/W word */ 4867215456aSTitus Rwantare if (15 < pmdev->page && pmdev->page < 21) { 4877215456aSTitus Rwantare s->temperature_peak[pmdev->page % 16] 4887215456aSTitus Rwantare = pmbus_receive16(pmdev); 4897215456aSTitus Rwantare } 4907215456aSTitus Rwantare break; 4917215456aSTitus Rwantare 4927215456aSTitus Rwantare case MAX34451_MFR_VOUT_MIN: /* R/W word */ 4937215456aSTitus Rwantare if (pmdev->page < 16) { 4947215456aSTitus Rwantare s->vout_min[pmdev->page] = pmbus_receive16(pmdev); 4957215456aSTitus Rwantare } 4967215456aSTitus Rwantare break; 4977215456aSTitus Rwantare 4987215456aSTitus Rwantare case MAX34451_MFR_NV_LOG_CONFIG: /* R/W word */ 4997215456aSTitus Rwantare s->nv_log_config = pmbus_receive16(pmdev); 5007215456aSTitus Rwantare break; 5017215456aSTitus Rwantare 5027215456aSTitus Rwantare case MAX34451_MFR_FAULT_RESPONSE: /* R/W 32 */ 5037215456aSTitus Rwantare if (pmdev->page < 16) { 5047215456aSTitus Rwantare s->fault_response[pmdev->page] = pmbus_receive32(pmdev); 5057215456aSTitus Rwantare } 5067215456aSTitus Rwantare break; 5077215456aSTitus Rwantare 5087215456aSTitus Rwantare case MAX34451_MFR_FAULT_RETRY: /* R/W word */ 5097215456aSTitus Rwantare s->fault_retry = pmbus_receive16(pmdev); 5107215456aSTitus Rwantare break; 5117215456aSTitus Rwantare 5127215456aSTitus Rwantare case MAX34451_MFR_TIME_COUNT: /* R/W 32 */ 5137215456aSTitus Rwantare s->time_count = pmbus_receive32(pmdev); 5147215456aSTitus Rwantare break; 5157215456aSTitus Rwantare 5167215456aSTitus Rwantare case MAX34451_MFR_MARGIN_CONFIG: /* R/W word */ 5177215456aSTitus Rwantare if (pmdev->page < 12) { 5187215456aSTitus Rwantare s->margin_config[pmdev->page] = pmbus_receive16(pmdev); 5197215456aSTitus Rwantare } 5207215456aSTitus Rwantare break; 5217215456aSTitus Rwantare 5227215456aSTitus Rwantare case MAX34451_MFR_CHANNEL_CONFIG: /* R/W word */ 5237215456aSTitus Rwantare if (pmdev->page < 16) { 5247215456aSTitus Rwantare s->channel_config[pmdev->page] = pmbus_receive16(pmdev); 5257215456aSTitus Rwantare } 5267215456aSTitus Rwantare break; 5277215456aSTitus Rwantare 5287215456aSTitus Rwantare case MAX34451_MFR_TON_SEQ_MAX: /* R/W word */ 5297215456aSTitus Rwantare if (pmdev->page < 12) { 5307215456aSTitus Rwantare s->ton_seq_max[pmdev->page] = pmbus_receive16(pmdev); 5317215456aSTitus Rwantare } 5327215456aSTitus Rwantare break; 5337215456aSTitus Rwantare 5347215456aSTitus Rwantare case MAX34451_MFR_PWM_CONFIG: /* R/W 32 */ 5357215456aSTitus Rwantare if (pmdev->page < 12) { 5367215456aSTitus Rwantare s->pwm_config[pmdev->page] = pmbus_receive32(pmdev); 5377215456aSTitus Rwantare } 5387215456aSTitus Rwantare break; 5397215456aSTitus Rwantare 5407215456aSTitus Rwantare case MAX34451_MFR_SEQ_CONFIG: /* R/W 32 */ 5417215456aSTitus Rwantare if (pmdev->page < 12) { 5427215456aSTitus Rwantare s->seq_config[pmdev->page] = pmbus_receive32(pmdev); 5437215456aSTitus Rwantare } 5447215456aSTitus Rwantare break; 5457215456aSTitus Rwantare 5467215456aSTitus Rwantare case MAX34451_MFR_TEMP_SENSOR_CONFIG: /* R/W word */ 5477215456aSTitus Rwantare if (15 < pmdev->page && pmdev->page < 21) { 5487215456aSTitus Rwantare s->temp_sensor_config[pmdev->page % 16] 5497215456aSTitus Rwantare = pmbus_receive16(pmdev); 5507215456aSTitus Rwantare } 5517215456aSTitus Rwantare break; 5527215456aSTitus Rwantare 5537215456aSTitus Rwantare case MAX34451_MFR_CRC: /* R/W word */ 5547215456aSTitus Rwantare s->crc = pmbus_receive16(pmdev); 5557215456aSTitus Rwantare break; 5567215456aSTitus Rwantare 5577215456aSTitus Rwantare case MAX34451_MFR_NV_FAULT_LOG: 5587215456aSTitus Rwantare case MAX34451_MFR_FW_SERIAL: 5597215456aSTitus Rwantare case MAX34451_MFR_IOUT_AVG: 5607215456aSTitus Rwantare /* Read only commands */ 5617215456aSTitus Rwantare pmdev->pages[index].status_word |= PMBUS_STATUS_CML; 5627215456aSTitus Rwantare pmdev->pages[index].status_cml |= PB_CML_FAULT_INVALID_DATA; 5637215456aSTitus Rwantare qemu_log_mask(LOG_GUEST_ERROR, 5647215456aSTitus Rwantare "%s: writing to read-only register 0x%02x\n", 5657215456aSTitus Rwantare __func__, pmdev->code); 5667215456aSTitus Rwantare break; 5677215456aSTitus Rwantare 5687215456aSTitus Rwantare default: 5697215456aSTitus Rwantare qemu_log_mask(LOG_GUEST_ERROR, 5707215456aSTitus Rwantare "%s: writing to unsupported register: 0x%02x\n", 5717215456aSTitus Rwantare __func__, pmdev->code); 5727215456aSTitus Rwantare break; 5737215456aSTitus Rwantare } 5747215456aSTitus Rwantare 5757215456aSTitus Rwantare return 0; 5767215456aSTitus Rwantare } 5777215456aSTitus Rwantare 5787215456aSTitus Rwantare static void max34451_get(Object *obj, Visitor *v, const char *name, 5797215456aSTitus Rwantare void *opaque, Error **errp) 5807215456aSTitus Rwantare { 5817215456aSTitus Rwantare visit_type_uint16(v, name, (uint16_t *)opaque, errp); 5827215456aSTitus Rwantare } 5837215456aSTitus Rwantare 5847215456aSTitus Rwantare static void max34451_set(Object *obj, Visitor *v, const char *name, 5857215456aSTitus Rwantare void *opaque, Error **errp) 5867215456aSTitus Rwantare { 5877215456aSTitus Rwantare MAX34451State *s = MAX34451(obj); 5887215456aSTitus Rwantare uint16_t *internal = opaque; 5897215456aSTitus Rwantare uint16_t value; 5907215456aSTitus Rwantare if (!visit_type_uint16(v, name, &value, errp)) { 5917215456aSTitus Rwantare return; 5927215456aSTitus Rwantare } 5937215456aSTitus Rwantare 5947215456aSTitus Rwantare *internal = value; 5957215456aSTitus Rwantare max34451_check_limits(s); 5967215456aSTitus Rwantare } 5977215456aSTitus Rwantare 5987215456aSTitus Rwantare /* used to init uint16_t arrays */ 5997215456aSTitus Rwantare static inline void *memset_word(void *s, uint16_t c, size_t n) 6007215456aSTitus Rwantare { 6017215456aSTitus Rwantare size_t i; 6027215456aSTitus Rwantare uint16_t *p = s; 6037215456aSTitus Rwantare 6047215456aSTitus Rwantare for (i = 0; i < n; i++) { 6057215456aSTitus Rwantare p[i] = c; 6067215456aSTitus Rwantare } 6077215456aSTitus Rwantare 6087215456aSTitus Rwantare return s; 6097215456aSTitus Rwantare } 6107215456aSTitus Rwantare 611ad80e367SPeter Maydell static void max34451_exit_reset(Object *obj, ResetType type) 6127215456aSTitus Rwantare { 6137215456aSTitus Rwantare PMBusDevice *pmdev = PMBUS_DEVICE(obj); 6147215456aSTitus Rwantare MAX34451State *s = MAX34451(obj); 6157215456aSTitus Rwantare pmdev->capability = DEFAULT_CAPABILITY; 6167215456aSTitus Rwantare 6177215456aSTitus Rwantare for (int i = 0; i < MAX34451_NUM_PAGES; i++) { 6187215456aSTitus Rwantare pmdev->pages[i].operation = DEFAULT_OP_ON; 6197215456aSTitus Rwantare pmdev->pages[i].on_off_config = DEFAULT_ON_OFF_CONFIG; 6207215456aSTitus Rwantare pmdev->pages[i].revision = 0x11; 6217215456aSTitus Rwantare pmdev->pages[i].vout_mode = DEFAULT_VOUT_MODE; 6227215456aSTitus Rwantare } 6237215456aSTitus Rwantare 6247215456aSTitus Rwantare for (int i = 0; i < MAX34451_NUM_PWR_DEVICES; i++) { 6257215456aSTitus Rwantare pmdev->pages[i].vout_scale_monitor = DEFAULT_SCALE; 6267215456aSTitus Rwantare pmdev->pages[i].vout_ov_fault_limit = DEFAULT_OV_LIMIT; 6277215456aSTitus Rwantare pmdev->pages[i].vout_ov_warn_limit = DEFAULT_OV_LIMIT; 6287215456aSTitus Rwantare pmdev->pages[i].iout_oc_warn_limit = DEFAULT_OC_LIMIT; 6297215456aSTitus Rwantare pmdev->pages[i].iout_oc_fault_limit = DEFAULT_OC_LIMIT; 6307215456aSTitus Rwantare } 6317215456aSTitus Rwantare 6327215456aSTitus Rwantare for (int i = 0; i < MAX34451_NUM_MARGINED_PSU; i++) { 6337215456aSTitus Rwantare pmdev->pages[i].ton_max_fault_limit = DEFAULT_TON_FAULT_LIMIT; 6347215456aSTitus Rwantare } 6357215456aSTitus Rwantare 6367215456aSTitus Rwantare for (int i = 16; i < MAX34451_NUM_TEMP_DEVICES + 16; i++) { 6377215456aSTitus Rwantare pmdev->pages[i].read_temperature_1 = DEFAULT_TEMPERATURE; 6387215456aSTitus Rwantare pmdev->pages[i].ot_warn_limit = DEFAULT_OT_LIMIT; 6397215456aSTitus Rwantare pmdev->pages[i].ot_fault_limit = DEFAULT_OT_LIMIT; 6407215456aSTitus Rwantare } 6417215456aSTitus Rwantare 6427215456aSTitus Rwantare memset_word(s->ton_max_fault_limit, DEFAULT_TON_FAULT_LIMIT, 6437215456aSTitus Rwantare MAX34451_NUM_MARGINED_PSU); 6447215456aSTitus Rwantare memset_word(s->channel_config, DEFAULT_CHANNEL_CONFIG, 6457215456aSTitus Rwantare MAX34451_NUM_PWR_DEVICES); 6467215456aSTitus Rwantare memset_word(s->vout_min, DEFAULT_VMIN, MAX34451_NUM_PWR_DEVICES); 6477215456aSTitus Rwantare 6487215456aSTitus Rwantare s->mfr_location = DEFAULT_TEXT; 6497215456aSTitus Rwantare s->mfr_date = DEFAULT_TEXT; 6507215456aSTitus Rwantare s->mfr_serial = DEFAULT_TEXT; 6517215456aSTitus Rwantare } 6527215456aSTitus Rwantare 6537215456aSTitus Rwantare static const VMStateDescription vmstate_max34451 = { 6547215456aSTitus Rwantare .name = TYPE_MAX34451, 6557215456aSTitus Rwantare .version_id = 0, 6567215456aSTitus Rwantare .minimum_version_id = 0, 657af10fff2SRichard Henderson .fields = (const VMStateField[]){ 6587215456aSTitus Rwantare VMSTATE_PMBUS_DEVICE(parent, MAX34451State), 6597215456aSTitus Rwantare VMSTATE_UINT16_ARRAY(power_good_on, MAX34451State, 6607215456aSTitus Rwantare MAX34451_NUM_PWR_DEVICES), 6617215456aSTitus Rwantare VMSTATE_UINT16_ARRAY(power_good_off, MAX34451State, 6627215456aSTitus Rwantare MAX34451_NUM_PWR_DEVICES), 6637215456aSTitus Rwantare VMSTATE_UINT16_ARRAY(ton_delay, MAX34451State, 6647215456aSTitus Rwantare MAX34451_NUM_MARGINED_PSU), 6657215456aSTitus Rwantare VMSTATE_UINT16_ARRAY(ton_max_fault_limit, MAX34451State, 6667215456aSTitus Rwantare MAX34451_NUM_MARGINED_PSU), 6677215456aSTitus Rwantare VMSTATE_UINT16_ARRAY(toff_delay, MAX34451State, 6687215456aSTitus Rwantare MAX34451_NUM_MARGINED_PSU), 6697215456aSTitus Rwantare VMSTATE_UINT8_ARRAY(status_mfr_specific, MAX34451State, 6707215456aSTitus Rwantare MAX34451_NUM_PWR_DEVICES), 6717215456aSTitus Rwantare VMSTATE_UINT64(mfr_location, MAX34451State), 6727215456aSTitus Rwantare VMSTATE_UINT64(mfr_date, MAX34451State), 6737215456aSTitus Rwantare VMSTATE_UINT64(mfr_serial, MAX34451State), 6747215456aSTitus Rwantare VMSTATE_UINT16(mfr_mode, MAX34451State), 6757215456aSTitus Rwantare VMSTATE_UINT32_ARRAY(psen_config, MAX34451State, 6767215456aSTitus Rwantare MAX34451_NUM_MARGINED_PSU), 6777215456aSTitus Rwantare VMSTATE_UINT16_ARRAY(vout_peak, MAX34451State, 6787215456aSTitus Rwantare MAX34451_NUM_PWR_DEVICES), 6797215456aSTitus Rwantare VMSTATE_UINT16_ARRAY(iout_peak, MAX34451State, 6807215456aSTitus Rwantare MAX34451_NUM_PWR_DEVICES), 6817215456aSTitus Rwantare VMSTATE_UINT16_ARRAY(temperature_peak, MAX34451State, 6827215456aSTitus Rwantare MAX34451_NUM_TEMP_DEVICES), 6837215456aSTitus Rwantare VMSTATE_UINT16_ARRAY(vout_min, MAX34451State, MAX34451_NUM_PWR_DEVICES), 6847215456aSTitus Rwantare VMSTATE_UINT16(nv_log_config, MAX34451State), 6857215456aSTitus Rwantare VMSTATE_UINT32_ARRAY(fault_response, MAX34451State, 6867215456aSTitus Rwantare MAX34451_NUM_PWR_DEVICES), 6877215456aSTitus Rwantare VMSTATE_UINT16(fault_retry, MAX34451State), 6887215456aSTitus Rwantare VMSTATE_UINT32(fault_log, MAX34451State), 6897215456aSTitus Rwantare VMSTATE_UINT32(time_count, MAX34451State), 6907215456aSTitus Rwantare VMSTATE_UINT16_ARRAY(margin_config, MAX34451State, 6917215456aSTitus Rwantare MAX34451_NUM_MARGINED_PSU), 6927215456aSTitus Rwantare VMSTATE_UINT16(fw_serial, MAX34451State), 6937215456aSTitus Rwantare VMSTATE_UINT16_ARRAY(iout_avg, MAX34451State, MAX34451_NUM_PWR_DEVICES), 6947215456aSTitus Rwantare VMSTATE_UINT16_ARRAY(channel_config, MAX34451State, 6957215456aSTitus Rwantare MAX34451_NUM_PWR_DEVICES), 6967215456aSTitus Rwantare VMSTATE_UINT16_ARRAY(ton_seq_max, MAX34451State, 6977215456aSTitus Rwantare MAX34451_NUM_MARGINED_PSU), 6987215456aSTitus Rwantare VMSTATE_UINT32_ARRAY(pwm_config, MAX34451State, 6997215456aSTitus Rwantare MAX34451_NUM_MARGINED_PSU), 7007215456aSTitus Rwantare VMSTATE_UINT32_ARRAY(seq_config, MAX34451State, 7017215456aSTitus Rwantare MAX34451_NUM_MARGINED_PSU), 7027215456aSTitus Rwantare VMSTATE_UINT16_ARRAY(temp_sensor_config, MAX34451State, 7037215456aSTitus Rwantare MAX34451_NUM_TEMP_DEVICES), 7047215456aSTitus Rwantare VMSTATE_UINT16(store_single, MAX34451State), 7057215456aSTitus Rwantare VMSTATE_UINT16(crc, MAX34451State), 7067215456aSTitus Rwantare VMSTATE_END_OF_LIST() 7077215456aSTitus Rwantare } 7087215456aSTitus Rwantare }; 7097215456aSTitus Rwantare 7107215456aSTitus Rwantare static void max34451_init(Object *obj) 7117215456aSTitus Rwantare { 7127215456aSTitus Rwantare PMBusDevice *pmdev = PMBUS_DEVICE(obj); 7137215456aSTitus Rwantare uint64_t psu_flags = PB_HAS_VOUT | PB_HAS_IOUT | PB_HAS_VOUT_MODE | 7147215456aSTitus Rwantare PB_HAS_IOUT_GAIN; 7157215456aSTitus Rwantare 7167215456aSTitus Rwantare for (int i = 0; i < MAX34451_NUM_PWR_DEVICES; i++) { 7177215456aSTitus Rwantare pmbus_page_config(pmdev, i, psu_flags); 7187215456aSTitus Rwantare } 7197215456aSTitus Rwantare 7207215456aSTitus Rwantare for (int i = 0; i < MAX34451_NUM_MARGINED_PSU; i++) { 7217215456aSTitus Rwantare pmbus_page_config(pmdev, i, psu_flags | PB_HAS_VOUT_MARGIN); 7227215456aSTitus Rwantare } 7237215456aSTitus Rwantare 7247215456aSTitus Rwantare for (int i = 16; i < MAX34451_NUM_TEMP_DEVICES + 16; i++) { 7257215456aSTitus Rwantare pmbus_page_config(pmdev, i, PB_HAS_TEMPERATURE | PB_HAS_VOUT_MODE); 7267215456aSTitus Rwantare } 7277215456aSTitus Rwantare 7287215456aSTitus Rwantare /* get and set the voltage in millivolts, max is 32767 mV */ 7297215456aSTitus Rwantare for (int i = 0; i < MAX34451_NUM_PWR_DEVICES; i++) { 7307215456aSTitus Rwantare object_property_add(obj, "vout[*]", "uint16", 7317215456aSTitus Rwantare max34451_get, 7327215456aSTitus Rwantare max34451_set, NULL, &pmdev->pages[i].read_vout); 7337215456aSTitus Rwantare } 7347215456aSTitus Rwantare 7357215456aSTitus Rwantare /* 7367215456aSTitus Rwantare * get and set the temperature of the internal temperature sensor in 7378fa21b80SMichael Tokarev * centidegrees Celsius i.e.: 2500 -> 25.00 C, max is 327.67 C 7387215456aSTitus Rwantare */ 7397215456aSTitus Rwantare for (int i = 0; i < MAX34451_NUM_TEMP_DEVICES; i++) { 7407215456aSTitus Rwantare object_property_add(obj, "temperature[*]", "uint16", 7417215456aSTitus Rwantare max34451_get, 7427215456aSTitus Rwantare max34451_set, 7437215456aSTitus Rwantare NULL, 7447215456aSTitus Rwantare &pmdev->pages[i + 16].read_temperature_1); 7457215456aSTitus Rwantare } 7467215456aSTitus Rwantare 7477215456aSTitus Rwantare } 7487215456aSTitus Rwantare 749*12d1a768SPhilippe Mathieu-Daudé static void max34451_class_init(ObjectClass *klass, const void *data) 7507215456aSTitus Rwantare { 7517215456aSTitus Rwantare ResettableClass *rc = RESETTABLE_CLASS(klass); 7527215456aSTitus Rwantare DeviceClass *dc = DEVICE_CLASS(klass); 7537215456aSTitus Rwantare PMBusDeviceClass *k = PMBUS_DEVICE_CLASS(klass); 7547215456aSTitus Rwantare dc->desc = "Maxim MAX34451 16-Channel V/I monitor"; 7557215456aSTitus Rwantare dc->vmsd = &vmstate_max34451; 7567215456aSTitus Rwantare k->write_data = max34451_write_data; 7577215456aSTitus Rwantare k->receive_byte = max34451_read_byte; 7587215456aSTitus Rwantare k->device_num_pages = MAX34451_NUM_PAGES; 7597215456aSTitus Rwantare rc->phases.exit = max34451_exit_reset; 7607215456aSTitus Rwantare } 7617215456aSTitus Rwantare 7627215456aSTitus Rwantare static const TypeInfo max34451_info = { 7637215456aSTitus Rwantare .name = TYPE_MAX34451, 7647215456aSTitus Rwantare .parent = TYPE_PMBUS_DEVICE, 7657215456aSTitus Rwantare .instance_size = sizeof(MAX34451State), 7667215456aSTitus Rwantare .instance_init = max34451_init, 7677215456aSTitus Rwantare .class_init = max34451_class_init, 7687215456aSTitus Rwantare }; 7697215456aSTitus Rwantare 7707215456aSTitus Rwantare static void max34451_register_types(void) 7717215456aSTitus Rwantare { 7727215456aSTitus Rwantare type_register_static(&max34451_info); 7737215456aSTitus Rwantare } 7747215456aSTitus Rwantare 7757215456aSTitus Rwantare type_init(max34451_register_types) 776