smbus.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /*
  2. * QEMU SMBus device emulation.
  3. *
  4. * Copyright (c) 2007 CodeSourcery.
  5. * Written by Paul Brook
  6. *
  7. * This code is licenced under the LGPL.
  8. */
  9. /* TODO: Implement PEC. */
  10. #include "hw.h"
  11. #include "i2c.h"
  12. #include "smbus.h"
  13. //#define DEBUG_SMBUS 1
  14. #ifdef DEBUG_SMBUS
  15. #define DPRINTF(fmt, args...) \
  16. do { printf("smbus(%02x): " fmt , dev->i2c.address, ##args); } while (0)
  17. #define BADF(fmt, args...) \
  18. do { fprintf(stderr, "smbus: error: " fmt , ##args); exit(1);} while (0)
  19. #else
  20. #define DPRINTF(fmt, args...) do {} while(0)
  21. #define BADF(fmt, args...) \
  22. do { fprintf(stderr, "smbus: error: " fmt , ##args);} while (0)
  23. #endif
  24. enum {
  25. SMBUS_IDLE,
  26. SMBUS_WRITE_DATA,
  27. SMBUS_RECV_BYTE,
  28. SMBUS_READ_DATA,
  29. SMBUS_DONE,
  30. SMBUS_CONFUSED = -1
  31. };
  32. static void smbus_do_quick_cmd(SMBusDevice *dev, int recv)
  33. {
  34. DPRINTF("Quick Command %d\n", recv);
  35. if (dev->quick_cmd)
  36. dev->quick_cmd(dev, recv);
  37. }
  38. static void smbus_do_write(SMBusDevice *dev)
  39. {
  40. if (dev->data_len == 0) {
  41. smbus_do_quick_cmd(dev, 0);
  42. } else if (dev->data_len == 1) {
  43. DPRINTF("Send Byte\n");
  44. if (dev->send_byte) {
  45. dev->send_byte(dev, dev->data_buf[0]);
  46. }
  47. } else {
  48. dev->command = dev->data_buf[0];
  49. DPRINTF("Command %d len %d\n", dev->command, dev->data_len - 1);
  50. if (dev->write_data) {
  51. dev->write_data(dev, dev->command, dev->data_buf + 1,
  52. dev->data_len - 1);
  53. }
  54. }
  55. }
  56. static void smbus_i2c_event(i2c_slave *s, enum i2c_event event)
  57. {
  58. SMBusDevice *dev = (SMBusDevice *)s;
  59. switch (event) {
  60. case I2C_START_SEND:
  61. switch (dev->mode) {
  62. case SMBUS_IDLE:
  63. DPRINTF("Incoming data\n");
  64. dev->mode = SMBUS_WRITE_DATA;
  65. break;
  66. default:
  67. BADF("Unexpected send start condition in state %d\n", dev->mode);
  68. dev->mode = SMBUS_CONFUSED;
  69. break;
  70. }
  71. break;
  72. case I2C_START_RECV:
  73. switch (dev->mode) {
  74. case SMBUS_IDLE:
  75. DPRINTF("Read mode\n");
  76. dev->mode = SMBUS_RECV_BYTE;
  77. break;
  78. case SMBUS_WRITE_DATA:
  79. if (dev->data_len == 0) {
  80. BADF("Read after write with no data\n");
  81. dev->mode = SMBUS_CONFUSED;
  82. } else {
  83. if (dev->data_len > 1) {
  84. smbus_do_write(dev);
  85. } else {
  86. dev->command = dev->data_buf[0];
  87. DPRINTF("%02x: Command %d\n", dev->i2c.address,
  88. dev->command);
  89. }
  90. DPRINTF("Read mode\n");
  91. dev->data_len = 0;
  92. dev->mode = SMBUS_READ_DATA;
  93. }
  94. break;
  95. default:
  96. BADF("Unexpected recv start condition in state %d\n", dev->mode);
  97. dev->mode = SMBUS_CONFUSED;
  98. break;
  99. }
  100. break;
  101. case I2C_FINISH:
  102. switch (dev->mode) {
  103. case SMBUS_WRITE_DATA:
  104. smbus_do_write(dev);
  105. break;
  106. case SMBUS_RECV_BYTE:
  107. smbus_do_quick_cmd(dev, 1);
  108. break;
  109. case SMBUS_READ_DATA:
  110. BADF("Unexpected stop during receive\n");
  111. break;
  112. default:
  113. /* Nothing to do. */
  114. break;
  115. }
  116. dev->mode = SMBUS_IDLE;
  117. dev->data_len = 0;
  118. break;
  119. case I2C_NACK:
  120. switch (dev->mode) {
  121. case SMBUS_DONE:
  122. /* Nothing to do. */
  123. break;
  124. case SMBUS_READ_DATA:
  125. dev->mode = SMBUS_DONE;
  126. break;
  127. default:
  128. BADF("Unexpected NACK in state %d\n", dev->mode);
  129. dev->mode = SMBUS_CONFUSED;
  130. break;
  131. }
  132. }
  133. }
  134. static int smbus_i2c_recv(i2c_slave *s)
  135. {
  136. SMBusDevice *dev = (SMBusDevice *)s;
  137. int ret;
  138. switch (dev->mode) {
  139. case SMBUS_RECV_BYTE:
  140. if (dev->receive_byte) {
  141. ret = dev->receive_byte(dev);
  142. } else {
  143. ret = 0;
  144. }
  145. DPRINTF("Receive Byte %02x\n", ret);
  146. dev->mode = SMBUS_DONE;
  147. break;
  148. case SMBUS_READ_DATA:
  149. if (dev->read_data) {
  150. ret = dev->read_data(dev, dev->command, dev->data_len);
  151. dev->data_len++;
  152. } else {
  153. ret = 0;
  154. }
  155. DPRINTF("Read data %02x\n", ret);
  156. break;
  157. default:
  158. BADF("Unexpected read in state %d\n", dev->mode);
  159. dev->mode = SMBUS_CONFUSED;
  160. ret = 0;
  161. break;
  162. }
  163. return ret;
  164. }
  165. static int smbus_i2c_send(i2c_slave *s, uint8_t data)
  166. {
  167. SMBusDevice *dev = (SMBusDevice *)s;
  168. switch (dev->mode) {
  169. case SMBUS_WRITE_DATA:
  170. DPRINTF("Write data %02x\n", data);
  171. dev->data_buf[dev->data_len++] = data;
  172. break;
  173. default:
  174. BADF("Unexpected write in state %d\n", dev->mode);
  175. break;
  176. }
  177. return 0;
  178. }
  179. SMBusDevice *smbus_device_init(i2c_bus *bus, int address, int size)
  180. {
  181. SMBusDevice *dev;
  182. if (size < sizeof(SMBusDevice))
  183. hw_error("SMBus struct too small");
  184. dev = (SMBusDevice *)i2c_slave_init(bus, address, size);
  185. dev->i2c.event = smbus_i2c_event;
  186. dev->i2c.recv = smbus_i2c_recv;
  187. dev->i2c.send = smbus_i2c_send;
  188. return dev;
  189. }
  190. /* Master device commands. */
  191. void smbus_quick_command(i2c_bus *bus, int addr, int read)
  192. {
  193. i2c_start_transfer(bus, addr, read);
  194. i2c_end_transfer(bus);
  195. }
  196. uint8_t smbus_receive_byte(i2c_bus *bus, int addr)
  197. {
  198. uint8_t data;
  199. i2c_start_transfer(bus, addr, 1);
  200. data = i2c_recv(bus);
  201. i2c_nack(bus);
  202. i2c_end_transfer(bus);
  203. return data;
  204. }
  205. void smbus_send_byte(i2c_bus *bus, int addr, uint8_t data)
  206. {
  207. i2c_start_transfer(bus, addr, 0);
  208. i2c_send(bus, data);
  209. i2c_end_transfer(bus);
  210. }
  211. uint8_t smbus_read_byte(i2c_bus *bus, int addr, uint8_t command)
  212. {
  213. uint8_t data;
  214. i2c_start_transfer(bus, addr, 0);
  215. i2c_send(bus, command);
  216. i2c_start_transfer(bus, addr, 1);
  217. data = i2c_recv(bus);
  218. i2c_nack(bus);
  219. i2c_end_transfer(bus);
  220. return data;
  221. }
  222. void smbus_write_byte(i2c_bus *bus, int addr, uint8_t command, uint8_t data)
  223. {
  224. i2c_start_transfer(bus, addr, 0);
  225. i2c_send(bus, command);
  226. i2c_send(bus, data);
  227. i2c_end_transfer(bus);
  228. }
  229. uint16_t smbus_read_word(i2c_bus *bus, int addr, uint8_t command)
  230. {
  231. uint16_t data;
  232. i2c_start_transfer(bus, addr, 0);
  233. i2c_send(bus, command);
  234. i2c_start_transfer(bus, addr, 1);
  235. data = i2c_recv(bus);
  236. data |= i2c_recv(bus) << 8;
  237. i2c_nack(bus);
  238. i2c_end_transfer(bus);
  239. return data;
  240. }
  241. void smbus_write_word(i2c_bus *bus, int addr, uint8_t command, uint16_t data)
  242. {
  243. i2c_start_transfer(bus, addr, 0);
  244. i2c_send(bus, command);
  245. i2c_send(bus, data & 0xff);
  246. i2c_send(bus, data >> 8);
  247. i2c_end_transfer(bus);
  248. }
  249. int smbus_read_block(i2c_bus *bus, int addr, uint8_t command, uint8_t *data)
  250. {
  251. int len;
  252. int i;
  253. i2c_start_transfer(bus, addr, 0);
  254. i2c_send(bus, command);
  255. i2c_start_transfer(bus, addr, 1);
  256. len = i2c_recv(bus);
  257. if (len > 32)
  258. len = 0;
  259. for (i = 0; i < len; i++)
  260. data[i] = i2c_recv(bus);
  261. i2c_nack(bus);
  262. i2c_end_transfer(bus);
  263. return len;
  264. }
  265. void smbus_write_block(i2c_bus *bus, int addr, uint8_t command, uint8_t *data,
  266. int len)
  267. {
  268. int i;
  269. if (len > 32)
  270. len = 32;
  271. i2c_start_transfer(bus, addr, 0);
  272. i2c_send(bus, command);
  273. i2c_send(bus, len);
  274. for (i = 0; i < len; i++)
  275. i2c_send(bus, data[i]);
  276. i2c_end_transfer(bus);
  277. }