bitbang_i2c.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. /*
  2. * Bit-Bang i2c emulation extracted from
  3. * Marvell MV88W8618 / Freecom MusicPal emulation.
  4. *
  5. * Copyright (c) 2008 Jan Kiszka
  6. *
  7. * This code is licensed under the GNU GPL v2.
  8. */
  9. #include "hw.h"
  10. #include "bitbang_i2c.h"
  11. #include "sysbus.h"
  12. //#define DEBUG_BITBANG_I2C
  13. #ifdef DEBUG_BITBANG_I2C
  14. #define DPRINTF(fmt, ...) \
  15. do { printf("bitbang_i2c: " fmt , ## __VA_ARGS__); } while (0)
  16. #else
  17. #define DPRINTF(fmt, ...) do {} while(0)
  18. #endif
  19. typedef enum bitbang_i2c_state {
  20. STOPPED = 0,
  21. SENDING_BIT7,
  22. SENDING_BIT6,
  23. SENDING_BIT5,
  24. SENDING_BIT4,
  25. SENDING_BIT3,
  26. SENDING_BIT2,
  27. SENDING_BIT1,
  28. SENDING_BIT0,
  29. WAITING_FOR_ACK,
  30. RECEIVING_BIT7,
  31. RECEIVING_BIT6,
  32. RECEIVING_BIT5,
  33. RECEIVING_BIT4,
  34. RECEIVING_BIT3,
  35. RECEIVING_BIT2,
  36. RECEIVING_BIT1,
  37. RECEIVING_BIT0,
  38. SENDING_ACK,
  39. SENT_NACK
  40. } bitbang_i2c_state;
  41. struct bitbang_i2c_interface {
  42. i2c_bus *bus;
  43. bitbang_i2c_state state;
  44. int last_data;
  45. int last_clock;
  46. int device_out;
  47. uint8_t buffer;
  48. int current_addr;
  49. };
  50. static void bitbang_i2c_enter_stop(bitbang_i2c_interface *i2c)
  51. {
  52. DPRINTF("STOP\n");
  53. if (i2c->current_addr >= 0)
  54. i2c_end_transfer(i2c->bus);
  55. i2c->current_addr = -1;
  56. i2c->state = STOPPED;
  57. }
  58. /* Set device data pin. */
  59. static int bitbang_i2c_ret(bitbang_i2c_interface *i2c, int level)
  60. {
  61. i2c->device_out = level;
  62. //DPRINTF("%d %d %d\n", i2c->last_clock, i2c->last_data, i2c->device_out);
  63. return level & i2c->last_data;
  64. }
  65. /* Leave device data pin unodified. */
  66. static int bitbang_i2c_nop(bitbang_i2c_interface *i2c)
  67. {
  68. return bitbang_i2c_ret(i2c, i2c->device_out);
  69. }
  70. /* Returns data line level. */
  71. int bitbang_i2c_set(bitbang_i2c_interface *i2c, int line, int level)
  72. {
  73. int data;
  74. if (level != 0 && level != 1) {
  75. abort();
  76. }
  77. if (line == BITBANG_I2C_SDA) {
  78. if (level == i2c->last_data) {
  79. return bitbang_i2c_nop(i2c);
  80. }
  81. i2c->last_data = level;
  82. if (i2c->last_clock == 0) {
  83. return bitbang_i2c_nop(i2c);
  84. }
  85. if (level == 0) {
  86. DPRINTF("START\n");
  87. /* START condition. */
  88. i2c->state = SENDING_BIT7;
  89. i2c->current_addr = -1;
  90. } else {
  91. /* STOP condition. */
  92. bitbang_i2c_enter_stop(i2c);
  93. }
  94. return bitbang_i2c_ret(i2c, 1);
  95. }
  96. data = i2c->last_data;
  97. if (i2c->last_clock == level) {
  98. return bitbang_i2c_nop(i2c);
  99. }
  100. i2c->last_clock = level;
  101. if (level == 0) {
  102. /* State is set/read at the start of the clock pulse.
  103. release the data line at the end. */
  104. return bitbang_i2c_ret(i2c, 1);
  105. }
  106. switch (i2c->state) {
  107. case STOPPED:
  108. case SENT_NACK:
  109. return bitbang_i2c_ret(i2c, 1);
  110. case SENDING_BIT7 ... SENDING_BIT0:
  111. i2c->buffer = (i2c->buffer << 1) | data;
  112. /* will end up in WAITING_FOR_ACK */
  113. i2c->state++;
  114. return bitbang_i2c_ret(i2c, 1);
  115. case WAITING_FOR_ACK:
  116. if (i2c->current_addr < 0) {
  117. i2c->current_addr = i2c->buffer;
  118. DPRINTF("Address 0x%02x\n", i2c->current_addr);
  119. i2c_start_transfer(i2c->bus, i2c->current_addr >> 1,
  120. i2c->current_addr & 1);
  121. } else {
  122. DPRINTF("Sent 0x%02x\n", i2c->buffer);
  123. i2c_send(i2c->bus, i2c->buffer);
  124. }
  125. if (i2c->current_addr & 1) {
  126. i2c->state = RECEIVING_BIT7;
  127. } else {
  128. i2c->state = SENDING_BIT7;
  129. }
  130. return bitbang_i2c_ret(i2c, 0);
  131. case RECEIVING_BIT7:
  132. i2c->buffer = i2c_recv(i2c->bus);
  133. DPRINTF("RX byte 0x%02x\n", i2c->buffer);
  134. /* Fall through... */
  135. case RECEIVING_BIT6 ... RECEIVING_BIT0:
  136. data = i2c->buffer >> 7;
  137. /* will end up in SENDING_ACK */
  138. i2c->state++;
  139. i2c->buffer <<= 1;
  140. return bitbang_i2c_ret(i2c, data);
  141. case SENDING_ACK:
  142. i2c->state = RECEIVING_BIT7;
  143. if (data != 0) {
  144. DPRINTF("NACKED\n");
  145. i2c->state = SENT_NACK;
  146. i2c_nack(i2c->bus);
  147. } else {
  148. DPRINTF("ACKED\n");
  149. }
  150. return bitbang_i2c_ret(i2c, 1);
  151. }
  152. abort();
  153. }
  154. bitbang_i2c_interface *bitbang_i2c_init(i2c_bus *bus)
  155. {
  156. bitbang_i2c_interface *s;
  157. s = g_malloc0(sizeof(bitbang_i2c_interface));
  158. s->bus = bus;
  159. s->last_data = 1;
  160. s->last_clock = 1;
  161. s->device_out = 1;
  162. return s;
  163. }
  164. /* GPIO interface. */
  165. typedef struct {
  166. SysBusDevice busdev;
  167. bitbang_i2c_interface *bitbang;
  168. int last_level;
  169. qemu_irq out;
  170. } GPIOI2CState;
  171. static void bitbang_i2c_gpio_set(void *opaque, int irq, int level)
  172. {
  173. GPIOI2CState *s = opaque;
  174. level = bitbang_i2c_set(s->bitbang, irq, level);
  175. if (level != s->last_level) {
  176. s->last_level = level;
  177. qemu_set_irq(s->out, level);
  178. }
  179. }
  180. static int gpio_i2c_init(SysBusDevice *dev)
  181. {
  182. GPIOI2CState *s = FROM_SYSBUS(GPIOI2CState, dev);
  183. i2c_bus *bus;
  184. sysbus_init_mmio(dev, 0x0, 0);
  185. bus = i2c_init_bus(&dev->qdev, "i2c");
  186. s->bitbang = bitbang_i2c_init(bus);
  187. qdev_init_gpio_in(&dev->qdev, bitbang_i2c_gpio_set, 2);
  188. qdev_init_gpio_out(&dev->qdev, &s->out, 1);
  189. return 0;
  190. }
  191. static SysBusDeviceInfo gpio_i2c_info = {
  192. .init = gpio_i2c_init,
  193. .qdev.name = "gpio_i2c",
  194. .qdev.desc = "Virtual GPIO to I2C bridge",
  195. .qdev.size = sizeof(GPIOI2CState),
  196. };
  197. static void bitbang_i2c_register(void)
  198. {
  199. sysbus_register_withprop(&gpio_i2c_info);
  200. }
  201. device_init(bitbang_i2c_register)