ihs_i2c.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /*
  2. * (C) Copyright 2013
  3. * Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.de
  4. *
  5. * SPDX-License-Identifier: GPL-2.0+
  6. */
  7. #include <common.h>
  8. #include <i2c.h>
  9. #include <gdsys_fpga.h>
  10. DECLARE_GLOBAL_DATA_PTR;
  11. #ifdef CONFIG_SYS_I2C_IHS_DUAL
  12. #define I2C_SET_REG(fld, val) \
  13. do { \
  14. if (I2C_ADAP_HWNR & 0x10) \
  15. FPGA_SET_REG(I2C_ADAP_HWNR & 0xf, i2c1.fld, val); \
  16. else \
  17. FPGA_SET_REG(I2C_ADAP_HWNR, i2c0.fld, val); \
  18. } while (0)
  19. #else
  20. #define I2C_SET_REG(fld, val) \
  21. FPGA_SET_REG(I2C_ADAP_HWNR, i2c0.fld, val)
  22. #endif
  23. #ifdef CONFIG_SYS_I2C_IHS_DUAL
  24. #define I2C_GET_REG(fld, val) \
  25. do { \
  26. if (I2C_ADAP_HWNR & 0x10) \
  27. FPGA_GET_REG(I2C_ADAP_HWNR & 0xf, i2c1.fld, val); \
  28. else \
  29. FPGA_GET_REG(I2C_ADAP_HWNR, i2c0.fld, val); \
  30. } while (0)
  31. #else
  32. #define I2C_GET_REG(fld, val) \
  33. FPGA_GET_REG(I2C_ADAP_HWNR, i2c0.fld, val)
  34. #endif
  35. enum {
  36. I2CINT_ERROR_EV = 1 << 13,
  37. I2CINT_TRANSMIT_EV = 1 << 14,
  38. I2CINT_RECEIVE_EV = 1 << 15,
  39. };
  40. enum {
  41. I2CMB_WRITE = 1 << 10,
  42. I2CMB_2BYTE = 1 << 11,
  43. I2CMB_HOLD_BUS = 1 << 13,
  44. I2CMB_NATIVE = 2 << 14,
  45. };
  46. static int wait_for_int(bool read)
  47. {
  48. u16 val;
  49. unsigned int ctr = 0;
  50. I2C_GET_REG(interrupt_status, &val);
  51. while (!(val & (I2CINT_ERROR_EV
  52. | (read ? I2CINT_RECEIVE_EV : I2CINT_TRANSMIT_EV)))) {
  53. udelay(10);
  54. if (ctr++ > 5000) {
  55. return 1;
  56. }
  57. I2C_GET_REG(interrupt_status, &val);
  58. }
  59. return (val & I2CINT_ERROR_EV) ? 1 : 0;
  60. }
  61. static int ihs_i2c_transfer(uchar chip, uchar *buffer, int len, bool read,
  62. bool is_last)
  63. {
  64. u16 val;
  65. I2C_SET_REG(interrupt_status, I2CINT_ERROR_EV
  66. | I2CINT_RECEIVE_EV | I2CINT_TRANSMIT_EV);
  67. I2C_GET_REG(interrupt_status, &val);
  68. if (!read && len) {
  69. val = buffer[0];
  70. if (len > 1)
  71. val |= buffer[1] << 8;
  72. I2C_SET_REG(write_mailbox_ext, val);
  73. }
  74. I2C_SET_REG(write_mailbox,
  75. I2CMB_NATIVE
  76. | (read ? 0 : I2CMB_WRITE)
  77. | (chip << 1)
  78. | ((len > 1) ? I2CMB_2BYTE : 0)
  79. | (is_last ? 0 : I2CMB_HOLD_BUS));
  80. if (wait_for_int(read))
  81. return 1;
  82. if (read) {
  83. I2C_GET_REG(read_mailbox_ext, &val);
  84. buffer[0] = val & 0xff;
  85. if (len > 1)
  86. buffer[1] = val >> 8;
  87. }
  88. return 0;
  89. }
  90. static int ihs_i2c_address(uchar chip, uint addr, int alen, bool hold_bus)
  91. {
  92. int shift = (alen-1) * 8;
  93. while (alen) {
  94. int transfer = min(alen, 2);
  95. uchar buf[2];
  96. bool is_last = alen <= transfer;
  97. buf[0] = addr >> shift;
  98. if (alen > 1)
  99. buf[1] = addr >> (shift - 8);
  100. if (ihs_i2c_transfer(chip, buf, transfer, false,
  101. hold_bus ? false : is_last))
  102. return 1;
  103. shift -= 16;
  104. alen -= transfer;
  105. }
  106. return 0;
  107. }
  108. static int ihs_i2c_access(struct i2c_adapter *adap, uchar chip, uint addr,
  109. int alen, uchar *buffer, int len, bool read)
  110. {
  111. if (len <= 0)
  112. return 1;
  113. if (ihs_i2c_address(chip, addr, alen, len))
  114. return 1;
  115. while (len) {
  116. int transfer = min(len, 2);
  117. if (ihs_i2c_transfer(chip, buffer, transfer, read,
  118. len <= transfer))
  119. return 1;
  120. buffer += transfer;
  121. addr += transfer;
  122. len -= transfer;
  123. }
  124. return 0;
  125. }
  126. static void ihs_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr)
  127. {
  128. #ifdef CONFIG_SYS_I2C_INIT_BOARD
  129. /*
  130. * Call board specific i2c bus reset routine before accessing the
  131. * environment, which might be in a chip on that bus. For details
  132. * about this problem see doc/I2C_Edge_Conditions.
  133. */
  134. i2c_init_board();
  135. #endif
  136. }
  137. static int ihs_i2c_probe(struct i2c_adapter *adap, uchar chip)
  138. {
  139. uchar buffer[2];
  140. if (ihs_i2c_transfer(chip, buffer, 0, true, true))
  141. return 1;
  142. return 0;
  143. }
  144. static int ihs_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr,
  145. int alen, uchar *buffer, int len)
  146. {
  147. return ihs_i2c_access(adap, chip, addr, alen, buffer, len, true);
  148. }
  149. static int ihs_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr,
  150. int alen, uchar *buffer, int len)
  151. {
  152. return ihs_i2c_access(adap, chip, addr, alen, buffer, len, false);
  153. }
  154. static unsigned int ihs_i2c_set_bus_speed(struct i2c_adapter *adap,
  155. unsigned int speed)
  156. {
  157. if (speed != adap->speed)
  158. return 1;
  159. return speed;
  160. }
  161. /*
  162. * Register IHS i2c adapters
  163. */
  164. #ifdef CONFIG_SYS_I2C_IHS_CH0
  165. U_BOOT_I2C_ADAP_COMPLETE(ihs0, ihs_i2c_init, ihs_i2c_probe,
  166. ihs_i2c_read, ihs_i2c_write,
  167. ihs_i2c_set_bus_speed,
  168. CONFIG_SYS_I2C_IHS_SPEED_0,
  169. CONFIG_SYS_I2C_IHS_SLAVE_0, 0)
  170. #ifdef CONFIG_SYS_I2C_IHS_DUAL
  171. U_BOOT_I2C_ADAP_COMPLETE(ihs0_1, ihs_i2c_init, ihs_i2c_probe,
  172. ihs_i2c_read, ihs_i2c_write,
  173. ihs_i2c_set_bus_speed,
  174. CONFIG_SYS_I2C_IHS_SPEED_0_1,
  175. CONFIG_SYS_I2C_IHS_SLAVE_0_1, 16)
  176. #endif
  177. #endif
  178. #ifdef CONFIG_SYS_I2C_IHS_CH1
  179. U_BOOT_I2C_ADAP_COMPLETE(ihs1, ihs_i2c_init, ihs_i2c_probe,
  180. ihs_i2c_read, ihs_i2c_write,
  181. ihs_i2c_set_bus_speed,
  182. CONFIG_SYS_I2C_IHS_SPEED_1,
  183. CONFIG_SYS_I2C_IHS_SLAVE_1, 1)
  184. #ifdef CONFIG_SYS_I2C_IHS_DUAL
  185. U_BOOT_I2C_ADAP_COMPLETE(ihs1_1, ihs_i2c_init, ihs_i2c_probe,
  186. ihs_i2c_read, ihs_i2c_write,
  187. ihs_i2c_set_bus_speed,
  188. CONFIG_SYS_I2C_IHS_SPEED_1_1,
  189. CONFIG_SYS_I2C_IHS_SLAVE_1_1, 17)
  190. #endif
  191. #endif
  192. #ifdef CONFIG_SYS_I2C_IHS_CH2
  193. U_BOOT_I2C_ADAP_COMPLETE(ihs2, ihs_i2c_init, ihs_i2c_probe,
  194. ihs_i2c_read, ihs_i2c_write,
  195. ihs_i2c_set_bus_speed,
  196. CONFIG_SYS_I2C_IHS_SPEED_2,
  197. CONFIG_SYS_I2C_IHS_SLAVE_2, 2)
  198. #ifdef CONFIG_SYS_I2C_IHS_DUAL
  199. U_BOOT_I2C_ADAP_COMPLETE(ihs2_1, ihs_i2c_init, ihs_i2c_probe,
  200. ihs_i2c_read, ihs_i2c_write,
  201. ihs_i2c_set_bus_speed,
  202. CONFIG_SYS_I2C_IHS_SPEED_2_1,
  203. CONFIG_SYS_I2C_IHS_SLAVE_2_1, 18)
  204. #endif
  205. #endif
  206. #ifdef CONFIG_SYS_I2C_IHS_CH3
  207. U_BOOT_I2C_ADAP_COMPLETE(ihs3, ihs_i2c_init, ihs_i2c_probe,
  208. ihs_i2c_read, ihs_i2c_write,
  209. ihs_i2c_set_bus_speed,
  210. CONFIG_SYS_I2C_IHS_SPEED_3,
  211. CONFIG_SYS_I2C_IHS_SLAVE_3, 3)
  212. #ifdef CONFIG_SYS_I2C_IHS_DUAL
  213. U_BOOT_I2C_ADAP_COMPLETE(ihs3_1, ihs_i2c_init, ihs_i2c_probe,
  214. ihs_i2c_read, ihs_i2c_write,
  215. ihs_i2c_set_bus_speed,
  216. CONFIG_SYS_I2C_IHS_SPEED_3_1,
  217. CONFIG_SYS_I2C_IHS_SLAVE_3_1, 19)
  218. #endif
  219. #endif