fspim.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  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: fspim.c
  15. * Date: 2022-02-10 14:53:42
  16. * LastEditTime: 2022-02-18 09:08:32
  17. * Description:  This files is for spim api implementation
  18. *
  19. * Modify History:
  20. * Ver   Who        Date         Changes
  21. * ----- ------     --------    --------------------------------------
  22. * 1.0 zhugengyu 2021-12-3 init commit
  23. * 1.1 zhugengyu 2022-4-15 support test mode
  24. * 1.2 zhugengyu 2022-5-13 support spi dma
  25. */
  26. /***************************** Include Files *********************************/
  27. #include <string.h>
  28. #include "fio.h"
  29. #include "ferror_code.h"
  30. #include "ftypes.h"
  31. #include "fdebug.h"
  32. #include "fspim_hw.h"
  33. #include "fspim.h"
  34. /************************** Constant Definitions *****************************/
  35. /**************************** Type Definitions *******************************/
  36. /***************** Macros (Inline Functions) Definitions *********************/
  37. #define FSPIM_DEBUG_TAG "SPIM"
  38. #define FSPIM_ERROR(format, ...) FT_DEBUG_PRINT_E(FSPIM_DEBUG_TAG, format, ##__VA_ARGS__)
  39. #define FSPIM_WARN(format, ...) FT_DEBUG_PRINT_W(FSPIM_DEBUG_TAG, format, ##__VA_ARGS__)
  40. #define FSPIM_INFO(format, ...) FT_DEBUG_PRINT_I(FSPIM_DEBUG_TAG, format, ##__VA_ARGS__)
  41. #define FSPIM_DEBUG(format, ...) FT_DEBUG_PRINT_D(FSPIM_DEBUG_TAG, format, ##__VA_ARGS__)
  42. /************************** Function Prototypes ******************************/
  43. FError FSpimReset(FSpim *instance_p);
  44. /************************** Variable Definitions *****************************/
  45. static const char *FSPIM_ERROR_CODE_MSG[FSPIM_NUM_OF_ERR_CODE] =
  46. {
  47. "FSPIM_SUCCESS : fspim success",
  48. "FSPIM_ERR_INVAL_STATE : fspim invalid state",
  49. "FSPIM_ERR_NOT_READY : fspim driver not ready",
  50. "FSPIM_ERR_INVAL_PARAM : fspim invalid input parameters",
  51. "FSPIM_ERR_BUS_BUSY : fspim bus is busy",
  52. "FSPIM_ERR_NOT_SUPPORT : fspim not support operation",
  53. "FSPIM_ERR_TIMEOUT : fspim wait timeout",
  54. "FSPIM_ERR_TRANS_FAIL : fspim data transfer failed",
  55. };
  56. /*****************************************************************************/
  57. /* 此文件主要为了完成用户对外接口,用户可以使用这些接口直接开始工作 */
  58. /* - 包括用户API的定义和实现
  59. - 同时包含必要的OPTION方法,方便用户进行配置
  60. - 如果驱动可以直接进行I/O操作,在此源文件下可以将API 进行实现 */
  61. /*
  62. * @name: FSpimCfgInitialize
  63. * @msg: Initializes a specific instance such that it is ready to be used.
  64. * @param {FSpim} *instance_p FSPIM驱动控制数据
  65. * @param {FSpimConfig} *config_p FSPIM驱动配置数据
  66. * @return 驱动初始化的错误码信息,FSPIM_SUCCESS 表示初始化成功,其它返回值表示初始化失败
  67. */
  68. FError FSpimCfgInitialize(FSpim *instance_p, const FSpimConfig *input_config_p)
  69. {
  70. FASSERT(instance_p && input_config_p);
  71. uintptr base_addr = instance_p->config.base_addr;
  72. FError ret = FSPIM_SUCCESS;
  73. /*
  74. * If the device is started, disallow the initialize and return a Status
  75. * indicating it is started. This allows the user to de-initialize the device
  76. * and reinitialize, but prevents a user from inadvertently
  77. * initializing.
  78. */
  79. if (FT_COMPONENT_IS_READY == instance_p->is_ready)
  80. {
  81. FSPIM_WARN("device is already initialized!!!");
  82. }
  83. /*
  84. * Set default values and configuration data, including setting the
  85. * callback handlers to stubs so the system will not crash should the
  86. * application not assign its own callbacks.
  87. */
  88. FSpimDeInitialize(instance_p);
  89. instance_p->config = *input_config_p;
  90. /*
  91. * Reset the device.
  92. */
  93. ret = FSpimReset(instance_p);
  94. if (FSPIM_SUCCESS == ret)
  95. {
  96. instance_p->is_ready = FT_COMPONENT_IS_READY;
  97. }
  98. return ret;
  99. }
  100. /**
  101. * @name: FSpimDeInitialize
  102. * @msg: DeInitialization function for the device instance
  103. * @return {无}
  104. * @param {FSpim} *instance_p FSPIM驱动控制数据
  105. */
  106. void FSpimDeInitialize(FSpim *instance_p)
  107. {
  108. FASSERT(instance_p);
  109. instance_p->is_ready = 0;
  110. memset(instance_p, 0, sizeof(*instance_p));
  111. return;
  112. }
  113. /**
  114. * @name: FSpimReset
  115. * @msg: 重置FSPIM控制器
  116. * @return {FError} FSPIM_SUCCESS表示重置成功,其它返回值表示重置失败
  117. * @param {FSpim} *instance_p
  118. */
  119. FError FSpimReset(FSpim *instance_p)
  120. {
  121. FASSERT(instance_p);
  122. uintptr base_addr = instance_p->config.base_addr;
  123. FError ret = FSPIM_SUCCESS;
  124. u32 reg_val;
  125. u32 fifo;
  126. /* 禁用SPI控制器 */
  127. FSpimSetEnable(base_addr, FALSE);
  128. /* 选择数据长度和帧格式 */
  129. reg_val = FSPIM_CTRL_R0_DFS(FSPIM_DEFAULT_DFS) |
  130. FSPIM_CTRL_R0_FRF(FSPIM_DEFAULT_FRF) |
  131. FSPIM_CTRL_R0_CFS(FSPIM_DEFAULT_CFS);
  132. if (instance_p->config.en_test)
  133. {
  134. reg_val |= FSPIM_CTRL_R0_SLV_SRL(FSPIM_SRL_TEST); /* 设置测试模式,TX Fifo和RX Fifo内部短接 */
  135. }
  136. else
  137. {
  138. reg_val |= FSPIM_CTRL_R0_SLV_SRL(FSPIM_SRL_NORAML); /* 设置为正常模式 */
  139. }
  140. FSpimSetCtrlR0(base_addr, reg_val);
  141. /* 选择串行时钟极性和相位 */
  142. FSpimSetCpha(base_addr, instance_p->config.cpha);
  143. FSpimSetCpol(base_addr, instance_p->config.cpol);
  144. /* 设置传输模式 */
  145. FSpimSetTransMode(base_addr, FSPIM_TRANS_MODE_RX_TX);
  146. /* 禁用slave */
  147. FSpimSetSlaveEnable(base_addr, FALSE);
  148. /* 禁用SPI 中断,设置slave设备 */
  149. FSpimMaskIrq(base_addr, FSPIM_IMR_ALL_BITS);
  150. FSpimSelSlaveDev(base_addr, instance_p->config.slave_dev_id);
  151. /* 获取SPI RX/TX FIFO 深度 */
  152. if (0 == instance_p->tx_fifo_len)
  153. {
  154. fifo = FSpimGetTxFifoDepth(base_addr);
  155. instance_p->tx_fifo_len = ((fifo == 1) ? 0 : fifo);
  156. FSPIM_INFO("fifo depth %d tx_fifo_len %d", fifo, instance_p->tx_fifo_len);
  157. }
  158. if (0 == instance_p->rx_fifo_len)
  159. {
  160. fifo = FSpimGetRxFifoDepth(base_addr);
  161. instance_p->rx_fifo_len = ((fifo == 1) ? 0 : fifo);
  162. FSPIM_INFO("fifo depth %d tx_fifo_len %d", fifo, instance_p->tx_fifo_len);
  163. }
  164. FSPIM_WRITE_REG32(base_addr, FSPIM_DMA_CR_OFFSET, 0x0); /* disable ddma */
  165. if (instance_p->config.en_dma)
  166. {
  167. /* recv data in continuous way */
  168. FSpimSetCtrlR1(base_addr, FSPIM_CTRL_R1_NDF_64KB);
  169. /* setup fifo threshold */
  170. FSpimSetRxFifoThreshold(base_addr, instance_p->rx_fifo_len);
  171. FSpimSetTxFifoThreshold(base_addr, instance_p->tx_fifo_len);
  172. /* setup fifo DMA level to trigger interrupt */
  173. FSpimSetRxDMALevel(base_addr, FSPIM_RX_DMA_LEVEL);
  174. FSpimSetTxDMALevel(base_addr, FSPIM_TX_DMA_LEVEL);
  175. }
  176. else
  177. {
  178. FSpimSetCtrlR1(base_addr, 0);
  179. FSpimSetRxFifoThreshold(base_addr, 0);
  180. FSpimSetTxFifoThreshold(base_addr, 0);
  181. FSpimSetRxDMALevel(base_addr, 0);
  182. FSpimSetTxDMALevel(base_addr, 0);
  183. }
  184. ret = FSpimSetSpeed(base_addr, instance_p->config.max_freq_hz);
  185. if (FSPIM_SUCCESS != ret)
  186. return ret;
  187. FSPIM_WRITE_REG32(base_addr, FSPIM_RX_SAMPLE_DLY_OFFSET, FSPIM_DEFAULT_RSD);
  188. /* 使能SPI控制器 */
  189. FSpimSetEnable(base_addr, TRUE);
  190. return ret;
  191. }
  192. /**
  193. * @name: FSpimGetTxRound
  194. * @msg: 计算当前FIFO支持的发送字节数
  195. * @return {fsize_t} 当前TX FIFO可以容纳的字节数
  196. * @param {FSpim} *instance_p
  197. */
  198. static fsize_t FSpimGetTxRound(FSpim *instance_p)
  199. {
  200. fsize_t data_width = instance_p->config.n_bytes;
  201. uintptr base_addr = instance_p->config.base_addr;
  202. fsize_t tx_left_round, tx_fifo_room, rx_tx_gap;
  203. tx_left_round = (fsize_t)(instance_p->tx_buff_end - instance_p->tx_buff) / data_width;
  204. tx_fifo_room = instance_p->tx_fifo_len -
  205. FSpimGetTxFifoLevel(base_addr);
  206. rx_tx_gap = ((fsize_t)(instance_p->rx_buff_end - instance_p->rx_buff) -
  207. (fsize_t)(instance_p->tx_buff_end - instance_p->tx_buff)) / data_width;
  208. FSPIM_DEBUG("tx_left_round: %d, tx_fifo_room: %d, gap: %d",
  209. tx_left_round,
  210. tx_fifo_room,
  211. ((fsize_t)(instance_p->tx_fifo_len) - rx_tx_gap));
  212. return min3(tx_left_round,
  213. tx_fifo_room,
  214. ((fsize_t)(instance_p->tx_fifo_len) - rx_tx_gap));
  215. }
  216. /**
  217. * @name: FSpimFifoTx
  218. * @msg: 利用Fifo进行发送
  219. * @return {无}
  220. * @param {FSpim} *instance_p
  221. */
  222. void FSpimFifoTx(FSpim *instance_p)
  223. {
  224. FASSERT(instance_p);
  225. fsize_t tx_round = FSpimGetTxRound(instance_p);
  226. FSPIM_DEBUG("tx round: %d", tx_round);
  227. uintptr base_addr = instance_p->config.base_addr;
  228. u32 data_width = instance_p->config.n_bytes;
  229. u16 data = 0xff;
  230. while (tx_round)
  231. {
  232. if (instance_p->tx_buff_end - instance_p->length)
  233. {
  234. if (FSPIM_1_BYTE == data_width)
  235. {
  236. /*
  237. * Data Transfer Width is Byte (8 bit).
  238. */
  239. data = *(u8 *)(instance_p->tx_buff);
  240. }
  241. else if (FSPIM_2_BYTE == data_width)
  242. {
  243. /*
  244. * Data Transfer Width is Half Word (16 bit).
  245. */
  246. data = *(u16 *)(instance_p->tx_buff);
  247. }
  248. else
  249. {
  250. FASSERT(0);
  251. }
  252. }
  253. FSpimWriteData(base_addr, data);
  254. FSPIM_DEBUG(" send 0x%x", data);
  255. instance_p->tx_buff += data_width;
  256. tx_round--;
  257. }
  258. }
  259. /**
  260. * @name: FSpimGetRxRound
  261. * @msg: 获取当前Fifo支持的接收字节数
  262. * @return {fsize_t} 当前RX FIFO可以容纳的字节数
  263. * @param {FSpim} *instance_p
  264. */
  265. static fsize_t FSpimGetRxRound(FSpim *instance_p)
  266. {
  267. fsize_t data_width = instance_p->config.n_bytes;
  268. uintptr base_addr = instance_p->config.base_addr;
  269. fsize_t rx_left_round = (fsize_t)(instance_p->rx_buff_end - instance_p->rx_buff) / data_width;
  270. FSPIM_DEBUG("left round %d, rx level %d", rx_left_round, FSpimGetRxFifoLevel(base_addr));
  271. return min(rx_left_round, (fsize_t)FSpimGetRxFifoLevel(base_addr));
  272. }
  273. /**
  274. * @name: FSpimFifoRx
  275. * @msg: 利用Fifo进行接收
  276. * @return {无}
  277. * @param {FSpim} *instance_p
  278. */
  279. void FSpimFifoRx(FSpim *instance_p)
  280. {
  281. FASSERT(instance_p);
  282. fsize_t rx_round = FSpimGetRxRound(instance_p);
  283. FSPIM_DEBUG("rx round: %d", rx_round);
  284. uintptr base_addr = instance_p->config.base_addr;
  285. u32 data_width = instance_p->config.n_bytes;
  286. u16 data;
  287. while (rx_round)
  288. {
  289. data = FSpimReadData(base_addr);
  290. if ((fsize_t)(instance_p->rx_buff_end - instance_p->length))
  291. {
  292. if (FSPIM_1_BYTE == data_width)
  293. {
  294. /*
  295. * Data Transfer Width is Byte (8 bit).
  296. */
  297. *(u8 *)(instance_p->rx_buff) = (u8)data;
  298. FSPIM_DEBUG(" recv 0x%x", *(u8 *)(instance_p->rx_buff));
  299. }
  300. else if (FSPIM_2_BYTE == data_width)
  301. {
  302. /*
  303. * Data Transfer Width is Half Word (16 bit).
  304. */
  305. *(u16 *)(instance_p->rx_buff) = (u16)data;
  306. FSPIM_DEBUG(" recv 0x%x", *(u16 *)(instance_p->rx_buff));
  307. }
  308. else
  309. {
  310. FASSERT(0);
  311. }
  312. }
  313. instance_p->rx_buff += data_width;
  314. rx_round--;
  315. }
  316. return;
  317. }
  318. /**
  319. * @name: FSpimTransferPollFifo
  320. * @msg: 先发送后接收数据 (阻塞处理),利用Fifo进行处理
  321. * @return {FError} FSPIM_SUCCESS表示处理成功,其它返回值表示处理失败
  322. * @param {FSpim} *instance_p 驱动控制数据
  323. * @param {void} *tx_buf 写缓冲区,可以为空,为空时表示只关注读数据,此时驱动会发送0xff读数据
  324. * @param {void} *rx_buf 读缓冲区, 可以为空,为空时表示值关注写数据,此时SPI总线上返回的数据会被抛弃
  325. * @param {fsize_t} len 进行传输的长度,如果tx_buf或者rx_buf不为空,则两个buf的长度必须为len
  326. - 使用此函数前需要确保FSPIM驱动初始化成功
  327. - 从函数不会使用中断,会按照TX FIFO的深度进行传输,每次发送填满TX FIFO后触发发送/接收动作
  328. */
  329. FError FSpimTransferPollFifo(FSpim *instance_p, const void *tx_buf, void *rx_buf, fsize_t len)
  330. {
  331. FASSERT(instance_p);
  332. u32 reg_val;
  333. uintptr base_addr = instance_p->config.base_addr;
  334. u32 data_width = instance_p->config.n_bytes;
  335. u32 tx_level;
  336. FError ret = FSPIM_SUCCESS;
  337. if (FT_COMPONENT_IS_READY != instance_p->is_ready)
  338. {
  339. FSPIM_ERROR("device is already initialized!!!");
  340. return FSPIM_ERR_NOT_READY;
  341. }
  342. FSpimSetEnable(base_addr, FALSE);
  343. reg_val = FSpimGetCtrlR0(base_addr);
  344. reg_val &= ~FSPIM_CTRL_R0_DFS_MASK;
  345. reg_val |= FSPIM_CTRL_R0_DFS((data_width << 3) - 1);
  346. reg_val &= ~FSPIM_CTRL_R0_TMOD_MASK;
  347. if (tx_buf && rx_buf)
  348. reg_val |= FSPIM_CTRL_R0_TMOD(FSPIM_TMOD_RX_TX);
  349. else if (rx_buf)
  350. reg_val |= FSPIM_CTRL_R0_TMOD(FSPIM_TMOD_RX_ONLY);
  351. else
  352. reg_val |= FSPIM_CTRL_R0_TMOD(FSPIM_TMOD_RX_TX);
  353. FSpimSetCtrlR0(base_addr, reg_val);
  354. FSpimMaskIrq(base_addr, FSPIM_IMR_ALL_BITS);
  355. instance_p->length = len;
  356. instance_p->tx_buff = tx_buf;
  357. instance_p->tx_buff_end = tx_buf + len;
  358. instance_p->rx_buff = rx_buf;
  359. instance_p->rx_buff_end = rx_buf + len;
  360. FSPIM_DEBUG("tx buff@%p-%d, rx buff@%p-%d",
  361. instance_p->tx_buff, len,
  362. instance_p->rx_buff, len);
  363. FSpimSetEnable(base_addr, TRUE);
  364. do
  365. {
  366. FSpimFifoTx(instance_p);
  367. FSpimFifoRx(instance_p);
  368. }
  369. while (instance_p->rx_buff_end > instance_p->rx_buff);
  370. return ret;
  371. }
  372. /**
  373. * @name: FSpimTransferByInterrupt
  374. * @msg: 先发送后接收数据 (中断处理),利用Fifo进行处理
  375. * @return {FError} FSPIM_SUCCESS表示处理成功,其它返回值表示处理失败
  376. * @param {FSpim} *instance_p 驱动控制数据
  377. * @param {void} *tx_buf 写缓冲区
  378. * @param {void} *rx_buf 读缓冲区
  379. * @param {fsize_t} len 读写缓冲区长度 (必须相等)
  380. */
  381. FError FSpimTransferByInterrupt(FSpim *instance_p, const void *tx_buf, void *rx_buf, fsize_t len)
  382. {
  383. FASSERT(instance_p);
  384. u32 reg_val;
  385. uintptr base_addr = instance_p->config.base_addr;
  386. u32 data_width = instance_p->config.n_bytes;
  387. u32 tx_level;
  388. if (FT_COMPONENT_IS_READY != instance_p->is_ready)
  389. {
  390. FSPIM_ERROR("device is already initialized!!!");
  391. return FSPIM_ERR_NOT_READY;
  392. }
  393. FSpimSetEnable(base_addr, FALSE);
  394. reg_val = FSpimGetCtrlR0(base_addr);
  395. reg_val &= ~FSPIM_CTRL_R0_DFS_MASK;
  396. reg_val |= FSPIM_CTRL_R0_DFS((data_width << 3) - 1);
  397. reg_val &= ~FSPIM_CTRL_R0_TMOD_MASK;
  398. if (tx_buf && rx_buf)
  399. reg_val |= FSPIM_CTRL_R0_TMOD(FSPIM_TMOD_RX_TX);
  400. else if (rx_buf)
  401. reg_val |= FSPIM_CTRL_R0_TMOD(FSPIM_TMOD_RX_ONLY);
  402. else
  403. reg_val |= FSPIM_CTRL_R0_TMOD(FSPIM_TMOD_RX_TX);
  404. FSpimSetCtrlR0(base_addr, reg_val);
  405. FSpimMaskIrq(base_addr, FSPIM_IMR_ALL_BITS);
  406. instance_p->length = len;
  407. instance_p->tx_buff = tx_buf;
  408. instance_p->tx_buff_end = instance_p->tx_buff + len;
  409. instance_p->rx_buff = rx_buf;
  410. instance_p->rx_buff_end = instance_p->rx_buff + len;
  411. /* 设置中断触发的时机,fifo填满一半,或者所有的数据填完 */
  412. tx_level = min(instance_p->tx_fifo_len / 2, instance_p->length / data_width);
  413. FSpimSetTxFifoThreshold(base_addr, tx_level);
  414. FSpimUmaskIrq(base_addr, FSPIM_IMR_TXEIS | FSPIM_IMR_TXOIS | FSPIM_IMR_RXUIS | FSPIM_IMR_RXOIS);
  415. FSpimSetEnable(base_addr, TRUE);
  416. return FSPIM_SUCCESS;
  417. }
  418. #ifdef FSPIM_VERSION_2 /* E2000 */
  419. /**
  420. * @name: FSpimTransferDMA
  421. * @msg: 启动SPIM DMA数据传输
  422. * @return {FError} FSPIM_SUCCESS表示启动DMA传输成功,其它值表示失败
  423. * @param {FSpim} *instance_p, 驱动控制数据
  424. * @param {boolean} tx, TRUE: 启动发送DMA
  425. * @param {boolean} rx, TRUE: 启动接收DMA
  426. */
  427. FError FSpimTransferDMA(FSpim *instance_p, boolean tx, boolean rx)
  428. {
  429. FASSERT(instance_p);
  430. u32 reg_val;
  431. uintptr base_addr = instance_p->config.base_addr;
  432. u32 data_width = instance_p->config.n_bytes;
  433. if (FT_COMPONENT_IS_READY != instance_p->is_ready)
  434. {
  435. FSPIM_ERROR("device is not yet initialized!!!");
  436. return FSPIM_ERR_NOT_READY;
  437. }
  438. FSpimSetEnable(base_addr, FALSE);
  439. /* set up spim transfer mode */
  440. reg_val = FSpimGetCtrlR0(base_addr);
  441. reg_val &= ~FSPIM_CTRL_R0_DFS_MASK;
  442. reg_val |= FSPIM_CTRL_R0_DFS((data_width << 3) - 1);
  443. reg_val &= ~FSPIM_CTRL_R0_TMOD_MASK;
  444. if (tx && rx)
  445. reg_val |= FSPIM_CTRL_R0_TMOD(FSPIM_TMOD_RX_TX);
  446. else if (rx)
  447. reg_val |= FSPIM_CTRL_R0_TMOD(FSPIM_TMOD_RX_ONLY);
  448. else
  449. reg_val |= FSPIM_CTRL_R0_TMOD(FSPIM_TMOD_RX_TX);
  450. FSpimSetCtrlR0(base_addr, reg_val);
  451. FSpimMaskIrq(base_addr, FSPIM_IMR_ALL_BITS); /* mask all interrupts */
  452. FSpimSetEnable(base_addr, TRUE);
  453. /* enable DMA tx / rx */
  454. reg_val = FSPIM_READ_REG32(base_addr, FSPIM_DMA_CR_OFFSET);
  455. if (tx)
  456. reg_val |= FSPIM_DMA_CR_TDMAE;
  457. else
  458. reg_val &= ~FSPIM_DMA_CR_TDMAE;
  459. if (rx)
  460. reg_val |= FSPIM_DMA_CR_RDMAE;
  461. else
  462. reg_val &= ~FSPIM_DMA_CR_RDMAE;
  463. FSPIM_WRITE_REG32(base_addr, FSPIM_DMA_CR_OFFSET, reg_val);
  464. FSpimSelSlaveDev(base_addr, instance_p->config.slave_dev_id);
  465. return FSPIM_SUCCESS;
  466. }
  467. /**
  468. * @name: FSpimSetChipSelection
  469. * @msg: 设置片选信号
  470. * @return {NONE}
  471. * @param {FSpim} *instance_p, 驱动控制数据
  472. * @param {boolean} on, TRUE: 片选打开, FALSE: 片选关闭
  473. */
  474. void FSpimSetChipSelection(FSpim *instance_p, boolean on)
  475. {
  476. FASSERT(instance_p);
  477. u32 reg_val;
  478. FSpimSlaveDevice cs_n = instance_p->config.slave_dev_id;
  479. uintptr base_addr = instance_p->config.base_addr;
  480. if (FT_COMPONENT_IS_READY != instance_p->is_ready)
  481. {
  482. FSPIM_ERROR("device is not yet initialized!!!");
  483. return;
  484. }
  485. reg_val = FSPIM_READ_REG32(base_addr, FSPIM_CS_OFFSET);
  486. if (on)
  487. {
  488. reg_val |= FSPIM_CHIP_SEL_EN((u32)cs_n);
  489. reg_val |= FSPIM_CHIP_SEL((u32)cs_n);
  490. }
  491. else
  492. {
  493. reg_val &= ~FSPIM_CHIP_SEL_EN((u32)cs_n);
  494. reg_val &= ~FSPIM_CHIP_SEL((u32)cs_n);
  495. }
  496. FSPIM_WRITE_REG32(base_addr, FSPIM_CS_OFFSET, reg_val);
  497. return;
  498. }
  499. #endif
  500. /**
  501. * @name: FSpimErrorToMessage
  502. * @msg: 获取FSPIM模块错误码对应的错误信息
  503. * @return {const char *}, 错误码信息,NULL表示失败
  504. * @param {FError} error, FSPIM输入错误码
  505. */
  506. const char *FSpimErrorToMessage(FError error)
  507. {
  508. const char *msg = NULL;
  509. if (FSPIM_SUCCESS != error && (FSPIM_ERR_CODE_PREFIX != error & (FT_ERRCODE_SYS_MODULE_MASK | FT_ERRCODE_SUB_MODULE_MASK)))
  510. {
  511. /* if input error do not belong to this module */
  512. return msg;
  513. }
  514. u32 index = error & FT_ERRCODE_TAIL_VALUE_MASK;
  515. if (index < FSPIM_NUM_OF_ERR_CODE)
  516. {
  517. msg = FSPIM_ERROR_CODE_MSG[index];
  518. }
  519. return msg;
  520. }