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

npcm7xx_smbus.c (32992B)


      1/*
      2 * Nuvoton NPCM7xx SMBus Module.
      3 *
      4 * Copyright 2020 Google LLC
      5 *
      6 * This program is free software; you can redistribute it and/or modify it
      7 * under the terms of the GNU General Public License as published by the
      8 * Free Software Foundation; either version 2 of the License, or
      9 * (at your option) any later version.
     10 *
     11 * This program is distributed in the hope that it will be useful, but WITHOUT
     12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
     14 * for more details.
     15 */
     16
     17#include "qemu/osdep.h"
     18
     19#include "hw/i2c/npcm7xx_smbus.h"
     20#include "migration/vmstate.h"
     21#include "qemu/bitops.h"
     22#include "qemu/guest-random.h"
     23#include "qemu/log.h"
     24#include "qemu/module.h"
     25#include "qemu/units.h"
     26
     27#include "trace.h"
     28
     29enum NPCM7xxSMBusCommonRegister {
     30    NPCM7XX_SMB_SDA     = 0x0,
     31    NPCM7XX_SMB_ST      = 0x2,
     32    NPCM7XX_SMB_CST     = 0x4,
     33    NPCM7XX_SMB_CTL1    = 0x6,
     34    NPCM7XX_SMB_ADDR1   = 0x8,
     35    NPCM7XX_SMB_CTL2    = 0xa,
     36    NPCM7XX_SMB_ADDR2   = 0xc,
     37    NPCM7XX_SMB_CTL3    = 0xe,
     38    NPCM7XX_SMB_CST2    = 0x18,
     39    NPCM7XX_SMB_CST3    = 0x19,
     40    NPCM7XX_SMB_VER     = 0x1f,
     41};
     42
     43enum NPCM7xxSMBusBank0Register {
     44    NPCM7XX_SMB_ADDR3   = 0x10,
     45    NPCM7XX_SMB_ADDR7   = 0x11,
     46    NPCM7XX_SMB_ADDR4   = 0x12,
     47    NPCM7XX_SMB_ADDR8   = 0x13,
     48    NPCM7XX_SMB_ADDR5   = 0x14,
     49    NPCM7XX_SMB_ADDR9   = 0x15,
     50    NPCM7XX_SMB_ADDR6   = 0x16,
     51    NPCM7XX_SMB_ADDR10  = 0x17,
     52    NPCM7XX_SMB_CTL4    = 0x1a,
     53    NPCM7XX_SMB_CTL5    = 0x1b,
     54    NPCM7XX_SMB_SCLLT   = 0x1c,
     55    NPCM7XX_SMB_FIF_CTL = 0x1d,
     56    NPCM7XX_SMB_SCLHT   = 0x1e,
     57};
     58
     59enum NPCM7xxSMBusBank1Register {
     60    NPCM7XX_SMB_FIF_CTS  = 0x10,
     61    NPCM7XX_SMB_FAIR_PER = 0x11,
     62    NPCM7XX_SMB_TXF_CTL  = 0x12,
     63    NPCM7XX_SMB_T_OUT    = 0x14,
     64    NPCM7XX_SMB_TXF_STS  = 0x1a,
     65    NPCM7XX_SMB_RXF_STS  = 0x1c,
     66    NPCM7XX_SMB_RXF_CTL  = 0x1e,
     67};
     68
     69/* ST fields */
     70#define NPCM7XX_SMBST_STP           BIT(7)
     71#define NPCM7XX_SMBST_SDAST         BIT(6)
     72#define NPCM7XX_SMBST_BER           BIT(5)
     73#define NPCM7XX_SMBST_NEGACK        BIT(4)
     74#define NPCM7XX_SMBST_STASTR        BIT(3)
     75#define NPCM7XX_SMBST_NMATCH        BIT(2)
     76#define NPCM7XX_SMBST_MODE          BIT(1)
     77#define NPCM7XX_SMBST_XMIT          BIT(0)
     78
     79/* CST fields */
     80#define NPCM7XX_SMBCST_ARPMATCH        BIT(7)
     81#define NPCM7XX_SMBCST_MATCHAF         BIT(6)
     82#define NPCM7XX_SMBCST_TGSCL           BIT(5)
     83#define NPCM7XX_SMBCST_TSDA            BIT(4)
     84#define NPCM7XX_SMBCST_GCMATCH         BIT(3)
     85#define NPCM7XX_SMBCST_MATCH           BIT(2)
     86#define NPCM7XX_SMBCST_BB              BIT(1)
     87#define NPCM7XX_SMBCST_BUSY            BIT(0)
     88
     89/* CST2 fields */
     90#define NPCM7XX_SMBCST2_INTSTS         BIT(7)
     91#define NPCM7XX_SMBCST2_MATCH7F        BIT(6)
     92#define NPCM7XX_SMBCST2_MATCH6F        BIT(5)
     93#define NPCM7XX_SMBCST2_MATCH5F        BIT(4)
     94#define NPCM7XX_SMBCST2_MATCH4F        BIT(3)
     95#define NPCM7XX_SMBCST2_MATCH3F        BIT(2)
     96#define NPCM7XX_SMBCST2_MATCH2F        BIT(1)
     97#define NPCM7XX_SMBCST2_MATCH1F        BIT(0)
     98
     99/* CST3 fields */
    100#define NPCM7XX_SMBCST3_EO_BUSY        BIT(7)
    101#define NPCM7XX_SMBCST3_MATCH10F       BIT(2)
    102#define NPCM7XX_SMBCST3_MATCH9F        BIT(1)
    103#define NPCM7XX_SMBCST3_MATCH8F        BIT(0)
    104
    105/* CTL1 fields */
    106#define NPCM7XX_SMBCTL1_STASTRE     BIT(7)
    107#define NPCM7XX_SMBCTL1_NMINTE      BIT(6)
    108#define NPCM7XX_SMBCTL1_GCMEN       BIT(5)
    109#define NPCM7XX_SMBCTL1_ACK         BIT(4)
    110#define NPCM7XX_SMBCTL1_EOBINTE     BIT(3)
    111#define NPCM7XX_SMBCTL1_INTEN       BIT(2)
    112#define NPCM7XX_SMBCTL1_STOP        BIT(1)
    113#define NPCM7XX_SMBCTL1_START       BIT(0)
    114
    115/* CTL2 fields */
    116#define NPCM7XX_SMBCTL2_SCLFRQ(rv)  extract8((rv), 1, 6)
    117#define NPCM7XX_SMBCTL2_ENABLE      BIT(0)
    118
    119/* CTL3 fields */
    120#define NPCM7XX_SMBCTL3_SCL_LVL     BIT(7)
    121#define NPCM7XX_SMBCTL3_SDA_LVL     BIT(6)
    122#define NPCM7XX_SMBCTL3_BNK_SEL     BIT(5)
    123#define NPCM7XX_SMBCTL3_400K_MODE   BIT(4)
    124#define NPCM7XX_SMBCTL3_IDL_START   BIT(3)
    125#define NPCM7XX_SMBCTL3_ARPMEN      BIT(2)
    126#define NPCM7XX_SMBCTL3_SCLFRQ(rv)  extract8((rv), 0, 2)
    127
    128/* ADDR fields */
    129#define NPCM7XX_ADDR_EN             BIT(7)
    130#define NPCM7XX_ADDR_A(rv)          extract8((rv), 0, 6)
    131
    132/* FIFO Mode Register Fields */
    133/* FIF_CTL fields */
    134#define NPCM7XX_SMBFIF_CTL_FIFO_EN          BIT(4)
    135#define NPCM7XX_SMBFIF_CTL_FAIR_RDY_IE      BIT(2)
    136#define NPCM7XX_SMBFIF_CTL_FAIR_RDY         BIT(1)
    137#define NPCM7XX_SMBFIF_CTL_FAIR_BUSY        BIT(0)
    138/* FIF_CTS fields */
    139#define NPCM7XX_SMBFIF_CTS_STR              BIT(7)
    140#define NPCM7XX_SMBFIF_CTS_CLR_FIFO         BIT(6)
    141#define NPCM7XX_SMBFIF_CTS_RFTE_IE          BIT(3)
    142#define NPCM7XX_SMBFIF_CTS_RXF_TXE          BIT(1)
    143/* TXF_CTL fields */
    144#define NPCM7XX_SMBTXF_CTL_THR_TXIE         BIT(6)
    145#define NPCM7XX_SMBTXF_CTL_TX_THR(rv)       extract8((rv), 0, 5)
    146/* T_OUT fields */
    147#define NPCM7XX_SMBT_OUT_ST                 BIT(7)
    148#define NPCM7XX_SMBT_OUT_IE                 BIT(6)
    149#define NPCM7XX_SMBT_OUT_CLKDIV(rv)         extract8((rv), 0, 6)
    150/* TXF_STS fields */
    151#define NPCM7XX_SMBTXF_STS_TX_THST          BIT(6)
    152#define NPCM7XX_SMBTXF_STS_TX_BYTES(rv)     extract8((rv), 0, 5)
    153/* RXF_STS fields */
    154#define NPCM7XX_SMBRXF_STS_RX_THST          BIT(6)
    155#define NPCM7XX_SMBRXF_STS_RX_BYTES(rv)     extract8((rv), 0, 5)
    156/* RXF_CTL fields */
    157#define NPCM7XX_SMBRXF_CTL_THR_RXIE         BIT(6)
    158#define NPCM7XX_SMBRXF_CTL_LAST             BIT(5)
    159#define NPCM7XX_SMBRXF_CTL_RX_THR(rv)       extract8((rv), 0, 5)
    160
    161#define KEEP_OLD_BIT(o, n, b)       (((n) & (~(b))) | ((o) & (b)))
    162#define WRITE_ONE_CLEAR(o, n, b)    ((n) & (b) ? (o) & (~(b)) : (o))
    163
    164#define NPCM7XX_SMBUS_ENABLED(s)    ((s)->ctl2 & NPCM7XX_SMBCTL2_ENABLE)
    165#define NPCM7XX_SMBUS_FIFO_ENABLED(s) ((s)->fif_ctl & \
    166                                       NPCM7XX_SMBFIF_CTL_FIFO_EN)
    167
    168/* VERSION fields values, read-only. */
    169#define NPCM7XX_SMBUS_VERSION_NUMBER 1
    170#define NPCM7XX_SMBUS_VERSION_FIFO_SUPPORTED 1
    171
    172/* Reset values */
    173#define NPCM7XX_SMB_ST_INIT_VAL     0x00
    174#define NPCM7XX_SMB_CST_INIT_VAL    0x10
    175#define NPCM7XX_SMB_CST2_INIT_VAL   0x00
    176#define NPCM7XX_SMB_CST3_INIT_VAL   0x00
    177#define NPCM7XX_SMB_CTL1_INIT_VAL   0x00
    178#define NPCM7XX_SMB_CTL2_INIT_VAL   0x00
    179#define NPCM7XX_SMB_CTL3_INIT_VAL   0xc0
    180#define NPCM7XX_SMB_CTL4_INIT_VAL   0x07
    181#define NPCM7XX_SMB_CTL5_INIT_VAL   0x00
    182#define NPCM7XX_SMB_ADDR_INIT_VAL   0x00
    183#define NPCM7XX_SMB_SCLLT_INIT_VAL  0x00
    184#define NPCM7XX_SMB_SCLHT_INIT_VAL  0x00
    185#define NPCM7XX_SMB_FIF_CTL_INIT_VAL 0x00
    186#define NPCM7XX_SMB_FIF_CTS_INIT_VAL 0x00
    187#define NPCM7XX_SMB_FAIR_PER_INIT_VAL 0x00
    188#define NPCM7XX_SMB_TXF_CTL_INIT_VAL 0x00
    189#define NPCM7XX_SMB_T_OUT_INIT_VAL 0x3f
    190#define NPCM7XX_SMB_TXF_STS_INIT_VAL 0x00
    191#define NPCM7XX_SMB_RXF_STS_INIT_VAL 0x00
    192#define NPCM7XX_SMB_RXF_CTL_INIT_VAL 0x01
    193
    194static uint8_t npcm7xx_smbus_get_version(void)
    195{
    196    return NPCM7XX_SMBUS_VERSION_FIFO_SUPPORTED << 7 |
    197           NPCM7XX_SMBUS_VERSION_NUMBER;
    198}
    199
    200static void npcm7xx_smbus_update_irq(NPCM7xxSMBusState *s)
    201{
    202    int level;
    203
    204    if (s->ctl1 & NPCM7XX_SMBCTL1_INTEN) {
    205        level = !!((s->ctl1 & NPCM7XX_SMBCTL1_NMINTE &&
    206                    s->st & NPCM7XX_SMBST_NMATCH) ||
    207                   (s->st & NPCM7XX_SMBST_BER) ||
    208                   (s->st & NPCM7XX_SMBST_NEGACK) ||
    209                   (s->st & NPCM7XX_SMBST_SDAST) ||
    210                   (s->ctl1 & NPCM7XX_SMBCTL1_STASTRE &&
    211                    s->st & NPCM7XX_SMBST_SDAST) ||
    212                   (s->ctl1 & NPCM7XX_SMBCTL1_EOBINTE &&
    213                    s->cst3 & NPCM7XX_SMBCST3_EO_BUSY) ||
    214                   (s->rxf_ctl & NPCM7XX_SMBRXF_CTL_THR_RXIE &&
    215                    s->rxf_sts & NPCM7XX_SMBRXF_STS_RX_THST) ||
    216                   (s->txf_ctl & NPCM7XX_SMBTXF_CTL_THR_TXIE &&
    217                    s->txf_sts & NPCM7XX_SMBTXF_STS_TX_THST) ||
    218                   (s->fif_cts & NPCM7XX_SMBFIF_CTS_RFTE_IE &&
    219                    s->fif_cts & NPCM7XX_SMBFIF_CTS_RXF_TXE));
    220
    221        if (level) {
    222            s->cst2 |= NPCM7XX_SMBCST2_INTSTS;
    223        } else {
    224            s->cst2 &= ~NPCM7XX_SMBCST2_INTSTS;
    225        }
    226        qemu_set_irq(s->irq, level);
    227    }
    228}
    229
    230static void npcm7xx_smbus_nack(NPCM7xxSMBusState *s)
    231{
    232    s->st &= ~NPCM7XX_SMBST_SDAST;
    233    s->st |= NPCM7XX_SMBST_NEGACK;
    234    s->status = NPCM7XX_SMBUS_STATUS_NEGACK;
    235}
    236
    237static void npcm7xx_smbus_clear_buffer(NPCM7xxSMBusState *s)
    238{
    239    s->fif_cts &= ~NPCM7XX_SMBFIF_CTS_RXF_TXE;
    240    s->txf_sts = 0;
    241    s->rxf_sts = 0;
    242}
    243
    244static void npcm7xx_smbus_send_byte(NPCM7xxSMBusState *s, uint8_t value)
    245{
    246    int rv = i2c_send(s->bus, value);
    247
    248    if (rv) {
    249        npcm7xx_smbus_nack(s);
    250    } else {
    251        s->st |= NPCM7XX_SMBST_SDAST;
    252        if (NPCM7XX_SMBUS_FIFO_ENABLED(s)) {
    253            s->fif_cts |= NPCM7XX_SMBFIF_CTS_RXF_TXE;
    254            if (NPCM7XX_SMBTXF_STS_TX_BYTES(s->txf_sts) ==
    255                NPCM7XX_SMBTXF_CTL_TX_THR(s->txf_ctl)) {
    256                s->txf_sts = NPCM7XX_SMBTXF_STS_TX_THST;
    257            } else {
    258                s->txf_sts = 0;
    259            }
    260        }
    261    }
    262    trace_npcm7xx_smbus_send_byte((DEVICE(s)->canonical_path), value, !rv);
    263    npcm7xx_smbus_update_irq(s);
    264}
    265
    266static void npcm7xx_smbus_recv_byte(NPCM7xxSMBusState *s)
    267{
    268    s->sda = i2c_recv(s->bus);
    269    s->st |= NPCM7XX_SMBST_SDAST;
    270    if (s->st & NPCM7XX_SMBCTL1_ACK) {
    271        trace_npcm7xx_smbus_nack(DEVICE(s)->canonical_path);
    272        i2c_nack(s->bus);
    273        s->st &= NPCM7XX_SMBCTL1_ACK;
    274    }
    275    trace_npcm7xx_smbus_recv_byte((DEVICE(s)->canonical_path), s->sda);
    276    npcm7xx_smbus_update_irq(s);
    277}
    278
    279static void npcm7xx_smbus_recv_fifo(NPCM7xxSMBusState *s)
    280{
    281    uint8_t expected_bytes = NPCM7XX_SMBRXF_CTL_RX_THR(s->rxf_ctl);
    282    uint8_t received_bytes = NPCM7XX_SMBRXF_STS_RX_BYTES(s->rxf_sts);
    283    uint8_t pos;
    284
    285    if (received_bytes == expected_bytes) {
    286        return;
    287    }
    288
    289    while (received_bytes < expected_bytes &&
    290           received_bytes < NPCM7XX_SMBUS_FIFO_SIZE) {
    291        pos = (s->rx_cur + received_bytes) % NPCM7XX_SMBUS_FIFO_SIZE;
    292        s->rx_fifo[pos] = i2c_recv(s->bus);
    293        trace_npcm7xx_smbus_recv_byte((DEVICE(s)->canonical_path),
    294                                      s->rx_fifo[pos]);
    295        ++received_bytes;
    296    }
    297
    298    trace_npcm7xx_smbus_recv_fifo((DEVICE(s)->canonical_path),
    299                                  received_bytes, expected_bytes);
    300    s->rxf_sts = received_bytes;
    301    if (unlikely(received_bytes < expected_bytes)) {
    302        qemu_log_mask(LOG_GUEST_ERROR,
    303                      "%s: invalid rx_thr value: 0x%02x\n",
    304                      DEVICE(s)->canonical_path, expected_bytes);
    305        return;
    306    }
    307
    308    s->rxf_sts |= NPCM7XX_SMBRXF_STS_RX_THST;
    309    if (s->rxf_ctl & NPCM7XX_SMBRXF_CTL_LAST) {
    310        trace_npcm7xx_smbus_nack(DEVICE(s)->canonical_path);
    311        i2c_nack(s->bus);
    312        s->rxf_ctl &= ~NPCM7XX_SMBRXF_CTL_LAST;
    313    }
    314    if (received_bytes == NPCM7XX_SMBUS_FIFO_SIZE) {
    315        s->st |= NPCM7XX_SMBST_SDAST;
    316        s->fif_cts |= NPCM7XX_SMBFIF_CTS_RXF_TXE;
    317    } else if (!(s->rxf_ctl & NPCM7XX_SMBRXF_CTL_THR_RXIE)) {
    318        s->st |= NPCM7XX_SMBST_SDAST;
    319    } else {
    320        s->st &= ~NPCM7XX_SMBST_SDAST;
    321    }
    322    npcm7xx_smbus_update_irq(s);
    323}
    324
    325static void npcm7xx_smbus_read_byte_fifo(NPCM7xxSMBusState *s)
    326{
    327    uint8_t received_bytes = NPCM7XX_SMBRXF_STS_RX_BYTES(s->rxf_sts);
    328
    329    if (received_bytes == 0) {
    330        npcm7xx_smbus_recv_fifo(s);
    331        return;
    332    }
    333
    334    s->sda = s->rx_fifo[s->rx_cur];
    335    s->rx_cur = (s->rx_cur + 1u) % NPCM7XX_SMBUS_FIFO_SIZE;
    336    --s->rxf_sts;
    337    npcm7xx_smbus_update_irq(s);
    338}
    339
    340static void npcm7xx_smbus_start(NPCM7xxSMBusState *s)
    341{
    342    /*
    343     * We can start the bus if one of these is true:
    344     * 1. The bus is idle (so we can request it)
    345     * 2. We are the occupier (it's a repeated start condition.)
    346     */
    347    int available = !i2c_bus_busy(s->bus) ||
    348                    s->status != NPCM7XX_SMBUS_STATUS_IDLE;
    349
    350    if (available) {
    351        s->st |= NPCM7XX_SMBST_MODE | NPCM7XX_SMBST_XMIT | NPCM7XX_SMBST_SDAST;
    352        s->cst |= NPCM7XX_SMBCST_BUSY;
    353        if (NPCM7XX_SMBUS_FIFO_ENABLED(s)) {
    354            s->fif_cts |= NPCM7XX_SMBFIF_CTS_RXF_TXE;
    355        }
    356    } else {
    357        s->st &= ~NPCM7XX_SMBST_MODE;
    358        s->cst &= ~NPCM7XX_SMBCST_BUSY;
    359        s->st |= NPCM7XX_SMBST_BER;
    360    }
    361
    362    trace_npcm7xx_smbus_start(DEVICE(s)->canonical_path, available);
    363    s->cst |= NPCM7XX_SMBCST_BB;
    364    s->status = NPCM7XX_SMBUS_STATUS_IDLE;
    365    npcm7xx_smbus_update_irq(s);
    366}
    367
    368static void npcm7xx_smbus_send_address(NPCM7xxSMBusState *s, uint8_t value)
    369{
    370    int recv;
    371    int rv;
    372
    373    recv = value & BIT(0);
    374    rv = i2c_start_transfer(s->bus, value >> 1, recv);
    375    trace_npcm7xx_smbus_send_address(DEVICE(s)->canonical_path,
    376                                     value >> 1, recv, !rv);
    377    if (rv) {
    378        qemu_log_mask(LOG_GUEST_ERROR,
    379                      "%s: requesting i2c bus for 0x%02x failed: %d\n",
    380                      DEVICE(s)->canonical_path, value, rv);
    381        /* Failed to start transfer. NACK to reject.*/
    382        if (recv) {
    383            s->st &= ~NPCM7XX_SMBST_XMIT;
    384        } else {
    385            s->st |= NPCM7XX_SMBST_XMIT;
    386        }
    387        npcm7xx_smbus_nack(s);
    388        npcm7xx_smbus_update_irq(s);
    389        return;
    390    }
    391
    392    s->st &= ~NPCM7XX_SMBST_NEGACK;
    393    if (recv) {
    394        s->status = NPCM7XX_SMBUS_STATUS_RECEIVING;
    395        s->st &= ~NPCM7XX_SMBST_XMIT;
    396    } else {
    397        s->status = NPCM7XX_SMBUS_STATUS_SENDING;
    398        s->st |= NPCM7XX_SMBST_XMIT;
    399    }
    400
    401    if (s->ctl1 & NPCM7XX_SMBCTL1_STASTRE) {
    402        s->st |= NPCM7XX_SMBST_STASTR;
    403        if (!recv) {
    404            s->st |= NPCM7XX_SMBST_SDAST;
    405        }
    406    } else if (recv) {
    407        s->st |= NPCM7XX_SMBST_SDAST;
    408        if (NPCM7XX_SMBUS_FIFO_ENABLED(s)) {
    409            npcm7xx_smbus_recv_fifo(s);
    410        } else {
    411            npcm7xx_smbus_recv_byte(s);
    412        }
    413    } else if (NPCM7XX_SMBUS_FIFO_ENABLED(s)) {
    414        s->st |= NPCM7XX_SMBST_SDAST;
    415        s->fif_cts |= NPCM7XX_SMBFIF_CTS_RXF_TXE;
    416    }
    417    npcm7xx_smbus_update_irq(s);
    418}
    419
    420static void npcm7xx_smbus_execute_stop(NPCM7xxSMBusState *s)
    421{
    422    i2c_end_transfer(s->bus);
    423    s->st = 0;
    424    s->cst = 0;
    425    s->status = NPCM7XX_SMBUS_STATUS_IDLE;
    426    s->cst3 |= NPCM7XX_SMBCST3_EO_BUSY;
    427    trace_npcm7xx_smbus_stop(DEVICE(s)->canonical_path);
    428    npcm7xx_smbus_update_irq(s);
    429}
    430
    431
    432static void npcm7xx_smbus_stop(NPCM7xxSMBusState *s)
    433{
    434    if (s->st & NPCM7XX_SMBST_MODE) {
    435        switch (s->status) {
    436        case NPCM7XX_SMBUS_STATUS_RECEIVING:
    437        case NPCM7XX_SMBUS_STATUS_STOPPING_LAST_RECEIVE:
    438            s->status = NPCM7XX_SMBUS_STATUS_STOPPING_LAST_RECEIVE;
    439            break;
    440
    441        case NPCM7XX_SMBUS_STATUS_NEGACK:
    442            s->status = NPCM7XX_SMBUS_STATUS_STOPPING_NEGACK;
    443            break;
    444
    445        default:
    446            npcm7xx_smbus_execute_stop(s);
    447            break;
    448        }
    449    }
    450}
    451
    452static uint8_t npcm7xx_smbus_read_sda(NPCM7xxSMBusState *s)
    453{
    454    uint8_t value = s->sda;
    455
    456    switch (s->status) {
    457    case NPCM7XX_SMBUS_STATUS_STOPPING_LAST_RECEIVE:
    458        if (NPCM7XX_SMBUS_FIFO_ENABLED(s)) {
    459            if (NPCM7XX_SMBRXF_STS_RX_BYTES(s->rxf_sts) <= 1) {
    460                npcm7xx_smbus_execute_stop(s);
    461            }
    462            if (NPCM7XX_SMBRXF_STS_RX_BYTES(s->rxf_sts) == 0) {
    463                qemu_log_mask(LOG_GUEST_ERROR,
    464                              "%s: read to SDA with an empty rx-fifo buffer, "
    465                              "result undefined: %u\n",
    466                              DEVICE(s)->canonical_path, s->sda);
    467                break;
    468            }
    469            npcm7xx_smbus_read_byte_fifo(s);
    470            value = s->sda;
    471        } else {
    472            npcm7xx_smbus_execute_stop(s);
    473        }
    474        break;
    475
    476    case NPCM7XX_SMBUS_STATUS_RECEIVING:
    477        if (NPCM7XX_SMBUS_FIFO_ENABLED(s)) {
    478            npcm7xx_smbus_read_byte_fifo(s);
    479            value = s->sda;
    480        } else {
    481            npcm7xx_smbus_recv_byte(s);
    482        }
    483        break;
    484
    485    default:
    486        /* Do nothing */
    487        break;
    488    }
    489
    490    return value;
    491}
    492
    493static void npcm7xx_smbus_write_sda(NPCM7xxSMBusState *s, uint8_t value)
    494{
    495    s->sda = value;
    496    if (s->st & NPCM7XX_SMBST_MODE) {
    497        switch (s->status) {
    498        case NPCM7XX_SMBUS_STATUS_IDLE:
    499            npcm7xx_smbus_send_address(s, value);
    500            break;
    501        case NPCM7XX_SMBUS_STATUS_SENDING:
    502            npcm7xx_smbus_send_byte(s, value);
    503            break;
    504        default:
    505            qemu_log_mask(LOG_GUEST_ERROR,
    506                          "%s: write to SDA in invalid status %d: %u\n",
    507                          DEVICE(s)->canonical_path, s->status, value);
    508            break;
    509        }
    510    }
    511}
    512
    513static void npcm7xx_smbus_write_st(NPCM7xxSMBusState *s, uint8_t value)
    514{
    515    s->st = WRITE_ONE_CLEAR(s->st, value, NPCM7XX_SMBST_STP);
    516    s->st = WRITE_ONE_CLEAR(s->st, value, NPCM7XX_SMBST_BER);
    517    s->st = WRITE_ONE_CLEAR(s->st, value, NPCM7XX_SMBST_STASTR);
    518    s->st = WRITE_ONE_CLEAR(s->st, value, NPCM7XX_SMBST_NMATCH);
    519
    520    if (value & NPCM7XX_SMBST_NEGACK) {
    521        s->st &= ~NPCM7XX_SMBST_NEGACK;
    522        if (s->status == NPCM7XX_SMBUS_STATUS_STOPPING_NEGACK) {
    523            npcm7xx_smbus_execute_stop(s);
    524        }
    525    }
    526
    527    if (value & NPCM7XX_SMBST_STASTR &&
    528        s->status == NPCM7XX_SMBUS_STATUS_RECEIVING) {
    529        if (NPCM7XX_SMBUS_FIFO_ENABLED(s)) {
    530            npcm7xx_smbus_recv_fifo(s);
    531        } else {
    532            npcm7xx_smbus_recv_byte(s);
    533        }
    534    }
    535
    536    npcm7xx_smbus_update_irq(s);
    537}
    538
    539static void npcm7xx_smbus_write_cst(NPCM7xxSMBusState *s, uint8_t value)
    540{
    541    uint8_t new_value = s->cst;
    542
    543    s->cst = WRITE_ONE_CLEAR(new_value, value, NPCM7XX_SMBCST_BB);
    544    npcm7xx_smbus_update_irq(s);
    545}
    546
    547static void npcm7xx_smbus_write_cst3(NPCM7xxSMBusState *s, uint8_t value)
    548{
    549    s->cst3 = WRITE_ONE_CLEAR(s->cst3, value, NPCM7XX_SMBCST3_EO_BUSY);
    550    npcm7xx_smbus_update_irq(s);
    551}
    552
    553static void npcm7xx_smbus_write_ctl1(NPCM7xxSMBusState *s, uint8_t value)
    554{
    555    s->ctl1 = KEEP_OLD_BIT(s->ctl1, value,
    556            NPCM7XX_SMBCTL1_START | NPCM7XX_SMBCTL1_STOP | NPCM7XX_SMBCTL1_ACK);
    557
    558    if (value & NPCM7XX_SMBCTL1_START) {
    559        npcm7xx_smbus_start(s);
    560    }
    561
    562    if (value & NPCM7XX_SMBCTL1_STOP) {
    563        npcm7xx_smbus_stop(s);
    564    }
    565
    566    npcm7xx_smbus_update_irq(s);
    567}
    568
    569static void npcm7xx_smbus_write_ctl2(NPCM7xxSMBusState *s, uint8_t value)
    570{
    571    s->ctl2 = value;
    572
    573    if (!NPCM7XX_SMBUS_ENABLED(s)) {
    574        /* Disable this SMBus module. */
    575        s->ctl1 = 0;
    576        s->st = 0;
    577        s->cst3 = s->cst3 & (~NPCM7XX_SMBCST3_EO_BUSY);
    578        s->cst = 0;
    579        npcm7xx_smbus_clear_buffer(s);
    580    }
    581}
    582
    583static void npcm7xx_smbus_write_ctl3(NPCM7xxSMBusState *s, uint8_t value)
    584{
    585    uint8_t old_ctl3 = s->ctl3;
    586
    587    /* Write to SDA and SCL bits are ignored. */
    588    s->ctl3 =  KEEP_OLD_BIT(old_ctl3, value,
    589                            NPCM7XX_SMBCTL3_SCL_LVL | NPCM7XX_SMBCTL3_SDA_LVL);
    590}
    591
    592static void npcm7xx_smbus_write_fif_ctl(NPCM7xxSMBusState *s, uint8_t value)
    593{
    594    uint8_t new_ctl = value;
    595
    596    new_ctl = KEEP_OLD_BIT(s->fif_ctl, new_ctl, NPCM7XX_SMBFIF_CTL_FAIR_RDY);
    597    new_ctl = WRITE_ONE_CLEAR(new_ctl, value, NPCM7XX_SMBFIF_CTL_FAIR_RDY);
    598    new_ctl = KEEP_OLD_BIT(s->fif_ctl, new_ctl, NPCM7XX_SMBFIF_CTL_FAIR_BUSY);
    599    s->fif_ctl = new_ctl;
    600}
    601
    602static void npcm7xx_smbus_write_fif_cts(NPCM7xxSMBusState *s, uint8_t value)
    603{
    604    s->fif_cts = WRITE_ONE_CLEAR(s->fif_cts, value, NPCM7XX_SMBFIF_CTS_STR);
    605    s->fif_cts = WRITE_ONE_CLEAR(s->fif_cts, value, NPCM7XX_SMBFIF_CTS_RXF_TXE);
    606    s->fif_cts = KEEP_OLD_BIT(value, s->fif_cts, NPCM7XX_SMBFIF_CTS_RFTE_IE);
    607
    608    if (value & NPCM7XX_SMBFIF_CTS_CLR_FIFO) {
    609        npcm7xx_smbus_clear_buffer(s);
    610    }
    611}
    612
    613static void npcm7xx_smbus_write_txf_ctl(NPCM7xxSMBusState *s, uint8_t value)
    614{
    615    s->txf_ctl = value;
    616}
    617
    618static void npcm7xx_smbus_write_t_out(NPCM7xxSMBusState *s, uint8_t value)
    619{
    620    uint8_t new_t_out = value;
    621
    622    if ((value & NPCM7XX_SMBT_OUT_ST) || (!(s->t_out & NPCM7XX_SMBT_OUT_ST))) {
    623        new_t_out &= ~NPCM7XX_SMBT_OUT_ST;
    624    } else {
    625        new_t_out |= NPCM7XX_SMBT_OUT_ST;
    626    }
    627
    628    s->t_out = new_t_out;
    629}
    630
    631static void npcm7xx_smbus_write_txf_sts(NPCM7xxSMBusState *s, uint8_t value)
    632{
    633    s->txf_sts = WRITE_ONE_CLEAR(s->txf_sts, value, NPCM7XX_SMBTXF_STS_TX_THST);
    634}
    635
    636static void npcm7xx_smbus_write_rxf_sts(NPCM7xxSMBusState *s, uint8_t value)
    637{
    638    if (value & NPCM7XX_SMBRXF_STS_RX_THST) {
    639        s->rxf_sts &= ~NPCM7XX_SMBRXF_STS_RX_THST;
    640        if (s->status == NPCM7XX_SMBUS_STATUS_RECEIVING) {
    641            npcm7xx_smbus_recv_fifo(s);
    642        }
    643    }
    644}
    645
    646static void npcm7xx_smbus_write_rxf_ctl(NPCM7xxSMBusState *s, uint8_t value)
    647{
    648    uint8_t new_ctl = value;
    649
    650    if (!(value & NPCM7XX_SMBRXF_CTL_LAST)) {
    651        new_ctl = KEEP_OLD_BIT(s->rxf_ctl, new_ctl, NPCM7XX_SMBRXF_CTL_LAST);
    652    }
    653    s->rxf_ctl = new_ctl;
    654}
    655
    656static uint64_t npcm7xx_smbus_read(void *opaque, hwaddr offset, unsigned size)
    657{
    658    NPCM7xxSMBusState *s = opaque;
    659    uint64_t value = 0;
    660    uint8_t bank = s->ctl3 & NPCM7XX_SMBCTL3_BNK_SEL;
    661
    662    /* The order of the registers are their order in memory. */
    663    switch (offset) {
    664    case NPCM7XX_SMB_SDA:
    665        value = npcm7xx_smbus_read_sda(s);
    666        break;
    667
    668    case NPCM7XX_SMB_ST:
    669        value = s->st;
    670        break;
    671
    672    case NPCM7XX_SMB_CST:
    673        value = s->cst;
    674        break;
    675
    676    case NPCM7XX_SMB_CTL1:
    677        value = s->ctl1;
    678        break;
    679
    680    case NPCM7XX_SMB_ADDR1:
    681        value = s->addr[0];
    682        break;
    683
    684    case NPCM7XX_SMB_CTL2:
    685        value = s->ctl2;
    686        break;
    687
    688    case NPCM7XX_SMB_ADDR2:
    689        value = s->addr[1];
    690        break;
    691
    692    case NPCM7XX_SMB_CTL3:
    693        value = s->ctl3;
    694        break;
    695
    696    case NPCM7XX_SMB_CST2:
    697        value = s->cst2;
    698        break;
    699
    700    case NPCM7XX_SMB_CST3:
    701        value = s->cst3;
    702        break;
    703
    704    case NPCM7XX_SMB_VER:
    705        value = npcm7xx_smbus_get_version();
    706        break;
    707
    708    /* This register is either invalid or banked at this point. */
    709    default:
    710        if (bank) {
    711            /* Bank 1 */
    712            switch (offset) {
    713            case NPCM7XX_SMB_FIF_CTS:
    714                value = s->fif_cts;
    715                break;
    716
    717            case NPCM7XX_SMB_FAIR_PER:
    718                value = s->fair_per;
    719                break;
    720
    721            case NPCM7XX_SMB_TXF_CTL:
    722                value = s->txf_ctl;
    723                break;
    724
    725            case NPCM7XX_SMB_T_OUT:
    726                value = s->t_out;
    727                break;
    728
    729            case NPCM7XX_SMB_TXF_STS:
    730                value = s->txf_sts;
    731                break;
    732
    733            case NPCM7XX_SMB_RXF_STS:
    734                value = s->rxf_sts;
    735                break;
    736
    737            case NPCM7XX_SMB_RXF_CTL:
    738                value = s->rxf_ctl;
    739                break;
    740
    741            default:
    742                qemu_log_mask(LOG_GUEST_ERROR,
    743                        "%s: read from invalid offset 0x%" HWADDR_PRIx "\n",
    744                        DEVICE(s)->canonical_path, offset);
    745                break;
    746            }
    747        } else {
    748            /* Bank 0 */
    749            switch (offset) {
    750            case NPCM7XX_SMB_ADDR3:
    751                value = s->addr[2];
    752                break;
    753
    754            case NPCM7XX_SMB_ADDR7:
    755                value = s->addr[6];
    756                break;
    757
    758            case NPCM7XX_SMB_ADDR4:
    759                value = s->addr[3];
    760                break;
    761
    762            case NPCM7XX_SMB_ADDR8:
    763                value = s->addr[7];
    764                break;
    765
    766            case NPCM7XX_SMB_ADDR5:
    767                value = s->addr[4];
    768                break;
    769
    770            case NPCM7XX_SMB_ADDR9:
    771                value = s->addr[8];
    772                break;
    773
    774            case NPCM7XX_SMB_ADDR6:
    775                value = s->addr[5];
    776                break;
    777
    778            case NPCM7XX_SMB_ADDR10:
    779                value = s->addr[9];
    780                break;
    781
    782            case NPCM7XX_SMB_CTL4:
    783                value = s->ctl4;
    784                break;
    785
    786            case NPCM7XX_SMB_CTL5:
    787                value = s->ctl5;
    788                break;
    789
    790            case NPCM7XX_SMB_SCLLT:
    791                value = s->scllt;
    792                break;
    793
    794            case NPCM7XX_SMB_FIF_CTL:
    795                value = s->fif_ctl;
    796                break;
    797
    798            case NPCM7XX_SMB_SCLHT:
    799                value = s->sclht;
    800                break;
    801
    802            default:
    803                qemu_log_mask(LOG_GUEST_ERROR,
    804                        "%s: read from invalid offset 0x%" HWADDR_PRIx "\n",
    805                        DEVICE(s)->canonical_path, offset);
    806                break;
    807            }
    808        }
    809        break;
    810    }
    811
    812    trace_npcm7xx_smbus_read(DEVICE(s)->canonical_path, offset, value, size);
    813
    814    return value;
    815}
    816
    817static void npcm7xx_smbus_write(void *opaque, hwaddr offset, uint64_t value,
    818                              unsigned size)
    819{
    820    NPCM7xxSMBusState *s = opaque;
    821    uint8_t bank = s->ctl3 & NPCM7XX_SMBCTL3_BNK_SEL;
    822
    823    trace_npcm7xx_smbus_write(DEVICE(s)->canonical_path, offset, value, size);
    824
    825    /* The order of the registers are their order in memory. */
    826    switch (offset) {
    827    case NPCM7XX_SMB_SDA:
    828        npcm7xx_smbus_write_sda(s, value);
    829        break;
    830
    831    case NPCM7XX_SMB_ST:
    832        npcm7xx_smbus_write_st(s, value);
    833        break;
    834
    835    case NPCM7XX_SMB_CST:
    836        npcm7xx_smbus_write_cst(s, value);
    837        break;
    838
    839    case NPCM7XX_SMB_CTL1:
    840        npcm7xx_smbus_write_ctl1(s, value);
    841        break;
    842
    843    case NPCM7XX_SMB_ADDR1:
    844        s->addr[0] = value;
    845        break;
    846
    847    case NPCM7XX_SMB_CTL2:
    848        npcm7xx_smbus_write_ctl2(s, value);
    849        break;
    850
    851    case NPCM7XX_SMB_ADDR2:
    852        s->addr[1] = value;
    853        break;
    854
    855    case NPCM7XX_SMB_CTL3:
    856        npcm7xx_smbus_write_ctl3(s, value);
    857        break;
    858
    859    case NPCM7XX_SMB_CST2:
    860        qemu_log_mask(LOG_GUEST_ERROR,
    861                "%s: write to read-only reg: offset 0x%" HWADDR_PRIx "\n",
    862                DEVICE(s)->canonical_path, offset);
    863        break;
    864
    865    case NPCM7XX_SMB_CST3:
    866        npcm7xx_smbus_write_cst3(s, value);
    867        break;
    868
    869    case NPCM7XX_SMB_VER:
    870        qemu_log_mask(LOG_GUEST_ERROR,
    871                "%s: write to read-only reg: offset 0x%" HWADDR_PRIx "\n",
    872                DEVICE(s)->canonical_path, offset);
    873        break;
    874
    875    /* This register is either invalid or banked at this point. */
    876    default:
    877        if (bank) {
    878            /* Bank 1 */
    879            switch (offset) {
    880            case NPCM7XX_SMB_FIF_CTS:
    881                npcm7xx_smbus_write_fif_cts(s, value);
    882                break;
    883
    884            case NPCM7XX_SMB_FAIR_PER:
    885                s->fair_per = value;
    886                break;
    887
    888            case NPCM7XX_SMB_TXF_CTL:
    889                npcm7xx_smbus_write_txf_ctl(s, value);
    890                break;
    891
    892            case NPCM7XX_SMB_T_OUT:
    893                npcm7xx_smbus_write_t_out(s, value);
    894                break;
    895
    896            case NPCM7XX_SMB_TXF_STS:
    897                npcm7xx_smbus_write_txf_sts(s, value);
    898                break;
    899
    900            case NPCM7XX_SMB_RXF_STS:
    901                npcm7xx_smbus_write_rxf_sts(s, value);
    902                break;
    903
    904            case NPCM7XX_SMB_RXF_CTL:
    905                npcm7xx_smbus_write_rxf_ctl(s, value);
    906                break;
    907
    908            default:
    909                qemu_log_mask(LOG_GUEST_ERROR,
    910                        "%s: write to invalid offset 0x%" HWADDR_PRIx "\n",
    911                        DEVICE(s)->canonical_path, offset);
    912                break;
    913            }
    914        } else {
    915            /* Bank 0 */
    916            switch (offset) {
    917            case NPCM7XX_SMB_ADDR3:
    918                s->addr[2] = value;
    919                break;
    920
    921            case NPCM7XX_SMB_ADDR7:
    922                s->addr[6] = value;
    923                break;
    924
    925            case NPCM7XX_SMB_ADDR4:
    926                s->addr[3] = value;
    927                break;
    928
    929            case NPCM7XX_SMB_ADDR8:
    930                s->addr[7] = value;
    931                break;
    932
    933            case NPCM7XX_SMB_ADDR5:
    934                s->addr[4] = value;
    935                break;
    936
    937            case NPCM7XX_SMB_ADDR9:
    938                s->addr[8] = value;
    939                break;
    940
    941            case NPCM7XX_SMB_ADDR6:
    942                s->addr[5] = value;
    943                break;
    944
    945            case NPCM7XX_SMB_ADDR10:
    946                s->addr[9] = value;
    947                break;
    948
    949            case NPCM7XX_SMB_CTL4:
    950                s->ctl4 = value;
    951                break;
    952
    953            case NPCM7XX_SMB_CTL5:
    954                s->ctl5 = value;
    955                break;
    956
    957            case NPCM7XX_SMB_SCLLT:
    958                s->scllt = value;
    959                break;
    960
    961            case NPCM7XX_SMB_FIF_CTL:
    962                npcm7xx_smbus_write_fif_ctl(s, value);
    963                break;
    964
    965            case NPCM7XX_SMB_SCLHT:
    966                s->sclht = value;
    967                break;
    968
    969            default:
    970                qemu_log_mask(LOG_GUEST_ERROR,
    971                        "%s: write to invalid offset 0x%" HWADDR_PRIx "\n",
    972                        DEVICE(s)->canonical_path, offset);
    973                break;
    974            }
    975        }
    976        break;
    977    }
    978}
    979
    980static const MemoryRegionOps npcm7xx_smbus_ops = {
    981    .read = npcm7xx_smbus_read,
    982    .write = npcm7xx_smbus_write,
    983    .endianness = DEVICE_LITTLE_ENDIAN,
    984    .valid = {
    985        .min_access_size = 1,
    986        .max_access_size = 1,
    987        .unaligned = false,
    988    },
    989};
    990
    991static void npcm7xx_smbus_enter_reset(Object *obj, ResetType type)
    992{
    993    NPCM7xxSMBusState *s = NPCM7XX_SMBUS(obj);
    994
    995    s->st = NPCM7XX_SMB_ST_INIT_VAL;
    996    s->cst = NPCM7XX_SMB_CST_INIT_VAL;
    997    s->cst2 = NPCM7XX_SMB_CST2_INIT_VAL;
    998    s->cst3 = NPCM7XX_SMB_CST3_INIT_VAL;
    999    s->ctl1 = NPCM7XX_SMB_CTL1_INIT_VAL;
   1000    s->ctl2 = NPCM7XX_SMB_CTL2_INIT_VAL;
   1001    s->ctl3 = NPCM7XX_SMB_CTL3_INIT_VAL;
   1002    s->ctl4 = NPCM7XX_SMB_CTL4_INIT_VAL;
   1003    s->ctl5 = NPCM7XX_SMB_CTL5_INIT_VAL;
   1004
   1005    for (int i = 0; i < NPCM7XX_SMBUS_NR_ADDRS; ++i) {
   1006        s->addr[i] = NPCM7XX_SMB_ADDR_INIT_VAL;
   1007    }
   1008    s->scllt = NPCM7XX_SMB_SCLLT_INIT_VAL;
   1009    s->sclht = NPCM7XX_SMB_SCLHT_INIT_VAL;
   1010
   1011    s->fif_ctl = NPCM7XX_SMB_FIF_CTL_INIT_VAL;
   1012    s->fif_cts = NPCM7XX_SMB_FIF_CTS_INIT_VAL;
   1013    s->fair_per = NPCM7XX_SMB_FAIR_PER_INIT_VAL;
   1014    s->txf_ctl = NPCM7XX_SMB_TXF_CTL_INIT_VAL;
   1015    s->t_out = NPCM7XX_SMB_T_OUT_INIT_VAL;
   1016    s->txf_sts = NPCM7XX_SMB_TXF_STS_INIT_VAL;
   1017    s->rxf_sts = NPCM7XX_SMB_RXF_STS_INIT_VAL;
   1018    s->rxf_ctl = NPCM7XX_SMB_RXF_CTL_INIT_VAL;
   1019
   1020    npcm7xx_smbus_clear_buffer(s);
   1021    s->status = NPCM7XX_SMBUS_STATUS_IDLE;
   1022    s->rx_cur = 0;
   1023}
   1024
   1025static void npcm7xx_smbus_hold_reset(Object *obj)
   1026{
   1027    NPCM7xxSMBusState *s = NPCM7XX_SMBUS(obj);
   1028
   1029    qemu_irq_lower(s->irq);
   1030}
   1031
   1032static void npcm7xx_smbus_init(Object *obj)
   1033{
   1034    NPCM7xxSMBusState *s = NPCM7XX_SMBUS(obj);
   1035    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
   1036
   1037    sysbus_init_irq(sbd, &s->irq);
   1038    memory_region_init_io(&s->iomem, obj, &npcm7xx_smbus_ops, s,
   1039                          "regs", 4 * KiB);
   1040    sysbus_init_mmio(sbd, &s->iomem);
   1041
   1042    s->bus = i2c_init_bus(DEVICE(s), "i2c-bus");
   1043}
   1044
   1045static const VMStateDescription vmstate_npcm7xx_smbus = {
   1046    .name = "npcm7xx-smbus",
   1047    .version_id = 0,
   1048    .minimum_version_id = 0,
   1049    .fields = (VMStateField[]) {
   1050        VMSTATE_UINT8(sda, NPCM7xxSMBusState),
   1051        VMSTATE_UINT8(st, NPCM7xxSMBusState),
   1052        VMSTATE_UINT8(cst, NPCM7xxSMBusState),
   1053        VMSTATE_UINT8(cst2, NPCM7xxSMBusState),
   1054        VMSTATE_UINT8(cst3, NPCM7xxSMBusState),
   1055        VMSTATE_UINT8(ctl1, NPCM7xxSMBusState),
   1056        VMSTATE_UINT8(ctl2, NPCM7xxSMBusState),
   1057        VMSTATE_UINT8(ctl3, NPCM7xxSMBusState),
   1058        VMSTATE_UINT8(ctl4, NPCM7xxSMBusState),
   1059        VMSTATE_UINT8(ctl5, NPCM7xxSMBusState),
   1060        VMSTATE_UINT8_ARRAY(addr, NPCM7xxSMBusState, NPCM7XX_SMBUS_NR_ADDRS),
   1061        VMSTATE_UINT8(scllt, NPCM7xxSMBusState),
   1062        VMSTATE_UINT8(sclht, NPCM7xxSMBusState),
   1063        VMSTATE_UINT8(fif_ctl, NPCM7xxSMBusState),
   1064        VMSTATE_UINT8(fif_cts, NPCM7xxSMBusState),
   1065        VMSTATE_UINT8(fair_per, NPCM7xxSMBusState),
   1066        VMSTATE_UINT8(txf_ctl, NPCM7xxSMBusState),
   1067        VMSTATE_UINT8(t_out, NPCM7xxSMBusState),
   1068        VMSTATE_UINT8(txf_sts, NPCM7xxSMBusState),
   1069        VMSTATE_UINT8(rxf_sts, NPCM7xxSMBusState),
   1070        VMSTATE_UINT8(rxf_ctl, NPCM7xxSMBusState),
   1071        VMSTATE_UINT8_ARRAY(rx_fifo, NPCM7xxSMBusState,
   1072                            NPCM7XX_SMBUS_FIFO_SIZE),
   1073        VMSTATE_UINT8(rx_cur, NPCM7xxSMBusState),
   1074        VMSTATE_END_OF_LIST(),
   1075    },
   1076};
   1077
   1078static void npcm7xx_smbus_class_init(ObjectClass *klass, void *data)
   1079{
   1080    ResettableClass *rc = RESETTABLE_CLASS(klass);
   1081    DeviceClass *dc = DEVICE_CLASS(klass);
   1082
   1083    dc->desc = "NPCM7xx System Management Bus";
   1084    dc->vmsd = &vmstate_npcm7xx_smbus;
   1085    rc->phases.enter = npcm7xx_smbus_enter_reset;
   1086    rc->phases.hold = npcm7xx_smbus_hold_reset;
   1087}
   1088
   1089static const TypeInfo npcm7xx_smbus_types[] = {
   1090    {
   1091        .name = TYPE_NPCM7XX_SMBUS,
   1092        .parent = TYPE_SYS_BUS_DEVICE,
   1093        .instance_size = sizeof(NPCM7xxSMBusState),
   1094        .class_init = npcm7xx_smbus_class_init,
   1095        .instance_init = npcm7xx_smbus_init,
   1096    },
   1097};
   1098DEFINE_TYPES(npcm7xx_smbus_types);