cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

max34451.c (27463B)


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