smbus_slave.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /*
  2. * QEMU SMBus device emulation.
  3. *
  4. * This code is a helper for SMBus device emulation. It implements an
  5. * I2C device interface and runs the SMBus protocol from the device
  6. * point of view and maps those to simple calls to emulate.
  7. *
  8. * Copyright (c) 2007 CodeSourcery.
  9. * Written by Paul Brook
  10. *
  11. * This code is licensed under the LGPL.
  12. */
  13. /* TODO: Implement PEC. */
  14. #include "qemu/osdep.h"
  15. #include "hw/i2c/i2c.h"
  16. #include "hw/i2c/smbus_slave.h"
  17. #include "migration/vmstate.h"
  18. #include "qemu/module.h"
  19. //#define DEBUG_SMBUS 1
  20. #ifdef DEBUG_SMBUS
  21. #define DPRINTF(fmt, ...) \
  22. do { printf("smbus(%02x): " fmt , dev->i2c.address, ## __VA_ARGS__); } while (0)
  23. #define BADF(fmt, ...) \
  24. do { g_autofree char *qom_path = object_get_canonical_path(OBJECT(dev)); \
  25. fprintf(stderr, "%s: smbus: error: " fmt , qom_path, ## __VA_ARGS__); \
  26. exit(1); } while (0)
  27. #else
  28. #define DPRINTF(fmt, ...) do {} while(0)
  29. #define BADF(fmt, ...) \
  30. do { g_autofree char *qom_path = object_get_canonical_path(OBJECT(dev)); \
  31. fprintf(stderr, "%s: smbus: error: " fmt , qom_path, ## __VA_ARGS__); \
  32. } while (0)
  33. #endif
  34. enum {
  35. SMBUS_IDLE,
  36. SMBUS_WRITE_DATA,
  37. SMBUS_READ_DATA,
  38. SMBUS_DONE,
  39. SMBUS_CONFUSED = -1
  40. };
  41. static void smbus_do_quick_cmd(SMBusDevice *dev, int recv)
  42. {
  43. SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev);
  44. DPRINTF("Quick Command %d\n", recv);
  45. if (sc->quick_cmd) {
  46. sc->quick_cmd(dev, recv);
  47. }
  48. }
  49. static void smbus_do_write(SMBusDevice *dev)
  50. {
  51. SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev);
  52. DPRINTF("Command %d len %d\n", dev->data_buf[0], dev->data_len);
  53. if (sc->write_data) {
  54. sc->write_data(dev, dev->data_buf, dev->data_len);
  55. }
  56. }
  57. static int smbus_i2c_event(I2CSlave *s, enum i2c_event event)
  58. {
  59. SMBusDevice *dev = SMBUS_DEVICE(s);
  60. switch (event) {
  61. case I2C_START_SEND:
  62. switch (dev->mode) {
  63. case SMBUS_IDLE:
  64. DPRINTF("Incoming data\n");
  65. dev->mode = SMBUS_WRITE_DATA;
  66. break;
  67. default:
  68. BADF("Unexpected send start condition in state %d\n", dev->mode);
  69. dev->mode = SMBUS_CONFUSED;
  70. break;
  71. }
  72. break;
  73. case I2C_START_RECV:
  74. switch (dev->mode) {
  75. case SMBUS_IDLE:
  76. DPRINTF("Read mode\n");
  77. dev->mode = SMBUS_READ_DATA;
  78. break;
  79. case SMBUS_WRITE_DATA:
  80. if (dev->data_len == 0) {
  81. BADF("Read after write with no data\n");
  82. dev->mode = SMBUS_CONFUSED;
  83. } else {
  84. smbus_do_write(dev);
  85. DPRINTF("Read mode\n");
  86. dev->mode = SMBUS_READ_DATA;
  87. }
  88. break;
  89. default:
  90. BADF("Unexpected recv start condition in state %d\n", dev->mode);
  91. dev->mode = SMBUS_CONFUSED;
  92. break;
  93. }
  94. break;
  95. case I2C_FINISH:
  96. if (dev->data_len == 0) {
  97. if (dev->mode == SMBUS_WRITE_DATA || dev->mode == SMBUS_READ_DATA) {
  98. smbus_do_quick_cmd(dev, dev->mode == SMBUS_READ_DATA);
  99. }
  100. } else {
  101. switch (dev->mode) {
  102. case SMBUS_WRITE_DATA:
  103. smbus_do_write(dev);
  104. break;
  105. case SMBUS_READ_DATA:
  106. BADF("Unexpected stop during receive\n");
  107. break;
  108. default:
  109. /* Nothing to do. */
  110. break;
  111. }
  112. }
  113. dev->mode = SMBUS_IDLE;
  114. dev->data_len = 0;
  115. break;
  116. case I2C_NACK:
  117. switch (dev->mode) {
  118. case SMBUS_DONE:
  119. /* Nothing to do. */
  120. break;
  121. case SMBUS_READ_DATA:
  122. dev->mode = SMBUS_DONE;
  123. break;
  124. default:
  125. BADF("Unexpected NACK in state %d\n", dev->mode);
  126. dev->mode = SMBUS_CONFUSED;
  127. break;
  128. }
  129. break;
  130. default:
  131. return -1;
  132. }
  133. return 0;
  134. }
  135. static uint8_t smbus_i2c_recv(I2CSlave *s)
  136. {
  137. SMBusDevice *dev = SMBUS_DEVICE(s);
  138. SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev);
  139. uint8_t ret = 0xff;
  140. switch (dev->mode) {
  141. case SMBUS_READ_DATA:
  142. if (sc->receive_byte) {
  143. ret = sc->receive_byte(dev);
  144. }
  145. DPRINTF("Read data %02x\n", ret);
  146. break;
  147. default:
  148. BADF("Unexpected read in state %d\n", dev->mode);
  149. dev->mode = SMBUS_CONFUSED;
  150. break;
  151. }
  152. return ret;
  153. }
  154. static int smbus_i2c_send(I2CSlave *s, uint8_t data)
  155. {
  156. SMBusDevice *dev = SMBUS_DEVICE(s);
  157. switch (dev->mode) {
  158. case SMBUS_WRITE_DATA:
  159. DPRINTF("Write data %02x\n", data);
  160. if (dev->data_len >= sizeof(dev->data_buf)) {
  161. BADF("Too many bytes sent\n");
  162. } else {
  163. dev->data_buf[dev->data_len++] = data;
  164. }
  165. break;
  166. default:
  167. BADF("Unexpected write in state %d\n", dev->mode);
  168. break;
  169. }
  170. return 0;
  171. }
  172. static void smbus_device_class_init(ObjectClass *klass, void *data)
  173. {
  174. I2CSlaveClass *sc = I2C_SLAVE_CLASS(klass);
  175. sc->event = smbus_i2c_event;
  176. sc->recv = smbus_i2c_recv;
  177. sc->send = smbus_i2c_send;
  178. }
  179. bool smbus_vmstate_needed(SMBusDevice *dev)
  180. {
  181. return dev->mode != SMBUS_IDLE;
  182. }
  183. const VMStateDescription vmstate_smbus_device = {
  184. .name = TYPE_SMBUS_DEVICE,
  185. .version_id = 1,
  186. .minimum_version_id = 1,
  187. .fields = (const VMStateField[]) {
  188. VMSTATE_I2C_SLAVE(i2c, SMBusDevice),
  189. VMSTATE_INT32(mode, SMBusDevice),
  190. VMSTATE_INT32(data_len, SMBusDevice),
  191. VMSTATE_UINT8_ARRAY(data_buf, SMBusDevice, SMBUS_DATA_MAX_LEN),
  192. VMSTATE_END_OF_LIST()
  193. }
  194. };
  195. static const TypeInfo smbus_device_type_info = {
  196. .name = TYPE_SMBUS_DEVICE,
  197. .parent = TYPE_I2C_SLAVE,
  198. .instance_size = sizeof(SMBusDevice),
  199. .abstract = true,
  200. .class_size = sizeof(SMBusDeviceClass),
  201. .class_init = smbus_device_class_init,
  202. };
  203. static void smbus_device_register_types(void)
  204. {
  205. type_register_static(&smbus_device_type_info);
  206. }
  207. type_init(smbus_device_register_types)