xref: /openbmc/qemu/hw/i2c/npcm7xx_smbus.c (revision 94e778793954afc6ed47ef8e161044c79488e446)
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 #define KEEP_OLD_BIT(o, n, b)       (((n) & (~(b))) | ((o) & (b)))
133 #define WRITE_ONE_CLEAR(o, n, b)    ((n) & (b) ? (o) & (~(b)) : (o))
134 
135 #define NPCM7XX_SMBUS_ENABLED(s)    ((s)->ctl2 & NPCM7XX_SMBCTL2_ENABLE)
136 
137 /* VERSION fields values, read-only. */
138 #define NPCM7XX_SMBUS_VERSION_NUMBER 1
139 #define NPCM7XX_SMBUS_VERSION_FIFO_SUPPORTED 0
140 
141 /* Reset values */
142 #define NPCM7XX_SMB_ST_INIT_VAL     0x00
143 #define NPCM7XX_SMB_CST_INIT_VAL    0x10
144 #define NPCM7XX_SMB_CST2_INIT_VAL   0x00
145 #define NPCM7XX_SMB_CST3_INIT_VAL   0x00
146 #define NPCM7XX_SMB_CTL1_INIT_VAL   0x00
147 #define NPCM7XX_SMB_CTL2_INIT_VAL   0x00
148 #define NPCM7XX_SMB_CTL3_INIT_VAL   0xc0
149 #define NPCM7XX_SMB_CTL4_INIT_VAL   0x07
150 #define NPCM7XX_SMB_CTL5_INIT_VAL   0x00
151 #define NPCM7XX_SMB_ADDR_INIT_VAL   0x00
152 #define NPCM7XX_SMB_SCLLT_INIT_VAL  0x00
153 #define NPCM7XX_SMB_SCLHT_INIT_VAL  0x00
154 
155 static uint8_t npcm7xx_smbus_get_version(void)
156 {
157     return NPCM7XX_SMBUS_VERSION_FIFO_SUPPORTED << 7 |
158            NPCM7XX_SMBUS_VERSION_NUMBER;
159 }
160 
161 static void npcm7xx_smbus_update_irq(NPCM7xxSMBusState *s)
162 {
163     int level;
164 
165     if (s->ctl1 & NPCM7XX_SMBCTL1_INTEN) {
166         level = !!((s->ctl1 & NPCM7XX_SMBCTL1_NMINTE &&
167                     s->st & NPCM7XX_SMBST_NMATCH) ||
168                    (s->st & NPCM7XX_SMBST_BER) ||
169                    (s->st & NPCM7XX_SMBST_NEGACK) ||
170                    (s->st & NPCM7XX_SMBST_SDAST) ||
171                    (s->ctl1 & NPCM7XX_SMBCTL1_STASTRE &&
172                     s->st & NPCM7XX_SMBST_SDAST) ||
173                    (s->ctl1 & NPCM7XX_SMBCTL1_EOBINTE &&
174                     s->cst3 & NPCM7XX_SMBCST3_EO_BUSY));
175 
176         if (level) {
177             s->cst2 |= NPCM7XX_SMBCST2_INTSTS;
178         } else {
179             s->cst2 &= ~NPCM7XX_SMBCST2_INTSTS;
180         }
181         qemu_set_irq(s->irq, level);
182     }
183 }
184 
185 static void npcm7xx_smbus_nack(NPCM7xxSMBusState *s)
186 {
187     s->st &= ~NPCM7XX_SMBST_SDAST;
188     s->st |= NPCM7XX_SMBST_NEGACK;
189     s->status = NPCM7XX_SMBUS_STATUS_NEGACK;
190 }
191 
192 static void npcm7xx_smbus_send_byte(NPCM7xxSMBusState *s, uint8_t value)
193 {
194     int rv = i2c_send(s->bus, value);
195 
196     if (rv) {
197         npcm7xx_smbus_nack(s);
198     } else {
199         s->st |= NPCM7XX_SMBST_SDAST;
200     }
201     trace_npcm7xx_smbus_send_byte((DEVICE(s)->canonical_path), value, !rv);
202     npcm7xx_smbus_update_irq(s);
203 }
204 
205 static void npcm7xx_smbus_recv_byte(NPCM7xxSMBusState *s)
206 {
207     s->sda = i2c_recv(s->bus);
208     s->st |= NPCM7XX_SMBST_SDAST;
209     if (s->st & NPCM7XX_SMBCTL1_ACK) {
210         trace_npcm7xx_smbus_nack(DEVICE(s)->canonical_path);
211         i2c_nack(s->bus);
212         s->st &= NPCM7XX_SMBCTL1_ACK;
213     }
214     trace_npcm7xx_smbus_recv_byte((DEVICE(s)->canonical_path), s->sda);
215     npcm7xx_smbus_update_irq(s);
216 }
217 
218 static void npcm7xx_smbus_start(NPCM7xxSMBusState *s)
219 {
220     /*
221      * We can start the bus if one of these is true:
222      * 1. The bus is idle (so we can request it)
223      * 2. We are the occupier (it's a repeated start condition.)
224      */
225     int available = !i2c_bus_busy(s->bus) ||
226                     s->status != NPCM7XX_SMBUS_STATUS_IDLE;
227 
228     if (available) {
229         s->st |= NPCM7XX_SMBST_MODE | NPCM7XX_SMBST_XMIT | NPCM7XX_SMBST_SDAST;
230         s->cst |= NPCM7XX_SMBCST_BUSY;
231     } else {
232         s->st &= ~NPCM7XX_SMBST_MODE;
233         s->cst &= ~NPCM7XX_SMBCST_BUSY;
234         s->st |= NPCM7XX_SMBST_BER;
235     }
236 
237     trace_npcm7xx_smbus_start(DEVICE(s)->canonical_path, available);
238     s->cst |= NPCM7XX_SMBCST_BB;
239     s->status = NPCM7XX_SMBUS_STATUS_IDLE;
240     npcm7xx_smbus_update_irq(s);
241 }
242 
243 static void npcm7xx_smbus_send_address(NPCM7xxSMBusState *s, uint8_t value)
244 {
245     int recv;
246     int rv;
247 
248     recv = value & BIT(0);
249     rv = i2c_start_transfer(s->bus, value >> 1, recv);
250     trace_npcm7xx_smbus_send_address(DEVICE(s)->canonical_path,
251                                      value >> 1, recv, !rv);
252     if (rv) {
253         qemu_log_mask(LOG_GUEST_ERROR,
254                       "%s: requesting i2c bus for 0x%02x failed: %d\n",
255                       DEVICE(s)->canonical_path, value, rv);
256         /* Failed to start transfer. NACK to reject.*/
257         if (recv) {
258             s->st &= ~NPCM7XX_SMBST_XMIT;
259         } else {
260             s->st |= NPCM7XX_SMBST_XMIT;
261         }
262         npcm7xx_smbus_nack(s);
263         npcm7xx_smbus_update_irq(s);
264         return;
265     }
266 
267     s->st &= ~NPCM7XX_SMBST_NEGACK;
268     if (recv) {
269         s->status = NPCM7XX_SMBUS_STATUS_RECEIVING;
270         s->st &= ~NPCM7XX_SMBST_XMIT;
271     } else {
272         s->status = NPCM7XX_SMBUS_STATUS_SENDING;
273         s->st |= NPCM7XX_SMBST_XMIT;
274     }
275 
276     if (s->ctl1 & NPCM7XX_SMBCTL1_STASTRE) {
277         s->st |= NPCM7XX_SMBST_STASTR;
278         if (!recv) {
279             s->st |= NPCM7XX_SMBST_SDAST;
280         }
281     } else if (recv) {
282         npcm7xx_smbus_recv_byte(s);
283     }
284     npcm7xx_smbus_update_irq(s);
285 }
286 
287 static void npcm7xx_smbus_execute_stop(NPCM7xxSMBusState *s)
288 {
289     i2c_end_transfer(s->bus);
290     s->st = 0;
291     s->cst = 0;
292     s->status = NPCM7XX_SMBUS_STATUS_IDLE;
293     s->cst3 |= NPCM7XX_SMBCST3_EO_BUSY;
294     trace_npcm7xx_smbus_stop(DEVICE(s)->canonical_path);
295     npcm7xx_smbus_update_irq(s);
296 }
297 
298 
299 static void npcm7xx_smbus_stop(NPCM7xxSMBusState *s)
300 {
301     if (s->st & NPCM7XX_SMBST_MODE) {
302         switch (s->status) {
303         case NPCM7XX_SMBUS_STATUS_RECEIVING:
304         case NPCM7XX_SMBUS_STATUS_STOPPING_LAST_RECEIVE:
305             s->status = NPCM7XX_SMBUS_STATUS_STOPPING_LAST_RECEIVE;
306             break;
307 
308         case NPCM7XX_SMBUS_STATUS_NEGACK:
309             s->status = NPCM7XX_SMBUS_STATUS_STOPPING_NEGACK;
310             break;
311 
312         default:
313             npcm7xx_smbus_execute_stop(s);
314             break;
315         }
316     }
317 }
318 
319 static uint8_t npcm7xx_smbus_read_sda(NPCM7xxSMBusState *s)
320 {
321     uint8_t value = s->sda;
322 
323     switch (s->status) {
324     case NPCM7XX_SMBUS_STATUS_STOPPING_LAST_RECEIVE:
325         npcm7xx_smbus_execute_stop(s);
326         break;
327 
328     case NPCM7XX_SMBUS_STATUS_RECEIVING:
329         npcm7xx_smbus_recv_byte(s);
330         break;
331 
332     default:
333         /* Do nothing */
334         break;
335     }
336 
337     return value;
338 }
339 
340 static void npcm7xx_smbus_write_sda(NPCM7xxSMBusState *s, uint8_t value)
341 {
342     s->sda = value;
343     if (s->st & NPCM7XX_SMBST_MODE) {
344         switch (s->status) {
345         case NPCM7XX_SMBUS_STATUS_IDLE:
346             npcm7xx_smbus_send_address(s, value);
347             break;
348         case NPCM7XX_SMBUS_STATUS_SENDING:
349             npcm7xx_smbus_send_byte(s, value);
350             break;
351         default:
352             qemu_log_mask(LOG_GUEST_ERROR,
353                           "%s: write to SDA in invalid status %d: %u\n",
354                           DEVICE(s)->canonical_path, s->status, value);
355             break;
356         }
357     }
358 }
359 
360 static void npcm7xx_smbus_write_st(NPCM7xxSMBusState *s, uint8_t value)
361 {
362     s->st = WRITE_ONE_CLEAR(s->st, value, NPCM7XX_SMBST_STP);
363     s->st = WRITE_ONE_CLEAR(s->st, value, NPCM7XX_SMBST_BER);
364     s->st = WRITE_ONE_CLEAR(s->st, value, NPCM7XX_SMBST_STASTR);
365     s->st = WRITE_ONE_CLEAR(s->st, value, NPCM7XX_SMBST_NMATCH);
366 
367     if (value & NPCM7XX_SMBST_NEGACK) {
368         s->st &= ~NPCM7XX_SMBST_NEGACK;
369         if (s->status == NPCM7XX_SMBUS_STATUS_STOPPING_NEGACK) {
370             npcm7xx_smbus_execute_stop(s);
371         }
372     }
373 
374     if (value & NPCM7XX_SMBST_STASTR &&
375             s->status == NPCM7XX_SMBUS_STATUS_RECEIVING) {
376         npcm7xx_smbus_recv_byte(s);
377     }
378 
379     npcm7xx_smbus_update_irq(s);
380 }
381 
382 static void npcm7xx_smbus_write_cst(NPCM7xxSMBusState *s, uint8_t value)
383 {
384     uint8_t new_value = s->cst;
385 
386     s->cst = WRITE_ONE_CLEAR(new_value, value, NPCM7XX_SMBCST_BB);
387     npcm7xx_smbus_update_irq(s);
388 }
389 
390 static void npcm7xx_smbus_write_cst3(NPCM7xxSMBusState *s, uint8_t value)
391 {
392     s->cst3 = WRITE_ONE_CLEAR(s->cst3, value, NPCM7XX_SMBCST3_EO_BUSY);
393     npcm7xx_smbus_update_irq(s);
394 }
395 
396 static void npcm7xx_smbus_write_ctl1(NPCM7xxSMBusState *s, uint8_t value)
397 {
398     s->ctl1 = KEEP_OLD_BIT(s->ctl1, value,
399             NPCM7XX_SMBCTL1_START | NPCM7XX_SMBCTL1_STOP | NPCM7XX_SMBCTL1_ACK);
400 
401     if (value & NPCM7XX_SMBCTL1_START) {
402         npcm7xx_smbus_start(s);
403     }
404 
405     if (value & NPCM7XX_SMBCTL1_STOP) {
406         npcm7xx_smbus_stop(s);
407     }
408 
409     npcm7xx_smbus_update_irq(s);
410 }
411 
412 static void npcm7xx_smbus_write_ctl2(NPCM7xxSMBusState *s, uint8_t value)
413 {
414     s->ctl2 = value;
415 
416     if (!NPCM7XX_SMBUS_ENABLED(s)) {
417         /* Disable this SMBus module. */
418         s->ctl1 = 0;
419         s->st = 0;
420         s->cst3 = s->cst3 & (~NPCM7XX_SMBCST3_EO_BUSY);
421         s->cst = 0;
422     }
423 }
424 
425 static void npcm7xx_smbus_write_ctl3(NPCM7xxSMBusState *s, uint8_t value)
426 {
427     uint8_t old_ctl3 = s->ctl3;
428 
429     /* Write to SDA and SCL bits are ignored. */
430     s->ctl3 =  KEEP_OLD_BIT(old_ctl3, value,
431                             NPCM7XX_SMBCTL3_SCL_LVL | NPCM7XX_SMBCTL3_SDA_LVL);
432 }
433 
434 static uint64_t npcm7xx_smbus_read(void *opaque, hwaddr offset, unsigned size)
435 {
436     NPCM7xxSMBusState *s = opaque;
437     uint64_t value = 0;
438     uint8_t bank = s->ctl3 & NPCM7XX_SMBCTL3_BNK_SEL;
439 
440     /* The order of the registers are their order in memory. */
441     switch (offset) {
442     case NPCM7XX_SMB_SDA:
443         value = npcm7xx_smbus_read_sda(s);
444         break;
445 
446     case NPCM7XX_SMB_ST:
447         value = s->st;
448         break;
449 
450     case NPCM7XX_SMB_CST:
451         value = s->cst;
452         break;
453 
454     case NPCM7XX_SMB_CTL1:
455         value = s->ctl1;
456         break;
457 
458     case NPCM7XX_SMB_ADDR1:
459         value = s->addr[0];
460         break;
461 
462     case NPCM7XX_SMB_CTL2:
463         value = s->ctl2;
464         break;
465 
466     case NPCM7XX_SMB_ADDR2:
467         value = s->addr[1];
468         break;
469 
470     case NPCM7XX_SMB_CTL3:
471         value = s->ctl3;
472         break;
473 
474     case NPCM7XX_SMB_CST2:
475         value = s->cst2;
476         break;
477 
478     case NPCM7XX_SMB_CST3:
479         value = s->cst3;
480         break;
481 
482     case NPCM7XX_SMB_VER:
483         value = npcm7xx_smbus_get_version();
484         break;
485 
486     /* This register is either invalid or banked at this point. */
487     default:
488         if (bank) {
489             /* Bank 1 */
490             qemu_log_mask(LOG_GUEST_ERROR,
491                     "%s: read from invalid offset 0x%" HWADDR_PRIx "\n",
492                     DEVICE(s)->canonical_path, offset);
493         } else {
494             /* Bank 0 */
495             switch (offset) {
496             case NPCM7XX_SMB_ADDR3:
497                 value = s->addr[2];
498                 break;
499 
500             case NPCM7XX_SMB_ADDR7:
501                 value = s->addr[6];
502                 break;
503 
504             case NPCM7XX_SMB_ADDR4:
505                 value = s->addr[3];
506                 break;
507 
508             case NPCM7XX_SMB_ADDR8:
509                 value = s->addr[7];
510                 break;
511 
512             case NPCM7XX_SMB_ADDR5:
513                 value = s->addr[4];
514                 break;
515 
516             case NPCM7XX_SMB_ADDR9:
517                 value = s->addr[8];
518                 break;
519 
520             case NPCM7XX_SMB_ADDR6:
521                 value = s->addr[5];
522                 break;
523 
524             case NPCM7XX_SMB_ADDR10:
525                 value = s->addr[9];
526                 break;
527 
528             case NPCM7XX_SMB_CTL4:
529                 value = s->ctl4;
530                 break;
531 
532             case NPCM7XX_SMB_CTL5:
533                 value = s->ctl5;
534                 break;
535 
536             case NPCM7XX_SMB_SCLLT:
537                 value = s->scllt;
538                 break;
539 
540             case NPCM7XX_SMB_SCLHT:
541                 value = s->sclht;
542                 break;
543 
544             default:
545                 qemu_log_mask(LOG_GUEST_ERROR,
546                         "%s: read from invalid offset 0x%" HWADDR_PRIx "\n",
547                         DEVICE(s)->canonical_path, offset);
548                 break;
549             }
550         }
551         break;
552     }
553 
554     trace_npcm7xx_smbus_read(DEVICE(s)->canonical_path, offset, value, size);
555 
556     return value;
557 }
558 
559 static void npcm7xx_smbus_write(void *opaque, hwaddr offset, uint64_t value,
560                               unsigned size)
561 {
562     NPCM7xxSMBusState *s = opaque;
563     uint8_t bank = s->ctl3 & NPCM7XX_SMBCTL3_BNK_SEL;
564 
565     trace_npcm7xx_smbus_write(DEVICE(s)->canonical_path, offset, value, size);
566 
567     /* The order of the registers are their order in memory. */
568     switch (offset) {
569     case NPCM7XX_SMB_SDA:
570         npcm7xx_smbus_write_sda(s, value);
571         break;
572 
573     case NPCM7XX_SMB_ST:
574         npcm7xx_smbus_write_st(s, value);
575         break;
576 
577     case NPCM7XX_SMB_CST:
578         npcm7xx_smbus_write_cst(s, value);
579         break;
580 
581     case NPCM7XX_SMB_CTL1:
582         npcm7xx_smbus_write_ctl1(s, value);
583         break;
584 
585     case NPCM7XX_SMB_ADDR1:
586         s->addr[0] = value;
587         break;
588 
589     case NPCM7XX_SMB_CTL2:
590         npcm7xx_smbus_write_ctl2(s, value);
591         break;
592 
593     case NPCM7XX_SMB_ADDR2:
594         s->addr[1] = value;
595         break;
596 
597     case NPCM7XX_SMB_CTL3:
598         npcm7xx_smbus_write_ctl3(s, value);
599         break;
600 
601     case NPCM7XX_SMB_CST2:
602         qemu_log_mask(LOG_GUEST_ERROR,
603                 "%s: write to read-only reg: offset 0x%" HWADDR_PRIx "\n",
604                 DEVICE(s)->canonical_path, offset);
605         break;
606 
607     case NPCM7XX_SMB_CST3:
608         npcm7xx_smbus_write_cst3(s, value);
609         break;
610 
611     case NPCM7XX_SMB_VER:
612         qemu_log_mask(LOG_GUEST_ERROR,
613                 "%s: write to read-only reg: offset 0x%" HWADDR_PRIx "\n",
614                 DEVICE(s)->canonical_path, offset);
615         break;
616 
617     /* This register is either invalid or banked at this point. */
618     default:
619         if (bank) {
620             /* Bank 1 */
621             qemu_log_mask(LOG_GUEST_ERROR,
622                     "%s: write to invalid offset 0x%" HWADDR_PRIx "\n",
623                     DEVICE(s)->canonical_path, offset);
624         } else {
625             /* Bank 0 */
626             switch (offset) {
627             case NPCM7XX_SMB_ADDR3:
628                 s->addr[2] = value;
629                 break;
630 
631             case NPCM7XX_SMB_ADDR7:
632                 s->addr[6] = value;
633                 break;
634 
635             case NPCM7XX_SMB_ADDR4:
636                 s->addr[3] = value;
637                 break;
638 
639             case NPCM7XX_SMB_ADDR8:
640                 s->addr[7] = value;
641                 break;
642 
643             case NPCM7XX_SMB_ADDR5:
644                 s->addr[4] = value;
645                 break;
646 
647             case NPCM7XX_SMB_ADDR9:
648                 s->addr[8] = value;
649                 break;
650 
651             case NPCM7XX_SMB_ADDR6:
652                 s->addr[5] = value;
653                 break;
654 
655             case NPCM7XX_SMB_ADDR10:
656                 s->addr[9] = value;
657                 break;
658 
659             case NPCM7XX_SMB_CTL4:
660                 s->ctl4 = value;
661                 break;
662 
663             case NPCM7XX_SMB_CTL5:
664                 s->ctl5 = value;
665                 break;
666 
667             case NPCM7XX_SMB_SCLLT:
668                 s->scllt = value;
669                 break;
670 
671             case NPCM7XX_SMB_SCLHT:
672                 s->sclht = value;
673                 break;
674 
675             default:
676                 qemu_log_mask(LOG_GUEST_ERROR,
677                         "%s: write to invalid offset 0x%" HWADDR_PRIx "\n",
678                         DEVICE(s)->canonical_path, offset);
679                 break;
680             }
681         }
682         break;
683     }
684 }
685 
686 static const MemoryRegionOps npcm7xx_smbus_ops = {
687     .read = npcm7xx_smbus_read,
688     .write = npcm7xx_smbus_write,
689     .endianness = DEVICE_LITTLE_ENDIAN,
690     .valid = {
691         .min_access_size = 1,
692         .max_access_size = 1,
693         .unaligned = false,
694     },
695 };
696 
697 static void npcm7xx_smbus_enter_reset(Object *obj, ResetType type)
698 {
699     NPCM7xxSMBusState *s = NPCM7XX_SMBUS(obj);
700 
701     s->st = NPCM7XX_SMB_ST_INIT_VAL;
702     s->cst = NPCM7XX_SMB_CST_INIT_VAL;
703     s->cst2 = NPCM7XX_SMB_CST2_INIT_VAL;
704     s->cst3 = NPCM7XX_SMB_CST3_INIT_VAL;
705     s->ctl1 = NPCM7XX_SMB_CTL1_INIT_VAL;
706     s->ctl2 = NPCM7XX_SMB_CTL2_INIT_VAL;
707     s->ctl3 = NPCM7XX_SMB_CTL3_INIT_VAL;
708     s->ctl4 = NPCM7XX_SMB_CTL4_INIT_VAL;
709     s->ctl5 = NPCM7XX_SMB_CTL5_INIT_VAL;
710 
711     for (int i = 0; i < NPCM7XX_SMBUS_NR_ADDRS; ++i) {
712         s->addr[i] = NPCM7XX_SMB_ADDR_INIT_VAL;
713     }
714     s->scllt = NPCM7XX_SMB_SCLLT_INIT_VAL;
715     s->sclht = NPCM7XX_SMB_SCLHT_INIT_VAL;
716 
717     s->status = NPCM7XX_SMBUS_STATUS_IDLE;
718 }
719 
720 static void npcm7xx_smbus_hold_reset(Object *obj)
721 {
722     NPCM7xxSMBusState *s = NPCM7XX_SMBUS(obj);
723 
724     qemu_irq_lower(s->irq);
725 }
726 
727 static void npcm7xx_smbus_init(Object *obj)
728 {
729     NPCM7xxSMBusState *s = NPCM7XX_SMBUS(obj);
730     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
731 
732     sysbus_init_irq(sbd, &s->irq);
733     memory_region_init_io(&s->iomem, obj, &npcm7xx_smbus_ops, s,
734                           "regs", 4 * KiB);
735     sysbus_init_mmio(sbd, &s->iomem);
736 
737     s->bus = i2c_init_bus(DEVICE(s), "i2c-bus");
738     s->status = NPCM7XX_SMBUS_STATUS_IDLE;
739 }
740 
741 static const VMStateDescription vmstate_npcm7xx_smbus = {
742     .name = "npcm7xx-smbus",
743     .version_id = 0,
744     .minimum_version_id = 0,
745     .fields = (VMStateField[]) {
746         VMSTATE_UINT8(sda, NPCM7xxSMBusState),
747         VMSTATE_UINT8(st, NPCM7xxSMBusState),
748         VMSTATE_UINT8(cst, NPCM7xxSMBusState),
749         VMSTATE_UINT8(cst2, NPCM7xxSMBusState),
750         VMSTATE_UINT8(cst3, NPCM7xxSMBusState),
751         VMSTATE_UINT8(ctl1, NPCM7xxSMBusState),
752         VMSTATE_UINT8(ctl2, NPCM7xxSMBusState),
753         VMSTATE_UINT8(ctl3, NPCM7xxSMBusState),
754         VMSTATE_UINT8(ctl4, NPCM7xxSMBusState),
755         VMSTATE_UINT8(ctl5, NPCM7xxSMBusState),
756         VMSTATE_UINT8_ARRAY(addr, NPCM7xxSMBusState, NPCM7XX_SMBUS_NR_ADDRS),
757         VMSTATE_UINT8(scllt, NPCM7xxSMBusState),
758         VMSTATE_UINT8(sclht, NPCM7xxSMBusState),
759         VMSTATE_END_OF_LIST(),
760     },
761 };
762 
763 static void npcm7xx_smbus_class_init(ObjectClass *klass, void *data)
764 {
765     ResettableClass *rc = RESETTABLE_CLASS(klass);
766     DeviceClass *dc = DEVICE_CLASS(klass);
767 
768     dc->desc = "NPCM7xx System Management Bus";
769     dc->vmsd = &vmstate_npcm7xx_smbus;
770     rc->phases.enter = npcm7xx_smbus_enter_reset;
771     rc->phases.hold = npcm7xx_smbus_hold_reset;
772 }
773 
774 static const TypeInfo npcm7xx_smbus_types[] = {
775     {
776         .name = TYPE_NPCM7XX_SMBUS,
777         .parent = TYPE_SYS_BUS_DEVICE,
778         .instance_size = sizeof(NPCM7xxSMBusState),
779         .class_init = npcm7xx_smbus_class_init,
780         .instance_init = npcm7xx_smbus_init,
781     },
782 };
783 DEFINE_TYPES(npcm7xx_smbus_types);
784