drv_i2c.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. /*
  2. * File : drv_i2c.c
  3. * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team
  4. *
  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. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program; if not, write to the Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18. *
  19. * Change Logs:
  20. * Date Author Notes
  21. * 2017-08-08 Yang the first version
  22. * 2018-03-24 LaiYiKeTang add hardware iic
  23. */
  24. #include <rtthread.h>
  25. #include <rtdevice.h>
  26. #include "board.h"
  27. #include "fsl_gpio.h"
  28. #include "fsl_lpi2c.h"
  29. #include "drv_i2c.h"
  30. //#define DRV_I2C_DEBUG
  31. #ifdef RT_USING_I2C
  32. #define I2C1BUS_NAME "i2c1"
  33. #define I2C2BUS_NAME "i2c2"
  34. #define I2C3BUS_NAME "i2c3"
  35. #define I2C4BUS_NAME "i2c4"
  36. #define LPI2C_CLOCK_SOURCE_DIVIDER 4
  37. /* Get frequency of lpi2c clock */
  38. #define LPI2C_CLOCK_FREQUENCY ((CLOCK_GetFreq(kCLOCK_Usb1PllClk) / 8) / (LPI2C_CLOCK_SOURCE_DIVIDER))
  39. #ifdef RT_USING_HW_I2C1
  40. static struct rt1052_i2c_bus lpi2c1 =
  41. {
  42. .I2C = LPI2C1,
  43. .device_name = I2C1BUS_NAME,
  44. };
  45. #endif /* RT_USING_HW_I2C1 */
  46. #ifdef RT_USING_HW_I2C2
  47. static struct rt1052_i2c_bus lpi2c2 =
  48. {
  49. .I2C = LPI2C2,
  50. .device_name = I2C2BUS_NAME,
  51. };
  52. #endif /* RT_USING_HW_I2C2 */
  53. #ifdef RT_USING_HW_I2C3
  54. static struct rt1052_i2c_bus lpi2c3 =
  55. {
  56. .I2C = LPI2C3,
  57. .device_name = I2C3BUS_NAME,
  58. };
  59. #endif /* RT_USING_HW_I2C3 */
  60. #ifdef RT_USING_HW_I2C4
  61. static struct rt1052_i2c_bus lpi2c4 =
  62. {
  63. .I2C = LPI2C4,
  64. .device_name = I2C4BUS_NAME,
  65. };
  66. #endif /* RT_USING_HW_I2C4 */
  67. #if (defined(RT_USING_HW_I2C1) || defined(RT_USING_HW_I2C2) || defined(RT_USING_HW_I2C3) || defined(RT_USING_HW_I2C4))
  68. static rt_size_t imxrt_i2c_mst_xfer(struct rt_i2c_bus_device *bus,
  69. struct rt_i2c_msg msgs[],
  70. rt_uint32_t num);
  71. static rt_size_t imxrt_i2c_slv_xfer(struct rt_i2c_bus_device *bus,
  72. struct rt_i2c_msg msgs[],
  73. rt_uint32_t num);
  74. static rt_err_t imxrt_i2c_bus_control(struct rt_i2c_bus_device *bus,
  75. rt_uint32_t,
  76. rt_uint32_t);
  77. static const struct rt_i2c_bus_device_ops imxrt_i2c_ops =
  78. {
  79. imxrt_i2c_mst_xfer,
  80. imxrt_i2c_slv_xfer,
  81. imxrt_i2c_bus_control,
  82. };
  83. void imxrt_lpi2c_gpio_init(struct rt1052_i2c_bus *bus)
  84. {
  85. if (bus->I2C == LPI2C1)
  86. {
  87. IOMUXC_SetPinMux(
  88. IOMUXC_GPIO_AD_B1_00_LPI2C1_SCL,
  89. 1U);
  90. IOMUXC_SetPinMux(
  91. IOMUXC_GPIO_AD_B1_01_LPI2C1_SDA,
  92. 1U);
  93. IOMUXC_SetPinConfig(
  94. IOMUXC_GPIO_AD_B1_00_LPI2C1_SCL,
  95. 0xD8B0u);
  96. IOMUXC_SetPinConfig(
  97. IOMUXC_GPIO_AD_B1_01_LPI2C1_SDA,
  98. 0xD8B0u);
  99. }
  100. else if (bus->I2C == LPI2C2)
  101. {
  102. IOMUXC_SetPinMux(
  103. IOMUXC_GPIO_B0_04_LPI2C2_SCL,
  104. 1U);
  105. IOMUXC_SetPinMux(
  106. IOMUXC_GPIO_B0_05_LPI2C2_SDA,
  107. 1U);
  108. IOMUXC_SetPinConfig(
  109. IOMUXC_GPIO_B0_04_LPI2C2_SCL,
  110. 0xD8B0u);
  111. IOMUXC_SetPinConfig(
  112. IOMUXC_GPIO_B0_05_LPI2C2_SDA,
  113. 0xD8B0u);
  114. }
  115. else if (bus->I2C == LPI2C3)
  116. {
  117. IOMUXC_SetPinMux(
  118. IOMUXC_GPIO_AD_B1_07_LPI2C3_SCL,
  119. 1U);
  120. IOMUXC_SetPinMux(
  121. IOMUXC_GPIO_AD_B1_06_LPI2C3_SDA,
  122. 1U);
  123. IOMUXC_SetPinConfig(
  124. IOMUXC_GPIO_AD_B1_07_LPI2C3_SCL,
  125. 0xD8B0u);
  126. IOMUXC_SetPinConfig(
  127. IOMUXC_GPIO_AD_B1_06_LPI2C3_SDA,
  128. 0xD8B0u);
  129. }
  130. else if (bus->I2C == LPI2C4)
  131. {
  132. IOMUXC_SetPinMux(
  133. IOMUXC_GPIO_EMC_12_LPI2C4_SCL,
  134. 1U);
  135. IOMUXC_SetPinMux(
  136. IOMUXC_GPIO_EMC_11_LPI2C4_SDA,
  137. 1U);
  138. IOMUXC_SetPinConfig(
  139. IOMUXC_GPIO_EMC_12_LPI2C4_SCL,
  140. 0xD8B0u);
  141. IOMUXC_SetPinConfig(
  142. IOMUXC_GPIO_EMC_11_LPI2C4_SDA,
  143. 0xD8B0u);
  144. }
  145. else
  146. {
  147. RT_ASSERT(RT_NULL);
  148. }
  149. }
  150. static rt_err_t imxrt_lpi2c_configure(struct rt1052_i2c_bus *bus, lpi2c_master_config_t *cfg)
  151. {
  152. RT_ASSERT(bus != RT_NULL);
  153. RT_ASSERT(cfg != RT_NULL);
  154. imxrt_lpi2c_gpio_init(bus);
  155. bus->parent.ops = &imxrt_i2c_ops;
  156. LPI2C_MasterInit(bus->I2C, cfg, LPI2C_CLOCK_FREQUENCY);
  157. return RT_EOK;
  158. }
  159. status_t LPI2C_MasterCheck(LPI2C_Type *base, uint32_t status)
  160. {
  161. status_t result = kStatus_Success;
  162. /* Check for error. These errors cause a stop to automatically be sent. We must */
  163. /* clear the errors before a new transfer can start. */
  164. status &= 0x3c00;
  165. if (status)
  166. {
  167. /* Select the correct error code. Ordered by severity, with bus issues first. */
  168. if (status & kLPI2C_MasterPinLowTimeoutFlag)
  169. {
  170. result = kStatus_LPI2C_PinLowTimeout;
  171. }
  172. else if (status & kLPI2C_MasterArbitrationLostFlag)
  173. {
  174. result = kStatus_LPI2C_ArbitrationLost;
  175. }
  176. else if (status & kLPI2C_MasterNackDetectFlag)
  177. {
  178. result = kStatus_LPI2C_Nak;
  179. }
  180. else if (status & kLPI2C_MasterFifoErrFlag)
  181. {
  182. result = kStatus_LPI2C_FifoError;
  183. }
  184. else
  185. {
  186. assert(false);
  187. }
  188. /* Clear the flags. */
  189. LPI2C_MasterClearStatusFlags(base, status);
  190. /* Reset fifos. These flags clear automatically. */
  191. base->MCR |= LPI2C_MCR_RRF_MASK | LPI2C_MCR_RTF_MASK;
  192. }
  193. return result;
  194. }
  195. /*!
  196. * @brief Wait until the tx fifo all empty.
  197. * @param base The LPI2C peripheral base address.
  198. * @retval #kStatus_Success
  199. * @retval #kStatus_LPI2C_PinLowTimeout
  200. * @retval #kStatus_LPI2C_ArbitrationLost
  201. * @retval #kStatus_LPI2C_Nak
  202. * @retval #kStatus_LPI2C_FifoError
  203. */
  204. static status_t LPI2C_MasterWaitForTxFifoAllEmpty(LPI2C_Type *base)
  205. {
  206. uint32_t status;
  207. size_t txCount;
  208. do
  209. {
  210. status_t result;
  211. /* Get the number of words in the tx fifo and compute empty slots. */
  212. LPI2C_MasterGetFifoCounts(base, NULL, &txCount);
  213. /* Check for error flags. */
  214. status = LPI2C_MasterGetStatusFlags(base);
  215. result = LPI2C_MasterCheck(base, status);
  216. if (result)
  217. {
  218. return result;
  219. }
  220. }
  221. while (txCount);
  222. return kStatus_Success;
  223. }
  224. static rt_size_t imxrt_i2c_mst_xfer(struct rt_i2c_bus_device *bus,
  225. struct rt_i2c_msg msgs[],
  226. rt_uint32_t num)
  227. {
  228. struct rt1052_i2c_bus *rt1052_i2c;
  229. rt_size_t i;
  230. RT_ASSERT(bus != RT_NULL);
  231. rt1052_i2c = (struct rt1052_i2c_bus *) bus;
  232. rt1052_i2c->msg = msgs;
  233. rt1052_i2c->msg_ptr = 0;
  234. rt1052_i2c->msg_cnt = num;
  235. rt1052_i2c->dptr = 0;
  236. for (i = 0; i < num; i++)
  237. {
  238. if (rt1052_i2c->msg[i].flags & RT_I2C_RD)
  239. {
  240. if (LPI2C_MasterStart(rt1052_i2c->I2C, rt1052_i2c->msg[i].addr, kLPI2C_Read) != kStatus_Success)
  241. {
  242. i = 0;
  243. break;
  244. }
  245. if (LPI2C_MasterWaitForTxFifoAllEmpty(rt1052_i2c->I2C) != kStatus_Success)
  246. {
  247. i = 0;
  248. break;
  249. }
  250. if (LPI2C_MasterReceive(rt1052_i2c->I2C, rt1052_i2c->msg[i].buf, rt1052_i2c->msg[i].len) != kStatus_Success)
  251. {
  252. i = 0;
  253. break;
  254. }
  255. if (LPI2C_MasterWaitForTxFifoAllEmpty(rt1052_i2c->I2C) != kStatus_Success)
  256. {
  257. i = 0;
  258. break;
  259. }
  260. }
  261. else
  262. {
  263. if (LPI2C_MasterStart(rt1052_i2c->I2C, rt1052_i2c->msg[i].addr, kLPI2C_Write) != kStatus_Success)
  264. {
  265. i = 0;
  266. break;
  267. }
  268. if (LPI2C_MasterWaitForTxFifoAllEmpty(rt1052_i2c->I2C) != kStatus_Success)
  269. {
  270. i = 0;
  271. break;
  272. }
  273. if (LPI2C_MasterSend(rt1052_i2c->I2C, rt1052_i2c->msg[i].buf, rt1052_i2c->msg[i].len) != kStatus_Success)
  274. {
  275. i = 0;
  276. break;
  277. }
  278. if (LPI2C_MasterWaitForTxFifoAllEmpty(rt1052_i2c->I2C) != kStatus_Success)
  279. {
  280. i = 0;
  281. break;
  282. }
  283. }
  284. }
  285. i2c_dbg("send stop condition\n");
  286. if (LPI2C_MasterStop(rt1052_i2c->I2C) != kStatus_Success)
  287. {
  288. i = 0;
  289. }
  290. rt1052_i2c->msg = RT_NULL;
  291. rt1052_i2c->msg_ptr = 0;
  292. rt1052_i2c->msg_cnt = 0;
  293. rt1052_i2c->dptr = 0;
  294. return i;
  295. }
  296. static rt_size_t imxrt_i2c_slv_xfer(struct rt_i2c_bus_device *bus,
  297. struct rt_i2c_msg msgs[],
  298. rt_uint32_t num)
  299. {
  300. return 0;
  301. }
  302. static rt_err_t imxrt_i2c_bus_control(struct rt_i2c_bus_device *bus,
  303. rt_uint32_t cmd,
  304. rt_uint32_t arg)
  305. {
  306. return RT_ERROR;
  307. }
  308. #endif
  309. int rt_hw_i2c_init(void)
  310. {
  311. #if (defined(RT_USING_HW_I2C1) || defined(RT_USING_HW_I2C2) || defined(RT_USING_HW_I2C3) || defined(RT_USING_HW_I2C4))
  312. lpi2c_master_config_t masterConfig = {0};
  313. /*Clock setting for LPI2C*/
  314. CLOCK_SetMux(kCLOCK_Lpi2cMux, 0);
  315. CLOCK_SetDiv(kCLOCK_Lpi2cDiv, LPI2C_CLOCK_SOURCE_DIVIDER - 1);
  316. #endif
  317. #if defined(RT_USING_HW_I2C1)
  318. LPI2C_MasterGetDefaultConfig(&masterConfig);
  319. #if defined(HW_I2C1_BADURATE_400kHZ)
  320. masterConfig.baudRate_Hz = 400000U;
  321. #elif defined(HW_I2C1_BADURATE_100kHZ)
  322. masterConfig.baudRate_Hz = 100000U;
  323. #endif
  324. imxrt_lpi2c_configure(&lpi2c1, &masterConfig);
  325. rt_i2c_bus_device_register(&lpi2c1.parent, lpi2c1.device_name);
  326. #endif
  327. #if defined(RT_USING_HW_I2C2)
  328. LPI2C_MasterGetDefaultConfig(&masterConfig);
  329. #if defined(HW_I2C2_BADURATE_400kHZ)
  330. masterConfig.baudRate_Hz = 400000U;
  331. #elif defined(HW_I2C2_BADURATE_100kHZ)
  332. masterConfig.baudRate_Hz = 100000U;
  333. #endif
  334. imxrt_lpi2c_configure(&lpi2c2, &masterConfig);
  335. rt_i2c_bus_device_register(&lpi2c2.parent, lpi2c2.device_name);
  336. #endif
  337. #if defined(RT_USING_HW_I2C3)
  338. LPI2C_MasterGetDefaultConfig(&masterConfig);
  339. #if defined(HW_I2C3_BADURATE_400kHZ)
  340. masterConfig.baudRate_Hz = 400000U;
  341. #elif defined(HW_I2C3_BADURATE_100kHZ)
  342. masterConfig.baudRate_Hz = 100000U;
  343. #endif
  344. imxrt_lpi2c_configure(&lpi2c3, &masterConfig);
  345. rt_i2c_bus_device_register(&lpi2c3.parent, lpi2c3.device_name);
  346. #endif
  347. #if defined(RT_USING_HW_I2C4)
  348. LPI2C_MasterGetDefaultConfig(&masterConfig);
  349. #if defined(HW_I2C4_BADURATE_400kHZ)
  350. masterConfig.baudRate_Hz = 400000U;
  351. #elif defined(HW_I2C4_BADURATE_100kHZ)
  352. masterConfig.baudRate_Hz = 100000U;
  353. #endif
  354. imxrt_lpi2c_configure(&lpi2c4, &masterConfig);
  355. rt_i2c_bus_device_register(&lpi2c4.parent, lpi2c4.device_name);
  356. #endif
  357. return 0;
  358. }
  359. INIT_DEVICE_EXPORT(rt_hw_i2c_init);
  360. #if defined(RT_USING_FINSH) && defined(DRV_I2C_DEBUG)
  361. #include <finsh.h>
  362. static rt_device_t _i2c_find(const char *name)
  363. {
  364. rt_device_t dev;
  365. dev = rt_device_find(name);
  366. if (!dev)
  367. {
  368. rt_kprintf("search device failed: %s\n", name);
  369. return RT_NULL;
  370. }
  371. if (rt_device_open(dev, RT_DEVICE_OFLAG_RDWR) != RT_EOK)
  372. {
  373. rt_kprintf("open device failed: %s\n", name);
  374. return RT_NULL;
  375. }
  376. rt_kprintf("open i2c bus: %s\n", name);
  377. return dev;
  378. }
  379. static void _search_i2c_device(rt_device_t dev, uint8_t cmd)
  380. {
  381. int count = 0;
  382. struct rt_i2c_msg msgs[2];
  383. uint8_t buf = 0;
  384. msgs[0].flags = RT_I2C_WR;
  385. msgs[0].buf = &cmd;
  386. msgs[0].len = sizeof(cmd);
  387. msgs[1].flags = RT_I2C_RD;
  388. msgs[1].buf = &buf;
  389. msgs[1].len = 1;
  390. for (int i = 0; i <= 0x7f; i++)
  391. {
  392. int len;
  393. msgs[0].addr = i;
  394. msgs[1].addr = i;
  395. len = rt_i2c_transfer((struct rt_i2c_bus_device *)dev, msgs, 2);
  396. if (len == 2)
  397. {
  398. count++;
  399. rt_kprintf("add:%02X transfer success, id: %02X\n", i, buf);
  400. }
  401. }
  402. rt_kprintf("i2c device: %d\n", count);
  403. }
  404. static int i2c_test(const char *name, uint8_t cmd)
  405. {
  406. rt_device_t dev = _i2c_find(name);
  407. if (dev == RT_NULL)
  408. {
  409. rt_kprintf("search i2c device faild\n");
  410. return -1;
  411. }
  412. _search_i2c_device(dev, cmd);
  413. rt_device_close(dev);
  414. return 0;
  415. }
  416. FINSH_FUNCTION_EXPORT(i2c_test, e.g: i2c_test("i2c1", 0xA3));
  417. #endif
  418. #endif /* RT_USING_I2C */