smbus_master.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /*
  2. * QEMU SMBus host (master) emulation.
  3. *
  4. * This code emulates SMBus transactions from the master point of view,
  5. * it runs the individual I2C transaction to do the SMBus protocol
  6. * over I2C.
  7. *
  8. * Copyright (c) 2007 CodeSourcery.
  9. * Written by Paul Brook
  10. *
  11. * This code is licensed under the LGPL.
  12. */
  13. #include "qemu/osdep.h"
  14. #include "hw/i2c/i2c.h"
  15. #include "hw/i2c/smbus_master.h"
  16. /* Master device commands. */
  17. int smbus_quick_command(I2CBus *bus, uint8_t addr, int read)
  18. {
  19. if (i2c_start_transfer(bus, addr, read)) {
  20. return -1;
  21. }
  22. i2c_end_transfer(bus);
  23. return 0;
  24. }
  25. int smbus_receive_byte(I2CBus *bus, uint8_t addr)
  26. {
  27. uint8_t data;
  28. if (i2c_start_transfer(bus, addr, 1)) {
  29. return -1;
  30. }
  31. data = i2c_recv(bus);
  32. i2c_nack(bus);
  33. i2c_end_transfer(bus);
  34. return data;
  35. }
  36. int smbus_send_byte(I2CBus *bus, uint8_t addr, uint8_t data)
  37. {
  38. if (i2c_start_transfer(bus, addr, 0)) {
  39. return -1;
  40. }
  41. i2c_send(bus, data);
  42. i2c_end_transfer(bus);
  43. return 0;
  44. }
  45. int smbus_read_byte(I2CBus *bus, uint8_t addr, uint8_t command)
  46. {
  47. uint8_t data;
  48. if (i2c_start_transfer(bus, addr, 0)) {
  49. return -1;
  50. }
  51. i2c_send(bus, command);
  52. if (i2c_start_transfer(bus, addr, 1)) {
  53. i2c_end_transfer(bus);
  54. return -1;
  55. }
  56. data = i2c_recv(bus);
  57. i2c_nack(bus);
  58. i2c_end_transfer(bus);
  59. return data;
  60. }
  61. int smbus_write_byte(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t data)
  62. {
  63. if (i2c_start_transfer(bus, addr, 0)) {
  64. return -1;
  65. }
  66. i2c_send(bus, command);
  67. i2c_send(bus, data);
  68. i2c_end_transfer(bus);
  69. return 0;
  70. }
  71. int smbus_read_word(I2CBus *bus, uint8_t addr, uint8_t command)
  72. {
  73. uint16_t data;
  74. if (i2c_start_transfer(bus, addr, 0)) {
  75. return -1;
  76. }
  77. i2c_send(bus, command);
  78. if (i2c_start_transfer(bus, addr, 1)) {
  79. i2c_end_transfer(bus);
  80. return -1;
  81. }
  82. data = i2c_recv(bus);
  83. data |= i2c_recv(bus) << 8;
  84. i2c_nack(bus);
  85. i2c_end_transfer(bus);
  86. return data;
  87. }
  88. int smbus_write_word(I2CBus *bus, uint8_t addr, uint8_t command, uint16_t data)
  89. {
  90. if (i2c_start_transfer(bus, addr, 0)) {
  91. return -1;
  92. }
  93. i2c_send(bus, command);
  94. i2c_send(bus, data & 0xff);
  95. i2c_send(bus, data >> 8);
  96. i2c_end_transfer(bus);
  97. return 0;
  98. }
  99. int smbus_read_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data,
  100. int len, bool recv_len, bool send_cmd)
  101. {
  102. int rlen;
  103. int i;
  104. if (send_cmd) {
  105. if (i2c_start_transfer(bus, addr, 0)) {
  106. return -1;
  107. }
  108. i2c_send(bus, command);
  109. }
  110. if (i2c_start_transfer(bus, addr, 1)) {
  111. if (send_cmd) {
  112. i2c_end_transfer(bus);
  113. }
  114. return -1;
  115. }
  116. if (recv_len) {
  117. rlen = i2c_recv(bus);
  118. } else {
  119. rlen = len;
  120. }
  121. if (rlen > len) {
  122. rlen = 0;
  123. }
  124. for (i = 0; i < rlen; i++) {
  125. data[i] = i2c_recv(bus);
  126. }
  127. i2c_nack(bus);
  128. i2c_end_transfer(bus);
  129. return rlen;
  130. }
  131. int smbus_write_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data,
  132. int len, bool send_len)
  133. {
  134. int i;
  135. if (len > 32) {
  136. len = 32;
  137. }
  138. if (i2c_start_transfer(bus, addr, 0)) {
  139. return -1;
  140. }
  141. i2c_send(bus, command);
  142. if (send_len) {
  143. i2c_send(bus, len);
  144. }
  145. for (i = 0; i < len; i++) {
  146. i2c_send(bus, data[i]);
  147. }
  148. i2c_end_transfer(bus);
  149. return 0;
  150. }