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
)
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
= (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
);