2
0

npcm7xx_smbus.c 32 KB

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