drv_i2c.c 15 KB

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