i2c.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  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. if (ret != RT_EOK) {
  75. goto done;
  76. }
  77. i2c_drv->msgs = msgs;
  78. i2c_drv->msgs_num = num;
  79. i2c_drv->msg_read_idx = 0;
  80. i2c_drv->msg_write_idx = 0;
  81. i2c_drv->cmd_err = 0;
  82. i2c_drv->msg_err = 0;
  83. i2c_drv->status = STATUS_IDLE;
  84. i2c_obj->abort_source = 0;
  85. ret = I2C_WaitDeviceIdle(i2c_obj);
  86. if (ret < 0)
  87. {
  88. //I2C_SetDataCmd(i2c_obj, 0x200);
  89. //goto done;
  90. }
  91. fh_i2c_xfer_init(dev, msgs, num);
  92. ret = rt_completion_wait(&i2c_drv->transfer_completion, RT_TICK_PER_SECOND);
  93. PRINT_I2C_DBG("%s transfer finished\n", "rt_completion_wait");
  94. if(ret)
  95. {
  96. rt_kprintf("ERROR: %s, transfer timeout\n", __func__);
  97. I2C_SetDataCmd(i2c_obj, 0x200);
  98. I2C_Init(i2c_obj);
  99. ret = -RT_ETIMEOUT;
  100. goto done;
  101. }
  102. if (i2c_drv->msg_err)
  103. {
  104. rt_kprintf("i2c_priv->msg_err: %d\n", i2c_drv->msg_err);
  105. ret = i2c_drv->msg_err;
  106. goto done;
  107. }
  108. /* no error */
  109. if (!i2c_drv->cmd_err)
  110. {
  111. /* Disable the adapter */
  112. I2C_WaitMasterIdle(i2c_obj);
  113. I2C_Enable(i2c_obj, RT_FALSE);
  114. ret = num;
  115. goto done;
  116. }
  117. /* We have an error */
  118. if (i2c_drv->cmd_err == DW_IC_ERR_TX_ABRT)
  119. {
  120. rt_kprintf("ERROR: %s, i2c_priv>cmd_err == DW_IC_ERR_TX_ABRT\n", __func__);
  121. ret = I2C_HandleTxAbort(i2c_obj);
  122. goto done;
  123. }
  124. ret = 1;
  125. done:
  126. I2C_Enable(i2c_obj, RT_FALSE);
  127. rt_mutex_release(i2c_drv->lock);
  128. PRINT_I2C_DBG(">>>>>>>>>>>>>%s end\n", __func__);
  129. return ret;
  130. }
  131. /*
  132. * Initiate (and continue) low level master read/write transaction.
  133. * This function is only called from i2c_fh_isr, and pumping i2c_msg
  134. * messages into the tx buffer. Even if the size of i2c_msg data is
  135. * longer than the size of the tx buffer, it handles everything.
  136. */
  137. static void i2c_fh_xfer_msg(struct rt_i2c_bus_device *dev)
  138. {
  139. struct i2c_driver *i2c_drv = (struct i2c_driver *)dev->priv;
  140. struct fh_i2c_obj *i2c_obj = (struct fh_i2c_obj *)i2c_drv->priv;
  141. struct rt_i2c_msg *msgs = i2c_drv->msgs;
  142. rt_uint32_t intr_mask, cmd;
  143. int tx_limit, rx_limit;
  144. rt_uint32_t addr = msgs[i2c_drv->msg_write_idx].addr;
  145. rt_uint32_t buf_len = i2c_drv->tx_buf_len;
  146. rt_uint8_t *buf = i2c_drv->tx_buf;
  147. PRINT_I2C_DBG("%s start, msgs_num: %d, write_idx: %d\n", __func__, i2c_drv->msgs_num, i2c_drv->msg_write_idx);
  148. intr_mask = DW_IC_INTR_DEFAULT_MASK;
  149. for (; i2c_drv->msg_write_idx < i2c_drv->msgs_num; i2c_drv->msg_write_idx++)
  150. {
  151. /*
  152. * if target address has changed, we need to
  153. * reprogram the target address in the i2c
  154. * adapter when we are done with this transfer
  155. */
  156. if (msgs[i2c_drv->msg_write_idx].addr != addr) {
  157. rt_kprintf(
  158. "ERROR: %s, invalid target address\n", __func__);
  159. i2c_drv->msg_err = 1;
  160. break;
  161. }
  162. if (msgs[i2c_drv->msg_write_idx].len == 0) {
  163. rt_kprintf(
  164. "ERROR: %s, invalid message length\n", __func__);
  165. i2c_drv->msg_err = 1;
  166. break;
  167. }
  168. if (!(i2c_drv->status & STATUS_WRITE_IN_PROGRESS))
  169. {
  170. /* new i2c_msg */
  171. buf = msgs[i2c_drv->msg_write_idx].buf;
  172. buf_len = msgs[i2c_drv->msg_write_idx].len;
  173. PRINT_I2C_DBG("new msg: len: %d, buf: 0x%x\n", buf_len, buf[0]);
  174. }
  175. tx_limit = i2c_obj->config.tx_fifo_depth - I2C_GetTransmitFifoLevel(i2c_obj);
  176. rx_limit = i2c_obj->config.rx_fifo_depth - I2C_GetReceiveFifoLevel(i2c_obj);
  177. while (buf_len > 0 && tx_limit > 0 && rx_limit > 0)
  178. {
  179. if (msgs[i2c_drv->msg_write_idx].flags & RT_I2C_RD)
  180. {
  181. cmd = 0x100;
  182. rx_limit--;
  183. }
  184. else
  185. {
  186. cmd = *buf++;
  187. }
  188. tx_limit--; buf_len--;
  189. if(!buf_len)
  190. {
  191. //2015-11-8 ar0130 bug fixed
  192. while(I2C_GetTransmitFifoLevel(i2c_obj));
  193. cmd |= 0x200;
  194. }
  195. I2C_SetDataCmd(i2c_obj, cmd);
  196. }
  197. i2c_drv->tx_buf = buf;
  198. i2c_drv->tx_buf_len = buf_len;
  199. if (buf_len > 0)
  200. {
  201. /* more bytes to be written */
  202. i2c_drv->status |= STATUS_WRITE_IN_PROGRESS;
  203. break;
  204. }
  205. else
  206. {
  207. i2c_drv->status &= ~STATUS_WRITE_IN_PROGRESS;
  208. }
  209. }
  210. /*
  211. * If i2c_msg index search is completed, we don't need TX_EMPTY
  212. * interrupt any more.
  213. */
  214. if (i2c_drv->msg_write_idx == i2c_drv->msgs_num)
  215. intr_mask &= ~DW_IC_INTR_TX_EMPTY;
  216. if (i2c_drv->msg_err)
  217. {
  218. rt_kprintf("ERROR: %s, msg_err: %d\n", __func__, i2c_drv->msg_err);
  219. intr_mask = 0;
  220. }
  221. I2C_SetInterruptMask(i2c_obj, intr_mask);
  222. PRINT_I2C_DBG("%s end\n", __func__);
  223. }
  224. static void i2c_fh_read(struct rt_i2c_bus_device *dev)
  225. {
  226. struct i2c_driver *i2c_drv = (struct i2c_driver *)dev->priv;
  227. struct fh_i2c_obj *i2c_obj = (struct fh_i2c_obj *)i2c_drv->priv;
  228. struct rt_i2c_msg *msgs = i2c_drv->msgs;
  229. int rx_valid;
  230. PRINT_I2C_DBG("%s start, msgs_num: %d, read_idx: %d\n", __func__, i2c_drv->msgs_num, i2c_drv->msg_read_idx);
  231. for (; i2c_drv->msg_read_idx < i2c_drv->msgs_num; i2c_drv->msg_read_idx++)
  232. {
  233. rt_uint32_t len;
  234. rt_uint8_t *buf;
  235. if (!(msgs[i2c_drv->msg_read_idx].flags & RT_I2C_RD))
  236. continue;
  237. if (!(i2c_drv->status & STATUS_READ_IN_PROGRESS))
  238. {
  239. len = msgs[i2c_drv->msg_read_idx].len;
  240. buf = msgs[i2c_drv->msg_read_idx].buf;
  241. }
  242. else
  243. {
  244. PRINT_I2C_DBG("STATUS_READ_IN_PROGRESS\n");
  245. len = i2c_drv->rx_buf_len;
  246. buf = i2c_drv->rx_buf;
  247. }
  248. rx_valid = I2C_GetReceiveFifoLevel(i2c_obj);
  249. if(rx_valid == 0)
  250. {
  251. rt_kprintf("ERROR: %s, rx_valid == 0\n", __func__);
  252. }
  253. PRINT_I2C_DBG("%s, len=%d, rx_valid=%d\n", __func__, len, rx_valid);
  254. for (; len > 0 && rx_valid > 0; len--, rx_valid--)
  255. {
  256. *buf++ = I2C_GetData(i2c_obj);
  257. }
  258. 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]);
  259. if (len > 0)
  260. {
  261. PRINT_I2C_DBG("len > 0\n");
  262. i2c_drv->status |= STATUS_READ_IN_PROGRESS;
  263. i2c_drv->rx_buf_len = len;
  264. i2c_drv->rx_buf = buf;
  265. return;
  266. }
  267. else
  268. i2c_drv->status &= ~STATUS_READ_IN_PROGRESS;
  269. }
  270. PRINT_I2C_DBG("%s end\n", __func__);
  271. }
  272. /*
  273. * Interrupt service routine. This gets called whenever an I2C interrupt
  274. * occurs.
  275. */
  276. static void fh_i2c_interrupt(int this_irq, void *dev_id)
  277. {
  278. struct i2c_driver *i2c_drv = dev_id;
  279. struct rt_i2c_bus_device *i2c_bus_dev = i2c_drv->i2c_bus_dev;
  280. struct fh_i2c_obj *i2c_obj = (struct fh_i2c_obj *)i2c_drv->priv;
  281. rt_uint32_t stat;
  282. stat = I2C_ClearAndGetInterrupts(i2c_obj);
  283. PRINT_I2C_DBG("status: 0x%x, mask: 0x%x\n", stat, I2C_GetInterruptMask(i2c_obj));
  284. if (stat & DW_IC_INTR_TX_ABRT)
  285. {
  286. PRINT_I2C_DBG("DW_IC_INTR_TX_ABRT\n");
  287. i2c_drv->cmd_err |= DW_IC_ERR_TX_ABRT;
  288. i2c_drv->status = STATUS_IDLE;
  289. /*
  290. * Anytime TX_ABRT is set, the contents of the tx/rx
  291. * buffers are flushed. Make sure to skip them.
  292. */
  293. I2C_SetInterruptMask(i2c_obj, 0);
  294. goto tx_aborted;
  295. }
  296. if (stat & DW_IC_INTR_RX_FULL)
  297. {
  298. i2c_fh_read(i2c_bus_dev);
  299. }
  300. if (stat & DW_IC_INTR_TX_EMPTY)
  301. {
  302. i2c_fh_xfer_msg(i2c_bus_dev);
  303. }
  304. /*
  305. * No need to modify or disable the interrupt mask here.
  306. * i2c_fh_xfer_msg() will take care of it according to
  307. * the current transmit status.
  308. */
  309. tx_aborted:
  310. if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || i2c_drv->msg_err)
  311. rt_completion_done(&i2c_drv->transfer_completion);
  312. }
  313. static const struct rt_i2c_bus_device_ops fh_i2c_ops =
  314. {
  315. .master_xfer = fh_i2c_xfer,
  316. };
  317. int fh_i2c_probe(void *priv_data)
  318. {
  319. int ret;
  320. struct i2c_driver *i2c_drv;
  321. struct rt_i2c_bus_device *i2c_bus_dev;
  322. struct fh_i2c_obj *i2c_obj = (struct fh_i2c_obj *)priv_data;
  323. char i2c_dev_name[5] = {0};
  324. PRINT_I2C_DBG("%s start\n", __func__);
  325. i2c_bus_dev = (struct rt_i2c_bus_device*)rt_calloc(1, sizeof(struct rt_i2c_bus_device));
  326. if (RT_NULL == i2c_bus_dev)
  327. {
  328. return -RT_ENOMEM;
  329. }
  330. i2c_bus_dev->ops = &fh_i2c_ops;
  331. rt_sprintf(i2c_dev_name, "%s%d", "i2c", i2c_obj->id);
  332. ret = rt_i2c_bus_device_register(i2c_bus_dev, i2c_dev_name);
  333. if (ret != RT_EOK)
  334. {
  335. rt_kprintf("ERROR:rt_spi_bus_register failed, ret=%d\n", ret);
  336. return -RT_ENOMEM;
  337. }
  338. //priv struct init
  339. i2c_drv = (struct i2c_driver*)rt_calloc(1, sizeof(struct i2c_driver));
  340. if (RT_NULL == i2c_drv)
  341. {
  342. return -RT_ENOMEM;
  343. }
  344. i2c_drv->i2c_bus_dev = i2c_bus_dev;
  345. i2c_drv->priv = priv_data;
  346. i2c_bus_dev->priv = i2c_drv;
  347. i2c_drv->lock = rt_mutex_create("i2c_mux", RT_IPC_FLAG_FIFO);
  348. if(i2c_obj->id == 0){
  349. rt_hw_interrupt_install(i2c_obj->irq, fh_i2c_interrupt,
  350. (void *)i2c_drv, "i2c_0");
  351. }
  352. else if(i2c_obj->id == 1){
  353. rt_hw_interrupt_install(i2c_obj->irq, fh_i2c_interrupt,
  354. (void *)i2c_drv, "i2c_1");
  355. }
  356. rt_hw_interrupt_umask(i2c_obj->irq);
  357. //fixme: get from clk tree
  358. i2c_obj->input_clock = 15000;
  359. I2C_Init(i2c_obj);
  360. PRINT_I2C_DBG("%s end\n", __func__);
  361. return ret;
  362. }
  363. int fh_i2c_exit(void *priv_data)
  364. {
  365. return 0;
  366. }
  367. struct fh_board_ops i2c_driver_ops =
  368. {
  369. .probe = fh_i2c_probe,
  370. .exit = fh_i2c_exit,
  371. };
  372. void rt_hw_i2c_init(void)
  373. {
  374. int ret;
  375. PRINT_I2C_DBG("%s start\n", __func__);
  376. fh_board_driver_register("i2c", &i2c_driver_ops);
  377. PRINT_I2C_DBG("%s end\n", __func__);
  378. //fixme: never release?
  379. }
  380. static rt_err_t fh_i2c_read_reg(struct rt_i2c_bus_device *fh81_i2c,
  381. rt_uint16_t reg, rt_uint8_t *data) {
  382. struct rt_i2c_msg msg[2];
  383. rt_uint8_t send_buf[2];
  384. rt_uint8_t recv_buf[1] = {0};
  385. PRINT_I2C_DBG("%s start\n", __func__);
  386. // send_buf[0] = ((reg >> 8) & 0xff);
  387. send_buf[0] = (reg & 0xFF);
  388. msg[0].addr = 0x51;
  389. msg[0].flags = RT_I2C_WR;
  390. msg[0].len = 1;
  391. msg[0].buf = send_buf;
  392. msg[1].addr = 0x51;
  393. msg[1].flags = RT_I2C_RD;
  394. msg[1].len = 1;
  395. msg[1].buf = recv_buf;
  396. rt_i2c_transfer(fh81_i2c, msg, 2);
  397. *data = recv_buf[0];
  398. return RT_EOK;
  399. }
  400. static rt_err_t fh_i2c_write_reg(struct rt_i2c_bus_device *fh81_i2c,
  401. rt_uint16_t reg, rt_uint8_t data) {
  402. struct rt_i2c_msg msg;
  403. rt_uint8_t send_buf[3];
  404. PRINT_I2C_DBG("%s start\n", __func__);
  405. // send_buf[0] = ((reg >> 8) & 0xff);
  406. send_buf[1] = (reg & 0xFF);
  407. send_buf[2] = data;
  408. msg.addr = 0x51;
  409. msg.flags = RT_I2C_WR;
  410. msg.len = 2;
  411. msg.buf = send_buf;
  412. rt_i2c_transfer(fh81_i2c, &msg, 1);
  413. PRINT_I2C_DBG("%s end\n", __func__);
  414. return RT_EOK;
  415. }
  416. void i2c_test_sensor() {
  417. struct rt_i2c_bus_device *fh81_i2c;
  418. struct rt_i2c_msg msg[2];
  419. rt_uint8_t data[1] = { 0x00 };
  420. fh81_i2c = rt_i2c_bus_device_find("i2c1");
  421. fh_i2c_write_reg(fh81_i2c, 0x04, 0x02);
  422. fh_i2c_read_reg(fh81_i2c, 0x02, data);
  423. rt_kprintf("data read from 0x3038 is 0x%x\r\n", data[0]);
  424. PRINT_I2C_DBG("%s end\n", __func__);
  425. }
  426. #ifdef RT_USING_FINSH
  427. #include <finsh.h>
  428. FINSH_FUNCTION_EXPORT(i2c_test_sensor, sensor i2c test);
  429. #endif