drv_hw_i2c.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  1. /*
  2. * Copyright (c) 2006-2024, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2024-02-14 ShichengChu first version
  9. */
  10. #include "drv_hw_i2c.h"
  11. #include <rtdevice.h>
  12. #include <board.h>
  13. #include "drv_pinmux.h"
  14. #include "drv_ioremap.h"
  15. #define DBG_TAG "drv.i2c"
  16. #define DBG_LVL DBG_INFO
  17. #include <rtdbg.h>
  18. struct dw_iic_bus
  19. {
  20. struct rt_i2c_bus_device parent;
  21. dw_iic_regs_t *iic_base;
  22. rt_uint32_t irq;
  23. char *device_name;
  24. };
  25. static struct dw_iic_bus _i2c_obj[] =
  26. {
  27. #ifdef BSP_USING_I2C0
  28. {
  29. .iic_base = (dw_iic_regs_t *)I2C0_BASE,
  30. .device_name = "i2c0",
  31. .irq = I2C0_IRQ,
  32. },
  33. #endif /* BSP_USING_I2C0 */
  34. #ifdef BSP_USING_I2C1
  35. {
  36. .iic_base = (dw_iic_regs_t *)I2C1_BASE,
  37. .device_name = "i2c1",
  38. .irq = I2C1_IRQ,
  39. },
  40. #endif /* BSP_USING_I2C1 */
  41. #ifdef BSP_USING_I2C2
  42. {
  43. .iic_base = (dw_iic_regs_t *)I2C2_BASE,
  44. .device_name = "i2c2",
  45. .irq = I2C2_IRQ,
  46. },
  47. #endif /* BSP_USING_I2C2 */
  48. #ifdef BSP_USING_I2C3
  49. {
  50. .iic_base = (dw_iic_regs_t *)I2C3_BASE,
  51. .device_name = "i2c3",
  52. .irq = I2C3_IRQ,
  53. },
  54. #endif /* BSP_USING_I2C3 */
  55. #ifdef BSP_USING_I2C4
  56. {
  57. .iic_base = (dw_iic_regs_t *)I2C4_BASE,
  58. .device_name = "i2c4",
  59. .irq = I2C4_IRQ,
  60. },
  61. #endif /* BSP_USING_I2C4 */
  62. };
  63. static rt_uint32_t dw_iic_wait_for_bb(dw_iic_regs_t *iic_base)
  64. {
  65. uint16_t timeout = 0;
  66. while ((iic_base->IC_STATUS & DW_IIC_MST_ACTIVITY_STATE) || !(iic_base->IC_STATUS & DW_IIC_TXFIFO_EMPTY_STATE))
  67. {
  68. /* Evaluate timeout */
  69. rt_hw_us_delay(5);
  70. timeout ++;
  71. if (timeout > 200)
  72. {
  73. /* exceed 1 ms */
  74. LOG_E("Timed out waiting for bus busy");
  75. return 1;
  76. }
  77. }
  78. return 0;
  79. }
  80. void dw_iic_set_reg_address(dw_iic_regs_t *iic_base, rt_uint32_t addr, uint8_t addr_len)
  81. {
  82. while (addr_len)
  83. {
  84. addr_len --;
  85. /* high byte address going out first */
  86. dw_iic_transmit_data(iic_base, (addr >> (addr_len * 8)) & 0xff);
  87. }
  88. }
  89. static void dw_iic_set_target_address(dw_iic_regs_t *iic_base, rt_uint32_t address)
  90. {
  91. rt_uint32_t i2c_status;
  92. i2c_status = dw_iic_get_iic_status(iic_base);
  93. dw_iic_disable(iic_base);
  94. iic_base->IC_TAR = (iic_base->IC_TAR & ~0x3ff) | address; /* this register can be written only when the I2C is disabled*/
  95. if (i2c_status == DW_IIC_EN)
  96. {
  97. dw_iic_enable(iic_base);
  98. }
  99. }
  100. static int dw_iic_xfer_init(dw_iic_regs_t *iic_base, rt_uint32_t dev_addr)
  101. {
  102. if (dw_iic_wait_for_bb(iic_base))
  103. return -RT_ERROR;
  104. dw_iic_set_target_address(iic_base, dev_addr);
  105. dw_iic_enable(iic_base);
  106. return RT_EOK;
  107. }
  108. static int dw_iic_xfer_finish(dw_iic_regs_t *iic_base)
  109. {
  110. rt_uint32_t timeout = 0;
  111. while (1)
  112. {
  113. if (iic_base->IC_RAW_INTR_STAT & DW_IIC_RAW_STOP_DET)
  114. {
  115. iic_base->IC_CLR_STOP_DET;
  116. break;
  117. }
  118. else
  119. {
  120. timeout ++;
  121. rt_hw_us_delay(5);
  122. if (timeout > 10000)
  123. {
  124. LOG_E("xfer finish tiemout");
  125. break;
  126. }
  127. }
  128. }
  129. if (dw_iic_wait_for_bb(iic_base))
  130. {
  131. return -RT_ERROR;
  132. }
  133. dw_iic_flush_rxfifo(iic_base);
  134. return RT_EOK;
  135. }
  136. static void dw_iic_set_slave_mode(dw_iic_regs_t *iic_base)
  137. {
  138. rt_uint32_t i2c_status;
  139. i2c_status = dw_iic_get_iic_status(iic_base);
  140. dw_iic_disable(iic_base);
  141. rt_uint32_t val = DW_IIC_CON_MASTER_EN | DW_IIC_CON_SLAVE_EN;
  142. iic_base->IC_CON &= ~val; ///< set 0 to disabled master mode; set 0 to enabled slave mode
  143. if (i2c_status == DW_IIC_EN)
  144. {
  145. dw_iic_enable(iic_base);
  146. }
  147. }
  148. static void dw_iic_set_master_mode(dw_iic_regs_t *iic_base)
  149. {
  150. rt_uint32_t i2c_status;
  151. i2c_status = dw_iic_get_iic_status(iic_base);
  152. dw_iic_disable(iic_base);
  153. rt_uint32_t val = DW_IIC_CON_MASTER_EN | DW_IIC_CON_SLAVE_EN; ///< set 1 to enabled master mode; set 1 to disabled slave mode
  154. iic_base->IC_CON |= val;
  155. if (i2c_status == DW_IIC_EN)
  156. {
  157. dw_iic_enable(iic_base);
  158. }
  159. }
  160. static rt_err_t dw_iic_recv(dw_iic_regs_t *iic_base, rt_uint32_t devaddr, rt_uint8_t *data, rt_uint32_t size, rt_uint32_t timeout)
  161. {
  162. rt_err_t ret = RT_EOK;
  163. rt_uint32_t timecount = 0;
  164. RT_ASSERT(data != RT_NULL);
  165. if (dw_iic_xfer_init(iic_base, devaddr))
  166. {
  167. ret = -RT_EIO;
  168. goto ERR_EXIT;
  169. }
  170. timecount = timeout + rt_tick_get_millisecond();
  171. for (int i = 0 ; i < size; i ++)
  172. {
  173. if(i != (size - 1))
  174. {
  175. dw_iic_transmit_data(iic_base, DW_IIC_DATA_CMD);
  176. }
  177. else
  178. {
  179. dw_iic_transmit_data(iic_base, DW_IIC_DATA_CMD | DW_IIC_DATA_STOP);
  180. }
  181. }
  182. while (size > 0)
  183. {
  184. if (iic_base->IC_STATUS & DW_IIC_RXFIFO_NOT_EMPTY_STATE)
  185. {
  186. *data ++ = dw_iic_receive_data(iic_base);
  187. -- size;
  188. }
  189. else if (rt_tick_get_millisecond() >= timecount)
  190. {
  191. LOG_E("Timed out read ic_cmd_data");
  192. ret = -RT_ETIMEOUT;
  193. goto ERR_EXIT;
  194. }
  195. }
  196. if (dw_iic_xfer_finish(iic_base))
  197. {
  198. ret = -RT_EIO;
  199. goto ERR_EXIT;
  200. }
  201. ERR_EXIT:
  202. dw_iic_disable(iic_base);
  203. return ret;
  204. }
  205. static rt_err_t dw_iic_send(dw_iic_regs_t *iic_base, rt_uint32_t devaddr, const uint8_t *data, rt_uint32_t size, rt_uint32_t timeout)
  206. {
  207. rt_err_t ret = RT_EOK;
  208. rt_uint32_t timecount;
  209. RT_ASSERT(data != RT_NULL);
  210. if (dw_iic_xfer_init(iic_base, devaddr))
  211. {
  212. ret = -RT_EIO;
  213. goto ERR_EXIT;
  214. }
  215. timecount = timeout + rt_tick_get_millisecond();
  216. while (size > 0)
  217. {
  218. if (iic_base->IC_STATUS & DW_IIC_TXFIFO_NOT_FULL_STATE)
  219. {
  220. if (-- size == 0)
  221. {
  222. dw_iic_transmit_data(iic_base, *data ++ | DW_IIC_DATA_STOP);
  223. }
  224. else
  225. {
  226. dw_iic_transmit_data(iic_base, *data ++);
  227. }
  228. }
  229. else if (rt_tick_get_millisecond() >= timecount)
  230. {
  231. LOG_D("ic status is not TFNF\n");
  232. ret = -RT_ETIMEOUT;
  233. goto ERR_EXIT;
  234. }
  235. }
  236. LOG_D("dw_iic_xfer_finish");
  237. if (dw_iic_xfer_finish(iic_base))
  238. {
  239. ret = -RT_EIO;
  240. goto ERR_EXIT;
  241. }
  242. ERR_EXIT:
  243. dw_iic_disable(iic_base);
  244. return ret;
  245. }
  246. static rt_ssize_t dw_iic_master_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num)
  247. {
  248. struct rt_i2c_msg *msg;
  249. rt_uint32_t i;
  250. rt_ssize_t ret = -RT_ERROR;
  251. rt_uint32_t timeout;
  252. struct dw_iic_bus *i2c_bus = (struct dw_iic_bus *)bus;
  253. dw_iic_regs_t *iic_base = i2c_bus->iic_base;
  254. for (i = 0; i < num; i++)
  255. {
  256. msg = &msgs[i];
  257. if (msg->flags & RT_I2C_ADDR_10BIT)
  258. {
  259. dw_iic_set_master_10bit_addr_mode(iic_base);
  260. dw_iic_set_slave_10bit_addr_mode(iic_base);
  261. }
  262. else
  263. {
  264. dw_iic_set_master_7bit_addr_mode(iic_base);
  265. dw_iic_set_slave_7bit_addr_mode(iic_base);
  266. }
  267. if (msg->flags & RT_I2C_RD)
  268. {
  269. timeout = 1000;
  270. ret = dw_iic_recv(iic_base, msg->addr, msg->buf, msg->len, timeout);
  271. if (ret != RT_EOK)
  272. LOG_E("dw_iic_recv error: %d", ret);
  273. }
  274. else
  275. {
  276. timeout = 100;
  277. ret = dw_iic_send(iic_base, msg->addr, msg->buf, msg->len, timeout);
  278. if (ret != RT_EOK)
  279. LOG_E("dw_iic_send error: %d", ret);
  280. }
  281. }
  282. return ret == RT_EOK ? num : ret;
  283. }
  284. static void dw_iic_set_transfer_speed_high(dw_iic_regs_t *iic_base)
  285. {
  286. rt_uint32_t speed_config = iic_base->IC_CON;
  287. speed_config &= ~(DW_IIC_CON_SPEEDL_EN | DW_IIC_CON_SPEEDH_EN);
  288. speed_config |= DW_IIC_CON_SPEEDL_EN | DW_IIC_CON_SPEEDH_EN;
  289. iic_base->IC_CON = speed_config;
  290. }
  291. static void dw_iic_set_transfer_speed_fast(dw_iic_regs_t *iic_base)
  292. {
  293. rt_uint32_t speed_config = iic_base->IC_CON;
  294. speed_config &= ~(DW_IIC_CON_SPEEDL_EN | DW_IIC_CON_SPEEDH_EN);
  295. speed_config |= DW_IIC_CON_SPEEDH_EN;
  296. iic_base->IC_CON = speed_config;
  297. }
  298. static void dw_iic_set_transfer_speed_standard(dw_iic_regs_t *iic_base)
  299. {
  300. rt_uint32_t speed_config = iic_base->IC_CON;
  301. speed_config &= ~(DW_IIC_CON_SPEEDL_EN | DW_IIC_CON_SPEEDH_EN);
  302. speed_config |= DW_IIC_CON_SPEEDL_EN;
  303. iic_base->IC_CON = speed_config;
  304. }
  305. static rt_err_t dw_iic_bus_control(struct rt_i2c_bus_device *bus, int cmd, void *args)
  306. {
  307. struct dw_iic_bus *i2c_bus = (struct dw_iic_bus *)bus;
  308. RT_ASSERT(bus != RT_NULL);
  309. dw_iic_regs_t *iic_base = i2c_bus->iic_base;
  310. switch (cmd)
  311. {
  312. case RT_I2C_DEV_CTRL_CLK:
  313. {
  314. rt_uint32_t speed = *(rt_uint32_t *)args;
  315. if (speed == 100 * 1000)
  316. {
  317. dw_iic_set_transfer_speed_standard(iic_base);
  318. dw_iic_set_standard_scl_hcnt(iic_base, (((IC_CLK * 4000U) / 1000U) - 7U));
  319. dw_iic_set_standard_scl_lcnt(iic_base, (((IC_CLK * 4700) / 1000U) - 1U));
  320. }
  321. else if (speed == 400 * 1000)
  322. {
  323. dw_iic_set_transfer_speed_fast(iic_base);
  324. dw_iic_set_fast_scl_hcnt(iic_base, (((IC_CLK * 600U) / 1000U) - 7U));
  325. dw_iic_set_fast_scl_lcnt(iic_base, (((IC_CLK * 1300U) / 1000U) - 1U));
  326. }
  327. else if (speed == 4 * 1000 * 1000)
  328. {
  329. dw_iic_set_transfer_speed_high(iic_base);
  330. dw_iic_set_high_scl_hcnt(iic_base, 6U);
  331. dw_iic_set_high_scl_lcnt(iic_base, 8U);
  332. }
  333. else
  334. {
  335. return -RT_EIO;
  336. }
  337. }
  338. break;
  339. case RT_I2C_DEV_CTRL_10BIT:
  340. dw_iic_set_master_10bit_addr_mode(iic_base);
  341. dw_iic_set_slave_10bit_addr_mode(iic_base);
  342. break;
  343. default:
  344. return -RT_EIO;
  345. break;
  346. }
  347. return RT_EOK;
  348. }
  349. static const struct rt_i2c_bus_device_ops i2c_ops =
  350. {
  351. .master_xfer = dw_iic_master_xfer,
  352. .slave_xfer = RT_NULL,
  353. .i2c_bus_control = dw_iic_bus_control,
  354. };
  355. static void dw_iic_init(dw_iic_regs_t *iic_base)
  356. {
  357. dw_iic_disable(iic_base);
  358. dw_iic_clear_all_irq(iic_base);
  359. dw_iic_disable_all_irq(iic_base);
  360. iic_base->IC_SAR = 0;
  361. dw_iic_set_receive_fifo_threshold(iic_base, 0x1);
  362. dw_iic_set_transmit_fifo_threshold(iic_base, 0x0);
  363. dw_iic_set_sda_hold_time(iic_base, 0x1e);
  364. dw_iic_set_master_mode(iic_base);
  365. dw_iic_enable_restart(iic_base);
  366. dw_iic_set_transfer_speed_standard(iic_base);
  367. dw_iic_set_standard_scl_hcnt(iic_base, (((IC_CLK * 4000U) / 1000U) - 7U));
  368. dw_iic_set_standard_scl_lcnt(iic_base, (((IC_CLK * 4700) / 1000U) - 1U));
  369. }
  370. #if defined(BOARD_TYPE_MILKV_DUO)
  371. #ifdef BSP_USING_I2C0
  372. static const char *pinname_whitelist_i2c0_scl[] = {
  373. "IIC0_SCL",
  374. NULL,
  375. };
  376. static const char *pinname_whitelist_i2c0_sda[] = {
  377. "IIC0_SDA",
  378. NULL,
  379. };
  380. #endif
  381. #ifdef BSP_USING_I2C1
  382. static const char *pinname_whitelist_i2c1_scl[] = {
  383. "SD1_D2",
  384. "SD1_D3",
  385. "PAD_MIPIRX0N",
  386. NULL,
  387. };
  388. static const char *pinname_whitelist_i2c1_sda[] = {
  389. "SD1_D1",
  390. "SD1_D0",
  391. "PAD_MIPIRX1P",
  392. NULL,
  393. };
  394. #endif
  395. #ifdef BSP_USING_I2C2
  396. // I2C2 is not ALLOWED for Duo
  397. static const char *pinname_whitelist_i2c2_scl[] = {
  398. NULL,
  399. };
  400. static const char *pinname_whitelist_i2c2_sda[] = {
  401. NULL,
  402. };
  403. #endif
  404. #ifdef BSP_USING_I2C3
  405. static const char *pinname_whitelist_i2c3_scl[] = {
  406. "SD1_CMD",
  407. NULL,
  408. };
  409. static const char *pinname_whitelist_i2c3_sda[] = {
  410. "SD1_CLK",
  411. NULL,
  412. };
  413. #endif
  414. #ifdef BSP_USING_I2C4
  415. // I2C4 is not ALLOWED for Duo
  416. static const char *pinname_whitelist_i2c4_scl[] = {
  417. NULL,
  418. };
  419. static const char *pinname_whitelist_i2c4_sda[] = {
  420. NULL,
  421. };
  422. #endif
  423. #elif defined(BOARD_TYPE_MILKV_DUO256M)
  424. #ifdef BSP_USING_I2C0
  425. // I2C0 is not ALLOWED for Duo256
  426. static const char *pinname_whitelist_i2c0_scl[] = {
  427. NULL,
  428. };
  429. static const char *pinname_whitelist_i2c0_sda[] = {
  430. NULL,
  431. };
  432. #endif
  433. #ifdef BSP_USING_I2C1
  434. static const char *pinname_whitelist_i2c1_scl[] = {
  435. "SD1_D2",
  436. "SD1_D3",
  437. NULL,
  438. };
  439. static const char *pinname_whitelist_i2c1_sda[] = {
  440. "SD1_D1",
  441. "SD1_D0",
  442. NULL,
  443. };
  444. #endif
  445. #ifdef BSP_USING_I2C2
  446. static const char *pinname_whitelist_i2c2_scl[] = {
  447. "PAD_MIPI_TXP1",
  448. NULL,
  449. };
  450. static const char *pinname_whitelist_i2c2_sda[] = {
  451. "PAD_MIPI_TXM1",
  452. NULL,
  453. };
  454. #endif
  455. #ifdef BSP_USING_I2C3
  456. static const char *pinname_whitelist_i2c3_scl[] = {
  457. "SD1_CMD",
  458. NULL,
  459. };
  460. static const char *pinname_whitelist_i2c3_sda[] = {
  461. "SD1_CLK",
  462. NULL,
  463. };
  464. #endif
  465. #ifdef BSP_USING_I2C4
  466. // I2C4 is not ALLOWED for Duo256
  467. static const char *pinname_whitelist_i2c4_scl[] = {
  468. NULL,
  469. };
  470. static const char *pinname_whitelist_i2c4_sda[] = {
  471. NULL,
  472. };
  473. #endif
  474. #else
  475. #error "Unsupported board type!"
  476. #endif
  477. static void rt_hw_i2c_pinmux_config()
  478. {
  479. #ifdef BSP_USING_I2C0
  480. pinmux_config(BSP_I2C0_SCL_PINNAME, IIC0_SCL, pinname_whitelist_i2c0_scl);
  481. pinmux_config(BSP_I2C0_SDA_PINNAME, IIC0_SDA, pinname_whitelist_i2c0_sda);
  482. #endif /* BSP_USING_I2C0 */
  483. #ifdef BSP_USING_I2C1
  484. pinmux_config(BSP_I2C1_SCL_PINNAME, IIC1_SCL, pinname_whitelist_i2c1_scl);
  485. pinmux_config(BSP_I2C1_SDA_PINNAME, IIC1_SDA, pinname_whitelist_i2c1_sda);
  486. #endif /* BSP_USING_I2C1 */
  487. #ifdef BSP_USING_I2C2
  488. pinmux_config(BSP_I2C2_SCL_PINNAME, IIC2_SCL, pinname_whitelist_i2c2_scl);
  489. pinmux_config(BSP_I2C2_SDA_PINNAME, IIC2_SDA, pinname_whitelist_i2c2_sda);
  490. #endif /* BSP_USING_I2C2 */
  491. #ifdef BSP_USING_I2C3
  492. pinmux_config(BSP_I2C3_SCL_PINNAME, IIC3_SCL, pinname_whitelist_i2c3_scl);
  493. pinmux_config(BSP_I2C3_SDA_PINNAME, IIC3_SDA, pinname_whitelist_i2c3_sda);
  494. #endif /* BSP_USING_I2C3 */
  495. #ifdef BSP_USING_I2C4
  496. pinmux_config(BSP_I2C4_SCL_PINNAME, IIC4_SCL, pinname_whitelist_i2c4_scl);
  497. pinmux_config(BSP_I2C4_SDA_PINNAME, IIC4_SDA, pinname_whitelist_i2c4_sda);
  498. #endif /* BSP_USING_I2C4 */
  499. }
  500. int rt_hw_i2c_init(void)
  501. {
  502. int result = RT_EOK;
  503. rt_hw_i2c_pinmux_config();
  504. for (rt_size_t i = 0; i < sizeof(_i2c_obj) / sizeof(struct dw_iic_bus); i++)
  505. {
  506. _i2c_obj->iic_base = (rt_ubase_t)DRV_IOREMAP((void *)_i2c_obj->iic_basee, 0x10000);
  507. dw_iic_init(_i2c_obj->iic_base);
  508. _i2c_obj[i].parent.ops = &i2c_ops;
  509. /* register i2c device */
  510. if (rt_i2c_bus_device_register(&_i2c_obj[i].parent, _i2c_obj[i].device_name) == RT_EOK)
  511. {
  512. LOG_D("%s init success", _i2c_obj[i].device_name);
  513. }
  514. else
  515. {
  516. LOG_E("%s register failed", _i2c_obj[i].device_name);
  517. result = -RT_ERROR;
  518. }
  519. }
  520. return result;
  521. }
  522. INIT_DEVICE_EXPORT(rt_hw_i2c_init);