drv_i2c.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. /**************************************************************************//**
  2. *
  3. * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. *
  7. * Change Logs:
  8. * Date Author Notes
  9. * 2021-04-20 Wayne First version
  10. ******************************************************************************/
  11. #include <rtconfig.h>
  12. #if defined( BSP_USING_I2C)
  13. #include <rtdevice.h>
  14. #include "NuMicro.h"
  15. //#include <drv_i2c.h>
  16. #include <drv_sys.h>
  17. /* Private define ---------------------------------------------------------------*/
  18. #define LOG_TAG "drv.i2c"
  19. #define DBG_ENABLE
  20. #define DBG_SECTION_NAME LOG_TAG
  21. #define DBG_LEVEL DBG_ERROR
  22. #define DBG_COLOR
  23. #include <rtdbg.h>
  24. #define I2C_REG_WRITE(dev, addr, byte) outpw(dev->base + addr, byte)
  25. #define I2C_REG_READ(dev, addr) inpw(dev->base + addr)
  26. #define I2C_DISABLE(dev) I2C_REG_WRITE(dev, I2C_CSR, 0x00) /* Disable i2c core and interrupt */
  27. #define I2C_ENABLE(dev) I2C_REG_WRITE(dev, I2C_CSR, 0x3) /* Enable i2c core and interrupt */
  28. #define I2C_ISBUSFREE(dev) (((I2C_REG_READ(dev, I2C_SWR) & 0x18) == 0x18 && (I2C_REG_READ(dev, I2C_CSR) & 0x0400) == 0) ? 1 : 0)
  29. enum
  30. {
  31. I2C_START = -1,
  32. #if defined(BSP_USING_I2C0)
  33. I2C0_IDX,
  34. #endif
  35. #if defined(BSP_USING_I2C1)
  36. I2C1_IDX,
  37. #endif
  38. I2C_CNT
  39. };
  40. /* Private typedef --------------------------------------------------------------*/
  41. typedef struct
  42. {
  43. int32_t base; /* i2c bus number */
  44. int32_t state;
  45. int32_t addr;
  46. uint32_t last_error;
  47. int32_t bNackValid;
  48. uint32_t subaddr;
  49. int32_t subaddr_len;
  50. uint8_t buffer[I2C_MAX_BUF_LEN];
  51. uint32_t pos, len;
  52. } nu_i2c_dev;
  53. typedef nu_i2c_dev *nu_i2c_dev_t;
  54. typedef struct
  55. {
  56. struct rt_i2c_bus_device parent;
  57. char *name;
  58. IRQn_Type irqn;
  59. E_SYS_IPRST rstidx;
  60. E_SYS_IPCLK clkidx;
  61. struct rt_i2c_msg *cur_i2c_msg;
  62. nu_i2c_dev dev;
  63. } nu_i2c_bus ;
  64. typedef nu_i2c_bus *nu_i2c_bus_t;
  65. /* Private variables ------------------------------------------------------------*/
  66. static nu_i2c_bus nu_i2c_arr [ ] =
  67. {
  68. #if defined(BSP_USING_I2C0)
  69. {
  70. .dev =
  71. {
  72. .base = I2C0_BA,
  73. },
  74. .name = "i2c0",
  75. .irqn = IRQ_I2C0,
  76. .rstidx = I2C0RST,
  77. .clkidx = I2C0CKEN,
  78. },
  79. #endif
  80. #if defined(BSP_USING_I2C1)
  81. {
  82. .dev =
  83. {
  84. .base = I2C1_BA,
  85. },
  86. .name = "i2c1",
  87. .irqn = IRQ_I2C1,
  88. .rstidx = I2C1RST,
  89. .clkidx = I2C1CKEN,
  90. },
  91. #endif
  92. };
  93. /* Private functions ------------------------------------------------------------*/
  94. /**
  95. * @brief Set i2c interface speed
  96. * @param[in] dev i2c device structure pointer
  97. * @param[in] sp i2c speed
  98. * @return always 0
  99. */
  100. static int32_t nu_i2c_set_speed(nu_i2c_dev_t psNuI2cDev, int32_t sp)
  101. {
  102. uint32_t d;
  103. if (sp != 100 && sp != 400)
  104. return (I2C_ERR_NOTTY);
  105. d = (sysGetClock(SYS_PCLK) * 1000) / (sp * 5) - 1;
  106. I2C_REG_WRITE(psNuI2cDev, I2C_DIVIDER, d & 0xffff);
  107. return 0;
  108. }
  109. /**
  110. * @brief Configure i2c command
  111. * @param[in] dev i2c device structure pointer
  112. * @param[in] cmd command
  113. * @return None
  114. */
  115. static void nu_i2c_command(nu_i2c_dev_t psNuI2cDev, int32_t cmd)
  116. {
  117. psNuI2cDev->bNackValid = (cmd & I2C_CMD_WRITE) ? 1 : 0;
  118. I2C_REG_WRITE(psNuI2cDev, I2C_CMDR, cmd);
  119. }
  120. /**
  121. * @brief Configure slave address data
  122. * @param[in] dev i2c device structure pointer
  123. * @param[in] mode could be write or read
  124. * @return None
  125. */
  126. static void nu_i2c_calculate_address(nu_i2c_dev_t psNuI2cDev, int32_t mode)
  127. {
  128. int32_t i;
  129. uint32_t subaddr = psNuI2cDev->subaddr;
  130. psNuI2cDev->buffer[0] = (((psNuI2cDev->addr << 1) & 0xfe) | I2C_WRITE) & 0xff;
  131. for (i = psNuI2cDev->subaddr_len; i > 0; i--)
  132. {
  133. psNuI2cDev->buffer[i] = subaddr & 0xff;
  134. subaddr >>= 8;
  135. }
  136. if (mode == I2C_STATE_READ)
  137. {
  138. i = psNuI2cDev->subaddr_len + 1;
  139. psNuI2cDev->buffer[i] = (((psNuI2cDev->addr << 1) & 0xfe)) | I2C_READ;
  140. }
  141. }
  142. /**
  143. * @brief Reset some variables
  144. * @param[in] dev i2c device structure pointer
  145. * @return None
  146. */
  147. static void nu_i2c_reset(nu_i2c_dev_t psNuI2cDev)
  148. {
  149. psNuI2cDev->addr = -1;
  150. psNuI2cDev->last_error = 0;
  151. psNuI2cDev->subaddr = 0;
  152. psNuI2cDev->subaddr_len = 0;
  153. }
  154. static void nu_i2c_isr(int vector, void *param)
  155. {
  156. nu_i2c_bus_t psNuI2CBus = (nu_i2c_bus_t)param;
  157. nu_i2c_dev_t psNuI2CDev = (nu_i2c_dev_t)&psNuI2CBus->dev;
  158. struct rt_i2c_msg *pmsg = psNuI2CBus->cur_i2c_msg;
  159. uint32_t msg_flag = pmsg->flags;
  160. uint32_t csr, val;
  161. csr = I2C_REG_READ(psNuI2CDev, I2C_CSR);
  162. csr |= 0x04;
  163. /* Clear interrupt flag */
  164. I2C_REG_WRITE(psNuI2CDev, I2C_CSR, csr);
  165. if (psNuI2CDev->state == I2C_STATE_NOP)
  166. return;
  167. /* NACK only valid in WRITE */
  168. if ((csr & 0x800) && psNuI2CDev->bNackValid && !(msg_flag & RT_I2C_IGNORE_NACK))
  169. {
  170. rt_kprintf("I2C W/ NACK\n");
  171. psNuI2CDev->last_error = I2C_ERR_NACK;
  172. nu_i2c_command(psNuI2CDev, I2C_CMD_STOP);
  173. psNuI2CDev->state = I2C_STATE_NOP;
  174. }
  175. /* Arbitration lost */
  176. else if (csr & 0x200)
  177. {
  178. rt_kprintf("Arbitration lost\n");
  179. psNuI2CDev->last_error = I2C_ERR_LOSTARBITRATION;
  180. psNuI2CDev->state = I2C_STATE_NOP;
  181. }
  182. /* Transmit complete */
  183. else if (!(csr & 0x100))
  184. {
  185. /* Send address state */
  186. if (psNuI2CDev->pos < psNuI2CDev->subaddr_len + 1)
  187. {
  188. val = psNuI2CDev->buffer[psNuI2CDev->pos++] & 0xff;
  189. I2C_REG_WRITE(psNuI2CDev, I2C_TxR, val);
  190. nu_i2c_command(psNuI2CDev, I2C_CMD_WRITE);
  191. }
  192. else if (psNuI2CDev->state == I2C_STATE_READ)
  193. {
  194. /* Sub-address send over, begin restart a read command */
  195. if (psNuI2CDev->pos == psNuI2CDev->subaddr_len + 1)
  196. {
  197. val = psNuI2CDev->buffer[psNuI2CDev->pos++];
  198. I2C_REG_WRITE(psNuI2CDev, I2C_TxR, val);
  199. nu_i2c_command(psNuI2CDev, I2C_CMD_START | I2C_CMD_WRITE);
  200. }
  201. else
  202. {
  203. psNuI2CDev->buffer[psNuI2CDev->pos++] = I2C_REG_READ(psNuI2CDev, I2C_RxR) & 0xff;
  204. if (psNuI2CDev->pos < psNuI2CDev->len)
  205. {
  206. /* Last character */
  207. if (psNuI2CDev->pos == psNuI2CDev->len - 1)
  208. nu_i2c_command(psNuI2CDev, I2C_CMD_READ | I2C_CMD_STOP | I2C_CMD_NACK);
  209. else
  210. nu_i2c_command(psNuI2CDev, I2C_CMD_READ);
  211. }
  212. else
  213. {
  214. psNuI2CDev->state = I2C_STATE_NOP;
  215. }
  216. }
  217. }
  218. /* Write data */
  219. else if (psNuI2CDev->state == I2C_STATE_WRITE)
  220. {
  221. if (psNuI2CDev->pos < psNuI2CDev->len)
  222. {
  223. val = psNuI2CDev->buffer[psNuI2CDev->pos];
  224. I2C_REG_WRITE(psNuI2CDev, I2C_TxR, val);
  225. /* Last character */
  226. if (psNuI2CDev->pos == psNuI2CDev->len - 1)
  227. nu_i2c_command(psNuI2CDev, I2C_CMD_WRITE | I2C_CMD_STOP);
  228. else
  229. nu_i2c_command(psNuI2CDev, I2C_CMD_WRITE);
  230. psNuI2CDev->pos ++;
  231. }
  232. else
  233. {
  234. psNuI2CDev->state = I2C_STATE_NOP;
  235. }
  236. }
  237. }
  238. }
  239. /**
  240. * @brief Read data from I2C slave.
  241. * @param[in] psNuI2cDev is interface structure pointer.
  242. * @param[in] pmsg is pointer of rt i2c message structure.
  243. * @return read status.
  244. * @retval >0 length when success.
  245. * @retval I2C_ERR_BUSY Interface busy.
  246. * @retval I2C_ERR_IO Interface not opened.
  247. * @retval I2C_ERR_NODEV No such device.
  248. * @retval I2C_ERR_NACK Slave returns an erroneous ACK.
  249. * @retval I2C_ERR_LOSTARBITRATION arbitration lost happen.
  250. */
  251. static int32_t nu_i2c_read(nu_i2c_dev_t psNuI2cDev, struct rt_i2c_msg *pmsg)
  252. {
  253. uint8_t *buf = pmsg->buf;
  254. uint32_t len = pmsg->len;
  255. if (len > I2C_MAX_BUF_LEN - 10)
  256. len = I2C_MAX_BUF_LEN - 10;
  257. psNuI2cDev->state = I2C_STATE_READ;
  258. psNuI2cDev->pos = 1;
  259. /* Current ISR design will get one garbage byte */
  260. /* plus 1 unused char */
  261. psNuI2cDev->len = psNuI2cDev->subaddr_len + 1 + len + 2;
  262. psNuI2cDev->last_error = 0;
  263. /* Get slave address */
  264. nu_i2c_calculate_address(psNuI2cDev, I2C_STATE_READ);
  265. /* Enable I2C-EN */
  266. I2C_ENABLE(psNuI2cDev);
  267. /* Send first byte to transfer the message. */
  268. I2C_REG_WRITE(psNuI2cDev, I2C_TxR, psNuI2cDev->buffer[0] & 0xff);
  269. if (!I2C_ISBUSFREE(psNuI2cDev))
  270. return (I2C_ERR_BUSY);
  271. nu_i2c_command(psNuI2cDev, I2C_CMD_START | I2C_CMD_WRITE);
  272. while (psNuI2cDev->state != I2C_STATE_NOP);
  273. /* Disable I2C-EN */
  274. I2C_DISABLE(psNuI2cDev);
  275. if (psNuI2cDev->last_error)
  276. return (psNuI2cDev->last_error);
  277. rt_memcpy(buf, psNuI2cDev->buffer + psNuI2cDev->subaddr_len + 3, len);
  278. psNuI2cDev->subaddr += len;
  279. return len;
  280. }
  281. /**
  282. * @brief Write data from I2C slave.
  283. * @param[in] psNuI2cDev is interface structure pointer.
  284. * @param[in] pmsg is pointer of rt i2c message structure.
  285. * @return write status.
  286. * @retval >0 length when success.
  287. * @retval I2C_ERR_BUSY Interface busy.
  288. * @retval I2C_ERR_IO Interface not opened.
  289. * @retval I2C_ERR_NODEV No such device.
  290. * @retval I2C_ERR_NACK Slave returns an erroneous ACK.
  291. * @retval I2C_ERR_LOSTARBITRATION arbitration lost happen.
  292. */
  293. static int32_t nu_i2c_write(nu_i2c_dev_t psNuI2cDev, struct rt_i2c_msg *pmsg)
  294. {
  295. uint8_t *buf = pmsg->buf;
  296. uint32_t len = pmsg->len;
  297. if (len > I2C_MAX_BUF_LEN - 10)
  298. len = I2C_MAX_BUF_LEN - 10;
  299. rt_memcpy(psNuI2cDev->buffer + psNuI2cDev->subaddr_len + 1, buf, len);
  300. psNuI2cDev->state = I2C_STATE_WRITE;
  301. psNuI2cDev->pos = 1;
  302. psNuI2cDev->len = psNuI2cDev->subaddr_len + 1 + len;
  303. psNuI2cDev->last_error = 0;
  304. /* Get slave address */
  305. nu_i2c_calculate_address(psNuI2cDev, I2C_STATE_WRITE);
  306. /* Enable I2C-EN */
  307. I2C_ENABLE(psNuI2cDev);
  308. /* Send first byte to transfer the message. */
  309. I2C_REG_WRITE(psNuI2cDev, I2C_TxR, psNuI2cDev->buffer[0] & 0xff);
  310. if (!I2C_ISBUSFREE(psNuI2cDev))
  311. return (I2C_ERR_BUSY);
  312. nu_i2c_command(psNuI2cDev, I2C_CMD_START | I2C_CMD_WRITE);
  313. while (psNuI2cDev->state != I2C_STATE_NOP);
  314. /* Disable I2C-EN */
  315. I2C_DISABLE(psNuI2cDev);
  316. if (psNuI2cDev->last_error)
  317. return (psNuI2cDev->last_error);
  318. psNuI2cDev->subaddr += len;
  319. return len;
  320. }
  321. /**
  322. * @brief Support some I2C driver commands for application.
  323. * @param[in] psNuI2cDev is interface structure pointer.
  324. * @param[in] cmd is command.
  325. * @param[in] arg0 is the first argument of command.
  326. * @param[in] arg1 is the second argument of command.
  327. * @return command status.
  328. * @retval 0 Success.
  329. * @retval I2C_ERR_IO Interface not opened.
  330. * @retval I2C_ERR_NODEV No such device.
  331. * @retval I2C_ERR_NOTTY Command not support, or parameter error.
  332. */
  333. static int32_t nu_i2c_ioctl(nu_i2c_dev_t psNuI2cDev, uint32_t cmd, uint32_t arg0, uint32_t arg1)
  334. {
  335. switch (cmd)
  336. {
  337. case I2C_IOC_SET_DEV_ADDRESS:
  338. psNuI2cDev->addr = arg0;
  339. break;
  340. case I2C_IOC_SET_SPEED:
  341. return (nu_i2c_set_speed(psNuI2cDev, (int32_t)arg0));
  342. case I2C_IOC_SET_SUB_ADDRESS:
  343. if (arg1 > 4)
  344. {
  345. return (I2C_ERR_NOTTY);
  346. }
  347. psNuI2cDev->subaddr = arg0;
  348. psNuI2cDev->subaddr_len = arg1;
  349. break;
  350. default:
  351. return (I2C_ERR_NOTTY);
  352. }
  353. return (0);
  354. }
  355. static rt_size_t nu_i2c_mst_xfer(struct rt_i2c_bus_device *bus,
  356. struct rt_i2c_msg msgs[],
  357. rt_uint32_t num)
  358. {
  359. nu_i2c_bus_t psNuI2cBus;
  360. nu_i2c_dev_t psNuI2cDev;
  361. rt_size_t i;
  362. rt_err_t ret;
  363. struct rt_i2c_msg *pmsg;
  364. RT_ASSERT(bus != RT_NULL);
  365. psNuI2cBus = (nu_i2c_bus_t) bus;
  366. psNuI2cDev = &psNuI2cBus->dev;
  367. for (i = 0; i < num; i++)
  368. {
  369. if (!I2C_ISBUSFREE(psNuI2cDev))
  370. break;
  371. pmsg = psNuI2cBus->cur_i2c_msg = &msgs[i];
  372. /* Not support 10bit. */
  373. if ((pmsg->flags & RT_I2C_ADDR_10BIT)
  374. || (pmsg->len == 0))
  375. break;
  376. /* Set device address */
  377. nu_i2c_reset(psNuI2cDev);
  378. nu_i2c_ioctl(psNuI2cDev, I2C_IOC_SET_DEV_ADDRESS, pmsg->addr, 0);
  379. if (pmsg->flags & RT_I2C_RD)
  380. {
  381. ret = nu_i2c_read(psNuI2cDev, pmsg);
  382. }
  383. else
  384. {
  385. ret = nu_i2c_write(psNuI2cDev, pmsg);
  386. }
  387. if (ret != pmsg->len) break;
  388. }
  389. return i;
  390. }
  391. static const struct rt_i2c_bus_device_ops nu_i2c_ops =
  392. {
  393. .master_xfer = nu_i2c_mst_xfer,
  394. .slave_xfer = NULL,
  395. .i2c_bus_control = NULL,
  396. };
  397. /* Public functions -------------------------------------------------------------*/
  398. int rt_hw_i2c_init(void)
  399. {
  400. int i;
  401. rt_err_t ret = RT_EOK;
  402. for (i = (I2C_START + 1); i < I2C_CNT; i++)
  403. {
  404. nu_i2c_dev_t psNuI2cDev = &nu_i2c_arr[i].dev;
  405. ret = rt_i2c_bus_device_register(&nu_i2c_arr[i].parent, nu_i2c_arr[i].name);
  406. RT_ASSERT(RT_EOK == ret);
  407. nu_i2c_arr[i].parent.ops = &nu_i2c_ops;
  408. /* Enable I2C engine clock and reset. */
  409. nu_sys_ipclk_enable(nu_i2c_arr[i].clkidx);
  410. nu_sys_ip_reset(nu_i2c_arr[i].rstidx);
  411. nu_i2c_ioctl(psNuI2cDev, I2C_IOC_SET_SPEED, 100, 0);
  412. /* Register ISR and Respond IRQ. */
  413. rt_hw_interrupt_install(nu_i2c_arr[i].irqn, nu_i2c_isr, &nu_i2c_arr[i], nu_i2c_arr[i].name);
  414. rt_hw_interrupt_umask(nu_i2c_arr[i].irqn);
  415. }
  416. return 0;
  417. }
  418. INIT_DEVICE_EXPORT(rt_hw_i2c_init);
  419. #endif /* BSP_USING_I2C */