i2c.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. /*
  2. * This file is part of FH8620 BSP for RT-Thread distribution.
  3. *
  4. * Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
  5. * All rights reserved
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License along
  18. * with this program; if not, write to the Free Software Foundation, Inc.,
  19. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  20. *
  21. * Visit http://www.fullhan.com to get contact with Fullhan.
  22. *
  23. * Change Logs:
  24. * Date Author Notes
  25. */
  26. #include <rtdevice.h>
  27. #include <rthw.h>
  28. #include "i2c.h"
  29. #include "inc/fh_driverlib.h"
  30. #include "board_info.h"
  31. //#define FH_I2C_DEBUG
  32. #ifdef FH_I2C_DEBUG
  33. #define PRINT_I2C_DBG(fmt, args...) \
  34. do \
  35. { \
  36. rt_kprintf("FH_I2C_DEBUG: "); \
  37. rt_kprintf(fmt, ## args); \
  38. } \
  39. while(0)
  40. #else
  41. #define PRINT_I2C_DBG(fmt, args...) do { } while (0)
  42. #endif
  43. static void fh_i2c_xfer_init(struct rt_i2c_bus_device *dev, struct rt_i2c_msg msgs[], rt_uint32_t num)
  44. {
  45. struct i2c_driver *i2c_drv = (struct i2c_driver *)dev->priv;
  46. struct fh_i2c_obj *i2c_obj = (struct fh_i2c_obj *)i2c_drv->priv;
  47. rt_uint32_t ic_con;
  48. /* if the slave address is ten bit address, ERROR*/
  49. if (msgs[i2c_drv->msg_write_idx].flags & I2C_M_TEN)
  50. {
  51. rt_kprintf("ERROR: %s, ten bit address is NOT supported\n", __func__);
  52. return;
  53. }
  54. /* Disable the adapter */
  55. I2C_WaitMasterIdle(i2c_obj);
  56. I2C_Enable(i2c_obj, RT_FALSE);
  57. /* set the slave (target) address */
  58. I2C_SetSlaveAddress(i2c_obj, msgs[i2c_drv->msg_write_idx].addr);
  59. /* Enable interrupts */
  60. I2C_SetInterruptMask(i2c_obj, DW_IC_INTR_DEFAULT_MASK);
  61. /* Enable the adapter */
  62. I2C_Enable(i2c_obj, RT_TRUE);
  63. }
  64. static rt_size_t fh_i2c_xfer(struct rt_i2c_bus_device *dev,
  65. struct rt_i2c_msg msgs[], rt_uint32_t num)
  66. {
  67. struct i2c_driver *i2c_drv = (struct i2c_driver *)dev->priv;
  68. struct fh_i2c_obj *i2c_obj = (struct fh_i2c_obj *)i2c_drv->priv;
  69. int ret;
  70. struct rt_i2c_msg *pmsg = RT_NULL;
  71. PRINT_I2C_DBG(">>>>>>>>>>>>>%s start\n", __func__);
  72. rt_completion_init(&i2c_drv->transfer_completion);
  73. ret = rt_mutex_take(i2c_drv->lock, RT_WAITING_FOREVER );
  74. i2c_drv->msgs = msgs;
  75. i2c_drv->msgs_num = num;
  76. i2c_drv->msg_read_idx = 0;
  77. i2c_drv->msg_write_idx = 0;
  78. i2c_drv->cmd_err = 0;
  79. i2c_drv->msg_err = 0;
  80. i2c_drv->status = STATUS_IDLE;
  81. i2c_obj->abort_source = 0;
  82. ret = I2C_WaitDeviceIdle(i2c_obj);
  83. if (ret < 0)
  84. {
  85. //I2C_SetDataCmd(i2c_obj, 0x200);
  86. //goto done;
  87. }
  88. fh_i2c_xfer_init(dev, msgs, num);
  89. ret = rt_completion_wait(&i2c_drv->transfer_completion, RT_TICK_PER_SECOND);
  90. PRINT_I2C_DBG("%s transfer finished\n", "rt_completion_wait");
  91. if(ret)
  92. {
  93. rt_kprintf("ERROR: %s, transfer timeout\n", __func__);
  94. I2C_SetDataCmd(i2c_obj, 0x200);
  95. I2C_Init(i2c_obj);
  96. ret = -RT_ETIMEOUT;
  97. goto done;
  98. }
  99. if (i2c_drv->msg_err)
  100. {
  101. rt_kprintf("i2c_priv->msg_err: %d\n", i2c_drv->msg_err);
  102. ret = i2c_drv->msg_err;
  103. goto done;
  104. }
  105. /* no error */
  106. if (!i2c_drv->cmd_err)
  107. {
  108. /* Disable the adapter */
  109. I2C_WaitMasterIdle(i2c_obj);
  110. I2C_Enable(i2c_obj, RT_FALSE);
  111. ret = num;
  112. goto done;
  113. }
  114. /* We have an error */
  115. if (i2c_drv->cmd_err == DW_IC_ERR_TX_ABRT)
  116. {
  117. rt_kprintf("ERROR: %s, i2c_priv>cmd_err == DW_IC_ERR_TX_ABRT\n", __func__);
  118. ret = I2C_HandleTxAbort(i2c_obj);
  119. goto done;
  120. }
  121. ret = 1;
  122. done:
  123. I2C_Enable(i2c_obj, RT_FALSE);
  124. rt_mutex_release(i2c_drv->lock);
  125. PRINT_I2C_DBG(">>>>>>>>>>>>>%s end\n", __func__);
  126. return ret;
  127. }
  128. /*
  129. * Initiate (and continue) low level master read/write transaction.
  130. * This function is only called from i2c_fh_isr, and pumping i2c_msg
  131. * messages into the tx buffer. Even if the size of i2c_msg data is
  132. * longer than the size of the tx buffer, it handles everything.
  133. */
  134. static void i2c_fh_xfer_msg(struct rt_i2c_bus_device *dev)
  135. {
  136. struct i2c_driver *i2c_drv = (struct i2c_driver *)dev->priv;
  137. struct fh_i2c_obj *i2c_obj = (struct fh_i2c_obj *)i2c_drv->priv;
  138. struct rt_i2c_msg *msgs = i2c_drv->msgs;
  139. rt_uint32_t intr_mask, cmd;
  140. int tx_limit, rx_limit;
  141. rt_uint32_t addr = msgs[i2c_drv->msg_write_idx].addr;
  142. rt_uint32_t buf_len = i2c_drv->tx_buf_len;
  143. rt_uint8_t *buf = i2c_drv->tx_buf;
  144. PRINT_I2C_DBG("%s start, msgs_num: %d, write_idx: %d\n", __func__, i2c_drv->msgs_num, i2c_drv->msg_write_idx);
  145. intr_mask = DW_IC_INTR_DEFAULT_MASK;
  146. for (; i2c_drv->msg_write_idx < i2c_drv->msgs_num; i2c_drv->msg_write_idx++)
  147. {
  148. /*
  149. * if target address has changed, we need to
  150. * reprogram the target address in the i2c
  151. * adapter when we are done with this transfer
  152. */
  153. if (msgs[i2c_drv->msg_write_idx].addr != addr) {
  154. rt_kprintf(
  155. "ERROR: %s, invalid target address\n", __func__);
  156. i2c_drv->msg_err = 1;
  157. break;
  158. }
  159. if (msgs[i2c_drv->msg_write_idx].len == 0) {
  160. rt_kprintf(
  161. "ERROR: %s, invalid message length\n", __func__);
  162. i2c_drv->msg_err = 1;
  163. break;
  164. }
  165. if (!(i2c_drv->status & STATUS_WRITE_IN_PROGRESS))
  166. {
  167. /* new i2c_msg */
  168. buf = msgs[i2c_drv->msg_write_idx].buf;
  169. buf_len = msgs[i2c_drv->msg_write_idx].len;
  170. PRINT_I2C_DBG("new msg: len: %d, buf: 0x%x\n", buf_len, buf[0]);
  171. }
  172. tx_limit = i2c_obj->config.tx_fifo_depth - I2C_GetTransmitFifoLevel(i2c_obj);
  173. rx_limit = i2c_obj->config.rx_fifo_depth - I2C_GetReceiveFifoLevel(i2c_obj);
  174. while (buf_len > 0 && tx_limit > 0 && rx_limit > 0)
  175. {
  176. if (msgs[i2c_drv->msg_write_idx].flags & RT_I2C_RD)
  177. {
  178. cmd = 0x100;
  179. rx_limit--;
  180. }
  181. else
  182. {
  183. cmd = *buf++;
  184. }
  185. tx_limit--; buf_len--;
  186. if(!buf_len)
  187. {
  188. //2015-11-8 ar0130 bug fixed
  189. while(I2C_GetTransmitFifoLevel(i2c_obj));
  190. cmd |= 0x200;
  191. }
  192. I2C_SetDataCmd(i2c_obj, cmd);
  193. }
  194. i2c_drv->tx_buf = buf;
  195. i2c_drv->tx_buf_len = buf_len;
  196. if (buf_len > 0)
  197. {
  198. /* more bytes to be written */
  199. i2c_drv->status |= STATUS_WRITE_IN_PROGRESS;
  200. break;
  201. }
  202. else
  203. {
  204. i2c_drv->status &= ~STATUS_WRITE_IN_PROGRESS;
  205. }
  206. }
  207. /*
  208. * If i2c_msg index search is completed, we don't need TX_EMPTY
  209. * interrupt any more.
  210. */
  211. if (i2c_drv->msg_write_idx == i2c_drv->msgs_num)
  212. intr_mask &= ~DW_IC_INTR_TX_EMPTY;
  213. if (i2c_drv->msg_err)
  214. {
  215. rt_kprintf("ERROR: %s, msg_err: %d\n", __func__, i2c_drv->msg_err);
  216. intr_mask = 0;
  217. }
  218. I2C_SetInterruptMask(i2c_obj, intr_mask);
  219. PRINT_I2C_DBG("%s end\n", __func__);
  220. }
  221. static void i2c_fh_read(struct rt_i2c_bus_device *dev)
  222. {
  223. struct i2c_driver *i2c_drv = (struct i2c_driver *)dev->priv;
  224. struct fh_i2c_obj *i2c_obj = (struct fh_i2c_obj *)i2c_drv->priv;
  225. struct rt_i2c_msg *msgs = i2c_drv->msgs;
  226. int rx_valid;
  227. PRINT_I2C_DBG("%s start, msgs_num: %d, read_idx: %d\n", __func__, i2c_drv->msgs_num, i2c_drv->msg_read_idx);
  228. for (; i2c_drv->msg_read_idx < i2c_drv->msgs_num; i2c_drv->msg_read_idx++)
  229. {
  230. rt_uint32_t len;
  231. rt_uint8_t *buf;
  232. if (!(msgs[i2c_drv->msg_read_idx].flags & RT_I2C_RD))
  233. continue;
  234. if (!(i2c_drv->status & STATUS_READ_IN_PROGRESS))
  235. {
  236. len = msgs[i2c_drv->msg_read_idx].len;
  237. buf = msgs[i2c_drv->msg_read_idx].buf;
  238. }
  239. else
  240. {
  241. PRINT_I2C_DBG("STATUS_READ_IN_PROGRESS\n");
  242. len = i2c_drv->rx_buf_len;
  243. buf = i2c_drv->rx_buf;
  244. }
  245. rx_valid = I2C_GetReceiveFifoLevel(i2c_obj);
  246. if(rx_valid == 0)
  247. {
  248. rt_kprintf("ERROR: %s, rx_valid == 0\n", __func__);
  249. }
  250. PRINT_I2C_DBG("%s, len=%d, rx_valid=%d\n", __func__, len, rx_valid);
  251. for (; len > 0 && rx_valid > 0; len--, rx_valid--)
  252. {
  253. *buf++ = I2C_GetData(i2c_obj);
  254. }
  255. PRINT_I2C_DBG("i2c_fh_read, len: %d, buf[0]: 0x%x\n", msgs[i2c_drv->msg_read_idx].len, msgs[i2c_drv->msg_read_idx].buf[0]);
  256. if (len > 0)
  257. {
  258. PRINT_I2C_DBG("len > 0\n");
  259. i2c_drv->status |= STATUS_READ_IN_PROGRESS;
  260. i2c_drv->rx_buf_len = len;
  261. i2c_drv->rx_buf = buf;
  262. return;
  263. }
  264. else
  265. i2c_drv->status &= ~STATUS_READ_IN_PROGRESS;
  266. }
  267. PRINT_I2C_DBG("%s end\n", __func__);
  268. }
  269. /*
  270. * Interrupt service routine. This gets called whenever an I2C interrupt
  271. * occurs.
  272. */
  273. static void fh_i2c_interrupt(int this_irq, void *dev_id)
  274. {
  275. struct i2c_driver *i2c_drv = dev_id;
  276. struct rt_i2c_bus_device *i2c_bus_dev = i2c_drv->i2c_bus_dev;
  277. struct fh_i2c_obj *i2c_obj = (struct fh_i2c_obj *)i2c_drv->priv;
  278. rt_uint32_t stat;
  279. stat = I2C_ClearAndGetInterrupts(i2c_obj);
  280. PRINT_I2C_DBG("status: 0x%x, mask: 0x%x\n", stat, I2C_GetInterruptMask(i2c_obj));
  281. if (stat & DW_IC_INTR_TX_ABRT)
  282. {
  283. PRINT_I2C_DBG("DW_IC_INTR_TX_ABRT\n");
  284. i2c_drv->cmd_err |= DW_IC_ERR_TX_ABRT;
  285. i2c_drv->status = STATUS_IDLE;
  286. /*
  287. * Anytime TX_ABRT is set, the contents of the tx/rx
  288. * buffers are flushed. Make sure to skip them.
  289. */
  290. I2C_SetInterruptMask(i2c_obj, 0);
  291. goto tx_aborted;
  292. }
  293. if (stat & DW_IC_INTR_RX_FULL)
  294. {
  295. i2c_fh_read(i2c_bus_dev);
  296. }
  297. if (stat & DW_IC_INTR_TX_EMPTY)
  298. {
  299. i2c_fh_xfer_msg(i2c_bus_dev);
  300. }
  301. /*
  302. * No need to modify or disable the interrupt mask here.
  303. * i2c_fh_xfer_msg() will take care of it according to
  304. * the current transmit status.
  305. */
  306. tx_aborted:
  307. if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || i2c_drv->msg_err)
  308. rt_completion_done(&i2c_drv->transfer_completion);
  309. }
  310. static const struct rt_i2c_bus_device_ops fh_i2c_ops =
  311. {
  312. .master_xfer = fh_i2c_xfer,
  313. };
  314. int fh_i2c_probe(void *priv_data)
  315. {
  316. int ret;
  317. struct i2c_driver *i2c_drv;
  318. struct rt_i2c_bus_device *i2c_bus_dev;
  319. struct fh_i2c_obj *i2c_obj = (struct fh_i2c_obj *)priv_data;
  320. char i2c_dev_name[5] = {0};
  321. PRINT_I2C_DBG("%s start\n", __func__);
  322. i2c_bus_dev = (struct rt_i2c_bus_device*)rt_malloc(sizeof(struct rt_i2c_bus_device));
  323. rt_memset(i2c_bus_dev, 0, sizeof(struct rt_i2c_bus_device));
  324. i2c_bus_dev->ops = &fh_i2c_ops;
  325. rt_sprintf(i2c_dev_name, "%s%d", "i2c", i2c_obj->id);
  326. ret = rt_i2c_bus_device_register(i2c_bus_dev, i2c_dev_name);
  327. if (ret != RT_EOK)
  328. {
  329. rt_kprintf("ERROR:rt_spi_bus_register failed, ret=%d\n", ret);
  330. return -RT_ENOMEM;
  331. }
  332. //priv struct init
  333. i2c_drv = (struct i2c_driver*)rt_malloc(sizeof(struct i2c_driver));
  334. rt_memset(i2c_drv, 0, sizeof(struct i2c_driver));
  335. i2c_drv->i2c_bus_dev = i2c_bus_dev;
  336. i2c_drv->priv = priv_data;
  337. i2c_bus_dev->priv = i2c_drv;
  338. i2c_drv->lock = rt_mutex_create("i2c_mux", RT_IPC_FLAG_FIFO);
  339. if(i2c_obj->id == 0){
  340. rt_hw_interrupt_install(i2c_obj->irq, fh_i2c_interrupt,
  341. (void *)i2c_drv, "i2c_0");
  342. }
  343. else if(i2c_obj->id == 1){
  344. rt_hw_interrupt_install(i2c_obj->irq, fh_i2c_interrupt,
  345. (void *)i2c_drv, "i2c_1");
  346. }
  347. rt_hw_interrupt_umask(i2c_obj->irq);
  348. //fixme: get from clk tree
  349. i2c_obj->input_clock = 15000;
  350. I2C_Init(i2c_obj);
  351. PRINT_I2C_DBG("%s end\n", __func__);
  352. return ret;
  353. }
  354. int fh_i2c_exit(void *priv_data)
  355. {
  356. return 0;
  357. }
  358. struct fh_board_ops i2c_driver_ops =
  359. {
  360. .probe = fh_i2c_probe,
  361. .exit = fh_i2c_exit,
  362. };
  363. void rt_hw_i2c_init(void)
  364. {
  365. int ret;
  366. PRINT_I2C_DBG("%s start\n", __func__);
  367. fh_board_driver_register("i2c", &i2c_driver_ops);
  368. PRINT_I2C_DBG("%s end\n", __func__);
  369. //fixme: never release?
  370. }
  371. static rt_err_t fh_i2c_read_reg(struct rt_i2c_bus_device *fh81_i2c,
  372. rt_uint16_t reg, rt_uint8_t *data) {
  373. struct rt_i2c_msg msg[2];
  374. rt_uint8_t send_buf[2];
  375. rt_uint8_t recv_buf[1] = {0};
  376. PRINT_I2C_DBG("%s start\n", __func__);
  377. // send_buf[0] = ((reg >> 8) & 0xff);
  378. send_buf[0] = (reg & 0xFF);
  379. msg[0].addr = 0x51;
  380. msg[0].flags = RT_I2C_WR;
  381. msg[0].len = 1;
  382. msg[0].buf = send_buf;
  383. msg[1].addr = 0x51;
  384. msg[1].flags = RT_I2C_RD;
  385. msg[1].len = 1;
  386. msg[1].buf = recv_buf;
  387. rt_i2c_transfer(fh81_i2c, msg, 2);
  388. *data = recv_buf[0];
  389. return RT_EOK;
  390. }
  391. static rt_err_t fh_i2c_write_reg(struct rt_i2c_bus_device *fh81_i2c,
  392. rt_uint16_t reg, rt_uint8_t data) {
  393. struct rt_i2c_msg msg;
  394. rt_uint8_t send_buf[3];
  395. PRINT_I2C_DBG("%s start\n", __func__);
  396. // send_buf[0] = ((reg >> 8) & 0xff);
  397. send_buf[1] = (reg & 0xFF);
  398. send_buf[2] = data;
  399. msg.addr = 0x51;
  400. msg.flags = RT_I2C_WR;
  401. msg.len = 2;
  402. msg.buf = send_buf;
  403. rt_i2c_transfer(fh81_i2c, &msg, 1);
  404. PRINT_I2C_DBG("%s end\n", __func__);
  405. return RT_EOK;
  406. }
  407. void i2c_test_sensor() {
  408. struct rt_i2c_bus_device *fh81_i2c;
  409. struct rt_i2c_msg msg[2];
  410. rt_uint8_t data[1] = { 0x00 };
  411. fh81_i2c = rt_i2c_bus_device_find("i2c1");
  412. fh_i2c_write_reg(fh81_i2c, 0x04, 0x02);
  413. fh_i2c_read_reg(fh81_i2c, 0x02, data);
  414. rt_kprintf("data read from 0x3038 is 0x%x\r\n", data[0]);
  415. PRINT_I2C_DBG("%s end\n", __func__);
  416. }
  417. #ifdef RT_USING_FINSH
  418. #include <finsh.h>
  419. FINSH_FUNCTION_EXPORT(i2c_test_sensor, sensor i2c test);
  420. #endif