2
* Nuvoton NPCM7xx SMBus Module.
4
* Copyright 2020 Google LLC
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.
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
17
#include "qemu/osdep.h"
19
#include "hw/i2c/npcm7xx_smbus.h"
20
#include "migration/vmstate.h"
21
#include "qemu/bitops.h"
22
#include "qemu/guest-random.h"
24
#include "qemu/module.h"
25
#include "qemu/units.h"
29
enum NPCM7xxSMBusCommonRegister {
30
NPCM7XX_SMB_SDA = 0x0,
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,
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,
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,
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)
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)
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)
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)
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)
116
#define NPCM7XX_SMBCTL2_SCLFRQ(rv) extract8((rv), 1, 6)
117
#define NPCM7XX_SMBCTL2_ENABLE BIT(0)
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)
129
#define NPCM7XX_ADDR_EN BIT(7)
130
#define NPCM7XX_ADDR_A(rv) extract8((rv), 0, 6)
132
/* FIFO Mode Register 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)
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)
144
#define NPCM7XX_SMBTXF_CTL_THR_TXIE BIT(6)
145
#define NPCM7XX_SMBTXF_CTL_TX_THR(rv) extract8((rv), 0, 5)
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)
151
#define NPCM7XX_SMBTXF_STS_TX_THST BIT(6)
152
#define NPCM7XX_SMBTXF_STS_TX_BYTES(rv) extract8((rv), 0, 5)
154
#define NPCM7XX_SMBRXF_STS_RX_THST BIT(6)
155
#define NPCM7XX_SMBRXF_STS_RX_BYTES(rv) extract8((rv), 0, 5)
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)
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))
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)
168
/* VERSION fields values, read-only. */
169
#define NPCM7XX_SMBUS_VERSION_NUMBER 1
170
#define NPCM7XX_SMBUS_VERSION_FIFO_SUPPORTED 1
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
194
static uint8_t npcm7xx_smbus_get_version(void)
196
return NPCM7XX_SMBUS_VERSION_FIFO_SUPPORTED << 7 |
197
NPCM7XX_SMBUS_VERSION_NUMBER;
200
static void npcm7xx_smbus_update_irq(NPCM7xxSMBusState *s)
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));
222
s->cst2 |= NPCM7XX_SMBCST2_INTSTS;
224
s->cst2 &= ~NPCM7XX_SMBCST2_INTSTS;
226
qemu_set_irq(s->irq, level);
230
static void npcm7xx_smbus_nack(NPCM7xxSMBusState *s)
232
s->st &= ~NPCM7XX_SMBST_SDAST;
233
s->st |= NPCM7XX_SMBST_NEGACK;
234
s->status = NPCM7XX_SMBUS_STATUS_NEGACK;
237
static void npcm7xx_smbus_clear_buffer(NPCM7xxSMBusState *s)
239
s->fif_cts &= ~NPCM7XX_SMBFIF_CTS_RXF_TXE;
244
static void npcm7xx_smbus_send_byte(NPCM7xxSMBusState *s, uint8_t value)
246
int rv = i2c_send(s->bus, value);
249
npcm7xx_smbus_nack(s);
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;
262
trace_npcm7xx_smbus_send_byte((DEVICE(s)->canonical_path), value, !rv);
263
npcm7xx_smbus_update_irq(s);
266
static void npcm7xx_smbus_recv_byte(NPCM7xxSMBusState *s)
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);
273
s->st &= NPCM7XX_SMBCTL1_ACK;
275
trace_npcm7xx_smbus_recv_byte((DEVICE(s)->canonical_path), s->sda);
276
npcm7xx_smbus_update_irq(s);
279
static void npcm7xx_smbus_recv_fifo(NPCM7xxSMBusState *s)
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);
285
if (received_bytes == expected_bytes) {
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),
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);
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);
312
s->rxf_ctl &= ~NPCM7XX_SMBRXF_CTL_LAST;
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;
320
s->st &= ~NPCM7XX_SMBST_SDAST;
322
npcm7xx_smbus_update_irq(s);
325
static void npcm7xx_smbus_read_byte_fifo(NPCM7xxSMBusState *s)
327
uint8_t received_bytes = NPCM7XX_SMBRXF_STS_RX_BYTES(s->rxf_sts);
329
if (received_bytes == 0) {
330
npcm7xx_smbus_recv_fifo(s);
334
s->sda = s->rx_fifo[s->rx_cur];
335
s->rx_cur = (s->rx_cur + 1u) % NPCM7XX_SMBUS_FIFO_SIZE;
337
npcm7xx_smbus_update_irq(s);
340
static void npcm7xx_smbus_start(NPCM7xxSMBusState *s)
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.)
347
int available = !i2c_bus_busy(s->bus) ||
348
s->status != NPCM7XX_SMBUS_STATUS_IDLE;
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;
357
s->st &= ~NPCM7XX_SMBST_MODE;
358
s->cst &= ~NPCM7XX_SMBCST_BUSY;
359
s->st |= NPCM7XX_SMBST_BER;
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);
368
static void npcm7xx_smbus_send_address(NPCM7xxSMBusState *s, uint8_t value)
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);
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.*/
383
s->st &= ~NPCM7XX_SMBST_XMIT;
385
s->st |= NPCM7XX_SMBST_XMIT;
387
npcm7xx_smbus_nack(s);
388
npcm7xx_smbus_update_irq(s);
392
s->st &= ~NPCM7XX_SMBST_NEGACK;
394
s->status = NPCM7XX_SMBUS_STATUS_RECEIVING;
395
s->st &= ~NPCM7XX_SMBST_XMIT;
397
s->status = NPCM7XX_SMBUS_STATUS_SENDING;
398
s->st |= NPCM7XX_SMBST_XMIT;
401
if (s->ctl1 & NPCM7XX_SMBCTL1_STASTRE) {
402
s->st |= NPCM7XX_SMBST_STASTR;
404
s->st |= NPCM7XX_SMBST_SDAST;
407
s->st |= NPCM7XX_SMBST_SDAST;
408
if (NPCM7XX_SMBUS_FIFO_ENABLED(s)) {
409
npcm7xx_smbus_recv_fifo(s);
411
npcm7xx_smbus_recv_byte(s);
413
} else if (NPCM7XX_SMBUS_FIFO_ENABLED(s)) {
414
s->st |= NPCM7XX_SMBST_SDAST;
415
s->fif_cts |= NPCM7XX_SMBFIF_CTS_RXF_TXE;
417
npcm7xx_smbus_update_irq(s);
420
static void npcm7xx_smbus_execute_stop(NPCM7xxSMBusState *s)
422
i2c_end_transfer(s->bus);
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);
432
static void npcm7xx_smbus_stop(NPCM7xxSMBusState *s)
434
if (s->st & NPCM7XX_SMBST_MODE) {
436
case NPCM7XX_SMBUS_STATUS_RECEIVING:
437
case NPCM7XX_SMBUS_STATUS_STOPPING_LAST_RECEIVE:
438
s->status = NPCM7XX_SMBUS_STATUS_STOPPING_LAST_RECEIVE;
441
case NPCM7XX_SMBUS_STATUS_NEGACK:
442
s->status = NPCM7XX_SMBUS_STATUS_STOPPING_NEGACK;
446
npcm7xx_smbus_execute_stop(s);
452
static uint8_t npcm7xx_smbus_read_sda(NPCM7xxSMBusState *s)
454
uint8_t value = s->sda;
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);
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);
469
npcm7xx_smbus_read_byte_fifo(s);
472
npcm7xx_smbus_execute_stop(s);
476
case NPCM7XX_SMBUS_STATUS_RECEIVING:
477
if (NPCM7XX_SMBUS_FIFO_ENABLED(s)) {
478
npcm7xx_smbus_read_byte_fifo(s);
481
npcm7xx_smbus_recv_byte(s);
493
static void npcm7xx_smbus_write_sda(NPCM7xxSMBusState *s, uint8_t value)
496
if (s->st & NPCM7XX_SMBST_MODE) {
498
case NPCM7XX_SMBUS_STATUS_IDLE:
499
npcm7xx_smbus_send_address(s, value);
501
case NPCM7XX_SMBUS_STATUS_SENDING:
502
npcm7xx_smbus_send_byte(s, value);
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);
513
static void npcm7xx_smbus_write_st(NPCM7xxSMBusState *s, uint8_t value)
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);
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);
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);
532
npcm7xx_smbus_recv_byte(s);
536
npcm7xx_smbus_update_irq(s);
539
static void npcm7xx_smbus_write_cst(NPCM7xxSMBusState *s, uint8_t value)
541
uint8_t new_value = s->cst;
543
s->cst = WRITE_ONE_CLEAR(new_value, value, NPCM7XX_SMBCST_BB);
544
npcm7xx_smbus_update_irq(s);
547
static void npcm7xx_smbus_write_cst3(NPCM7xxSMBusState *s, uint8_t value)
549
s->cst3 = WRITE_ONE_CLEAR(s->cst3, value, NPCM7XX_SMBCST3_EO_BUSY);
550
npcm7xx_smbus_update_irq(s);
553
static void npcm7xx_smbus_write_ctl1(NPCM7xxSMBusState *s, uint8_t value)
555
s->ctl1 = KEEP_OLD_BIT(s->ctl1, value,
556
NPCM7XX_SMBCTL1_START | NPCM7XX_SMBCTL1_STOP | NPCM7XX_SMBCTL1_ACK);
558
if (value & NPCM7XX_SMBCTL1_START) {
559
npcm7xx_smbus_start(s);
562
if (value & NPCM7XX_SMBCTL1_STOP) {
563
npcm7xx_smbus_stop(s);
566
npcm7xx_smbus_update_irq(s);
569
static void npcm7xx_smbus_write_ctl2(NPCM7xxSMBusState *s, uint8_t value)
573
if (!NPCM7XX_SMBUS_ENABLED(s)) {
574
/* Disable this SMBus module. */
577
s->cst3 = s->cst3 & (~NPCM7XX_SMBCST3_EO_BUSY);
579
npcm7xx_smbus_clear_buffer(s);
583
static void npcm7xx_smbus_write_ctl3(NPCM7xxSMBusState *s, uint8_t value)
585
uint8_t old_ctl3 = s->ctl3;
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);
592
static void npcm7xx_smbus_write_fif_ctl(NPCM7xxSMBusState *s, uint8_t value)
594
uint8_t new_ctl = value;
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;
602
static void npcm7xx_smbus_write_fif_cts(NPCM7xxSMBusState *s, uint8_t value)
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);
608
if (value & NPCM7XX_SMBFIF_CTS_CLR_FIFO) {
609
npcm7xx_smbus_clear_buffer(s);
613
static void npcm7xx_smbus_write_txf_ctl(NPCM7xxSMBusState *s, uint8_t value)
618
static void npcm7xx_smbus_write_t_out(NPCM7xxSMBusState *s, uint8_t value)
620
uint8_t new_t_out = value;
622
if ((value & NPCM7XX_SMBT_OUT_ST) || (!(s->t_out & NPCM7XX_SMBT_OUT_ST))) {
623
new_t_out &= ~NPCM7XX_SMBT_OUT_ST;
625
new_t_out |= NPCM7XX_SMBT_OUT_ST;
628
s->t_out = new_t_out;
631
static void npcm7xx_smbus_write_txf_sts(NPCM7xxSMBusState *s, uint8_t value)
633
s->txf_sts = WRITE_ONE_CLEAR(s->txf_sts, value, NPCM7XX_SMBTXF_STS_TX_THST);
636
static void npcm7xx_smbus_write_rxf_sts(NPCM7xxSMBusState *s, uint8_t value)
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);
646
static void npcm7xx_smbus_write_rxf_ctl(NPCM7xxSMBusState *s, uint8_t value)
648
uint8_t new_ctl = value;
650
if (!(value & NPCM7XX_SMBRXF_CTL_LAST)) {
651
new_ctl = KEEP_OLD_BIT(s->rxf_ctl, new_ctl, NPCM7XX_SMBRXF_CTL_LAST);
653
s->rxf_ctl = new_ctl;
656
static uint64_t npcm7xx_smbus_read(void *opaque, hwaddr offset, unsigned size)
658
NPCM7xxSMBusState *s = opaque;
660
uint8_t bank = s->ctl3 & NPCM7XX_SMBCTL3_BNK_SEL;
662
/* The order of the registers are their order in memory. */
664
case NPCM7XX_SMB_SDA:
665
value = npcm7xx_smbus_read_sda(s);
672
case NPCM7XX_SMB_CST:
676
case NPCM7XX_SMB_CTL1:
680
case NPCM7XX_SMB_ADDR1:
684
case NPCM7XX_SMB_CTL2:
688
case NPCM7XX_SMB_ADDR2:
692
case NPCM7XX_SMB_CTL3:
696
case NPCM7XX_SMB_CST2:
700
case NPCM7XX_SMB_CST3:
704
case NPCM7XX_SMB_VER:
705
value = npcm7xx_smbus_get_version();
708
/* This register is either invalid or banked at this point. */
713
case NPCM7XX_SMB_FIF_CTS:
717
case NPCM7XX_SMB_FAIR_PER:
721
case NPCM7XX_SMB_TXF_CTL:
725
case NPCM7XX_SMB_T_OUT:
729
case NPCM7XX_SMB_TXF_STS:
733
case NPCM7XX_SMB_RXF_STS:
737
case NPCM7XX_SMB_RXF_CTL:
742
qemu_log_mask(LOG_GUEST_ERROR,
743
"%s: read from invalid offset 0x%" HWADDR_PRIx "\n",
744
DEVICE(s)->canonical_path, offset);
750
case NPCM7XX_SMB_ADDR3:
754
case NPCM7XX_SMB_ADDR7:
758
case NPCM7XX_SMB_ADDR4:
762
case NPCM7XX_SMB_ADDR8:
766
case NPCM7XX_SMB_ADDR5:
770
case NPCM7XX_SMB_ADDR9:
774
case NPCM7XX_SMB_ADDR6:
778
case NPCM7XX_SMB_ADDR10:
782
case NPCM7XX_SMB_CTL4:
786
case NPCM7XX_SMB_CTL5:
790
case NPCM7XX_SMB_SCLLT:
794
case NPCM7XX_SMB_FIF_CTL:
798
case NPCM7XX_SMB_SCLHT:
803
qemu_log_mask(LOG_GUEST_ERROR,
804
"%s: read from invalid offset 0x%" HWADDR_PRIx "\n",
805
DEVICE(s)->canonical_path, offset);
812
trace_npcm7xx_smbus_read(DEVICE(s)->canonical_path, offset, value, size);
817
static void npcm7xx_smbus_write(void *opaque, hwaddr offset, uint64_t value,
820
NPCM7xxSMBusState *s = opaque;
821
uint8_t bank = s->ctl3 & NPCM7XX_SMBCTL3_BNK_SEL;
823
trace_npcm7xx_smbus_write(DEVICE(s)->canonical_path, offset, value, size);
825
/* The order of the registers are their order in memory. */
827
case NPCM7XX_SMB_SDA:
828
npcm7xx_smbus_write_sda(s, value);
832
npcm7xx_smbus_write_st(s, value);
835
case NPCM7XX_SMB_CST:
836
npcm7xx_smbus_write_cst(s, value);
839
case NPCM7XX_SMB_CTL1:
840
npcm7xx_smbus_write_ctl1(s, value);
843
case NPCM7XX_SMB_ADDR1:
847
case NPCM7XX_SMB_CTL2:
848
npcm7xx_smbus_write_ctl2(s, value);
851
case NPCM7XX_SMB_ADDR2:
855
case NPCM7XX_SMB_CTL3:
856
npcm7xx_smbus_write_ctl3(s, value);
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);
865
case NPCM7XX_SMB_CST3:
866
npcm7xx_smbus_write_cst3(s, value);
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);
875
/* This register is either invalid or banked at this point. */
880
case NPCM7XX_SMB_FIF_CTS:
881
npcm7xx_smbus_write_fif_cts(s, value);
884
case NPCM7XX_SMB_FAIR_PER:
888
case NPCM7XX_SMB_TXF_CTL:
889
npcm7xx_smbus_write_txf_ctl(s, value);
892
case NPCM7XX_SMB_T_OUT:
893
npcm7xx_smbus_write_t_out(s, value);
896
case NPCM7XX_SMB_TXF_STS:
897
npcm7xx_smbus_write_txf_sts(s, value);
900
case NPCM7XX_SMB_RXF_STS:
901
npcm7xx_smbus_write_rxf_sts(s, value);
904
case NPCM7XX_SMB_RXF_CTL:
905
npcm7xx_smbus_write_rxf_ctl(s, value);
909
qemu_log_mask(LOG_GUEST_ERROR,
910
"%s: write to invalid offset 0x%" HWADDR_PRIx "\n",
911
DEVICE(s)->canonical_path, offset);
917
case NPCM7XX_SMB_ADDR3:
921
case NPCM7XX_SMB_ADDR7:
925
case NPCM7XX_SMB_ADDR4:
929
case NPCM7XX_SMB_ADDR8:
933
case NPCM7XX_SMB_ADDR5:
937
case NPCM7XX_SMB_ADDR9:
941
case NPCM7XX_SMB_ADDR6:
945
case NPCM7XX_SMB_ADDR10:
949
case NPCM7XX_SMB_CTL4:
953
case NPCM7XX_SMB_CTL5:
957
case NPCM7XX_SMB_SCLLT:
961
case NPCM7XX_SMB_FIF_CTL:
962
npcm7xx_smbus_write_fif_ctl(s, value);
965
case NPCM7XX_SMB_SCLHT:
970
qemu_log_mask(LOG_GUEST_ERROR,
971
"%s: write to invalid offset 0x%" HWADDR_PRIx "\n",
972
DEVICE(s)->canonical_path, offset);
980
static const MemoryRegionOps npcm7xx_smbus_ops = {
981
.read = npcm7xx_smbus_read,
982
.write = npcm7xx_smbus_write,
983
.endianness = DEVICE_LITTLE_ENDIAN,
985
.min_access_size = 1,
986
.max_access_size = 1,
991
static void npcm7xx_smbus_enter_reset(Object *obj, ResetType type)
993
NPCM7xxSMBusState *s = NPCM7XX_SMBUS(obj);
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;
1005
for (int i = 0; i < NPCM7XX_SMBUS_NR_ADDRS; ++i) {
1006
s->addr[i] = NPCM7XX_SMB_ADDR_INIT_VAL;
1008
s->scllt = NPCM7XX_SMB_SCLLT_INIT_VAL;
1009
s->sclht = NPCM7XX_SMB_SCLHT_INIT_VAL;
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;
1020
npcm7xx_smbus_clear_buffer(s);
1021
s->status = NPCM7XX_SMBUS_STATUS_IDLE;
1025
static void npcm7xx_smbus_hold_reset(Object *obj, ResetType type)
1027
NPCM7xxSMBusState *s = NPCM7XX_SMBUS(obj);
1029
qemu_irq_lower(s->irq);
1032
static void npcm7xx_smbus_init(Object *obj)
1034
NPCM7xxSMBusState *s = NPCM7XX_SMBUS(obj);
1035
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
1037
sysbus_init_irq(sbd, &s->irq);
1038
memory_region_init_io(&s->iomem, obj, &npcm7xx_smbus_ops, s,
1040
sysbus_init_mmio(sbd, &s->iomem);
1042
s->bus = i2c_init_bus(DEVICE(s), "i2c-bus");
1045
static const VMStateDescription vmstate_npcm7xx_smbus = {
1046
.name = "npcm7xx-smbus",
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(),
1078
static void npcm7xx_smbus_class_init(ObjectClass *klass, void *data)
1080
ResettableClass *rc = RESETTABLE_CLASS(klass);
1081
DeviceClass *dc = DEVICE_CLASS(klass);
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;
1089
static const TypeInfo npcm7xx_smbus_types[] = {
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,
1098
DEFINE_TYPES(npcm7xx_smbus_types);