fi2c_master.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. /*
  2. * Copyright : (C) 2022 Phytium Information Technology, Inc.
  3. * All Rights Reserved.
  4. *
  5. * This program is OPEN SOURCE software: you can redistribute it and/or modify it
  6. * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
  7. * either version 1.0 of the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
  10. * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. * See the Phytium Public License for more details.
  12. *
  13. *
  14. * FilePath: fi2c_master.c
  15. * Date: 2022-02-10 14:53:42
  16. * LastEditTime: 2022-02-18 08:36:46
  17. * Description:  This files is for
  18. *
  19. * Modify History:
  20. * Ver   Who        Date         Changes
  21. * ----- ------     --------    --------------------------------------
  22. */
  23. /*
  24. - 一些驱动模块,直接操作硬件的I/O接口,无法实现有意义的操作,此时需要针对中间件或者用户使用习惯设计此模块 (i2c,nand,eth)
  25. - 部分场景适用, 分角色的 I/O 操作
  26. - 此模块的函数原型,在fooxx.h 中声明一次,方便用户或者中间件层调用
  27. */
  28. /***************************** Include Files *********************************/
  29. #include "fio.h"
  30. #include "fsleep.h"
  31. #include "fdebug.h"
  32. #include "fi2c_hw.h"
  33. #include "fi2c.h"
  34. #include "finterrupt.h"
  35. /************************** Constant Definitions *****************************/
  36. /**************************** Type Definitions *******************************/
  37. /***************** Macros (Inline Functions) Definitions *********************/
  38. #define FI2C_DEBUG_TAG "I2C_MASTER"
  39. #define FI2C_ERROR(format, ...) FT_DEBUG_PRINT_E(FI2C_DEBUG_TAG, format, ##__VA_ARGS__)
  40. #define FI2C_INFO(format, ...) FT_DEBUG_PRINT_I(FI2C_DEBUG_TAG, format, ##__VA_ARGS__)
  41. #define FI2C_DEBUG(format, ...) FT_DEBUG_PRINT_D(FI2C_DEBUG_TAG, format, ##__VA_ARGS__)
  42. #define FI2C_TIMEOUT 500
  43. /************************** Function Prototypes ******************************/
  44. /************************** Variable Definitions *****************************/
  45. /*****************************************************************************/
  46. /**
  47. * @name: FI2cMasterStartTrans
  48. * @msg: I2C主机开始传输
  49. * @return {*}
  50. * @param {FI2c} *instance_p, I2C驱动实例数据
  51. * @param {u32} mem_addr, 从机的片内偏移
  52. * @param {u8} mem_byte_len, Size of internal memory address 1->8bit ~ 4->32bit
  53. * @param {u8} flag ,for cmd reg STOP,RESTART.
  54. */
  55. static FError FI2cMasterStartTrans(FI2c *instance_p, u32 mem_addr, u8 mem_byte_len, u16 flag)
  56. {
  57. FASSERT(instance_p);
  58. uintptr base_addr = instance_p->config.base_addr;
  59. FError ret = FI2C_SUCCESS;
  60. u32 addr_len = mem_byte_len;
  61. ret = FI2cWaitBusBusy(base_addr);
  62. if (FI2C_SUCCESS != ret)
  63. return ret;
  64. ret = FI2cSetTar(base_addr, instance_p->config.slave_addr); /* 设备地址 */
  65. if (FI2C_SUCCESS != ret)
  66. return ret;
  67. while (addr_len)
  68. {
  69. ret = FI2cWaitStatus(base_addr, FI2C_STATUS_TFNF);
  70. if (FI2C_SUCCESS != ret)
  71. break;
  72. if (FI2C_GET_STATUS(base_addr) & FI2C_STATUS_TFNF)
  73. {
  74. addr_len--;
  75. if (addr_len != 0)
  76. {
  77. FI2C_WRITE_REG32(base_addr, FI2C_DATA_CMD_OFFSET,
  78. (mem_addr >> (addr_len * BITS_PER_BYTE)) & FI2C_DATA_MASK); /* word address */
  79. }
  80. else
  81. {
  82. FI2C_WRITE_REG32(base_addr, FI2C_DATA_CMD_OFFSET,
  83. ((mem_addr >> (addr_len * BITS_PER_BYTE)) & FI2C_DATA_MASK) + flag); /* word address */
  84. }
  85. }
  86. }
  87. return ret;
  88. }
  89. /**
  90. * @name: FI2cMasterStopTrans
  91. * @msg: I2C主机结束传输
  92. * @return {*}
  93. * @param {FI2c} *instance_p, I2C驱动实例数据
  94. */
  95. static FError FI2cMasterStopTrans(FI2c *instance_p)
  96. {
  97. FASSERT(instance_p);
  98. FError ret = FI2C_SUCCESS;
  99. uintptr base_addr = instance_p->config.base_addr;
  100. u32 reg_val;
  101. u32 timeout = 0;
  102. FI2C_INFO("GET MASTER STOP, stat: 0x%x, 0x%x", FI2C_READ_INTR_STAT(base_addr),
  103. FI2C_READ_RAW_INTR_STAT(base_addr));
  104. while (TRUE)
  105. {
  106. if (FI2C_READ_RAW_INTR_STAT(base_addr) & FI2C_INTR_STOP_DET)
  107. {
  108. reg_val = FI2C_READ_REG32(base_addr, FI2C_CLR_STOP_DET_OFFSET); /* read to clr intr status */
  109. break;
  110. }
  111. else if (FI2C_TIMEOUT < ++timeout)
  112. {
  113. break; /* wait timeout, but no error code ret */
  114. }
  115. }
  116. ret = FI2cWaitBusBusy(base_addr);
  117. if (FI2C_SUCCESS == ret)
  118. ret = FI2cFlushRxFifo(base_addr);
  119. return ret;
  120. }
  121. /**
  122. * @name: FI2cMasterReadPoll
  123. * @msg: I2C主机读,阻塞直到完成读操作或失败
  124. * @return {FError *} 返回错误码
  125. * @param {FI2c} *instance_p I2C驱动实例数据
  126. * @param {u32} mem_addr 从机的内部偏移地址
  127. * @param {u8} mem_byte_len, Size of internal memory address 1->8bit ~ 4->32bit
  128. * @param {u8} *buf_p 读目的缓冲区
  129. * @param {int} buf_len 读目的缓冲区长度
  130. */
  131. FError FI2cMasterReadPoll(FI2c *instance_p, u32 mem_addr, u8 mem_byte_len, u8 *buf_p, u32 buf_len)
  132. {
  133. FError ret = FI2C_SUCCESS;
  134. FASSERT(instance_p);
  135. u32 mask;
  136. u32 reg_val;
  137. u32 tx_len = buf_len;
  138. u32 rx_len = buf_len;
  139. u32 rx_limit, tx_limit;
  140. u32 trans_timeout = 0;
  141. uintptr base_addr = instance_p->config.base_addr;
  142. if (FT_COMPONENT_IS_READY != instance_p->is_ready)
  143. {
  144. FI2C_ERROR("i2c driver not ready");
  145. return FI2C_ERR_NOT_READY;
  146. }
  147. if (FI2C_MASTER != instance_p->config.work_mode)
  148. {
  149. FI2C_ERROR("i2c work mode shall be master");
  150. return FI2C_ERR_INVAL_STATE;
  151. }
  152. ret = FI2cMasterStartTrans(instance_p, mem_addr, mem_byte_len, FI2C_DATA_CMD_WRITE);
  153. if (FI2C_SUCCESS != ret)
  154. return ret;
  155. /*for trigger rx intr*/
  156. while (tx_len > 0 || rx_len > 0)
  157. {
  158. /* code */
  159. rx_limit = FI2C_IIC_FIFO_MAX_LV - FI2C_READ_REG32(base_addr, FI2C_RXFLR_OFFSET);
  160. tx_limit = FI2C_IIC_FIFO_MAX_LV - FI2C_READ_REG32(base_addr, FI2C_TXFLR_OFFSET);
  161. while (tx_len > 0 & rx_limit > 0 & tx_limit > 0)
  162. {
  163. /* code */
  164. if (tx_len == 1)
  165. {
  166. reg_val = FI2C_DATA_CMD_READ | FI2C_DATA_CMD_STOP;
  167. FI2C_WRITE_REG32(instance_p->config.base_addr, FI2C_DATA_CMD_OFFSET, reg_val);
  168. }
  169. else
  170. {
  171. reg_val = FI2C_DATA_CMD_READ;
  172. FI2C_WRITE_REG32(instance_p->config.base_addr, FI2C_DATA_CMD_OFFSET, reg_val);
  173. }
  174. tx_len--;
  175. rx_limit--;
  176. tx_limit--;
  177. }
  178. u8 rx_tem = FI2C_READ_REG32(base_addr, FI2C_RXFLR_OFFSET);
  179. while (rx_tem > 0 & rx_len > 0)
  180. {
  181. /* code */
  182. if (FI2C_GET_STATUS(base_addr) & FI2C_STATUS_RFNE)
  183. {
  184. /* trans one byte */
  185. *buf_p++ = FI2C_READ_DATA(base_addr);
  186. rx_len--;
  187. rx_tem--;
  188. trans_timeout = 0;
  189. }
  190. else if (FI2C_TIMEOUT < (++trans_timeout))
  191. {
  192. ret = FI2C_ERR_TIMEOUT;
  193. FI2C_ERROR("timeout in i2c master read");
  194. break;
  195. }
  196. }
  197. }
  198. if (FI2C_SUCCESS == ret)
  199. {
  200. ret = FI2cMasterStopTrans(instance_p);
  201. }
  202. return ret;
  203. }
  204. /**
  205. * @name: FI2cMasterWritePoll
  206. * @msg: I2C主机写,阻塞直到完成写操作或失败
  207. * @return {FError *} 返回错误码
  208. * @param {FI2c} *instance_p I2C驱动实例数据
  209. * @param {u32} mem_addr 从机的内部偏移地址
  210. * @param {u8} mem_byte_len, Size of internal memory address 1->8bit ~ 4->32bit
  211. * @param {u8} *buf_p 写源缓冲区
  212. * @param {size_t} buf_len 写源缓冲区长度
  213. */
  214. FError FI2cMasterWritePoll(FI2c *instance_p, u32 mem_addr, u8 mem_byte_len, const u8 *buf_p, u32 buf_len)
  215. {
  216. FASSERT(instance_p && buf_p);
  217. FError ret = FI2C_SUCCESS;
  218. u32 buf_idx = buf_len;
  219. u32 tx_limit;
  220. uintptr base_addr = instance_p->config.base_addr;
  221. u32 reg_val;
  222. u32 trans_timeout = 0;
  223. if (FT_COMPONENT_IS_READY != instance_p->is_ready)
  224. {
  225. FI2C_ERROR("i2c driver not ready");
  226. return FI2C_ERR_NOT_READY;
  227. }
  228. if (FI2C_MASTER != instance_p->config.work_mode)
  229. {
  230. FI2C_ERROR("i2c work mode shall be master");
  231. return FI2C_ERR_INVAL_STATE;
  232. }
  233. ret = FI2cMasterStartTrans(instance_p, mem_addr, mem_byte_len, FI2C_DATA_CMD_WRITE);
  234. if (FI2C_SUCCESS != ret)
  235. return ret;
  236. while (buf_idx)
  237. {
  238. tx_limit = FI2C_IIC_FIFO_MAX_LV - FI2C_READ_REG32(base_addr, FI2C_TXFLR_OFFSET);
  239. while (tx_limit > 0 & buf_idx > 0)
  240. {
  241. if (FI2C_GET_STATUS(base_addr) & FI2C_STATUS_TFNF)
  242. {
  243. if (1 == buf_idx)
  244. {
  245. reg_val = (FI2C_DATA_MASK & *buf_p) |
  246. FI2C_DATA_CMD_WRITE |
  247. FI2C_DATA_CMD_STOP;
  248. FI2C_INFO("Write Stop Singal");
  249. }
  250. else
  251. {
  252. reg_val = (FI2C_DATA_MASK & *buf_p) |
  253. FI2C_DATA_CMD_WRITE;
  254. }
  255. buf_idx--;
  256. tx_limit--;
  257. FI2C_WRITE_REG32(base_addr, FI2C_DATA_CMD_OFFSET, reg_val);
  258. buf_p++;
  259. trans_timeout = 0;
  260. }
  261. else if (FI2C_TIMEOUT < ++trans_timeout)
  262. {
  263. ret = FI2C_ERR_TIMEOUT;
  264. FI2C_ERROR("timeout in i2c master write");
  265. break;
  266. }
  267. }
  268. }
  269. if (FI2C_SUCCESS == ret)
  270. {
  271. ret = FI2cMasterStopTrans(instance_p);
  272. }
  273. return ret;
  274. }
  275. /**
  276. * @name: FI2cMasterReadIntr
  277. * @msg: I2C主机读,中断完成读操作或失败
  278. * @return {FError *} 返回错误码
  279. * @param {FI2c} *instance_p I2C驱动实例数据
  280. * @param {u32} mem_addr 从机的内部偏移地址
  281. * @param {u8} mem_byte_len, Size of internal memory address 1->8bit ~ 4->32bit
  282. * @param {u8} *buf_p 读目的缓冲区
  283. * @param {int} buf_len 读目的缓冲区长度
  284. */
  285. FError FI2cMasterReadIntr(FI2c *instance_p, u32 mem_addr, u8 mem_byte_len, u8 *buf_p, u32 buf_len)
  286. {
  287. FError ret = FI2C_SUCCESS;
  288. FASSERT(instance_p);
  289. u32 mask;
  290. u32 reg_val;
  291. u32 trans_timeout;
  292. if (FT_COMPONENT_IS_READY != instance_p->is_ready)
  293. {
  294. FI2C_ERROR("i2c driver not ready");
  295. return FI2C_ERR_NOT_READY;
  296. }
  297. if (FI2C_MASTER != instance_p->config.work_mode)
  298. {
  299. FI2C_ERROR("i2c work mode shall be master");
  300. return FI2C_ERR_INVAL_STATE;
  301. }
  302. while (instance_p->status != STATUS_IDLE)
  303. {
  304. /* code */
  305. fsleep_millisec(1);
  306. if (FI2C_TIMEOUT < (++trans_timeout))
  307. {
  308. ret = FI2C_ERR_TIMEOUT;
  309. FI2C_ERROR("timeout in i2c master read intr.");
  310. break;
  311. }
  312. }
  313. instance_p->rxframe.data_buff = buf_p;
  314. instance_p->rxframe.rx_total_num = buf_len;
  315. instance_p->txframe.tx_total_num = buf_len;
  316. instance_p->rxframe.rx_cnt = 0;
  317. FI2C_SET_RX_TL(instance_p->config.base_addr, 0);/* 0 表示接收缓冲区大于等于 1 时触发中断 */
  318. ret = FI2cMasterStartTrans(instance_p, mem_addr, mem_byte_len, FI2C_DATA_CMD_WRITE);
  319. instance_p->status = STATUS_READ_IN_PROGRESS;
  320. if (FI2C_SUCCESS != ret)
  321. return ret;
  322. mask = FI2C_GET_INTRRUPT_MASK(instance_p->config.base_addr);
  323. mask |= FI2C_INTR_MASTER_RD_MASK;
  324. ret = FI2cMasterSetupIntr(instance_p, mask);
  325. if (FI2C_SUCCESS != ret)
  326. return ret;
  327. return ret;
  328. }
  329. /**
  330. * @name: FI2cMasterWriteIntr
  331. * @msg: I2C主机写,中断写操作或失败
  332. * @return {FError *} 返回错误码
  333. * @param {FI2c} *instance_p I2C驱动实例数据
  334. * @param {u32} mem_addr 从机的内部偏移地址
  335. * @param {u8} mem_byte_len, Size of internal memory address 1->8bit ~ 4->32bit
  336. * @param {u8} *buf_p 写源缓冲区
  337. * @param {size_t} buf_len 写源缓冲区长度
  338. */
  339. FError FI2cMasterWriteIntr(FI2c *instance_p, u32 mem_addr, u8 mem_byte_len, const u8 *buf_p, u32 buf_len)
  340. {
  341. FError ret = FI2C_SUCCESS;
  342. FASSERT(instance_p);
  343. u32 mask;
  344. u32 trans_timeout = 0;
  345. if (FT_COMPONENT_IS_READY != instance_p->is_ready)
  346. {
  347. FI2C_ERROR("i2c driver not ready");
  348. return FI2C_ERR_NOT_READY;
  349. }
  350. if (FI2C_MASTER != instance_p->config.work_mode)
  351. {
  352. FI2C_ERROR("i2c work mode shall be master");
  353. return FI2C_ERR_INVAL_STATE;
  354. }
  355. while (instance_p->status != STATUS_IDLE)
  356. {
  357. /* code */
  358. fsleep_millisec(1);
  359. if (FI2C_TIMEOUT < (++trans_timeout))
  360. {
  361. ret = FI2C_ERR_TIMEOUT;
  362. FI2C_ERROR("timeout in i2c master write intr.");
  363. break;
  364. }
  365. }
  366. instance_p->txframe.data_buff = buf_p;
  367. instance_p->txframe.tx_total_num = buf_len;
  368. instance_p->txframe.tx_cnt = 0;
  369. ret = FI2cMasterStartTrans(instance_p, mem_addr, mem_byte_len, FI2C_DATA_CMD_WRITE);
  370. if (FI2C_SUCCESS != ret)
  371. return ret;
  372. instance_p->status = STATUS_WRITE_IN_PROGRESS;
  373. mask = FI2C_GET_INTRRUPT_MASK(instance_p->config.base_addr);
  374. mask |= FI2C_INTR_MASTER_WR_MASK;
  375. ret = FI2cMasterSetupIntr(instance_p, mask);
  376. if (FI2C_SUCCESS != ret)
  377. return ret;
  378. return ret;
  379. }