fci_i2c.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /*****************************************************************************
  2. Copyright(c) 2009 FCI Inc. All Rights Reserved
  3. File name : fci_i2c.c
  4. Description : fci i2c driver
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  16. History :
  17. ----------------------------------------------------------------------
  18. 2009/09/11 jason initial
  19. *******************************************************************************/
  20. #include <linux/input.h>
  21. #include "fci_types.h"
  22. #include "fci_oal.h"
  23. #include "fc8050_regs.h"
  24. #include "fci_hal.h"
  25. #ifdef CONFIG_TDMB_EBI
  26. #define FEATURE_FCI_I2C_CHECK_STATUS
  27. #endif
  28. #define I2CSTAT_TIP 0x02 /* Tip bit */
  29. #define I2CSTAT_NACK 0x80 /* Nack bit */
  30. #define I2C_TIMEOUT 1 /* 1 second */
  31. #define I2C_CR_STA 0x80
  32. #define I2C_CR_STO 0x40
  33. #define I2C_CR_RD 0x20
  34. #define I2C_CR_WR 0x10
  35. #define I2C_CR_NACK 0x08
  36. #define I2C_CR_IACK 0x01
  37. #define I2C_WRITE 0
  38. #define I2C_READ 1
  39. #define I2C_OK 0
  40. #define I2C_NOK 1
  41. #define I2C_NACK 2
  42. #define I2C_NOK_LA 3 /* Lost arbitration */
  43. #define I2C_NOK_TOUT 4 /* time out */
  44. static int wait_for_xfer(HANDLE hDevice)
  45. {
  46. int i;
  47. int res = I2C_OK;
  48. u8 status;
  49. i = I2C_TIMEOUT * 10000;
  50. /* wait for transfer complete */
  51. do {
  52. bbm_read(hDevice, BBM_I2C_SR, &status);
  53. i--;
  54. } while ((i > 0) && (status & I2CSTAT_TIP));
  55. /* check time out or nack */
  56. if (status & I2CSTAT_TIP)
  57. res = I2C_NOK_TOUT;
  58. #ifdef FEATURE_FCI_I2C_CHECK_STATUS
  59. else {
  60. bbm_read(hDevice, BBM_I2C_SR, &status);
  61. if (status & I2CSTAT_NACK)
  62. res = I2C_NACK;
  63. else
  64. res = I2C_OK;
  65. }
  66. #endif
  67. return res;
  68. }
  69. static int fci_i2c_transfer(
  70. HANDLE hDevice, u8 cmd_type, u8 chip
  71. , u8 addr[], u8 addr_len, u8 data[], u8 data_len)
  72. {
  73. int i;
  74. int result = I2C_OK;
  75. switch (cmd_type) {
  76. case I2C_WRITE:
  77. bbm_write(hDevice, BBM_I2C_TXR, chip | cmd_type);
  78. bbm_write(hDevice, BBM_I2C_CR, I2C_CR_STA | I2C_CR_WR);
  79. #ifdef FEATURE_FCI_I2C_CHECK_STATUS
  80. result = wait_for_xfer(hDevice);
  81. if (result != I2C_OK)
  82. return result;
  83. #endif
  84. if (addr && addr_len) {
  85. i = 0;
  86. while ((i < addr_len) && (result == I2C_OK)) {
  87. bbm_write(hDevice, BBM_I2C_TXR, addr[i]);
  88. bbm_write(hDevice, BBM_I2C_CR, I2C_CR_WR);
  89. #ifdef FEATURE_FCI_I2C_CHECK_STATUS
  90. result = wait_for_xfer(hDevice);
  91. if (result != I2C_OK)
  92. return result;
  93. #endif
  94. i++;
  95. }
  96. }
  97. i = 0;
  98. while ((i < data_len) && (result == I2C_OK)) {
  99. bbm_write(hDevice, BBM_I2C_TXR, data[i]);
  100. bbm_write(hDevice, BBM_I2C_CR, I2C_CR_WR);
  101. #ifdef FEATURE_FCI_I2C_CHECK_STATUS
  102. result = wait_for_xfer(hDevice);
  103. if (result != I2C_OK)
  104. return result;
  105. #endif
  106. i++;
  107. }
  108. bbm_write(hDevice, BBM_I2C_CR, I2C_CR_STO);
  109. #ifdef FEATURE_FCI_I2C_CHECK_STATUS
  110. result = wait_for_xfer(hDevice);
  111. if (result != I2C_OK)
  112. return result;
  113. #endif
  114. break;
  115. case I2C_READ:
  116. if (addr && addr_len) {
  117. bbm_write(hDevice, BBM_I2C_TXR, chip | I2C_WRITE);
  118. bbm_write(hDevice, BBM_I2C_CR, I2C_CR_STA | I2C_CR_WR);
  119. #ifdef FEATURE_FCI_I2C_CHECK_STATUS
  120. result = wait_for_xfer(hDevice);
  121. if (result != I2C_OK)
  122. return result;
  123. #endif
  124. i = 0;
  125. while ((i < addr_len) && (result == I2C_OK)) {
  126. bbm_write(hDevice, BBM_I2C_TXR, addr[i]);
  127. bbm_write(hDevice, BBM_I2C_CR, I2C_CR_WR);
  128. #ifdef FEATURE_FCI_I2C_CHECK_STATUS
  129. result = wait_for_xfer(hDevice);
  130. if (result != I2C_OK)
  131. return result;
  132. #endif
  133. i++;
  134. }
  135. }
  136. bbm_write(hDevice, BBM_I2C_TXR, chip | I2C_READ);
  137. bbm_write(hDevice, BBM_I2C_CR, I2C_CR_STA | I2C_CR_WR);
  138. #ifdef FEATURE_FCI_I2C_CHECK_STATUS
  139. result = wait_for_xfer(hDevice);
  140. if (result != I2C_OK)
  141. return result;
  142. #endif
  143. i = 0;
  144. while ((i < data_len) && (result == I2C_OK)) {
  145. if (i == data_len - 1) {
  146. bbm_write(hDevice, BBM_I2C_CR
  147. , I2C_CR_RD|I2C_CR_NACK);
  148. result = wait_for_xfer(hDevice);
  149. if ((result != I2C_NACK)
  150. && (result != I2C_OK)) {
  151. print_log(hDevice, "NACK4-0[%02x]\n"
  152. , result);
  153. return result;
  154. }
  155. } else {
  156. bbm_write(hDevice, BBM_I2C_CR, I2C_CR_RD);
  157. result = wait_for_xfer(hDevice);
  158. if (result != I2C_OK) {
  159. print_log(hDevice, "NACK4-1[%02x]\n"
  160. , result);
  161. return result;
  162. }
  163. }
  164. bbm_read(hDevice, BBM_I2C_RXR, &data[i]);
  165. i++;
  166. }
  167. bbm_write(hDevice, BBM_I2C_CR, I2C_CR_STO);
  168. #ifdef FEATURE_FCI_I2C_CHECK_STATUS
  169. result = wait_for_xfer(hDevice);
  170. if ((result != I2C_NACK) && (result != I2C_OK)) {
  171. print_log(hDevice, "NACK5[%02X]\n", result);
  172. return result;
  173. }
  174. #endif
  175. break;
  176. default:
  177. return I2C_NOK;
  178. }
  179. return I2C_OK;
  180. }
  181. int fci_i2c_init(HANDLE hDevice, int speed, int slaveaddr)
  182. {
  183. u16 pr, rpr = 0;
  184. pr = (u16)((4800 / speed) - 1);
  185. /* pr=400; */
  186. bbm_word_write(hDevice, BBM_I2C_PR, pr);
  187. bbm_word_read(hDevice, BBM_I2C_PR, &rpr);
  188. if (pr != rpr)
  189. return BBM_NOK;
  190. /* i2c master core enable & interrupt enable */
  191. bbm_write(hDevice, BBM_I2C_CTR, 0xC0);
  192. return BBM_OK;
  193. }
  194. int fci_i2c_read(
  195. HANDLE hDevice, u8 chip, u8 addr, u8 address_len, u8 *data, u8 len)
  196. {
  197. int ret;
  198. u8 tmp[4] = {0xcc, 0xcc, 0xcc, 0xcc};
  199. ret = fci_i2c_transfer(hDevice, I2C_READ, chip << 1
  200. , &addr, address_len, &tmp[0], len);
  201. if (ret != I2C_OK) {
  202. print_log(hDevice
  203. , "fci_i2c_read() result=%d, addr = %x, data=%x\n"
  204. , ret, addr, *data);
  205. return ret;
  206. }
  207. /* *data = tmp[0]; */
  208. memcpy(data, tmp, len);
  209. return ret;
  210. }
  211. int fci_i2c_write(
  212. HANDLE hDevice, u8 chip, u8 addr, u8 address_len, u8 *data, u8 len)
  213. {
  214. int ret;
  215. u8 *paddr = &addr;
  216. ret = fci_i2c_transfer(hDevice, I2C_WRITE, chip << 1
  217. , paddr, address_len, data, len);
  218. if (ret != I2C_OK)
  219. print_log(hDevice
  220. , "fci_i2c_write() result=%d, addr= %x, data=%x\n"
  221. , ret, addr, *data);
  222. return ret;
  223. }