qemu

Форк
0
/
npcm7xx_smbus.c 
1098 строк · 32.2 Кб
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

29
enum 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

43
enum 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

59
enum 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

194
static uint8_t npcm7xx_smbus_get_version(void)
195
{
196
    return NPCM7XX_SMBUS_VERSION_FIFO_SUPPORTED << 7 |
197
           NPCM7XX_SMBUS_VERSION_NUMBER;
198
}
199

200
static 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

230
static 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

237
static 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

244
static 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

266
static 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

279
static 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

325
static 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

340
static 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

368
static 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

420
static 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

432
static 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

452
static 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

493
static 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

513
static 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

539
static 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

547
static 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

553
static 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

569
static 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

583
static 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

592
static 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

602
static 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

613
static void npcm7xx_smbus_write_txf_ctl(NPCM7xxSMBusState *s, uint8_t value)
614
{
615
    s->txf_ctl = value;
616
}
617

618
static 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

631
static 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

636
static 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

646
static 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

656
static 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

817
static 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

980
static 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

991
static 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

1025
static void npcm7xx_smbus_hold_reset(Object *obj, ResetType type)
1026
{
1027
    NPCM7xxSMBusState *s = NPCM7XX_SMBUS(obj);
1028

1029
    qemu_irq_lower(s->irq);
1030
}
1031

1032
static 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

1045
static const VMStateDescription vmstate_npcm7xx_smbus = {
1046
    .name = "npcm7xx-smbus",
1047
    .version_id = 0,
1048
    .minimum_version_id = 0,
1049
    .fields = (const 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

1078
static 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

1089
static 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
};
1098
DEFINE_TYPES(npcm7xx_smbus_types);
1099

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.